From e7bf2512eef2afdcfa27c0394ade4a0e05937fbd Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 5 May 2021 05:05:32 +0000 Subject: [PATCH 01/46] Bump @types/node from 15.0.1 to 15.0.2 (#194) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index b3dd9fb..a29d5c4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -156,9 +156,9 @@ } }, "@types/node": { - "version": "15.0.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.0.1.tgz", - "integrity": "sha512-TMkXt0Ck1y0KKsGr9gJtWGjttxlZnnvDtphxUOSd0bfaR6Q1jle+sPvrzNR1urqYTWMinoKvjKfXUGsumaO1PA==", + "version": "15.0.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.0.2.tgz", + "integrity": "sha512-p68+a+KoxpoB47015IeYZYRrdqMUcpbK8re/zpFB8Ld46LHC1lPEbp3EXgkEhAYEcPvjJF6ZO+869SQ0aH1dcA==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index 1a5f261..6305f0c 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "dependencies": {}, "devDependencies": { "@ava/typescript": "^1.1.0", - "@types/node": "^15.0.1", + "@types/node": "^15.0.2", "ava": "^3.15.0", "typescript": "^4.2.4" }, From 93ee33f83934f9f27a5ad711b4459bade80b7178 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 7 May 2021 05:02:22 +0000 Subject: [PATCH 02/46] [Security] Bump lodash from 4.17.20 to 4.17.21 (#195) --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index a29d5c4..3d318f1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1396,9 +1396,9 @@ } }, "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, "log-symbols": { From 8675d682112e5ea631d23a4b01132af52998c393 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 7 May 2021 18:51:18 +0000 Subject: [PATCH 03/46] [Security] Bump hosted-git-info from 2.8.8 to 2.8.9 (#196) --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3d318f1..7c5004c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1094,9 +1094,9 @@ "dev": true }, "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, "http-cache-semantics": { From a084e459212f5c43fba98eae32e2b783afe26657 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 13 May 2021 05:03:31 +0000 Subject: [PATCH 04/46] Bump @types/node from 15.0.2 to 15.0.3 (#197) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7c5004c..f28e0ea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -156,9 +156,9 @@ } }, "@types/node": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.0.2.tgz", - "integrity": "sha512-p68+a+KoxpoB47015IeYZYRrdqMUcpbK8re/zpFB8Ld46LHC1lPEbp3EXgkEhAYEcPvjJF6ZO+869SQ0aH1dcA==", + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.0.3.tgz", + "integrity": "sha512-/WbxFeBU+0F79z9RdEOXH4CsDga+ibi5M8uEYr91u3CkT/pdWcV8MCook+4wDPnZBexRdwWS+PiVZ2xJviAzcQ==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index 6305f0c..1a857e4 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "dependencies": {}, "devDependencies": { "@ava/typescript": "^1.1.0", - "@types/node": "^15.0.2", + "@types/node": "^15.0.3", "ava": "^3.15.0", "typescript": "^4.2.4" }, From a352676fb0c9875c263c4c54e8c5dbdd6b2710ac Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 17 May 2021 05:03:30 +0000 Subject: [PATCH 05/46] Bump @types/node from 15.0.3 to 15.3.0 (#198) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index f28e0ea..82a0d4d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -156,9 +156,9 @@ } }, "@types/node": { - "version": "15.0.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.0.3.tgz", - "integrity": "sha512-/WbxFeBU+0F79z9RdEOXH4CsDga+ibi5M8uEYr91u3CkT/pdWcV8MCook+4wDPnZBexRdwWS+PiVZ2xJviAzcQ==", + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.3.0.tgz", + "integrity": "sha512-8/bnjSZD86ZfpBsDlCIkNXIvm+h6wi9g7IqL+kmFkQ+Wvu3JrasgLElfiPgoo8V8vVfnEi0QVS12gbl94h9YsQ==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index 1a857e4..32206b5 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "dependencies": {}, "devDependencies": { "@ava/typescript": "^1.1.0", - "@types/node": "^15.0.3", + "@types/node": "^15.3.0", "ava": "^3.15.0", "typescript": "^4.2.4" }, From e588574a17963dd45cfb20c1a9c572f124ee8cda Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 20 May 2021 05:27:47 +0000 Subject: [PATCH 06/46] Bump @types/node from 15.3.0 to 15.3.1 (#199) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 82a0d4d..066b400 100644 --- a/package-lock.json +++ b/package-lock.json @@ -156,9 +156,9 @@ } }, "@types/node": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.3.0.tgz", - "integrity": "sha512-8/bnjSZD86ZfpBsDlCIkNXIvm+h6wi9g7IqL+kmFkQ+Wvu3JrasgLElfiPgoo8V8vVfnEi0QVS12gbl94h9YsQ==", + "version": "15.3.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.3.1.tgz", + "integrity": "sha512-weaeiP4UF4XgF++3rpQhpIJWsCTS4QJw5gvBhQu6cFIxTwyxWIe3xbnrY/o2lTCQ0lsdb8YIUDUvLR4Vuz5rbw==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index 32206b5..6ab16fe 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "dependencies": {}, "devDependencies": { "@ava/typescript": "^1.1.0", - "@types/node": "^15.3.0", + "@types/node": "^15.3.1", "ava": "^3.15.0", "typescript": "^4.2.4" }, From 8af86d2fb312bfb2d56d056f0ea663648b95d99a Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 24 May 2021 05:05:40 +0000 Subject: [PATCH 07/46] Bump @types/node from 15.3.1 to 15.6.0 (#200) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 066b400..c5e6aac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -156,9 +156,9 @@ } }, "@types/node": { - "version": "15.3.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.3.1.tgz", - "integrity": "sha512-weaeiP4UF4XgF++3rpQhpIJWsCTS4QJw5gvBhQu6cFIxTwyxWIe3xbnrY/o2lTCQ0lsdb8YIUDUvLR4Vuz5rbw==", + "version": "15.6.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.6.0.tgz", + "integrity": "sha512-gCYSfQpy+LYhOFTKAeE8BkyGqaxmlFxe+n4DKM6DR0wzw/HISUE/hAmkC/KT8Sw5PCJblqg062b3z9gucv3k0A==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index 6ab16fe..0dd9143 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "dependencies": {}, "devDependencies": { "@ava/typescript": "^1.1.0", - "@types/node": "^15.3.1", + "@types/node": "^15.6.0", "ava": "^3.15.0", "typescript": "^4.2.4" }, From de918cd367f1b336875e4b5b96ec0242ad4d75a9 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 25 May 2021 04:52:30 +0000 Subject: [PATCH 08/46] Bump @types/node from 15.6.0 to 15.6.1 (#201) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index c5e6aac..a340d6d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -156,9 +156,9 @@ } }, "@types/node": { - "version": "15.6.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.6.0.tgz", - "integrity": "sha512-gCYSfQpy+LYhOFTKAeE8BkyGqaxmlFxe+n4DKM6DR0wzw/HISUE/hAmkC/KT8Sw5PCJblqg062b3z9gucv3k0A==", + "version": "15.6.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.6.1.tgz", + "integrity": "sha512-7EIraBEyRHEe7CH+Fm1XvgqU6uwZN8Q7jppJGcqjROMT29qhAuuOxYB1uEY5UMYQKEmA5D+5tBnhdaPXSsLONA==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index 0dd9143..38ca2b5 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "dependencies": {}, "devDependencies": { "@ava/typescript": "^1.1.0", - "@types/node": "^15.6.0", + "@types/node": "^15.6.1", "ava": "^3.15.0", "typescript": "^4.2.4" }, From 00b7f050e0d9e6367f444f25b0421cccd334ef40 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 27 May 2021 05:01:20 +0000 Subject: [PATCH 09/46] Bump typescript from 4.2.4 to 4.3.2 (#202) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index a340d6d..2ac9583 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2274,9 +2274,9 @@ } }, "typescript": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", - "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.2.tgz", + "integrity": "sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==", "dev": true }, "unique-string": { diff --git a/package.json b/package.json index 38ca2b5..60c8b1e 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "@ava/typescript": "^1.1.0", "@types/node": "^15.6.1", "ava": "^3.15.0", - "typescript": "^4.2.4" + "typescript": "^4.3.2" }, "ava": { "typescript": { From 3bf6793518f928c641e84dfcedd95ecdb0b70410 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 3 Jun 2021 05:00:15 +0000 Subject: [PATCH 10/46] Bump @types/node from 15.6.1 to 15.9.0 (#203) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2ac9583..4b01827 100644 --- a/package-lock.json +++ b/package-lock.json @@ -156,9 +156,9 @@ } }, "@types/node": { - "version": "15.6.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.6.1.tgz", - "integrity": "sha512-7EIraBEyRHEe7CH+Fm1XvgqU6uwZN8Q7jppJGcqjROMT29qhAuuOxYB1uEY5UMYQKEmA5D+5tBnhdaPXSsLONA==", + "version": "15.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.9.0.tgz", + "integrity": "sha512-AR1Vq1Ei1GaA5FjKL5PBqblTZsL5M+monvGSZwe6sSIdGiuu7Xr/pNwWJY+0ZQuN8AapD/XMB5IzBAyYRFbocA==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index 60c8b1e..52bf125 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "dependencies": {}, "devDependencies": { "@ava/typescript": "^1.1.0", - "@types/node": "^15.6.1", + "@types/node": "^15.9.0", "ava": "^3.15.0", "typescript": "^4.3.2" }, From 7ecf20e8f6a1e2195c4cf5db8faf6527fd58b096 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 4 Jun 2021 04:54:22 +0000 Subject: [PATCH 11/46] Bump @types/node from 15.9.0 to 15.12.0 (#204) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4b01827..b51d439 100644 --- a/package-lock.json +++ b/package-lock.json @@ -156,9 +156,9 @@ } }, "@types/node": { - "version": "15.9.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.9.0.tgz", - "integrity": "sha512-AR1Vq1Ei1GaA5FjKL5PBqblTZsL5M+monvGSZwe6sSIdGiuu7Xr/pNwWJY+0ZQuN8AapD/XMB5IzBAyYRFbocA==", + "version": "15.12.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.0.tgz", + "integrity": "sha512-+aHJvoCsVhO2ZCuT4o5JtcPrCPyDE3+1nvbDprYes+pPkEsbjH7AGUCNtjMOXS0fqH14t+B7yLzaqSz92FPWyw==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index 52bf125..52baced 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "dependencies": {}, "devDependencies": { "@ava/typescript": "^1.1.0", - "@types/node": "^15.9.0", + "@types/node": "^15.12.0", "ava": "^3.15.0", "typescript": "^4.3.2" }, From 4bb7cdf9ea52d362d96e522484554199a58cdc12 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 7 Jun 2021 04:59:34 +0000 Subject: [PATCH 12/46] Bump @types/node from 15.12.0 to 15.12.1 (#205) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index b51d439..a553313 100644 --- a/package-lock.json +++ b/package-lock.json @@ -156,9 +156,9 @@ } }, "@types/node": { - "version": "15.12.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.0.tgz", - "integrity": "sha512-+aHJvoCsVhO2ZCuT4o5JtcPrCPyDE3+1nvbDprYes+pPkEsbjH7AGUCNtjMOXS0fqH14t+B7yLzaqSz92FPWyw==", + "version": "15.12.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.1.tgz", + "integrity": "sha512-zyxJM8I1c9q5sRMtVF+zdd13Jt6RU4r4qfhTd7lQubyThvLfx6yYekWSQjGCGV2Tkecgxnlpl/DNlb6Hg+dmEw==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index 52baced..c77645c 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "dependencies": {}, "devDependencies": { "@ava/typescript": "^1.1.0", - "@types/node": "^15.12.0", + "@types/node": "^15.12.1", "ava": "^3.15.0", "typescript": "^4.3.2" }, From b524f043f56c91a567c6dfd0ef025fe8e516996a Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 8 Jun 2021 04:59:07 +0000 Subject: [PATCH 13/46] [Security] Bump glob-parent from 5.1.1 to 5.1.2 (#206) --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index a553313..fd1a397 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1016,9 +1016,9 @@ } }, "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "requires": { "is-glob": "^4.0.1" From 7c284dabf2b719825d56cb46e5fd130b4c871e9f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 8 Jun 2021 04:59:43 +0000 Subject: [PATCH 14/46] Bump @types/node from 15.12.1 to 15.12.2 (#207) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index fd1a397..f14a88c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -156,9 +156,9 @@ } }, "@types/node": { - "version": "15.12.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.1.tgz", - "integrity": "sha512-zyxJM8I1c9q5sRMtVF+zdd13Jt6RU4r4qfhTd7lQubyThvLfx6yYekWSQjGCGV2Tkecgxnlpl/DNlb6Hg+dmEw==", + "version": "15.12.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.2.tgz", + "integrity": "sha512-zjQ69G564OCIWIOHSXyQEEDpdpGl+G348RAKY0XXy9Z5kU9Vzv1GMNnkar/ZJ8dzXB3COzD9Mo9NtRZ4xfgUww==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index c77645c..54e4c9a 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "dependencies": {}, "devDependencies": { "@ava/typescript": "^1.1.0", - "@types/node": "^15.12.1", + "@types/node": "^15.12.2", "ava": "^3.15.0", "typescript": "^4.3.2" }, From d64547b5408ae66cae3c26931a9d7854a6beb394 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 9 Jun 2021 05:00:03 +0000 Subject: [PATCH 15/46] [Security] Bump normalize-url from 4.5.0 to 4.5.1 (#208) --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index f14a88c..45803da 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1571,9 +1571,9 @@ "dev": true }, "normalize-url": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", - "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", "dev": true }, "once": { From 90a4442e0227f7e4a8d5f1551ea8546cc960fad3 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 17 Jun 2021 04:50:27 +0000 Subject: [PATCH 16/46] Bump typescript from 4.3.2 to 4.3.3 (#209) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 45803da..0871e60 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2274,9 +2274,9 @@ } }, "typescript": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.2.tgz", - "integrity": "sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.3.tgz", + "integrity": "sha512-rUvLW0WtF7PF2b9yenwWUi9Da9euvDRhmH7BLyBG4DCFfOJ850LGNknmRpp8Z8kXNUPObdZQEfKOiHtXuQHHKA==", "dev": true }, "unique-string": { diff --git a/package.json b/package.json index 54e4c9a..5a6c7c8 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "@ava/typescript": "^1.1.0", "@types/node": "^15.12.2", "ava": "^3.15.0", - "typescript": "^4.3.2" + "typescript": "^4.3.3" }, "ava": { "typescript": { From d3d0fadca3aeee0f0227bf176671bc4b4f6ad7f6 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 18 Jun 2021 05:03:40 +0000 Subject: [PATCH 17/46] Bump typescript from 4.3.3 to 4.3.4 (#210) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0871e60..6f989ca 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2274,9 +2274,9 @@ } }, "typescript": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.3.tgz", - "integrity": "sha512-rUvLW0WtF7PF2b9yenwWUi9Da9euvDRhmH7BLyBG4DCFfOJ850LGNknmRpp8Z8kXNUPObdZQEfKOiHtXuQHHKA==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.4.tgz", + "integrity": "sha512-uauPG7XZn9F/mo+7MrsRjyvbxFpzemRjKEZXS4AK83oP2KKOJPvb+9cO/gmnv8arWZvhnjVOXz7B49m1l0e9Ew==", "dev": true }, "unique-string": { diff --git a/package.json b/package.json index 5a6c7c8..e72c871 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "@ava/typescript": "^1.1.0", "@types/node": "^15.12.2", "ava": "^3.15.0", - "typescript": "^4.3.3" + "typescript": "^4.3.4" }, "ava": { "typescript": { From ffba8548a25a0633822a4c94ffb208532c687441 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 21 Jun 2021 04:58:44 +0000 Subject: [PATCH 18/46] Bump @types/node from 15.12.2 to 15.12.4 (#211) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6f989ca..9e1b6e9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -156,9 +156,9 @@ } }, "@types/node": { - "version": "15.12.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.2.tgz", - "integrity": "sha512-zjQ69G564OCIWIOHSXyQEEDpdpGl+G348RAKY0XXy9Z5kU9Vzv1GMNnkar/ZJ8dzXB3COzD9Mo9NtRZ4xfgUww==", + "version": "15.12.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.4.tgz", + "integrity": "sha512-zrNj1+yqYF4WskCMOHwN+w9iuD12+dGm0rQ35HLl9/Ouuq52cEtd0CH9qMgrdNmi5ejC1/V7vKEXYubB+65DkA==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index e72c871..2a947c4 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "dependencies": {}, "devDependencies": { "@ava/typescript": "^1.1.0", - "@types/node": "^15.12.2", + "@types/node": "^15.12.4", "ava": "^3.15.0", "typescript": "^4.3.4" }, From b61af91521db0482da29ae34d15ee3989690a846 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 28 Jun 2021 05:06:14 +0000 Subject: [PATCH 19/46] Bump @types/node from 15.12.4 to 15.12.5 (#212) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9e1b6e9..a897a53 100644 --- a/package-lock.json +++ b/package-lock.json @@ -156,9 +156,9 @@ } }, "@types/node": { - "version": "15.12.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.4.tgz", - "integrity": "sha512-zrNj1+yqYF4WskCMOHwN+w9iuD12+dGm0rQ35HLl9/Ouuq52cEtd0CH9qMgrdNmi5ejC1/V7vKEXYubB+65DkA==", + "version": "15.12.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.5.tgz", + "integrity": "sha512-se3yX7UHv5Bscf8f1ERKvQOD6sTyycH3hdaoozvaLxgUiY5lIGEeH37AD0G0Qi9kPqihPn0HOfd2yaIEN9VwEg==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index 2a947c4..4d07606 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "dependencies": {}, "devDependencies": { "@ava/typescript": "^1.1.0", - "@types/node": "^15.12.4", + "@types/node": "^15.12.5", "ava": "^3.15.0", "typescript": "^4.3.4" }, From 6047b3cdf40f9ce6344c4481175f0b01367f6c8f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 1 Jul 2021 04:57:45 +0000 Subject: [PATCH 20/46] Bump typescript from 4.3.4 to 4.3.5 (#213) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index a897a53..49ed7d6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2274,9 +2274,9 @@ } }, "typescript": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.4.tgz", - "integrity": "sha512-uauPG7XZn9F/mo+7MrsRjyvbxFpzemRjKEZXS4AK83oP2KKOJPvb+9cO/gmnv8arWZvhnjVOXz7B49m1l0e9Ew==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", + "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", "dev": true }, "unique-string": { diff --git a/package.json b/package.json index 4d07606..7f54e1a 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "@ava/typescript": "^1.1.0", "@types/node": "^15.12.5", "ava": "^3.15.0", - "typescript": "^4.3.4" + "typescript": "^4.3.5" }, "ava": { "typescript": { From ad47defb53a4e51713ca715de3328ebfb548e3af Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 2 Jul 2021 04:55:29 +0000 Subject: [PATCH 21/46] Bump @types/node from 15.12.5 to 15.14.0 (#214) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 49ed7d6..ae15def 100644 --- a/package-lock.json +++ b/package-lock.json @@ -156,9 +156,9 @@ } }, "@types/node": { - "version": "15.12.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.5.tgz", - "integrity": "sha512-se3yX7UHv5Bscf8f1ERKvQOD6sTyycH3hdaoozvaLxgUiY5lIGEeH37AD0G0Qi9kPqihPn0HOfd2yaIEN9VwEg==", + "version": "15.14.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.14.0.tgz", + "integrity": "sha512-um/+/ip3QZmwLfIkWZSNtQIJNVAqrJ92OkLMeuZrjZMTAJniI7fh8N8OICyDhAJ2mzgk/fmYFo72jRr5HyZ1EQ==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index 7f54e1a..0c32bef 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "dependencies": {}, "devDependencies": { "@ava/typescript": "^1.1.0", - "@types/node": "^15.12.5", + "@types/node": "^15.14.0", "ava": "^3.15.0", "typescript": "^4.3.5" }, From d1265021bce3916dc492c46c52f77925385f547c Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 5 Jul 2021 05:01:50 +0000 Subject: [PATCH 22/46] Bump @types/node from 15.14.0 to 16.0.0 (#215) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index ae15def..8f5df24 100644 --- a/package-lock.json +++ b/package-lock.json @@ -156,9 +156,9 @@ } }, "@types/node": { - "version": "15.14.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.14.0.tgz", - "integrity": "sha512-um/+/ip3QZmwLfIkWZSNtQIJNVAqrJ92OkLMeuZrjZMTAJniI7fh8N8OICyDhAJ2mzgk/fmYFo72jRr5HyZ1EQ==", + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.0.0.tgz", + "integrity": "sha512-TmCW5HoZ2o2/z2EYi109jLqIaPIi9y/lc2LmDCWzuCi35bcaQ+OtUh6nwBiFK7SOu25FAU5+YKdqFZUwtqGSdg==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index 0c32bef..84c4348 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "dependencies": {}, "devDependencies": { "@ava/typescript": "^1.1.0", - "@types/node": "^15.14.0", + "@types/node": "^16.0.0", "ava": "^3.15.0", "typescript": "^4.3.5" }, From d37ba264316c573364fbd628b52cbfdda3ddcd4e Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 8 Jul 2021 04:58:56 +0000 Subject: [PATCH 23/46] Bump @types/node from 16.0.0 to 16.0.1 (#217) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8f5df24..067ad1a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -156,9 +156,9 @@ } }, "@types/node": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.0.0.tgz", - "integrity": "sha512-TmCW5HoZ2o2/z2EYi109jLqIaPIi9y/lc2LmDCWzuCi35bcaQ+OtUh6nwBiFK7SOu25FAU5+YKdqFZUwtqGSdg==", + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.0.1.tgz", + "integrity": "sha512-hBOx4SUlEPKwRi6PrXuTGw1z6lz0fjsibcWCM378YxsSu/6+C30L6CR49zIBKHiwNWCYIcOLjg4OHKZaFeLAug==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index 84c4348..0e1b6be 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "dependencies": {}, "devDependencies": { "@ava/typescript": "^1.1.0", - "@types/node": "^16.0.0", + "@types/node": "^16.0.1", "ava": "^3.15.0", "typescript": "^4.3.5" }, From 19846d59b7cef2ea51d32aaa7497d831f436ae7f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 9 Jul 2021 04:45:09 +0000 Subject: [PATCH 24/46] Bump @types/node from 16.0.1 to 16.3.0 (#218) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 067ad1a..c8255e1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -156,9 +156,9 @@ } }, "@types/node": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.0.1.tgz", - "integrity": "sha512-hBOx4SUlEPKwRi6PrXuTGw1z6lz0fjsibcWCM378YxsSu/6+C30L6CR49zIBKHiwNWCYIcOLjg4OHKZaFeLAug==", + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.3.0.tgz", + "integrity": "sha512-OydMCocGMGqw/1BnWbhtK+AtwyWTOigtrQlRe57OQmTNcI3HKlVI5FGlh+c4mSqInMPLynFrTlYjfajPu9O/eQ==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index 0e1b6be..c7a1378 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "dependencies": {}, "devDependencies": { "@ava/typescript": "^1.1.0", - "@types/node": "^16.0.1", + "@types/node": "^16.3.0", "ava": "^3.15.0", "typescript": "^4.3.5" }, From 46b108fcc0935c388afb20814bb32853d5473e1f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 12 Jul 2021 04:57:44 +0000 Subject: [PATCH 25/46] Bump @types/node from 16.3.0 to 16.3.1 (#219) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index c8255e1..83efbe7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -156,9 +156,9 @@ } }, "@types/node": { - "version": "16.3.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.3.0.tgz", - "integrity": "sha512-OydMCocGMGqw/1BnWbhtK+AtwyWTOigtrQlRe57OQmTNcI3HKlVI5FGlh+c4mSqInMPLynFrTlYjfajPu9O/eQ==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.3.1.tgz", + "integrity": "sha512-N87VuQi7HEeRJkhzovao/JviiqKjDKMVKxKMfUvSKw+MbkbW8R0nA3fi/MQhhlxV2fQ+2ReM+/Nt4efdrJx3zA==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index c7a1378..8275254 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "dependencies": {}, "devDependencies": { "@ava/typescript": "^1.1.0", - "@types/node": "^16.3.0", + "@types/node": "^16.3.1", "ava": "^3.15.0", "typescript": "^4.3.5" }, From cfa0baab1c12c0a3b7d1959e44698496d9f9d2fc Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 14 Jul 2021 05:03:33 +0000 Subject: [PATCH 26/46] Bump @types/node from 16.3.1 to 16.3.2 (#220) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 83efbe7..7b87b48 100644 --- a/package-lock.json +++ b/package-lock.json @@ -156,9 +156,9 @@ } }, "@types/node": { - "version": "16.3.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.3.1.tgz", - "integrity": "sha512-N87VuQi7HEeRJkhzovao/JviiqKjDKMVKxKMfUvSKw+MbkbW8R0nA3fi/MQhhlxV2fQ+2ReM+/Nt4efdrJx3zA==", + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.3.2.tgz", + "integrity": "sha512-jJs9ErFLP403I+hMLGnqDRWT0RYKSvArxuBVh2veudHV7ifEC1WAmjJADacZ7mRbA2nWgHtn8xyECMAot0SkAw==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index 8275254..404a913 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "dependencies": {}, "devDependencies": { "@ava/typescript": "^1.1.0", - "@types/node": "^16.3.1", + "@types/node": "^16.3.2", "ava": "^3.15.0", "typescript": "^4.3.5" }, From 96454b90707e228ffab28821dae4395276166984 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 19 Jul 2021 04:56:54 +0000 Subject: [PATCH 27/46] Bump @types/node from 16.3.2 to 16.3.3 (#221) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7b87b48..1567217 100644 --- a/package-lock.json +++ b/package-lock.json @@ -156,9 +156,9 @@ } }, "@types/node": { - "version": "16.3.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.3.2.tgz", - "integrity": "sha512-jJs9ErFLP403I+hMLGnqDRWT0RYKSvArxuBVh2veudHV7ifEC1WAmjJADacZ7mRbA2nWgHtn8xyECMAot0SkAw==", + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.3.3.tgz", + "integrity": "sha512-8h7k1YgQKxKXWckzFCMfsIwn0Y61UK6tlD6y2lOb3hTOIMlK3t9/QwHOhc81TwU+RMf0As5fj7NPjroERCnejQ==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index 404a913..a52dfe4 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "dependencies": {}, "devDependencies": { "@ava/typescript": "^1.1.0", - "@types/node": "^16.3.2", + "@types/node": "^16.3.3", "ava": "^3.15.0", "typescript": "^4.3.5" }, From 968dabe087ff987bee35267f3b0c1ed084a3161e Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 21 Jul 2021 05:02:16 +0000 Subject: [PATCH 28/46] Bump @types/node from 16.3.3 to 16.4.0 (#222) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1567217..ce2c3ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -156,9 +156,9 @@ } }, "@types/node": { - "version": "16.3.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.3.3.tgz", - "integrity": "sha512-8h7k1YgQKxKXWckzFCMfsIwn0Y61UK6tlD6y2lOb3hTOIMlK3t9/QwHOhc81TwU+RMf0As5fj7NPjroERCnejQ==", + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.0.tgz", + "integrity": "sha512-HrJuE7Mlqcjj+00JqMWpZ3tY8w7EUd+S0U3L1+PQSWiXZbOgyQDvi+ogoUxaHApPJq5diKxYBQwA3iIlNcPqOg==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index a52dfe4..47e0a57 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "dependencies": {}, "devDependencies": { "@ava/typescript": "^1.1.0", - "@types/node": "^16.3.3", + "@types/node": "^16.4.0", "ava": "^3.15.0", "typescript": "^4.3.5" }, From 00434de9d1517bf8a3502dc79c8fd3718d946862 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 23 Jul 2021 05:01:21 +0000 Subject: [PATCH 29/46] Bump @types/node from 16.4.0 to 16.4.1 (#223) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index ce2c3ee..1750415 100644 --- a/package-lock.json +++ b/package-lock.json @@ -156,9 +156,9 @@ } }, "@types/node": { - "version": "16.4.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.0.tgz", - "integrity": "sha512-HrJuE7Mlqcjj+00JqMWpZ3tY8w7EUd+S0U3L1+PQSWiXZbOgyQDvi+ogoUxaHApPJq5diKxYBQwA3iIlNcPqOg==", + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.1.tgz", + "integrity": "sha512-UW7cbLqf/Wu5XH2RKKY1cHwUNLicIDRLMraYKz+HHAerJ0ZffUEk+fMnd8qU2JaS6cAy0r8tsaf7yqHASf/Y0Q==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index 47e0a57..5b1697f 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "dependencies": {}, "devDependencies": { "@ava/typescript": "^1.1.0", - "@types/node": "^16.4.0", + "@types/node": "^16.4.1", "ava": "^3.15.0", "typescript": "^4.3.5" }, From b1302b69036b7d961abd6c4818d48c907029b6bc Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 26 Jul 2021 04:57:17 +0000 Subject: [PATCH 30/46] Bump @types/node from 16.4.1 to 16.4.3 (#224) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1750415..589f63e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -156,9 +156,9 @@ } }, "@types/node": { - "version": "16.4.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.1.tgz", - "integrity": "sha512-UW7cbLqf/Wu5XH2RKKY1cHwUNLicIDRLMraYKz+HHAerJ0ZffUEk+fMnd8qU2JaS6cAy0r8tsaf7yqHASf/Y0Q==", + "version": "16.4.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.3.tgz", + "integrity": "sha512-GKM4FLMkWDc0sfx7tXqPWkM6NBow1kge0fgQh0bOnlqo4iT1kvTvMEKE0c1RtUGnbLlGRXiAA8SumE//90uKAg==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index 5b1697f..6144e9b 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "dependencies": {}, "devDependencies": { "@ava/typescript": "^1.1.0", - "@types/node": "^16.4.1", + "@types/node": "^16.4.3", "ava": "^3.15.0", "typescript": "^4.3.5" }, From d6b4925d18d4d3a27090388ee587285980f00689 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 28 Jul 2021 04:57:50 +0000 Subject: [PATCH 31/46] Bump @types/node from 16.4.3 to 16.4.4 (#225) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 589f63e..73839fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -156,9 +156,9 @@ } }, "@types/node": { - "version": "16.4.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.3.tgz", - "integrity": "sha512-GKM4FLMkWDc0sfx7tXqPWkM6NBow1kge0fgQh0bOnlqo4iT1kvTvMEKE0c1RtUGnbLlGRXiAA8SumE//90uKAg==", + "version": "16.4.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.4.tgz", + "integrity": "sha512-BH/jX0HjzElFCQdAwaEMwuGBQwm6ViDZ00X6LKdnRRmGWOzkWugEH4+7a0BwfHQ8DfPPCSd/mdsm3Nu8FKFu0w==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index 6144e9b..b0c4dfc 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "dependencies": {}, "devDependencies": { "@ava/typescript": "^1.1.0", - "@types/node": "^16.4.3", + "@types/node": "^16.4.4", "ava": "^3.15.0", "typescript": "^4.3.5" }, From 419a0d20659591f96d8beb351f6d215b3e47068f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 29 Jul 2021 04:57:31 +0000 Subject: [PATCH 32/46] Bump @types/node from 16.4.4 to 16.4.6 (#226) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 73839fa..e1571b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -156,9 +156,9 @@ } }, "@types/node": { - "version": "16.4.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.4.tgz", - "integrity": "sha512-BH/jX0HjzElFCQdAwaEMwuGBQwm6ViDZ00X6LKdnRRmGWOzkWugEH4+7a0BwfHQ8DfPPCSd/mdsm3Nu8FKFu0w==", + "version": "16.4.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.6.tgz", + "integrity": "sha512-FKyawK3o5KL16AwbeFajen8G4K3mmqUrQsehn5wNKs8IzlKHE8TfnSmILXVMVziAEcnB23u1RCFU1NT6hSyr7Q==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index b0c4dfc..09c8570 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "dependencies": {}, "devDependencies": { "@ava/typescript": "^1.1.0", - "@types/node": "^16.4.4", + "@types/node": "^16.4.6", "ava": "^3.15.0", "typescript": "^4.3.5" }, From ba074df4c64628c43a7634dd49196f160a27985a Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 30 Jul 2021 04:56:31 +0000 Subject: [PATCH 33/46] Bump @types/node from 16.4.6 to 16.4.7 (#227) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index e1571b0..818925c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -156,9 +156,9 @@ } }, "@types/node": { - "version": "16.4.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.6.tgz", - "integrity": "sha512-FKyawK3o5KL16AwbeFajen8G4K3mmqUrQsehn5wNKs8IzlKHE8TfnSmILXVMVziAEcnB23u1RCFU1NT6hSyr7Q==", + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.7.tgz", + "integrity": "sha512-aDDY54sst8sx47CWT6QQqIZp45yURq4dic0+HCYfYNcY5Ejlb/CLmFnRLfy3wQuYafOeh3lB/DAKaqRKBtcZmA==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index 09c8570..92a3c58 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "dependencies": {}, "devDependencies": { "@ava/typescript": "^1.1.0", - "@types/node": "^16.4.6", + "@types/node": "^16.4.7", "ava": "^3.15.0", "typescript": "^4.3.5" }, From 6801dc1f4ceadf508ca835a90fdd154f4d5cbcbc Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 2 Aug 2021 04:50:46 +0000 Subject: [PATCH 34/46] Bump @types/node from 16.4.7 to 16.4.10 (#228) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 818925c..e1e1e0d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -156,9 +156,9 @@ } }, "@types/node": { - "version": "16.4.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.7.tgz", - "integrity": "sha512-aDDY54sst8sx47CWT6QQqIZp45yURq4dic0+HCYfYNcY5Ejlb/CLmFnRLfy3wQuYafOeh3lB/DAKaqRKBtcZmA==", + "version": "16.4.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.10.tgz", + "integrity": "sha512-TmVHsm43br64js9BqHWqiDZA+xMtbUpI1MBIA0EyiBmoV9pcEYFOSdj5fr6enZNfh4fChh+AGOLIzGwJnkshyQ==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index 92a3c58..8a1a90a 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "dependencies": {}, "devDependencies": { "@ava/typescript": "^1.1.0", - "@types/node": "^16.4.7", + "@types/node": "^16.4.10", "ava": "^3.15.0", "typescript": "^4.3.5" }, From db46c2b7e0eb3c24fb56ebbe962979d03461d322 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrique=20P=C3=B6hlmann?= <45039845+notanengineercom@users.noreply.github.com> Date: Mon, 4 Oct 2021 23:23:12 +0200 Subject: [PATCH 35/46] Add publish Github Action (#235) * Create npm-publish.yml * add beta tag support and improve release * add default npm tag --- .github/workflows/npm-publish.yml | 57 +++++++++++++++++++++++++++++++ package.json | 5 ++- 2 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/npm-publish.yml diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml new file mode 100644 index 0000000..50d18ef --- /dev/null +++ b/.github/workflows/npm-publish.yml @@ -0,0 +1,57 @@ +name: Publish + +on: + release: + types: [created] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: 14 + - run: npm ci --ignore-scripts + - run: npm test + + publish-npm: + needs: build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: 14 + registry-url: https://registry.npmjs.org/ + - run: npm ci --ignore-scripts + - run: npm run build + - run: echo "tag=latest" >> $GITHUB_ENV + - name: Sets npm tag + if: contains(github.event.release.tag_name, 'beta') + run: echo "tag=beta" >> $GITHUB_ENV + - run: npm publish --access public --tag {{ env.tag }} + env: + NODE_AUTH_TOKEN: ${{ secrets.npm_token }} + + publish-github: + needs: build + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: 14 + registry-url: https://npm.pkg.github.com/ + - run: npm ci --ignore-scripts + - run: npm run build + - run: echo "tag=latest" >> $GITHUB_ENV + - name: Sets npm tag + if: contains(github.event.release.tag_name, 'beta') + run: echo "tag=beta" >> $GITHUB_ENV + - run: npm publish --tag {{ env.tag }} + env: + NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/package.json b/package.json index 8a1a90a..4f9dbdc 100644 --- a/package.json +++ b/package.json @@ -40,9 +40,8 @@ "dist/src/**/*" ], "scripts": { - "prepack": "npm i && tsc", "test": "tsc --sourceMap && ava", - "build": "tsc" + "build": "rm -rf dist && tsc" }, "dependencies": {}, "devDependencies": { @@ -61,4 +60,4 @@ "failFast": true, "failWithoutAssertions": true } -} +} \ No newline at end of file From a15528d45d3a2940f37fa2153dc87c053f1d3b72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrique=20P=C3=B6hlmann?= Date: Thu, 21 Oct 2021 23:13:04 +0200 Subject: [PATCH 36/46] add missing syntax to github action --- .github/workflows/npm-publish.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index 50d18ef..c06c750 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -30,7 +30,7 @@ jobs: - name: Sets npm tag if: contains(github.event.release.tag_name, 'beta') run: echo "tag=beta" >> $GITHUB_ENV - - run: npm publish --access public --tag {{ env.tag }} + - run: npm publish --access public --tag ${{ env.tag }} env: NODE_AUTH_TOKEN: ${{ secrets.npm_token }} @@ -52,6 +52,6 @@ jobs: - name: Sets npm tag if: contains(github.event.release.tag_name, 'beta') run: echo "tag=beta" >> $GITHUB_ENV - - run: npm publish --tag {{ env.tag }} + - run: npm publish --tag ${{ env.tag }} env: NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 52a6965b2e0031359276a9dae068276512f67f08 Mon Sep 17 00:00:00 2001 From: Mathias Lykkegaard Lorenzen Date: Fri, 22 Oct 2021 20:37:11 +0200 Subject: [PATCH 37/46] Update npm-publish.yml --- .github/workflows/npm-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index c06c750..98a1adf 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -32,7 +32,7 @@ jobs: run: echo "tag=beta" >> $GITHUB_ENV - run: npm publish --access public --tag ${{ env.tag }} env: - NODE_AUTH_TOKEN: ${{ secrets.npm_token }} + NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }} publish-github: needs: build From 6e3011a81f9cb2beba0b7248500fbd1bf94369aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrique=20P=C3=B6hlmann?= <45039845+notanengineercom@users.noreply.github.com> Date: Thu, 2 Jun 2022 09:26:34 +0200 Subject: [PATCH 38/46] [ReleaseBranch] Substitute v2-beta: Rework substitution logic (#139) * add ts-node * create linked list classes * minor refactoring * add root substitute graph * replace context with contextNode * add recorded arguments class * add working returns example * update dependencies * add compile key to ava config * refactor existing interfaces This includes SubstituteBase, SubstituteException, Arguments, Utilities * replace linked list implementations with recorder + node * rework substitute implementation * refactor Arguments.ts * Substitute v2-beta: Tests (#231) * move existing tests to regression folder * add RecordedArguments spec * create Utilities spec * Improve perfomance: implement RecordsSet (#232) * improve proxy creation function * use node contexts to simplify node logic * implement custom records set RecordsSet implements the higher order filter and map methods which get applied when retrieving the iterator. This increases performance as it doesn't create arrays on each .map or .filter -> the iterator yields only the end values with one iteration * Add clear substitute (#233) resolves #46 * implement clearSubstitute * add clearSubstitute spec * 2.0.0-beta.0 * refactor and add recorder related specs (#236) * Update package.json Co-authored-by: Mathias Lykkegaard Lorenzen --- package-lock.json | 591 ++++++++++++++---------- package.json | 13 +- spec/Arguments.spec.ts | 111 ----- spec/ClearSubstitute.spec.ts | 65 +++ spec/RecordedArguments.spec.ts | 138 ++++++ spec/Recorder.spec.ts | 80 ++++ spec/RecordsSet.spec.ts | 66 +++ spec/Utilities.spec.ts | 103 +---- spec/didNotReceive.spec.ts | 52 --- spec/index.test.ts | 152 ------ spec/issues/11.test.ts | 28 -- spec/issues/23.test.ts | 25 - spec/issues/45.test.ts | 36 -- spec/mimicks.spec.ts | 65 --- spec/received.spec.ts | 139 ------ spec/regression/Arguments.spec.ts | 110 +++++ spec/regression/didNotReceive.spec.ts | 52 +++ spec/regression/index.test.ts | 155 +++++++ spec/regression/issues/11.test.ts | 28 ++ spec/regression/issues/23.test.ts | 25 + spec/{ => regression}/issues/36.test.ts | 50 +- spec/regression/issues/45.test.ts | 36 ++ spec/{ => regression}/issues/59.test.ts | 6 +- spec/regression/mimicks.spec.ts | 65 +++ spec/regression/received.spec.ts | 137 ++++++ spec/regression/rejects.spec.ts | 48 ++ spec/regression/resolves.spec.ts | 49 ++ spec/regression/returns.spec.ts | 184 ++++++++ spec/{ => regression}/throws.spec.ts | 2 +- spec/rejects.spec.ts | 52 --- spec/resolves.spec.ts | 49 -- spec/returns.spec.ts | 186 -------- spec/util/compatibility.ts | 6 - src/Arguments.ts | 169 ++++--- src/Context.ts | 128 ----- src/RecordedArguments.ts | 93 ++++ src/Recorder.ts | 54 +++ src/RecordsSet.ts | 65 +++ src/Substitute.ts | 120 +++-- src/SubstituteBase.ts | 86 +--- src/SubstituteException.ts | 52 +++ src/SubstituteNode.ts | 206 +++++++++ src/SubstituteNodeBase.ts | 67 +++ src/SubstituteProxy.ts | 32 ++ src/Transformations.ts | 6 +- src/Utilities.ts | 143 ++---- src/index.ts | 8 +- src/states/ContextState.ts | 10 - src/states/GetPropertyState.ts | 131 ------ src/states/InitialState.ts | 138 ------ src/states/SetPropertyState.ts | 58 --- 51 files changed, 2431 insertions(+), 2039 deletions(-) delete mode 100644 spec/Arguments.spec.ts create mode 100644 spec/ClearSubstitute.spec.ts create mode 100644 spec/RecordedArguments.spec.ts create mode 100644 spec/Recorder.spec.ts create mode 100644 spec/RecordsSet.spec.ts delete mode 100644 spec/didNotReceive.spec.ts delete mode 100644 spec/index.test.ts delete mode 100644 spec/issues/11.test.ts delete mode 100644 spec/issues/23.test.ts delete mode 100644 spec/issues/45.test.ts delete mode 100644 spec/mimicks.spec.ts delete mode 100644 spec/received.spec.ts create mode 100644 spec/regression/Arguments.spec.ts create mode 100644 spec/regression/didNotReceive.spec.ts create mode 100644 spec/regression/index.test.ts create mode 100644 spec/regression/issues/11.test.ts create mode 100644 spec/regression/issues/23.test.ts rename spec/{ => regression}/issues/36.test.ts (57%) create mode 100644 spec/regression/issues/45.test.ts rename spec/{ => regression}/issues/59.test.ts (76%) create mode 100644 spec/regression/mimicks.spec.ts create mode 100644 spec/regression/received.spec.ts create mode 100644 spec/regression/rejects.spec.ts create mode 100644 spec/regression/resolves.spec.ts create mode 100644 spec/regression/returns.spec.ts rename spec/{ => regression}/throws.spec.ts (97%) delete mode 100644 spec/rejects.spec.ts delete mode 100644 spec/resolves.spec.ts delete mode 100644 spec/returns.spec.ts delete mode 100644 spec/util/compatibility.ts delete mode 100644 src/Context.ts create mode 100644 src/RecordedArguments.ts create mode 100644 src/Recorder.ts create mode 100644 src/RecordsSet.ts create mode 100644 src/SubstituteException.ts create mode 100644 src/SubstituteNode.ts create mode 100644 src/SubstituteNodeBase.ts create mode 100644 src/SubstituteProxy.ts delete mode 100644 src/states/ContextState.ts delete mode 100644 src/states/GetPropertyState.ts delete mode 100644 src/states/InitialState.ts delete mode 100644 src/states/SetPropertyState.ts diff --git a/package-lock.json b/package-lock.json index e1e1e0d..885b5f0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,40 +1,41 @@ { "name": "@fluffy-spoon/substitute", - "version": "1.0.0", + "version": "2.0.0-beta.0", "lockfileVersion": 1, "requires": true, "dependencies": { "@ava/typescript": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@ava/typescript/-/typescript-1.1.1.tgz", - "integrity": "sha512-KbLUAe2cWXK63WLK6LnOJonjwEDU/8MNXCOA1ooX/YFZgKRmeAD1kZu+2K0ks5fnOCEcckNQAooyBNGdZUmMQA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@ava/typescript/-/typescript-2.0.0.tgz", + "integrity": "sha512-sn+upcMk81AMrlnx/hb/9T7gCGuBfw7hi+p79NPSSQMvY2G64mOB7qRaDExiHiZfZ7FN9j7HwQeFhHZLGD/NWQ==", "dev": true, "requires": { - "escape-string-regexp": "^2.0.0" + "escape-string-regexp": "^4.0.0", + "execa": "^5.0.0" } }, "@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", + "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", "dev": true, "requires": { - "@babel/highlight": "^7.10.4" + "@babel/highlight": "^7.14.5" } }, "@babel/helper-validator-identifier": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", - "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "version": "7.14.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", + "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", "dev": true }, "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.10.4", + "@babel/helper-validator-identifier": "^7.14.5", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -115,28 +116,28 @@ } }, "@nodelib/fs.scandir": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", - "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, "requires": { - "@nodelib/fs.stat": "2.0.4", + "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "@nodelib/fs.stat": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", - "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true }, "@nodelib/fs.walk": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", - "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "requires": { - "@nodelib/fs.scandir": "2.1.4", + "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, @@ -156,27 +157,27 @@ } }, "@types/node": { - "version": "16.4.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.10.tgz", - "integrity": "sha512-TmVHsm43br64js9BqHWqiDZA+xMtbUpI1MBIA0EyiBmoV9pcEYFOSdj5fr6enZNfh4fChh+AGOLIzGwJnkshyQ==", + "version": "12.20.24", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.24.tgz", + "integrity": "sha512-yxDeaQIAJlMav7fH5AQqPH1u8YIuhYJXYBzxaQ4PifsU0GDO38MSdmEDeRlIxrKbC6NbEaaEHDanWb+y30U8SQ==", "dev": true }, "@types/normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", "dev": true }, "acorn": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.0.4.tgz", - "integrity": "sha512-XNP0PqF1XD19ZlLKvB7cMmnZswW4C/03pRHgirB30uSJTaS3A3V1/P4sS3HPvFmjoriPCJQs+JDSbm4bL1TxGQ==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.5.0.tgz", + "integrity": "sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q==", "dev": true }, "acorn-walk": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.0.0.tgz", - "integrity": "sha512-oZRad/3SMOI/pxbbmqyurIx7jHw1wZDcR9G44L8pUVFEomX/0dH89SrM1KaDXuv1NpzAXz6Op/Xu/Qd5XXzdEA==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", "dev": true }, "aggregate-error": { @@ -245,15 +246,15 @@ "dev": true }, "ansi-styles": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.0.0.tgz", - "integrity": "sha512-6564t0m0fuQMnockqBv7wJxo9T5C2V9JpYXyNScfRDPVLusOQQhkpMGrFC17QbiolraQ1sMXX+Y5nJpjqozL4g==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true }, "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "dev": true, "requires": { "normalize-path": "^3.0.0", @@ -364,9 +365,9 @@ } }, "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, "base64-js": { @@ -376,15 +377,15 @@ "dev": true }, "binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true }, "bl": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.0.3.tgz", - "integrity": "sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "dev": true, "requires": { "buffer": "^5.5.0", @@ -399,44 +400,25 @@ "dev": true }, "boxen": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", - "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.0.1.tgz", + "integrity": "sha512-49VBlw+PrWEF51aCmy7QIteYPIFZxSpvqBdP/2itCPPlJ49kj9zg/XPRFrdkne2W+CfwXUls8exMvu1RysZpKA==", "dev": true, "requires": { "ansi-align": "^3.0.0", - "camelcase": "^5.3.1", - "chalk": "^3.0.0", - "cli-boxes": "^2.2.0", - "string-width": "^4.1.0", - "term-size": "^2.1.0", - "type-fest": "^0.8.1", - "widest-line": "^3.1.0" + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.0", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" }, "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true } } @@ -471,9 +453,9 @@ } }, "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, "cacheable-request": { @@ -515,15 +497,15 @@ "dev": true }, "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", "dev": true }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -542,19 +524,19 @@ } }, "chokidar": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", - "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", "dev": true, "requires": { - "anymatch": "~3.1.1", + "anymatch": "~3.1.2", "braces": "~3.0.2", - "fsevents": "~2.1.2", - "glob-parent": "~5.1.0", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" + "readdirp": "~3.6.0" } }, "chunkd": { @@ -603,9 +585,9 @@ } }, "cli-spinners": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.5.0.tgz", - "integrity": "sha512-PC+AmIuK04E6aeSs/pUccSujsTzBhu4HzC2dL+CfJB/Jcc2qTRbEwZQDfIUpt2Xl8BodYBEq8w4fc0kU2I9DjQ==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.0.tgz", + "integrity": "sha512-t+4/y50K/+4xcCRosKkA7W4gTr1MySvLV0q+PxmG7FJ5g+66ChKurYjxBCjHggHH3HA5Hh9cy+lcUGWDqVH+4Q==", "dev": true }, "cli-truncate": { @@ -681,9 +663,9 @@ "dev": true }, "concordance": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/concordance/-/concordance-5.0.1.tgz", - "integrity": "sha512-TbNtInKVElgEBnJ1v2Xg+MFX2lvFLbmlv3EuSC5wTfCwpB8kC3w3mffF6cKuUhkn475Ym1f1I4qmuXzx2+uXpw==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/concordance/-/concordance-5.0.4.tgz", + "integrity": "sha512-OAcsnTEYu1ARJqWVGwf4zh4JDfHZEaSNlNccFmt8YjB2l/n19/PF2viLINHc57vO4FKIAFl2FWASIGZZWZ2Kxw==", "dev": true, "requires": { "date-time": "^3.1.0", @@ -711,9 +693,9 @@ } }, "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", "dev": true, "requires": { "safe-buffer": "~5.1.1" @@ -725,6 +707,17 @@ "integrity": "sha1-fj5Iu+bZl7FBfdyihoIEtNPYVxU=", "dev": true }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, "crypto-random-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", @@ -750,9 +743,9 @@ } }, "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, "requires": { "ms": "2.1.2" @@ -885,9 +878,9 @@ "dev": true }, "escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true }, "esprima": { @@ -902,6 +895,23 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, "fast-diff": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", @@ -909,23 +919,22 @@ "dev": true }, "fast-glob": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", - "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", + "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", + "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.2", - "picomatch": "^2.2.1" + "micromatch": "^4.0.4" } }, "fastq": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.10.0.tgz", - "integrity": "sha512-NL2Qc5L3iQEsyYzweq7qfgy5OtXCmGzGvhElGEd/SoFWEMOEczNh5s5ocaF01HDetxz+p8ecjNPA6cZxxIHmzA==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", "dev": true, "requires": { "reusify": "^1.0.4" @@ -974,9 +983,9 @@ "dev": true }, "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, "optional": true }, @@ -993,18 +1002,15 @@ "dev": true }, "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true }, "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -1025,18 +1031,18 @@ } }, "global-dirs": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.1.0.tgz", - "integrity": "sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", + "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", "dev": true, "requires": { - "ini": "1.3.7" + "ini": "2.0.0" } }, "globby": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz", - "integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==", + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", + "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", "dev": true, "requires": { "array-union": "^2.1.0", @@ -1064,12 +1070,23 @@ "p-cancelable": "^1.0.0", "to-readable-stream": "^1.0.0", "url-parse-lax": "^3.0.0" + }, + "dependencies": { + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + } } }, "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", "dev": true }, "has": { @@ -1105,6 +1122,12 @@ "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", "dev": true }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true + }, "ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -1168,15 +1191,15 @@ "dev": true }, "ini": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz", - "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", "dev": true }, "irregular-plurals": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.2.0.tgz", - "integrity": "sha512-YqTdPLfwP7YFN0SsD3QUVCkm9ZG2VzOXv3DOrw5G5mkMbVwptTwVcFv7/C0vOpBmgTxAeTG19XpUs1E522LW9Q==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.3.0.tgz", + "integrity": "sha512-MVBLKUTangM3EfRPFROhmWQQKRDsrgI83J8GS3jXy+OwYqiR2/aoWndYQ5416jLE3uaGgLH7ncme3X9y09gZ3g==", "dev": true }, "is-arrayish": { @@ -1204,9 +1227,9 @@ } }, "is-core-module": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", - "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.6.0.tgz", + "integrity": "sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==", "dev": true, "requires": { "has": "^1.0.3" @@ -1240,13 +1263,13 @@ } }, "is-installed-globally": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", - "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", "dev": true, "requires": { - "global-dirs": "^2.0.1", - "is-path-inside": "^3.0.1" + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" } }, "is-interactive": { @@ -1280,9 +1303,9 @@ "dev": true }, "is-path-inside": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.2.tgz", - "integrity": "sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true }, "is-plain-object": { @@ -1297,18 +1320,36 @@ "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", "dev": true }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true + }, "is-yarn-global": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", "dev": true }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, "js-string-escape": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", @@ -1402,12 +1443,13 @@ "dev": true }, "log-symbols": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", - "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "requires": { - "chalk": "^4.0.0" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" } }, "lowercase-keys": { @@ -1458,14 +1500,6 @@ "dev": true, "requires": { "escape-string-regexp": "^4.0.0" - }, - "dependencies": { - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - } } }, "md5-hex": { @@ -1478,9 +1512,9 @@ } }, "mem": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-8.0.0.tgz", - "integrity": "sha512-qrcJOe6uD+EW8Wrci1Vdiua/15Xw3n/QnaNXE7varnB6InxSk7nu3/i5jfy3S6kWxr8WYJ6R1o0afMUtvorTsA==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/mem/-/mem-8.1.1.tgz", + "integrity": "sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA==", "dev": true, "requires": { "map-age-cleaner": "^0.1.3", @@ -1495,6 +1529,12 @@ } } }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, "merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -1502,13 +1542,13 @@ "dev": true }, "micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", "dev": true, "requires": { "braces": "^3.0.1", - "picomatch": "^2.0.5" + "picomatch": "^2.2.3" } }, "mimic-fn": { @@ -1576,6 +1616,15 @@ "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", "dev": true }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -1595,17 +1644,18 @@ } }, "ora": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.2.0.tgz", - "integrity": "sha512-+wG2v8TUU8EgzPHun1k/n45pXquQ9fHnbXVetl9rRgO6kjZszGGbraF3XPTIdgeA+s1lbRjSEftAnyT0w8ZMvQ==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", "dev": true, "requires": { - "bl": "^4.0.3", + "bl": "^4.1.0", "chalk": "^4.1.0", "cli-cursor": "^3.1.0", "cli-spinners": "^2.5.0", "is-interactive": "^1.0.0", - "log-symbols": "^4.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", "strip-ansi": "^6.0.0", "wcwidth": "^1.0.1" } @@ -1727,10 +1777,16 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, "path-type": { @@ -1740,9 +1796,9 @@ "dev": true }, "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", "dev": true }, "pify": { @@ -1849,6 +1905,12 @@ "escape-goat": "^2.0.0" } }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, "rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -1859,6 +1921,14 @@ "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + } } }, "read-pkg": { @@ -1874,9 +1944,9 @@ }, "dependencies": { "parse-json": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", - "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", @@ -1905,9 +1975,9 @@ } }, "readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "requires": { "picomatch": "^2.2.1" @@ -1938,12 +2008,12 @@ "dev": true }, "resolve": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", - "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", "dev": true, "requires": { - "is-core-module": "^2.1.0", + "is-core-module": "^2.2.0", "path-parse": "^1.0.6" } }, @@ -1997,10 +2067,13 @@ } }, "run-parallel": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", - "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", - "dev": true + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } }, "safe-buffer": { "version": "5.1.2", @@ -2009,9 +2082,9 @@ "dev": true }, "semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -2051,6 +2124,21 @@ } } }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, "signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", @@ -2092,9 +2180,9 @@ "dev": true }, "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "version": "0.5.20", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.20.tgz", + "integrity": "sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -2128,9 +2216,9 @@ } }, "spdx-license-ids": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz", - "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==", + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", + "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", "dev": true }, "sprintf-js": { @@ -2146,12 +2234,20 @@ "dev": true, "requires": { "escape-string-regexp": "^2.0.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + } } }, "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", "dev": true, "requires": { "emoji-regex": "^8.0.0", @@ -2191,6 +2287,12 @@ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -2225,12 +2327,6 @@ "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", "dev": true }, - "term-size": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", - "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", - "dev": true - }, "time-zone": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/time-zone/-/time-zone-1.0.0.tgz", @@ -2274,9 +2370,9 @@ } }, "typescript": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", - "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.3.tgz", + "integrity": "sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==", "dev": true }, "unique-string": { @@ -2289,23 +2385,23 @@ } }, "update-notifier": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.0.1.tgz", - "integrity": "sha512-BuVpRdlwxeIOvmc32AGYvO1KVdPlsmqSh8KDDBxS6kDE5VR7R8OMP1d8MdhaVBvxl4H3551k9akXr0Y1iIB2Wg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", + "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", "dev": true, "requires": { - "boxen": "^4.2.0", + "boxen": "^5.0.0", "chalk": "^4.1.0", "configstore": "^5.0.1", "has-yarn": "^2.1.0", "import-lazy": "^2.1.0", "is-ci": "^2.0.0", - "is-installed-globally": "^0.3.2", + "is-installed-globally": "^0.4.0", "is-npm": "^5.0.0", "is-yarn-global": "^0.3.0", "latest-version": "^5.1.0", "pupa": "^2.1.1", - "semver": "^7.3.2", + "semver": "^7.3.4", "semver-diff": "^3.1.1", "xdg-basedir": "^4.0.0" } @@ -2350,6 +2446,15 @@ "integrity": "sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q==", "dev": true }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, "widest-line": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", @@ -2406,9 +2511,9 @@ "dev": true }, "y18n": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz", - "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true }, "yallist": { @@ -2433,9 +2538,9 @@ } }, "yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true } } diff --git a/package.json b/package.json index 4f9dbdc..53ba734 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@fluffy-spoon/substitute", - "version": "1.0.0", + "version": "2.0.0-beta.1", "description": "TypeScript port of NSubstitute, which aims to provide a much more fluent mocking opportunity for strong-typed languages", "license": "MIT", "funding": { @@ -45,19 +45,20 @@ }, "dependencies": {}, "devDependencies": { - "@ava/typescript": "^1.1.0", - "@types/node": "^16.4.10", + "@ava/typescript": "^2.0.0", + "@types/node": "^12.20.24", "ava": "^3.15.0", - "typescript": "^4.3.5" + "typescript": "^4.4.3" }, "ava": { "typescript": { "rewritePaths": { "/": "dist/" - } + }, + "compile": false }, "cache": false, "failFast": true, "failWithoutAssertions": true } -} \ No newline at end of file +} diff --git a/spec/Arguments.spec.ts b/spec/Arguments.spec.ts deleted file mode 100644 index 6efa1c6..0000000 --- a/spec/Arguments.spec.ts +++ /dev/null @@ -1,111 +0,0 @@ -import test from 'ava'; -import { Arg } from '../src'; -import { Argument } from 'src/Arguments'; - -const testObject = { "foo": "bar" }; -const testArray = ["a", 1, true]; - -const parent = {} as any; -parent.child = parent; -const root = {} as any; -root.path = { to: { nested: root } }; -const testFunc = () => { }; - -test('should match any argument(s) using Arg.all', t => { - t.true(Arg.all().matches([])); - t.true(Arg.all().matches([0])); - t.true(Arg.all().matches([1])); - t.true(Arg.all().matches(['string'])); - t.true(Arg.all().matches([true])); - t.true(Arg.all().matches([false])); - t.true(Arg.all().matches(null)); - t.true(Arg.all().matches(undefined)); - t.true(Arg.all().matches([1, 2])); - t.true(Arg.all().matches(['string1', 'string2'])); -}) - -test('should match any argument using Arg.any', t => { - t.true(Arg.any().matches('hi')); - t.true(Arg.any().matches(1)); - t.true(Arg.any().matches(0)); - t.true(Arg.any().matches(false)); - t.true(Arg.any().matches(true)); - t.true(Arg.any().matches(null)); - t.true(Arg.any().matches(undefined)); - t.true(Arg.any().matches(testObject)); - t.true(Arg.any().matches(testArray)); - t.true(Arg.any().matches(testFunc)); - t.true(Arg.any().matches()); - t.true(Arg.any().matches(parent)); - t.true(Arg.any().matches(root)); - t.true(Arg.any().matches(parent)); - t.true(Arg.any().matches(root)); -}); - -test('should not match any argument using Arg.any.not', t => { - t.false(Arg.any.not().matches('hi')); - t.false(Arg.any.not().matches(1)); - t.false(Arg.any.not().matches(0)); - t.false(Arg.any.not().matches(false)); - t.false(Arg.any.not().matches(true)); - t.false(Arg.any.not().matches(null)); - t.false(Arg.any.not().matches(undefined)); - t.false(Arg.any.not().matches(testObject)); - t.false(Arg.any.not().matches(testArray)); - t.false(Arg.any.not().matches(testFunc)); - t.false(Arg.any.not().matches()); - t.false(Arg.any.not().matches(parent)); - t.false(Arg.any.not().matches(root)); - t.false(Arg.any.not().matches(parent)); - t.false(Arg.any.not().matches(root)); -}); - -test('should match the type of the argument using Arg.any', t => { - t.true(Arg.any('string').matches('foo')); - t.true(Arg.any('number').matches(1)); - t.true(Arg.any('boolean').matches(true)); - t.true(Arg.any('symbol').matches(Symbol())); - t.true((>Arg.any('undefined')).matches(undefined)); - t.true(Arg.any('object').matches(testObject)); - t.true(Arg.any('array').matches(testArray)); - t.true(Arg.any('function').matches(testFunc)); - t.true(Arg.any('object').matches(parent)); - t.true(Arg.any('object').matches(root)); - - t.false((>Arg.any('string')).matches(1)); - t.false((>Arg.any('number')).matches('string')); - t.false(Arg.any('boolean').matches(null)); - t.false((>Arg.any('object')).matches('foo')); - t.false((>Arg.any('array')).matches('bar')); - t.false((>Arg.any('function')).matches('foo')); -}); - - -test('should not match the type of the argument using Arg.any.not', t => { - t.false(Arg.any.not('string').matches('123')); - t.false(Arg.any.not('number').matches(123)); - t.false(Arg.any.not('boolean').matches(true)); - t.false(Arg.any.not('symbol').matches(Symbol())); - t.false((>Arg.any.not('undefined')).matches(undefined)); - t.false(Arg.any.not('object').matches(testObject)); - t.false(Arg.any.not('array').matches(testArray)); - t.false(Arg.any.not('function').matches(testFunc)); - t.false(Arg.any.not('object').matches(parent)); - t.false(Arg.any.not('object').matches(root)); -}); - -test('should match the argument with the predicate function using Arg.is', t => { - t.true(Arg.is(x => x === 'foo').matches('foo')); - t.true(Arg.is(x => x % 2 == 0).matches(4)); - - t.false(Arg.is(x => x === 'foo').matches('bar')); - t.false(Arg.is(x => x % 2 == 0).matches(3)); -}); - -test('should not match the argument with the predicate function using Arg.is.not', t => { - t.false(Arg.is.not(x => x === 'foo').matches('foo')); - t.false(Arg.is.not(x => x % 2 == 0).matches(4)); - - t.true(Arg.is.not(x => x === 'foo').matches('bar')); - t.true(Arg.is.not(x => x % 2 == 0).matches(3)); -}); \ No newline at end of file diff --git a/spec/ClearSubstitute.spec.ts b/spec/ClearSubstitute.spec.ts new file mode 100644 index 0000000..b587d4c --- /dev/null +++ b/spec/ClearSubstitute.spec.ts @@ -0,0 +1,65 @@ +import test from 'ava' + +import { Substitute, SubstituteOf } from '../src' +import { SubstituteBase } from '../src/SubstituteBase' +import { SubstituteNode } from '../src/SubstituteNode' + +interface Calculator { + add(a: number, b: number): number + subtract(a: number, b: number): number + divide(a: number, b: number): number + isEnabled: boolean +} + +type InstanceReturningSubstitute = SubstituteOf & { + [SubstituteBase.instance]: Substitute +} + +test('clears everything on a substitute', t => { + const calculator = Substitute.for() as InstanceReturningSubstitute + calculator.add(1, 1) + calculator.received().add(1, 1) + calculator.clearSubstitute() + + t.is(calculator[Substitute.instance].recorder.records.size, 0) + t.is(calculator[Substitute.instance].recorder.indexedRecords.size, 0) + + t.throws(() => calculator.received().add(1, 1)) + + // explicitly using 'all' + calculator.add(1, 1) + calculator.received().add(1, 1) + calculator.clearSubstitute('all') + + t.is(calculator[Substitute.instance].recorder.records.size, 0) + t.is(calculator[Substitute.instance].recorder.indexedRecords.size, 0) + + t.throws(() => calculator.received().add(1, 1)) +}) + +test('clears received calls on a substitute', t => { + const calculator = Substitute.for() as InstanceReturningSubstitute + calculator.add(1, 1) + calculator.add(1, 1).returns(2) + calculator.clearSubstitute('receivedCalls') + + t.is(calculator[Substitute.instance].recorder.records.size, 2) + t.is(calculator[Substitute.instance].recorder.indexedRecords.size, 2) + + t.throws(() => calculator.received().add(1, 1)) + t.is(calculator.add(1, 1), 2) +}) + +test('clears return values on a substitute', t => { + const calculator = Substitute.for() as InstanceReturningSubstitute + calculator.add(1, 1) + calculator.add(1, 1).returns(2) + calculator.clearSubstitute('substituteValues') + + t.is(calculator[Substitute.instance].recorder.records.size, 2) + t.is(calculator[Substitute.instance].recorder.indexedRecords.size, 2) + + t.notThrows(() => calculator.received().add(1, 1)) + // @ts-expect-error + t.true(calculator.add(1, 1)[SubstituteBase.instance] instanceof SubstituteNode) +}) \ No newline at end of file diff --git a/spec/RecordedArguments.spec.ts b/spec/RecordedArguments.spec.ts new file mode 100644 index 0000000..d661585 --- /dev/null +++ b/spec/RecordedArguments.spec.ts @@ -0,0 +1,138 @@ +import test from 'ava' +import { inspect } from 'util' + +import { Arg } from '../src' +import { RecordedArguments } from '../src/RecordedArguments' + +const testObject = { 'foo': 'bar' } +const testArray = ['a', 1, true] + +// #90: Infinite recursion in deepEqual https://github.com/ffMathy/FluffySpoon.JavaScript.Testing.Faking/blob/master/spec/issues/90.test.ts +const parent = {} as any +parent.child = parent +const root = {} as any +root.path = { to: { nested: root } } + +const testFunc = () => { } +const testSymbol = Symbol() + +test('records values and classifies them correctly', t => { + const emptyArguments = RecordedArguments.from([]) + t.deepEqual(emptyArguments.value, []) + t.is(emptyArguments.argumentsClass, 'plain') + t.is(emptyArguments.hasNoArguments, false) + + const primitivesOnlyArguments = RecordedArguments.from([1, 'Substitute', false, testSymbol, undefined, null, testFunc, {}]) + t.deepEqual(primitivesOnlyArguments.value, [1, 'Substitute', false, testSymbol, undefined, null, testFunc, {}]) + t.is(primitivesOnlyArguments.argumentsClass, 'plain') + t.is(primitivesOnlyArguments.hasNoArguments, false) + + const anyArg = Arg.any('any') + const withSingleArgumentArguments = RecordedArguments.from([1, 'Substitute', false, testSymbol, undefined, null, testFunc, {}, anyArg]) + t.deepEqual(withSingleArgumentArguments.value, [1, 'Substitute', false, testSymbol, undefined, null, testFunc, {}, anyArg]) + t.is(withSingleArgumentArguments.argumentsClass, 'with-predicate') + t.is(withSingleArgumentArguments.hasNoArguments, false) + + const allArg = Arg.all() + const allArgumentArguments = RecordedArguments.from([allArg]) + t.deepEqual(allArgumentArguments.value, [allArg]) + t.is(allArgumentArguments.argumentsClass, 'wildcard') + t.is(allArgumentArguments.hasNoArguments, false) +}) + +test('creates a valid instance for no arguments', t => { + const args = RecordedArguments.none() + + t.is(args.value, undefined) + t.is(args.argumentsClass, undefined) + t.is(args.hasNoArguments, true) +}) + +test('sorts correctly objects with RecordedArguments', t => { + const plain1 = RecordedArguments.from([]) + const plain2 = RecordedArguments.from([1, 2]) + const withPredicate1 = RecordedArguments.from([1, Arg.any()]) + const withPredicate2 = RecordedArguments.from([Arg.any()]) + const wildcard1 = RecordedArguments.from([Arg.all()]) + const wildcard2 = RecordedArguments.from([Arg.all()]) + + const wrapper = (recordedArguments: RecordedArguments[]) => recordedArguments.map(args => ({ recordedArguments: args })) + const sortedArgs1 = RecordedArguments.sort(wrapper([wildcard1, wildcard2, withPredicate1, withPredicate2, plain1, plain2])) + const sortedArgs2 = RecordedArguments.sort(wrapper([wildcard1, withPredicate1, plain1, withPredicate2, wildcard2, plain2])) + + t.deepEqual(sortedArgs1, wrapper([plain1, plain2, withPredicate1, withPredicate2, wildcard1, wildcard2])) + t.deepEqual(sortedArgs2, wrapper([plain1, plain2, withPredicate1, withPredicate2, wildcard1, wildcard2])) +}) + +test('matches correctly with another RecordedArguments instance when none arguments are recorded', t => { + const args = RecordedArguments.none() + + t.true(args.match(args)) + t.true(args.match(RecordedArguments.none())) + + t.false(args.match(RecordedArguments.from([]))) + t.false(RecordedArguments.from([]).match(args)) + t.false(args.match(RecordedArguments.from([undefined]))) +}) + +test('matches correctly with another RecordedArguments instance when primitive arguments are recorded', t => { + // single + t.true(RecordedArguments.from([]).match(RecordedArguments.from([]))) + t.true(RecordedArguments.from(['Substitute']).match(RecordedArguments.from(['Substitute']))) + t.true(RecordedArguments.from([0]).match(RecordedArguments.from([0]))) + t.true(RecordedArguments.from([true]).match(RecordedArguments.from([true]))) + t.true(RecordedArguments.from([false]).match(RecordedArguments.from([false]))) + t.true(RecordedArguments.from([undefined]).match(RecordedArguments.from([undefined]))) + t.true(RecordedArguments.from([null]).match(RecordedArguments.from([null]))) + t.true(RecordedArguments.from([Symbol.for('test')]).match(RecordedArguments.from([Symbol.for('test')]))) + + t.false(RecordedArguments.from(['a']).match(RecordedArguments.from(['b']))) + t.false(RecordedArguments.from([1]).match(RecordedArguments.from([2]))) + t.false(RecordedArguments.from([true]).match(RecordedArguments.from([false]))) + t.false(RecordedArguments.from([undefined]).match(RecordedArguments.from([null]))) + t.false(RecordedArguments.from(['1']).match(RecordedArguments.from([1]))) + + // multi + t.true(RecordedArguments.from([1, 2, 3]).match(RecordedArguments.from([1, 2, 3]))) + + t.false(RecordedArguments.from([1, 2, 3]).match(RecordedArguments.from([3, 2, 1]))) + t.false(RecordedArguments.from([1, 2, 3]).match(RecordedArguments.from([1, 2, 3, 4]))) + t.false(RecordedArguments.from([1, 2, 3, 4]).match(RecordedArguments.from([1, 2, 3]))) +}) + +test('matches correctly with another RecordedArguments instance when object arguments are recorded', t => { + // same reference + t.true(RecordedArguments.from([testObject]).match(RecordedArguments.from([testObject]))) + t.true(RecordedArguments.from([testArray]).match(RecordedArguments.from([testArray]))) + t.true(RecordedArguments.from([testFunc]).match(RecordedArguments.from([testFunc]))) + t.true(RecordedArguments.from([parent]).match(RecordedArguments.from([parent]))) + t.true(RecordedArguments.from([root]).match(RecordedArguments.from([root]))) + + // deep equal + const objectWithSelfReference = { a: 1, b: 2 } as any + objectWithSelfReference.c = objectWithSelfReference + const anotherObjectWithSelfReference = { a: 1, b: 2 } as any + anotherObjectWithSelfReference.c = anotherObjectWithSelfReference + + t.true(RecordedArguments.from([{ a: 1 }]).match(RecordedArguments.from([{ a: 1 }]))) + t.true(RecordedArguments.from([[]]).match(RecordedArguments.from([[]]))) + t.true(RecordedArguments.from([[1, 'a']]).match(RecordedArguments.from([[1, 'a']]))) + t.true(RecordedArguments.from([objectWithSelfReference]).match(RecordedArguments.from([anotherObjectWithSelfReference]))) +}) + +test('matches correctly with another RecordedArguments instance when using a wildcard argument', t => { + t.true(RecordedArguments.from([Arg.all()]).match(RecordedArguments.from([1, 2, 3]))) + t.true(RecordedArguments.from(['Substitute', 'JS']).match(RecordedArguments.from([Arg.all()]))) +}) + +test('matches correctly with another RecordedArguments instance when using predicate arguments', t => { + t.true(RecordedArguments.from([Arg.any(), Arg.any('number'), Arg.is((x: number) => x === 3), 4]).match(RecordedArguments.from([1, 2, 3, 4]))) + t.true(RecordedArguments.from(['Substitute', 'JS']).match(RecordedArguments.from([Arg.is(x => typeof x === 'string'), Arg.any('string')]))) +}) + +test('generates custom text representation', t => { + t.is(inspect(RecordedArguments.none()), '') + t.is(inspect(RecordedArguments.from([])), '()') + t.is(inspect(RecordedArguments.from([undefined])), 'undefined') + t.is(inspect(RecordedArguments.from([undefined, 1])), '(undefined, 1)') +}) \ No newline at end of file diff --git a/spec/Recorder.spec.ts b/spec/Recorder.spec.ts new file mode 100644 index 0000000..0526185 --- /dev/null +++ b/spec/Recorder.spec.ts @@ -0,0 +1,80 @@ +import test from 'ava' + +import { Recorder } from '../src/Recorder' +import { RecordsSet } from '../src/RecordsSet' +import { Substitute } from '../src/Substitute' +import { SubstituteNodeBase } from '../src/SubstituteNodeBase' + +const nodeFactory = (key: string) => { + const node = Substitute.for() + node.key.returns(key) + return node +} + +const node = nodeFactory('node') +const otherNode = nodeFactory('otherNode') +const otherNodeDifferentInstance = nodeFactory('otherNode') + +test('adds all records once only', t => { + const recorder = new Recorder() + recorder.addRecord(node) + recorder.addRecord(node) + recorder.addRecord(otherNode) + recorder.addRecord(otherNode) + recorder.addRecord(otherNodeDifferentInstance) + + const allRecords = [...recorder.records] + t.deepEqual(allRecords, [node, otherNode, otherNodeDifferentInstance]) +}) + +test('indexes all records correctly', t => { + const recorder = new Recorder() + recorder.addIndexedRecord(node) + recorder.addIndexedRecord(node) + recorder.addIndexedRecord(otherNode) + recorder.addIndexedRecord(otherNode) + recorder.addIndexedRecord(otherNodeDifferentInstance) + + const allRecords = [...recorder.records] + t.deepEqual(allRecords, [node, otherNode, otherNodeDifferentInstance]) + + const nodeSet = recorder.indexedRecords.get(node.key) + t.true(nodeSet instanceof RecordsSet) + t.deepEqual([...nodeSet], [node]) + + const otherNodeSet = recorder.indexedRecords.get(otherNode.key) + t.true(otherNodeSet instanceof RecordsSet) + t.deepEqual([...otherNodeSet], [otherNode, otherNodeDifferentInstance]) +}) + +test('returns all sibling nodes', t => { + const recorder = new Recorder() + recorder.addIndexedRecord(node) + recorder.addIndexedRecord(otherNode) + recorder.addIndexedRecord(otherNodeDifferentInstance) + + const nodeSiblings = recorder.getSiblingsOf(node) + t.deepEqual([...nodeSiblings], []) + + const otherNodeSiblings = recorder.getSiblingsOf(otherNode) + t.deepEqual([...otherNodeSiblings], [otherNodeDifferentInstance]) + + const otherNodeDifferentInstanceSiblings = recorder.getSiblingsOf(otherNodeDifferentInstance) + t.deepEqual([...otherNodeDifferentInstanceSiblings], [otherNode]) +}) + +test('clears recorded nodes by a given filter function', t => { + const recorder = new Recorder() + recorder.addIndexedRecord(node) + recorder.addIndexedRecord(otherNode) + recorder.addIndexedRecord(otherNodeDifferentInstance) + + recorder.clearRecords(n => n.key === otherNode.key) + t.deepEqual([...recorder.records], [node]) + t.deepEqual([...recorder.indexedRecords.get(node.key)], [node]) + t.is(recorder.indexedRecords.get(otherNode.key), undefined) + + recorder.clearRecords(_ => true) + t.deepEqual([...recorder.records], []) + t.deepEqual(recorder.indexedRecords.get(node.key), undefined) +}) diff --git a/spec/RecordsSet.spec.ts b/spec/RecordsSet.spec.ts new file mode 100644 index 0000000..2f90868 --- /dev/null +++ b/spec/RecordsSet.spec.ts @@ -0,0 +1,66 @@ +import test, { ExecutionContext, Macro } from 'ava' + +import { RecordsSet } from '../src/RecordsSet' + +const dataArray = [1, 2, 3] +function* dataArrayGenerator() { + yield* dataArray +} +const inputData = [dataArray, dataArray[Symbol.iterator](), new Set(dataArray), dataArrayGenerator(), new RecordsSet(dataArray)] +const macro: Macro = (t: ExecutionContext, ...inputData: Iterable[]): void => { + inputData.forEach(input => { + const set = new RecordsSet(input) + + t.true(set.has(1)) + t.true(set.has(2)) + t.true(set.has(3)) + t.is(set.size, 3) + t.deepEqual([...set], dataArray) + t.deepEqual([...set[Symbol.iterator]()], dataArray) + t.deepEqual([...set.values()], dataArray) + + t.false(set.delete(4)) + t.true(set.delete(3)) + t.false(set.delete(3)) + t.is(set.size, 2) + + set.clear() + t.is(set.size, 0) + }) +} + +test('behaves like a native Set object', macro, ...inputData) + +test('applies a filter function everytime the iterator is consumed', t => { + const set = new RecordsSet([1, 2, 3]) + const setWithFilter = set.filter(number => number !== 2) + + t.deepEqual([...set], [1, 2, 3]) + t.deepEqual([...setWithFilter], [1, 3]) + t.deepEqual([...setWithFilter], [1, 3]) +}) + +test('applies a map function everytime the iterator is consumed', t => { + const set = new RecordsSet([1, 2, 3]) + const setWithMap = set.map(number => number.toString()) + + t.deepEqual([...set], [1, 2, 3]) + t.deepEqual([...setWithMap], ['1', '2', '3']) + t.deepEqual([...setWithMap], ['1', '2', '3']) +}) + +test('applies and preserves the order of filter and map functions everytime the iterator is consumed', t => { + const set = new RecordsSet([1, 2, 3]) + const setWithFilter = set.filter(number => number !== 2) + const setWithFilterAndMap = setWithFilter.map(number => number.toString()) + const setWithFilterMapAndAnotherFilter = setWithFilterAndMap.filter(string => string === '3') + + t.deepEqual([...set], [1, 2, 3]) + t.deepEqual([...setWithFilter], [1, 3]) + t.deepEqual([...setWithFilterAndMap], ['1', '3']) + t.deepEqual([...setWithFilterMapAndAnotherFilter], ['3']) + + t.deepEqual([...setWithFilter], [1, 3]) + t.deepEqual([...setWithFilterAndMap], ['1', '3']) + t.deepEqual([...setWithFilterMapAndAnotherFilter], ['3']) +}) \ No newline at end of file diff --git a/spec/Utilities.spec.ts b/spec/Utilities.spec.ts index be6ea2b..462b7fd 100644 --- a/spec/Utilities.spec.ts +++ b/spec/Utilities.spec.ts @@ -1,102 +1,5 @@ -import test from 'ava'; +import test from 'ava' -import { Arg } from '../src'; -import { areArgumentArraysEqual } from '../src/Utilities'; - -const testObject = { "foo": "bar" }; -const testArray = ["a", 1, true]; - -// #90: Infinite recursion in deepEqual https://github.com/ffMathy/FluffySpoon.JavaScript.Testing.Faking/blob/master/spec/issues/90.test.ts -const parent = {} as any; -parent.child = parent; -const root = {} as any; -root.path = { to: { nested: root } }; - -const testFunc = () => { }; - -//#region areArgumentArraysEqual test('areArgumentArraysEqual should return valid result for primitive arguments', t => { - // single - t.true(areArgumentArraysEqual([''], [''])); - t.true(areArgumentArraysEqual(['a'], ['a'])); - t.true(areArgumentArraysEqual([0], [0])); - t.true(areArgumentArraysEqual([1], [1])); - t.true(areArgumentArraysEqual([true], [true])); - t.true(areArgumentArraysEqual([false], [false])); - t.true(areArgumentArraysEqual([undefined], [undefined])); - t.true(areArgumentArraysEqual([null], [null])); - t.true(areArgumentArraysEqual([testObject], [testObject])); - t.true(areArgumentArraysEqual([testArray], [testArray])); - t.true(areArgumentArraysEqual([testFunc], [testFunc])); - t.true(areArgumentArraysEqual([parent], [parent])); - t.true(areArgumentArraysEqual([root], [root])); - - t.false(areArgumentArraysEqual(['a'], ['b'])); - t.false(areArgumentArraysEqual([1], [2])); - t.false(areArgumentArraysEqual([true], [false])); - t.false(areArgumentArraysEqual([undefined], [null])); - t.false(areArgumentArraysEqual([testObject], [testArray])); - - // multi - t.true(areArgumentArraysEqual([1, 2, 3], [1, 2, 3])); - - t.false(areArgumentArraysEqual([1, 2, 3], [3, 2, 1])); - t.false(areArgumentArraysEqual([1, 2, 3, 4], [1, 2, 3])); - t.false(areArgumentArraysEqual([1, 2, 3], [1, 2, 3, 4])); -}); - -test('areArgumentArraysEqual should return valid result using Arg.all()', t => { - t.true(areArgumentArraysEqual([Arg.all()], [])); - t.true(areArgumentArraysEqual([Arg.all()], [0])); - t.true(areArgumentArraysEqual([Arg.all()], [1])); - t.true(areArgumentArraysEqual([Arg.all()], ['string'])); - t.true(areArgumentArraysEqual([Arg.all()], [true])); - t.true(areArgumentArraysEqual([Arg.all()], [false])); - t.true(areArgumentArraysEqual([Arg.all()], [null])); - t.true(areArgumentArraysEqual([Arg.all()], [undefined])); - t.true(areArgumentArraysEqual([Arg.all()], [1, 2])); - t.true(areArgumentArraysEqual([Arg.all()], ['string1', 'string2'])); - t.true(areArgumentArraysEqual([Arg.all()], [parent, root])); -}) - -test('areArgumentArraysEqual should return valid result using Arg', t => { - t.true(areArgumentArraysEqual([Arg.any()], ['hi'])); - t.true(areArgumentArraysEqual([Arg.any()], [1])); - t.true(areArgumentArraysEqual([Arg.any()], [0])); - t.true(areArgumentArraysEqual([Arg.any()], [false])); - t.true(areArgumentArraysEqual([Arg.any()], [true])); - t.true(areArgumentArraysEqual([Arg.any()], [null])); - t.true(areArgumentArraysEqual([Arg.any()], [undefined])); - t.true(areArgumentArraysEqual([Arg.any()], [testObject])); - t.true(areArgumentArraysEqual([Arg.any()], [testArray])); - t.true(areArgumentArraysEqual([Arg.any()], [testFunc])); - t.true(areArgumentArraysEqual([Arg.any()], [])); - t.true(areArgumentArraysEqual([Arg.any()], [parent])); - t.true(areArgumentArraysEqual([Arg.any()], [root])); - - t.true(areArgumentArraysEqual([Arg.any('string')], ['foo'])); - t.true(areArgumentArraysEqual([Arg.any('number')], [1])); - t.true(areArgumentArraysEqual([Arg.any('boolean')], [true])); - t.true(areArgumentArraysEqual([Arg.any('symbol')], [Symbol()])); - t.true(areArgumentArraysEqual([Arg.any('undefined')], [undefined])); - t.true(areArgumentArraysEqual([Arg.any('object')], [testObject])); - t.true(areArgumentArraysEqual([Arg.any('array')], [testArray])); - t.true(areArgumentArraysEqual([Arg.any('function')], [testFunc])); - t.true(areArgumentArraysEqual([Arg.any('object')], [parent])); - t.true(areArgumentArraysEqual([Arg.any('object')], [root])); - - t.false(areArgumentArraysEqual([Arg.any('string')], [1])); - t.false(areArgumentArraysEqual([Arg.any('number')], ['string'])); - t.false(areArgumentArraysEqual([Arg.any('boolean')], [null])); - t.false(areArgumentArraysEqual([Arg.any('object')], ['foo'])); - t.false(areArgumentArraysEqual([Arg.any('array')], ['bar'])); - t.false(areArgumentArraysEqual([Arg.any('function')], ['foo'])); -}) - -test('areArgumentArraysEqual should return valid result using Arg.is()', t => { - t.true(areArgumentArraysEqual([Arg.is(x => x === 'foo')], ['foo'])); - t.true(areArgumentArraysEqual([Arg.is(x => x % 2 == 0)], [4])); - - t.false(areArgumentArraysEqual([Arg.is(x => x === 'foo')], ['bar'])); - t.false(areArgumentArraysEqual([Arg.is(x => x % 2 == 0)], [3])); -}); \ No newline at end of file + t.pass() +}) \ No newline at end of file diff --git a/spec/didNotReceive.spec.ts b/spec/didNotReceive.spec.ts deleted file mode 100644 index 6333a1f..0000000 --- a/spec/didNotReceive.spec.ts +++ /dev/null @@ -1,52 +0,0 @@ -import test from 'ava'; -import { Substitute, Arg } from '../src/index'; -import { SubstituteException } from '../src/SubstituteBase'; - -interface Calculator { - add(a: number, b: number): number; - subtract(a: number, b: number): number; - divide(a: number, b: number): number; - isEnabled: boolean; -} - -test('not calling a method correctly asserts the call count', t => { - const calculator = Substitute.for(); - - calculator.didNotReceive().add(1, 1); - t.throws(() => calculator.received(1).add(1, 1), { instanceOf: SubstituteException }); - t.throws(() => calculator.received().add(Arg.all()), { instanceOf: SubstituteException }); -}); - -test('not getting a property correctly asserts the call count', t => { - const calculator = Substitute.for(); - - calculator.didNotReceive().isEnabled; - t.throws(() => calculator.received(1).isEnabled, { instanceOf: SubstituteException }); - t.throws(() => calculator.received().isEnabled, { instanceOf: SubstituteException }); -}); - -test('not setting a property correctly asserts the call count', t => { - const calculator = Substitute.for(); - - calculator.didNotReceive().isEnabled = true; - t.throws(() => calculator.received(1).isEnabled = true, { instanceOf: SubstituteException }); - t.throws(() => calculator.received().isEnabled = true, { instanceOf: SubstituteException }); -}); - -test('not calling a method with mock correctly asserts the call count', t => { - const calculator = Substitute.for(); - calculator.add(1, 1).returns(2); - - calculator.didNotReceive().add(1, 1); - t.throws(() => calculator.received(1).add(1, 1), { instanceOf: SubstituteException }); - t.throws(() => calculator.received().add(Arg.all()), { instanceOf: SubstituteException }); -}); - -test('not getting a property with mock correctly asserts the call count', t => { - const calculator = Substitute.for(); - calculator.isEnabled.returns(true); - - calculator.didNotReceive().isEnabled; - t.throws(() => calculator.received(1).isEnabled, { instanceOf: SubstituteException }); - t.throws(() => calculator.received().isEnabled, { instanceOf: SubstituteException }); -}); \ No newline at end of file diff --git a/spec/index.test.ts b/spec/index.test.ts deleted file mode 100644 index dac9eaa..0000000 --- a/spec/index.test.ts +++ /dev/null @@ -1,152 +0,0 @@ -import test from 'ava'; - -import { Substitute, Arg } from '../src'; -import { OmitProxyMethods, ObjectSubstitute } from '../src/Transformations'; - -class Dummy { - -} - -export class Example { - a = "1337"; - - c(arg1: string, arg2: string) { - return "hello " + arg1 + " world (" + arg2 + ")"; - } - - get d() { - return 1337; - } - - set v(x: string | null | undefined) { - } - - received(stuff: number | string) { - - } - - returnPromise() { - return Promise.resolve(new Dummy()); - } - - foo(): string | undefined | null { - return 'stuff'; - } - - bar(a: number, b?: number): number { - return a + b || 0 - } -} - -let instance: Example; -let substitute: ObjectSubstitute, Example>; - -function initialize() { - instance = new Example(); - substitute = Substitute.for(); -}; - -test('class with method called "received" can be used for call count verification when proxies are suspended', t => { - initialize(); - - Substitute.disableFor(substitute).received(2); - - t.throws(() => substitute.received(2).received(2)); - t.notThrows(() => substitute.received(1).received(2)); -}); - -test('class with method called "received" can be used for call count verification', t => { - initialize(); - - Substitute.disableFor(substitute).received('foo'); - - t.notThrows(() => substitute.received(1).received('foo')); - t.throws(() => substitute.received(2).received('foo')); -}); - -test('class string field set received', t => { - initialize(); - - substitute.v = undefined; - substitute.v = null; - substitute.v = 'hello'; - substitute.v = 'hello'; - substitute.v = 'world'; - - t.notThrows(() => substitute.received().v = 'hello'); - t.notThrows(() => substitute.received(5).v = Arg.any()); - t.notThrows(() => substitute.received().v = Arg.any()); - t.notThrows(() => substitute.received(2).v = 'hello'); - t.notThrows(() => substitute.received(2).v = Arg.is(x => x && x.indexOf('ll') > -1)); - - t.throws(() => substitute.received(2).v = Arg.any()); - t.throws(() => substitute.received(1).v = Arg.any()); - t.throws(() => substitute.received(1).v = Arg.is(x => x && x.indexOf('ll') > -1)); - t.throws(() => substitute.received(3).v = 'hello'); -}); - -test('resolving promises works', async t => { - initialize(); - - substitute.returnPromise().resolves(1338); - - t.is(1338, await substitute.returnPromise()); -}); - -test('class void returns', t => { - initialize(); - - substitute.foo().returns(void 0, null); - - t.is(substitute.foo(), void 0); - t.is(substitute.foo(), null); -}); - -test('class method received', t => { - initialize(); - - void substitute.c("hi", "there"); - void substitute.c("hi", "the1re"); - void substitute.c("hi", "there"); - void substitute.c("hi", "there"); - void substitute.c("hi", "there"); - - t.notThrows(() => substitute.received(4).c('hi', 'there')); - t.notThrows(() => substitute.received(1).c('hi', 'the1re')); - t.notThrows(() => substitute.received().c('hi', 'there')); - - const expectedMessage = 'Expected 7 calls to the method c with arguments [\'hi\', \'there\'], but received 4 of such calls.\n' + - 'All calls received to method c:\n' + - '-> call with arguments [\'hi\', \'there\']\n' + - '-> call with arguments [\'hi\', \'the1re\']\n' + - '-> call with arguments [\'hi\', \'there\']\n' + - '-> call with arguments [\'hi\', \'there\']\n' + - '-> call with arguments [\'hi\', \'there\']' - t.throws(() => { substitute.received(7).c('hi', 'there') }, { message: expectedMessage }); -}); - -test('received call matches after partial mocks using property instance mimicks', t => { - initialize(); - - substitute.d.mimicks(() => instance.d); - substitute.c('lala', 'bar'); - - substitute.received(1).c('lala', 'bar'); - substitute.received(1).c('lala', 'bar'); - - t.notThrows(() => substitute.received(1).c('lala', 'bar')); - const expectedMessage = 'Expected 2 calls to the method c with arguments [\'lala\', \'bar\'], but received 1 of such call.\n' + - 'All calls received to method c:\n' + - '-> call with arguments [\'lala\', \'bar\']' - t.throws(() => substitute.received(2).c('lala', 'bar'), { message: expectedMessage }); - - t.deepEqual(substitute.d, 1337); -}); - -test('partial mocks using property instance mimicks', t => { - initialize(); - - substitute.d.mimicks(() => instance.d); - - t.deepEqual(substitute.d, 1337); -}); diff --git a/spec/issues/11.test.ts b/spec/issues/11.test.ts deleted file mode 100644 index eb4d4cd..0000000 --- a/spec/issues/11.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -import test from 'ava'; -import { Substitute, Arg } from '../../src/index'; - -type Addands = { - op1: number; - op2: number; -} - -class RealCalculator { - add(addands: Addands): number { - return addands.op1 + addands.op2; - } -} - -test('issue 11: arg.is is only called once', async t => { - let mockedCalculator = Substitute.for(); - mockedCalculator.add(Arg.any()).returns(4); - - let count = 0; - mockedCalculator.add({ op1: 1, op2: 2 }); - - mockedCalculator.received(1).add(Arg.is(a => { - count++; - return a.op1 === 1 && a.op2 === 2; - })); - - t.is(count, 1); -}); \ No newline at end of file diff --git a/spec/issues/23.test.ts b/spec/issues/23.test.ts deleted file mode 100644 index 838bd62..0000000 --- a/spec/issues/23.test.ts +++ /dev/null @@ -1,25 +0,0 @@ -import test from "ava"; - -import { Substitute, Arg } from "../../src/index"; - -interface CalculatorInterface { - add(a: number, b: number): number; - subtract(a: number, b: number): number; - divide(a: number, b: number): number; - isEnabled: boolean; -} - -test("issue 23: mimick received should not call method", t => { - const mockedCalculator = Substitute.for(); - - let calls = 0 - - mockedCalculator.add(Arg.all()).mimicks((a, b) => { - t.deepEqual(++calls, 1, 'mimick called twice') - return a + b; - }); - - mockedCalculator.add(1, 1); // ok - - mockedCalculator.received(1).add(1, 1) // not ok, calls mimick func -}); diff --git a/spec/issues/45.test.ts b/spec/issues/45.test.ts deleted file mode 100644 index 34a24fa..0000000 --- a/spec/issues/45.test.ts +++ /dev/null @@ -1,36 +0,0 @@ -import test from 'ava'; - -import { Substitute, Arg } from '../../src/index'; - -class DependencyClass { - public methodOne() {} - public methodTwo(someArg: string) {} -} - -class SubjectClass { - private readonly dependency: DependencyClass; - - public constructor(dependency: DependencyClass) { - this.dependency = dependency; - } - - public callToMethodOne() { - this.dependency.methodOne(); - } - public callToMethodTwo() { - this.dependency.methodTwo('string'); - } -} - -test('issue 45 Checking received calls off at times', async t => { - const mock = Substitute.for(); - const subject = new SubjectClass(mock); - - subject.callToMethodOne(); - subject.callToMethodTwo(); - - t.notThrows(() => { - mock.received(1).methodOne(); - mock.received(1).methodTwo(Arg.is(x => x === 'string')); - }); -}); diff --git a/spec/mimicks.spec.ts b/spec/mimicks.spec.ts deleted file mode 100644 index d37bbc5..0000000 --- a/spec/mimicks.spec.ts +++ /dev/null @@ -1,65 +0,0 @@ -import test from 'ava'; -import { Substitute, Arg } from '../src'; - -interface Calculator { - add(a: number, b: number): number; - multiply(a: number, b?: number): number; - clear(): void; - getMemory(): Promise; - viewResult(back?: number): number; - heavyOperation(...input: number[]): Promise; - isEnabled: boolean; - model: Promise; -}; - -test('mimicks a method with specific arguments', t => { - const calculator = Substitute.for(); - const addMimick = (a: number, b: number) => a + b; - - calculator.add(1, 1).mimicks(addMimick); - t.is(calculator.add(1, 1), 2); -}); - -test('mimicks a method with specific and conditional arguments', t => { - const calculator = Substitute.for(); - const addMimick = (a: number, b: number) => a + b; - - calculator.add(Arg.any('number'), Arg.is((input: number) => input >= 0 && input <= 10)).mimicks(addMimick); - calculator.add(42, -42).mimicks((a: number, b: number) => 0); - - t.is(calculator.add(1234, 6), 1240); - t.is(calculator.add(42, -42), 0); -}); - -test('mimicks a method with Arg.all', t => { - const calculator = Substitute.for(); - const addMimick = (a: number, b: number) => a + b; - - - calculator.add(Arg.all()).mimicks(addMimick); - t.is(calculator.add(42, 58), 100); -}); - -test('mimicks a method with optional arguments', t => { - const calculator = Substitute.for(); - const multiplyOneArgMimicks = (a: number) => a * a; - const multiplyMimicks = (a: number, b?: number) => a * b; - - calculator.multiply(0, Arg.is((b: number) => b > 10 && b < 20)).mimicks(multiplyMimicks); - calculator.multiply(Arg.any('number'), Arg.is((b: number) => b === 2)).mimicks(multiplyMimicks); - calculator.multiply(2).mimicks(multiplyOneArgMimicks); - - t.is(calculator.multiply(0, 13), 0); - t.is(calculator.multiply(42, 2), 84); - t.is(calculator.multiply(2), 4); -}); - -test('mimicks a method where it\'s only argument is optional', t => { - const calculator = Substitute.for(); - - calculator.viewResult().mimicks(() => 0); - calculator.viewResult(3).mimicks(() => 42); - - t.is(calculator.viewResult(), 0); - t.is(calculator.viewResult(3), 42); -}); \ No newline at end of file diff --git a/spec/received.spec.ts b/spec/received.spec.ts deleted file mode 100644 index 65f00db..0000000 --- a/spec/received.spec.ts +++ /dev/null @@ -1,139 +0,0 @@ -import test from 'ava'; -import { Substitute, Arg } from '../src'; -import { SubstituteException } from '../src/SubstituteBase'; - -interface Calculator { - add(a: number, b: number): number; - multiply(a: number, b?: number): number; - isEnabled: boolean; -} - -test('calling a method twice correctly asserts the call count', t => { - const calculator = Substitute.for(); - calculator.add(1, 1); - calculator.add(1, 1); - - calculator.received(2).add(1, 1); - calculator.received().add(1, 1); - t.throws(() => calculator.received(0).add(1, 1), { instanceOf: SubstituteException }); - t.throws(() => calculator.received(1).add(1, 1), { instanceOf: SubstituteException }); - t.throws(() => calculator.received(2).add(1, 0), { instanceOf: SubstituteException }); - t.throws(() => calculator.received().add(1, 0), { instanceOf: SubstituteException }); -}); - -test('calling a method twice correctly asserts the call count each time', t => { - const calculator = Substitute.for(); - - calculator.add(1, 1); - calculator.received(1).add(1, 1); - - calculator.add(1, 1); - calculator.received(2).add(1, 1); - - t.throws(() => calculator.received(1).add(1, 1), { instanceOf: SubstituteException }); -}); - -test('calling a method with optional arguments correctly asserts the call count', t => { - const calculator = Substitute.for(); - calculator.multiply(1); - calculator.multiply(1, 1); - calculator.multiply(2, 1); - - calculator.received(1).multiply(1); - calculator.received(1).multiply(1, 1); - calculator.received(0).multiply(2); - calculator.received(1).multiply(2, 1); - - t.throws(() => calculator.received(0).multiply(1), { instanceOf: SubstituteException }); - t.throws(() => calculator.received(0).multiply(1, 1), { instanceOf: SubstituteException }); - t.throws(() => calculator.received(2).multiply(1), { instanceOf: SubstituteException }); - t.throws(() => calculator.received(2).multiply(1, 1), { instanceOf: SubstituteException }); - t.throws(() => calculator.received(1).multiply(2), { instanceOf: SubstituteException }); -}); - -test('getting a property twice correctly asserts the call count', t => { - const calculator = Substitute.for(); - calculator.isEnabled; - calculator.isEnabled; - - calculator.received(2).isEnabled; - calculator.received().isEnabled; - t.throws(() => calculator.received(0).isEnabled, { instanceOf: SubstituteException }); - t.throws(() => calculator.received(1).isEnabled, { instanceOf: SubstituteException }); -}); - -test('setting a property twice correctly asserts the call count', t => { - const calculator = Substitute.for(); - calculator.isEnabled = true; - calculator.isEnabled = true; - - calculator.received(2).isEnabled = true; - calculator.received().isEnabled = true; - t.throws(() => calculator.received(0).isEnabled = true, { instanceOf: SubstituteException }); - t.throws(() => calculator.received(1).isEnabled = true, { instanceOf: SubstituteException }); - t.throws(() => calculator.received(2).isEnabled = false, { instanceOf: SubstituteException }); - t.throws(() => calculator.received().isEnabled = false, { instanceOf: SubstituteException }); -}); - -test('calling a method twice with mock correctly asserts the call count', t => { - const calculator = Substitute.for(); - calculator.add(1, 1).returns(2); - calculator.add(1, 1); - calculator.add(1, 1); - - calculator.received(2).add(1, 1); - calculator.received().add(1, 1); - t.throws(() => calculator.received(0).add(1, 1), { instanceOf: SubstituteException }); - t.throws(() => calculator.received(1).add(1, 1), { instanceOf: SubstituteException }); - t.throws(() => calculator.received(2).add(1, 0), { instanceOf: SubstituteException }); - t.throws(() => calculator.received().add(1, 0), { instanceOf: SubstituteException }); -}); - -test('calling a method with mock based on Arg correctly asserts the call count', t => { - const calculator = Substitute.for(); - calculator.add(Arg.all()).returns(0); - calculator.add(1, 1); - - calculator.received().add(Arg.all()); - calculator.received().add(Arg.any(), Arg.any()); - calculator.received().add(Arg.any('number'), Arg.any('number')); - calculator.received().add(1, 1); - ; - t.throws(() => calculator.received().add(1, 0), { instanceOf: SubstituteException }); -}); - -test('getting a property twice with mock correctly asserts the call count', t => { - const calculator = Substitute.for(); - calculator.isEnabled.returns(true); - calculator.isEnabled; - calculator.isEnabled; - - calculator.received(2).isEnabled; - calculator.received().isEnabled; - t.throws(() => calculator.received(0).isEnabled, { instanceOf: SubstituteException }); - t.throws(() => calculator.received(1).isEnabled, { instanceOf: SubstituteException }); - t.throws(() => calculator.received().isEnabled, { instanceOf: SubstituteException }); -}); - -test('calling a method with Arg correctly asserts the call count with Arg', t => { - // #18: receive with arg https://github.com/ffMathy/FluffySpoon.JavaScript.Testing.Faking/issues/18 - const calculator = Substitute.for(); - calculator.add(Arg.all()); - - calculator.received(1).add(Arg.all()); - calculator.received().add(Arg.all()); - t.throws(() => calculator.received(0).add(1, 1), { instanceOf: SubstituteException }); -}); - -test('calling a method does not interfere with other properties or methods call counts', t => { - // #51: All functions share the same state https://github.com/ffMathy/FluffySpoon.JavaScript.Testing.Faking/issues/51 - const calculator = Substitute.for(); - calculator.add(1, 1); - - calculator.received(0).multiply(1, 1); - calculator.received(0).multiply(Arg.all()); - calculator.received(0).isEnabled; - - t.throws(() => calculator.received().multiply(1, 1), { instanceOf: SubstituteException }); - t.throws(() => calculator.received().multiply(Arg.all()), { instanceOf: SubstituteException }); -}); \ No newline at end of file diff --git a/spec/regression/Arguments.spec.ts b/spec/regression/Arguments.spec.ts new file mode 100644 index 0000000..d471db0 --- /dev/null +++ b/spec/regression/Arguments.spec.ts @@ -0,0 +1,110 @@ +import test from 'ava' +import { Arg } from '../../src' +import { Argument } from '../../src/Arguments' + +const testObject = { "foo": "bar" } +const testArray = ["a", 1, true] + +const parent = {} as any +parent.child = parent +const root = {} as any +root.path = { to: { nested: root } } +const testFunc = () => { } + +test('should match any argument(s) using Arg.all', t => { + t.true(Arg.all().matches([])) + t.true(Arg.all().matches([0])) + t.true(Arg.all().matches([1])) + t.true(Arg.all().matches(['string'])) + t.true(Arg.all().matches([true])) + t.true(Arg.all().matches([false])) + t.true(Arg.all().matches(null)) + t.true(Arg.all().matches(undefined)) + t.true(Arg.all().matches([1, 2])) + t.true(Arg.all().matches(['string1', 'string2'])) +}) + +test('should match any argument using Arg.any', t => { + t.true(Arg.any().matches('hi')) + t.true(Arg.any().matches(1)) + t.true(Arg.any().matches(0)) + t.true(Arg.any().matches(false)) + t.true(Arg.any().matches(true)) + t.true(Arg.any().matches(null)) + t.true(Arg.any().matches(undefined)) + t.true(Arg.any().matches(testObject)) + t.true(Arg.any().matches(testArray)) + t.true(Arg.any().matches(testFunc)) + t.true(Arg.any().matches()) + t.true(Arg.any().matches(parent)) + t.true(Arg.any().matches(root)) + t.true(Arg.any().matches(parent)) + t.true(Arg.any().matches(root)) +}) + +test('should not match any argument using Arg.any.not', t => { + t.false(Arg.any.not().matches('hi')) + t.false(Arg.any.not().matches(1)) + t.false(Arg.any.not().matches(0)) + t.false(Arg.any.not().matches(false)) + t.false(Arg.any.not().matches(true)) + t.false(Arg.any.not().matches(null)) + t.false(Arg.any.not().matches(undefined)) + t.false(Arg.any.not().matches(testObject)) + t.false(Arg.any.not().matches(testArray)) + t.false(Arg.any.not().matches(testFunc)) + t.false(Arg.any.not().matches()) + t.false(Arg.any.not().matches(parent)) + t.false(Arg.any.not().matches(root)) + t.false(Arg.any.not().matches(parent)) + t.false(Arg.any.not().matches(root)) +}) + +test('should match the type of the argument using Arg.any', t => { + t.true(Arg.any('string').matches('foo')) + t.true(Arg.any('number').matches(1)) + t.true(Arg.any('boolean').matches(true)) + t.true(Arg.any('symbol').matches(Symbol())) + t.true((>Arg.any('undefined')).matches(undefined)) + t.true(Arg.any('object').matches(testObject)) + t.true(Arg.any('array').matches(testArray)) + t.true(Arg.any('function').matches(testFunc)) + t.true(Arg.any('object').matches(parent)) + t.true(Arg.any('object').matches(root)) + + t.false((>Arg.any('string')).matches(1)) + t.false((>Arg.any('number')).matches('string')) + t.false(Arg.any('boolean').matches(null)) + t.false((>Arg.any('object')).matches('foo')) + t.false((>Arg.any('array')).matches('bar')) + t.false((>Arg.any('function')).matches('foo')) +}) + +test('should not match the type of the argument using Arg.any.not', t => { + t.false(Arg.any.not('string').matches('123')) + t.false(Arg.any.not('number').matches(123)) + t.false(Arg.any.not('boolean').matches(true)) + t.false(Arg.any.not('symbol').matches(Symbol())) + t.false((>Arg.any.not('undefined')).matches(undefined)) + t.false(Arg.any.not('object').matches(testObject)) + t.false(Arg.any.not('array').matches(testArray)) + t.false(Arg.any.not('function').matches(testFunc)) + t.false(Arg.any.not('object').matches(parent)) + t.false(Arg.any.not('object').matches(root)) +}) + +test('should match the argument with the predicate function using Arg.is', t => { + t.true(Arg.is(x => x === 'foo').matches('foo')) + t.true(Arg.is(x => x % 2 == 0).matches(4)) + + t.false(Arg.is(x => x === 'foo').matches('bar')) + t.false(Arg.is(x => x % 2 == 0).matches(3)) +}) + +test('should not match the argument with the predicate function using Arg.is.not', t => { + t.false(Arg.is.not(x => x === 'foo').matches('foo')) + t.false(Arg.is.not(x => x % 2 == 0).matches(4)) + + t.true(Arg.is.not(x => x === 'foo').matches('bar')) + t.true(Arg.is.not(x => x % 2 == 0).matches(3)) +}) \ No newline at end of file diff --git a/spec/regression/didNotReceive.spec.ts b/spec/regression/didNotReceive.spec.ts new file mode 100644 index 0000000..2b01ecc --- /dev/null +++ b/spec/regression/didNotReceive.spec.ts @@ -0,0 +1,52 @@ +import test from 'ava' +import { Substitute, Arg } from '../../src' +import { SubstituteException } from '../../src/SubstituteException' + +interface Calculator { + add(a: number, b: number): number + subtract(a: number, b: number): number + divide(a: number, b: number): number + isEnabled: boolean +} + +test('not calling a method correctly asserts the call count', t => { + const calculator = Substitute.for() + + calculator.didNotReceive().add(1, 1) + t.throws(() => calculator.received(1).add(1, 1), { instanceOf: SubstituteException }) + t.throws(() => calculator.received().add(Arg.all()), { instanceOf: SubstituteException }) +}) + +test('not getting a property correctly asserts the call count', t => { + const calculator = Substitute.for() + + calculator.didNotReceive().isEnabled + t.throws(() => calculator.received(1).isEnabled, { instanceOf: SubstituteException }) + t.throws(() => calculator.received().isEnabled, { instanceOf: SubstituteException }) +}) + +test('not setting a property correctly asserts the call count', t => { + const calculator = Substitute.for() + + calculator.didNotReceive().isEnabled = true + t.throws(() => calculator.received(1).isEnabled = true, { instanceOf: SubstituteException }) + t.throws(() => calculator.received().isEnabled = true, { instanceOf: SubstituteException }) +}) + +test('not calling a method with mock correctly asserts the call count', t => { + const calculator = Substitute.for() + calculator.add(1, 1).returns(2) + + calculator.didNotReceive().add(1, 1) + t.throws(() => calculator.received(1).add(1, 1), { instanceOf: SubstituteException }) + t.throws(() => calculator.received().add(Arg.all()), { instanceOf: SubstituteException }) +}) + +test('not getting a property with mock correctly asserts the call count', t => { + const calculator = Substitute.for() + calculator.isEnabled.returns(true) + + calculator.didNotReceive().isEnabled + t.throws(() => calculator.received(1).isEnabled, { instanceOf: SubstituteException }) + t.throws(() => calculator.received().isEnabled, { instanceOf: SubstituteException }) +}) \ No newline at end of file diff --git a/spec/regression/index.test.ts b/spec/regression/index.test.ts new file mode 100644 index 0000000..1ea0105 --- /dev/null +++ b/spec/regression/index.test.ts @@ -0,0 +1,155 @@ +import test from 'ava' + +import { Substitute, Arg } from '../../src' +import { OmitProxyMethods, ObjectSubstitute } from '../../src/Transformations' + +class Dummy { + +} + +export class Example { + a = '1337'; + + c(arg1: string, arg2: string) { + return 'hello ' + arg1 + ' world (' + arg2 + ')' + } + + get d() { + return 1337 + } + + set v(x: string | null | undefined) { + } + + received(stuff: number | string) { + + } + + returnPromise() { + return Promise.resolve(new Dummy()) + } + + foo(): string | undefined | null { + return 'stuff' + } + + bar(a: number, b?: number): number { + return a + b || 0 + } +} + +let instance: Example +let substitute: ObjectSubstitute, Example> + +function initialize() { + instance = new Example() + substitute = Substitute.for() +}; + +const textModifierRegex = /\x1b\[\d+m/g + +test('class with method called \'received\' can be used for call count verification when proxies are suspended', t => { + initialize() + + Substitute.disableFor(substitute).received(2) + + t.throws(() => substitute.received(2).received(2)) + t.notThrows(() => substitute.received(1).received(2)) +}) + +test('class with method called \'received\' can be used for call count verification', t => { + initialize() + + Substitute.disableFor(substitute).received('foo') + + t.notThrows(() => substitute.received(1).received('foo')) + t.throws(() => substitute.received(2).received('foo')) +}) + +test('class string field set received', t => { + initialize() + + substitute.v = undefined + substitute.v = null + substitute.v = 'hello' + substitute.v = 'hello' + substitute.v = 'world' + + t.notThrows(() => substitute.received().v = 'hello') + t.notThrows(() => substitute.received(5).v = Arg.any()) + t.notThrows(() => substitute.received().v = Arg.any()) + t.notThrows(() => substitute.received(2).v = 'hello') + t.notThrows(() => substitute.received(2).v = Arg.is(x => x && x.indexOf('ll') > -1)) + + t.throws(() => substitute.received(2).v = Arg.any()) + t.throws(() => substitute.received(1).v = Arg.any()) + t.throws(() => substitute.received(1).v = Arg.is(x => x && x.indexOf('ll') > -1)) + t.throws(() => substitute.received(3).v = 'hello') +}) + +test('resolving promises works', async t => { + initialize() + + substitute.returnPromise().resolves(1338) + + t.is(1338, await substitute.returnPromise()) +}) + +test('class void returns', t => { + initialize() + + substitute.foo().returns(void 0, null) + + t.is(substitute.foo(), void 0) + t.is(substitute.foo(), null) +}) + +test('class method received', t => { + initialize() + + void substitute.c('hi', 'there') + void substitute.c('hi', 'the1re') + void substitute.c('hi', 'there') + void substitute.c('hi', 'there') + void substitute.c('hi', 'there') + + t.notThrows(() => substitute.received(4).c('hi', 'there')) + t.notThrows(() => substitute.received(1).c('hi', 'the1re')) + t.notThrows(() => substitute.received().c('hi', 'there')) + + const expectedMessage = 'Expected 7 calls to the method c with arguments [\'hi\', \'there\'], but received 4 of such calls.\n' + + 'All calls received to method c:\n' + + '-> call with arguments [\'hi\', \'there\']\n' + + '-> call with arguments [\'hi\', \'the1re\']\n' + + '-> call with arguments [\'hi\', \'there\']\n' + + '-> call with arguments [\'hi\', \'there\']\n' + + '-> call with arguments [\'hi\', \'there\']' + const { message } = t.throws(() => { substitute.received(7).c('hi', 'there') }) + t.is(message.replace(textModifierRegex, ''), expectedMessage) +}) + +test('received call matches after partial mocks using property instance mimicks', t => { + initialize() + + substitute.d.mimicks(() => instance.d) + substitute.c('lala', 'bar') + + substitute.received(1).c('lala', 'bar') + substitute.received(1).c('lala', 'bar') + + t.notThrows(() => substitute.received(1).c('lala', 'bar')) + const expectedMessage = 'Expected 2 calls to the method c with arguments [\'lala\', \'bar\'], but received 1 of such calls.\n' + + 'All calls received to method c:\n' + + '-> call with arguments [\'lala\', \'bar\']' + const { message } = t.throws(() => substitute.received(2).c('lala', 'bar')) + t.is(message.replace(textModifierRegex, ''), expectedMessage) + t.deepEqual(substitute.d, 1337) +}) + +test('partial mocks using property instance mimicks', t => { + initialize() + + substitute.d.mimicks(() => instance.d) + + t.deepEqual(substitute.d, 1337) +}) diff --git a/spec/regression/issues/11.test.ts b/spec/regression/issues/11.test.ts new file mode 100644 index 0000000..4bd6d77 --- /dev/null +++ b/spec/regression/issues/11.test.ts @@ -0,0 +1,28 @@ +import test from 'ava' +import { Substitute, Arg } from '../../../src' + +type Addands = { + op1: number + op2: number +} + +class RealCalculator { + add(addands: Addands): number { + return addands.op1 + addands.op2 + } +} + +test('issue 11: arg.is is only called once', async t => { + let mockedCalculator = Substitute.for() + mockedCalculator.add(Arg.any()).returns(4) + + let count = 0 + mockedCalculator.add({ op1: 1, op2: 2 }) + + mockedCalculator.received(1).add(Arg.is(a => { + count++ + return a.op1 === 1 && a.op2 === 2 + })) + + t.is(count, 1) +}) \ No newline at end of file diff --git a/spec/regression/issues/23.test.ts b/spec/regression/issues/23.test.ts new file mode 100644 index 0000000..a26666f --- /dev/null +++ b/spec/regression/issues/23.test.ts @@ -0,0 +1,25 @@ +import test from 'ava' + +import { Substitute, Arg } from '../../../src' + +interface CalculatorInterface { + add(a: number, b: number): number + subtract(a: number, b: number): number + divide(a: number, b: number): number + isEnabled: boolean +} + +test('issue 23: mimick received should not call method', t => { + const mockedCalculator = Substitute.for() + + let calls = 0 + + mockedCalculator.add(Arg.all()).mimicks((a, b) => { + t.deepEqual(++calls, 1, 'mimick called twice') + return a + b + }) + + mockedCalculator.add(1, 1) // ok + + mockedCalculator.received(1).add(1, 1) // not ok, calls mimick func +}) diff --git a/spec/issues/36.test.ts b/spec/regression/issues/36.test.ts similarity index 57% rename from spec/issues/36.test.ts rename to spec/regression/issues/36.test.ts index 36b2216..54449e2 100644 --- a/spec/issues/36.test.ts +++ b/spec/regression/issues/36.test.ts @@ -1,33 +1,33 @@ -import test from 'ava'; +import test from 'ava' -import { Substitute, Arg } from '../../src/index'; +import { Substitute, Arg } from '../../../src' class Key { private constructor(private _value: string) { } static create() { - return new this('123'); + return new this('123') } get value(): string { - return this._value; + return this._value } } class IData { private constructor(private _serverCheck: Date, private _data: number[]) { } static create() { - return new this(new Date(), [1]); + return new this(new Date(), [1]) } set data(newData: number[]) { - this._data = newData; + this._data = newData } get serverCheck(): Date { - return this._serverCheck; + return this._serverCheck } get data(): number[] { - return this._data; + return this._data } } abstract class IFetch { @@ -37,35 +37,35 @@ abstract class IFetch { class Service { constructor(private _database: IFetch) { } public async handle(arg?: Key) { - const updateData = await this.getData(arg); - updateData.data = [100]; - await this._database.storeUpdates(updateData); + const updateData = await this.getData(arg) + updateData.data = [100] + await this._database.storeUpdates(updateData) } private getData(arg?: Key) { - return this._database.getUpdates(arg); + return this._database.getUpdates(arg) } } test('issue 36 - promises returning object with properties', async t => { - const emptyFetch = Substitute.for(); - emptyFetch.getUpdates(Key.create()).returns(Promise.resolve(IData.create())); - const result = await emptyFetch.getUpdates(Key.create()); - t.true(result.serverCheck instanceof Date, 'given date is instanceof Date'); + const emptyFetch = Substitute.for() + emptyFetch.getUpdates(Key.create()).returns(Promise.resolve(IData.create())) + const result = await emptyFetch.getUpdates(Key.create()) + t.true(result.serverCheck instanceof Date, 'given date is instanceof Date') t.deepEqual(result.data, [1], 'arrays are deep equal') -}); +}) test('using objects or classes as arguments should be able to match mock', async t => { - const db = Substitute.for(); - const data = IData.create(); - db.getUpdates(Key.create()).returns(Promise.resolve(data)); - const service = new Service(db); + const db = Substitute.for() + const data = IData.create() + db.getUpdates(Key.create()).returns(Promise.resolve(data)) + const service = new Service(db) - await service.handle(Key.create()); + await service.handle(Key.create()) db.received(1).storeUpdates(Arg.is((arg: IData) => arg.serverCheck instanceof Date && arg instanceof IData && arg.data[0] === 100 - )); - t.pass(); -}); \ No newline at end of file + )) + t.pass() +}) \ No newline at end of file diff --git a/spec/regression/issues/45.test.ts b/spec/regression/issues/45.test.ts new file mode 100644 index 0000000..e77f985 --- /dev/null +++ b/spec/regression/issues/45.test.ts @@ -0,0 +1,36 @@ +import test from 'ava' + +import { Substitute, Arg } from '../../../src' + +class DependencyClass { + public methodOne() { } + public methodTwo(someArg: string) { } +} + +class SubjectClass { + private readonly dependency: DependencyClass + + public constructor(dependency: DependencyClass) { + this.dependency = dependency + } + + public callToMethodOne() { + this.dependency.methodOne() + } + public callToMethodTwo() { + this.dependency.methodTwo('string') + } +} + +test('issue 45 Checking received calls off at times', async t => { + const mock = Substitute.for() + const subject = new SubjectClass(mock) + + subject.callToMethodOne() + subject.callToMethodTwo() + + t.notThrows(() => { + mock.received(1).methodOne() + mock.received(1).methodTwo(Arg.is(x => x === 'string')) + }) +}) diff --git a/spec/issues/59.test.ts b/spec/regression/issues/59.test.ts similarity index 76% rename from spec/issues/59.test.ts rename to spec/regression/issues/59.test.ts index 96edb8e..13ffd81 100644 --- a/spec/issues/59.test.ts +++ b/spec/regression/issues/59.test.ts @@ -1,6 +1,6 @@ -import test from 'ava'; +import test from 'ava' -import { Substitute } from '../../src/index'; +import { Substitute } from '../../../src' interface IEcho { echo(a: string): string @@ -13,6 +13,6 @@ test('issue 59 - Mock function with optional parameters', (t) => { echoer.maybeEcho().returns('baz') t.is(echoer.maybeEcho('foo'), 'bar') - echoer.received().maybeEcho('foo'); + echoer.received().maybeEcho('foo') t.is(echoer.maybeEcho(), 'baz') }) diff --git a/spec/regression/mimicks.spec.ts b/spec/regression/mimicks.spec.ts new file mode 100644 index 0000000..1592e15 --- /dev/null +++ b/spec/regression/mimicks.spec.ts @@ -0,0 +1,65 @@ +import test from 'ava' +import { Substitute, Arg } from '../../src' + +interface Calculator { + add(a: number, b: number): number + multiply(a: number, b?: number): number + clear(): void + getMemory(): Promise + viewResult(back?: number): number + heavyOperation(...input: number[]): Promise + isEnabled: boolean + model: Promise +}; + +test('mimicks a method with specific arguments', t => { + const calculator = Substitute.for() + const addMimick = (a: number, b: number) => a + b + + calculator.add(1, 1).mimicks(addMimick) + t.is(calculator.add(1, 1), 2) +}) + +test('mimicks a method with specific and conditional arguments', t => { + const calculator = Substitute.for() + const addMimick = (a: number, b: number) => a + b + + calculator.add(Arg.any('number'), Arg.is((input: number) => input >= 0 && input <= 10)).mimicks(addMimick) + calculator.add(42, -42).mimicks((a: number, b: number) => 0) + + t.is(calculator.add(1234, 6), 1240) + t.is(calculator.add(42, -42), 0) +}) + +test('mimicks a method with Arg.all', t => { + const calculator = Substitute.for() + const addMimick = (a: number, b: number) => a + b + + + calculator.add(Arg.all()).mimicks(addMimick) + t.is(calculator.add(42, 58), 100) +}) + +test('mimicks a method with optional arguments', t => { + const calculator = Substitute.for() + const multiplyOneArgMimicks = (a: number) => a * a + const multiplyMimicks = (a: number, b?: number) => a * b + + calculator.multiply(0, Arg.is((b: number) => b > 10 && b < 20)).mimicks(multiplyMimicks) + calculator.multiply(Arg.any('number'), Arg.is((b: number) => b === 2)).mimicks(multiplyMimicks) + calculator.multiply(2).mimicks(multiplyOneArgMimicks) + + t.is(calculator.multiply(0, 13), 0) + t.is(calculator.multiply(42, 2), 84) + t.is(calculator.multiply(2), 4) +}) + +test('mimicks a method where it\'s only argument is optional', t => { + const calculator = Substitute.for() + + calculator.viewResult().mimicks(() => 0) + calculator.viewResult(3).mimicks(() => 42) + + t.is(calculator.viewResult(), 0) + t.is(calculator.viewResult(3), 42) +}) \ No newline at end of file diff --git a/spec/regression/received.spec.ts b/spec/regression/received.spec.ts new file mode 100644 index 0000000..3fac2d7 --- /dev/null +++ b/spec/regression/received.spec.ts @@ -0,0 +1,137 @@ +import test from 'ava' +import { Substitute, Arg } from '../../src' +import { SubstituteException } from '../../src/SubstituteException' + +interface Calculator { + add(a: number, b: number): number + multiply(a: number, b?: number): number + isEnabled: boolean +} + +test('calling a method twice correctly asserts the call count', t => { + const calculator = Substitute.for() + calculator.add(1, 1) + calculator.add(1, 1) + + calculator.received(2).add(1, 1) + calculator.received().add(1, 1) + t.throws(() => calculator.received(0).add(1, 1), { instanceOf: SubstituteException }) + t.throws(() => calculator.received(1).add(1, 1), { instanceOf: SubstituteException }) + t.throws(() => calculator.received(2).add(1, 0), { instanceOf: SubstituteException }) + t.throws(() => calculator.received().add(1, 0), { instanceOf: SubstituteException }) +}) + +test('calling a method twice correctly asserts the call count each time', t => { + const calculator = Substitute.for() + + calculator.add(1, 1) + calculator.received(1).add(1, 1) + + calculator.add(1, 1) + calculator.received(2).add(1, 1) + + t.throws(() => calculator.received(1).add(1, 1), { instanceOf: SubstituteException }) +}) + +test('calling a method with optional arguments correctly asserts the call count', t => { + const calculator = Substitute.for() + calculator.multiply(1) + calculator.multiply(1, 1) + calculator.multiply(2, 1) + + calculator.received(1).multiply(1) + calculator.received(1).multiply(1, 1) + calculator.received(0).multiply(2) + calculator.received(1).multiply(2, 1) + + t.throws(() => calculator.received(0).multiply(1), { instanceOf: SubstituteException }) + t.throws(() => calculator.received(0).multiply(1, 1), { instanceOf: SubstituteException }) + t.throws(() => calculator.received(2).multiply(1), { instanceOf: SubstituteException }) + t.throws(() => calculator.received(2).multiply(1, 1), { instanceOf: SubstituteException }) + t.throws(() => calculator.received(1).multiply(2), { instanceOf: SubstituteException }) +}) + +test('getting a property twice correctly asserts the call count', t => { + const calculator = Substitute.for() + calculator.isEnabled + calculator.isEnabled + + calculator.received(2).isEnabled + calculator.received().isEnabled + t.throws(() => calculator.received(0).isEnabled, { instanceOf: SubstituteException }) + t.throws(() => calculator.received(1).isEnabled, { instanceOf: SubstituteException }) +}) + +test('setting a property twice correctly asserts the call count', t => { + const calculator = Substitute.for() + calculator.isEnabled = true + calculator.isEnabled = true + + calculator.received(2).isEnabled = true + calculator.received().isEnabled = true + t.throws(() => calculator.received(0).isEnabled = true, { instanceOf: SubstituteException }) + t.throws(() => calculator.received(1).isEnabled = true, { instanceOf: SubstituteException }) + t.throws(() => calculator.received(2).isEnabled = false, { instanceOf: SubstituteException }) + t.throws(() => calculator.received().isEnabled = false, { instanceOf: SubstituteException }) +}) + +test('calling a method twice with mock correctly asserts the call count', t => { + const calculator = Substitute.for() + calculator.add(1, 1).returns(2) + calculator.add(1, 1) + calculator.add(1, 1) + + calculator.received(2).add(1, 1) + calculator.received().add(1, 1) + t.throws(() => calculator.received(0).add(1, 1), { instanceOf: SubstituteException }) + t.throws(() => calculator.received(1).add(1, 1), { instanceOf: SubstituteException }) + t.throws(() => calculator.received(2).add(1, 0), { instanceOf: SubstituteException }) + t.throws(() => calculator.received().add(1, 0), { instanceOf: SubstituteException }) +}) + +test('calling a method with mock based on Arg correctly asserts the call count', t => { + const calculator = Substitute.for() + calculator.add(Arg.all()).returns(0) + calculator.add(1, 1) + + calculator.received().add(Arg.all()) + calculator.received().add(Arg.any(), Arg.any()) + calculator.received().add(Arg.any('number'), Arg.any('number')) + calculator.received().add(1, 1) + t.throws(() => calculator.received().add(1, 0), { instanceOf: SubstituteException }) +}) + +test('getting a property twice with mock correctly asserts the call count', t => { + const calculator = Substitute.for() + calculator.isEnabled.returns(true) + calculator.isEnabled + calculator.isEnabled + + calculator.received(2).isEnabled + calculator.received().isEnabled + t.throws(() => calculator.received(0).isEnabled, { instanceOf: SubstituteException }) + t.throws(() => calculator.received(1).isEnabled, { instanceOf: SubstituteException }) +}) + +test('calling a method with Arg correctly asserts the call count with Arg', t => { + // #18: receive with arg https://github.com/ffMathy/FluffySpoon.JavaScript.Testing.Faking/issues/18 + const calculator = Substitute.for() + calculator.add(Arg.all()) + + calculator.received(1).add(Arg.all()) + calculator.received().add(Arg.all()) + t.throws(() => calculator.received(0).add(1, 1), { instanceOf: SubstituteException }) +}) + +test('calling a method does not interfere with other properties or methods call counts', t => { + // #51: All functions share the same state https://github.com/ffMathy/FluffySpoon.JavaScript.Testing.Faking/issues/51 + const calculator = Substitute.for() + calculator.add(1, 1) + + calculator.received(0).multiply(1, 1) + calculator.received(0).multiply(Arg.all()) + calculator.received(0).isEnabled + + t.throws(() => calculator.received().multiply(1, 1), { instanceOf: SubstituteException }) + t.throws(() => calculator.received().multiply(Arg.all()), { instanceOf: SubstituteException }) +}) \ No newline at end of file diff --git a/spec/regression/rejects.spec.ts b/spec/regression/rejects.spec.ts new file mode 100644 index 0000000..a92cdbf --- /dev/null +++ b/spec/regression/rejects.spec.ts @@ -0,0 +1,48 @@ +import test from 'ava' + +import { Substitute, Arg } from '../../src' + +interface Calculator { + getMemory(): Promise + heavyOperation(...args: number[]): Promise + model: Promise +} + +test('rejects a method with no arguments', async t => { + const calculator = Substitute.for() + calculator.getMemory().rejects(new Error('No memory')) + + await t.throwsAsync(calculator.getMemory(), { instanceOf: Error, message: 'No memory' }) +}) + +test('rejects a method with arguments', async t => { + const calculator = Substitute.for() + calculator.heavyOperation(0, 1, 1, 2, 4, 5, 8).rejects(new Error('Wrong sequence!')) + + await t.throwsAsync(calculator.heavyOperation(0, 1, 1, 2, 4, 5, 8), { instanceOf: Error, message: 'Wrong sequence!' }) +}) + +test('rejects different values in the specified order on a method', async t => { + const calculator = Substitute.for() + calculator.heavyOperation(Arg.any('number')).rejects(new Error('Wrong!'), new Error('Wrong again!')) + + await t.throwsAsync(calculator.heavyOperation(0), { instanceOf: Error, message: 'Wrong!' }) + await t.throwsAsync(calculator.heavyOperation(0), { instanceOf: Error, message: 'Wrong again!' }) + await t.throwsAsync(calculator.heavyOperation(0), { instanceOf: Error, message: 'Wrong again!' }) +}) + +test('rejects a property', async t => { + const calculator = Substitute.for() + calculator.model.rejects(new Error('No model')) + + await t.throwsAsync(calculator.model, { instanceOf: Error, message: 'No model' }) +}) + +test('rejects different values in the specified order on a property', async t => { + const calculator = Substitute.for() + calculator.model.rejects(new Error('No model'), new Error('I said "no model"')) + + await t.throwsAsync(calculator.model, { instanceOf: Error, message: 'No model' }) + await t.throwsAsync(calculator.model, { instanceOf: Error, message: 'I said "no model"' }) + await t.throwsAsync(calculator.model, { instanceOf: Error, message: 'I said "no model"' }) +}) diff --git a/spec/regression/resolves.spec.ts b/spec/regression/resolves.spec.ts new file mode 100644 index 0000000..6916d1b --- /dev/null +++ b/spec/regression/resolves.spec.ts @@ -0,0 +1,49 @@ +import test from 'ava' + +import { Substitute, Arg } from '../../src' + +interface Calculator { + getMemory(): Promise + heavyOperation(...args: number[]): Promise + model: Promise +} + +test('resolves a method with no arguments', async t => { + const calculator = Substitute.for() + calculator.getMemory().resolves(0) + + t.is(await calculator.getMemory(), 0) +}) + +test('resolves a method with arguments', async t => { + const calculator = Substitute.for() + calculator.heavyOperation(0, 1, 1, 2, 3, 5, 8).resolves(13) + + t.is(await calculator.heavyOperation(0, 1, 1, 2, 3, 5, 8), 13) +}) + +test('resolves different values in the specified order on a method', async t => { + const calculator = Substitute.for() + calculator.heavyOperation(Arg.any('number')).resolves(1, 2, 3) + + t.is(await calculator.heavyOperation(0), 1) + t.is(await calculator.heavyOperation(0), 2) + t.is(await calculator.heavyOperation(0), 3) + t.is(await calculator.heavyOperation(0), 3) // https://github.com/nsubstitute/NSubstitute/blob/master/tests/NSubstitute.Acceptance.Specs/ReturningResults.cs#L37-L42 +}) + +test('resolves a property', async t => { + const calculator = Substitute.for() + calculator.model.resolves('Casio FX-82') + + t.is(await calculator.model, 'Casio FX-82') +}) + +test('resolves different values in the specified order on a property', async t => { + const calculator = Substitute.for() + calculator.model.resolves('Casio FX-82', 'TI-84 Plus') + + t.is(await calculator.model, 'Casio FX-82') + t.is(await calculator.model, 'TI-84 Plus') + t.is(await calculator.model, 'TI-84 Plus') +}) diff --git a/spec/regression/returns.spec.ts b/spec/regression/returns.spec.ts new file mode 100644 index 0000000..ef6cdbb --- /dev/null +++ b/spec/regression/returns.spec.ts @@ -0,0 +1,184 @@ +import test from 'ava' +import { types } from 'util' + +import { Substitute, Arg } from '../../src' + +interface Calculator { + add(a: number, b: number): number + multiply(a: number, b?: number): number + clear(): void + getMemory(): Promise + viewResult(back?: number): number + heavyOperation(...input: number[]): Promise + isEnabled: boolean + model: Promise +}; + +test('returns a primitive value for method with no arguments', t => { + const calculator = Substitute.for() + calculator.clear().returns() + + t.is(calculator.clear(), void 0) +}) + +test('returns a primitive value for method with specific arguments', t => { + const calculator = Substitute.for() + const noResult = calculator.add(1, 1) + + calculator.add(1, 1).returns(2) + + t.is(calculator.add(1, 1), 2) + t.is(calculator.add(1, 1), 2) + t.true(types.isProxy(noResult)) +}) + +test('returns a primitive value for method with specific arguments where the last argument is optional', t => { + const calculator = Substitute.for() + + calculator.multiply(2).returns(4) + calculator.multiply(0, Arg.any('number')).returns(0) + calculator.multiply(1, Arg.any()).returns(10) + calculator.multiply(1).returns(1) + + t.is(calculator.multiply(2), 4) + t.is(calculator.multiply(0, 10), 0) + t.is(calculator.multiply(1), 1) + t.is(calculator.multiply(1, 10), 10) + + const noResult = calculator.multiply(2, 2) + const noResult2 = calculator.multiply(0) + + t.true(types.isProxy(noResult)) + t.true(types.isProxy(noResult2)) +}) + +test('returns a primitive value for method with specific and conditional arguments', t => { + const calculator = Substitute.for() + calculator.add(0, 0).returns(0) + calculator.add(1, Arg.is((input: number) => input === 1)).returns(2) + calculator.add(2, Arg.any('number')).returns(10) + calculator.add(Arg.is((input: number) => input > 2), Arg.any('number')).returns(42) + + const results = [calculator.add(0, 0), calculator.add(1, 1), calculator.add(2, 100), calculator.add(42, 84)] + + t.deepEqual(results, [0, 2, 10, 42]) +}) + +test('returns a primitive value for method with Arg.all', t => { + // #25: call verification does not work when using Arg.all() to set up return values https://github.com/ffMathy/FluffySpoon.JavaScript.Testing.Faking/issues/25 + const calculator = Substitute.for() + calculator.add(Arg.all()).returns(42) + + const results = [calculator.add(0, 0), calculator.add(1, 1), calculator.add(2, 100)] + + t.deepEqual(results, [42, 42, 42]) +}) + +test('returns a primitive value for method with one optional argument', t => { + // #24: Mocked method arguments not allowed when verifying method was called https://github.com/ffMathy/FluffySpoon.JavaScript.Testing.Faking/issues/24 + const calculator = Substitute.for() + calculator.viewResult().returns(0) + calculator.viewResult(3).returns(123) + + t.is(calculator.viewResult(), 0) + t.is(calculator.viewResult(3), 123) +}) + +test('returns a promise for method with no arguments', async t => { + const calculator = Substitute.for() + calculator.getMemory().returns(Promise.resolve(42)) + + t.is(await calculator.getMemory(), 42) +}) + +test('returns a promise for method with specific arguments', async t => { + const calculator = Substitute.for() + calculator.heavyOperation(1, 1).returns(Promise.resolve(true)) + + const result = await calculator.heavyOperation(1, 1) + const noResult = calculator.heavyOperation(1, 1, 1) + + t.true(result) + t.true(types.isProxy(noResult)) +}) + +test('returns a promise for method with specific and conditional arguments', async t => { + const calculator = Substitute.for() + calculator.heavyOperation(0).returns(Promise.resolve(true)) + calculator.heavyOperation(1, Arg.is((input: number) => input === 1)).returns(Promise.resolve(false)) + calculator.heavyOperation(2, Arg.any('number'), 100).returns(Promise.resolve(true)) + + const results = await Promise.all([calculator.heavyOperation(0), calculator.heavyOperation(1, 1), calculator.heavyOperation(2, 4321, 100)]) + + t.deepEqual(results, [true, false, true]) +}) + +test('returns a promise for method with Arg.all', async t => { + const calculator = Substitute.for() + calculator.heavyOperation(Arg.all()).returns(Promise.resolve(true)) + + const results = await Promise.all([calculator.heavyOperation(0), calculator.heavyOperation(4321, 11, 42, 1234), calculator.heavyOperation(-1, 444)]) + + t.deepEqual(results, [true, true, true]) +}) + +test('returns different primitive values in the specified order for method with arguments', t => { + const calculator = Substitute.for() + calculator.add(1, Arg.any()).returns(1, NaN) + + t.is(calculator.add(1, 1), 1) + t.is(calculator.add(1, 0), NaN) + t.is(calculator.add(1, 1), NaN) + t.is(calculator.add(1, 5), NaN) +}) + +test('returns another substituted instance for method with arguments', t => { + const calculator = Substitute.for() + const addResult = Substitute.for() + addResult.toLocaleString().returns('What a weird number') + calculator.add(1, Arg.any()).returns(addResult) + + const result = calculator.add(1, 1) + + t.is(result, addResult) + t.is(result.toLocaleString(), 'What a weird number') +}) + +test('returns a primitive value on a property', t => { + // #15: can call properties twice https://github.com/ffMathy/FluffySpoon.JavaScript.Testing.Faking/issues/15 + const calculator = Substitute.for() + const noResult = calculator.isEnabled + + calculator.isEnabled.returns(true) + + t.true(calculator.isEnabled) + t.true(calculator.isEnabled) + t.true(types.isProxy(noResult)) +}) + +test('returns a promise on a property', async t => { + const calculator = Substitute.for() + calculator.model.returns(Promise.resolve('Casio FX-82')) + + t.is(await calculator.model, 'Casio FX-82') +}) + +test('returns different primitive values in the specified order on a property', t => { + const calculator = Substitute.for() + calculator.isEnabled.returns(false, true) + + t.is(calculator.isEnabled, false) + t.is(calculator.isEnabled, true) + t.is(calculator.isEnabled, true) +}) + +test('returns another substituted instance on a property', async t => { + const calculator = Substitute.for() + const modelResult = Substitute.for() + modelResult.replace(Arg.all()).returns('TI-83') + calculator.model.returns(Promise.resolve(modelResult)) + + const result = await calculator.model + t.is(result, modelResult) + t.is(result.replace('...', '---'), 'TI-83') +}) \ No newline at end of file diff --git a/spec/throws.spec.ts b/spec/regression/throws.spec.ts similarity index 97% rename from spec/throws.spec.ts rename to spec/regression/throws.spec.ts index d754bb9..80d3c21 100644 --- a/spec/throws.spec.ts +++ b/spec/regression/throws.spec.ts @@ -1,6 +1,6 @@ import test from 'ava' -import { Substitute, Arg } from '../src' +import { Substitute, Arg } from '../../src' interface Calculator { add(a: number, b: number): number diff --git a/spec/rejects.spec.ts b/spec/rejects.spec.ts deleted file mode 100644 index 8aa1db2..0000000 --- a/spec/rejects.spec.ts +++ /dev/null @@ -1,52 +0,0 @@ -import test from 'ava'; - -import { Substitute, Arg } from '../src'; - -interface Calculator { - getMemory(): Promise; - heavyOperation(...args: number[]): Promise; - model: Promise; -} - -test('rejects a method with no arguments', async t => { - const calculator = Substitute.for(); - calculator.getMemory().rejects(new Error('No memory')); - - await t.throwsAsync(calculator.getMemory(), { instanceOf: Error, message: 'No memory' }); -}); - -test('rejects a method with arguments', async t => { - const calculator = Substitute.for(); - calculator.heavyOperation(0, 1, 1, 2, 4, 5, 8).rejects(new Error('Wrong sequence!')); - - await t.throwsAsync(calculator.heavyOperation(0, 1, 1, 2, 4, 5, 8), { instanceOf: Error, message: 'Wrong sequence!' }); -}); - -test('rejects different values in the specified order on a method', async t => { - const calculator = Substitute.for(); - calculator.heavyOperation(Arg.any('number')).rejects(new Error('Wrong!'), new Error('Wrong again!')); - - await t.throwsAsync(calculator.heavyOperation(0), { instanceOf: Error, message: 'Wrong!' }); - await t.throwsAsync(calculator.heavyOperation(0), { instanceOf: Error, message: 'Wrong again!' }); - await calculator.heavyOperation(0) - .then(() => t.fail('Promise.catch should have been executed')) - .catch(error => t.is(error, void 0)); -}); - -test('rejects a property', async t => { - const calculator = Substitute.for(); - calculator.model.rejects(new Error('No model')); - - await t.throwsAsync(calculator.model, { instanceOf: Error, message: 'No model' }); -}); - -test('rejects different values in the specified order on a property', async t => { - const calculator = Substitute.for(); - calculator.model.rejects(new Error('No model'), new Error('I said "no model"')); - - await t.throwsAsync(calculator.model, { instanceOf: Error, message: 'No model' }); - await t.throwsAsync(calculator.model, { instanceOf: Error, message: 'I said "no model"' }); - await calculator.model - .then(() => t.fail('Promise.catch should have been executed')) - .catch(error => t.is(error, void 0)); -}); diff --git a/spec/resolves.spec.ts b/spec/resolves.spec.ts deleted file mode 100644 index aaf5bb7..0000000 --- a/spec/resolves.spec.ts +++ /dev/null @@ -1,49 +0,0 @@ -import test from 'ava'; - -import { Substitute, Arg } from '../src'; - -interface Calculator { - getMemory(): Promise; - heavyOperation(...args: number[]): Promise; - model: Promise; -} - -test('resolves a method with no arguments', async t => { - const calculator = Substitute.for(); - calculator.getMemory().resolves(0); - - t.is(await calculator.getMemory(), 0); -}); - -test('resolves a method with arguments', async t => { - const calculator = Substitute.for(); - calculator.heavyOperation(0, 1, 1, 2, 3, 5, 8).resolves(13); - - t.is(await calculator.heavyOperation(0, 1, 1, 2, 3, 5, 8), 13); -}); - -test('resolves different values in the specified order on a method', async t => { - const calculator = Substitute.for(); - calculator.heavyOperation(Arg.any('number')).resolves(1, 2, 3); - - t.is(await calculator.heavyOperation(0), 1); - t.is(await calculator.heavyOperation(0), 2); - t.is(await calculator.heavyOperation(0), 3); - t.is(await calculator.heavyOperation(0), void 0); -}); - -test('resolves a property', async t => { - const calculator = Substitute.for(); - calculator.model.resolves('Casio FX-82'); - - t.is(await calculator.model, 'Casio FX-82'); -}); - -test('resolves different values in the specified order on a property', async t => { - const calculator = Substitute.for(); - calculator.model.resolves('Casio FX-82', 'TI-84 Plus'); - - t.is(await calculator.model, 'Casio FX-82'); - t.is(await calculator.model, 'TI-84 Plus'); - t.is(await calculator.model, void 0); -}); diff --git a/spec/returns.spec.ts b/spec/returns.spec.ts deleted file mode 100644 index 0cce01e..0000000 --- a/spec/returns.spec.ts +++ /dev/null @@ -1,186 +0,0 @@ -import test from 'ava'; -import { inspect } from 'util' - -import { Substitute, Arg } from '../src'; -import { getCorrectConstructorDescriptor } from './util/compatibility'; - -interface Calculator { - add(a: number, b: number): number; - multiply(a: number, b?: number): number; - clear(): void; - getMemory(): Promise; - viewResult(back?: number): number; - heavyOperation(...input: number[]): Promise; - isEnabled: boolean; - model: Promise; -}; - -test('returns a primitive value for method with no arguments', t => { - const calculator = Substitute.for(); - calculator.clear().returns(); - - t.is(calculator.clear(), void 0); -}); - -test('returns a primitive value for method with specific arguments', t => { - const calculator = Substitute.for(); - const noResult = calculator.add(1, 1); - - calculator.add(1, 1).returns(2); - - t.is(calculator.add(1, 1), 2); - t.is(calculator.add(1, 1), 2); - t.is(inspect(noResult.constructor), `[${getCorrectConstructorDescriptor()} SubstituteJS]`); -}); - -test('returns a primitive value for method with specific arguments where the last argument is optional', t => { - const calculator = Substitute.for(); - - calculator.multiply(2).returns(4); - calculator.multiply(0, Arg.any('number')).returns(0); - calculator.multiply(1, Arg.any()).returns(10); - - t.is(calculator.multiply(2), 4); - t.is(calculator.multiply(0, 10), 0); - t.is(calculator.multiply(1), 10); - t.is(calculator.multiply(1, 10), 10); - - const noResult = calculator.multiply(2, 2); - const noResult2 = calculator.multiply(0); - - t.is(inspect(noResult.constructor), `[${getCorrectConstructorDescriptor()} SubstituteJS]`); - t.is(inspect(noResult2.constructor), `[${getCorrectConstructorDescriptor()} SubstituteJS]`); -}); - -test('returns a primitive value for method with specific and conditional arguments', t => { - const calculator = Substitute.for(); - calculator.add(0, 0).returns(0); - calculator.add(1, Arg.is((input: number) => input === 1)).returns(2); - calculator.add(2, Arg.any('number')).returns(10); - calculator.add(Arg.is((input: number) => input > 2), Arg.any('number')).returns(42); - - const results = [calculator.add(0, 0), calculator.add(1, 1), calculator.add(2, 100), calculator.add(42, 84)]; - - t.deepEqual(results, [0, 2, 10, 42]); -}); - -test('returns a primitive value for method with Arg.all', t => { - // #25: call verification does not work when using Arg.all() to set up return values https://github.com/ffMathy/FluffySpoon.JavaScript.Testing.Faking/issues/25 - const calculator = Substitute.for(); - calculator.add(Arg.all()).returns(42); - - const results = [calculator.add(0, 0), calculator.add(1, 1), calculator.add(2, 100)]; - - t.deepEqual(results, [42, 42, 42]); -}); - -test('returns a primitive value for method with one optional argument', t => { - // #24: Mocked method arguments not allowed when verifying method was called https://github.com/ffMathy/FluffySpoon.JavaScript.Testing.Faking/issues/24 - const calculator = Substitute.for(); - calculator.viewResult().returns(0); - calculator.viewResult(3).returns(123); - - t.is(calculator.viewResult(), 0); - t.is(calculator.viewResult(3), 123); -}); - -test('returns a promise for method with no arguments', async t => { - const calculator = Substitute.for(); - calculator.getMemory().returns(Promise.resolve(42)) - - t.is(await calculator.getMemory(), 42); -}); - -test('returns a promise for method with specific arguments', async t => { - const calculator = Substitute.for(); - calculator.heavyOperation(1, 1).returns(Promise.resolve(true)); - - const result = await calculator.heavyOperation(1, 1); - const noResult = calculator.heavyOperation(1, 1, 1); - - t.is(result, true); - t.is(inspect(noResult.constructor), `[${getCorrectConstructorDescriptor()} SubstituteJS]`); -}); - -test('returns a promise for method with specific and conditional arguments', async t => { - const calculator = Substitute.for(); - calculator.heavyOperation(0).returns(Promise.resolve(true)); - calculator.heavyOperation(1, Arg.is((input: number) => input === 1)).returns(Promise.resolve(false)); - calculator.heavyOperation(2, Arg.any('number'), 100).returns(Promise.resolve(true)); - - const results = await Promise.all([calculator.heavyOperation(0), calculator.heavyOperation(1, 1), calculator.heavyOperation(2, 4321, 100)]); - - t.deepEqual(results, [true, false, true]); -}); - -test('returns a promise for method with Arg.all', async t => { - const calculator = Substitute.for(); - calculator.heavyOperation(Arg.all()).returns(Promise.resolve(true)); - - const results = await Promise.all([calculator.heavyOperation(0), calculator.heavyOperation(4321, 11, 42, 1234), calculator.heavyOperation(-1, 444)]); - - t.deepEqual(results, [true, true, true]); -}); - -test('returns different primitive values in the specified order for method with arguments', t => { - const calculator = Substitute.for(); - calculator.add(1, Arg.any()).returns(1, NaN); - - t.is(calculator.add(1, 1), 1); - t.is(calculator.add(1, 0), NaN); - t.is(calculator.add(1, 1), void 0); - t.is(calculator.add(1, 5), void 0); -}); - -test('returns another substituted instance for method with arguments', t => { - const calculator = Substitute.for(); - const addResult = Substitute.for(); - addResult.toLocaleString().returns('What a weird number'); - calculator.add(1, Arg.any()).returns(addResult); - - const result = calculator.add(1, 1); - - t.is(result, addResult); - t.is(result.toLocaleString(), 'What a weird number'); -}); - -test('returns a primitive value on a property', t => { - // #15: can call properties twice https://github.com/ffMathy/FluffySpoon.JavaScript.Testing.Faking/issues/15 - const calculator = Substitute.for(); - const noResult = calculator.isEnabled; - - calculator.isEnabled.returns(true); - - t.is(calculator.isEnabled, true); - t.is(calculator.isEnabled, true); - t.is(inspect(noResult.constructor), `[${getCorrectConstructorDescriptor()} SubstituteJS]`); -}); - -test('returns a promise on a property', async t => { - const calculator = Substitute.for(); - calculator.model.returns(Promise.resolve('Casio FX-82')); - - t.is(await calculator.model, 'Casio FX-82'); -}); - -test('returns different primitive values in the specified order on a property', t => { - const calculator = Substitute.for(); - calculator.isEnabled.returns(false, true); - - t.is(calculator.isEnabled, false); - t.is(calculator.isEnabled, true); - t.is(calculator.isEnabled, void 0); - t.is(calculator.isEnabled, void 0); -}); - -test('returns another substituted instance on a property', async t => { - const calculator = Substitute.for(); - const modelResult = Substitute.for(); - modelResult.replace(Arg.all()).returns('TI-83'); - calculator.model.returns(Promise.resolve(modelResult)); - - const result = await calculator.model; - - t.is(result, modelResult); - t.is(result.replace('...', '---'), 'TI-83'); -}); \ No newline at end of file diff --git a/spec/util/compatibility.ts b/spec/util/compatibility.ts deleted file mode 100644 index ee10811..0000000 --- a/spec/util/compatibility.ts +++ /dev/null @@ -1,6 +0,0 @@ -export const getCorrectConstructorDescriptor = () => { - const nodeVersionLowerThan12 = Number(process.versions.node.split('.')[0]) < 12; - return nodeVersionLowerThan12 ? - 'Function:' : - 'class'; -}; \ No newline at end of file diff --git a/src/Arguments.ts b/src/Arguments.ts index 5d03c33..5b60c02 100644 --- a/src/Arguments.ts +++ b/src/Arguments.ts @@ -1,105 +1,98 @@ type PredicateFunction = (arg: T) => boolean type ArgumentOptions = { - inverseMatch?: boolean + inverseMatch?: boolean } class BaseArgument { - constructor( - private _description: string, - private _matchingFunction: PredicateFunction, - private _options?: ArgumentOptions - ) { } - - matches(arg: T) { - const inverseMatch = this._options?.inverseMatch ?? false - return inverseMatch ? !this._matchingFunction(arg) : this._matchingFunction(arg); - } - - toString() { - return this._description; - } - - [Symbol.for('nodejs.util.inspect.custom')]() { - return this._description; - } + constructor( + private _description: string, + private _matchingFunction: PredicateFunction, + private _options?: ArgumentOptions + ) { } + + matches(arg: T) { + const inverseMatch = this._options?.inverseMatch ?? false + return inverseMatch ? !this._matchingFunction(arg) : this._matchingFunction(arg) + } + + toString() { + return this._description + } + + [Symbol.for('nodejs.util.inspect.custom')]() { + return this._description + } } export class Argument extends BaseArgument { - private readonly _type = 'SingleArgument'; - constructor(description: string, matchingFunction: PredicateFunction, options?: ArgumentOptions) { - super(description, matchingFunction, options); - } - get type(): 'SingleArgument' { - return this._type; - } + private readonly _type = 'SingleArgument'; + get type(): 'SingleArgument' { + return this._type + } } export class AllArguments extends BaseArgument { - private readonly _type = 'AllArguments'; - constructor() { - super('{all}', () => true, {}); - } - get type(): 'AllArguments' { - return this._type; - } + private readonly _type = 'AllArguments'; + constructor() { + super('{all}', () => true, {}) + } + get type(): 'AllArguments' { + return this._type // TODO: Needed? + } } export namespace Arg { - type ExtractFirstArg = T extends AllArguments ? TArgs[0] : T - type ReturnArg = Argument & T; - type Inversable = T & { not: T } - const factory = (factoryF: Function) => (...args: any[]): T => factoryF(...args) - const toStringify = (obj: any) => { - if (typeof obj.inspect === 'function') - return obj.inspect(); - - if (typeof obj.toString === 'function') - return obj.toString(); - - return obj; + type Inversable = T & { not: T } + type ExtractFirstArg = T extends AllArguments ? TArgs[0] : T + type ReturnArg = Argument & T + const createInversable = (target: (arg: TArg, opt?: ArgumentOptions) => TReturn): Inversable<(arg: TArg) => TReturn> => { + const inversable = (arg: TArg) => target(arg) + inversable.not = (arg: TArg) => target(arg, { inverseMatch: true }) + return inversable + } + + const toStringify = (obj: any) => { + if (typeof obj.inspect === 'function') return obj.inspect() + if (typeof obj.toString === 'function') return obj.toString() + return obj + } + + export const all = (): AllArguments => new AllArguments() + + type Is = (predicate: PredicateFunction>) => ReturnArg> + const isFunction = (predicate: PredicateFunction>, options?: ArgumentOptions) => new Argument( + `{predicate ${toStringify(predicate)}}`, predicate, options + ) + export const is = createInversable(isFunction) as Inversable + + type MapAnyReturn = T extends 'any' ? + ReturnArg : T extends 'string' ? + ReturnArg : T extends 'number' ? + ReturnArg : T extends 'boolean' ? + ReturnArg : T extends 'symbol' ? + ReturnArg : T extends 'undefined' ? + ReturnArg : T extends 'object' ? + ReturnArg : T extends 'function' ? + ReturnArg : T extends 'array' ? + ReturnArg : any + + type AnyType = 'string' | 'number' | 'boolean' | 'symbol' | 'undefined' | 'object' | 'function' | 'array' | 'any' + type Any = (type?: T) => MapAnyReturn + + const anyFunction = (type: AnyType = 'any', options?: ArgumentOptions) => { + const description = `{type ${type}}` + const predicate = (x: any) => { + switch (type) { + case 'any': + return true + case 'array': + return Array.isArray(x) + default: + return typeof x === type + } } - export const all = (): AllArguments => new AllArguments(); - - type Is = (predicate: PredicateFunction>) => ReturnArg> - const isFunction = >(predicate: T, options?: ArgumentOptions) => new Argument( - `{predicate ${toStringify(predicate)}}`, predicate, options - ); - - const isArgFunction: Inversable = (predicate) => factory(isFunction)(predicate); - isArgFunction.not = (predicate) => factory(isFunction)(predicate, { inverseMatch: true }); - export const is = isArgFunction - - type MapAnyReturn = T extends 'any' ? - ReturnArg : T extends 'string' ? - ReturnArg : T extends 'number' ? - ReturnArg : T extends 'boolean' ? - ReturnArg : T extends 'symbol' ? - ReturnArg : T extends 'undefined' ? - ReturnArg : T extends 'object' ? - ReturnArg : T extends 'function' ? - ReturnArg : T extends 'array' ? - ReturnArg : any; - - type AnyType = 'string' | 'number' | 'boolean' | 'symbol' | 'undefined' | 'object' | 'function' | 'array' | 'any'; - type Any = (type?: T) => MapAnyReturn; - - const anyFunction = (type: AnyType = 'any', options?: ArgumentOptions) => { - const description = !type ? '{any arg}' : `{type ${type}}`; - const predicate = (x: any) => { - switch (type) { - case 'any': - return true; - case 'array': - return Array.isArray(x); - default: - return typeof x === type; - } - } - - return new Argument(description, predicate, options); - } + return new Argument(description, predicate, options) + } - const anyArgFunction: Inversable = (type) => factory(anyFunction)(type); - anyArgFunction.not = (type) => factory(anyFunction)(type, { inverseMatch: true }); - export const any = anyArgFunction; + export const any = createInversable(anyFunction) as Inversable } \ No newline at end of file diff --git a/src/Context.ts b/src/Context.ts deleted file mode 100644 index 9c3d415..0000000 --- a/src/Context.ts +++ /dev/null @@ -1,128 +0,0 @@ -import { inspect } from 'util' -import { ContextState } from './states/ContextState'; -import { InitialState } from './states/InitialState'; -import { HandlerKey } from './Substitute'; -import { PropertyType } from './Utilities'; -import { SetPropertyState } from './states/SetPropertyState'; -import { SubstituteJS as SubstituteBase, SubstituteException } from './SubstituteBase' - -export class Context { - private _initialState: InitialState; - - private _proxy: any; - private _rootProxy: any; - private _receivedProxy: any; - - private _getState: ContextState; - private _setState: ContextState; - private _receivedState: ContextState; - - constructor() { - this._initialState = new InitialState(); - this._setState = this._initialState; - this._getState = this._initialState; - - this._proxy = new Proxy(SubstituteBase, { - apply: (_target, _this, args) => this.getStateApply(_target, _this, args), - set: (_target, property, value) => (this.setStateSet(_target, property, value), true), - get: (_target, property) => this._filterAndReturnProperty(_target, property, this.getStateGet) - }); - - this._rootProxy = new Proxy(SubstituteBase, { - apply: (_target, _this, args) => this.initialState.apply(this, args), - set: (_target, property, value) => (this.initialState.set(this, property, value), true), - get: (_target, property) => this._filterAndReturnProperty(_target, property, this.rootGet) - }); - - this._receivedProxy = new Proxy(SubstituteBase, { - apply: (_target, _this, args) => this._receivedState === void 0 ? void 0 : this._receivedState.apply(this, args), - set: (_target, property, value) => (this.setStateSet(_target, property, value), true), - get: (_target, property) => { - const state = this.initialState.getPropertyStates.find(getPropertyState => getPropertyState.property === property); - if (state === void 0) return this.handleNotFoundState(property); - if (!state.isFunctionState) - state.get(this, property); - this._receivedState = state; - return this.receivedProxy; - } - }); - } - - private _filterAndReturnProperty(target: typeof SubstituteBase, property: PropertyKey, getToExecute: ContextState['get']) { - switch (property) { - case 'constructor': - case 'valueOf': - case '$$typeof': - case 'length': - case 'toString': - case 'inspect': - case 'lastRegisteredSubstituteJSMethodOrProperty': - return target.prototype[property]; - case Symbol.toPrimitive: - return target.prototype[Symbol.toPrimitive]; - case inspect.custom: - return target.prototype[inspect.custom]; - case Symbol.iterator: - return target.prototype[Symbol.iterator]; - case Symbol.toStringTag: - return target.prototype[Symbol.toStringTag]; - default: - target.prototype.lastRegisteredSubstituteJSMethodOrProperty = property.toString() - return getToExecute.bind(this)(target as any, property); - } - } - - private handleNotFoundState(property: PropertyKey) { - if (this.initialState.hasExpectations && this.initialState.expectedCount !== null) { - this.initialState.assertCallCountMatchesExpectations([], 0, PropertyType.property, property, []); - return this.receivedProxy; - } - throw SubstituteException.forPropertyNotMocked(property); - } - - rootGet(_target: any, property: PropertyKey) { - return this.initialState.get(this, property); - } - - getStateApply(_target: any, _this: any, args: any[]) { - return this._getState.apply(this, args); - } - - setStateSet(_target: any, property: PropertyKey, value: any) { - return this._setState.set(this, property, value); - } - - getStateGet(_target: any, property: PropertyKey) { - if (property === HandlerKey) { - return this; - } - - return this._getState.get(this, property); - } - - public get proxy() { - return this._proxy; - } - - public get rootProxy() { - return this._rootProxy; - } - - public get receivedProxy() { - return this._receivedProxy; - } - - public get initialState() { - return this._initialState; - } - - public set state(state: ContextState) { - if (this._setState === state) - return; - - state instanceof SetPropertyState ? - this._setState = state : this._getState = state - if (state.onSwitchedTo) - state.onSwitchedTo(this); - } -} \ No newline at end of file diff --git a/src/RecordedArguments.ts b/src/RecordedArguments.ts new file mode 100644 index 0000000..b778f62 --- /dev/null +++ b/src/RecordedArguments.ts @@ -0,0 +1,93 @@ +import { inspect, InspectOptions, isDeepStrictEqual } from 'util' +import { Argument, AllArguments } from './Arguments' + +type ArgumentsClass = 'plain' | 'with-predicate' | 'wildcard' +export class RecordedArguments { + private _argumentsClass: ArgumentsClass + private _value?: any[] + private readonly _hasNoArguments: boolean = false + + private constructor(rawArguments: any[] | void) { + if (typeof rawArguments === 'undefined') { + this._hasNoArguments = true + return this + } + + this._argumentsClass = this.classifyArguments(rawArguments) + this._value = rawArguments + } + + static from(rawArguments: any[]): RecordedArguments { + return new this(rawArguments) + } + + static none(): RecordedArguments { + return new this() + } + + static sort(objectWithArguments: T[]): T[] { + return objectWithArguments.sort((a, b) => { + const aClass = a.recordedArguments.argumentsClass + const bClass = b.recordedArguments.argumentsClass + + if (aClass === bClass) return 0 + if (aClass === 'plain') return -1 + if (bClass === 'plain') return 1 + + if (aClass === 'with-predicate') return -1 + if (bClass === 'with-predicate') return 1 + + if (aClass === 'wildcard') return -1 + return 1 + }) + } + + get argumentsClass(): ArgumentsClass { + return this._argumentsClass + } + + get value(): any[] | undefined { + return this._value + } + + get hasNoArguments(): boolean { + return this._hasNoArguments + } + + public match(other: RecordedArguments) { + if (this.argumentsClass === 'wildcard' || other.argumentsClass === 'wildcard') return true + if (this.hasNoArguments || other.hasNoArguments) return this.hasNoArguments && other.hasNoArguments + if (this.value.length !== other.value.length) return false + + return this.value.every((argument, index) => this.areArgumentsEqual(argument, other.value[index])) + } + + private classifyArguments(rawArguments: any[]): ArgumentsClass { + const allPlain = rawArguments.every(arg => !(arg instanceof Argument || arg instanceof AllArguments)) + if (allPlain) return 'plain' + + const hasSingleArgument = rawArguments.some(arg => arg instanceof Argument) + if (hasSingleArgument) return 'with-predicate' + + return 'wildcard' + } + + private areArgumentsEqual(a: any, b: any): boolean { + if (a instanceof Argument && b instanceof Argument) return false + if (a instanceof Argument) return a.matches(b) + if (b instanceof Argument) return b.matches(a) + return isDeepStrictEqual(a, b) + } + + [inspect.custom](_: number, options: InspectOptions) { + return this.printableForm(options) + } + + private printableForm(options: InspectOptions): string { + const inspectedValues = this.value?.map(v => inspect(v, options)) + if (!Array.isArray(inspectedValues)) return '' + return inspectedValues.length !== 1 + ? `(${inspectedValues.join(', ')})` + : inspectedValues[0] + } +} \ No newline at end of file diff --git a/src/Recorder.ts b/src/Recorder.ts new file mode 100644 index 0000000..6da2ee8 --- /dev/null +++ b/src/Recorder.ts @@ -0,0 +1,54 @@ +import { inspect, InspectOptions } from 'util' +import { SubstituteNodeBase } from './SubstituteNodeBase' +import { RecordsSet } from './RecordsSet' + +export class Recorder { + private _records: RecordsSet + private _indexedRecords: Map> + + constructor() { + this._records = new RecordsSet() + this._indexedRecords = new Map() + } + + public get records(): RecordsSet { + return this._records + } + + public get indexedRecords(): Map> { + return this._indexedRecords + } + + public addIndexedRecord(node: SubstituteNodeBase): void { + this.addRecord(node) + const existingNodes = this.indexedRecords.get(node.key) + if (typeof existingNodes === 'undefined') this.indexedRecords.set(node.key, new RecordsSet([node])) + else existingNodes.add(node) + } + + public addRecord(node: SubstituteNodeBase): void { + this._records.add(node) + } + + public getSiblingsOf(node: SubstituteNodeBase): RecordsSet { + const siblingNodes = this.indexedRecords.get(node.key) ?? new RecordsSet() + return siblingNodes.filter(siblingNode => siblingNode !== node) + } + + public clearRecords(filterFunction: (node: SubstituteNodeBase) => boolean) { + const recordsToRemove = this.records.filter(filterFunction) + for (const record of recordsToRemove) { + const indexedRecord = this.indexedRecords.get(record.key) + indexedRecord.delete(record) + if (indexedRecord.size === 0) this.indexedRecords.delete(record.key) + this.records.delete(record) + } + } + + public [inspect.custom](_: number, options: InspectOptions): string { + const entries = [...this.indexedRecords.entries()] + return entries.map( + ([key, value]) => `\n ${key.toString()}: {\n${[...value.map(v => ` ${inspect(v, options)}`)].join(',\n')}\n }` + ).join() + } +} diff --git a/src/RecordsSet.ts b/src/RecordsSet.ts new file mode 100644 index 0000000..0d16501 --- /dev/null +++ b/src/RecordsSet.ts @@ -0,0 +1,65 @@ +type FilterFunction = (item: T) => boolean +type MapperFunction = (item: T) => R +type Transformer = { type: 'filter', fnc: FilterFunction } | { type: 'mapper', fnc: MapperFunction } + +export class RecordsSet extends Set { + private _transformer: Transformer + private readonly _prevIter?: RecordsSet + + constructor(value?: Iterable | readonly T[]) { + super(value instanceof RecordsSet ? undefined : value) + if (value instanceof RecordsSet) this._prevIter = value + } + + get size(): number { + const currentSize = super.size + if (this._prevIter instanceof RecordsSet) return currentSize + this._prevIter.size + return currentSize + } + + filter(predicate: (item: T) => boolean): RecordsSet { + const newInstance = new RecordsSet(this) + newInstance._transformer = { type: 'filter', fnc: predicate } + return newInstance + } + + map(predicate: (item: T) => R): RecordsSet { + const newInstance = new RecordsSet(this) + newInstance._transformer = { type: 'mapper', fnc: predicate } + return newInstance as RecordsSet + } + + has(value: T): boolean { + if (super.has(value)) return true + return this._prevIter instanceof RecordsSet ? this._prevIter.has(value) : false + } + + delete(value: T): boolean { + const deleted = super.delete(value) + if (deleted) return true + return this._prevIter instanceof RecordsSet ? this._prevIter.delete(value) : false + } + + clear() { + Object.defineProperty(this, '_prevIter', { value: undefined }) + super.clear() + } + + *[Symbol.iterator](): IterableIterator { + yield* this.values() + } + + *values(): IterableIterator { + if (this._prevIter instanceof RecordsSet) yield* this.applyTransform(this._prevIter) + yield* this.applyTransform(super.values()) + } + + private *applyTransform(itarable: Iterable): IterableIterator { + const transform = this._transformer + if (typeof transform === 'undefined') return yield* itarable + for (const value of itarable) { + if (transform.type === 'mapper') yield transform.fnc(value) + if (transform.type === 'filter' && transform.fnc(value)) yield value + } + } +} \ No newline at end of file diff --git a/src/Substitute.ts b/src/Substitute.ts index cc1ea08..21afa3f 100644 --- a/src/Substitute.ts +++ b/src/Substitute.ts @@ -1,41 +1,81 @@ -import { Context } from './Context'; -import { ObjectSubstitute, OmitProxyMethods, DisabledSubstituteObject } from './Transformations'; - -export const HandlerKey = Symbol(); -export const AreProxiesDisabledKey = Symbol(); - -export type SubstituteOf = ObjectSubstitute, T> & T; - -export class Substitute { - static for(): SubstituteOf { - const objectContext = new Context(); - return objectContext.rootProxy; - } - - static disableFor>>(substitute: T): DisabledSubstituteObject { - const thisProxy = substitute as any; // rootProxy - const thisExposedProxy = thisProxy[HandlerKey]; // Context - - const disableProxy = (f: K): K => { - return function () { - thisProxy[AreProxiesDisabledKey] = true; - const returnValue = f.call(thisExposedProxy, ...arguments); - thisProxy[AreProxiesDisabledKey] = false; - return returnValue; - } as any; - }; - - return new Proxy(() => { }, { - apply: function (_target, _this, args) { - return disableProxy(thisExposedProxy.getStateApply)(...arguments) - }, - set: function (_target, property, value) { - return disableProxy(thisExposedProxy.setStateSet)(...arguments) - }, - get: function (_target, property) { - thisExposedProxy._initialState.handleGet(thisExposedProxy, property) - return disableProxy(thisExposedProxy.getStateGet)(...arguments) - } - }) as any; - } +import { inspect, InspectOptions } from 'util' + +import { SubstituteBase } from './SubstituteBase' +import { createSubstituteProxy } from './SubstituteProxy' +import { Recorder } from './Recorder' +import { DisabledSubstituteObject, ObjectSubstitute, OmitProxyMethods } from './Transformations' + +export type SubstituteOf = ObjectSubstitute, T> & T +type Instantiable = { [SubstituteBase.instance]?: T } + +export class Substitute extends SubstituteBase { + private _proxy: Substitute + private _recorder: Recorder = new Recorder() + private _context: { disableAssertions: boolean } = { disableAssertions: false } + + constructor() { + super() + this._proxy = createSubstituteProxy( + this, + { + get: (target, _property, _, node) => { + if (target.context.disableAssertions) node.disableAssertions() + } + // apply: (target, _, args, __, proxy) => { + // const rootProperty = proxy.get(target, '()', proxy) TODO: Implement to support callable interfaces + // return Reflect.apply(rootProperty, rootProperty, args) + // } + } + ) + } + + static for(): SubstituteOf { + const substitute = new this() + return substitute.proxy as unknown as SubstituteOf + } + + static disableFor & Instantiable>(substituteProxy: T): DisabledSubstituteObject { + const substitute = substituteProxy[SubstituteBase.instance] + + const disableProxy = < + TParameters extends unknown[], + TReturnType extends unknown + >(reflection: (...args: TParameters) => TReturnType): typeof reflection => (...args) => { + substitute.context.disableAssertions = true + const reflectionResult = reflection(...args) + substitute.context.disableAssertions = false + return reflectionResult + } + + return new Proxy(substitute.proxy, { + get: function (target, property) { + return disableProxy(Reflect.get)(target, property) + }, + set: function (target, property, value) { + return disableProxy(Reflect.set)(target, property, value) + }, + apply: function (target, _, args) { + return disableProxy(Reflect.apply)(target, _, args) + } + }) as DisabledSubstituteObject + } + + public get proxy() { + return this._proxy + } + + public get recorder() { + return this._recorder + } + + public get context() { + return this._context + } + + protected printableForm(_: number, options: InspectOptions): string { + const records = inspect(this.recorder, options) + + const instanceName = 'Substitute' // Substitute + return instanceName + ' {' + records + '\n}' + } } \ No newline at end of file diff --git a/src/SubstituteBase.ts b/src/SubstituteBase.ts index f2ea606..a0eb4c0 100644 --- a/src/SubstituteBase.ts +++ b/src/SubstituteBase.ts @@ -1,73 +1,35 @@ -import { inspect } from 'util'; -import { PropertyType, stringifyArguments, stringifyCalls, Call } from './Utilities'; +import { inspect, InspectOptions, types } from 'util' +import { SubstituteException } from './SubstituteException' -export class SubstituteJS { - private _lastRegisteredSubstituteJSMethodOrProperty: string - set lastRegisteredSubstituteJSMethodOrProperty(value: string) { - this._lastRegisteredSubstituteJSMethodOrProperty = value; +const instance = Symbol('Substitute:Instance') +type SpecialProperty = typeof instance | typeof inspect.custom | 'then' +export abstract class SubstituteBase extends Function { + constructor() { + super() } - get lastRegisteredSubstituteJSMethodOrProperty() { - return typeof this._lastRegisteredSubstituteJSMethodOrProperty === 'undefined' ? 'root' : this._lastRegisteredSubstituteJSMethodOrProperty; - } - [Symbol.toPrimitive]() { - return `[class ${this.constructor.name}] -> ${this.lastRegisteredSubstituteJSMethodOrProperty}`; - } - [Symbol.toStringTag]() { - return `[class ${this.constructor.name}] -> ${this.lastRegisteredSubstituteJSMethodOrProperty}`; - } - [Symbol.iterator]() { - return `[class ${this.constructor.name}] -> ${this.lastRegisteredSubstituteJSMethodOrProperty}`; - } - [inspect.custom]() { - return `[class ${this.constructor.name}] -> ${this.lastRegisteredSubstituteJSMethodOrProperty}`; - } - valueOf() { - return `[class ${this.constructor.name}] -> ${this.lastRegisteredSubstituteJSMethodOrProperty}`; - } - $$typeof() { - return `[class ${this.constructor.name}] -> ${this.lastRegisteredSubstituteJSMethodOrProperty}`; - } - toString() { - return `[class ${this.constructor.name}] -> ${this.lastRegisteredSubstituteJSMethodOrProperty}`; - } - inspect() { - return `[class ${this.constructor.name}] -> ${this.lastRegisteredSubstituteJSMethodOrProperty}`; - } - length = `[class ${this.constructor.name}] -> ${this.lastRegisteredSubstituteJSMethodOrProperty}`; -} -enum SubstituteExceptionTypes { - CallCountMissMatch = 'CallCountMissMatch', - PropertyNotMocked = 'PropertyNotMocked' -} + static instance: typeof instance = instance -export class SubstituteException extends Error { - type: SubstituteExceptionTypes - constructor(msg: string, exceptionType?: SubstituteExceptionTypes) { - super(msg); - Error.captureStackTrace(this, SubstituteException); - this.name = new.target.name; - this.type = exceptionType + protected isSpecialProperty(property: PropertyKey): property is SpecialProperty { + return property === SubstituteBase.instance || property === inspect.custom || property === 'then' } - static forCallCountMissMatch( - callCount: { expected: number | null, received: number }, - property: { type: PropertyType, value: PropertyKey }, - calls: { expectedArguments: any[], received: Call[] } - ) { - const message = 'Expected ' + (callCount.expected === null ? '1 or more' : callCount.expected) + - ' call' + (callCount.expected === 1 ? '' : 's') + ' to the ' + property.type + ' ' + property.value.toString() + - ' with ' + stringifyArguments(calls.expectedArguments) + ', but received ' + (callCount.received === 0 ? 'none' : callCount.received) + - ' of such call' + (callCount.received === 1 ? '' : 's') + - '.\nAll calls received to ' + property.type + ' ' + property.value.toString() + ':' + stringifyCalls(calls.received); - return new this(message, SubstituteExceptionTypes.CallCountMissMatch); + protected evaluateSpecialProperty(property: SpecialProperty) { + switch (property) { + case SubstituteBase.instance: + return this + case inspect.custom: + return this.printableForm.bind(this) + case 'then': + return + default: + throw SubstituteException.generic(`Evaluation of special property ${property} is not implemented`) + } } - static forPropertyNotMocked(property: PropertyKey) { - return new this(`There is no mock for property: ${String(property)}`, SubstituteExceptionTypes.PropertyNotMocked) - } + protected abstract printableForm(_: number, options: InspectOptions): string - static generic(message: string) { - return new this(message) + public [inspect.custom](...args: [_: number, options: InspectOptions]): string { + return types.isProxy(this) ? this[inspect.custom](...args) : this.printableForm(...args) } } \ No newline at end of file diff --git a/src/SubstituteException.ts b/src/SubstituteException.ts new file mode 100644 index 0000000..d72f01f --- /dev/null +++ b/src/SubstituteException.ts @@ -0,0 +1,52 @@ +import { RecordedArguments } from './RecordedArguments' +import { PropertyType, stringifyArguments, stringifyCalls, textModifier, plurify } from './Utilities' + +enum SubstituteExceptionTypes { + CallCountMissMatch = 'CallCountMissMatch', + PropertyNotMocked = 'PropertyNotMocked' +} + +export class SubstituteException extends Error { + type: SubstituteExceptionTypes + + constructor(msg: string, exceptionType?: SubstituteExceptionTypes) { + super(msg) + Error.captureStackTrace(this, SubstituteException) + this.name = new.target.name + this.type = exceptionType + } + + static forCallCountMissMatch( + count: { expected: number | null, received: number }, + property: { type: PropertyType, value: PropertyKey }, + calls: { expected: RecordedArguments, received: RecordedArguments[] } + ) { + const propertyValue = textModifier.bold(property.value.toString()) + const commonMessage = `Expected ${textModifier.bold( + count.expected === undefined ? '1 or more' : count.expected.toString() + )} ${plurify('call', count.expected)} to the ${textModifier.italic(property.type)} ${propertyValue}` + + const messageForMethods = property.type === PropertyType.method ? ` with ${stringifyArguments(calls.expected)}` : '' // should also apply for setters (instead of methods only) + const receivedMessage = `, but received ${textModifier.bold(count.received < 1 ? 'none' : count.received.toString())} of such calls.` + + const callTrace = calls.received.length > 0 + ? `\nAll calls received to ${textModifier.italic(property.type)} ${propertyValue}:${stringifyCalls(calls.received)}` + : '' + + return new this( + commonMessage + messageForMethods + receivedMessage + callTrace, + SubstituteExceptionTypes.CallCountMissMatch + ) + } + + static forPropertyNotMocked(property: PropertyKey) { + return new this( + `There is no mock for property: ${property.toString()}`, + SubstituteExceptionTypes.PropertyNotMocked + ) + } + + static generic(message: string) { + return new this(message) + } +} \ No newline at end of file diff --git a/src/SubstituteNode.ts b/src/SubstituteNode.ts new file mode 100644 index 0000000..800603a --- /dev/null +++ b/src/SubstituteNode.ts @@ -0,0 +1,206 @@ +import { inspect, InspectOptions } from 'util' + +import { PropertyType, isSubstitutionMethod, isAssertionMethod, AssertionMethod, SubstitutionMethod, textModifier, ConfigurationMethod, isSubstituteMethod } from './Utilities' +import { SubstituteException } from './SubstituteException' +import { RecordedArguments } from './RecordedArguments' +import { SubstituteNodeBase } from './SubstituteNodeBase' +import { SubstituteBase } from './SubstituteBase' +import { createSubstituteProxy } from './SubstituteProxy' +import { ClearType } from './Transformations' + +type SubstituteContext = SubstitutionMethod | AssertionMethod | ConfigurationMethod | 'none' +const clearTypeToFilterMap: Record boolean> = { + all: () => true, + receivedCalls: node => !node.hasContext, + substituteValues: node => node.isSubstitution +} + +export class SubstituteNode extends SubstituteNodeBase { + private _proxy: SubstituteNode + private _propertyType: PropertyType = PropertyType.property + private _accessorType: 'get' | 'set' = 'get' + private _recordedArguments: RecordedArguments = RecordedArguments.none() + + private _context: SubstituteContext = 'none' + private _disabledAssertions: boolean = false + + constructor(property: PropertyKey, parent: SubstituteNode | SubstituteBase) { + super(property, parent) + this._proxy = createSubstituteProxy( + this, + { + get: (node, _, __, nextNode) => { + if (node.isAssertion) nextNode.executeAssertion() + }, + set: (node, _, __, ___, nextNode) => { + if (node.isAssertion) nextNode.executeAssertion() + }, + apply: (node, _, rawArguments) => { + node.handleMethod(rawArguments) + if (node.context === 'clearSubstitute') return node.clear() + return node.parent?.isAssertion ?? false ? node.executeAssertion() : node.read() + } + } + ) + } + + public get proxy() { + return this._proxy + } + + get context(): SubstituteContext { + return this._context + } + + get hasContext(): boolean { + return this.context !== 'none' + } + + get isSubstitution(): boolean { + return isSubstitutionMethod(this.context) + } + + get isAssertion(): boolean { + return isAssertionMethod(this.context) + } + + get property() { + return this.key + } + + get propertyType() { + return this._propertyType + } + + get accessorType() { + return this._accessorType + } + + get recordedArguments() { + return this._recordedArguments + } + + public get disabledAssertions() { + return this._disabledAssertions + } + + public assignContext(context: SubstituteContext): void { + this._context = context + } + + public disableAssertions() { + this._disabledAssertions = true + } + + public read(): SubstituteNode | void | never { + if (this.parent?.isSubstitution ?? false) return + if (this.isAssertion) return this.proxy + + const mostSuitableSubstitution = this.getMostSuitableSubstitution() + return mostSuitableSubstitution instanceof SubstituteNode + ? mostSuitableSubstitution.executeSubstitution(this.recordedArguments) + : this.proxy + } + + public write(value: any) { + this._accessorType = 'set' + this._recordedArguments = RecordedArguments.from([value]) + } + + public clear() { + const clearType: ClearType = this.recordedArguments.value[0] ?? 'all' + const filter = clearTypeToFilterMap[clearType] as (node: SubstituteNodeBase) => boolean + this.root.recorder.clearRecords(filter) + } + + public executeSubstitution(contextArguments: RecordedArguments) { + const substitutionMethod = this.context as SubstitutionMethod + const substitutionValue = this.child.recordedArguments.value.length > 1 + ? this.child.recordedArguments.value.shift() + : this.child.recordedArguments.value[0] + switch (substitutionMethod) { + case 'throws': + throw substitutionValue + case 'mimicks': + const argumentsToApply = this.propertyType === PropertyType.property ? [] : contextArguments.value + return substitutionValue(...argumentsToApply) + case 'resolves': + return Promise.resolve(substitutionValue) + case 'rejects': + return Promise.reject(substitutionValue) + case 'returns': + return substitutionValue + default: + throw SubstituteException.generic(`Substitution method '${substitutionMethod}' not implemented`) + } + } + + public executeAssertion(): void | never { + const siblings = [...this.getAllSiblings().filter(n => !n.hasContext && n.accessorType === this.accessorType)] + if (!this.isIntermediateNode()) throw new Error('Not possible') + + const expectedCount = this.parent.recordedArguments.value[0] ?? undefined + const finiteExpectation = expectedCount !== undefined + if (finiteExpectation && (!Number.isInteger(expectedCount) || expectedCount < 0)) throw new Error('Expected count has to be a positive integer') + + const hasRecordedCalls = siblings.length > 0 + const allRecordedArguments = siblings.map(sibling => sibling.recordedArguments) + + if ( + !hasRecordedCalls && + (!finiteExpectation || expectedCount > 0) + ) throw SubstituteException.forCallCountMissMatch( // Here we don't know here if it's a property or method, so we should throw something more generic + { expected: expectedCount, received: 0 }, + { type: this.propertyType, value: this.property }, + { expected: this.recordedArguments, received: allRecordedArguments } + ) + + if (!hasRecordedCalls || siblings.some(sibling => sibling.propertyType === this.propertyType)) { + const actualCount = allRecordedArguments.filter(r => r.match(this.recordedArguments)).length + const matchedExpectation = (!finiteExpectation && actualCount > 0) || expectedCount === actualCount + + if (!matchedExpectation) throw SubstituteException.forCallCountMissMatch( + { expected: expectedCount, received: actualCount }, + { type: this.propertyType, value: this.property }, + { expected: this.recordedArguments, received: allRecordedArguments } + ) + } + } + + public handleMethod(rawArguments: any[]): void { + this._propertyType = PropertyType.method + this._recordedArguments = RecordedArguments.from(rawArguments) + if (!isSubstituteMethod(this.property)) return + + if (this.isIntermediateNode() && isSubstitutionMethod(this.property)) return this.parent.assignContext(this.property) + if (this.disabledAssertions || !this.isHead()) return + + this.assignContext(this.property) + if (this.context === 'didNotReceive') this._recordedArguments = RecordedArguments.from([0]) + } + + private getMostSuitableSubstitution(): SubstituteNode { + const nodes = this.getAllSiblings().filter(node => node.isSubstitution && + node.propertyType === this.propertyType && + node.recordedArguments.match(this.recordedArguments) + ) + const sortedNodes = RecordedArguments.sort([...nodes]) + return sortedNodes[0] + } + + protected printableForm(_: number, options: InspectOptions): string { + const hasContext = this.hasContext + const args = inspect(this.recordedArguments, options) + const label = this.isSubstitution + ? '=> ' + : this.isAssertion + ? `${this.child.property.toString()}` + : '' + const s = hasContext + ? ` ${label}${inspect(this.child?.recordedArguments, options)}` + : '' + + const printableNode = `${this.propertyType}<${this.property.toString()}>: ${args}${s}` + return hasContext ? textModifier.italic(printableNode) : printableNode + } +} \ No newline at end of file diff --git a/src/SubstituteNodeBase.ts b/src/SubstituteNodeBase.ts new file mode 100644 index 0000000..21c9e4d --- /dev/null +++ b/src/SubstituteNodeBase.ts @@ -0,0 +1,67 @@ +import { SubstituteBase } from './SubstituteBase' +import { Substitute } from './Substitute' +import { RecordsSet } from './RecordsSet' + +export abstract class SubstituteNodeBase> extends SubstituteBase { + private _parent?: T + private _child?: T + private _head: T & { parent: undefined } + private _root: Substitute + + constructor(private _key: PropertyKey, caller: SubstituteBase) { + super() + + if (caller instanceof Substitute) { + caller.recorder.addIndexedRecord(this) + this._root = caller + } + if (!(caller instanceof SubstituteNodeBase)) return + + this._parent = caller as T + this._head = caller.head as T & { parent: undefined } + caller.child = this + } + + get key(): PropertyKey { + return this._key + } + + set parent(parent: T | undefined) { + this._parent = parent + } + + get parent(): T | undefined { + return this._parent + } + + set child(child: T) { + this._child = child + } + + get child(): T { + return this._child + } + + get head(): T & { parent: undefined } { + return this.isHead() ? this : this._head + } + + protected get root(): Substitute { + return this.head._root + } + + protected isHead(): this is T & { parent: undefined } { + return typeof this._parent === 'undefined' + } + + protected isIntermediateNode(): this is T & { parent: T } { + return !this.isHead() + } + + protected getAllSiblings(): RecordsSet { + return this.root.recorder.getSiblingsOf(this) as RecordsSet + } + + public abstract read(): void + public abstract write(value: any): void +} \ No newline at end of file diff --git a/src/SubstituteProxy.ts b/src/SubstituteProxy.ts new file mode 100644 index 0000000..c8e927c --- /dev/null +++ b/src/SubstituteProxy.ts @@ -0,0 +1,32 @@ +import { SubstituteBase } from './SubstituteBase' +import { SubstituteNode } from './SubstituteNode' + +type BeforeNodeExecutionHook = { + [Handler in keyof ProxyHandler]?: (...args: [..._: Parameters[Handler]>, node: SubstituteNode | undefined, proxy: ProxyHandler]) => void +} +export const createSubstituteProxy = ( + target: T, + beforeNodeExecutionHook: BeforeNodeExecutionHook +) => new Proxy( + target, + { + get: function (this: SubstituteBase, ...args) { + const [target, property] = args + if (target.isSpecialProperty(property)) return target.evaluateSpecialProperty(property) + const newNode = new SubstituteNode(property, target) + beforeNodeExecutionHook.get?.(...args, newNode, this) + return newNode.read() + }, + set: function (...args) { + const [target, property, value] = args + const newNode = new SubstituteNode(property, target) + newNode.write(value) + beforeNodeExecutionHook.set?.(...args, newNode, this) + return true + }, + apply: function (...args) { + return beforeNodeExecutionHook.apply?.(...args, undefined, this) + + } + } +) \ No newline at end of file diff --git a/src/Transformations.ts b/src/Transformations.ts index e6a34b0..f2089c6 100644 --- a/src/Transformations.ts +++ b/src/Transformations.ts @@ -1,4 +1,4 @@ -import { AllArguments } from "./Arguments"; +import { AllArguments } from './Arguments'; type FunctionSubstituteWithOverloads = TFunc extends { @@ -70,6 +70,7 @@ export type ObjectSubstitute = ObjectSub received(amount?: number): TerminatingObject; didNotReceive(): TerminatingObject; mimick(instance: T): void; + clearSubstitute(clearType?: ClearType): void; } type TerminatingFunction = ((...args: TArguments) => void) & ((arg: AllArguments) => void) @@ -92,5 +93,6 @@ type ObjectSubstituteTransformation = { type Omit = Pick>; -export type OmitProxyMethods = Omit; +export type ClearType = 'all' | 'receivedCalls' | 'substituteValues'; +export type OmitProxyMethods = Omit; export type DisabledSubstituteObject = T extends ObjectSubstitute, infer K> ? K : never; diff --git a/src/Utilities.ts b/src/Utilities.ts index 207c05d..53ba35b 100644 --- a/src/Utilities.ts +++ b/src/Utilities.ts @@ -1,99 +1,44 @@ -import { Argument, AllArguments } from './Arguments'; -import { GetPropertyState } from './states/GetPropertyState'; -import { InitialState } from './states/InitialState'; -import { Context } from './Context'; -import * as util from 'util'; - -export type Call = any[] // list of args - -export enum PropertyType { - method = 'method', - property = 'property' -} - -export enum SubstituteMethods { - received = 'received', - didNotReceive = 'didNotReceive', - mimicks = 'mimicks', - throws = 'throws', - returns = 'returns', - resolves = 'resolves', - rejects = 'rejects' -} - -const seenObject = Symbol(); - -export function stringifyArguments(args: any[]) { - args = args.map(x => util.inspect(x)); - return args && args.length > 0 ? 'arguments [' + args.join(', ') + ']' : 'no arguments'; -}; - -export function areArgumentArraysEqual(a: any[], b: any[]) { - if (a.find(x => x instanceof AllArguments) || b.find(b => b instanceof AllArguments)) { - return true; - } - - for (let i = 0; i < Math.max(b.length, a.length); i++) { - if (!areArgumentsEqual(b[i], a[i])) { - return false; - } - } - - return true; -} - -export function stringifyCalls(calls: Call[]) { - - if (calls.length === 0) - return ' (no calls)'; - - let output = ''; - for (let call of calls) { - output += '\n-> call with ' + (call.length ? stringifyArguments(call) : '(no arguments)') - } - - return output; -}; - -export function areArgumentsEqual(a: any, b: any) { - - if (a instanceof Argument && b instanceof Argument) - return false; - - if (a instanceof AllArguments || b instanceof AllArguments) - return true; - - if (a instanceof Argument) - return a.matches(b); - - if (b instanceof Argument) - return b.matches(a); - - return deepEqual(a, b); -}; - -function deepEqual(realA: any, realB: any, objectReferences: object[] = []): boolean { - const a = objectReferences.includes(realA) ? seenObject : realA; - const b = objectReferences.includes(realB) ? seenObject : realB; - const newObjectReferences = updateObjectReferences(objectReferences, a, b); - - if (nonNullObject(a) && nonNullObject(b)) { - if (a.constructor !== b.constructor) return false; - const objectAKeys = Object.keys(a); - if (objectAKeys.length !== Object.keys(b).length) return false; - for (const key of objectAKeys) { - if (!deepEqual(a[key], b[key], newObjectReferences)) return false; - } - return true; - } - return a === b; -} - -function updateObjectReferences(objectReferences: Array, a: any, b: any) { - const tempObjectReferences = [...objectReferences, nonNullObject(a) && !objectReferences.includes(a) ? a : void 0]; - return [...tempObjectReferences, nonNullObject(b) && !tempObjectReferences.includes(b) ? b : void 0]; -} - -function nonNullObject(value: any): value is { [key: string]: any } { - return typeof value === 'object' && value !== null; -} \ No newline at end of file +import { inspect } from 'util' +import { RecordedArguments } from './RecordedArguments' + +export enum PropertyType { + method = 'method', + property = 'property' +} + +export type AssertionMethod = 'received' | 'didNotReceive' +export const isAssertionMethod = (property: PropertyKey): property is AssertionMethod => + property === 'received' || property === 'didNotReceive' + +export type ConfigurationMethod = 'clearSubstitute' +export const isConfigurationMethod = (property: PropertyKey): property is ConfigurationMethod => property === 'clearSubstitute' + +export type SubstitutionMethod = 'mimicks' | 'throws' | 'returns' | 'resolves' | 'rejects' +export const isSubstitutionMethod = (property: PropertyKey): property is SubstitutionMethod => + property === 'mimicks' || property === 'returns' || property === 'throws' || property === 'resolves' || property === 'rejects' + +export const isSubstituteMethod = (property: PropertyKey): property is SubstitutionMethod | ConfigurationMethod | AssertionMethod => + isSubstitutionMethod(property) || isConfigurationMethod(property) || isAssertionMethod(property) + +export const stringifyArguments = (args: RecordedArguments) => textModifier.faint( + args.hasNoArguments + ? 'no arguments' + : `arguments [${args.value.map(x => inspect(x, { colors: true })).join(', ')}]` +) + +export const stringifyCalls = (calls: RecordedArguments[]) => { + if (calls.length === 0) return ' (no calls)' + + const key = '\n-> call with ' + const callsDetails = calls.map(stringifyArguments) + return `${key}${callsDetails.join(key)}` +} + +const baseTextModifier = (str: string, modifierStart: number, modifierEnd: number) => `\x1b[${modifierStart}m${str}\x1b[${modifierEnd}m` +export const textModifier = { + bold: (str: string) => baseTextModifier(str, 1, 22), + faint: (str: string) => baseTextModifier(str, 2, 22), + italic: (str: string) => baseTextModifier(str, 3, 23) +} + +export const plurify = (str: string, count: number) => `${str}${count === 1 ? '' : 's'}` \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 2177c84..c054fa3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,6 @@ -import { Substitute, SubstituteOf } from './Substitute'; +import { Substitute, SubstituteOf } from './Substitute' -export { Arg } from './Arguments'; -export { Substitute, SubstituteOf }; +export { Arg } from './Arguments' +export { Substitute, SubstituteOf } -export default Substitute; \ No newline at end of file +export default Substitute \ No newline at end of file diff --git a/src/states/ContextState.ts b/src/states/ContextState.ts deleted file mode 100644 index 6448fbd..0000000 --- a/src/states/ContextState.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Context } from "../Context"; - -export type PropertyKey = string | number | symbol; - -export interface ContextState { - onSwitchedTo?(context: Context): void; - apply(context: Context, args: any[]): any; - set(context: Context, property: PropertyKey, value: any): void; - get(context: Context, property: PropertyKey): any; -} \ No newline at end of file diff --git a/src/states/GetPropertyState.ts b/src/states/GetPropertyState.ts deleted file mode 100644 index a5abd91..0000000 --- a/src/states/GetPropertyState.ts +++ /dev/null @@ -1,131 +0,0 @@ -import { ContextState, PropertyKey } from './ContextState'; -import { Context } from '../Context'; -import { PropertyType, SubstituteMethods, Call, areArgumentArraysEqual } from '../Utilities'; -import { SubstituteException } from '../SubstituteBase'; - -interface SubstituteMock { - arguments: Call - mockValues: any[] - substituteType: SubstituteMethods -} - -export class GetPropertyState implements ContextState { - private _mocks: SubstituteMock[]; - private _recordedCalls: Call[]; - private _isFunctionState: boolean; - private _lastArgs?: Call; - - public get property(): PropertyKey { - return this._property; - } - - get isFunctionState(): boolean { - return this._isFunctionState; - } - - public get callCount(): number { - return this._recordedCalls.length; - } - - constructor(private _property: PropertyKey) { - this._mocks = []; - this._recordedCalls = []; - this._isFunctionState = false; - } - - private getCallCount(args: Call): number { - const callFilter = (recordedCall: Call): boolean => areArgumentArraysEqual(recordedCall, args); - return this._recordedCalls.filter(callFilter).length; - } - - private applySubstituteMethodLogic(substituteMethod: SubstituteMethods, mockValue: any, args?: Call) { - switch (substituteMethod) { - case SubstituteMethods.resolves: - return Promise.resolve(mockValue); - case SubstituteMethods.rejects: - return Promise.reject(mockValue); - case SubstituteMethods.returns: - return mockValue; - case SubstituteMethods.throws: - throw mockValue; - case SubstituteMethods.mimicks: - return mockValue.apply(mockValue, args); - default: - throw SubstituteException.generic(`Method ${substituteMethod} not implemented`) - } - } - - private processProperty(context: Context, args: any[], propertyType: PropertyType) { - const hasExpectations = context.initialState.hasExpectations; - if (!hasExpectations) { - this._recordedCalls.push(args); - const foundSubstitute = this._mocks.find(mock => areArgumentArraysEqual(mock.arguments, args)); - if (foundSubstitute !== void 0) { - const mockValue = foundSubstitute.mockValues.length > 1 ? - foundSubstitute.mockValues.shift() : - foundSubstitute.mockValues[0]; - return this.applySubstituteMethodLogic(foundSubstitute.substituteType, mockValue, args); - } - } - - context.initialState.assertCallCountMatchesExpectations( - this._recordedCalls, - this.getCallCount(args), - propertyType, - this.property, - args - ); - - return context.proxy; - } - - apply(context: Context, args: any[]) { - if (!this._isFunctionState) { - this._isFunctionState = true; - this._recordedCalls = []; - } - this._lastArgs = args; - return this.processProperty(context, args, PropertyType.method); - } - - set(context: Context, property: PropertyKey, value: any) { } - - private isSubstituteMethod(property: PropertyKey): property is SubstituteMethods { - return property === SubstituteMethods.returns || - property === SubstituteMethods.mimicks || - property === SubstituteMethods.throws || - property === SubstituteMethods.resolves || - property === SubstituteMethods.rejects; - } - - private sanitizeSubstituteMockInputs(mockInputs: Call): Call { - if (mockInputs.length === 0) return [undefined]; - return mockInputs.length > 1 ? - [...mockInputs, undefined] : - [...mockInputs]; - } - - get(context: Context, property: PropertyKey) { - if (property === 'then') return void 0; - - if (this.isSubstituteMethod(property)) { - return (...inputs: Call) => { - const mockInputs = this.sanitizeSubstituteMockInputs(inputs); - const args = this._isFunctionState ? this._lastArgs : []; - if (args === void 0) - throw SubstituteException.generic('Eh, there\'s a bug, no args recorded :/'); - - this._mocks.push({ - arguments: args, - mockValues: mockInputs, - substituteType: property - }); - - this._recordedCalls.pop(); - context.state = context.initialState; - } - } - if (this._isFunctionState) return context.proxy; - return this.processProperty(context, [], PropertyType.property); - } -} \ No newline at end of file diff --git a/src/states/InitialState.ts b/src/states/InitialState.ts deleted file mode 100644 index d7648ec..0000000 --- a/src/states/InitialState.ts +++ /dev/null @@ -1,138 +0,0 @@ -import { ContextState, PropertyKey } from './ContextState'; -import { Context } from '../Context'; -import { GetPropertyState } from './GetPropertyState'; -import { SetPropertyState } from './SetPropertyState'; -import { SubstituteMethods, Call, PropertyType } from '../Utilities'; -import { AreProxiesDisabledKey } from '../Substitute'; -import { SubstituteException } from '../SubstituteBase'; - -export class InitialState implements ContextState { - private recordedGetPropertyStates: Map; - private recordedSetPropertyStates: SetPropertyState[]; - - private _expectedCount: number | undefined | null; - private _areProxiesDisabled: boolean; - - public get expectedCount(): number | undefined | null { - return this._expectedCount; - } - - public get hasExpectations(): boolean { - return this._expectedCount !== void 0; - } - - public get setPropertyStates(): SetPropertyState[] { - return [...this.recordedSetPropertyStates]; - } - - public get getPropertyStates(): GetPropertyState[] { - return [...this.recordedGetPropertyStates.values()]; - } - - public recordGetPropertyState(property: PropertyKey, getState: GetPropertyState): void { - this.recordedGetPropertyStates.set(property, getState); - } - - public recordSetPropertyState(setState: SetPropertyState): void { - this.recordedSetPropertyStates.push(setState); - } - - constructor() { - this.recordedGetPropertyStates = new Map(); - this.recordedSetPropertyStates = []; - - this._areProxiesDisabled = false; - this._expectedCount = void 0; - } - - public assertCallCountMatchesExpectations( - receivedCalls: Call[], - receivedCount: number, - type: PropertyType, - propertyValue: PropertyKey, - args: any[] - ): void | never { - const expectedCount = this._expectedCount; - - this.clearExpectations(); - if (this.doesCallCountMatchExpectations(expectedCount, receivedCount)) - return; - - const callCount = { expected: expectedCount, received: receivedCount }; - const property = { type, value: propertyValue }; - const calls = { expectedArguments: args, received: receivedCalls }; - - throw SubstituteException.forCallCountMissMatch(callCount, property, calls); - } - - private doesCallCountMatchExpectations(expectedCount: number | undefined | null, actualCount: number) { - if (expectedCount === void 0) - return true; - - if (expectedCount === null && actualCount > 0) - return true; - - return expectedCount === actualCount; - } - - apply(context: Context, args: any[]) { } - - set(context: Context, property: PropertyKey, value: any) { - if (property === AreProxiesDisabledKey) { - this._areProxiesDisabled = value; - return; - } - - const existingSetState = this.recordedSetPropertyStates.find(x => x.arguments[0] === value); - if (existingSetState) { - return existingSetState.set(context, property, value); - } - - const setPropertyState = new SetPropertyState(property, value); - this.recordedSetPropertyStates.push(setPropertyState); - - context.state = setPropertyState; - return context.setStateSet(context, property, value); - } - - get(context: Context, property: PropertyKey) { - switch (property) { - case AreProxiesDisabledKey: - return this._areProxiesDisabled; - case SubstituteMethods.received: - return (count?: number) => { - this._expectedCount = count ?? null; - return context.receivedProxy; - }; - case SubstituteMethods.didNotReceive: - return () => { - this._expectedCount = 0; - return context.receivedProxy; - }; - default: - return this.handleGet(context, property); - } - } - - private clearExpectations() { - this._expectedCount = void 0; - } - - onSwitchedTo() { - this.clearExpectations(); - } - - public handleGet(context: Context, property: PropertyKey) { - const existingGetState = this.getPropertyStates.find(state => state.property === property); - if (existingGetState !== void 0) { - context.state = existingGetState; - return context.getStateGet(void 0, property); - } - - const getState = new GetPropertyState(property); - this.recordGetPropertyState(property, getState); - - context.state = getState; - return context.getStateGet(void 0, property); - } -} \ No newline at end of file diff --git a/src/states/SetPropertyState.ts b/src/states/SetPropertyState.ts deleted file mode 100644 index c7e62fd..0000000 --- a/src/states/SetPropertyState.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { ContextState, PropertyKey } from './ContextState'; -import { Context } from '../Context'; -import { areArgumentsEqual, PropertyType } from '../Utilities'; -import { SubstituteException } from '../SubstituteBase'; - -export class SetPropertyState implements ContextState { - private _callCount: number; - private _arguments: any[]; - - public get arguments() { - return this._arguments; - } - - public get property() { - return this._property; - } - - public get callCount() { - return this._callCount; - } - - constructor(private _property: PropertyKey, ...args: any[]) { - this._arguments = args; - this._callCount = 0; - } - - apply(context: Context): undefined { - throw SubstituteException.generic('Calling apply of setPropertyState is not normal behaviour, something went wrong'); - } - - set(context: Context, property: PropertyKey, value: any) { - let callCount = this._callCount; - const hasExpectations = context.initialState.hasExpectations; - if (hasExpectations) { - callCount = context.initialState - .setPropertyStates - .filter(x => areArgumentsEqual(x.arguments[0], value)) - .map(x => x._callCount) - .reduce((a, b) => a + b, 0); - } - - context.initialState.assertCallCountMatchesExpectations( - [[]], - callCount, - PropertyType.property, - this.property, - this.arguments - ); - - if (!hasExpectations) { - this._callCount++; - } - } - - get(context: Context, property: PropertyKey): undefined { - throw SubstituteException.generic('Calling get of setPropertyState is not normal behaviour, something went wrong'); - } -} \ No newline at end of file From c9e573cdee94ae96b06cf3115b30894972d8d7f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrique=20P=C3=B6hlmann?= <45039845+notanengineercom@users.noreply.github.com> Date: Thu, 13 Oct 2022 20:28:37 +0200 Subject: [PATCH 39/46] Refactor: simplify core (#243) * refactor core types * refactor substitute core * refactor recorder and recordsSet * fix tests due to refactor * fix types for typescript < 4.6 * Compatibility with strict mode (#244) * stricter types on recorded arguments * make types more verbose and explicit * fix types verbosity on tests * remove strictNullChecks flag * remove strict mode warning from readme * 2.0.0-beta.2 * Maintenance upgrades, guarantee support for node.js 18 & drop node.js 10 (#245) * better tsconfig setup * upgrade dependencies to latest * fix ava types * upgrade github actions * support up to node.js 18 * drop node.js 10 from test matrix * use ava config file --- .github/workflows/codeql-analysis.yml | 6 +- .github/workflows/nodejs.yml | 21 +- .github/workflows/npm-publish.yml | 21 +- README.md | 14 - ava.config.js | 13 + package-lock.json | 1960 ++++++------------------- package.json | 33 +- spec/ClearSubstitute.spec.ts | 23 +- spec/RecordedArguments.spec.ts | 10 +- spec/Recorder.spec.ts | 14 +- spec/RecordsSet.spec.ts | 32 +- spec/regression/Arguments.spec.ts | 6 +- spec/regression/index.test.ts | 28 +- spec/regression/issues/36.test.ts | 1 + spec/regression/issues/59.test.ts | 4 +- spec/regression/mimicks.spec.ts | 20 +- spec/regression/received.spec.ts | 7 +- spec/regression/returns.spec.ts | 39 +- spec/tsconfig.json | 10 + src/RecordedArguments.ts | 19 +- src/Recorder.ts | 63 +- src/RecordsSet.ts | 38 +- src/Substitute.ts | 65 +- src/SubstituteBase.ts | 35 - src/SubstituteException.ts | 9 +- src/SubstituteNode.ts | 159 +- src/SubstituteNodeBase.ts | 79 +- src/SubstituteProxy.ts | 32 - src/Transformations.ts | 27 +- src/Types.ts | 12 + src/Utilities.ts | 28 +- src/index.ts | 1 + tsconfig.json | 12 +- 33 files changed, 921 insertions(+), 1920 deletions(-) create mode 100644 ava.config.js create mode 100644 spec/tsconfig.json delete mode 100644 src/SubstituteBase.ts delete mode 100644 src/SubstituteProxy.ts create mode 100644 src/Types.ts diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 6ce9e70..480b5a5 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -22,7 +22,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. @@ -35,9 +35,9 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }} - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 2ffdbce..3814e7a 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -1,26 +1,25 @@ name: Node CI - on: [push] jobs: build: - runs-on: ubuntu-latest - strategy: matrix: - node-version: ['10.x', '12.x', '14.x'] + node-version: [12, 14, 16, 18] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v2-beta + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} - - name: install dependencies, build and test - run: | - npm ci - npm run build --if-present - npm test + cache: 'npm' + - name: Install dependencies + run: npm ci + - name: Transpile typescript + run: npm run build --if-present + - name: Run tests + run: npm test env: CI: true diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index 98a1adf..648763e 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -5,25 +5,27 @@ on: types: [created] jobs: - build: + build-test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 with: node-version: 14 + cache: 'npm' - run: npm ci --ignore-scripts - run: npm test publish-npm: - needs: build + needs: build-test runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 with: node-version: 14 registry-url: https://registry.npmjs.org/ + cache: 'npm' - run: npm ci --ignore-scripts - run: npm run build - run: echo "tag=latest" >> $GITHUB_ENV @@ -35,17 +37,18 @@ jobs: NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }} publish-github: - needs: build + needs: build-test runs-on: ubuntu-latest permissions: contents: read packages: write steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 with: node-version: 14 registry-url: https://npm.pkg.github.com/ + cache: 'npm' - run: npm ci --ignore-scripts - run: npm run build - run: echo "tag=latest" >> $GITHUB_ENV diff --git a/README.md b/README.md index e2bc52e..56d1c1e 100644 --- a/README.md +++ b/README.md @@ -226,20 +226,6 @@ Substitute.disableFor(fake).received(1337); fake.received().received(1337); ``` -## Strict mode -If you have `strict` set to `true` in your `tsconfig.json`, you may need to toggle off strict null checks. The framework does not currently support this. - -However, it is only needed for your test projects anyway. - -```json -{ - "compilerOptions": { - "strict": true, - "strictNullChecks": false - } -} -``` - ## Contributors ### Code Contributors diff --git a/ava.config.js b/ava.config.js new file mode 100644 index 0000000..cc81cf1 --- /dev/null +++ b/ava.config.js @@ -0,0 +1,13 @@ + +module.exports = { + files: ['spec/**/*.ts'], + typescript: { + compile: false, + rewritePaths: { + '/': 'dist/' + } + }, + cache: false, + failFast: true, + failWithoutAssertions: true +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 885b5f0..026eb5d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,118 +1,17 @@ { "name": "@fluffy-spoon/substitute", - "version": "2.0.0-beta.0", + "version": "2.0.0-beta.2", "lockfileVersion": 1, "requires": true, "dependencies": { "@ava/typescript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@ava/typescript/-/typescript-2.0.0.tgz", - "integrity": "sha512-sn+upcMk81AMrlnx/hb/9T7gCGuBfw7hi+p79NPSSQMvY2G64mOB7qRaDExiHiZfZ7FN9j7HwQeFhHZLGD/NWQ==", - "dev": true, - "requires": { - "escape-string-regexp": "^4.0.0", - "execa": "^5.0.0" - } - }, - "@babel/code-frame": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", - "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.14.5" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", - "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", - "dev": true - }, - "@babel/highlight": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", - "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.5", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@concordance/react": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@concordance/react/-/react-2.0.0.tgz", - "integrity": "sha512-huLSkUuM2/P+U0uy2WwlKuixMsTODD8p4JVQBI4VKeopkiN0C7M3N9XYVawb4M+4spN5RrO/eLhk7KoQX6nsfA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@ava/typescript/-/typescript-3.0.1.tgz", + "integrity": "sha512-/JXIUuKsvkaneaiA9ckk3ksFTqvu0mDNlChASrTe2BnDsvMbhQdPWyqQjJ9WRJWVhhs5TWn1/0Pp1G6Rv8Syrw==", "dev": true, "requires": { - "arrify": "^1.0.1" - }, - "dependencies": { - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - } + "escape-string-regexp": "^5.0.0", + "execa": "^5.1.1" } }, "@nodelib/fs.scandir": { @@ -141,37 +40,16 @@ "fastq": "^1.6.0" } }, - "@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", - "dev": true - }, - "@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", - "dev": true, - "requires": { - "defer-to-connect": "^1.0.1" - } - }, "@types/node": { - "version": "12.20.24", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.24.tgz", - "integrity": "sha512-yxDeaQIAJlMav7fH5AQqPH1u8YIuhYJXYBzxaQ4PifsU0GDO38MSdmEDeRlIxrKbC6NbEaaEHDanWb+y30U8SQ==", - "dev": true - }, - "@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", "dev": true }, "acorn": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.5.0.tgz", - "integrity": "sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", + "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", "dev": true }, "acorn-walk": { @@ -188,67 +66,26 @@ "requires": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" - } - }, - "ansi-align": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", - "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", - "dev": true, - "requires": { - "string-width": "^3.0.0" }, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } } } }, "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true }, "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.1.1.tgz", + "integrity": "sha512-qDOv24WjnYuL+wbwHdlsYZFy+cgPtrYw0Tn7GLORicQp9BkQLzrgI3Pm4VyR9ERZ41YTn7KlMPuL1n05WdZvmg==", "dev": true }, "anymatch": { @@ -273,7 +110,7 @@ "array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "integrity": "sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==", "dev": true }, "array-union": { @@ -289,79 +126,62 @@ "dev": true }, "arrify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", - "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", - "dev": true - }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-3.0.0.tgz", + "integrity": "sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw==", "dev": true }, "ava": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/ava/-/ava-3.15.0.tgz", - "integrity": "sha512-HGAnk1SHPk4Sx6plFAUkzV/XC1j9+iQhOzt4vBly18/yo0AV8Oytx7mtJd/CR8igCJ5p160N/Oo/cNJi2uSeWA==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/ava/-/ava-4.3.3.tgz", + "integrity": "sha512-9Egq/d9R74ExrWohHeqUlexjDbgZJX5jA1Wq4KCTqc3wIfpGEK79zVy4rBtofJ9YKIxs4PzhJ8BgbW5PlAYe6w==", "dev": true, "requires": { - "@concordance/react": "^2.0.0", - "acorn": "^8.0.4", - "acorn-walk": "^8.0.0", - "ansi-styles": "^5.0.0", + "acorn": "^8.7.1", + "acorn-walk": "^8.2.0", + "ansi-styles": "^6.1.0", "arrgv": "^1.0.2", - "arrify": "^2.0.1", - "callsites": "^3.1.0", - "chalk": "^4.1.0", - "chokidar": "^3.4.3", + "arrify": "^3.0.0", + "callsites": "^4.0.0", + "cbor": "^8.1.0", + "chalk": "^5.0.1", + "chokidar": "^3.5.3", "chunkd": "^2.0.1", - "ci-info": "^2.0.0", + "ci-info": "^3.3.1", "ci-parallel-vars": "^1.0.1", "clean-yaml-object": "^0.1.0", - "cli-cursor": "^3.1.0", - "cli-truncate": "^2.1.0", - "code-excerpt": "^3.0.0", + "cli-truncate": "^3.1.0", + "code-excerpt": "^4.0.0", "common-path-prefix": "^3.0.0", - "concordance": "^5.0.1", - "convert-source-map": "^1.7.0", + "concordance": "^5.0.4", "currently-unhandled": "^0.4.1", - "debug": "^4.3.1", - "del": "^6.0.0", - "emittery": "^0.8.0", - "equal-length": "^1.0.0", - "figures": "^3.2.0", - "globby": "^11.0.1", - "ignore-by-default": "^2.0.0", - "import-local": "^3.0.2", - "indent-string": "^4.0.0", + "debug": "^4.3.4", + "del": "^6.1.1", + "emittery": "^0.11.0", + "figures": "^4.0.1", + "globby": "^13.1.1", + "ignore-by-default": "^2.1.0", + "indent-string": "^5.0.0", "is-error": "^2.2.2", "is-plain-object": "^5.0.0", "is-promise": "^4.0.0", - "lodash": "^4.17.20", - "matcher": "^3.0.0", - "md5-hex": "^3.0.1", - "mem": "^8.0.0", + "matcher": "^5.0.0", + "mem": "^9.0.2", "ms": "^2.1.3", - "ora": "^5.2.0", - "p-event": "^4.2.0", - "p-map": "^4.0.0", - "picomatch": "^2.2.2", - "pkg-conf": "^3.1.0", - "plur": "^4.0.0", + "p-event": "^5.0.1", + "p-map": "^5.4.0", + "picomatch": "^2.3.1", + "pkg-conf": "^4.0.0", + "plur": "^5.1.0", "pretty-ms": "^7.0.1", - "read-pkg": "^5.2.0", "resolve-cwd": "^3.0.0", "slash": "^3.0.0", - "source-map-support": "^0.5.19", - "stack-utils": "^2.0.3", - "strip-ansi": "^6.0.0", - "supertap": "^2.0.0", + "stack-utils": "^2.0.5", + "strip-ansi": "^7.0.1", + "supertap": "^3.0.1", "temp-dir": "^2.0.0", - "trim-off-newlines": "^1.0.1", - "update-notifier": "^5.0.1", - "write-file-atomic": "^3.0.3", - "yargs": "^16.2.0" + "write-file-atomic": "^4.0.1", + "yargs": "^17.5.1" } }, "balanced-match": { @@ -370,59 +190,18 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true - }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true }, - "bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, "blueimp-md5": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.18.0.tgz", - "integrity": "sha512-vE52okJvzsVWhcgUHOv+69OG3Mdg151xyn41aVQN/5W5S+S43qZhxECtYLAEHMSFWX6Mv5IZrzj3T5+JqXfj5Q==", + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz", + "integrity": "sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==", "dev": true }, - "boxen": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.0.1.tgz", - "integrity": "sha512-49VBlw+PrWEF51aCmy7QIteYPIFZxSpvqBdP/2itCPPlJ49kj9zg/XPRFrdkne2W+CfwXUls8exMvu1RysZpKA==", - "dev": true, - "requires": { - "ansi-align": "^3.0.0", - "camelcase": "^6.2.0", - "chalk": "^4.1.0", - "cli-boxes": "^2.2.1", - "string-width": "^4.2.0", - "type-fest": "^0.20.2", - "widest-line": "^3.1.0", - "wrap-ansi": "^7.0.0" - }, - "dependencies": { - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - } - } - }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -442,91 +221,31 @@ "fill-range": "^7.0.1" } }, - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "callsites": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-4.0.0.tgz", + "integrity": "sha512-y3jRROutgpKdz5vzEhWM34TidDU8vkJppF8dszITeb1PQmSqV3DTxyV8G/lyO/DNvtE1YTedehmw9MPZsCBHxQ==", "dev": true }, - "cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "cbor": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-8.1.0.tgz", + "integrity": "sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==", "dev": true, "requires": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "dependencies": { - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true - } + "nofilter": "^3.1.0" } }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", - "dev": true - }, "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - } - } + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.1.0.tgz", + "integrity": "sha512-56zD4khRTBoIyzUYAFgDDaPhUMN/fC/rySe6aZGqbj/VWiU2eI3l6ZLOtYGFZAV5v02mwPjtpzlrOveJiz5eZQ==", + "dev": true }, "chokidar": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", - "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, "requires": { "anymatch": "~3.1.2", @@ -546,9 +265,9 @@ "dev": true }, "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.5.0.tgz", + "integrity": "sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==", "dev": true }, "ci-parallel-vars": { @@ -566,73 +285,77 @@ "clean-yaml-object": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/clean-yaml-object/-/clean-yaml-object-0.1.0.tgz", - "integrity": "sha1-Y/sRDcLOGoTcIfbZM0h20BCui2g=", - "dev": true - }, - "cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", - "dev": true - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-spinners": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.0.tgz", - "integrity": "sha512-t+4/y50K/+4xcCRosKkA7W4gTr1MySvLV0q+PxmG7FJ5g+66ChKurYjxBCjHggHH3HA5Hh9cy+lcUGWDqVH+4Q==", + "integrity": "sha512-3yONmlN9CSAkzNwnRCiJQ7Q2xK5mWuEfL3PuTZcAUzhObbXsfsnMptJzXwz93nc5zn9V9TwCVMmV7w4xsm43dw==", "dev": true }, "cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", + "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", "dev": true, "requires": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" + "slice-ansi": "^5.0.0", + "string-width": "^5.0.0" } }, "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "requires": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" - } - }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, - "clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true, - "requires": { - "mimic-response": "^1.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + } } }, "code-excerpt": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/code-excerpt/-/code-excerpt-3.0.0.tgz", - "integrity": "sha512-VHNTVhd7KsLGOqfX3SyeO8RyYPMp1GJOg194VITk04WMYCv4plV68YWe6TJZxd9MhobjtpMRnVky01gqZsalaw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/code-excerpt/-/code-excerpt-4.0.0.tgz", + "integrity": "sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==", "dev": true, "requires": { - "convert-to-spaces": "^1.0.1" + "convert-to-spaces": "^2.0.1" } }, "color-convert": { @@ -659,7 +382,7 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, "concordance": { @@ -678,33 +401,10 @@ "well-known-symbols": "^2.0.0" } }, - "configstore": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", - "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", - "dev": true, - "requires": { - "dot-prop": "^5.2.0", - "graceful-fs": "^4.1.2", - "make-dir": "^3.0.0", - "unique-string": "^2.0.0", - "write-file-atomic": "^3.0.0", - "xdg-basedir": "^4.0.0" - } - }, - "convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, "convert-to-spaces": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/convert-to-spaces/-/convert-to-spaces-1.0.2.tgz", - "integrity": "sha1-fj5Iu+bZl7FBfdyihoIEtNPYVxU=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/convert-to-spaces/-/convert-to-spaces-2.0.1.tgz", + "integrity": "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==", "dev": true }, "cross-spawn": { @@ -718,16 +418,10 @@ "which": "^2.0.1" } }, - "crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", - "dev": true - }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "integrity": "sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng==", "dev": true, "requires": { "array-find-index": "^1.0.1" @@ -743,9 +437,9 @@ } }, "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "requires": { "ms": "2.1.2" @@ -759,40 +453,10 @@ } } }, - "decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, - "requires": { - "mimic-response": "^1.0.0" - } - }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true - }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true, - "requires": { - "clone": "^1.0.2" - } - }, - "defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", - "dev": true - }, "del": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", - "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", + "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", "dev": true, "requires": { "globby": "^11.0.1", @@ -803,6 +467,31 @@ "p-map": "^4.0.0", "rimraf": "^3.0.2", "slash": "^3.0.0" + }, + "dependencies": { + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + } } }, "dir-glob": { @@ -814,73 +503,34 @@ "path-type": "^4.0.0" } }, - "dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "requires": { - "is-obj": "^2.0.0" - } - }, - "duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, "emittery": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", - "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.11.0.tgz", + "integrity": "sha512-S/7tzL6v5i+4iJd627Nhv9cLFIo5weAIlGccqJFpnBoDB8U1TF2k5tez4J/QNuxyyhWuFqHg1L84Kd3m7iXg6g==", "dev": true }, "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "equal-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/equal-length/-/equal-length-1.0.1.tgz", - "integrity": "sha1-IcoRLUirJLTh5//A5TOdMf38J0w=", - "dev": true - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true }, - "escape-goat": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", - "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", - "dev": true - }, "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", "dev": true }, "esprima": { @@ -919,9 +569,9 @@ "dev": true }, "fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", @@ -941,20 +591,13 @@ } }, "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/figures/-/figures-4.0.1.tgz", + "integrity": "sha512-rElJwkA/xS04Vfg+CaZodpso7VqBknOYbzi6I76hI4X80RUjkSxO2oAyPmGbuXUppywjqndOrQDl817hDnI++w==", "dev": true, "requires": { - "escape-string-regexp": "^1.0.5" - }, - "dependencies": { - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - } + "escape-string-regexp": "^5.0.0", + "is-unicode-supported": "^1.2.0" } }, "fill-range": { @@ -967,19 +610,19 @@ } }, "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", "dev": true, "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" } }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, "fsevents": { @@ -989,12 +632,6 @@ "dev": true, "optional": true }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -1008,15 +645,15 @@ "dev": true }, "glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } @@ -1030,96 +667,31 @@ "is-glob": "^4.0.1" } }, - "global-dirs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", - "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", - "dev": true, - "requires": { - "ini": "2.0.0" - } - }, "globby": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", - "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.2.tgz", + "integrity": "sha512-LKSDZXToac40u8Q1PQtZihbNdTYSNMuWe+K5l+oa6KgDzSvVrHXlJy40hUP522RjAIoNLJYBJi7ow+rbFpIhHQ==", "dev": true, "requires": { - "array-union": "^2.1.0", "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", - "slash": "^3.0.0" - } - }, - "got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "dev": true, - "requires": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" + "fast-glob": "^3.2.11", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^4.0.0" }, "dependencies": { - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } + "slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true } } }, "graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "has-yarn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", - "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", - "dev": true - }, - "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", "dev": true }, "human-signals": { @@ -1128,56 +700,34 @@ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true - }, "ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", "dev": true }, "ignore-by-default": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-2.0.0.tgz", - "integrity": "sha512-+mQSgMRiFD3L3AOxLYOCxjIq4OnAmo5CIuC+lj5ehCJcPtV++QacEV7FdpzvYxH6DaOySWzQU6RR0lPLy37ckA==", - "dev": true - }, - "import-lazy": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-2.1.0.tgz", + "integrity": "sha512-yiWd4GVmJp0Q6ghmM2B/V3oZGRmjrKLXvHR3TE1nfoXsmoggllfZUQe74EN0fJdPFZu2NIvNdrMMLm3OsV7Ohw==", "dev": true }, - "import-local": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", - "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", - "dev": true, - "requires": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - } - }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true }, "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", "dev": true }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dev": true, "requires": { "once": "^1.3.0", @@ -1190,24 +740,12 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, - "ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "dev": true - }, "irregular-plurals": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.3.0.tgz", "integrity": "sha512-MVBLKUTangM3EfRPFROhmWQQKRDsrgI83J8GS3jXy+OwYqiR2/aoWndYQ5416jLE3uaGgLH7ncme3X9y09gZ3g==", "dev": true }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -1217,24 +755,6 @@ "binary-extensions": "^2.0.0" } }, - "is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, - "requires": { - "ci-info": "^2.0.0" - } - }, - "is-core-module": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.6.0.tgz", - "integrity": "sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, "is-error": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/is-error/-/is-error-2.2.2.tgz", @@ -1244,58 +764,30 @@ "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true }, "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", "dev": true }, "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "requires": { "is-extglob": "^2.1.1" } }, - "is-installed-globally": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", - "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", - "dev": true, - "requires": { - "global-dirs": "^3.0.0", - "is-path-inside": "^3.0.2" - } - }, - "is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true - }, - "is-npm": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", - "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", - "dev": true - }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, - "is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true - }, "is-path-cwd": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", @@ -1326,40 +818,22 @@ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, "is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true - }, - "is-yarn-global": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", - "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", "dev": true }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, "js-string-escape": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", - "integrity": "sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8=", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "integrity": "sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==", "dev": true }, "js-yaml": { @@ -1372,68 +846,19 @@ "esprima": "^4.0.0" } }, - "json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", - "dev": true - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "dev": true, - "requires": { - "json-buffer": "3.0.0" - } - }, - "latest-version": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", - "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", - "dev": true, - "requires": { - "package-json": "^6.3.0" - } - }, - "lines-and-columns": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", - "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", - "dev": true - }, "load-json-file": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", - "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.15", - "parse-json": "^4.0.0", - "pify": "^4.0.1", - "strip-bom": "^3.0.0", - "type-fest": "^0.3.0" - } + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-7.0.1.tgz", + "integrity": "sha512-Gnxj3ev3mB5TkVBGad0JM6dmLiQL+o0t23JPBZ9sd+yvSLk05mFoqKBw5N8gbbkU4TNXyqCgIrl/VM17OgUIgQ==", + "dev": true }, "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.1.1.tgz", + "integrity": "sha512-vJXaRMJgRVD3+cUZs3Mncj2mxpt5mP0EmNOsxRSZRMlbqjvxzDEOIUWXGmavo0ZC9+tNZCBLQ66reA11nbpHZg==", "dev": true, "requires": { - "p-locate": "^4.1.0" + "p-locate": "^6.0.0" } }, "lodash": { @@ -1442,22 +867,6 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - } - }, - "lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true - }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -1467,23 +876,6 @@ "yallist": "^4.0.0" } }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, "map-age-cleaner": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", @@ -1494,12 +886,12 @@ } }, "matcher": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", - "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-5.0.0.tgz", + "integrity": "sha512-s2EMBOWtXFc8dgqvoAzKJXxNHibcdJMV0gwqKUaw9E2JBJuGUK7DrNKrA6g/i+v72TT16+6sVm5mS3thaMLQUw==", "dev": true, "requires": { - "escape-string-regexp": "^4.0.0" + "escape-string-regexp": "^5.0.0" } }, "md5-hex": { @@ -1512,19 +904,19 @@ } }, "mem": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/mem/-/mem-8.1.1.tgz", - "integrity": "sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/mem/-/mem-9.0.2.tgz", + "integrity": "sha512-F2t4YIv9XQUBHt6AOJ0y7lSmP1+cY7Fm1DRh9GClTGzKST7UWLMx6ly9WZdLH/G/ppM5RL4MlQfRT71ri9t19A==", "dev": true, "requires": { "map-age-cleaner": "^0.1.3", - "mimic-fn": "^3.1.0" + "mimic-fn": "^4.0.0" }, "dependencies": { "mimic-fn": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz", - "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", "dev": true } } @@ -1542,13 +934,13 @@ "dev": true }, "micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "requires": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" + "braces": "^3.0.2", + "picomatch": "^2.3.1" } }, "mimic-fn": { @@ -1557,52 +949,26 @@ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, - "mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true - }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "requires": { "brace-expansion": "^1.1.7" } }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, "ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } + "nofilter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz", + "integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==", + "dev": true }, "normalize-path": { "version": "3.0.0", @@ -1610,12 +976,6 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, - "normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", - "dev": true - }, "npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -1628,7 +988,7 @@ "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, "requires": { "wrappy": "1" @@ -1643,121 +1003,74 @@ "mimic-fn": "^2.1.0" } }, - "ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "requires": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - } - }, - "p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", - "dev": true - }, "p-defer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "integrity": "sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==", "dev": true }, "p-event": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/p-event/-/p-event-4.2.0.tgz", - "integrity": "sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-5.0.1.tgz", + "integrity": "sha512-dd589iCQ7m1L0bmC5NLlVYfy3TbBEsMUfWx9PyAgPeIcFZ/E2yaTZ4Rz4MiBmmJShviiftHVXOqfnfzJ6kyMrQ==", "dev": true, "requires": { - "p-timeout": "^3.1.0" + "p-timeout": "^5.0.2" } }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true - }, "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", "dev": true, "requires": { - "p-try": "^2.0.0" + "yocto-queue": "^1.0.0" } }, "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", "dev": true, "requires": { - "p-limit": "^2.2.0" + "p-limit": "^4.0.0" } }, "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "p-timeout": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", - "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", - "dev": true, - "requires": { - "p-finally": "^1.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "package-json": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", - "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-5.5.0.tgz", + "integrity": "sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==", "dev": true, "requires": { - "got": "^9.6.0", - "registry-auth-token": "^4.0.0", - "registry-url": "^5.0.0", - "semver": "^6.2.0" + "aggregate-error": "^4.0.0" }, "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true + "aggregate-error": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz", + "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", + "dev": true, + "requires": { + "clean-stack": "^4.0.0", + "indent-string": "^5.0.0" + } + }, + "clean-stack": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.2.0.tgz", + "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", + "dev": true, + "requires": { + "escape-string-regexp": "5.0.0" + } } } }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } + "p-timeout": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-5.1.0.tgz", + "integrity": "sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==", + "dev": true }, "parse-ms": { "version": "2.1.0", @@ -1766,15 +1079,15 @@ "dev": true }, "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", "dev": true }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true }, "path-key": { @@ -1783,12 +1096,6 @@ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -1796,87 +1103,30 @@ "dev": true }, "picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", - "dev": true - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, "pkg-conf": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-3.1.0.tgz", - "integrity": "sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ==", - "dev": true, - "requires": { - "find-up": "^3.0.0", - "load-json-file": "^5.2.0" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - } - } - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-4.0.0.tgz", + "integrity": "sha512-7dmgi4UY4qk+4mj5Cd8v/GExPo0K+SlY+hulOSdfZ/T6jVH6//y7NtzZo5WrfhDBxuQ0jCa7fLZmNaNh7EWL/w==", "dev": true, "requires": { - "find-up": "^4.0.0" + "find-up": "^6.0.0", + "load-json-file": "^7.0.0" } }, "plur": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/plur/-/plur-4.0.0.tgz", - "integrity": "sha512-4UGewrYgqDFw9vV6zNV+ADmPAUAfJPKtGvb/VdpQAx25X5f3xXdGdyOEVFwkl8Hl/tl7+xbeHqSEM+D5/TirUg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/plur/-/plur-5.1.0.tgz", + "integrity": "sha512-VP/72JeXqak2KiOzjgKtQen5y3IZHn+9GOuLDafPv0eXa47xq0At93XahYBs26MsifCQ4enGKwbjBTKgb9QJXg==", "dev": true, "requires": { - "irregular-plurals": "^3.2.0" + "irregular-plurals": "^3.3.0" } }, - "prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", - "dev": true - }, "pretty-ms": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz", @@ -1886,94 +1136,12 @@ "parse-ms": "^2.1.0" } }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "pupa": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", - "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", - "dev": true, - "requires": { - "escape-goat": "^2.0.0" - } - }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - } - } - }, - "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "dependencies": { - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true - } - } - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, "readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -1983,40 +1151,12 @@ "picomatch": "^2.2.1" } }, - "registry-auth-token": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", - "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==", - "dev": true, - "requires": { - "rc": "^1.2.8" - } - }, - "registry-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", - "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", - "dev": true, - "requires": { - "rc": "^1.2.8" - } - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true }, - "resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "dev": true, - "requires": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - } - }, "resolve-cwd": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", @@ -2032,25 +1172,6 @@ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true }, - "responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true, - "requires": { - "lowercase-keys": "^1.0.0" - } - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -2075,38 +1196,15 @@ "queue-microtask": "^1.2.2" } }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, "requires": { "lru-cache": "^6.0.0" } }, - "semver-diff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", - "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", - "dev": true, - "requires": { - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, "serialize-error": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", @@ -2114,14 +1212,6 @@ "dev": true, "requires": { "type-fest": "^0.13.1" - }, - "dependencies": { - "type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "dev": true - } } }, "shebang-command": { @@ -2140,9 +1230,9 @@ "dev": true }, "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, "slash": { @@ -2152,85 +1242,25 @@ "dev": true }, "slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - } - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-support": { - "version": "0.5.20", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.20.tgz", - "integrity": "sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", "dev": true, "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" } }, - "spdx-license-ids": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", - "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", - "dev": true - }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, "stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", "dev": true, "requires": { "escape-string-regexp": "^2.0.0" @@ -2245,80 +1275,41 @@ } }, "string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, "requires": { - "safe-buffer": "~5.2.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" } }, "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", "dev": true, "requires": { - "ansi-regex": "^5.0.0" + "ansi-regex": "^6.0.1" } }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, "strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - }, "supertap": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supertap/-/supertap-2.0.0.tgz", - "integrity": "sha512-jRzcXlCeDYvKoZGA5oRhYyR3jUIYu0enkSxtmAgHRlD7HwrovTpH4bDSi0py9FtuA8si9cW/fKommJHuaoDHJA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/supertap/-/supertap-3.0.1.tgz", + "integrity": "sha512-u1ZpIBCawJnO+0QePsEiOknOfCRq0yERxiAchT0i4li0WHNUJbf0evXXSXOcCAR4M8iMDoajXYmstm/qO81Isw==", "dev": true, "requires": { - "arrify": "^2.0.1", - "indent-string": "^4.0.0", - "js-yaml": "^3.14.0", + "indent-string": "^5.0.0", + "js-yaml": "^3.14.1", "serialize-error": "^7.0.1", - "strip-ansi": "^6.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" + "strip-ansi": "^7.0.1" } }, "temp-dir": { @@ -2330,13 +1321,7 @@ "time-zone": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/time-zone/-/time-zone-1.0.0.tgz", - "integrity": "sha1-mcW/VZWJZq9tBtg73zgA3IL67F0=", - "dev": true - }, - "to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "integrity": "sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==", "dev": true }, "to-regex-range": { @@ -2348,98 +1333,18 @@ "is-number": "^7.0.0" } }, - "trim-off-newlines": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz", - "integrity": "sha1-n5up2e+odkw4dpi8v+sshI8RrbM=", - "dev": true - }, "type-fest": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", - "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", "dev": true }, - "typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "requires": { - "is-typedarray": "^1.0.0" - } - }, "typescript": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.3.tgz", - "integrity": "sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==", - "dev": true - }, - "unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "dev": true, - "requires": { - "crypto-random-string": "^2.0.0" - } - }, - "update-notifier": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", - "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", - "dev": true, - "requires": { - "boxen": "^5.0.0", - "chalk": "^4.1.0", - "configstore": "^5.0.1", - "has-yarn": "^2.1.0", - "import-lazy": "^2.1.0", - "is-ci": "^2.0.0", - "is-installed-globally": "^0.4.0", - "is-npm": "^5.0.0", - "is-yarn-global": "^0.3.0", - "latest-version": "^5.1.0", - "pupa": "^2.1.1", - "semver": "^7.3.4", - "semver-diff": "^3.1.1", - "xdg-basedir": "^4.0.0" - } - }, - "url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", - "dev": true, - "requires": { - "prepend-http": "^2.0.0" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", + "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", "dev": true }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", - "dev": true, - "requires": { - "defaults": "^1.0.3" - } - }, "well-known-symbols": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/well-known-symbols/-/well-known-symbols-2.0.0.tgz", @@ -2455,15 +1360,6 @@ "isexe": "^2.0.0" } }, - "widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", - "dev": true, - "requires": { - "string-width": "^4.0.0" - } - }, "wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -2475,6 +1371,12 @@ "strip-ansi": "^6.0.0" }, "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -2483,33 +1385,57 @@ "requires": { "color-convert": "^2.0.1" } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } } } }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, "write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, "requires": { "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" + "signal-exit": "^3.0.7" } }, - "xdg-basedir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", - "dev": true - }, "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -2523,24 +1449,70 @@ "dev": true }, "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "version": "17.6.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.0.tgz", + "integrity": "sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g==", "dev": true, "requires": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.0", + "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yargs-parser": "^21.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + } } }, "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true + }, + "yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", "dev": true } } diff --git a/package.json b/package.json index 53ba734..c7c3b1e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@fluffy-spoon/substitute", - "version": "2.0.0-beta.1", + "version": "2.0.0-beta.2", "description": "TypeScript port of NSubstitute, which aims to provide a much more fluent mocking opportunity for strong-typed languages", "license": "MIT", "funding": { @@ -34,31 +34,20 @@ "engines": { "node": ">=10" }, - "main": "dist/src/index.js", - "typings": "./dist/src/index.d.ts", + "main": "dist/index.js", + "typings": "./dist/index.d.ts", "files": [ - "dist/src/**/*" + "dist/**/*" ], "scripts": { - "test": "tsc --sourceMap && ava", - "build": "rm -rf dist && tsc" + "build": "rm -rf dist && tsc", + "test": "npm run build -- -p spec && ava" }, "dependencies": {}, "devDependencies": { - "@ava/typescript": "^2.0.0", - "@types/node": "^12.20.24", - "ava": "^3.15.0", - "typescript": "^4.4.3" - }, - "ava": { - "typescript": { - "rewritePaths": { - "/": "dist/" - }, - "compile": false - }, - "cache": false, - "failFast": true, - "failWithoutAssertions": true + "@ava/typescript": "^3.0.1", + "@types/node": "^12.20.55", + "ava": "^4.3.3", + "typescript": "^4.8.4" } -} +} \ No newline at end of file diff --git a/spec/ClearSubstitute.spec.ts b/spec/ClearSubstitute.spec.ts index b587d4c..0dad128 100644 --- a/spec/ClearSubstitute.spec.ts +++ b/spec/ClearSubstitute.spec.ts @@ -1,7 +1,6 @@ import test from 'ava' import { Substitute, SubstituteOf } from '../src' -import { SubstituteBase } from '../src/SubstituteBase' import { SubstituteNode } from '../src/SubstituteNode' interface Calculator { @@ -12,7 +11,7 @@ interface Calculator { } type InstanceReturningSubstitute = SubstituteOf & { - [SubstituteBase.instance]: Substitute + [SubstituteNode.instance]: SubstituteNode } test('clears everything on a substitute', t => { @@ -21,8 +20,8 @@ test('clears everything on a substitute', t => { calculator.received().add(1, 1) calculator.clearSubstitute() - t.is(calculator[Substitute.instance].recorder.records.size, 0) - t.is(calculator[Substitute.instance].recorder.indexedRecords.size, 0) + t.is(calculator[SubstituteNode.instance].recorder.records.size, 0) + t.is(calculator[SubstituteNode.instance].recorder.indexedRecords.size, 0) t.throws(() => calculator.received().add(1, 1)) @@ -31,8 +30,8 @@ test('clears everything on a substitute', t => { calculator.received().add(1, 1) calculator.clearSubstitute('all') - t.is(calculator[Substitute.instance].recorder.records.size, 0) - t.is(calculator[Substitute.instance].recorder.indexedRecords.size, 0) + t.is(calculator[SubstituteNode.instance].recorder.records.size, 0) + t.is(calculator[SubstituteNode.instance].recorder.indexedRecords.size, 0) t.throws(() => calculator.received().add(1, 1)) }) @@ -43,11 +42,11 @@ test('clears received calls on a substitute', t => { calculator.add(1, 1).returns(2) calculator.clearSubstitute('receivedCalls') - t.is(calculator[Substitute.instance].recorder.records.size, 2) - t.is(calculator[Substitute.instance].recorder.indexedRecords.size, 2) + t.is(calculator[SubstituteNode.instance].recorder.records.size, 2) + t.is(calculator[SubstituteNode.instance].recorder.indexedRecords.size, 2) t.throws(() => calculator.received().add(1, 1)) - t.is(calculator.add(1, 1), 2) + t.is(2, calculator.add(1, 1)) }) test('clears return values on a substitute', t => { @@ -56,10 +55,10 @@ test('clears return values on a substitute', t => { calculator.add(1, 1).returns(2) calculator.clearSubstitute('substituteValues') - t.is(calculator[Substitute.instance].recorder.records.size, 2) - t.is(calculator[Substitute.instance].recorder.indexedRecords.size, 2) + t.is(calculator[SubstituteNode.instance].recorder.records.size, 2) + t.is(calculator[SubstituteNode.instance].recorder.indexedRecords.size, 2) t.notThrows(() => calculator.received().add(1, 1)) // @ts-expect-error - t.true(calculator.add(1, 1)[SubstituteBase.instance] instanceof SubstituteNode) + t.true(calculator.add(1, 1)[SubstituteNode.instance] instanceof SubstituteNode) }) \ No newline at end of file diff --git a/spec/RecordedArguments.spec.ts b/spec/RecordedArguments.spec.ts index d661585..103efb3 100644 --- a/spec/RecordedArguments.spec.ts +++ b/spec/RecordedArguments.spec.ts @@ -20,24 +20,24 @@ test('records values and classifies them correctly', t => { const emptyArguments = RecordedArguments.from([]) t.deepEqual(emptyArguments.value, []) t.is(emptyArguments.argumentsClass, 'plain') - t.is(emptyArguments.hasNoArguments, false) + t.is(emptyArguments.hasArguments(), true) const primitivesOnlyArguments = RecordedArguments.from([1, 'Substitute', false, testSymbol, undefined, null, testFunc, {}]) t.deepEqual(primitivesOnlyArguments.value, [1, 'Substitute', false, testSymbol, undefined, null, testFunc, {}]) t.is(primitivesOnlyArguments.argumentsClass, 'plain') - t.is(primitivesOnlyArguments.hasNoArguments, false) + t.is(primitivesOnlyArguments.hasArguments(), true) const anyArg = Arg.any('any') const withSingleArgumentArguments = RecordedArguments.from([1, 'Substitute', false, testSymbol, undefined, null, testFunc, {}, anyArg]) t.deepEqual(withSingleArgumentArguments.value, [1, 'Substitute', false, testSymbol, undefined, null, testFunc, {}, anyArg]) t.is(withSingleArgumentArguments.argumentsClass, 'with-predicate') - t.is(withSingleArgumentArguments.hasNoArguments, false) + t.is(withSingleArgumentArguments.hasArguments(), true) const allArg = Arg.all() const allArgumentArguments = RecordedArguments.from([allArg]) t.deepEqual(allArgumentArguments.value, [allArg]) t.is(allArgumentArguments.argumentsClass, 'wildcard') - t.is(allArgumentArguments.hasNoArguments, false) + t.is(allArgumentArguments.hasArguments(), true) }) test('creates a valid instance for no arguments', t => { @@ -45,7 +45,7 @@ test('creates a valid instance for no arguments', t => { t.is(args.value, undefined) t.is(args.argumentsClass, undefined) - t.is(args.hasNoArguments, true) + t.is(args.hasArguments(), false) }) test('sorts correctly objects with RecordedArguments', t => { diff --git a/spec/Recorder.spec.ts b/spec/Recorder.spec.ts index 0526185..348a0b9 100644 --- a/spec/Recorder.spec.ts +++ b/spec/Recorder.spec.ts @@ -16,7 +16,7 @@ const otherNode = nodeFactory('otherNode') const otherNodeDifferentInstance = nodeFactory('otherNode') test('adds all records once only', t => { - const recorder = new Recorder() + const recorder = Recorder.withIdentityProperty('key') recorder.addRecord(node) recorder.addRecord(node) recorder.addRecord(otherNode) @@ -28,7 +28,7 @@ test('adds all records once only', t => { }) test('indexes all records correctly', t => { - const recorder = new Recorder() + const recorder = Recorder.withIdentityProperty('key') recorder.addIndexedRecord(node) recorder.addIndexedRecord(node) recorder.addIndexedRecord(otherNode) @@ -40,15 +40,15 @@ test('indexes all records correctly', t => { const nodeSet = recorder.indexedRecords.get(node.key) t.true(nodeSet instanceof RecordsSet) - t.deepEqual([...nodeSet], [node]) + t.deepEqual([...nodeSet!], [node]) const otherNodeSet = recorder.indexedRecords.get(otherNode.key) t.true(otherNodeSet instanceof RecordsSet) - t.deepEqual([...otherNodeSet], [otherNode, otherNodeDifferentInstance]) + t.deepEqual([...otherNodeSet!], [otherNode, otherNodeDifferentInstance]) }) test('returns all sibling nodes', t => { - const recorder = new Recorder() + const recorder = Recorder.withIdentityProperty('key') recorder.addIndexedRecord(node) recorder.addIndexedRecord(otherNode) recorder.addIndexedRecord(otherNodeDifferentInstance) @@ -64,14 +64,14 @@ test('returns all sibling nodes', t => { }) test('clears recorded nodes by a given filter function', t => { - const recorder = new Recorder() + const recorder = Recorder.withIdentityProperty('key') recorder.addIndexedRecord(node) recorder.addIndexedRecord(otherNode) recorder.addIndexedRecord(otherNodeDifferentInstance) recorder.clearRecords(n => n.key === otherNode.key) t.deepEqual([...recorder.records], [node]) - t.deepEqual([...recorder.indexedRecords.get(node.key)], [node]) + t.deepEqual([...recorder.indexedRecords.get(node.key)!], [node]) t.is(recorder.indexedRecords.get(otherNode.key), undefined) recorder.clearRecords(_ => true) diff --git a/spec/RecordsSet.spec.ts b/spec/RecordsSet.spec.ts index 2f90868..62b83ae 100644 --- a/spec/RecordsSet.spec.ts +++ b/spec/RecordsSet.spec.ts @@ -1,4 +1,4 @@ -import test, { ExecutionContext, Macro } from 'ava' +import test, { ExecutionContext } from 'ava' import { RecordsSet } from '../src/RecordsSet' @@ -7,7 +7,7 @@ function* dataArrayGenerator() { yield* dataArray } const inputData = [dataArray, dataArray[Symbol.iterator](), new Set(dataArray), dataArrayGenerator(), new RecordsSet(dataArray)] -const macro: Macro = (t: ExecutionContext, ...inputData: Iterable[]): void => { +const macro = test.macro((t: ExecutionContext, ...inputData: Iterable[]): void => { inputData.forEach(input => { const set = new RecordsSet(input) @@ -27,7 +27,7 @@ const macro: Macro = (t: ExecutionContext, ...inputData: Iterable set.clear() t.is(set.size, 0) }) -} +}) test('behaves like a native Set object', macro, ...inputData) @@ -35,18 +35,18 @@ test('applies a filter function everytime the iterator is consumed', t => { const set = new RecordsSet([1, 2, 3]) const setWithFilter = set.filter(number => number !== 2) - t.deepEqual([...set], [1, 2, 3]) - t.deepEqual([...setWithFilter], [1, 3]) - t.deepEqual([...setWithFilter], [1, 3]) + t.deepEqual([...set], [1, 2, 3]) + t.deepEqual([...setWithFilter], [1, 3]) + t.deepEqual([...setWithFilter], [1, 3]) }) test('applies a map function everytime the iterator is consumed', t => { const set = new RecordsSet([1, 2, 3]) const setWithMap = set.map(number => number.toString()) - t.deepEqual([...set], [1, 2, 3]) - t.deepEqual([...setWithMap], ['1', '2', '3']) - t.deepEqual([...setWithMap], ['1', '2', '3']) + t.deepEqual([...set], [1, 2, 3]) + t.deepEqual([...setWithMap], ['1', '2', '3']) + t.deepEqual([...setWithMap], ['1', '2', '3']) }) test('applies and preserves the order of filter and map functions everytime the iterator is consumed', t => { @@ -55,12 +55,12 @@ test('applies and preserves the order of filter and map functions everytime the const setWithFilterAndMap = setWithFilter.map(number => number.toString()) const setWithFilterMapAndAnotherFilter = setWithFilterAndMap.filter(string => string === '3') - t.deepEqual([...set], [1, 2, 3]) - t.deepEqual([...setWithFilter], [1, 3]) - t.deepEqual([...setWithFilterAndMap], ['1', '3']) - t.deepEqual([...setWithFilterMapAndAnotherFilter], ['3']) + t.deepEqual([...set], [1, 2, 3]) + t.deepEqual([...setWithFilter], [1, 3]) + t.deepEqual([...setWithFilterAndMap], ['1', '3']) + t.deepEqual([...setWithFilterMapAndAnotherFilter], ['3']) - t.deepEqual([...setWithFilter], [1, 3]) - t.deepEqual([...setWithFilterAndMap], ['1', '3']) - t.deepEqual([...setWithFilterMapAndAnotherFilter], ['3']) + t.deepEqual([...setWithFilter], [1, 3]) + t.deepEqual([...setWithFilterAndMap], ['1', '3']) + t.deepEqual([...setWithFilterMapAndAnotherFilter], ['3']) }) \ No newline at end of file diff --git a/spec/regression/Arguments.spec.ts b/spec/regression/Arguments.spec.ts index d471db0..a04e5d2 100644 --- a/spec/regression/Arguments.spec.ts +++ b/spec/regression/Arguments.spec.ts @@ -18,8 +18,8 @@ test('should match any argument(s) using Arg.all', t => { t.true(Arg.all().matches(['string'])) t.true(Arg.all().matches([true])) t.true(Arg.all().matches([false])) - t.true(Arg.all().matches(null)) - t.true(Arg.all().matches(undefined)) + t.true(Arg.all().matches([null])) + t.true(Arg.all().matches([undefined])) t.true(Arg.all().matches([1, 2])) t.true(Arg.all().matches(['string1', 'string2'])) }) @@ -74,7 +74,7 @@ test('should match the type of the argument using Arg.any', t => { t.false((>Arg.any('string')).matches(1)) t.false((>Arg.any('number')).matches('string')) - t.false(Arg.any('boolean').matches(null)) + t.false((>Arg.any('boolean')).matches(null)) t.false((>Arg.any('object')).matches('foo')) t.false((>Arg.any('array')).matches('bar')) t.false((>Arg.any('function')).matches('foo')) diff --git a/spec/regression/index.test.ts b/spec/regression/index.test.ts index 1ea0105..6a5aff0 100644 --- a/spec/regression/index.test.ts +++ b/spec/regression/index.test.ts @@ -1,7 +1,6 @@ import test from 'ava' -import { Substitute, Arg } from '../../src' -import { OmitProxyMethods, ObjectSubstitute } from '../../src/Transformations' +import { Substitute, Arg, SubstituteOf } from '../../src' class Dummy { @@ -34,12 +33,12 @@ export class Example { } bar(a: number, b?: number): number { - return a + b || 0 + return a + (b ?? 0) } } let instance: Example -let substitute: ObjectSubstitute, Example> +let substitute: SubstituteOf function initialize() { instance = new Example() @@ -69,21 +68,26 @@ test('class with method called \'received\' can be used for call count verificat test('class string field set received', t => { initialize() - substitute.v = undefined - substitute.v = null - substitute.v = 'hello' - substitute.v = 'hello' - substitute.v = 'world' + const runLogic = (example: Example) => { + example.v = undefined + example.v = null + example.v = 'hello' + example.v = 'hello' + example.v = 'world' + } + + runLogic(substitute) + t.notThrows(() => substitute.received().v = 'hello') t.notThrows(() => substitute.received(5).v = Arg.any()) t.notThrows(() => substitute.received().v = Arg.any()) t.notThrows(() => substitute.received(2).v = 'hello') - t.notThrows(() => substitute.received(2).v = Arg.is(x => x && x.indexOf('ll') > -1)) + t.notThrows(() => substitute.received(2).v = Arg.is(x => typeof x === 'string' && x.indexOf('ll') > -1)) t.throws(() => substitute.received(2).v = Arg.any()) t.throws(() => substitute.received(1).v = Arg.any()) - t.throws(() => substitute.received(1).v = Arg.is(x => x && x.indexOf('ll') > -1)) + t.throws(() => substitute.received(1).v = Arg.is(x => typeof x === 'string' && x.indexOf('ll') > -1)) t.throws(() => substitute.received(3).v = 'hello') }) @@ -92,7 +96,7 @@ test('resolving promises works', async t => { substitute.returnPromise().resolves(1338) - t.is(1338, await substitute.returnPromise()) + t.is(1338, await substitute.returnPromise() as number) }) test('class void returns', t => { diff --git a/spec/regression/issues/36.test.ts b/spec/regression/issues/36.test.ts index 54449e2..508b3c3 100644 --- a/spec/regression/issues/36.test.ts +++ b/spec/regression/issues/36.test.ts @@ -42,6 +42,7 @@ class Service { await this._database.storeUpdates(updateData) } private getData(arg?: Key) { + if (typeof arg === 'undefined') throw new TypeError('Key is undefined') return this._database.getUpdates(arg) } } diff --git a/spec/regression/issues/59.test.ts b/spec/regression/issues/59.test.ts index 13ffd81..36dd296 100644 --- a/spec/regression/issues/59.test.ts +++ b/spec/regression/issues/59.test.ts @@ -12,7 +12,7 @@ test('issue 59 - Mock function with optional parameters', (t) => { echoer.maybeEcho('foo').returns('bar') echoer.maybeEcho().returns('baz') - t.is(echoer.maybeEcho('foo'), 'bar') + t.is('bar', echoer.maybeEcho('foo')) echoer.received().maybeEcho('foo') - t.is(echoer.maybeEcho(), 'baz') + t.is('baz', echoer.maybeEcho()) }) diff --git a/spec/regression/mimicks.spec.ts b/spec/regression/mimicks.spec.ts index 1592e15..a6b5b8a 100644 --- a/spec/regression/mimicks.spec.ts +++ b/spec/regression/mimicks.spec.ts @@ -17,7 +17,7 @@ test('mimicks a method with specific arguments', t => { const addMimick = (a: number, b: number) => a + b calculator.add(1, 1).mimicks(addMimick) - t.is(calculator.add(1, 1), 2) + t.is(2, calculator.add(1, 1)) }) test('mimicks a method with specific and conditional arguments', t => { @@ -27,8 +27,8 @@ test('mimicks a method with specific and conditional arguments', t => { calculator.add(Arg.any('number'), Arg.is((input: number) => input >= 0 && input <= 10)).mimicks(addMimick) calculator.add(42, -42).mimicks((a: number, b: number) => 0) - t.is(calculator.add(1234, 6), 1240) - t.is(calculator.add(42, -42), 0) + t.is(1240, calculator.add(1234, 6)) + t.is(0, calculator.add(42, -42)) }) test('mimicks a method with Arg.all', t => { @@ -37,21 +37,21 @@ test('mimicks a method with Arg.all', t => { calculator.add(Arg.all()).mimicks(addMimick) - t.is(calculator.add(42, 58), 100) + t.is(100, calculator.add(42, 58)) }) test('mimicks a method with optional arguments', t => { const calculator = Substitute.for() const multiplyOneArgMimicks = (a: number) => a * a - const multiplyMimicks = (a: number, b?: number) => a * b + const multiplyMimicks = (a: number, b?: number) => a * (b ?? 0) calculator.multiply(0, Arg.is((b: number) => b > 10 && b < 20)).mimicks(multiplyMimicks) calculator.multiply(Arg.any('number'), Arg.is((b: number) => b === 2)).mimicks(multiplyMimicks) calculator.multiply(2).mimicks(multiplyOneArgMimicks) - t.is(calculator.multiply(0, 13), 0) - t.is(calculator.multiply(42, 2), 84) - t.is(calculator.multiply(2), 4) + t.is(0, calculator.multiply(0, 13)) + t.is(84, calculator.multiply(42, 2)) + t.is(4, calculator.multiply(2)) }) test('mimicks a method where it\'s only argument is optional', t => { @@ -60,6 +60,6 @@ test('mimicks a method where it\'s only argument is optional', t => { calculator.viewResult().mimicks(() => 0) calculator.viewResult(3).mimicks(() => 42) - t.is(calculator.viewResult(), 0) - t.is(calculator.viewResult(3), 42) + t.is(0, calculator.viewResult()) + t.is(42, calculator.viewResult(3)) }) \ No newline at end of file diff --git a/spec/regression/received.spec.ts b/spec/regression/received.spec.ts index 3fac2d7..c9a4519 100644 --- a/spec/regression/received.spec.ts +++ b/spec/regression/received.spec.ts @@ -64,8 +64,11 @@ test('getting a property twice correctly asserts the call count', t => { test('setting a property twice correctly asserts the call count', t => { const calculator = Substitute.for() - calculator.isEnabled = true - calculator.isEnabled = true + const runLogic = (calc: Calculator) => { + calc.isEnabled = true + calc.isEnabled = true + } + runLogic(calculator) calculator.received(2).isEnabled = true calculator.received().isEnabled = true diff --git a/spec/regression/returns.spec.ts b/spec/regression/returns.spec.ts index ef6cdbb..54f61a6 100644 --- a/spec/regression/returns.spec.ts +++ b/spec/regression/returns.spec.ts @@ -7,18 +7,23 @@ interface Calculator { add(a: number, b: number): number multiply(a: number, b?: number): number clear(): void + other(): Calculator getMemory(): Promise viewResult(back?: number): number heavyOperation(...input: number[]): Promise isEnabled: boolean + isEnabled2: Calculator model: Promise }; test('returns a primitive value for method with no arguments', t => { const calculator = Substitute.for() calculator.clear().returns() + // calculator.add(1, 2).toExponential() + // calculator.isEnabled2.viewResult().returns(3) + // calculator.other().viewResult().returns(2) - t.is(calculator.clear(), void 0) + t.is(void 0 as void, calculator.clear()) }) test('returns a primitive value for method with specific arguments', t => { @@ -27,8 +32,8 @@ test('returns a primitive value for method with specific arguments', t => { calculator.add(1, 1).returns(2) - t.is(calculator.add(1, 1), 2) - t.is(calculator.add(1, 1), 2) + t.is(2, calculator.add(1, 1)) + t.is(2, calculator.add(1, 1)) t.true(types.isProxy(noResult)) }) @@ -40,10 +45,10 @@ test('returns a primitive value for method with specific arguments where the las calculator.multiply(1, Arg.any()).returns(10) calculator.multiply(1).returns(1) - t.is(calculator.multiply(2), 4) - t.is(calculator.multiply(0, 10), 0) - t.is(calculator.multiply(1), 1) - t.is(calculator.multiply(1, 10), 10) + t.is(4, calculator.multiply(2)) + t.is(0, calculator.multiply(0, 10)) + t.is(1, calculator.multiply(1)) + t.is(10, calculator.multiply(1, 10)) const noResult = calculator.multiply(2, 2) const noResult2 = calculator.multiply(0) @@ -80,8 +85,8 @@ test('returns a primitive value for method with one optional argument', t => { calculator.viewResult().returns(0) calculator.viewResult(3).returns(123) - t.is(calculator.viewResult(), 0) - t.is(calculator.viewResult(3), 123) + t.is(0, calculator.viewResult()) + t.is(123, calculator.viewResult(3)) }) test('returns a promise for method with no arguments', async t => { @@ -126,10 +131,10 @@ test('returns different primitive values in the specified order for method with const calculator = Substitute.for() calculator.add(1, Arg.any()).returns(1, NaN) - t.is(calculator.add(1, 1), 1) - t.is(calculator.add(1, 0), NaN) - t.is(calculator.add(1, 1), NaN) - t.is(calculator.add(1, 5), NaN) + t.is(1, calculator.add(1, 1)) + t.is(NaN, calculator.add(1, 0)) + t.is(NaN, calculator.add(1, 1)) + t.is(NaN, calculator.add(1, 5)) }) test('returns another substituted instance for method with arguments', t => { @@ -140,7 +145,7 @@ test('returns another substituted instance for method with arguments', t => { const result = calculator.add(1, 1) - t.is(result, addResult) + t.is(addResult, result) t.is(result.toLocaleString(), 'What a weird number') }) @@ -167,9 +172,9 @@ test('returns different primitive values in the specified order on a property', const calculator = Substitute.for() calculator.isEnabled.returns(false, true) - t.is(calculator.isEnabled, false) - t.is(calculator.isEnabled, true) - t.is(calculator.isEnabled, true) + t.is(false, calculator.isEnabled) + t.is(true, calculator.isEnabled) + t.is(true, calculator.isEnabled) }) test('returns another substituted instance on a property', async t => { diff --git a/spec/tsconfig.json b/spec/tsconfig.json new file mode 100644 index 0000000..316c923 --- /dev/null +++ b/spec/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "strictNullChecks": false, + "sourceMap": true + }, + "include": [ + "./**/*" + ] +} \ No newline at end of file diff --git a/src/RecordedArguments.ts b/src/RecordedArguments.ts index b778f62..318962c 100644 --- a/src/RecordedArguments.ts +++ b/src/RecordedArguments.ts @@ -3,15 +3,11 @@ import { Argument, AllArguments } from './Arguments' type ArgumentsClass = 'plain' | 'with-predicate' | 'wildcard' export class RecordedArguments { - private _argumentsClass: ArgumentsClass + private _argumentsClass?: ArgumentsClass private _value?: any[] - private readonly _hasNoArguments: boolean = false private constructor(rawArguments: any[] | void) { - if (typeof rawArguments === 'undefined') { - this._hasNoArguments = true - return this - } + if (typeof rawArguments === 'undefined') return this this._argumentsClass = this.classifyArguments(rawArguments) this._value = rawArguments @@ -42,7 +38,7 @@ export class RecordedArguments { }) } - get argumentsClass(): ArgumentsClass { + get argumentsClass(): ArgumentsClass | undefined { return this._argumentsClass } @@ -50,15 +46,14 @@ export class RecordedArguments { return this._value } - get hasNoArguments(): boolean { - return this._hasNoArguments + public hasArguments(): this is this & { argumentsClass: ArgumentsClass, value: any[] } { + return Array.isArray(this._value) } - public match(other: RecordedArguments) { + public match(other: RecordedArguments): boolean { if (this.argumentsClass === 'wildcard' || other.argumentsClass === 'wildcard') return true - if (this.hasNoArguments || other.hasNoArguments) return this.hasNoArguments && other.hasNoArguments + if (!this.hasArguments() || !other.hasArguments()) return !this.hasArguments() && !other.hasArguments() if (this.value.length !== other.value.length) return false - return this.value.every((argument, index) => this.areArgumentsEqual(argument, other.value[index])) } diff --git a/src/Recorder.ts b/src/Recorder.ts index 6da2ee8..bc6b97c 100644 --- a/src/Recorder.ts +++ b/src/Recorder.ts @@ -1,46 +1,52 @@ import { inspect, InspectOptions } from 'util' -import { SubstituteNodeBase } from './SubstituteNodeBase' + +import { FilterFunction } from './Types' import { RecordsSet } from './RecordsSet' -export class Recorder { - private _records: RecordsSet - private _indexedRecords: Map> +export class Recorder { + private _identity: PropertyKey + private _records: RecordsSet + private _indexedRecords: Map> - constructor() { + private constructor(identity: PropertyKey) { + this._identity = identity this._records = new RecordsSet() this._indexedRecords = new Map() } - public get records(): RecordsSet { + public static withIdentityProperty(identity: keyof TRecord): Recorder { + return new this(identity) + } + + public get records(): RecordsSet { return this._records } - public get indexedRecords(): Map> { + public get indexedRecords(): Map> { return this._indexedRecords } - public addIndexedRecord(node: SubstituteNodeBase): void { - this.addRecord(node) - const existingNodes = this.indexedRecords.get(node.key) - if (typeof existingNodes === 'undefined') this.indexedRecords.set(node.key, new RecordsSet([node])) - else existingNodes.add(node) + public addIndexedRecord(record: TRecord): void { + const id = this.getIdentity(record) + this.addRecord(record) + const existingNodes = this.indexedRecords.get(id) + if (typeof existingNodes === 'undefined') this.indexedRecords.set(id, new RecordsSet([record])) + else existingNodes.add(record) } - public addRecord(node: SubstituteNodeBase): void { - this._records.add(node) + public addRecord(record: TRecord): void { + this._records.add(record) } - public getSiblingsOf(node: SubstituteNodeBase): RecordsSet { - const siblingNodes = this.indexedRecords.get(node.key) ?? new RecordsSet() - return siblingNodes.filter(siblingNode => siblingNode !== node) + public getSiblingsOf(record: TRecord): RecordsSet { + const siblings = this.indexedRecords.get(this.getIdentity(record)) ?? new RecordsSet() + return siblings.filter(sibling => sibling !== record) } - public clearRecords(filterFunction: (node: SubstituteNodeBase) => boolean) { + public clearRecords(filterFunction: FilterFunction): void { const recordsToRemove = this.records.filter(filterFunction) for (const record of recordsToRemove) { - const indexedRecord = this.indexedRecords.get(record.key) - indexedRecord.delete(record) - if (indexedRecord.size === 0) this.indexedRecords.delete(record.key) + this.clearIndexedRecord(record) this.records.delete(record) } } @@ -51,4 +57,17 @@ export class Recorder { ([key, value]) => `\n ${key.toString()}: {\n${[...value.map(v => ` ${inspect(v, options)}`)].join(',\n')}\n }` ).join() } -} + + private getIdentity(record: TRecord): PropertyKey { + // for typescript < 4.6, we need to intersect PropertyKey with the default type + return record[this._identity as keyof TRecord] as TRecord[keyof TRecord] & PropertyKey + } + + private clearIndexedRecord(record: TRecord): void { + const id = this.getIdentity(record) + const indexedRecord = this.indexedRecords.get(id) + if (typeof indexedRecord === 'undefined') return + indexedRecord.delete(record) + if (indexedRecord.size === 0) this.indexedRecords.delete(id) + } +} \ No newline at end of file diff --git a/src/RecordsSet.ts b/src/RecordsSet.ts index 0d16501..cc8026e 100644 --- a/src/RecordsSet.ts +++ b/src/RecordsSet.ts @@ -1,14 +1,16 @@ -type FilterFunction = (item: T) => boolean +import { FilterFunction } from './Types' + type MapperFunction = (item: T) => R -type Transformer = { type: 'filter', fnc: FilterFunction } | { type: 'mapper', fnc: MapperFunction } +type Transformer = { type: 'filter', predicate: FilterFunction } | { type: 'mapper', predicate: MapperFunction } export class RecordsSet extends Set { - private _transformer: Transformer + private _transformer?: Transformer private readonly _prevIter?: RecordsSet constructor(value?: Iterable | readonly T[]) { - super(value instanceof RecordsSet ? undefined : value) - if (value instanceof RecordsSet) this._prevIter = value + const isRecordSet = value instanceof RecordsSet + super(isRecordSet ? undefined : value) + if (isRecordSet) this._prevIter = value } get size(): number { @@ -17,15 +19,15 @@ export class RecordsSet extends Set { return currentSize } - filter(predicate: (item: T) => boolean): RecordsSet { - const newInstance = new RecordsSet(this) - newInstance._transformer = { type: 'filter', fnc: predicate } + filter(predicate: FilterFunction): RecordsSet { + const newInstance = new RecordsSet(this as RecordsSet) + newInstance._transformer = { type: 'filter', predicate } return newInstance } - map(predicate: (item: T) => R): RecordsSet { + map(predicate: MapperFunction): RecordsSet { const newInstance = new RecordsSet(this) - newInstance._transformer = { type: 'mapper', fnc: predicate } + newInstance._transformer = { type: 'mapper', predicate } return newInstance as RecordsSet } @@ -41,7 +43,10 @@ export class RecordsSet extends Set { } clear() { - Object.defineProperty(this, '_prevIter', { value: undefined }) + if (this._prevIter instanceof RecordsSet) { + this._prevIter.clear() + Object.defineProperty(this, '_prevIter', { value: undefined }) + } super.clear() } @@ -54,12 +59,17 @@ export class RecordsSet extends Set { yield* this.applyTransform(super.values()) } - private *applyTransform(itarable: Iterable): IterableIterator { + private * applyTransform(itarable: Iterable): IterableIterator { const transform = this._transformer if (typeof transform === 'undefined') return yield* itarable for (const value of itarable) { - if (transform.type === 'mapper') yield transform.fnc(value) - if (transform.type === 'filter' && transform.fnc(value)) yield value + switch (transform.type) { + case 'filter': + if (transform.predicate(value)) yield value + break + case 'mapper': yield transform.predicate(value) + break + } } } } \ No newline at end of file diff --git a/src/Substitute.ts b/src/Substitute.ts index 21afa3f..3f87849 100644 --- a/src/Substitute.ts +++ b/src/Substitute.ts @@ -1,49 +1,25 @@ -import { inspect, InspectOptions } from 'util' +import { DisabledSubstituteObject, ObjectSubstitute } from './Transformations' +import { SubstituteNode } from './SubstituteNode' -import { SubstituteBase } from './SubstituteBase' -import { createSubstituteProxy } from './SubstituteProxy' -import { Recorder } from './Recorder' -import { DisabledSubstituteObject, ObjectSubstitute, OmitProxyMethods } from './Transformations' +export type SubstituteOf = ObjectSubstitute & T +type InstantiableSubstitute> = T & { [SubstituteNode.instance]: SubstituteNode } -export type SubstituteOf = ObjectSubstitute, T> & T -type Instantiable = { [SubstituteBase.instance]?: T } - -export class Substitute extends SubstituteBase { - private _proxy: Substitute - private _recorder: Recorder = new Recorder() - private _context: { disableAssertions: boolean } = { disableAssertions: false } - - constructor() { - super() - this._proxy = createSubstituteProxy( - this, - { - get: (target, _property, _, node) => { - if (target.context.disableAssertions) node.disableAssertions() - } - // apply: (target, _, args, __, proxy) => { - // const rootProperty = proxy.get(target, '()', proxy) TODO: Implement to support callable interfaces - // return Reflect.apply(rootProperty, rootProperty, args) - // } - } - ) - } - - static for(): SubstituteOf { - const substitute = new this() +export class Substitute { + public static for(): SubstituteOf { + const substitute = SubstituteNode.createRoot() return substitute.proxy as unknown as SubstituteOf } - static disableFor & Instantiable>(substituteProxy: T): DisabledSubstituteObject { - const substitute = substituteProxy[SubstituteBase.instance] + public static disableFor>(substituteProxy: T): DisabledSubstituteObject { + const substitute = this.extractSubstituteNodeFromSubstitute(substituteProxy as InstantiableSubstitute) const disableProxy = < TParameters extends unknown[], TReturnType extends unknown >(reflection: (...args: TParameters) => TReturnType): typeof reflection => (...args) => { - substitute.context.disableAssertions = true + substitute.rootContext.substituteMethodsEnabled = false const reflectionResult = reflection(...args) - substitute.context.disableAssertions = false + substitute.rootContext.substituteMethodsEnabled = true return reflectionResult } @@ -60,22 +36,7 @@ export class Substitute extends SubstituteBase { }) as DisabledSubstituteObject } - public get proxy() { - return this._proxy - } - - public get recorder() { - return this._recorder - } - - public get context() { - return this._context - } - - protected printableForm(_: number, options: InspectOptions): string { - const records = inspect(this.recorder, options) - - const instanceName = 'Substitute' // Substitute - return instanceName + ' {' + records + '\n}' + private static extractSubstituteNodeFromSubstitute(substitute: InstantiableSubstitute>): SubstituteNode { + return substitute[SubstituteNode.instance] } } \ No newline at end of file diff --git a/src/SubstituteBase.ts b/src/SubstituteBase.ts deleted file mode 100644 index a0eb4c0..0000000 --- a/src/SubstituteBase.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { inspect, InspectOptions, types } from 'util' -import { SubstituteException } from './SubstituteException' - -const instance = Symbol('Substitute:Instance') -type SpecialProperty = typeof instance | typeof inspect.custom | 'then' -export abstract class SubstituteBase extends Function { - constructor() { - super() - } - - static instance: typeof instance = instance - - protected isSpecialProperty(property: PropertyKey): property is SpecialProperty { - return property === SubstituteBase.instance || property === inspect.custom || property === 'then' - } - - protected evaluateSpecialProperty(property: SpecialProperty) { - switch (property) { - case SubstituteBase.instance: - return this - case inspect.custom: - return this.printableForm.bind(this) - case 'then': - return - default: - throw SubstituteException.generic(`Evaluation of special property ${property} is not implemented`) - } - } - - protected abstract printableForm(_: number, options: InspectOptions): string - - public [inspect.custom](...args: [_: number, options: InspectOptions]): string { - return types.isProxy(this) ? this[inspect.custom](...args) : this.printableForm(...args) - } -} \ No newline at end of file diff --git a/src/SubstituteException.ts b/src/SubstituteException.ts index d72f01f..4595a01 100644 --- a/src/SubstituteException.ts +++ b/src/SubstituteException.ts @@ -1,5 +1,6 @@ +import { PropertyType } from './Types' import { RecordedArguments } from './RecordedArguments' -import { PropertyType, stringifyArguments, stringifyCalls, textModifier, plurify } from './Utilities' +import { PropertyType as PropertyTypeMap, stringifyArguments, stringifyCalls, textModifier, plurify } from './Utilities' enum SubstituteExceptionTypes { CallCountMissMatch = 'CallCountMissMatch', @@ -7,7 +8,7 @@ enum SubstituteExceptionTypes { } export class SubstituteException extends Error { - type: SubstituteExceptionTypes + type?: SubstituteExceptionTypes constructor(msg: string, exceptionType?: SubstituteExceptionTypes) { super(msg) @@ -17,7 +18,7 @@ export class SubstituteException extends Error { } static forCallCountMissMatch( - count: { expected: number | null, received: number }, + count: { expected: number | undefined, received: number }, property: { type: PropertyType, value: PropertyKey }, calls: { expected: RecordedArguments, received: RecordedArguments[] } ) { @@ -26,7 +27,7 @@ export class SubstituteException extends Error { count.expected === undefined ? '1 or more' : count.expected.toString() )} ${plurify('call', count.expected)} to the ${textModifier.italic(property.type)} ${propertyValue}` - const messageForMethods = property.type === PropertyType.method ? ` with ${stringifyArguments(calls.expected)}` : '' // should also apply for setters (instead of methods only) + const messageForMethods = property.type === PropertyTypeMap.Method ? ` with ${stringifyArguments(calls.expected)}` : '' // should also apply for setters (instead of methods only) const receivedMessage = `, but received ${textModifier.bold(count.received < 1 ? 'none' : count.received.toString())} of such calls.` const callTrace = calls.received.length > 0 diff --git a/src/SubstituteNode.ts b/src/SubstituteNode.ts index 800603a..a48d0d4 100644 --- a/src/SubstituteNode.ts +++ b/src/SubstituteNode.ts @@ -1,53 +1,79 @@ -import { inspect, InspectOptions } from 'util' +import { inspect, InspectOptions, types } from 'util' -import { PropertyType, isSubstitutionMethod, isAssertionMethod, AssertionMethod, SubstitutionMethod, textModifier, ConfigurationMethod, isSubstituteMethod } from './Utilities' -import { SubstituteException } from './SubstituteException' -import { RecordedArguments } from './RecordedArguments' import { SubstituteNodeBase } from './SubstituteNodeBase' -import { SubstituteBase } from './SubstituteBase' -import { createSubstituteProxy } from './SubstituteProxy' -import { ClearType } from './Transformations' +import { RecordedArguments } from './RecordedArguments' +import { ClearType as ClearTypeMap, PropertyType as PropertyTypeMap, isAssertionMethod, isSubstituteMethod, isSubstitutionMethod, textModifier } from './Utilities' +import { SubstituteException } from './SubstituteException' +import type { FilterFunction, SubstituteContext, SubstitutionMethod, ClearType, PropertyType } from './Types' -type SubstituteContext = SubstitutionMethod | AssertionMethod | ConfigurationMethod | 'none' -const clearTypeToFilterMap: Record boolean> = { +const instance = Symbol('Substitute:Instance') +const clearTypeToFilterMap: Record> = { all: () => true, receivedCalls: node => !node.hasContext, substituteValues: node => node.isSubstitution } -export class SubstituteNode extends SubstituteNodeBase { +type SpecialProperty = typeof instance | typeof inspect.custom | 'then' +type RootContext = { substituteMethodsEnabled: boolean } + +export class SubstituteNode extends SubstituteNodeBase { private _proxy: SubstituteNode - private _propertyType: PropertyType = PropertyType.property + private _rootContext: RootContext + + private _propertyType: PropertyType = PropertyTypeMap.Property private _accessorType: 'get' | 'set' = 'get' private _recordedArguments: RecordedArguments = RecordedArguments.none() private _context: SubstituteContext = 'none' - private _disabledAssertions: boolean = false + private _disabledSubstituteMethods: boolean = false - constructor(property: PropertyKey, parent: SubstituteNode | SubstituteBase) { - super(property, parent) - this._proxy = createSubstituteProxy( + private constructor(key: PropertyKey, parent?: SubstituteNode) { + super(key, parent) + if (this.isRoot()) this._rootContext = { substituteMethodsEnabled: true } + else this._rootContext = this.root.rootContext + this._proxy = new Proxy( this, { - get: (node, _, __, nextNode) => { - if (node.isAssertion) nextNode.executeAssertion() + get: function (target, property) { + if (target.isSpecialProperty(property)) return target.evaluateSpecialProperty(property) + const newNode = SubstituteNode.createChild(property, target) + if (target.isRoot() && !target.rootContext.substituteMethodsEnabled) newNode.disableSubstituteMethods() + if (target.isIntermediateNode() && target.isAssertion) newNode.executeAssertion() + return newNode.read() }, - set: (node, _, __, ___, nextNode) => { - if (node.isAssertion) nextNode.executeAssertion() + set: function (target, property, value) { + const newNode = SubstituteNode.createChild(property, target) + newNode.write(value) + if (target.isAssertion) newNode.executeAssertion() + return true }, - apply: (node, _, rawArguments) => { - node.handleMethod(rawArguments) - if (node.context === 'clearSubstitute') return node.clear() - return node.parent?.isAssertion ?? false ? node.executeAssertion() : node.read() + apply: function (target, _thisArg, rawArguments) { + target.handleMethod(rawArguments) + if (target.hasContext) target.handleSpecialContext() + return (target.parent?.isAssertion ?? false) ? target.executeAssertion() : target.read() } } ) } - public get proxy() { + public static instance: typeof instance = instance + + public static createRoot(): SubstituteNode { + return new this('*Substitute') + } + + public static createChild(key: PropertyKey, parent: SubstituteNode): SubstituteNode { + return new this(key, parent) + } + + public get proxy(): SubstituteNode { return this._proxy } + public get rootContext(): RootContext { + return this._rootContext + } + get context(): SubstituteContext { return this._context } @@ -64,11 +90,11 @@ export class SubstituteNode extends SubstituteNodeBase { return isAssertionMethod(this.context) } - get property() { + get property(): PropertyKey { return this.key } - get propertyType() { + get propertyType(): PropertyType { return this._propertyType } @@ -76,24 +102,24 @@ export class SubstituteNode extends SubstituteNodeBase { return this._accessorType } - get recordedArguments() { + get recordedArguments(): RecordedArguments { return this._recordedArguments } - public get disabledAssertions() { - return this._disabledAssertions + public get disabledSubstituteMethods(): boolean { + return this._disabledSubstituteMethods } public assignContext(context: SubstituteContext): void { this._context = context } - public disableAssertions() { - this._disabledAssertions = true + public disableSubstituteMethods() { + this._disabledSubstituteMethods = true } public read(): SubstituteNode | void | never { - if (this.parent?.isSubstitution ?? false) return + if ((this.parent?.isSubstitution ?? false) || this.context === 'clearSubstitute') return if (this.isAssertion) return this.proxy const mostSuitableSubstitution = this.getMostSuitableSubstitution() @@ -108,22 +134,27 @@ export class SubstituteNode extends SubstituteNodeBase { } public clear() { - const clearType: ClearType = this.recordedArguments.value[0] ?? 'all' - const filter = clearTypeToFilterMap[clearType] as (node: SubstituteNodeBase) => boolean - this.root.recorder.clearRecords(filter) + if (!this.recordedArguments.hasArguments()) throw new TypeError('No args') + const clearType: ClearType = this.recordedArguments.value[0] ?? ClearTypeMap.All + const filter = clearTypeToFilterMap[clearType] + this.recorder.clearRecords(filter) } public executeSubstitution(contextArguments: RecordedArguments) { + if (!this.hasChild()) throw new TypeError('Substitue node has no child') + if (!this.child.recordedArguments.hasArguments()) throw new TypeError('Child args') + const substitutionMethod = this.context as SubstitutionMethod const substitutionValue = this.child.recordedArguments.value.length > 1 - ? this.child.recordedArguments.value.shift() + ? this.child.recordedArguments.value?.shift() : this.child.recordedArguments.value[0] switch (substitutionMethod) { case 'throws': throw substitutionValue case 'mimicks': - const argumentsToApply = this.propertyType === PropertyType.property ? [] : contextArguments.value - return substitutionValue(...argumentsToApply) + if (this.propertyType === PropertyTypeMap.Property) return substitutionValue() + if (!contextArguments.hasArguments()) throw new TypeError('Context arguments cannot be undefined') + return substitutionValue(...contextArguments.value) case 'resolves': return Promise.resolve(substitutionValue) case 'rejects': @@ -136,8 +167,9 @@ export class SubstituteNode extends SubstituteNodeBase { } public executeAssertion(): void | never { - const siblings = [...this.getAllSiblings().filter(n => !n.hasContext && n.accessorType === this.accessorType)] if (!this.isIntermediateNode()) throw new Error('Not possible') + if (!this.parent.recordedArguments.hasArguments()) throw new TypeError('Parent args') + const siblings = [...this.getAllSiblings().filter(n => !n.hasContext && n.accessorType === this.accessorType)] const expectedCount = this.parent.recordedArguments.value[0] ?? undefined const finiteExpectation = expectedCount !== undefined @@ -168,14 +200,20 @@ export class SubstituteNode extends SubstituteNodeBase { } public handleMethod(rawArguments: any[]): void { - this._propertyType = PropertyType.method + this._propertyType = PropertyTypeMap.Method this._recordedArguments = RecordedArguments.from(rawArguments) - if (!isSubstituteMethod(this.property)) return + this.tryToAssignContext() + } + private tryToAssignContext() { + if (!isSubstituteMethod(this.property)) return if (this.isIntermediateNode() && isSubstitutionMethod(this.property)) return this.parent.assignContext(this.property) - if (this.disabledAssertions || !this.isHead()) return - + if (this.disabledSubstituteMethods) return this.assignContext(this.property) + } + + private handleSpecialContext(): void { + if (this.context === 'clearSubstitute') return this.clear() if (this.context === 'didNotReceive') this._recordedArguments = RecordedArguments.from([0]) } @@ -188,13 +226,44 @@ export class SubstituteNode extends SubstituteNodeBase { return sortedNodes[0] } - protected printableForm(_: number, options: InspectOptions): string { + private isSpecialProperty(property: PropertyKey): property is SpecialProperty { + return property === SubstituteNode.instance || property === inspect.custom || property === 'then' + } + + private evaluateSpecialProperty(property: SpecialProperty) { + switch (property) { + case SubstituteNode.instance: + return this + case inspect.custom: + return this.printableForm.bind(this) + case 'then': + return + default: + throw SubstituteException.generic(`Evaluation of special property ${property} is not implemented`) + } + } + + public [inspect.custom](...args: [_: number, options: InspectOptions]): string { + return types.isProxy(this) ? this[inspect.custom](...args) : this.printableForm(...args) + } + + private printableForm(_: number, options: InspectOptions): string { + return this.isRoot() ? this.printRootNode(options) : this.printNode(options) + } + + private printRootNode(options: InspectOptions): string { + const records = inspect(this.recorder, options) + const instanceName = '*Substitute' // Substitute + return instanceName + ' {' + records + '\n}' + } + + private printNode(options: InspectOptions): string { const hasContext = this.hasContext const args = inspect(this.recordedArguments, options) const label = this.isSubstitution ? '=> ' : this.isAssertion - ? `${this.child.property.toString()}` + ? `${this.child?.property.toString()}` : '' const s = hasContext ? ` ${label}${inspect(this.child?.recordedArguments, options)}` diff --git a/src/SubstituteNodeBase.ts b/src/SubstituteNodeBase.ts index 21c9e4d..4cf2193 100644 --- a/src/SubstituteNodeBase.ts +++ b/src/SubstituteNodeBase.ts @@ -1,65 +1,78 @@ -import { SubstituteBase } from './SubstituteBase' -import { Substitute } from './Substitute' +import { Recorder } from './Recorder' import { RecordsSet } from './RecordsSet' -export abstract class SubstituteNodeBase> extends SubstituteBase { - private _parent?: T - private _child?: T - private _head: T & { parent: undefined } - private _root: Substitute +export abstract class SubstituteNodeBase extends Function { + private _root: this & { parent: undefined } + private _parent?: this + private _child?: this + private _depth: number - constructor(private _key: PropertyKey, caller: SubstituteBase) { - super() + private _recorder: Recorder - if (caller instanceof Substitute) { - caller.recorder.addIndexedRecord(this) - this._root = caller + constructor(private _key: PropertyKey, parent?: SubstituteNodeBase) { + super() + const shouldBeRoot = !this.isNode(parent) + if (shouldBeRoot) { + this._recorder = Recorder.withIdentityProperty('key') + this._root = this as this & { parent: undefined } + this._depth = 0 + return } - if (!(caller instanceof SubstituteNodeBase)) return - this._parent = caller as T - this._head = caller.head as T & { parent: undefined } - caller.child = this + parent.assignChild(this) + this._parent = parent + this._recorder = parent.recorder + this._root = parent.root + this._depth = parent.depth + 1 + if (this.parent === this.root) this.recorder.addIndexedRecord(this) + } + + private isNode(node?: SubstituteNodeBase): node is this { + return typeof node !== 'undefined' } - get key(): PropertyKey { + public get key(): PropertyKey { return this._key } - set parent(parent: T | undefined) { - this._parent = parent + public get recorder(): Recorder { + return this._recorder } - get parent(): T | undefined { + protected get parent(): this | undefined { return this._parent } - set child(child: T) { - this._child = child + protected get child(): this | undefined { + return this._child } - get child(): T { - return this._child + protected get root(): this & { parent: undefined } { + return this._root } - get head(): T & { parent: undefined } { - return this.isHead() ? this : this._head + protected get depth(): number { + return this._depth } - protected get root(): Substitute { - return this.head._root + private assignChild(child: this): void { + this._child = child } - protected isHead(): this is T & { parent: undefined } { + protected isRoot(): this is this & { parent: undefined } { return typeof this._parent === 'undefined' } - protected isIntermediateNode(): this is T & { parent: T } { - return !this.isHead() + protected isIntermediateNode(): this is this & { parent: ThisType } { + return !this.isRoot() + } + + protected getAllSiblings(): RecordsSet { + return this.recorder.getSiblingsOf(this) } - protected getAllSiblings(): RecordsSet { - return this.root.recorder.getSiblingsOf(this) as RecordsSet + protected hasChild(): this is this & { child: ThisType } { + return this.child instanceof SubstituteNodeBase } public abstract read(): void diff --git a/src/SubstituteProxy.ts b/src/SubstituteProxy.ts deleted file mode 100644 index c8e927c..0000000 --- a/src/SubstituteProxy.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { SubstituteBase } from './SubstituteBase' -import { SubstituteNode } from './SubstituteNode' - -type BeforeNodeExecutionHook = { - [Handler in keyof ProxyHandler]?: (...args: [..._: Parameters[Handler]>, node: SubstituteNode | undefined, proxy: ProxyHandler]) => void -} -export const createSubstituteProxy = ( - target: T, - beforeNodeExecutionHook: BeforeNodeExecutionHook -) => new Proxy( - target, - { - get: function (this: SubstituteBase, ...args) { - const [target, property] = args - if (target.isSpecialProperty(property)) return target.evaluateSpecialProperty(property) - const newNode = new SubstituteNode(property, target) - beforeNodeExecutionHook.get?.(...args, newNode, this) - return newNode.read() - }, - set: function (...args) { - const [target, property, value] = args - const newNode = new SubstituteNode(property, target) - newNode.write(value) - beforeNodeExecutionHook.set?.(...args, newNode, this) - return true - }, - apply: function (...args) { - return beforeNodeExecutionHook.apply?.(...args, undefined, this) - - } - } -) \ No newline at end of file diff --git a/src/Transformations.ts b/src/Transformations.ts index f2089c6..f824b68 100644 --- a/src/Transformations.ts +++ b/src/Transformations.ts @@ -1,4 +1,5 @@ -import { AllArguments } from './Arguments'; +import type { AllArguments } from './Arguments'; +import type { ClearType, FirstLevelMethod } from './Types'; type FunctionSubstituteWithOverloads = TFunc extends { @@ -44,7 +45,7 @@ export type FunctionSubstitute = ((allArguments: AllArguments) => (TReturnType & MockObjectMixin)) export type NoArgumentFunctionSubstitute = (() => (TReturnType & NoArgumentMockObjectMixin)) -export type PropertySubstitute = (TReturnType & Partial>); +export type PropertySubstitute = (TReturnType & NoArgumentMockObjectMixin); type OneArgumentRequiredFunction = (requiredInput: TArgs, ...restInputs: TArgs[]) => TReturnType; @@ -66,13 +67,6 @@ type MockObjectMixin = BaseMockObjectMixi mimicks: OneArgumentRequiredFunction<(...args: TArguments) => TReturnType, void>; } -export type ObjectSubstitute = ObjectSubstituteTransformation & { - received(amount?: number): TerminatingObject; - didNotReceive(): TerminatingObject; - mimick(instance: T): void; - clearSubstitute(clearType?: ClearType): void; -} - type TerminatingFunction = ((...args: TArguments) => void) & ((arg: AllArguments) => void) type TerminatingObject = { @@ -83,7 +77,7 @@ type TerminatingObject = { T[P]; } -type ObjectSubstituteTransformation = { +type ObjectSubstituteTransformation> = { [P in keyof T]: T[P] extends (...args: infer F) => infer R ? F extends [] ? NoArgumentFunctionSubstitute : @@ -91,8 +85,11 @@ type ObjectSubstituteTransformation = { PropertySubstitute; } -type Omit = Pick>; - -export type ClearType = 'all' | 'receivedCalls' | 'substituteValues'; -export type OmitProxyMethods = Omit; -export type DisabledSubstituteObject = T extends ObjectSubstitute, infer K> ? K : never; +export type OmitProxyMethods = Omit; +export type ObjectSubstitute = ObjectSubstituteTransformation & { + received(amount?: number): TerminatingObject; + didNotReceive(): TerminatingObject; + mimick(instance: OmitProxyMethods): void; + clearSubstitute(clearType?: ClearType): void; +} +export type DisabledSubstituteObject = T extends ObjectSubstitute ? K : never; diff --git a/src/Types.ts b/src/Types.ts new file mode 100644 index 0000000..d9b6228 --- /dev/null +++ b/src/Types.ts @@ -0,0 +1,12 @@ +export type PropertyType = 'method' | 'property' +export type AssertionMethod = 'received' | 'didNotReceive' +export type ConfigurationMethod = 'clearSubstitute' | 'mimick' +export type SubstitutionMethod = 'mimicks' | 'throws' | 'returns' | 'resolves' | 'rejects' + +export type FirstLevelMethod = AssertionMethod | ConfigurationMethod +export type SubstituteMethod = FirstLevelMethod | SubstitutionMethod +export type SubstituteContext = SubstituteMethod | 'none' + +export type ClearType = 'all' | 'receivedCalls' | 'substituteValues' + +export type FilterFunction = (item: T) => boolean \ No newline at end of file diff --git a/src/Utilities.ts b/src/Utilities.ts index 53ba35b..c7c6757 100644 --- a/src/Utilities.ts +++ b/src/Utilities.ts @@ -1,29 +1,33 @@ import { inspect } from 'util' import { RecordedArguments } from './RecordedArguments' +import type { AssertionMethod, ConfigurationMethod, SubstituteMethod, SubstitutionMethod } from './Types' -export enum PropertyType { - method = 'method', - property = 'property' -} +export const PropertyType = { + Method: 'method', + Property: 'property' +} as const -export type AssertionMethod = 'received' | 'didNotReceive' export const isAssertionMethod = (property: PropertyKey): property is AssertionMethod => property === 'received' || property === 'didNotReceive' -export type ConfigurationMethod = 'clearSubstitute' export const isConfigurationMethod = (property: PropertyKey): property is ConfigurationMethod => property === 'clearSubstitute' -export type SubstitutionMethod = 'mimicks' | 'throws' | 'returns' | 'resolves' | 'rejects' export const isSubstitutionMethod = (property: PropertyKey): property is SubstitutionMethod => property === 'mimicks' || property === 'returns' || property === 'throws' || property === 'resolves' || property === 'rejects' -export const isSubstituteMethod = (property: PropertyKey): property is SubstitutionMethod | ConfigurationMethod | AssertionMethod => +export const isSubstituteMethod = (property: PropertyKey): property is SubstituteMethod => isSubstitutionMethod(property) || isConfigurationMethod(property) || isAssertionMethod(property) +export const ClearType = { + All: 'all', + ReceivedCalls: 'receivedCalls', + SubstituteValues: 'substituteValues' +} as const + export const stringifyArguments = (args: RecordedArguments) => textModifier.faint( - args.hasNoArguments - ? 'no arguments' - : `arguments [${args.value.map(x => inspect(x, { colors: true })).join(', ')}]` + args.hasArguments() ? + `arguments [${args.value.map(x => inspect(x, { colors: true })).join(', ')}]` : + 'no arguments' ) export const stringifyCalls = (calls: RecordedArguments[]) => { @@ -41,4 +45,4 @@ export const textModifier = { italic: (str: string) => baseTextModifier(str, 3, 23) } -export const plurify = (str: string, count: number) => `${str}${count === 1 ? '' : 's'}` \ No newline at end of file +export const plurify = (str: string, count?: number) => `${str}${count === 1 ? '' : 's'}` \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index c054fa3..ffd8ce0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,5 +2,6 @@ import { Substitute, SubstituteOf } from './Substitute' export { Arg } from './Arguments' export { Substitute, SubstituteOf } +export { ClearType } from './Utilities' export default Substitute \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index cc175a0..668168a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,13 +1,15 @@ { - "compileOnSave": true, "compilerOptions": { "module": "commonjs", "moduleResolution": "node", + "target": "ES6", "baseUrl": ".", "declaration": true, - "outDir": "./dist", + "outDir": "dist", "strict": true, - "strictNullChecks": false, - "target": "ES6" - } + "removeComments": true + }, + "include": [ + "src/**/*" + ] } \ No newline at end of file From b642745eec31933e144309ae5d3e7f75ce3dbb95 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 13 Oct 2022 20:33:07 +0200 Subject: [PATCH 40/46] Upgrade to GitHub-native Dependabot (#192) Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- .github/dependabot.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..29f5a79 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +version: 2 +updates: +- package-ecosystem: npm + directory: "/" + schedule: + interval: daily + time: "04:00" + open-pull-requests-limit: 30 + ignore: + - dependency-name: typescript + versions: + - 4.1.4 From 0cb621b1020d7fc2e310e8f9c5258866a210fbf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrique=20P=C3=B6hlmann?= <45039845+notanengineercom@users.noreply.github.com> Date: Thu, 13 Oct 2022 20:54:07 +0200 Subject: [PATCH 41/46] add github actions in dependabot check (#247) --- .github/dependabot.yml | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 29f5a79..5570919 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,12 +1,14 @@ version: 2 updates: -- package-ecosystem: npm - directory: "/" - schedule: - interval: daily - time: "04:00" - open-pull-requests-limit: 30 - ignore: - - dependency-name: typescript - versions: - - 4.1.4 + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: weekly + + - package-ecosystem: npm + directory: "/" + schedule: + interval: daily + time: "04:00" + open-pull-requests-limit: 10 From 1e1f3307a3a65f6a66a5d2823a02daf45e5a15e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrique=20P=C3=B6hlmann?= <45039845+notanengineercom@users.noreply.github.com> Date: Fri, 8 Mar 2024 14:48:29 +0100 Subject: [PATCH 42/46] Support ambiguous property types on mocked interfaces (#248) * refactor recorded arguments * enhance transformation type to allow callable interfaces * implement logic to handle unresolved property type * add regression test with failing assertion * rework core types for terminating object * simplify context switching * support assertion on ambiguous properties * support node.js lts * remove ts-node from root package * create compatiblity checks to verify test runners --- .github/workflows/nodejs.yml | 2 +- compatibility-checks/ava.config.js | 9 + compatibility-checks/jest.config.js | 5 + compatibility-checks/package-lock.json | 8350 +++++++++++++++++ compatibility-checks/package.json | 40 + .../test-runners/_common/index.ts | 21 + .../test-runners/ava/index.ts | 6 + .../test-runners/jest/index.spec.ts | 5 + .../test-runners/mocha/index.ts | 6 + .../test-runners/nodejs/index.ts | 6 + .../test-runners/vitest/index.spec.ts | 6 + compatibility-checks/test/index.ts | 53 + compatibility-checks/tsconfig.json | 16 + package-lock.json | 2246 ++++- package.json | 5 +- spec/regression/issues/178.test.ts | 40 + src/RecordedArguments.ts | 22 +- src/SubstituteNode.ts | 164 +- src/SubstituteNodeBase.ts | 7 +- src/Transformations.ts | 29 +- src/Utilities.ts | 2 +- 21 files changed, 10936 insertions(+), 104 deletions(-) create mode 100644 compatibility-checks/ava.config.js create mode 100644 compatibility-checks/jest.config.js create mode 100644 compatibility-checks/package-lock.json create mode 100644 compatibility-checks/package.json create mode 100644 compatibility-checks/test-runners/_common/index.ts create mode 100644 compatibility-checks/test-runners/ava/index.ts create mode 100644 compatibility-checks/test-runners/jest/index.spec.ts create mode 100644 compatibility-checks/test-runners/mocha/index.ts create mode 100644 compatibility-checks/test-runners/nodejs/index.ts create mode 100644 compatibility-checks/test-runners/vitest/index.spec.ts create mode 100644 compatibility-checks/test/index.ts create mode 100644 compatibility-checks/tsconfig.json create mode 100644 spec/regression/issues/178.test.ts diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 3814e7a..13b561c 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -6,7 +6,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [12, 14, 16, 18] + node-version: [12, 14, 16, 18, 20] steps: - uses: actions/checkout@v3 diff --git a/compatibility-checks/ava.config.js b/compatibility-checks/ava.config.js new file mode 100644 index 0000000..91554c1 --- /dev/null +++ b/compatibility-checks/ava.config.js @@ -0,0 +1,9 @@ +module.exports = { + extensions: { + ts: 'commonjs', + }, + nodeArguments: [ + '--require=tsx/cjs' + ], + failWithoutAssertions: false +} \ No newline at end of file diff --git a/compatibility-checks/jest.config.js b/compatibility-checks/jest.config.js new file mode 100644 index 0000000..b413e10 --- /dev/null +++ b/compatibility-checks/jest.config.js @@ -0,0 +1,5 @@ +/** @type {import('ts-jest').JestConfigWithTsJest} */ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', +}; \ No newline at end of file diff --git a/compatibility-checks/package-lock.json b/compatibility-checks/package-lock.json new file mode 100644 index 0000000..c7a0171 --- /dev/null +++ b/compatibility-checks/package-lock.json @@ -0,0 +1,8350 @@ +{ + "name": "substitute-compatibility-checks", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "substitute-compatibility-checks", + "version": "0.0.0", + "license": "MIT", + "devDependencies": { + "@types/mocha": "^10.0.6", + "@types/node": "^20.11.25", + "ansi-regex": "^6.0.1", + "ava": "^6.1.2", + "jest": "^29.7.0", + "mocha": "^10.3.0", + "ts-jest": "^29.1.2", + "tsx": "^4.7.1", + "typescript": "^5.4.2", + "vitest": "^1.3.1" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/substitute-js#section-contribute" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@ava/typescript": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@ava/typescript/-/typescript-3.0.1.tgz", + "integrity": "sha512-/JXIUuKsvkaneaiA9ckk3ksFTqvu0mDNlChASrTe2BnDsvMbhQdPWyqQjJ9WRJWVhhs5TWn1/0Pp1G6Rv8Syrw==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "escape-string-regexp": "^5.0.0", + "execa": "^5.1.1" + }, + "engines": { + "node": ">=12.22 <13 || >=14.17 <15 || >=16.4 <17 || >=17" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.0.tgz", + "integrity": "sha512-fQfkg0Gjkza3nf0c7/w6Xf34BW4YvzNfACRLmmb7XRLa6XHdR+K9AlJlxneFfWYf6uhOzuzZVTjF/8KfndZANw==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.24.0", + "@babel/parser": "^7.24.0", + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.0", + "@babel/types": "^7.24.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.23.6", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", + "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.0.tgz", + "integrity": "sha512-ulDZdc0Aj5uLc5nETsa7EPx2L7rM0YJM8r7ck7U73AXi7qOV44IHHRAYZHY6iU1rr3C5N4NtTmMRUJP6kwCWeA==", + "dev": true, + "dependencies": { + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.0", + "@babel/types": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.0.tgz", + "integrity": "sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", + "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", + "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.0.tgz", + "integrity": "sha512-HfuJlI8qq3dEDmNU5ChzzpZRWq+oxCZQyMzIMEqLho+AQnhMnKQUzH6ydo3RBl/YjPCuk68Y6s0Gx0AeyULiWw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", + "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", + "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", + "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", + "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", + "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", + "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", + "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", + "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", + "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", + "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", + "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", + "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", + "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", + "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", + "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", + "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", + "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", + "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", + "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", + "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", + "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", + "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", + "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/console/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/console/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/console/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/core/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/reporters/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/reporters/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/reporters/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map/node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/transform/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/transform/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/transform/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/transform/node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "dev": true, + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@rollup/pluginutils": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", + "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", + "dev": true, + "dependencies": { + "estree-walker": "^2.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/@rollup/pluginutils/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.12.1.tgz", + "integrity": "sha512-iU2Sya8hNn1LhsYyf0N+L4Gf9Qc+9eBTJJJsaOGUp+7x4n2M9dxTt8UvhJl3oeftSjblSlpCfvjA/IfP3g5VjQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.12.1.tgz", + "integrity": "sha512-wlzcWiH2Ir7rdMELxFE5vuM7D6TsOcJ2Yw0c3vaBR3VOsJFVTx9xvwnAvhgU5Ii8Gd6+I11qNHwndDscIm0HXg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.12.1.tgz", + "integrity": "sha512-YRXa1+aZIFN5BaImK+84B3uNK8C6+ynKLPgvn29X9s0LTVCByp54TB7tdSMHDR7GTV39bz1lOmlLDuedgTwwHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.12.1.tgz", + "integrity": "sha512-opjWJ4MevxeA8FhlngQWPBOvVWYNPFkq6/25rGgG+KOy0r8clYwL1CFd+PGwRqqMFVQ4/Qd3sQu5t7ucP7C/Uw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.12.1.tgz", + "integrity": "sha512-uBkwaI+gBUlIe+EfbNnY5xNyXuhZbDSx2nzzW8tRMjUmpScd6lCQYKY2V9BATHtv5Ef2OBq6SChEP8h+/cxifQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.12.1.tgz", + "integrity": "sha512-0bK9aG1kIg0Su7OcFTlexkVeNZ5IzEsnz1ept87a0TUgZ6HplSgkJAnFpEVRW7GRcikT4GlPV0pbtVedOaXHQQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.12.1.tgz", + "integrity": "sha512-qB6AFRXuP8bdkBI4D7UPUbE7OQf7u5OL+R94JE42Z2Qjmyj74FtDdLGeriRyBDhm4rQSvqAGCGC01b8Fu2LthQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.12.1.tgz", + "integrity": "sha512-sHig3LaGlpNgDj5o8uPEoGs98RII8HpNIqFtAI8/pYABO8i0nb1QzT0JDoXF/pxzqO+FkxvwkHZo9k0NJYDedg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.12.1.tgz", + "integrity": "sha512-nD3YcUv6jBJbBNFvSbp0IV66+ba/1teuBcu+fBBPZ33sidxitc6ErhON3JNavaH8HlswhWMC3s5rgZpM4MtPqQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.12.1.tgz", + "integrity": "sha512-7/XVZqgBby2qp/cO0TQ8uJK+9xnSdJ9ct6gSDdEr4MfABrjTyrW6Bau7HQ73a2a5tPB7hno49A0y1jhWGDN9OQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.12.1.tgz", + "integrity": "sha512-CYc64bnICG42UPL7TrhIwsJW4QcKkIt9gGlj21gq3VV0LL6XNb1yAdHVp1pIi9gkts9gGcT3OfUYHjGP7ETAiw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.12.1.tgz", + "integrity": "sha512-LN+vnlZ9g0qlHGlS920GR4zFCqAwbv2lULrR29yGaWP9u7wF5L7GqWu9Ah6/kFZPXPUkpdZwd//TNR+9XC9hvA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.12.1.tgz", + "integrity": "sha512-n+vkrSyphvmU0qkQ6QBNXCGr2mKjhP08mPRM/Xp5Ck2FV4NrHU+y6axzDeixUrCBHVUS51TZhjqrKBBsHLKb2Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", + "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/mocha": { + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.6.tgz", + "integrity": "sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.11.25", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.25.tgz", + "integrity": "sha512-TBHyJxk2b7HceLVGFcpAUjsa5zIdsPWlR6XHfyGzd0SFu+/NFgQgMAl96MSDZgQDvJAvV6BKsFOrt6zIL09JDw==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true + }, + "node_modules/@types/yargs": { + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true + }, + "node_modules/@vercel/nft": { + "version": "0.26.4", + "resolved": "https://registry.npmjs.org/@vercel/nft/-/nft-0.26.4.tgz", + "integrity": "sha512-j4jCOOXke2t8cHZCIxu1dzKLHLcFmYzC3yqAK6MfZznOL1QIJKd0xcFsXK3zcqzU7ScsE2zWkiMMNHGMHgp+FA==", + "dev": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.5", + "@rollup/pluginutils": "^4.0.0", + "acorn": "^8.6.0", + "acorn-import-attributes": "^1.9.2", + "async-sema": "^3.1.1", + "bindings": "^1.4.0", + "estree-walker": "2.0.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.2", + "node-gyp-build": "^4.2.2", + "resolve-from": "^5.0.0" + }, + "bin": { + "nft": "out/cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@vitest/expect": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.3.1.tgz", + "integrity": "sha512-xofQFwIzfdmLLlHa6ag0dPV8YsnKOCP1KdAeVVh34vSjN2dcUiXYCD9htu/9eM7t8Xln4v03U9HLxLpPlsXdZw==", + "dev": true, + "dependencies": { + "@vitest/spy": "1.3.1", + "@vitest/utils": "1.3.1", + "chai": "^4.3.10" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.3.1.tgz", + "integrity": "sha512-5FzF9c3jG/z5bgCnjr8j9LNq/9OxV2uEBAITOXfoe3rdZJTdO7jzThth7FXv/6b+kdY65tpRQB7WaKhNZwX+Kg==", + "dev": true, + "dependencies": { + "@vitest/utils": "1.3.1", + "p-limit": "^5.0.0", + "pathe": "^1.1.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner/node_modules/p-limit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", + "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@vitest/runner/node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@vitest/snapshot": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.3.1.tgz", + "integrity": "sha512-EF++BZbt6RZmOlE3SuTPu/NfwBF6q4ABS37HHXzs2LUVPBLx2QoY/K0fKpRChSo8eLiuxcbCVfqKgx/dplCDuQ==", + "dev": true, + "dependencies": { + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.3.1.tgz", + "integrity": "sha512-xAcW+S099ylC9VLU7eZfdT9myV67Nor9w9zhf0mGCYJSO+zM2839tOeROTdikOi/8Qeusffvxb/MyBSOja1Uig==", + "dev": true, + "dependencies": { + "tinyspy": "^2.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.3.1.tgz", + "integrity": "sha512-d3Waie/299qqRyHTm2DjADeTaNdNSVsnwHPWrs20JMpjh6eiVq7ggggweO8rc4arhf6rRkWuHKwvxGvejUXZZQ==", + "dev": true, + "dependencies": { + "diff-sequences": "^29.6.3", + "estree-walker": "^3.0.3", + "loupe": "^2.3.7", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-attributes": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.2.tgz", + "integrity": "sha512-O+nfJwNolEA771IYJaiLWK1UAwjNsQmZbTRqqwBYxCgVQTmpFEMvBw6LOIQV0Me339L5UMVYFyRohGnGlQDdIQ==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "dev": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arrgv": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/arrgv/-/arrgv-1.0.2.tgz", + "integrity": "sha512-a4eg4yhp7mmruZDQFqVMlxNRFGi/i1r87pt8SDHy0/I8PqSXoUTlWZRdAZo0VXgvEARcujbtTk8kiZRi1uDGRw==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/arrify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-3.0.0.tgz", + "integrity": "sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/async-sema": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/async-sema/-/async-sema-3.1.1.tgz", + "integrity": "sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==", + "dev": true + }, + "node_modules/ava": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/ava/-/ava-6.1.2.tgz", + "integrity": "sha512-WcpxJ8yZ7mk9ABTinD0IAjcemovSeVGjuuwZx0JS9johREWFeLTl8UP6wd7l6nmnrWqkKZdwaD71a/ocH4qPKw==", + "dev": true, + "dependencies": { + "@vercel/nft": "^0.26.2", + "acorn": "^8.11.3", + "acorn-walk": "^8.3.2", + "ansi-styles": "^6.2.1", + "arrgv": "^1.0.2", + "arrify": "^3.0.0", + "callsites": "^4.1.0", + "cbor": "^9.0.1", + "chalk": "^5.3.0", + "chunkd": "^2.0.1", + "ci-info": "^4.0.0", + "ci-parallel-vars": "^1.0.1", + "cli-truncate": "^4.0.0", + "code-excerpt": "^4.0.0", + "common-path-prefix": "^3.0.0", + "concordance": "^5.0.4", + "currently-unhandled": "^0.4.1", + "debug": "^4.3.4", + "emittery": "^1.0.1", + "figures": "^6.0.1", + "globby": "^14.0.0", + "ignore-by-default": "^2.1.0", + "indent-string": "^5.0.0", + "is-plain-object": "^5.0.0", + "is-promise": "^4.0.0", + "matcher": "^5.0.0", + "memoize": "^10.0.0", + "ms": "^2.1.3", + "p-map": "^7.0.1", + "package-config": "^5.0.0", + "picomatch": "^3.0.1", + "plur": "^5.1.0", + "pretty-ms": "^9.0.0", + "resolve-cwd": "^3.0.0", + "stack-utils": "^2.0.6", + "strip-ansi": "^7.1.0", + "supertap": "^3.0.1", + "temp-dir": "^3.0.0", + "write-file-atomic": "^5.0.1", + "yargs": "^17.7.2" + }, + "bin": { + "ava": "entrypoints/cli.mjs" + }, + "engines": { + "node": "^18.18 || ^20.8 || ^21" + }, + "peerDependencies": { + "@ava/typescript": "*" + }, + "peerDependenciesMeta": { + "@ava/typescript": { + "optional": true + } + } + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/babel-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/babel-jest/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/blueimp-md5": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz", + "integrity": "sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "node_modules/browserslist": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/callsites": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-4.1.0.tgz", + "integrity": "sha512-aBMbD1Xxay75ViYezwT40aQONfr+pSXTHwNKvIXhXD6+LY3F1dLIcceoC5OZKBVHbXcysz1hL9D2w0JJIMXpUw==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001596", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001596.tgz", + "integrity": "sha512-zpkZ+kEr6We7w63ORkoJ2pOfBwBkY/bJrG/UZ90qNb45Isblu8wzDgevEOrRL1r9dWayHjYiiyCMEXPn4DweGQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/cbor": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.2.tgz", + "integrity": "sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==", + "dev": true, + "dependencies": { + "nofilter": "^3.1.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/chai": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", + "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.0.8" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chunkd": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/chunkd/-/chunkd-2.0.1.tgz", + "integrity": "sha512-7d58XsFmOq0j6el67Ug9mHf9ELUXsQXYJBkyxhH/k+6Ke0qXRnv0kbemx+Twc6fRJ07C49lcbdgm9FL1Ei/6SQ==", + "dev": true + }, + "node_modules/ci-info": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.0.0.tgz", + "integrity": "sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/ci-parallel-vars": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ci-parallel-vars/-/ci-parallel-vars-1.0.1.tgz", + "integrity": "sha512-uvzpYrpmidaoxvIQHM+rKSrigjOe9feHYbw4uOI2gdfe1C3xIlxO+kVXq83WQWNniTf8bAxVpy+cQeFQsMERKg==", + "dev": true + }, + "node_modules/cjs-module-lexer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "dev": true + }, + "node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "dev": true, + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/code-excerpt": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/code-excerpt/-/code-excerpt-4.0.0.tgz", + "integrity": "sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==", + "dev": true, + "dependencies": { + "convert-to-spaces": "^2.0.1" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true, + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/common-path-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/concordance": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/concordance/-/concordance-5.0.4.tgz", + "integrity": "sha512-OAcsnTEYu1ARJqWVGwf4zh4JDfHZEaSNlNccFmt8YjB2l/n19/PF2viLINHc57vO4FKIAFl2FWASIGZZWZ2Kxw==", + "dev": true, + "dependencies": { + "date-time": "^3.1.0", + "esutils": "^2.0.3", + "fast-diff": "^1.2.0", + "js-string-escape": "^1.0.1", + "lodash": "^4.17.15", + "md5-hex": "^3.0.1", + "semver": "^7.3.2", + "well-known-symbols": "^2.0.0" + }, + "engines": { + "node": ">=10.18.0 <11 || >=12.14.0 <13 || >=14" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/convert-to-spaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/convert-to-spaces/-/convert-to-spaces-2.0.1.tgz", + "integrity": "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/create-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/create-jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng==", + "dev": true, + "dependencies": { + "array-find-index": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/date-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/date-time/-/date-time-3.1.0.tgz", + "integrity": "sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==", + "dev": true, + "dependencies": { + "time-zone": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dedent": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true + }, + "node_modules/detect-libc": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.696", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.696.tgz", + "integrity": "sha512-SOr0bHP52OvYg2chCsz/0+FUSMGFm8L8HKwPpx3cbwRY24EOemVJtbgTm+IFO8LzhcnPy+hXmTq7ZcZ8uUuaYg==", + "dev": true + }, + "node_modules/emittery": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-1.0.3.tgz", + "integrity": "sha512-tJdCJitoy2lrC2ldJcqN4vkqJ00lT+tOWNT1hBJjO/3FDMJa5TTIiYGCKGkn/WfCyOzUMObeohbVTj00fhiLiA==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/esbuild": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", + "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.19.12", + "@esbuild/android-arm": "0.19.12", + "@esbuild/android-arm64": "0.19.12", + "@esbuild/android-x64": "0.19.12", + "@esbuild/darwin-arm64": "0.19.12", + "@esbuild/darwin-x64": "0.19.12", + "@esbuild/freebsd-arm64": "0.19.12", + "@esbuild/freebsd-x64": "0.19.12", + "@esbuild/linux-arm": "0.19.12", + "@esbuild/linux-arm64": "0.19.12", + "@esbuild/linux-ia32": "0.19.12", + "@esbuild/linux-loong64": "0.19.12", + "@esbuild/linux-mips64el": "0.19.12", + "@esbuild/linux-ppc64": "0.19.12", + "@esbuild/linux-riscv64": "0.19.12", + "@esbuild/linux-s390x": "0.19.12", + "@esbuild/linux-x64": "0.19.12", + "@esbuild/netbsd-x64": "0.19.12", + "@esbuild/openbsd-x64": "0.19.12", + "@esbuild/sunos-x64": "0.19.12", + "@esbuild/win32-arm64": "0.19.12", + "@esbuild/win32-ia32": "0.19.12", + "@esbuild/win32-x64": "0.19.12" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/figures": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", + "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", + "dev": true, + "dependencies": { + "is-unicode-supported": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-up-simple": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.0.tgz", + "integrity": "sha512-q7Us7kcjj2VMePAa02hDAF6d+MzsdsAWEwYyOpwUtlerRBkOEPBCRZrAV4XfcSN8fHAgaD0hP7miwoay6DCprw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "dev": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gauge/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/gauge/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/gauge/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/gauge/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/gauge/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-tsconfig": { + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.3.tgz", + "integrity": "sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/globby": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.1.tgz", + "integrity": "sha512-jOMLD2Z7MAhyG8aJpNOpmziMOP4rPLcc95oQPKXBazW82z+CEgPFBQvEpRUa1KeIMUJo4Wsm+q6uzO/Q/4BksQ==", + "dev": true, + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.2", + "ignore": "^5.2.4", + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "dev": true + }, + "node_modules/hasown": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", + "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/ignore-by-default": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-2.1.0.tgz", + "integrity": "sha512-yiWd4GVmJp0Q6ghmM2B/V3oZGRmjrKLXvHR3TE1nfoXsmoggllfZUQe74EN0fJdPFZu2NIvNdrMMLm3OsV7Ohw==", + "dev": true, + "engines": { + "node": ">=10 <11 || >=12 <13 || >=14" + } + }, + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/irregular-plurals": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.5.0.tgz", + "integrity": "sha512-1ANGLZ+Nkv1ptFb2pa8oG8Lem4krflKuX/gINiHJHjJUKaJHk/SXk5x6K3J+39/p0h1RQ2saROclJJ+QLvETCQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "dev": true + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-unicode-supported": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.0.0.tgz", + "integrity": "sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz", + "integrity": "sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-circus/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-circus/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-circus/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-cli/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-cli/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-cli/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-config/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-config/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-config/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-config/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-diff/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-each/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-each/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-matcher-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-matcher-utils/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-message-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-resolve/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-resolve/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-resolve/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-runner/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-runner/node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/jest-runner/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-snapshot/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-snapshot/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-util/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-util/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/jest-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-validate/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-validate/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-watcher/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-watcher/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-watcher/node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/jest-watcher/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/js-string-escape": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", + "integrity": "sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", + "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", + "dev": true + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/load-json-file": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-7.0.1.tgz", + "integrity": "sha512-Gnxj3ev3mB5TkVBGad0JM6dmLiQL+o0t23JPBZ9sd+yvSLk05mFoqKBw5N8gbbkU4TNXyqCgIrl/VM17OgUIgQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/local-pkg": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", + "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==", + "dev": true, + "dependencies": { + "mlly": "^1.4.2", + "pkg-types": "^1.0.3" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.1" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/magic-string": { + "version": "0.30.8", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", + "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/matcher": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-5.0.0.tgz", + "integrity": "sha512-s2EMBOWtXFc8dgqvoAzKJXxNHibcdJMV0gwqKUaw9E2JBJuGUK7DrNKrA6g/i+v72TT16+6sVm5mS3thaMLQUw==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/md5-hex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/md5-hex/-/md5-hex-3.0.1.tgz", + "integrity": "sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==", + "dev": true, + "dependencies": { + "blueimp-md5": "^2.10.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/memoize": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/memoize/-/memoize-10.0.0.tgz", + "integrity": "sha512-H6cBLgsi6vMWOcCpvVCdFFnl3kerEXbrYh9q+lY6VXvQSmM6CkmV08VOwT+WE2tzIEqRPFfAq3fm4v/UIW6mSA==", + "dev": true, + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sindresorhus/memoize?sponsor=1" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mimic-function": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.0.tgz", + "integrity": "sha512-RBfQ+9X9DpXdEoK7Bu+KeEU6vFhumEIiXKWECPzRBmDserEq4uR2b/VCm0LwpMSosoq2k+Zuxj/GzOr0Fn6h/g==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mlly": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.6.1.tgz", + "integrity": "sha512-vLgaHvaeunuOXHSmEbZ9izxPx3USsk8KCQ8iC+aTlp5sKRSoZvwhHh5L9VbKSaVC6sJDqbyohIS76E2VmHIPAA==", + "dev": true, + "dependencies": { + "acorn": "^8.11.3", + "pathe": "^1.1.2", + "pkg-types": "^1.0.3", + "ufo": "^1.3.2" + } + }, + "node_modules/mocha": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.3.0.tgz", + "integrity": "sha512-uF2XJs+7xSLsrmIvn37i/wnc91nw7XjOQB8ccyx5aEgdnohr7n+rEiZP23WkCYHjilR6+EboEnbq/ZQDz4LSbg==", + "dev": true, + "dependencies": { + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.4", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "8.1.0", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "5.0.1", + "ms": "2.1.3", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "workerpool": "6.2.1", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/mocha/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/mocha/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/mocha/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/mocha/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/mocha/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/mocha/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mocha/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/mocha/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/mocha/node_modules/minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mocha/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mocha/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-gyp-build": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz", + "integrity": "sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==", + "dev": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "node_modules/nofilter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz", + "integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==", + "dev": true, + "engines": { + "node": ">=12.19" + } + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "dev": true, + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/onetime/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.1.tgz", + "integrity": "sha512-2wnaR0XL/FDOj+TgpDuRb2KTjLnu3Fma6b1ZUwGY7LcqenMcvP/YFpjpbPKY6WVGsbuJZRuoUz8iPrt8ORnAFw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-config": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/package-config/-/package-config-5.0.0.tgz", + "integrity": "sha512-GYTTew2slBcYdvRHqjhwaaydVMvn/qrGC323+nKclYioNSLTDUM/lGgtGTgyHVtYcozb+XkE8CNhwcraOmZ9Mg==", + "dev": true, + "dependencies": { + "find-up-simple": "^1.0.0", + "load-json-file": "^7.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-ms": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", + "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-type": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-3.0.1.tgz", + "integrity": "sha512-I3EurrIQMlRc9IaAZnqRR044Phh2DXY+55o7uJ0V+hYZAcQYSuFWsc9q5PvyDHUSCe1Qxn/iBz+78s86zWnGag==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-types": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz", + "integrity": "sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==", + "dev": true, + "dependencies": { + "jsonc-parser": "^3.2.0", + "mlly": "^1.2.0", + "pathe": "^1.1.0" + } + }, + "node_modules/plur": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/plur/-/plur-5.1.0.tgz", + "integrity": "sha512-VP/72JeXqak2KiOzjgKtQen5y3IZHn+9GOuLDafPv0eXa47xq0At93XahYBs26MsifCQ4enGKwbjBTKgb9QJXg==", + "dev": true, + "dependencies": { + "irregular-plurals": "^3.3.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/postcss": { + "version": "8.4.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", + "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/pretty-ms": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.0.0.tgz", + "integrity": "sha512-E9e9HJ9R9NasGOgPaPE8VMeiPKAyWR5jcFpNnwIejslIhWqdqOrb2wShBsncMPUb+BcCd2OPYfh7p2W6oemTng==", + "dev": true, + "dependencies": { + "parse-ms": "^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pure-rand": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", + "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/readdirp/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.12.1.tgz", + "integrity": "sha512-ggqQKvx/PsB0FaWXhIvVkSWh7a/PCLQAsMjBc+nA2M8Rv2/HG0X6zvixAB7KyZBRtifBUhy5k8voQX/mRnABPg==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.12.1", + "@rollup/rollup-android-arm64": "4.12.1", + "@rollup/rollup-darwin-arm64": "4.12.1", + "@rollup/rollup-darwin-x64": "4.12.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.12.1", + "@rollup/rollup-linux-arm64-gnu": "4.12.1", + "@rollup/rollup-linux-arm64-musl": "4.12.1", + "@rollup/rollup-linux-riscv64-gnu": "4.12.1", + "@rollup/rollup-linux-x64-gnu": "4.12.1", + "@rollup/rollup-linux-x64-musl": "4.12.1", + "@rollup/rollup-win32-arm64-msvc": "4.12.1", + "@rollup/rollup-win32-ia32-msvc": "4.12.1", + "@rollup/rollup-win32-x64-msvc": "4.12.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "dev": true, + "dependencies": { + "type-fest": "^0.13.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true + }, + "node_modules/std-env": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", + "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", + "dev": true + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-length/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-length/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-literal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.0.0.tgz", + "integrity": "sha512-f9vHgsCWBq2ugHAkGMiiYY+AYG0D/cbloKKg0nhaaaSNsujdGIpVXCNsrJpCKr5M0f4aI31mr13UjY6GAuXCKA==", + "dev": true, + "dependencies": { + "js-tokens": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/strip-literal/node_modules/js-tokens": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-8.0.3.tgz", + "integrity": "sha512-UfJMcSJc+SEXEl9lH/VLHSZbThQyLpw1vLO1Lb+j4RWDvG3N2f7yj3PVQA3cmkTBNldJ9eFnM+xEXxHIXrYiJw==", + "dev": true + }, + "node_modules/supertap": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/supertap/-/supertap-3.0.1.tgz", + "integrity": "sha512-u1ZpIBCawJnO+0QePsEiOknOfCRq0yERxiAchT0i4li0WHNUJbf0evXXSXOcCAR4M8iMDoajXYmstm/qO81Isw==", + "dev": true, + "dependencies": { + "indent-string": "^5.0.0", + "js-yaml": "^3.14.1", + "serialize-error": "^7.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tar": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/temp-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz", + "integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==", + "dev": true, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/time-zone": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/time-zone/-/time-zone-1.0.0.tgz", + "integrity": "sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/tinybench": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.6.0.tgz", + "integrity": "sha512-N8hW3PG/3aOoZAN5V/NSAEDz0ZixDSSt5b/a05iqtpgfLWMSVuCo7w0k2vVvEjdrIoeGqZzweX2WlyioNIHchA==", + "dev": true + }, + "node_modules/tinypool": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.2.tgz", + "integrity": "sha512-SUszKYe5wgsxnNOVlBYO6IC+8VGWdVGZWAqUxp3UErNBtptZvWbwyUOyzNL59zigz2rCA92QiL3wvG+JDSdJdQ==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", + "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "node_modules/ts-jest": { + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.2.tgz", + "integrity": "sha512-br6GJoH/WUX4pu7FbZXuWGKGNDuU7b8Uj77g/Sp7puZV6EXzuByl6JrECvm0MzVzSTkSHWTihsXt+5XYER5b+g==", + "dev": true, + "dependencies": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "^7.5.3", + "yargs-parser": "^21.0.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^16.10.0 || ^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "node_modules/tsx": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.7.1.tgz", + "integrity": "sha512-8d6VuibXHtlN5E3zFkgY8u4DX7Y3Z27zvvPKVmLon/D4AjuKzarkUBTLDBgj9iTQ0hg5xM7c/mYiRVM+HETf0g==", + "dev": true, + "dependencies": { + "esbuild": "~0.19.10", + "get-tsconfig": "^4.7.2" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", + "integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/ufo": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.4.0.tgz", + "integrity": "sha512-Hhy+BhRBleFjpJ2vchUNN40qgkh0366FWJGqVLYBHev0vpHTrXSA0ryT+74UiW6KWsldNurQMKGqCm1M2zBciQ==", + "dev": true + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/v8-to-istanbul": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", + "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/vite": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.5.tgz", + "integrity": "sha512-BdN1xh0Of/oQafhU+FvopafUp6WaYenLU/NFoL5WyJL++GxkNfieKzBhM24H3HVsPQrlAqB7iJYTHabzaRed5Q==", + "dev": true, + "dependencies": { + "esbuild": "^0.19.3", + "postcss": "^8.4.35", + "rollup": "^4.2.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.3.1.tgz", + "integrity": "sha512-azbRrqRxlWTJEVbzInZCTchx0X69M/XPTCz4H+TLvlTcR/xH/3hkRqhOakT41fMJCMzXTu4UvegkZiEoJAWvng==", + "dev": true, + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.4", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.3.1.tgz", + "integrity": "sha512-/1QJqXs8YbCrfv/GPQ05wAZf2eakUPLPa18vkJAKE7RXOKfVHqMZZ1WlTjiwl6Gcn65M5vpNUB6EFLnEdRdEXQ==", + "dev": true, + "dependencies": { + "@vitest/expect": "1.3.1", + "@vitest/runner": "1.3.1", + "@vitest/snapshot": "1.3.1", + "@vitest/spy": "1.3.1", + "@vitest/utils": "1.3.1", + "acorn-walk": "^8.3.2", + "chai": "^4.3.10", + "debug": "^4.3.4", + "execa": "^8.0.1", + "local-pkg": "^0.5.0", + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "std-env": "^3.5.0", + "strip-literal": "^2.0.0", + "tinybench": "^2.5.1", + "tinypool": "^0.8.2", + "vite": "^5.0.0", + "vite-node": "1.3.1", + "why-is-node-running": "^2.2.2" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "1.3.1", + "@vitest/ui": "1.3.1", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/vitest/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vitest/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/vitest/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vitest/node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vitest/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vitest/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vitest/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/vitest/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "node_modules/well-known-symbols": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/well-known-symbols/-/well-known-symbols-2.0.0.tgz", + "integrity": "sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/why-is-node-running": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz", + "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==", + "dev": true, + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wide-align/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wide-align/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wide-align/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wide-align/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wide-align/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/workerpool": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/write-file-atomic/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/compatibility-checks/package.json b/compatibility-checks/package.json new file mode 100644 index 0000000..b611b98 --- /dev/null +++ b/compatibility-checks/package.json @@ -0,0 +1,40 @@ +{ + "name": "substitute-compatibility-checks", + "version": "0.0.0", + "description": "Checks compatibility of @fluffy-spoon/substitute with various test runners.", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/substitute-js#section-contribute" + }, + "repository": { + "type": "git", + "url": "https://github.com/ffMathy/FluffySpoon.JavaScript.Testing.Faking.git" + }, + "engines": { + "node": ">=20" + }, + "scripts": { + "validate:ava": "ava test-runners/ava/**.ts", + "validate:jest": "jest test-runners/jest/**.ts", + "validate:mocha": "mocha --require tsx/cjs test-runners/mocha/**.ts", + "validate:nodejs": "node --require tsx/cjs --test ./test-runners/nodejs/*.ts", + "validate:vitest": "vitest run ./test-runners/vitest/*.ts", + "test": "node --require tsx/cjs --test test/**" + }, + "devDependencies": { + "@types/mocha": "^10.0.6", + "@types/node": "^20.11.25", + "ansi-regex": "^6.0.1", + "ava": "^6.1.2", + "jest": "^29.7.0", + "mocha": "^10.3.0", + "ts-jest": "^29.1.2", + "tsx": "^4.7.1", + "typescript": "^5.4.2", + "vitest": "^1.3.1" + }, + "volta": { + "node": "20.11.1" + } +} \ No newline at end of file diff --git a/compatibility-checks/test-runners/_common/index.ts b/compatibility-checks/test-runners/_common/index.ts new file mode 100644 index 0000000..3eadf2d --- /dev/null +++ b/compatibility-checks/test-runners/_common/index.ts @@ -0,0 +1,21 @@ +import Substitute from '../../../src' + +interface Library { + subSection: AmbiguousSection +} + +interface AmbiguousSection { + (): string + subMethod: () => string +} + + +export const ambiguousPropertyTypeAssertion = () => { + const lib = Substitute.for() + lib.subSection().returns('subSection as method') + lib.subSection.returns({ subMethod: () => 'subSection as property' } as AmbiguousSection) + + lib.subSection() + lib.subSection.subMethod() + lib.received(2).subSection +} diff --git a/compatibility-checks/test-runners/ava/index.ts b/compatibility-checks/test-runners/ava/index.ts new file mode 100644 index 0000000..e29ce02 --- /dev/null +++ b/compatibility-checks/test-runners/ava/index.ts @@ -0,0 +1,6 @@ +import test from 'ava' +import { ambiguousPropertyTypeAssertion } from '../_common' + +test('can substitute callable interfaces', () => { + ambiguousPropertyTypeAssertion() +}) diff --git a/compatibility-checks/test-runners/jest/index.spec.ts b/compatibility-checks/test-runners/jest/index.spec.ts new file mode 100644 index 0000000..6ddcfea --- /dev/null +++ b/compatibility-checks/test-runners/jest/index.spec.ts @@ -0,0 +1,5 @@ +import { ambiguousPropertyTypeAssertion } from '../_common' + +test('can substitute callable interfaces', () => { + ambiguousPropertyTypeAssertion() +}) diff --git a/compatibility-checks/test-runners/mocha/index.ts b/compatibility-checks/test-runners/mocha/index.ts new file mode 100644 index 0000000..022935c --- /dev/null +++ b/compatibility-checks/test-runners/mocha/index.ts @@ -0,0 +1,6 @@ +import { test } from 'mocha' +import { ambiguousPropertyTypeAssertion } from '../_common' + +test('can substitute callable interfaces', () => { + ambiguousPropertyTypeAssertion() +}) diff --git a/compatibility-checks/test-runners/nodejs/index.ts b/compatibility-checks/test-runners/nodejs/index.ts new file mode 100644 index 0000000..14f7f6b --- /dev/null +++ b/compatibility-checks/test-runners/nodejs/index.ts @@ -0,0 +1,6 @@ +import * as test from 'node:test' +import { ambiguousPropertyTypeAssertion } from '../_common' + +test.test('can substitute callable interfaces', () => { + ambiguousPropertyTypeAssertion() +}) diff --git a/compatibility-checks/test-runners/vitest/index.spec.ts b/compatibility-checks/test-runners/vitest/index.spec.ts new file mode 100644 index 0000000..c81ebe4 --- /dev/null +++ b/compatibility-checks/test-runners/vitest/index.spec.ts @@ -0,0 +1,6 @@ +import { test } from 'vitest' +import { ambiguousPropertyTypeAssertion } from '../_common' + +test('can substitute callable interfaces', () => { + ambiguousPropertyTypeAssertion() +}) diff --git a/compatibility-checks/test/index.ts b/compatibility-checks/test/index.ts new file mode 100644 index 0000000..ce90233 --- /dev/null +++ b/compatibility-checks/test/index.ts @@ -0,0 +1,53 @@ +import * as test from 'node:test' +import * as assert from 'node:assert' +import { execSync } from 'node:child_process' + +type TestRunner = { + name: string + failureAcknowledgementText: string + failureLocationText: string +} + +test.describe('Verifies test runner compatibility', () => { + const failingExec = (command: string): string => { + process.env + const { FORCE_COLOR, ...environment } = { ...process.env, CI: '1', NO_COLOR: '1' } as Partial> + try { + execSync(command, { env: environment, stdio: 'pipe' }) + assert.fail('Execution should have failed with a non-zero exit code. We expect the test runner have 1 failing test.') + } catch (error) { + if (error instanceof assert.AssertionError) throw error + // @ts-expect-error + return error.stdout.toString() + error.stderr.toString() + } + } + + const testRunners: TestRunner[] = [ + { name: 'ava', failureAcknowledgementText: '1 uncaught exception', failureLocationText: 'test-runners/ava/index.ts' }, + { name: 'jest', failureAcknowledgementText: '', failureLocationText: 'test-runners/jest/index.spec.ts' }, + { name: 'mocha', failureAcknowledgementText: '1 failing', failureLocationText: 'can substitute callable interfaces:' }, + { name: 'nodejs', failureAcknowledgementText: 'fail 1', failureLocationText: 'test-runners/nodejs/index.ts' }, + { name: 'vitest', failureAcknowledgementText: '1 error', failureLocationText: 'error originated in "test-runners/vitest/index.spec.ts" test file' } + ] + + testRunners.forEach(testRunner => { + test.describe(testRunner.name, () => { + test.it('reports the uncaught Substitute exception', () => { + const result = failingExec(`npm run validate:${testRunner.name}`) + assert.ok( + result.includes(testRunner.failureAcknowledgementText), + `Could not find the expected failure acknowledgement in the output. Expected "${testRunner.failureAcknowledgementText}"` + ) + assert.ok( + result.includes(testRunner.failureLocationText), + `Could not find the expected failure location in the output. Expected "${testRunner.failureLocationText}"` + ) + assert.ok( + result.includes('SubstituteException: Expected'), + `Could not find the expected exception message in the output: ${result}` + ) + }) + }) + }) +}) + diff --git a/compatibility-checks/tsconfig.json b/compatibility-checks/tsconfig.json new file mode 100644 index 0000000..5b0ab6d --- /dev/null +++ b/compatibility-checks/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "module": "commonjs", + "moduleResolution": "node", + "target": "ESNext", + "baseUrl": ".", + "declaration": true, + "outDir": "dist", + "strict": true, + "removeComments": true + }, + "include": [ + "test-runners/**/*", + "test/**/*" + ] +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 026eb5d..a327bff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,8 +1,2222 @@ { "name": "@fluffy-spoon/substitute", "version": "2.0.0-beta.2", - "lockfileVersion": 1, + "lockfileVersion": 2, "requires": true, + "packages": { + "": { + "name": "@fluffy-spoon/substitute", + "version": "2.0.0-beta.2", + "license": "MIT", + "devDependencies": { + "@ava/typescript": "^3.0.1", + "@sinonjs/fake-timers": "^11.2.2", + "@types/node": "^12.20.55", + "@types/sinonjs__fake-timers": "^8.1.5", + "ava": "^4.3.3", + "typescript": "^4.8.4" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/substitute-js#section-contribute" + } + }, + "node_modules/@ava/typescript": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@ava/typescript/-/typescript-3.0.1.tgz", + "integrity": "sha512-/JXIUuKsvkaneaiA9ckk3ksFTqvu0mDNlChASrTe2BnDsvMbhQdPWyqQjJ9WRJWVhhs5TWn1/0Pp1G6Rv8Syrw==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^5.0.0", + "execa": "^5.1.1" + }, + "engines": { + "node": ">=12.22 <13 || >=14.17 <15 || >=16.4 <17 || >=17" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz", + "integrity": "sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", + "dev": true + }, + "node_modules/@types/sinonjs__fake-timers": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz", + "integrity": "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", + "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/aggregate-error/node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.1.1.tgz", + "integrity": "sha512-qDOv24WjnYuL+wbwHdlsYZFy+cgPtrYw0Tn7GLORicQp9BkQLzrgI3Pm4VyR9ERZ41YTn7KlMPuL1n05WdZvmg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/arrgv": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/arrgv/-/arrgv-1.0.2.tgz", + "integrity": "sha512-a4eg4yhp7mmruZDQFqVMlxNRFGi/i1r87pt8SDHy0/I8PqSXoUTlWZRdAZo0VXgvEARcujbtTk8kiZRi1uDGRw==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/arrify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-3.0.0.tgz", + "integrity": "sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ava": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/ava/-/ava-4.3.3.tgz", + "integrity": "sha512-9Egq/d9R74ExrWohHeqUlexjDbgZJX5jA1Wq4KCTqc3wIfpGEK79zVy4rBtofJ9YKIxs4PzhJ8BgbW5PlAYe6w==", + "dev": true, + "dependencies": { + "acorn": "^8.7.1", + "acorn-walk": "^8.2.0", + "ansi-styles": "^6.1.0", + "arrgv": "^1.0.2", + "arrify": "^3.0.0", + "callsites": "^4.0.0", + "cbor": "^8.1.0", + "chalk": "^5.0.1", + "chokidar": "^3.5.3", + "chunkd": "^2.0.1", + "ci-info": "^3.3.1", + "ci-parallel-vars": "^1.0.1", + "clean-yaml-object": "^0.1.0", + "cli-truncate": "^3.1.0", + "code-excerpt": "^4.0.0", + "common-path-prefix": "^3.0.0", + "concordance": "^5.0.4", + "currently-unhandled": "^0.4.1", + "debug": "^4.3.4", + "del": "^6.1.1", + "emittery": "^0.11.0", + "figures": "^4.0.1", + "globby": "^13.1.1", + "ignore-by-default": "^2.1.0", + "indent-string": "^5.0.0", + "is-error": "^2.2.2", + "is-plain-object": "^5.0.0", + "is-promise": "^4.0.0", + "matcher": "^5.0.0", + "mem": "^9.0.2", + "ms": "^2.1.3", + "p-event": "^5.0.1", + "p-map": "^5.4.0", + "picomatch": "^2.3.1", + "pkg-conf": "^4.0.0", + "plur": "^5.1.0", + "pretty-ms": "^7.0.1", + "resolve-cwd": "^3.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.5", + "strip-ansi": "^7.0.1", + "supertap": "^3.0.1", + "temp-dir": "^2.0.0", + "write-file-atomic": "^4.0.1", + "yargs": "^17.5.1" + }, + "bin": { + "ava": "entrypoints/cli.mjs" + }, + "engines": { + "node": ">=12.22 <13 || >=14.17 <15 || >=16.4 <17 || >=18" + }, + "peerDependencies": { + "@ava/typescript": "*" + }, + "peerDependenciesMeta": { + "@ava/typescript": { + "optional": true + } + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/blueimp-md5": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz", + "integrity": "sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/callsites": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-4.0.0.tgz", + "integrity": "sha512-y3jRROutgpKdz5vzEhWM34TidDU8vkJppF8dszITeb1PQmSqV3DTxyV8G/lyO/DNvtE1YTedehmw9MPZsCBHxQ==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cbor": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-8.1.0.tgz", + "integrity": "sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==", + "dev": true, + "dependencies": { + "nofilter": "^3.1.0" + }, + "engines": { + "node": ">=12.19" + } + }, + "node_modules/chalk": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.1.0.tgz", + "integrity": "sha512-56zD4khRTBoIyzUYAFgDDaPhUMN/fC/rySe6aZGqbj/VWiU2eI3l6ZLOtYGFZAV5v02mwPjtpzlrOveJiz5eZQ==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chunkd": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/chunkd/-/chunkd-2.0.1.tgz", + "integrity": "sha512-7d58XsFmOq0j6el67Ug9mHf9ELUXsQXYJBkyxhH/k+6Ke0qXRnv0kbemx+Twc6fRJ07C49lcbdgm9FL1Ei/6SQ==", + "dev": true + }, + "node_modules/ci-info": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.5.0.tgz", + "integrity": "sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==", + "dev": true + }, + "node_modules/ci-parallel-vars": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ci-parallel-vars/-/ci-parallel-vars-1.0.1.tgz", + "integrity": "sha512-uvzpYrpmidaoxvIQHM+rKSrigjOe9feHYbw4uOI2gdfe1C3xIlxO+kVXq83WQWNniTf8bAxVpy+cQeFQsMERKg==", + "dev": true + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/clean-yaml-object": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/clean-yaml-object/-/clean-yaml-object-0.1.0.tgz", + "integrity": "sha512-3yONmlN9CSAkzNwnRCiJQ7Q2xK5mWuEfL3PuTZcAUzhObbXsfsnMptJzXwz93nc5zn9V9TwCVMmV7w4xsm43dw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cli-truncate": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", + "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", + "dev": true, + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/code-excerpt": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/code-excerpt/-/code-excerpt-4.0.0.tgz", + "integrity": "sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==", + "dev": true, + "dependencies": { + "convert-to-spaces": "^2.0.1" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/common-path-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/concordance": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/concordance/-/concordance-5.0.4.tgz", + "integrity": "sha512-OAcsnTEYu1ARJqWVGwf4zh4JDfHZEaSNlNccFmt8YjB2l/n19/PF2viLINHc57vO4FKIAFl2FWASIGZZWZ2Kxw==", + "dev": true, + "dependencies": { + "date-time": "^3.1.0", + "esutils": "^2.0.3", + "fast-diff": "^1.2.0", + "js-string-escape": "^1.0.1", + "lodash": "^4.17.15", + "md5-hex": "^3.0.1", + "semver": "^7.3.2", + "well-known-symbols": "^2.0.0" + }, + "engines": { + "node": ">=10.18.0 <11 || >=12.14.0 <13 || >=14" + } + }, + "node_modules/convert-to-spaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/convert-to-spaces/-/convert-to-spaces-2.0.1.tgz", + "integrity": "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng==", + "dev": true, + "dependencies": { + "array-find-index": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/date-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/date-time/-/date-time-3.1.0.tgz", + "integrity": "sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==", + "dev": true, + "dependencies": { + "time-zone": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/del": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", + "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", + "dev": true, + "dependencies": { + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/del/node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/del/node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/emittery": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.11.0.tgz", + "integrity": "sha512-S/7tzL6v5i+4iJd627Nhv9cLFIo5weAIlGccqJFpnBoDB8U1TF2k5tez4J/QNuxyyhWuFqHg1L84Kd3m7iXg6g==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/figures": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/figures/-/figures-4.0.1.tgz", + "integrity": "sha512-rElJwkA/xS04Vfg+CaZodpso7VqBknOYbzi6I76hI4X80RUjkSxO2oAyPmGbuXUppywjqndOrQDl817hDnI++w==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^5.0.0", + "is-unicode-supported": "^1.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "dev": true, + "dependencies": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globby": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.2.tgz", + "integrity": "sha512-LKSDZXToac40u8Q1PQtZihbNdTYSNMuWe+K5l+oa6KgDzSvVrHXlJy40hUP522RjAIoNLJYBJi7ow+rbFpIhHQ==", + "dev": true, + "dependencies": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.11", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/ignore-by-default": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-2.1.0.tgz", + "integrity": "sha512-yiWd4GVmJp0Q6ghmM2B/V3oZGRmjrKLXvHR3TE1nfoXsmoggllfZUQe74EN0fJdPFZu2NIvNdrMMLm3OsV7Ohw==", + "dev": true, + "engines": { + "node": ">=10 <11 || >=12 <13 || >=14" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/irregular-plurals": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.3.0.tgz", + "integrity": "sha512-MVBLKUTangM3EfRPFROhmWQQKRDsrgI83J8GS3jXy+OwYqiR2/aoWndYQ5416jLE3uaGgLH7ncme3X9y09gZ3g==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-error": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-error/-/is-error-2.2.2.tgz", + "integrity": "sha512-IOQqts/aHWbiisY5DuPJQ0gcbvaLFCa7fBa9xoLfxBZvQ+ZI/Zh9xoI7Gk+G64N0FdK4AbibytHht2tWgpJWLg==", + "dev": true + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "dev": true + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/js-string-escape": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", + "integrity": "sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/load-json-file": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-7.0.1.tgz", + "integrity": "sha512-Gnxj3ev3mB5TkVBGad0JM6dmLiQL+o0t23JPBZ9sd+yvSLk05mFoqKBw5N8gbbkU4TNXyqCgIrl/VM17OgUIgQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/locate-path": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.1.1.tgz", + "integrity": "sha512-vJXaRMJgRVD3+cUZs3Mncj2mxpt5mP0EmNOsxRSZRMlbqjvxzDEOIUWXGmavo0ZC9+tNZCBLQ66reA11nbpHZg==", + "dev": true, + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "dependencies": { + "p-defer": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/matcher": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-5.0.0.tgz", + "integrity": "sha512-s2EMBOWtXFc8dgqvoAzKJXxNHibcdJMV0gwqKUaw9E2JBJuGUK7DrNKrA6g/i+v72TT16+6sVm5mS3thaMLQUw==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/md5-hex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/md5-hex/-/md5-hex-3.0.1.tgz", + "integrity": "sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==", + "dev": true, + "dependencies": { + "blueimp-md5": "^2.10.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mem": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/mem/-/mem-9.0.2.tgz", + "integrity": "sha512-F2t4YIv9XQUBHt6AOJ0y7lSmP1+cY7Fm1DRh9GClTGzKST7UWLMx6ly9WZdLH/G/ppM5RL4MlQfRT71ri9t19A==", + "dev": true, + "dependencies": { + "map-age-cleaner": "^0.1.3", + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sindresorhus/mem?sponsor=1" + } + }, + "node_modules/mem/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/nofilter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz", + "integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==", + "dev": true, + "engines": { + "node": ">=12.19" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-event": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-5.0.1.tgz", + "integrity": "sha512-dd589iCQ7m1L0bmC5NLlVYfy3TbBEsMUfWx9PyAgPeIcFZ/E2yaTZ4Rz4MiBmmJShviiftHVXOqfnfzJ6kyMrQ==", + "dev": true, + "dependencies": { + "p-timeout": "^5.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dev": true, + "dependencies": { + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-5.5.0.tgz", + "integrity": "sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==", + "dev": true, + "dependencies": { + "aggregate-error": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map/node_modules/aggregate-error": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz", + "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", + "dev": true, + "dependencies": { + "clean-stack": "^4.0.0", + "indent-string": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map/node_modules/clean-stack": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.2.0.tgz", + "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-timeout": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-5.1.0.tgz", + "integrity": "sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz", + "integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkg-conf": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-4.0.0.tgz", + "integrity": "sha512-7dmgi4UY4qk+4mj5Cd8v/GExPo0K+SlY+hulOSdfZ/T6jVH6//y7NtzZo5WrfhDBxuQ0jCa7fLZmNaNh7EWL/w==", + "dev": true, + "dependencies": { + "find-up": "^6.0.0", + "load-json-file": "^7.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/plur": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/plur/-/plur-5.1.0.tgz", + "integrity": "sha512-VP/72JeXqak2KiOzjgKtQen5y3IZHn+9GOuLDafPv0eXa47xq0At93XahYBs26MsifCQ4enGKwbjBTKgb9QJXg==", + "dev": true, + "dependencies": { + "irregular-plurals": "^3.3.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pretty-ms": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz", + "integrity": "sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==", + "dev": true, + "dependencies": { + "parse-ms": "^2.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "dev": true, + "dependencies": { + "type-fest": "^0.13.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/supertap": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/supertap/-/supertap-3.0.1.tgz", + "integrity": "sha512-u1ZpIBCawJnO+0QePsEiOknOfCRq0yERxiAchT0i4li0WHNUJbf0evXXSXOcCAR4M8iMDoajXYmstm/qO81Isw==", + "dev": true, + "dependencies": { + "indent-string": "^5.0.0", + "js-yaml": "^3.14.1", + "serialize-error": "^7.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/time-zone": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/time-zone/-/time-zone-1.0.0.tgz", + "integrity": "sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", + "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/well-known-symbols": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/well-known-symbols/-/well-known-symbols-2.0.0.tgz", + "integrity": "sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yargs": { + "version": "17.6.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.0.tgz", + "integrity": "sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, "dependencies": { "@ava/typescript": { "version": "3.0.1", @@ -40,12 +2254,36 @@ "fastq": "^1.6.0" } }, + "@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz", + "integrity": "sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw==", + "dev": true, + "requires": { + "@sinonjs/commons": "^3.0.0" + } + }, "@types/node": { "version": "12.20.55", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", "dev": true }, + "@types/sinonjs__fake-timers": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz", + "integrity": "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==", + "dev": true + }, "acorn": { "version": "8.8.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", @@ -1333,6 +3571,12 @@ "is-number": "^7.0.0" } }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, "type-fest": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", diff --git a/package.json b/package.json index c7c3b1e..c318b6b 100644 --- a/package.json +++ b/package.json @@ -43,11 +43,12 @@ "build": "rm -rf dist && tsc", "test": "npm run build -- -p spec && ava" }, - "dependencies": {}, "devDependencies": { "@ava/typescript": "^3.0.1", + "@sinonjs/fake-timers": "^11.2.2", "@types/node": "^12.20.55", + "@types/sinonjs__fake-timers": "^8.1.5", "ava": "^4.3.3", "typescript": "^4.8.4" } -} \ No newline at end of file +} diff --git a/spec/regression/issues/178.test.ts b/spec/regression/issues/178.test.ts new file mode 100644 index 0000000..dacf607 --- /dev/null +++ b/spec/regression/issues/178.test.ts @@ -0,0 +1,40 @@ +import test, { ExecutionContext, ThrowsExpectation } from 'ava' +import * as fakeTimers from '@sinonjs/fake-timers' +import { types } from 'util' + +import { Substitute } from '../../../src' +import { SubstituteException } from '../../../src/SubstituteException' + +interface Library { + subSection: Subsection + coreMethod: () => string +} + +interface Subsection { + (): string + subMethod: () => string +} + +const throwsUncaughtException = (cb: () => any, t: ExecutionContext, expectation: ThrowsExpectation) => { + const clock = fakeTimers.install({ toFake: ['nextTick'] }) + cb() + t.throws(() => clock.tick(1), expectation) + clock.uninstall() +} + +test('can substitute callable interfaces', async t => { + const lib = Substitute.for() + lib.subSection().returns('subSection as method') + lib.subSection.returns({ subMethod: () => 'subSection as property' } as Subsection) + + t.is('subSection as method', lib.subSection()) + t.true(types.isProxy(lib.subSection), 'Expected proxy: given the context, it\'s not possible to determine the property type') + t.is('subSection as property', lib.subSection.subMethod()) + + lib.received().subSection() + lib.received(1).subSection() + lib.received(2).subSection + t.throws(() => lib.didNotReceive().subSection(), { instanceOf: SubstituteException }) + t.throws(() => lib.received(2).subSection(), { instanceOf: SubstituteException }) + throwsUncaughtException(() => lib.received(3).subSection, t, { instanceOf: SubstituteException }) +}) diff --git a/src/RecordedArguments.ts b/src/RecordedArguments.ts index 318962c..3ea8910 100644 --- a/src/RecordedArguments.ts +++ b/src/RecordedArguments.ts @@ -2,6 +2,13 @@ import { inspect, InspectOptions, isDeepStrictEqual } from 'util' import { Argument, AllArguments } from './Arguments' type ArgumentsClass = 'plain' | 'with-predicate' | 'wildcard' +const argumentsClassDigitMapper: Record = { + plain: 0, + 'with-predicate': 1, + wildcard: 2, + none: 4 +} + export class RecordedArguments { private _argumentsClass?: ArgumentsClass private _value?: any[] @@ -23,18 +30,9 @@ export class RecordedArguments { static sort(objectWithArguments: T[]): T[] { return objectWithArguments.sort((a, b) => { - const aClass = a.recordedArguments.argumentsClass - const bClass = b.recordedArguments.argumentsClass - - if (aClass === bClass) return 0 - if (aClass === 'plain') return -1 - if (bClass === 'plain') return 1 - - if (aClass === 'with-predicate') return -1 - if (bClass === 'with-predicate') return 1 - - if (aClass === 'wildcard') return -1 - return 1 + const aClass = a.recordedArguments.argumentsClass ?? 'none' + const bClass = b.recordedArguments.argumentsClass ?? 'none' + return argumentsClassDigitMapper[aClass] - argumentsClassDigitMapper[bClass] }) } diff --git a/src/SubstituteNode.ts b/src/SubstituteNode.ts index a48d0d4..03119ce 100644 --- a/src/SubstituteNode.ts +++ b/src/SubstituteNode.ts @@ -2,9 +2,10 @@ import { inspect, InspectOptions, types } from 'util' import { SubstituteNodeBase } from './SubstituteNodeBase' import { RecordedArguments } from './RecordedArguments' -import { ClearType as ClearTypeMap, PropertyType as PropertyTypeMap, isAssertionMethod, isSubstituteMethod, isSubstitutionMethod, textModifier } from './Utilities' +import { ClearType as ClearTypeMap, PropertyType as PropertyTypeMap, isAssertionMethod, isSubstituteMethod, isSubstitutionMethod, textModifier, isConfigurationMethod } from './Utilities' import { SubstituteException } from './SubstituteException' import type { FilterFunction, SubstituteContext, SubstitutionMethod, ClearType, PropertyType } from './Types' +import type { ObjectSubstitute } from './Transformations' const instance = Symbol('Substitute:Instance') const clearTypeToFilterMap: Record> = { @@ -16,7 +17,7 @@ const clearTypeToFilterMap: Record> = type SpecialProperty = typeof instance | typeof inspect.custom | 'then' type RootContext = { substituteMethodsEnabled: boolean } -export class SubstituteNode extends SubstituteNodeBase { +export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitute { private _proxy: SubstituteNode private _rootContext: RootContext @@ -25,7 +26,7 @@ export class SubstituteNode extends SubstituteNodeBase { private _recordedArguments: RecordedArguments = RecordedArguments.none() private _context: SubstituteContext = 'none' - private _disabledSubstituteMethods: boolean = false + private _retrySubstitutionExecutionAttempt: boolean = false private constructor(key: PropertyKey, parent?: SubstituteNode) { super(key, parent) @@ -36,21 +37,28 @@ export class SubstituteNode extends SubstituteNodeBase { { get: function (target, property) { if (target.isSpecialProperty(property)) return target.evaluateSpecialProperty(property) + if (target._retrySubstitutionExecutionAttempt) return target.reattemptSubstitutionExecution()[property] const newNode = SubstituteNode.createChild(property, target) - if (target.isRoot() && !target.rootContext.substituteMethodsEnabled) newNode.disableSubstituteMethods() - if (target.isIntermediateNode() && target.isAssertion) newNode.executeAssertion() - return newNode.read() + if (target.isAssertion) newNode.executeAssertion() + if (target.isRoot() && target.rootContext.substituteMethodsEnabled && (isAssertionMethod(property) || isConfigurationMethod(property))) { + newNode.assignContext(property) + return newNode[property].bind(newNode) + } + return newNode.attemptSubstitutionExecution() }, set: function (target, property, value) { const newNode = SubstituteNode.createChild(property, target) - newNode.write(value) + newNode.handleSetter(value) if (target.isAssertion) newNode.executeAssertion() return true }, apply: function (target, _thisArg, rawArguments) { target.handleMethod(rawArguments) - if (target.hasContext) target.handleSpecialContext() - return (target.parent?.isAssertion ?? false) ? target.executeAssertion() : target.read() + if (target.hasDepthOfAtLeast(2)) { + if (isSubstitutionMethod(target.property)) return target.parent.assignContext(target.property) + if (target.parent.isAssertion) return target.executeAssertion() + } + return target.isAssertion ? target.proxy : target.attemptSubstitutionExecution() } } ) @@ -106,41 +114,49 @@ export class SubstituteNode extends SubstituteNodeBase { return this._recordedArguments } - public get disabledSubstituteMethods(): boolean { - return this._disabledSubstituteMethods + public received(amount?: number): SubstituteNode { + this.handleMethod([amount]) + return this.proxy } - public assignContext(context: SubstituteContext): void { - this._context = context + public didNotReceive(): SubstituteNode { + this.handleMethod([0]) + return this.proxy } - public disableSubstituteMethods() { - this._disabledSubstituteMethods = true + public mimick() { + throw new Error('Mimick is not implemented yet') } - public read(): SubstituteNode | void | never { - if ((this.parent?.isSubstitution ?? false) || this.context === 'clearSubstitute') return - if (this.isAssertion) return this.proxy + public clearSubstitute(clearType: ClearType = ClearTypeMap.All): void { + this.handleMethod([clearType]) + const filter = clearTypeToFilterMap[clearType] + this.recorder.clearRecords(filter) + } - const mostSuitableSubstitution = this.getMostSuitableSubstitution() - return mostSuitableSubstitution instanceof SubstituteNode - ? mostSuitableSubstitution.executeSubstitution(this.recordedArguments) - : this.proxy + public [inspect.custom](...args: [_: number, options: InspectOptions]): string { + return types.isProxy(this) ? this[inspect.custom](...args) : this.printableForm(...args) } - public write(value: any) { - this._accessorType = 'set' - this._recordedArguments = RecordedArguments.from([value]) + private assignContext(context: SubstituteContext): void { + if (!isSubstituteMethod(context)) throw new Error(`Cannot assign context for property ${context.toString()}`) + this._context = context } - public clear() { - if (!this.recordedArguments.hasArguments()) throw new TypeError('No args') - const clearType: ClearType = this.recordedArguments.value[0] ?? ClearTypeMap.All - const filter = clearTypeToFilterMap[clearType] - this.recorder.clearRecords(filter) + private reattemptSubstitutionExecution(): SubstituteNode | any { + const result = this.attemptSubstitutionExecution() + this._retrySubstitutionExecutionAttempt = false + return result } - public executeSubstitution(contextArguments: RecordedArguments) { + private attemptSubstitutionExecution(): SubstituteNode | any { + const mostSuitableSubstitution = this.getMostSuitableSubstitution() + return mostSuitableSubstitution instanceof SubstituteNode + ? mostSuitableSubstitution.executeSubstitution(this.recordedArguments) + : this.proxy + } + + private executeSubstitution(contextArguments: RecordedArguments) { if (!this.hasChild()) throw new TypeError('Substitue node has no child') if (!this.child.recordedArguments.hasArguments()) throw new TypeError('Child args') @@ -166,20 +182,20 @@ export class SubstituteNode extends SubstituteNodeBase { } } - public executeAssertion(): void | never { - if (!this.isIntermediateNode()) throw new Error('Not possible') + private executeAssertion(): void | never { + if (!this.hasDepthOfAtLeast(2)) throw new Error('Not possible') if (!this.parent.recordedArguments.hasArguments()) throw new TypeError('Parent args') - const siblings = [...this.getAllSiblings().filter(n => !n.hasContext && n.accessorType === this.accessorType)] - const expectedCount = this.parent.recordedArguments.value[0] ?? undefined const finiteExpectation = expectedCount !== undefined if (finiteExpectation && (!Number.isInteger(expectedCount) || expectedCount < 0)) throw new Error('Expected count has to be a positive integer') - const hasRecordedCalls = siblings.length > 0 + const siblings = [...this.getAllSiblings().filter(n => !n.hasContext && n.accessorType === this.accessorType)] + const hasBeenCalled = siblings.length > 0 + const hasSiblingOfSamePropertyType = siblings.some(sibling => sibling.propertyType === this.propertyType) const allRecordedArguments = siblings.map(sibling => sibling.recordedArguments) if ( - !hasRecordedCalls && + !hasBeenCalled && (!finiteExpectation || expectedCount > 0) ) throw SubstituteException.forCallCountMissMatch( // Here we don't know here if it's a property or method, so we should throw something more generic { expected: expectedCount, received: 0 }, @@ -187,43 +203,57 @@ export class SubstituteNode extends SubstituteNodeBase { { expected: this.recordedArguments, received: allRecordedArguments } ) - if (!hasRecordedCalls || siblings.some(sibling => sibling.propertyType === this.propertyType)) { + if (!hasBeenCalled || hasSiblingOfSamePropertyType) { + this._scheduledAssertionException = undefined const actualCount = allRecordedArguments.filter(r => r.match(this.recordedArguments)).length const matchedExpectation = (!finiteExpectation && actualCount > 0) || expectedCount === actualCount - - if (!matchedExpectation) throw SubstituteException.forCallCountMissMatch( + if (matchedExpectation) return + const exception = SubstituteException.forCallCountMissMatch( { expected: expectedCount, received: actualCount }, { type: this.propertyType, value: this.property }, { expected: this.recordedArguments, received: allRecordedArguments } ) + const potentialMethodAssertion = this.propertyType === PropertyTypeMap.Property && siblings.some(sibling => sibling.propertyType === PropertyTypeMap.Method) + if (potentialMethodAssertion) this.schedulePropertyAssertionException(exception) + else throw exception } } - public handleMethod(rawArguments: any[]): void { - this._propertyType = PropertyTypeMap.Method - this._recordedArguments = RecordedArguments.from(rawArguments) - this.tryToAssignContext() + private schedulePropertyAssertionException(exception: SubstituteException) { + this._scheduledAssertionException = exception + process.nextTick(() => { + const nodeIsStillProperty = this.propertyType === PropertyTypeMap.Property + if (nodeIsStillProperty && this._scheduledAssertionException !== undefined) throw this._scheduledAssertionException + }) } - private tryToAssignContext() { - if (!isSubstituteMethod(this.property)) return - if (this.isIntermediateNode() && isSubstitutionMethod(this.property)) return this.parent.assignContext(this.property) - if (this.disabledSubstituteMethods) return - this.assignContext(this.property) + private _scheduledAssertionException: SubstituteException | undefined + + private handleSetter(value: any) { + this._accessorType = 'set' + this._recordedArguments = RecordedArguments.from([value]) } - private handleSpecialContext(): void { - if (this.context === 'clearSubstitute') return this.clear() - if (this.context === 'didNotReceive') this._recordedArguments = RecordedArguments.from([0]) + private handleMethod(rawArguments: any[]): void { + this._propertyType = PropertyTypeMap.Method + this._recordedArguments = RecordedArguments.from(rawArguments) } - private getMostSuitableSubstitution(): SubstituteNode { - const nodes = this.getAllSiblings().filter(node => node.isSubstitution && - node.propertyType === this.propertyType && - node.recordedArguments.match(this.recordedArguments) + private getMostSuitableSubstitution(): SubstituteNode | void { + const commonSuitableSubstitutionsSet = this.getAllSiblings().filter(node => node.isSubstitution) + const strictSuitableSubstitutionsSet = commonSuitableSubstitutionsSet.filter( + node => node.propertyType === this.propertyType && node.recordedArguments.match(this.recordedArguments) ) - const sortedNodes = RecordedArguments.sort([...nodes]) - return sortedNodes[0] + const potentialSuitableSubstitutionsSet = this.propertyType === PropertyTypeMap.Property && !this._retrySubstitutionExecutionAttempt ? + commonSuitableSubstitutionsSet.filter(node => node.propertyType === PropertyTypeMap.Method) : + [] + + const strictSuitableSubstitutions = [...strictSuitableSubstitutionsSet] + const potentialSuitableSubstitutions = [...potentialSuitableSubstitutionsSet] + const hasSuitableSubstitutions = strictSuitableSubstitutions.length > 0 + const onlySubstitutionsWithThisNodePropertyType = potentialSuitableSubstitutions.length === 0 + if (onlySubstitutionsWithThisNodePropertyType && hasSuitableSubstitutions) return RecordedArguments.sort(strictSuitableSubstitutions)[0] + if (!onlySubstitutionsWithThisNodePropertyType) this._retrySubstitutionExecutionAttempt = true } private isSpecialProperty(property: PropertyKey): property is SpecialProperty { @@ -243,10 +273,6 @@ export class SubstituteNode extends SubstituteNodeBase { } } - public [inspect.custom](...args: [_: number, options: InspectOptions]): string { - return types.isProxy(this) ? this[inspect.custom](...args) : this.printableForm(...args) - } - private printableForm(_: number, options: InspectOptions): string { return this.isRoot() ? this.printRootNode(options) : this.printNode(options) } @@ -260,14 +286,12 @@ export class SubstituteNode extends SubstituteNodeBase { private printNode(options: InspectOptions): string { const hasContext = this.hasContext const args = inspect(this.recordedArguments, options) - const label = this.isSubstitution - ? '=> ' - : this.isAssertion - ? `${this.child?.property.toString()}` - : '' - const s = hasContext - ? ` ${label}${inspect(this.child?.recordedArguments, options)}` - : '' + const label = this.isSubstitution ? + '=> ' : + this.isAssertion ? + `${this.child?.property.toString()}` : + '' + const s = hasContext ? `${label}${inspect(this.child?.recordedArguments, options)}` : '' const printableNode = `${this.propertyType}<${this.property.toString()}>: ${args}${s}` return hasContext ? textModifier.italic(printableNode) : printableNode diff --git a/src/SubstituteNodeBase.ts b/src/SubstituteNodeBase.ts index 4cf2193..9cbff07 100644 --- a/src/SubstituteNodeBase.ts +++ b/src/SubstituteNodeBase.ts @@ -63,8 +63,8 @@ export abstract class SubstituteNodeBase extends Function { return typeof this._parent === 'undefined' } - protected isIntermediateNode(): this is this & { parent: ThisType } { - return !this.isRoot() + protected hasDepthOfAtLeast(depth: TDepth): this is (TDepth extends 0 ? this & { parent: undefined } : this & { parent: ThisType }) { + return this.depth >= depth } protected getAllSiblings(): RecordsSet { @@ -74,7 +74,4 @@ export abstract class SubstituteNodeBase extends Function { protected hasChild(): this is this & { child: ThisType } { return this.child instanceof SubstituteNodeBase } - - public abstract read(): void - public abstract write(value: any): void } \ No newline at end of file diff --git a/src/Transformations.ts b/src/Transformations.ts index f824b68..e927822 100644 --- a/src/Transformations.ts +++ b/src/Transformations.ts @@ -44,8 +44,8 @@ export type FunctionSubstitute = ((...args: TArguments) => (TReturnType & MockObjectMixin)) & ((allArguments: AllArguments) => (TReturnType & MockObjectMixin)) -export type NoArgumentFunctionSubstitute = (() => (TReturnType & NoArgumentMockObjectMixin)) -export type PropertySubstitute = (TReturnType & NoArgumentMockObjectMixin); +export type NoArgumentFunctionSubstitute = () => TReturnType & NoArgumentMockObjectMixin; +export type PropertySubstitute = TReturnType & NoArgumentMockObjectMixin; type OneArgumentRequiredFunction = (requiredInput: TArgs, ...restInputs: TArgs[]) => TReturnType; @@ -69,20 +69,25 @@ type MockObjectMixin = BaseMockObjectMixi type TerminatingFunction = ((...args: TArguments) => void) & ((arg: AllArguments) => void) +type TryToExpandNonArgumentedTerminatingFunction = + TObject[TProperty] extends (...args: []) => unknown ? () => void : {} +type TryToExpandArgumentedTerminatingFunction = + TObject[TProperty] extends (...args: any) => any ? FunctionSubstituteWithOverloads : {} + type TerminatingObject = { - [P in keyof T]: - T[P] extends (...args: infer F) => any ? - F extends [] ? () => void : - FunctionSubstituteWithOverloads : - T[P]; + [P in keyof T]: TryToExpandNonArgumentedTerminatingFunction & TryToExpandArgumentedTerminatingFunction & T[P]; } +type TryToExpandNonArgumentedFunctionSubstitute = + TObject[TProperty] extends (...args: []) => infer R ? NoArgumentFunctionSubstitute : {} + +type TryToExpandArgumentedFunctionSubstitute = + TObject[TProperty] extends (...args: infer F) => infer R ? F extends [] ? {} : FunctionSubstituteWithOverloads : {} + +type TryToExpandPropertySubstitute = PropertySubstitute + type ObjectSubstituteTransformation> = { - [P in keyof T]: - T[P] extends (...args: infer F) => infer R ? - F extends [] ? NoArgumentFunctionSubstitute : - FunctionSubstituteWithOverloads : - PropertySubstitute; + [P in keyof T]: TryToExpandNonArgumentedFunctionSubstitute & TryToExpandArgumentedFunctionSubstitute & TryToExpandPropertySubstitute; } export type OmitProxyMethods = Omit; diff --git a/src/Utilities.ts b/src/Utilities.ts index c7c6757..87414f4 100644 --- a/src/Utilities.ts +++ b/src/Utilities.ts @@ -10,7 +10,7 @@ export const PropertyType = { export const isAssertionMethod = (property: PropertyKey): property is AssertionMethod => property === 'received' || property === 'didNotReceive' -export const isConfigurationMethod = (property: PropertyKey): property is ConfigurationMethod => property === 'clearSubstitute' +export const isConfigurationMethod = (property: PropertyKey): property is ConfigurationMethod => property === 'clearSubstitute' || property === 'mimick' export const isSubstitutionMethod = (property: PropertyKey): property is SubstitutionMethod => property === 'mimicks' || property === 'returns' || property === 'throws' || property === 'resolves' || property === 'rejects' From cf95e144f31be482d4047930406607d4f877e0f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrique=20P=C3=B6hlmann?= <45039845+notanengineercom@users.noreply.github.com> Date: Fri, 8 Mar 2024 16:48:27 +0100 Subject: [PATCH 43/46] 2.0.0-beta.3 (#279) --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index a327bff..ecd2088 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@fluffy-spoon/substitute", - "version": "2.0.0-beta.2", + "version": "2.0.0-beta.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@fluffy-spoon/substitute", - "version": "2.0.0-beta.2", + "version": "2.0.0-beta.3", "license": "MIT", "devDependencies": { "@ava/typescript": "^3.0.1", diff --git a/package.json b/package.json index c318b6b..737ac2a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@fluffy-spoon/substitute", - "version": "2.0.0-beta.2", + "version": "2.0.0-beta.3", "description": "TypeScript port of NSubstitute, which aims to provide a much more fluent mocking opportunity for strong-typed languages", "license": "MIT", "funding": { From 30c69d9586fd6ccc3affa1bdab9c956d7c679715 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrique=20P=C3=B6hlmann?= <45039845+notanengineercom@users.noreply.github.com> Date: Thu, 21 Mar 2024 22:16:01 +0100 Subject: [PATCH 44/46] Improve assertion messages when running expectations (#281) * tweak Arg generated description * capture stacktraces on each call * add textBuilder and improve assertion messages * bump to node18 * refactor utilities * replace utilities * add rest of constants and stringifies * replace stringify & raw values * support serialization in different contexts * 2.0.0-beta.4 --- .github/workflows/codeql-analysis.yml | 9 +-- .github/workflows/nodejs.yml | 8 ++- .github/workflows/npm-publish.yml | 24 ++++--- package-lock.json | 40 ++++++++---- package.json | 7 +- spec/regression/index.test.ts | 28 +++++--- spec/regression/issues/138.test.ts | 13 ++++ spec/regression/issues/27.test.ts | 39 ++++++++++++ src/Arguments.ts | 13 ++-- src/SubstituteException.ts | 61 ++++++++---------- src/SubstituteNode.ts | 92 +++++++++++---------------- src/Types.ts | 15 ++++- src/Utilities.ts | 48 -------------- src/index.ts | 4 +- src/utilities/Constants.ts | 40 ++++++++++++ src/utilities/Guards.ts | 64 +++++++++++++++++++ src/utilities/Stringify.ts | 88 +++++++++++++++++++++++++ src/utilities/TextBuilder.ts | 79 +++++++++++++++++++++++ src/utilities/index.ts | 4 ++ 19 files changed, 494 insertions(+), 182 deletions(-) create mode 100644 spec/regression/issues/138.test.ts create mode 100644 spec/regression/issues/27.test.ts delete mode 100644 src/Utilities.ts create mode 100644 src/utilities/Constants.ts create mode 100644 src/utilities/Guards.ts create mode 100644 src/utilities/Stringify.ts create mode 100644 src/utilities/TextBuilder.ts create mode 100644 src/utilities/index.ts diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 480b5a5..50341b8 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -16,17 +16,18 @@ jobs: strategy: fail-fast: false matrix: - language: ['javascript'] + language: ['javascript-typescript'] # Learn more... # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. fetch-depth: 2 + show-progress: false # If this run was triggered by a pull request event, then checkout # the head of the pull request instead of the merge commit. @@ -35,9 +36,9 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 13b561c..b566fe3 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -6,12 +6,14 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [12, 14, 16, 18, 20] + node-version: [18, 20, 21] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 + with: + show-progress: false - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} cache: 'npm' diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index 648763e..6198b96 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -8,10 +8,12 @@ jobs: build-test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 + - uses: actions/checkout@v4 with: - node-version: 14 + show-progress: false + - uses: actions/setup-node@v4 + with: + node-version: 18 cache: 'npm' - run: npm ci --ignore-scripts - run: npm test @@ -20,10 +22,12 @@ jobs: needs: build-test runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 + - uses: actions/checkout@v4 + with: + show-progress: false + - uses: actions/setup-node@v4 with: - node-version: 14 + node-version: 18 registry-url: https://registry.npmjs.org/ cache: 'npm' - run: npm ci --ignore-scripts @@ -43,10 +47,12 @@ jobs: contents: read packages: write steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 + - uses: actions/checkout@v4 + with: + show-progress: false + - uses: actions/setup-node@v4 with: - node-version: 14 + node-version: 18 registry-url: https://npm.pkg.github.com/ cache: 'npm' - run: npm ci --ignore-scripts diff --git a/package-lock.json b/package-lock.json index ecd2088..8e56c98 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,17 @@ { "name": "@fluffy-spoon/substitute", - "version": "2.0.0-beta.3", + "version": "2.0.0-beta.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@fluffy-spoon/substitute", - "version": "2.0.0-beta.3", + "version": "2.0.0-beta.4", "license": "MIT", "devDependencies": { "@ava/typescript": "^3.0.1", "@sinonjs/fake-timers": "^11.2.2", - "@types/node": "^12.20.55", + "@types/node": "^18.19.22", "@types/sinonjs__fake-timers": "^8.1.5", "ava": "^4.3.3", "typescript": "^4.8.4" @@ -91,10 +91,13 @@ } }, "node_modules/@types/node": { - "version": "12.20.55", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", - "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", - "dev": true + "version": "18.19.22", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.22.tgz", + "integrity": "sha512-p3pDIfuMg/aXBmhkyanPshdfJuX5c5+bQjYLIikPLXAUycEogij/c50n/C+8XOA5L93cU4ZRXtn+dNQGi0IZqQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/@types/sinonjs__fake-timers": { "version": "8.1.5", @@ -1987,6 +1990,12 @@ "node": ">=4.2.0" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, "node_modules/well-known-symbols": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/well-known-symbols/-/well-known-symbols-2.0.0.tgz", @@ -2273,10 +2282,13 @@ } }, "@types/node": { - "version": "12.20.55", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", - "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", - "dev": true + "version": "18.19.22", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.22.tgz", + "integrity": "sha512-p3pDIfuMg/aXBmhkyanPshdfJuX5c5+bQjYLIikPLXAUycEogij/c50n/C+8XOA5L93cU4ZRXtn+dNQGi0IZqQ==", + "dev": true, + "requires": { + "undici-types": "~5.26.4" + } }, "@types/sinonjs__fake-timers": { "version": "8.1.5", @@ -3589,6 +3601,12 @@ "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", "dev": true }, + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, "well-known-symbols": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/well-known-symbols/-/well-known-symbols-2.0.0.tgz", diff --git a/package.json b/package.json index 737ac2a..631e8d1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@fluffy-spoon/substitute", - "version": "2.0.0-beta.3", + "version": "2.0.0-beta.4", "description": "TypeScript port of NSubstitute, which aims to provide a much more fluent mocking opportunity for strong-typed languages", "license": "MIT", "funding": { @@ -46,9 +46,12 @@ "devDependencies": { "@ava/typescript": "^3.0.1", "@sinonjs/fake-timers": "^11.2.2", - "@types/node": "^12.20.55", + "@types/node": "^18.19.22", "@types/sinonjs__fake-timers": "^8.1.5", "ava": "^4.3.3", "typescript": "^4.8.4" + }, + "volta": { + "node": "18.19.1" } } diff --git a/spec/regression/index.test.ts b/spec/regression/index.test.ts index 6a5aff0..16aba9e 100644 --- a/spec/regression/index.test.ts +++ b/spec/regression/index.test.ts @@ -121,13 +121,19 @@ test('class method received', t => { t.notThrows(() => substitute.received(1).c('hi', 'the1re')) t.notThrows(() => substitute.received().c('hi', 'there')) - const expectedMessage = 'Expected 7 calls to the method c with arguments [\'hi\', \'there\'], but received 4 of such calls.\n' + - 'All calls received to method c:\n' + - '-> call with arguments [\'hi\', \'there\']\n' + - '-> call with arguments [\'hi\', \'the1re\']\n' + - '-> call with arguments [\'hi\', \'there\']\n' + - '-> call with arguments [\'hi\', \'there\']\n' + - '-> call with arguments [\'hi\', \'there\']' + const expectedMessage = 'Call count mismatch in @Substitute.c:\n' + + `Expected to receive 7 method calls matching c('hi', 'there'), but received 4.\n` + + 'All property or method calls to @Substitute.c received so far:\n' + + `› ✔ @Substitute.c('hi', 'there')\n` + + ` called at (${process.cwd()}/spec/regression/index.test.ts:114:18)\n` + + `› ✘ @Substitute.c('hi', 'the1re')\n` + + ` called at (${process.cwd()}/spec/regression/index.test.ts:115:18)\n` + + `› ✔ @Substitute.c('hi', 'there')\n` + + ` called at (${process.cwd()}/spec/regression/index.test.ts:116:18)\n` + + `› ✔ @Substitute.c('hi', 'there')\n` + + ` called at (${process.cwd()}/spec/regression/index.test.ts:117:18)\n` + + `› ✔ @Substitute.c('hi', 'there')\n` + + ` called at (${process.cwd()}/spec/regression/index.test.ts:118:18)\n` const { message } = t.throws(() => { substitute.received(7).c('hi', 'there') }) t.is(message.replace(textModifierRegex, ''), expectedMessage) }) @@ -142,9 +148,11 @@ test('received call matches after partial mocks using property instance mimicks' substitute.received(1).c('lala', 'bar') t.notThrows(() => substitute.received(1).c('lala', 'bar')) - const expectedMessage = 'Expected 2 calls to the method c with arguments [\'lala\', \'bar\'], but received 1 of such calls.\n' + - 'All calls received to method c:\n' + - '-> call with arguments [\'lala\', \'bar\']' + const expectedMessage = 'Call count mismatch in @Substitute.c:\n' + + `Expected to receive 2 method calls matching c('lala', 'bar'), but received 1.\n` + + 'All property or method calls to @Substitute.c received so far:\n' + + `› ✔ @Substitute.c('lala', 'bar')\n` + + ` called at (${process.cwd()}/spec/regression/index.test.ts:145:13)\n` const { message } = t.throws(() => substitute.received(2).c('lala', 'bar')) t.is(message.replace(textModifierRegex, ''), expectedMessage) t.deepEqual(substitute.d, 1337) diff --git a/spec/regression/issues/138.test.ts b/spec/regression/issues/138.test.ts new file mode 100644 index 0000000..ed6a8c0 --- /dev/null +++ b/spec/regression/issues/138.test.ts @@ -0,0 +1,13 @@ +import test from 'ava' + +import { Substitute } from '../../../src' + +interface Library { } + +test('issue 138: serializes to JSON compatible data', t => { + const lib = Substitute.for() + const result = JSON.stringify(lib) + + t.true(typeof result === 'string') + t.is(result, '"@Substitute {\\n}"') +}) diff --git a/spec/regression/issues/27.test.ts b/spec/regression/issues/27.test.ts new file mode 100644 index 0000000..9bb1b75 --- /dev/null +++ b/spec/regression/issues/27.test.ts @@ -0,0 +1,39 @@ +import test from 'ava' +import { types } from 'util' + +import { Substitute } from '../../../src' + +interface Library { + subSection: () => string +} + +// Adapted snipped extracted from https://github.com/angular/angular/blob/main/packages/compiler/src/parse_util.ts#L176 +// This is to reproduce the behavior of the Angular compiler. This function tries to extract the id from a reference. +const identifierName = (compileIdentifier: { reference: any } | null | undefined): string | null => { + if (!compileIdentifier || !compileIdentifier.reference) { + return null + } + const ref = compileIdentifier.reference + if (ref['__anonymousType']) { + return ref['__anonymousType'] + } +} + +test('issue 27: mocks should work with Angular TestBed', t => { + const lib = Substitute.for() + lib.subSection().returns('This is the mocked value') + const result = identifierName({ reference: lib }) + + t.not(result, null) + t.true(types.isProxy(result)) + + const jitId = `jit_${result}` + t.is(jitId, 'jit_property<__anonymousType>: ') +}) + +test('issue 27: subsitute node can be coerced to a primitive value', t => { + const lib = Substitute.for() + t.true(typeof `${lib}` === 'string') + t.true(typeof (lib + '') === 'string') + t.is(`${lib}`, '@Substitute {\n}') +}) diff --git a/src/Arguments.ts b/src/Arguments.ts index 5b60c02..6db6412 100644 --- a/src/Arguments.ts +++ b/src/Arguments.ts @@ -3,11 +3,14 @@ type ArgumentOptions = { inverseMatch?: boolean } class BaseArgument { + private _description: string constructor( - private _description: string, + description: string, private _matchingFunction: PredicateFunction, private _options?: ArgumentOptions - ) { } + ) { + this._description = `${this._options?.inverseMatch ? 'Not ' : ''}${description}` + } matches(arg: T) { const inverseMatch = this._options?.inverseMatch ?? false @@ -33,7 +36,7 @@ export class Argument extends BaseArgument { export class AllArguments extends BaseArgument { private readonly _type = 'AllArguments'; constructor() { - super('{all}', () => true, {}) + super('Arg.all{}', () => true, {}) } get type(): 'AllArguments' { return this._type // TODO: Needed? @@ -60,7 +63,7 @@ export namespace Arg { type Is = (predicate: PredicateFunction>) => ReturnArg> const isFunction = (predicate: PredicateFunction>, options?: ArgumentOptions) => new Argument( - `{predicate ${toStringify(predicate)}}`, predicate, options + `Arg.is{${toStringify(predicate)}}`, predicate, options ) export const is = createInversable(isFunction) as Inversable @@ -79,7 +82,7 @@ export namespace Arg { type Any = (type?: T) => MapAnyReturn const anyFunction = (type: AnyType = 'any', options?: ArgumentOptions) => { - const description = `{type ${type}}` + const description = `Arg.any{${type}}` const predicate = (x: any) => { switch (type) { case 'any': diff --git a/src/SubstituteException.ts b/src/SubstituteException.ts index 4595a01..b396057 100644 --- a/src/SubstituteException.ts +++ b/src/SubstituteException.ts @@ -1,53 +1,46 @@ -import { PropertyType } from './Types' -import { RecordedArguments } from './RecordedArguments' -import { PropertyType as PropertyTypeMap, stringifyArguments, stringifyCalls, textModifier, plurify } from './Utilities' - -enum SubstituteExceptionTypes { - CallCountMissMatch = 'CallCountMissMatch', - PropertyNotMocked = 'PropertyNotMocked' -} +import { SubstituteNodeModel, SubstituteExceptionType } from './Types' +import { stringify, TextBuilder, constants } from './utilities' export class SubstituteException extends Error { - type?: SubstituteExceptionTypes + public type?: SubstituteExceptionType - constructor(msg: string, exceptionType?: SubstituteExceptionTypes) { + constructor(msg: string, exceptionType?: SubstituteExceptionType) { super(msg) - Error.captureStackTrace(this, SubstituteException) this.name = new.target.name this.type = exceptionType + const errorConstructor = exceptionType !== undefined ? SubstituteException[`for${exceptionType}`] : undefined + Error.captureStackTrace(this, errorConstructor) } - static forCallCountMissMatch( - count: { expected: number | undefined, received: number }, - property: { type: PropertyType, value: PropertyKey }, - calls: { expected: RecordedArguments, received: RecordedArguments[] } + public static forCallCountMismatch( + expected: { count: number | undefined, call: SubstituteNodeModel }, + received: { matchCount: number, calls: SubstituteNodeModel[] } ) { - const propertyValue = textModifier.bold(property.value.toString()) - const commonMessage = `Expected ${textModifier.bold( - count.expected === undefined ? '1 or more' : count.expected.toString() - )} ${plurify('call', count.expected)} to the ${textModifier.italic(property.type)} ${propertyValue}` - - const messageForMethods = property.type === PropertyTypeMap.Method ? ` with ${stringifyArguments(calls.expected)}` : '' // should also apply for setters (instead of methods only) - const receivedMessage = `, but received ${textModifier.bold(count.received < 1 ? 'none' : count.received.toString())} of such calls.` - - const callTrace = calls.received.length > 0 - ? `\nAll calls received to ${textModifier.italic(property.type)} ${propertyValue}:${stringifyCalls(calls.received)}` - : '' - - return new this( - commonMessage + messageForMethods + receivedMessage + callTrace, - SubstituteExceptionTypes.CallCountMissMatch - ) + const callPath = `@Substitute.${expected.call.property.toString()}` + + const textBuilder = new TextBuilder() + .add('Call count mismatch in ') + .add('@Substitute.', t => t.underline()) + .add(expected.call.property.toString(), t => t.bold().underline()) + .add(':') + .newLine().add('Expected to receive ') + .addParts(...stringify.expectation(expected)) + .add(', but received ') + .add(received.matchCount < 1 ? 'none' : received.matchCount.toString(), t => t.faint()) + .add('.') + if (received.calls.length > 0) textBuilder.newLine().add(`All property or method calls to ${callPath} received so far:${stringify.receivedCalls(callPath, expected.call, received.calls)}`) + + return new this(textBuilder.toString(), constants.EXCEPTION.callCountMismatch) } - static forPropertyNotMocked(property: PropertyKey) { + public static forPropertyNotMocked(property: PropertyKey) { return new this( `There is no mock for property: ${property.toString()}`, - SubstituteExceptionTypes.PropertyNotMocked + constants.EXCEPTION.propertyNotMocked ) } - static generic(message: string) { + public static generic(message: string) { return new this(message) } } \ No newline at end of file diff --git a/src/SubstituteNode.ts b/src/SubstituteNode.ts index 03119ce..3abc044 100644 --- a/src/SubstituteNode.ts +++ b/src/SubstituteNode.ts @@ -2,32 +2,34 @@ import { inspect, InspectOptions, types } from 'util' import { SubstituteNodeBase } from './SubstituteNodeBase' import { RecordedArguments } from './RecordedArguments' -import { ClearType as ClearTypeMap, PropertyType as PropertyTypeMap, isAssertionMethod, isSubstituteMethod, isSubstitutionMethod, textModifier, isConfigurationMethod } from './Utilities' +import { constants, is, stringify } from './utilities' import { SubstituteException } from './SubstituteException' -import type { FilterFunction, SubstituteContext, SubstitutionMethod, ClearType, PropertyType } from './Types' +import type { FilterFunction, SubstituteContext, SubstitutionMethod, ClearType, PropertyType, SubstituteNodeModel, AccessorType } from './Types' import type { ObjectSubstitute } from './Transformations' const instance = Symbol('Substitute:Instance') -const clearTypeToFilterMap: Record> = { +const clearTypeToFilterMap: Record> = { all: () => true, - receivedCalls: node => !node.hasContext, - substituteValues: node => node.isSubstitution + receivedCalls: node => is.CONTEXT.none(node.context), + substituteValues: node => is.CONTEXT.substitution(node.context) } -type SpecialProperty = typeof instance | typeof inspect.custom | 'then' +type SpecialProperty = typeof instance | typeof inspect.custom | typeof Symbol.toPrimitive | 'then' | 'toJSON' type RootContext = { substituteMethodsEnabled: boolean } -export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitute { +export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitute, SubstituteNodeModel { private _proxy: SubstituteNode private _rootContext: RootContext - private _propertyType: PropertyType = PropertyTypeMap.Property - private _accessorType: 'get' | 'set' = 'get' + private _propertyType: PropertyType = constants.PROPERTY.property + private _accessorType: AccessorType = constants.ACCESSOR.get private _recordedArguments: RecordedArguments = RecordedArguments.none() - private _context: SubstituteContext = 'none' + private _context: SubstituteContext = constants.CONTEXT.none private _retrySubstitutionExecutionAttempt: boolean = false + public stack?: string + private constructor(key: PropertyKey, parent?: SubstituteNode) { super(key, parent) if (this.isRoot()) this._rootContext = { substituteMethodsEnabled: true } @@ -40,10 +42,11 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu if (target._retrySubstitutionExecutionAttempt) return target.reattemptSubstitutionExecution()[property] const newNode = SubstituteNode.createChild(property, target) if (target.isAssertion) newNode.executeAssertion() - if (target.isRoot() && target.rootContext.substituteMethodsEnabled && (isAssertionMethod(property) || isConfigurationMethod(property))) { + if (target.isRoot() && target.rootContext.substituteMethodsEnabled && (is.method.assertion(property) || is.method.configuration(property))) { newNode.assignContext(property) return newNode[property].bind(newNode) } + Error.captureStackTrace(newNode, this.get) return newNode.attemptSubstitutionExecution() }, set: function (target, property, value) { @@ -55,9 +58,10 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu apply: function (target, _thisArg, rawArguments) { target.handleMethod(rawArguments) if (target.hasDepthOfAtLeast(2)) { - if (isSubstitutionMethod(target.property)) return target.parent.assignContext(target.property) + if (is.method.substitution(target.property)) return target.parent.assignContext(target.property) if (target.parent.isAssertion) return target.executeAssertion() } + Error.captureStackTrace(target, this.apply) return target.isAssertion ? target.proxy : target.attemptSubstitutionExecution() } } @@ -91,11 +95,11 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu } get isSubstitution(): boolean { - return isSubstitutionMethod(this.context) + return is.method.substitution(this.context) } get isAssertion(): boolean { - return isAssertionMethod(this.context) + return is.method.assertion(this.context) } get property(): PropertyKey { @@ -128,7 +132,7 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu throw new Error('Mimick is not implemented yet') } - public clearSubstitute(clearType: ClearType = ClearTypeMap.All): void { + public clearSubstitute(clearType: ClearType = constants.CLEAR.all): void { this.handleMethod([clearType]) const filter = clearTypeToFilterMap[clearType] this.recorder.clearRecords(filter) @@ -139,7 +143,7 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu } private assignContext(context: SubstituteContext): void { - if (!isSubstituteMethod(context)) throw new Error(`Cannot assign context for property ${context.toString()}`) + if (!is.method.substitute(context)) throw new Error(`Cannot assign context for property ${context.toString()}`) this._context = context } @@ -168,7 +172,7 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu case 'throws': throw substitutionValue case 'mimicks': - if (this.propertyType === PropertyTypeMap.Property) return substitutionValue() + if (is.PROPERTY.property(this.propertyType)) return substitutionValue() if (!contextArguments.hasArguments()) throw new TypeError('Context arguments cannot be undefined') return substitutionValue(...contextArguments.value) case 'resolves': @@ -185,7 +189,7 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu private executeAssertion(): void | never { if (!this.hasDepthOfAtLeast(2)) throw new Error('Not possible') if (!this.parent.recordedArguments.hasArguments()) throw new TypeError('Parent args') - const expectedCount = this.parent.recordedArguments.value[0] ?? undefined + const expectedCount: number | undefined = this.parent.recordedArguments.value[0] ?? undefined const finiteExpectation = expectedCount !== undefined if (finiteExpectation && (!Number.isInteger(expectedCount) || expectedCount < 0)) throw new Error('Expected count has to be a positive integer') @@ -197,10 +201,9 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu if ( !hasBeenCalled && (!finiteExpectation || expectedCount > 0) - ) throw SubstituteException.forCallCountMissMatch( // Here we don't know here if it's a property or method, so we should throw something more generic - { expected: expectedCount, received: 0 }, - { type: this.propertyType, value: this.property }, - { expected: this.recordedArguments, received: allRecordedArguments } + ) throw SubstituteException.forCallCountMismatch( // Here we don't know here if it's a property or method, so we should throw something more generic + { count: expectedCount, call: this }, + { matchCount: 0, calls: siblings } ) if (!hasBeenCalled || hasSiblingOfSamePropertyType) { @@ -208,12 +211,11 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu const actualCount = allRecordedArguments.filter(r => r.match(this.recordedArguments)).length const matchedExpectation = (!finiteExpectation && actualCount > 0) || expectedCount === actualCount if (matchedExpectation) return - const exception = SubstituteException.forCallCountMissMatch( - { expected: expectedCount, received: actualCount }, - { type: this.propertyType, value: this.property }, - { expected: this.recordedArguments, received: allRecordedArguments } + const exception = SubstituteException.forCallCountMismatch( + { count: expectedCount, call: this }, + { matchCount: actualCount, calls: siblings } ) - const potentialMethodAssertion = this.propertyType === PropertyTypeMap.Property && siblings.some(sibling => sibling.propertyType === PropertyTypeMap.Method) + const potentialMethodAssertion = is.PROPERTY.property(this.propertyType) && siblings.some(sibling => is.PROPERTY.method(sibling.propertyType)) if (potentialMethodAssertion) this.schedulePropertyAssertionException(exception) else throw exception } @@ -222,7 +224,7 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu private schedulePropertyAssertionException(exception: SubstituteException) { this._scheduledAssertionException = exception process.nextTick(() => { - const nodeIsStillProperty = this.propertyType === PropertyTypeMap.Property + const nodeIsStillProperty = is.PROPERTY.property(this.propertyType) if (nodeIsStillProperty && this._scheduledAssertionException !== undefined) throw this._scheduledAssertionException }) } @@ -230,12 +232,12 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu private _scheduledAssertionException: SubstituteException | undefined private handleSetter(value: any) { - this._accessorType = 'set' + this._accessorType = constants.ACCESSOR.set this._recordedArguments = RecordedArguments.from([value]) } private handleMethod(rawArguments: any[]): void { - this._propertyType = PropertyTypeMap.Method + this._propertyType = constants.PROPERTY.method this._recordedArguments = RecordedArguments.from(rawArguments) } @@ -244,8 +246,8 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu const strictSuitableSubstitutionsSet = commonSuitableSubstitutionsSet.filter( node => node.propertyType === this.propertyType && node.recordedArguments.match(this.recordedArguments) ) - const potentialSuitableSubstitutionsSet = this.propertyType === PropertyTypeMap.Property && !this._retrySubstitutionExecutionAttempt ? - commonSuitableSubstitutionsSet.filter(node => node.propertyType === PropertyTypeMap.Method) : + const potentialSuitableSubstitutionsSet = is.PROPERTY.property(this.propertyType) && !this._retrySubstitutionExecutionAttempt ? + commonSuitableSubstitutionsSet.filter(node => is.PROPERTY.method(node.propertyType)) : [] const strictSuitableSubstitutions = [...strictSuitableSubstitutionsSet] @@ -257,14 +259,16 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu } private isSpecialProperty(property: PropertyKey): property is SpecialProperty { - return property === SubstituteNode.instance || property === inspect.custom || property === 'then' + return property === SubstituteNode.instance || property === inspect.custom || property === Symbol.toPrimitive || property === 'then' || property === 'toJSON' } private evaluateSpecialProperty(property: SpecialProperty) { switch (property) { case SubstituteNode.instance: return this + case 'toJSON': case inspect.custom: + case Symbol.toPrimitive: return this.printableForm.bind(this) case 'then': return @@ -274,26 +278,6 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu } private printableForm(_: number, options: InspectOptions): string { - return this.isRoot() ? this.printRootNode(options) : this.printNode(options) - } - - private printRootNode(options: InspectOptions): string { - const records = inspect(this.recorder, options) - const instanceName = '*Substitute' // Substitute - return instanceName + ' {' + records + '\n}' - } - - private printNode(options: InspectOptions): string { - const hasContext = this.hasContext - const args = inspect(this.recordedArguments, options) - const label = this.isSubstitution ? - '=> ' : - this.isAssertion ? - `${this.child?.property.toString()}` : - '' - const s = hasContext ? `${label}${inspect(this.child?.recordedArguments, options)}` : '' - - const printableNode = `${this.propertyType}<${this.property.toString()}>: ${args}${s}` - return hasContext ? textModifier.italic(printableNode) : printableNode + return this.isRoot() ? stringify.rootNode(this, inspect(this.recorder, options)) : stringify.node(this, this.child, options) } } \ No newline at end of file diff --git a/src/Types.ts b/src/Types.ts index d9b6228..1fe75b6 100644 --- a/src/Types.ts +++ b/src/Types.ts @@ -1,4 +1,7 @@ +import { RecordedArguments } from './RecordedArguments' + export type PropertyType = 'method' | 'property' +export type AccessorType = 'get' | 'set' export type AssertionMethod = 'received' | 'didNotReceive' export type ConfigurationMethod = 'clearSubstitute' | 'mimick' export type SubstitutionMethod = 'mimicks' | 'throws' | 'returns' | 'resolves' | 'rejects' @@ -9,4 +12,14 @@ export type SubstituteContext = SubstituteMethod | 'none' export type ClearType = 'all' | 'receivedCalls' | 'substituteValues' -export type FilterFunction = (item: T) => boolean \ No newline at end of file +export type SubstituteExceptionType = 'CallCountMismatch' | 'PropertyNotMocked' + +export type FilterFunction = (item: T) => boolean + +export type SubstituteNodeModel = { + propertyType: PropertyType + property: PropertyKey + context: SubstituteContext + recordedArguments: RecordedArguments + stack?: string +} \ No newline at end of file diff --git a/src/Utilities.ts b/src/Utilities.ts deleted file mode 100644 index 87414f4..0000000 --- a/src/Utilities.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { inspect } from 'util' -import { RecordedArguments } from './RecordedArguments' -import type { AssertionMethod, ConfigurationMethod, SubstituteMethod, SubstitutionMethod } from './Types' - -export const PropertyType = { - Method: 'method', - Property: 'property' -} as const - -export const isAssertionMethod = (property: PropertyKey): property is AssertionMethod => - property === 'received' || property === 'didNotReceive' - -export const isConfigurationMethod = (property: PropertyKey): property is ConfigurationMethod => property === 'clearSubstitute' || property === 'mimick' - -export const isSubstitutionMethod = (property: PropertyKey): property is SubstitutionMethod => - property === 'mimicks' || property === 'returns' || property === 'throws' || property === 'resolves' || property === 'rejects' - -export const isSubstituteMethod = (property: PropertyKey): property is SubstituteMethod => - isSubstitutionMethod(property) || isConfigurationMethod(property) || isAssertionMethod(property) - -export const ClearType = { - All: 'all', - ReceivedCalls: 'receivedCalls', - SubstituteValues: 'substituteValues' -} as const - -export const stringifyArguments = (args: RecordedArguments) => textModifier.faint( - args.hasArguments() ? - `arguments [${args.value.map(x => inspect(x, { colors: true })).join(', ')}]` : - 'no arguments' -) - -export const stringifyCalls = (calls: RecordedArguments[]) => { - if (calls.length === 0) return ' (no calls)' - - const key = '\n-> call with ' - const callsDetails = calls.map(stringifyArguments) - return `${key}${callsDetails.join(key)}` -} - -const baseTextModifier = (str: string, modifierStart: number, modifierEnd: number) => `\x1b[${modifierStart}m${str}\x1b[${modifierEnd}m` -export const textModifier = { - bold: (str: string) => baseTextModifier(str, 1, 22), - faint: (str: string) => baseTextModifier(str, 2, 22), - italic: (str: string) => baseTextModifier(str, 3, 23) -} - -export const plurify = (str: string, count?: number) => `${str}${count === 1 ? '' : 's'}` \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index ffd8ce0..66a2325 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,9 @@ import { Substitute, SubstituteOf } from './Substitute' +import { constants } from './utilities' +const clear = constants.CLEAR export { Arg } from './Arguments' export { Substitute, SubstituteOf } -export { ClearType } from './Utilities' +export { clear as ClearType } export default Substitute \ No newline at end of file diff --git a/src/utilities/Constants.ts b/src/utilities/Constants.ts new file mode 100644 index 0000000..ae7f42f --- /dev/null +++ b/src/utilities/Constants.ts @@ -0,0 +1,40 @@ +import { AccessorType, ClearType, PropertyType, SubstituteContext, SubstituteExceptionType } from '../Types' + +type ValueToMap = { [key in T as Uncapitalize]: key } +const propertyTypes: ValueToMap = { + method: 'method', + property: 'property' +} +const accessorTypes: ValueToMap = { + get: 'get', + set: 'set' +} +const clearTypes: ValueToMap = { + all: 'all', + receivedCalls: 'receivedCalls', + substituteValues: 'substituteValues' +} +const contextTypes: ValueToMap = { + none: 'none', + received: 'received', + didNotReceive: 'didNotReceive', + clearSubstitute: 'clearSubstitute', + mimick: 'mimick', + mimicks: 'mimicks', + throws: 'throws', + returns: 'returns', + resolves: 'resolves', + rejects: 'rejects' +} +const SubstituteExceptionTypes: ValueToMap = { + callCountMismatch: 'CallCountMismatch', + propertyNotMocked: 'PropertyNotMocked' +} + +export const constants = { + PROPERTY: propertyTypes, + ACCESSOR: accessorTypes, + CLEAR: clearTypes, + CONTEXT: contextTypes, + EXCEPTION: SubstituteExceptionTypes +} \ No newline at end of file diff --git a/src/utilities/Guards.ts b/src/utilities/Guards.ts new file mode 100644 index 0000000..26db312 --- /dev/null +++ b/src/utilities/Guards.ts @@ -0,0 +1,64 @@ +import { AssertionMethod, ClearType, ConfigurationMethod, PropertyType, SubstituteMethod, SubstitutionMethod, SubstituteContext } from '../Types' +import { constants } from './Constants' + +const isAssertionMethod = (property: PropertyKey): property is AssertionMethod => + property === 'received' || property === 'didNotReceive' +const isConfigurationMethod = (property: PropertyKey): property is ConfigurationMethod => property === 'clearSubstitute' || property === 'mimick' +const isSubstitutionMethod = (property: PropertyKey): property is SubstitutionMethod => + property === 'mimicks' || property === 'returns' || property === 'throws' || property === 'resolves' || property === 'rejects' +const isSubstituteMethod = (property: PropertyKey): property is SubstituteMethod => + isSubstitutionMethod(property) || isConfigurationMethod(property) || isAssertionMethod(property) + +const isPropertyProperty = (value: PropertyType): value is (typeof constants['PROPERTY']['property']) => value === constants.PROPERTY.property +const isPropertyMethod = (value: PropertyType): value is (typeof constants['PROPERTY']['method']) => value === constants.PROPERTY.method + +const isClearAll = (value: ClearType): value is (typeof constants['CLEAR']['all']) => value === constants.CLEAR.all +const isClearReceivedCalls = (value: ClearType): value is (typeof constants['CLEAR']['receivedCalls']) => value === constants.CLEAR.receivedCalls +const isClearSubstituteValues = (value: ClearType): value is (typeof constants['CLEAR']['substituteValues']) => value === constants.CLEAR.substituteValues + +const isContextNone = (value: SubstituteContext): value is (typeof constants['CONTEXT']['none']) => value === constants.CONTEXT.none +const isContextReceived = (value: SubstituteContext): value is (typeof constants['CONTEXT']['received']) => value === constants.CONTEXT.received +const isContextDidNotReceive = (value: SubstituteContext): value is (typeof constants['CONTEXT']['didNotReceive']) => value === constants.CONTEXT.didNotReceive +const isContextClearSubstitute = (value: SubstituteContext): value is (typeof constants['CONTEXT']['clearSubstitute']) => value === constants.CONTEXT.clearSubstitute +const isContextMimick = (value: SubstituteContext): value is (typeof constants['CONTEXT']['mimick']) => value === constants.CONTEXT.mimick +const isContextMimicks = (value: SubstituteContext): value is (typeof constants['CONTEXT']['mimicks']) => value === constants.CONTEXT.mimicks +const isContextThrows = (value: SubstituteContext): value is (typeof constants['CONTEXT']['throws']) => value === constants.CONTEXT.throws +const isContextReturns = (value: SubstituteContext): value is (typeof constants['CONTEXT']['returns']) => value === constants.CONTEXT.returns +const isContextResolves = (value: SubstituteContext): value is (typeof constants['CONTEXT']['resolves']) => value === constants.CONTEXT.resolves +const isContextRejects = (value: SubstituteContext): value is (typeof constants['CONTEXT']['rejects']) => value === constants.CONTEXT.rejects +const isContextSubstitution = (value: SubstituteContext): value is SubstitutionMethod => isSubstitutionMethod(value) +const isContextAssertion = (value: SubstituteContext): value is AssertionMethod => isAssertionMethod(value) + +export const method = { + assertion: isAssertionMethod, + configuration: isConfigurationMethod, + substitution: isSubstitutionMethod, + substitute: isSubstituteMethod, +} + +export const PROPERTY = { + property: isPropertyProperty, + method: isPropertyMethod +} + +export const CLEAR = { + all: isClearAll, + receivedCalls: isClearReceivedCalls, + substituteValues: isClearSubstituteValues +} + +export const CONTEXT = { + none: isContextNone, + received: isContextReceived, + didNotReceive: isContextDidNotReceive, + clearSubstitute: isContextClearSubstitute, + mimick: isContextMimick, + mimicks: isContextMimicks, + throws: isContextThrows, + returns: isContextReturns, + resolves: isContextResolves, + rejects: isContextRejects, + substitution: isContextSubstitution, + assertion: isContextAssertion +} + diff --git a/src/utilities/Stringify.ts b/src/utilities/Stringify.ts new file mode 100644 index 0000000..b4ec0bb --- /dev/null +++ b/src/utilities/Stringify.ts @@ -0,0 +1,88 @@ +import { InspectOptions, inspect } from 'node:util' +import { RecordedArguments } from '../RecordedArguments' +import { SubstituteNodeModel } from '../Types' +import { TextBuilder, TextPart } from './TextBuilder' +import * as is from './Guards' + +const stringifyArguments = (args: RecordedArguments, options?: InspectOptions) => args.hasArguments() + ? `(${args.value.map(x => inspect(x, { colors: true, ...options })).join(', ')})` + : '' + +const matchBasedPrefix = (isMatch?: boolean) => { + switch (isMatch) { + case true: return '✔ ' + case false: return '✘ ' + default: return '' + } +} + +const matchBasedTextPartModifier = (isMatch?: boolean) => (part: TextPart) => isMatch === undefined + ? part + : isMatch + ? part.faint() + : part.bold() + +const stringifyCall = (context: { callPath: string, expectedArguments?: RecordedArguments }) => { + return (call: SubstituteNodeModel): TextPart[] => { + const isMatch = context.expectedArguments?.match(call.recordedArguments) + const textBuilder = new TextBuilder() + .add(matchBasedPrefix(isMatch)) + .add(context.callPath) + .add(stringifyArguments(call.recordedArguments)) + if (call.stack !== undefined && isMatch !== undefined) textBuilder.newLine().add(call.stack.split('\n')[1].replace('at ', 'called at '), t => t.faint()) + return textBuilder.parts.map(matchBasedTextPartModifier(isMatch)) + } +} + +const plurify = (str: string, count?: number) => `${str}${count === 1 ? '' : 's'}` + +const stringifyExpectation = (expected: { count: number | undefined, call: SubstituteNodeModel }) => { + const textBuilder = new TextBuilder() + textBuilder.add(expected.count === undefined ? '1 or more' : expected.count.toString(), t => t.bold()) + .add(' ') + .add(expected.call.propertyType, t => t.bold()) + .add(plurify(' call', expected.count), t => t.bold()) + .add(' matching ') + .addParts(...stringifyCall({ callPath: expected.call.property.toString() })(expected.call).map(t => t.bold())) + return textBuilder.parts +} + +const createKey = () => { + const textBuilder = new TextBuilder() + textBuilder.newLine().add('› ') + return textBuilder +} + +const stringifyReceivedCalls = (callPath: string, expected: SubstituteNodeModel, received: SubstituteNodeModel[]) => { + const textBuilder = new TextBuilder() + const stringify = stringifyCall({ callPath, expectedArguments: expected.recordedArguments }) + received.forEach(receivedCall => textBuilder.addParts(...createKey().parts, ...stringify(receivedCall))) + return textBuilder.newLine().toString() +} + +const stringifyRootNode = (_node: SubstituteNodeModel, stringifiedChildNodes: string) => { + const instanceName = '@Substitute' + return instanceName + ' {' + stringifiedChildNodes + '\n}' + +} + +const stringifyNode = (node: SubstituteNodeModel, childNode: SubstituteNodeModel | undefined, options: InspectOptions) => { + const hasContext = !is.CONTEXT.none(node.context) + const args = stringifyArguments(node.recordedArguments, options) + const label = is.CONTEXT.substitution(node.context) ? + ' => ' : + is.CONTEXT.assertion(node.context) ? + `${childNode?.property.toString()}` : + '' + const s = hasContext ? `${label}${inspect(childNode?.recordedArguments, options)}` : '' + + return `${node.propertyType}<${node.property.toString()}>: ${args}${s}` +} + +export const stringify = { + call: stringifyCall, + expectation: stringifyExpectation, + receivedCalls: stringifyReceivedCalls, + rootNode: stringifyRootNode, + node: stringifyNode +} diff --git a/src/utilities/TextBuilder.ts b/src/utilities/TextBuilder.ts new file mode 100644 index 0000000..b0a22d4 --- /dev/null +++ b/src/utilities/TextBuilder.ts @@ -0,0 +1,79 @@ +export class TextPart { + private _modifiers: string[] = [] + private readonly _value: string + constructor(valueOrInstance: string | TextPart) { + if (valueOrInstance instanceof TextPart) { + this._modifiers = [...valueOrInstance._modifiers] + this._value = valueOrInstance._value + } else this._value = valueOrInstance + } + + private baseTextModifier(modifier: number) { + return `\x1b[${modifier}m` + } + + public bold() { + this._modifiers.push(this.baseTextModifier(1)) + return this + } + + public faint() { + this._modifiers.push(this.baseTextModifier(2)) + return this + } + + public italic() { + this._modifiers.push(this.baseTextModifier(3)) + return this + } + + public underline() { + this._modifiers.push(this.baseTextModifier(4)) + return this + } + + public resetFormat(): void { + this._modifiers = [] + } + + public clone(): TextPart { + return new TextPart(this) + } + + toString() { + return this._modifiers.length > 0 ? `${this._modifiers.join('')}${this._value}\x1b[0m` : this._value + } +} + +export class TextBuilder { + private readonly _parts: TextPart[] = [] + + public add(text: string, texPartCb: (textPart: TextPart) => void = () => { }): this { + const textPart = new TextPart(text) + this._parts.push(textPart) + texPartCb(textPart) + return this + } + + public addParts(...textParts: TextPart[]): this { + this._parts.push(...textParts) + return this + } + + public newLine() { + this._parts.push(new TextPart('\n')) + return this + } + + public toString() { + return this._parts.join('') + } + + public clone() { + return new TextBuilder().addParts(...this._parts.map(x => x.clone())) + } + + public get parts() { + return this._parts + } +} \ No newline at end of file diff --git a/src/utilities/index.ts b/src/utilities/index.ts new file mode 100644 index 0000000..6448fa3 --- /dev/null +++ b/src/utilities/index.ts @@ -0,0 +1,4 @@ +export * from './TextBuilder' +export * from './Stringify' +export * from './Constants' +export * as is from './Guards' From b31b21789ca30e594b253bef61ede5d0e90c7b2a Mon Sep 17 00:00:00 2001 From: Mathias Lykkegaard Lorenzen Date: Thu, 21 Aug 2025 12:20:42 +0200 Subject: [PATCH 45/46] refactor: 2.0 readiness (#280) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: introduce symbols * fix: progress on new syntax * fix: progress on symbols * feat: symbols for methods - removed Substitute.disableFor * refactor: import path alignment * refactor: symbols only when needed * refac: use symbols for context handling * fix: update compatibility assertion * fix: update test import * fix: use symbol representation on clear method * test: add overlapping interface regression --------- Co-authored-by: Enrique Pöhlmann --- ava.config.js | 4 +- compatibility-checks/test/index.ts | 4 +- package-lock.json | 30 ++-- package.json | 4 +- spec/ClearSubstitute.spec.ts | 64 -------- spec/RecordedArguments.spec.ts | 4 +- spec/Recorder.spec.ts | 8 +- spec/RecordsSet.spec.ts | 4 +- spec/regression/Arguments.spec.ts | 4 +- spec/regression/clearReceivedCalls.spec.ts | 28 ++++ spec/regression/didNotReceive.spec.ts | 6 +- spec/regression/index.test.ts | 71 ++++----- spec/regression/issues/11.test.ts | 2 +- spec/regression/issues/178.test.ts | 2 +- spec/regression/issues/23.test.ts | 2 +- spec/regression/issues/36.test.ts | 2 +- spec/regression/issues/45.test.ts | 2 +- spec/regression/issues/59.test.ts | 2 +- spec/regression/mimicks.spec.ts | 2 +- spec/regression/overlap.spec.ts | 54 +++++++ spec/regression/received.spec.ts | 4 +- spec/regression/rejects.spec.ts | 2 +- spec/regression/resolves.spec.ts | 2 +- spec/regression/returns.spec.ts | 5 +- spec/regression/throws.spec.ts | 2 +- src/Arguments.ts | 101 ------------ src/Substitute.ts | 42 ----- src/Transformations.ts | 100 ------------ src/Types.ts | 25 --- src/api/Arg.ts | 56 +++++++ src/api/Constants.ts | 13 ++ src/api/Substitute.ts | 11 ++ src/api/index.ts | 3 + src/api/types/FunctionSubstitute.ts | 48 ++++++ src/api/types/Substitute.ts | 38 +++++ src/api/types/SubstituteMethods.ts | 29 ++++ src/api/types/SubstitutionLevel.ts | 41 +++++ src/api/types/index.ts | 9 ++ src/index.ts | 12 +- src/internals/Constants.ts | 18 +++ src/{ => internals}/RecordedArguments.ts | 4 +- src/{ => internals}/Recorder.ts | 2 +- src/{ => internals}/RecordsSet.ts | 2 +- src/{ => internals}/SubstituteException.ts | 5 +- src/{ => internals}/SubstituteNode.ts | 153 +++++++++++++------ src/{ => internals}/SubstituteNodeBase.ts | 0 src/internals/Types.ts | 42 +++++ src/internals/index.ts | 1 + src/internals/utilities/Guards.ts | 73 +++++++++ src/{ => internals}/utilities/Stringify.ts | 4 +- src/{ => internals}/utilities/TextBuilder.ts | 0 src/internals/utilities/Transformations.ts | 17 +++ src/{ => internals}/utilities/index.ts | 2 +- src/shared/Arguments.ts | 44 ++++++ src/shared/Constants.ts | 75 +++++++++ src/shared/index.ts | 2 + src/utilities/Constants.ts | 40 ----- src/utilities/Guards.ts | 64 -------- 58 files changed, 795 insertions(+), 595 deletions(-) delete mode 100644 spec/ClearSubstitute.spec.ts create mode 100644 spec/regression/clearReceivedCalls.spec.ts create mode 100644 spec/regression/overlap.spec.ts delete mode 100644 src/Arguments.ts delete mode 100644 src/Substitute.ts delete mode 100644 src/Transformations.ts delete mode 100644 src/Types.ts create mode 100644 src/api/Arg.ts create mode 100644 src/api/Constants.ts create mode 100644 src/api/Substitute.ts create mode 100644 src/api/index.ts create mode 100644 src/api/types/FunctionSubstitute.ts create mode 100644 src/api/types/Substitute.ts create mode 100644 src/api/types/SubstituteMethods.ts create mode 100644 src/api/types/SubstitutionLevel.ts create mode 100644 src/api/types/index.ts create mode 100644 src/internals/Constants.ts rename src/{ => internals}/RecordedArguments.ts (98%) rename src/{ => internals}/Recorder.ts (99%) rename src/{ => internals}/RecordsSet.ts (99%) rename src/{ => internals}/SubstituteException.ts (94%) rename src/{ => internals}/SubstituteNode.ts (64%) rename src/{ => internals}/SubstituteNodeBase.ts (100%) create mode 100644 src/internals/Types.ts create mode 100644 src/internals/index.ts create mode 100644 src/internals/utilities/Guards.ts rename src/{ => internals}/utilities/Stringify.ts (95%) rename src/{ => internals}/utilities/TextBuilder.ts (100%) create mode 100644 src/internals/utilities/Transformations.ts rename src/{ => internals}/utilities/index.ts (65%) create mode 100644 src/shared/Arguments.ts create mode 100644 src/shared/Constants.ts create mode 100644 src/shared/index.ts delete mode 100644 src/utilities/Constants.ts delete mode 100644 src/utilities/Guards.ts diff --git a/ava.config.js b/ava.config.js index cc81cf1..d47ef16 100644 --- a/ava.config.js +++ b/ava.config.js @@ -1,6 +1,6 @@ module.exports = { - files: ['spec/**/*.ts'], + files: ['spec/**/*.spec.ts'], typescript: { compile: false, rewritePaths: { @@ -10,4 +10,4 @@ module.exports = { cache: false, failFast: true, failWithoutAssertions: true -} \ No newline at end of file +} diff --git a/compatibility-checks/test/index.ts b/compatibility-checks/test/index.ts index ce90233..afaa9ff 100644 --- a/compatibility-checks/test/index.ts +++ b/compatibility-checks/test/index.ts @@ -10,7 +10,6 @@ type TestRunner = { test.describe('Verifies test runner compatibility', () => { const failingExec = (command: string): string => { - process.env const { FORCE_COLOR, ...environment } = { ...process.env, CI: '1', NO_COLOR: '1' } as Partial> try { execSync(command, { env: environment, stdio: 'pipe' }) @@ -43,11 +42,10 @@ test.describe('Verifies test runner compatibility', () => { `Could not find the expected failure location in the output. Expected "${testRunner.failureLocationText}"` ) assert.ok( - result.includes('SubstituteException: Expected'), + result.includes('SubstituteException: Call count mismatch'), `Could not find the expected exception message in the output: ${result}` ) }) }) }) }) - diff --git a/package-lock.json b/package-lock.json index 8e56c98..2efcbf7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,10 +11,10 @@ "devDependencies": { "@ava/typescript": "^3.0.1", "@sinonjs/fake-timers": "^11.2.2", - "@types/node": "^18.19.22", + "@types/node": "^18.19.122", "@types/sinonjs__fake-timers": "^8.1.5", "ava": "^4.3.3", - "typescript": "^4.8.4" + "typescript": "^5.9.2" }, "engines": { "node": ">=10" @@ -91,9 +91,9 @@ } }, "node_modules/@types/node": { - "version": "18.19.22", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.22.tgz", - "integrity": "sha512-p3pDIfuMg/aXBmhkyanPshdfJuX5c5+bQjYLIikPLXAUycEogij/c50n/C+8XOA5L93cU4ZRXtn+dNQGi0IZqQ==", + "version": "18.19.122", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.122.tgz", + "integrity": "sha512-yzegtT82dwTNEe/9y+CM8cgb42WrUfMMCg2QqSddzO1J6uPmBD7qKCZ7dOHZP2Yrpm/kb0eqdNMn2MUyEiqBmA==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -1978,16 +1978,16 @@ } }, "node_modules/typescript": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", - "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, "node_modules/undici-types": { @@ -2282,9 +2282,9 @@ } }, "@types/node": { - "version": "18.19.22", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.22.tgz", - "integrity": "sha512-p3pDIfuMg/aXBmhkyanPshdfJuX5c5+bQjYLIikPLXAUycEogij/c50n/C+8XOA5L93cU4ZRXtn+dNQGi0IZqQ==", + "version": "18.19.122", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.122.tgz", + "integrity": "sha512-yzegtT82dwTNEe/9y+CM8cgb42WrUfMMCg2QqSddzO1J6uPmBD7qKCZ7dOHZP2Yrpm/kb0eqdNMn2MUyEiqBmA==", "dev": true, "requires": { "undici-types": "~5.26.4" @@ -3596,9 +3596,9 @@ "dev": true }, "typescript": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", - "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", "dev": true }, "undici-types": { diff --git a/package.json b/package.json index 631e8d1..cca6f69 100644 --- a/package.json +++ b/package.json @@ -46,10 +46,10 @@ "devDependencies": { "@ava/typescript": "^3.0.1", "@sinonjs/fake-timers": "^11.2.2", - "@types/node": "^18.19.22", + "@types/node": "^18.19.122", "@types/sinonjs__fake-timers": "^8.1.5", "ava": "^4.3.3", - "typescript": "^4.8.4" + "typescript": "^5.9.2" }, "volta": { "node": "18.19.1" diff --git a/spec/ClearSubstitute.spec.ts b/spec/ClearSubstitute.spec.ts deleted file mode 100644 index 0dad128..0000000 --- a/spec/ClearSubstitute.spec.ts +++ /dev/null @@ -1,64 +0,0 @@ -import test from 'ava' - -import { Substitute, SubstituteOf } from '../src' -import { SubstituteNode } from '../src/SubstituteNode' - -interface Calculator { - add(a: number, b: number): number - subtract(a: number, b: number): number - divide(a: number, b: number): number - isEnabled: boolean -} - -type InstanceReturningSubstitute = SubstituteOf & { - [SubstituteNode.instance]: SubstituteNode -} - -test('clears everything on a substitute', t => { - const calculator = Substitute.for() as InstanceReturningSubstitute - calculator.add(1, 1) - calculator.received().add(1, 1) - calculator.clearSubstitute() - - t.is(calculator[SubstituteNode.instance].recorder.records.size, 0) - t.is(calculator[SubstituteNode.instance].recorder.indexedRecords.size, 0) - - t.throws(() => calculator.received().add(1, 1)) - - // explicitly using 'all' - calculator.add(1, 1) - calculator.received().add(1, 1) - calculator.clearSubstitute('all') - - t.is(calculator[SubstituteNode.instance].recorder.records.size, 0) - t.is(calculator[SubstituteNode.instance].recorder.indexedRecords.size, 0) - - t.throws(() => calculator.received().add(1, 1)) -}) - -test('clears received calls on a substitute', t => { - const calculator = Substitute.for() as InstanceReturningSubstitute - calculator.add(1, 1) - calculator.add(1, 1).returns(2) - calculator.clearSubstitute('receivedCalls') - - t.is(calculator[SubstituteNode.instance].recorder.records.size, 2) - t.is(calculator[SubstituteNode.instance].recorder.indexedRecords.size, 2) - - t.throws(() => calculator.received().add(1, 1)) - t.is(2, calculator.add(1, 1)) -}) - -test('clears return values on a substitute', t => { - const calculator = Substitute.for() as InstanceReturningSubstitute - calculator.add(1, 1) - calculator.add(1, 1).returns(2) - calculator.clearSubstitute('substituteValues') - - t.is(calculator[SubstituteNode.instance].recorder.records.size, 2) - t.is(calculator[SubstituteNode.instance].recorder.indexedRecords.size, 2) - - t.notThrows(() => calculator.received().add(1, 1)) - // @ts-expect-error - t.true(calculator.add(1, 1)[SubstituteNode.instance] instanceof SubstituteNode) -}) \ No newline at end of file diff --git a/spec/RecordedArguments.spec.ts b/spec/RecordedArguments.spec.ts index 103efb3..ea37629 100644 --- a/spec/RecordedArguments.spec.ts +++ b/spec/RecordedArguments.spec.ts @@ -2,7 +2,7 @@ import test from 'ava' import { inspect } from 'util' import { Arg } from '../src' -import { RecordedArguments } from '../src/RecordedArguments' +import { RecordedArguments } from '../src/internals/RecordedArguments' const testObject = { 'foo': 'bar' } const testArray = ['a', 1, true] @@ -135,4 +135,4 @@ test('generates custom text representation', t => { t.is(inspect(RecordedArguments.from([])), '()') t.is(inspect(RecordedArguments.from([undefined])), 'undefined') t.is(inspect(RecordedArguments.from([undefined, 1])), '(undefined, 1)') -}) \ No newline at end of file +}) diff --git a/spec/Recorder.spec.ts b/spec/Recorder.spec.ts index 348a0b9..47b55cf 100644 --- a/spec/Recorder.spec.ts +++ b/spec/Recorder.spec.ts @@ -1,9 +1,9 @@ import test from 'ava' -import { Recorder } from '../src/Recorder' -import { RecordsSet } from '../src/RecordsSet' -import { Substitute } from '../src/Substitute' -import { SubstituteNodeBase } from '../src/SubstituteNodeBase' +import { Recorder } from '../src/internals/Recorder' +import { RecordsSet } from '../src/internals/RecordsSet' +import { Substitute } from '../src/api/Substitute' +import { SubstituteNodeBase } from '../src/internals/SubstituteNodeBase' const nodeFactory = (key: string) => { const node = Substitute.for() diff --git a/spec/RecordsSet.spec.ts b/spec/RecordsSet.spec.ts index 62b83ae..d17aec4 100644 --- a/spec/RecordsSet.spec.ts +++ b/spec/RecordsSet.spec.ts @@ -1,6 +1,6 @@ import test, { ExecutionContext } from 'ava' -import { RecordsSet } from '../src/RecordsSet' +import { RecordsSet } from '../src/internals/RecordsSet' const dataArray = [1, 2, 3] function* dataArrayGenerator() { @@ -63,4 +63,4 @@ test('applies and preserves the order of filter and map functions everytime the t.deepEqual([...setWithFilter], [1, 3]) t.deepEqual([...setWithFilterAndMap], ['1', '3']) t.deepEqual([...setWithFilterMapAndAnotherFilter], ['3']) -}) \ No newline at end of file +}) diff --git a/spec/regression/Arguments.spec.ts b/spec/regression/Arguments.spec.ts index a04e5d2..1625fd4 100644 --- a/spec/regression/Arguments.spec.ts +++ b/spec/regression/Arguments.spec.ts @@ -1,6 +1,6 @@ import test from 'ava' import { Arg } from '../../src' -import { Argument } from '../../src/Arguments' +import { Argument } from '../../src/shared' const testObject = { "foo": "bar" } const testArray = ["a", 1, true] @@ -107,4 +107,4 @@ test('should not match the argument with the predicate function using Arg.is.not t.true(Arg.is.not(x => x === 'foo').matches('bar')) t.true(Arg.is.not(x => x % 2 == 0).matches(3)) -}) \ No newline at end of file +}) diff --git a/spec/regression/clearReceivedCalls.spec.ts b/spec/regression/clearReceivedCalls.spec.ts new file mode 100644 index 0000000..4325f5c --- /dev/null +++ b/spec/regression/clearReceivedCalls.spec.ts @@ -0,0 +1,28 @@ +import test from 'ava' + +import { Substitute, SubstituteOf, clearReceivedCalls } from '../../src' +import { SubstituteNode, instance } from '../../src/internals/SubstituteNode' + +interface Calculator { + add(a: number, b: number): number + subtract(a: number, b: number): number + divide(a: number, b: number): number + isEnabled: boolean +} + +type InstanceReturningSubstitute = SubstituteOf & { + [instance]: SubstituteNode +} + +test('clears received calls on a substitute', t => { + const calculator = Substitute.for() as InstanceReturningSubstitute + calculator.add(1, 1) + calculator.add(1, 1).returns(2) + calculator[clearReceivedCalls](); + + t.is(calculator[instance].recorder.records.size, 2) + t.is(calculator[instance].recorder.indexedRecords.size, 2) + + t.throws(() => calculator.received().add(1, 1)) + t.is(2, calculator.add(1, 1)) +}) diff --git a/spec/regression/didNotReceive.spec.ts b/spec/regression/didNotReceive.spec.ts index 2b01ecc..588da00 100644 --- a/spec/regression/didNotReceive.spec.ts +++ b/spec/regression/didNotReceive.spec.ts @@ -1,6 +1,6 @@ import test from 'ava' import { Substitute, Arg } from '../../src' -import { SubstituteException } from '../../src/SubstituteException' +import { SubstituteException } from '../../src/internals/SubstituteException' interface Calculator { add(a: number, b: number): number @@ -13,7 +13,7 @@ test('not calling a method correctly asserts the call count', t => { const calculator = Substitute.for() calculator.didNotReceive().add(1, 1) - t.throws(() => calculator.received(1).add(1, 1), { instanceOf: SubstituteException }) + t.throws(() => calculator.received().add(1, 1), { instanceOf: SubstituteException }) t.throws(() => calculator.received().add(Arg.all()), { instanceOf: SubstituteException }) }) @@ -49,4 +49,4 @@ test('not getting a property with mock correctly asserts the call count', t => { calculator.didNotReceive().isEnabled t.throws(() => calculator.received(1).isEnabled, { instanceOf: SubstituteException }) t.throws(() => calculator.received().isEnabled, { instanceOf: SubstituteException }) -}) \ No newline at end of file +}) diff --git a/spec/regression/index.test.ts b/spec/regression/index.test.ts index 16aba9e..45107c3 100644 --- a/spec/regression/index.test.ts +++ b/spec/regression/index.test.ts @@ -1,6 +1,6 @@ import test from 'ava' -import { Substitute, Arg, SubstituteOf } from '../../src' +import { Substitute, Arg, SubstituteOf, received } from '../../src' class Dummy { @@ -20,7 +20,7 @@ export class Example { set v(x: string | null | undefined) { } - received(stuff: number | string) { + received(_stuff: string) { } @@ -28,7 +28,7 @@ export class Example { return Promise.resolve(new Dummy()) } - foo(): string | undefined | null { + foo(_arg?: string): string | undefined | null { return 'stuff' } @@ -47,22 +47,13 @@ function initialize() { const textModifierRegex = /\x1b\[\d+m/g -test('class with method called \'received\' can be used for call count verification when proxies are suspended', t => { - initialize() - - Substitute.disableFor(substitute).received(2) - - t.throws(() => substitute.received(2).received(2)) - t.notThrows(() => substitute.received(1).received(2)) -}) - -test('class with method called \'received\' can be used for call count verification', t => { - initialize() +test('class with method called \'received\' can be used for call count verification when using symbols', t => { + const substitute = Substitute.for() - Substitute.disableFor(substitute).received('foo') + substitute.received("foo") - t.notThrows(() => substitute.received(1).received('foo')) - t.throws(() => substitute.received(2).received('foo')) + t.notThrows(() => substitute[received](1).received("foo")) + t.throws(() => substitute[received](2).received("foo")) }) test('class string field set received', t => { @@ -79,16 +70,16 @@ test('class string field set received', t => { runLogic(substitute) - t.notThrows(() => substitute.received().v = 'hello') - t.notThrows(() => substitute.received(5).v = Arg.any()) - t.notThrows(() => substitute.received().v = Arg.any()) - t.notThrows(() => substitute.received(2).v = 'hello') - t.notThrows(() => substitute.received(2).v = Arg.is(x => typeof x === 'string' && x.indexOf('ll') > -1)) + t.notThrows(() => substitute[received]().v = 'hello') + t.notThrows(() => substitute[received](5).v = Arg.any()) + t.notThrows(() => substitute[received]().v = Arg.any()) + t.notThrows(() => substitute[received](2).v = 'hello') + t.notThrows(() => substitute[received](2).v = Arg.is(x => typeof x === 'string' && x.indexOf('ll') > -1)) - t.throws(() => substitute.received(2).v = Arg.any()) - t.throws(() => substitute.received(1).v = Arg.any()) - t.throws(() => substitute.received(1).v = Arg.is(x => typeof x === 'string' && x.indexOf('ll') > -1)) - t.throws(() => substitute.received(3).v = 'hello') + t.throws(() => substitute[received](2).v = Arg.any()) + t.throws(() => substitute[received](1).v = Arg.any()) + t.throws(() => substitute[received](1).v = Arg.is(x => typeof x === 'string' && x.indexOf('ll') > -1)) + t.throws(() => substitute[received](3).v = 'hello') }) test('resolving promises works', async t => { @@ -117,24 +108,24 @@ test('class method received', t => { void substitute.c('hi', 'there') void substitute.c('hi', 'there') - t.notThrows(() => substitute.received(4).c('hi', 'there')) - t.notThrows(() => substitute.received(1).c('hi', 'the1re')) - t.notThrows(() => substitute.received().c('hi', 'there')) + t.notThrows(() => substitute[received](4).c('hi', 'there')) + t.notThrows(() => substitute[received](1).c('hi', 'the1re')) + t.notThrows(() => substitute[received]().c('hi', 'there')) const expectedMessage = 'Call count mismatch in @Substitute.c:\n' + `Expected to receive 7 method calls matching c('hi', 'there'), but received 4.\n` + 'All property or method calls to @Substitute.c received so far:\n' + `› ✔ @Substitute.c('hi', 'there')\n` + - ` called at (${process.cwd()}/spec/regression/index.test.ts:114:18)\n` + + ` called at (${process.cwd()}/spec/regression/index.test.ts:105:18)\n` + `› ✘ @Substitute.c('hi', 'the1re')\n` + - ` called at (${process.cwd()}/spec/regression/index.test.ts:115:18)\n` + + ` called at (${process.cwd()}/spec/regression/index.test.ts:106:18)\n` + `› ✔ @Substitute.c('hi', 'there')\n` + - ` called at (${process.cwd()}/spec/regression/index.test.ts:116:18)\n` + + ` called at (${process.cwd()}/spec/regression/index.test.ts:107:18)\n` + `› ✔ @Substitute.c('hi', 'there')\n` + - ` called at (${process.cwd()}/spec/regression/index.test.ts:117:18)\n` + + ` called at (${process.cwd()}/spec/regression/index.test.ts:108:18)\n` + `› ✔ @Substitute.c('hi', 'there')\n` + - ` called at (${process.cwd()}/spec/regression/index.test.ts:118:18)\n` - const { message } = t.throws(() => { substitute.received(7).c('hi', 'there') }) + ` called at (${process.cwd()}/spec/regression/index.test.ts:109:18)\n` + const { message } = t.throws(() => { substitute[received](7).c('hi', 'there') }) t.is(message.replace(textModifierRegex, ''), expectedMessage) }) @@ -144,16 +135,16 @@ test('received call matches after partial mocks using property instance mimicks' substitute.d.mimicks(() => instance.d) substitute.c('lala', 'bar') - substitute.received(1).c('lala', 'bar') - substitute.received(1).c('lala', 'bar') + substitute[received](1).c('lala', 'bar') + substitute[received](1).c('lala', 'bar') - t.notThrows(() => substitute.received(1).c('lala', 'bar')) + t.notThrows(() => substitute[received](1).c('lala', 'bar')) const expectedMessage = 'Call count mismatch in @Substitute.c:\n' + `Expected to receive 2 method calls matching c('lala', 'bar'), but received 1.\n` + 'All property or method calls to @Substitute.c received so far:\n' + `› ✔ @Substitute.c('lala', 'bar')\n` + - ` called at (${process.cwd()}/spec/regression/index.test.ts:145:13)\n` - const { message } = t.throws(() => substitute.received(2).c('lala', 'bar')) + ` called at (${process.cwd()}/spec/regression/index.test.ts:136:13)\n` + const { message } = t.throws(() => substitute[received](2).c('lala', 'bar')) t.is(message.replace(textModifierRegex, ''), expectedMessage) t.deepEqual(substitute.d, 1337) }) diff --git a/spec/regression/issues/11.test.ts b/spec/regression/issues/11.test.ts index 4bd6d77..64e7b08 100644 --- a/spec/regression/issues/11.test.ts +++ b/spec/regression/issues/11.test.ts @@ -1,5 +1,5 @@ import test from 'ava' -import { Substitute, Arg } from '../../../src' +import { Substitute, Arg, received, returns } from '../../../src' type Addands = { op1: number diff --git a/spec/regression/issues/178.test.ts b/spec/regression/issues/178.test.ts index dacf607..78efeb6 100644 --- a/spec/regression/issues/178.test.ts +++ b/spec/regression/issues/178.test.ts @@ -3,7 +3,7 @@ import * as fakeTimers from '@sinonjs/fake-timers' import { types } from 'util' import { Substitute } from '../../../src' -import { SubstituteException } from '../../../src/SubstituteException' +import { SubstituteException } from '../../../src/internals/SubstituteException' interface Library { subSection: Subsection diff --git a/spec/regression/issues/23.test.ts b/spec/regression/issues/23.test.ts index a26666f..1126b7e 100644 --- a/spec/regression/issues/23.test.ts +++ b/spec/regression/issues/23.test.ts @@ -1,6 +1,6 @@ import test from 'ava' -import { Substitute, Arg } from '../../../src' +import { Substitute, Arg, received, mimicks } from '../../../src' interface CalculatorInterface { add(a: number, b: number): number diff --git a/spec/regression/issues/36.test.ts b/spec/regression/issues/36.test.ts index 508b3c3..9d9be54 100644 --- a/spec/regression/issues/36.test.ts +++ b/spec/regression/issues/36.test.ts @@ -1,6 +1,6 @@ import test from 'ava' -import { Substitute, Arg } from '../../../src' +import { Substitute, Arg, received, returns } from '../../../src' class Key { private constructor(private _value: string) { } diff --git a/spec/regression/issues/45.test.ts b/spec/regression/issues/45.test.ts index e77f985..9c87540 100644 --- a/spec/regression/issues/45.test.ts +++ b/spec/regression/issues/45.test.ts @@ -1,6 +1,6 @@ import test from 'ava' -import { Substitute, Arg } from '../../../src' +import { Substitute, Arg, received } from '../../../src' class DependencyClass { public methodOne() { } diff --git a/spec/regression/issues/59.test.ts b/spec/regression/issues/59.test.ts index 36dd296..fbe6603 100644 --- a/spec/regression/issues/59.test.ts +++ b/spec/regression/issues/59.test.ts @@ -1,6 +1,6 @@ import test from 'ava' -import { Substitute } from '../../../src' +import { Substitute, received, returns } from '../../../src' interface IEcho { echo(a: string): string diff --git a/spec/regression/mimicks.spec.ts b/spec/regression/mimicks.spec.ts index a6b5b8a..d741131 100644 --- a/spec/regression/mimicks.spec.ts +++ b/spec/regression/mimicks.spec.ts @@ -1,5 +1,5 @@ import test from 'ava' -import { Substitute, Arg } from '../../src' +import { Substitute, Arg, mimicks } from '../../src' interface Calculator { add(a: number, b: number): number diff --git a/spec/regression/overlap.spec.ts b/spec/regression/overlap.spec.ts new file mode 100644 index 0000000..b2cc942 --- /dev/null +++ b/spec/regression/overlap.spec.ts @@ -0,0 +1,54 @@ +import test from 'ava' + +import { Substitute, received, didNotReceive } from '../../src' + +export interface OverlappingInterface { + received(value: number): string + didNotReceive(): unknown + clearReceivedCalls(): void +} + +test('(clearReceivedCalls) handles overlaps safely without substitutions', t => { + const substitute = Substitute.for>() + substitute.clearReceivedCalls() + t.notThrows(() => substitute.received(1).clearReceivedCalls()) + t.throws(() => substitute[didNotReceive]().clearReceivedCalls()) + }) + +test('(clearReceivedCalls) handles overlaps safely with substitutions', t => { + const substitute = Substitute.for>() + substitute.clearReceivedCalls().returns() + substitute.clearReceivedCalls() + t.notThrows(() => substitute.received(1).clearReceivedCalls()) + t.throws(() => substitute[didNotReceive]().clearReceivedCalls()) +}) + +test('(received) handles overlaps safely without substitutions', t => { + const substitute = Substitute.for>() + substitute.received(10) + t.notThrows(() => substitute[received](1).received(10)) + t.throws(() => substitute.didNotReceive().received(10)) +}) + +test('(received) handles overlaps safely with substitutions', t => { + const substitute = Substitute.for>() + substitute.received(10).returns('foo') + t.is('foo', substitute.received(10)) + t.notThrows(() => substitute[received](1).received(10)) + t.throws(() => substitute.didNotReceive().received(10)) +}) + +test('(didNotReceive) handles overlaps safely without substitutions', t => { + const substitute = Substitute.for>() + substitute.didNotReceive() + t.notThrows(() => substitute.received(1).didNotReceive()) + t.throws(() => substitute[didNotReceive]().didNotReceive()) +}) + +test('(didNotReceive) handles overlaps safely with substitutions', t => { + const substitute = Substitute.for>() + substitute.didNotReceive().returns('foo') + t.is('foo' as unknown, substitute.didNotReceive()) + t.notThrows(() => substitute.received(1).didNotReceive()) + t.throws(() => substitute[didNotReceive]().didNotReceive()) +}) diff --git a/spec/regression/received.spec.ts b/spec/regression/received.spec.ts index c9a4519..69651f9 100644 --- a/spec/regression/received.spec.ts +++ b/spec/regression/received.spec.ts @@ -1,6 +1,6 @@ import test from 'ava' import { Substitute, Arg } from '../../src' -import { SubstituteException } from '../../src/SubstituteException' +import { SubstituteException } from '../../src/internals/SubstituteException' interface Calculator { add(a: number, b: number): number @@ -137,4 +137,4 @@ test('calling a method does not interfere with other properties or methods call t.throws(() => calculator.received().multiply(1, 1), { instanceOf: SubstituteException }) t.throws(() => calculator.received().multiply(Arg.all()), { instanceOf: SubstituteException }) -}) \ No newline at end of file +}) diff --git a/spec/regression/rejects.spec.ts b/spec/regression/rejects.spec.ts index a92cdbf..016fa7b 100644 --- a/spec/regression/rejects.spec.ts +++ b/spec/regression/rejects.spec.ts @@ -1,6 +1,6 @@ import test from 'ava' -import { Substitute, Arg } from '../../src' +import { Substitute, Arg, rejects } from '../../src' interface Calculator { getMemory(): Promise diff --git a/spec/regression/resolves.spec.ts b/spec/regression/resolves.spec.ts index 6916d1b..10fe86b 100644 --- a/spec/regression/resolves.spec.ts +++ b/spec/regression/resolves.spec.ts @@ -1,6 +1,6 @@ import test from 'ava' -import { Substitute, Arg } from '../../src' +import { Substitute, Arg, resolves } from '../../src' interface Calculator { getMemory(): Promise diff --git a/spec/regression/returns.spec.ts b/spec/regression/returns.spec.ts index 54f61a6..6f8fb93 100644 --- a/spec/regression/returns.spec.ts +++ b/spec/regression/returns.spec.ts @@ -19,9 +19,6 @@ interface Calculator { test('returns a primitive value for method with no arguments', t => { const calculator = Substitute.for() calculator.clear().returns() - // calculator.add(1, 2).toExponential() - // calculator.isEnabled2.viewResult().returns(3) - // calculator.other().viewResult().returns(2) t.is(void 0 as void, calculator.clear()) }) @@ -186,4 +183,4 @@ test('returns another substituted instance on a property', async t => { const result = await calculator.model t.is(result, modelResult) t.is(result.replace('...', '---'), 'TI-83') -}) \ No newline at end of file +}) diff --git a/spec/regression/throws.spec.ts b/spec/regression/throws.spec.ts index 80d3c21..eac673d 100644 --- a/spec/regression/throws.spec.ts +++ b/spec/regression/throws.spec.ts @@ -1,6 +1,6 @@ import test from 'ava' -import { Substitute, Arg } from '../../src' +import { Substitute, Arg, returns, throws } from '../../src' interface Calculator { add(a: number, b: number): number diff --git a/src/Arguments.ts b/src/Arguments.ts deleted file mode 100644 index 6db6412..0000000 --- a/src/Arguments.ts +++ /dev/null @@ -1,101 +0,0 @@ -type PredicateFunction = (arg: T) => boolean -type ArgumentOptions = { - inverseMatch?: boolean -} -class BaseArgument { - private _description: string - constructor( - description: string, - private _matchingFunction: PredicateFunction, - private _options?: ArgumentOptions - ) { - this._description = `${this._options?.inverseMatch ? 'Not ' : ''}${description}` - } - - matches(arg: T) { - const inverseMatch = this._options?.inverseMatch ?? false - return inverseMatch ? !this._matchingFunction(arg) : this._matchingFunction(arg) - } - - toString() { - return this._description - } - - [Symbol.for('nodejs.util.inspect.custom')]() { - return this._description - } -} - -export class Argument extends BaseArgument { - private readonly _type = 'SingleArgument'; - get type(): 'SingleArgument' { - return this._type - } -} - -export class AllArguments extends BaseArgument { - private readonly _type = 'AllArguments'; - constructor() { - super('Arg.all{}', () => true, {}) - } - get type(): 'AllArguments' { - return this._type // TODO: Needed? - } -} - -export namespace Arg { - type Inversable = T & { not: T } - type ExtractFirstArg = T extends AllArguments ? TArgs[0] : T - type ReturnArg = Argument & T - const createInversable = (target: (arg: TArg, opt?: ArgumentOptions) => TReturn): Inversable<(arg: TArg) => TReturn> => { - const inversable = (arg: TArg) => target(arg) - inversable.not = (arg: TArg) => target(arg, { inverseMatch: true }) - return inversable - } - - const toStringify = (obj: any) => { - if (typeof obj.inspect === 'function') return obj.inspect() - if (typeof obj.toString === 'function') return obj.toString() - return obj - } - - export const all = (): AllArguments => new AllArguments() - - type Is = (predicate: PredicateFunction>) => ReturnArg> - const isFunction = (predicate: PredicateFunction>, options?: ArgumentOptions) => new Argument( - `Arg.is{${toStringify(predicate)}}`, predicate, options - ) - export const is = createInversable(isFunction) as Inversable - - type MapAnyReturn = T extends 'any' ? - ReturnArg : T extends 'string' ? - ReturnArg : T extends 'number' ? - ReturnArg : T extends 'boolean' ? - ReturnArg : T extends 'symbol' ? - ReturnArg : T extends 'undefined' ? - ReturnArg : T extends 'object' ? - ReturnArg : T extends 'function' ? - ReturnArg : T extends 'array' ? - ReturnArg : any - - type AnyType = 'string' | 'number' | 'boolean' | 'symbol' | 'undefined' | 'object' | 'function' | 'array' | 'any' - type Any = (type?: T) => MapAnyReturn - - const anyFunction = (type: AnyType = 'any', options?: ArgumentOptions) => { - const description = `Arg.any{${type}}` - const predicate = (x: any) => { - switch (type) { - case 'any': - return true - case 'array': - return Array.isArray(x) - default: - return typeof x === type - } - } - - return new Argument(description, predicate, options) - } - - export const any = createInversable(anyFunction) as Inversable -} \ No newline at end of file diff --git a/src/Substitute.ts b/src/Substitute.ts deleted file mode 100644 index 3f87849..0000000 --- a/src/Substitute.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { DisabledSubstituteObject, ObjectSubstitute } from './Transformations' -import { SubstituteNode } from './SubstituteNode' - -export type SubstituteOf = ObjectSubstitute & T -type InstantiableSubstitute> = T & { [SubstituteNode.instance]: SubstituteNode } - -export class Substitute { - public static for(): SubstituteOf { - const substitute = SubstituteNode.createRoot() - return substitute.proxy as unknown as SubstituteOf - } - - public static disableFor>(substituteProxy: T): DisabledSubstituteObject { - const substitute = this.extractSubstituteNodeFromSubstitute(substituteProxy as InstantiableSubstitute) - - const disableProxy = < - TParameters extends unknown[], - TReturnType extends unknown - >(reflection: (...args: TParameters) => TReturnType): typeof reflection => (...args) => { - substitute.rootContext.substituteMethodsEnabled = false - const reflectionResult = reflection(...args) - substitute.rootContext.substituteMethodsEnabled = true - return reflectionResult - } - - return new Proxy(substitute.proxy, { - get: function (target, property) { - return disableProxy(Reflect.get)(target, property) - }, - set: function (target, property, value) { - return disableProxy(Reflect.set)(target, property, value) - }, - apply: function (target, _, args) { - return disableProxy(Reflect.apply)(target, _, args) - } - }) as DisabledSubstituteObject - } - - private static extractSubstituteNodeFromSubstitute(substitute: InstantiableSubstitute>): SubstituteNode { - return substitute[SubstituteNode.instance] - } -} \ No newline at end of file diff --git a/src/Transformations.ts b/src/Transformations.ts deleted file mode 100644 index e927822..0000000 --- a/src/Transformations.ts +++ /dev/null @@ -1,100 +0,0 @@ -import type { AllArguments } from './Arguments'; -import type { ClearType, FirstLevelMethod } from './Types'; - -type FunctionSubstituteWithOverloads = - TFunc extends { - (...args: infer A1): infer R1; - (...args: infer A2): infer R2; - (...args: infer A3): infer R3; - (...args: infer A4): infer R4; - (...args: infer A5): infer R5; - } ? - FunctionHandler & FunctionHandler & - FunctionHandler & FunctionHandler - & FunctionHandler : TFunc extends { - (...args: infer A1): infer R1; - (...args: infer A2): infer R2; - (...args: infer A3): infer R3; - (...args: infer A4): infer R4; - } ? - FunctionHandler & FunctionHandler & - FunctionHandler & FunctionHandler : TFunc extends { - (...args: infer A1): infer R1; - (...args: infer A2): infer R2; - (...args: infer A3): infer R3; - } ? - FunctionHandler & FunctionHandler - & FunctionHandler : TFunc extends { - (...args: infer A1): infer R1; - (...args: infer A2): infer R2; - } ? - FunctionHandler & FunctionHandler : TFunc extends { - (...args: infer A1): infer R1; - } ? - FunctionHandler : never; - -type Equals = (() => T extends A ? 1 : 2) extends (() => T extends B ? 1 : 2) ? true : false; -type FunctionHandler = - Equals extends true ? - {} : Terminating extends true ? - TerminatingFunction : - FunctionSubstitute - -export type FunctionSubstitute = - ((...args: TArguments) => (TReturnType & MockObjectMixin)) & - ((allArguments: AllArguments) => (TReturnType & MockObjectMixin)) - -export type NoArgumentFunctionSubstitute = () => TReturnType & NoArgumentMockObjectMixin; -export type PropertySubstitute = TReturnType & NoArgumentMockObjectMixin; - -type OneArgumentRequiredFunction = (requiredInput: TArgs, ...restInputs: TArgs[]) => TReturnType; - -type MockObjectPromise = TReturnType extends Promise ? { - resolves: OneArgumentRequiredFunction; - rejects: OneArgumentRequiredFunction; -} : {} - -type BaseMockObjectMixin = MockObjectPromise & { - returns: OneArgumentRequiredFunction; - throws: OneArgumentRequiredFunction; -} - -type NoArgumentMockObjectMixin = BaseMockObjectMixin & { - mimicks: OneArgumentRequiredFunction<() => TReturnType, void>; -} - -type MockObjectMixin = BaseMockObjectMixin & { - mimicks: OneArgumentRequiredFunction<(...args: TArguments) => TReturnType, void>; -} - -type TerminatingFunction = ((...args: TArguments) => void) & ((arg: AllArguments) => void) - -type TryToExpandNonArgumentedTerminatingFunction = - TObject[TProperty] extends (...args: []) => unknown ? () => void : {} -type TryToExpandArgumentedTerminatingFunction = - TObject[TProperty] extends (...args: any) => any ? FunctionSubstituteWithOverloads : {} - -type TerminatingObject = { - [P in keyof T]: TryToExpandNonArgumentedTerminatingFunction & TryToExpandArgumentedTerminatingFunction & T[P]; -} - -type TryToExpandNonArgumentedFunctionSubstitute = - TObject[TProperty] extends (...args: []) => infer R ? NoArgumentFunctionSubstitute : {} - -type TryToExpandArgumentedFunctionSubstitute = - TObject[TProperty] extends (...args: infer F) => infer R ? F extends [] ? {} : FunctionSubstituteWithOverloads : {} - -type TryToExpandPropertySubstitute = PropertySubstitute - -type ObjectSubstituteTransformation> = { - [P in keyof T]: TryToExpandNonArgumentedFunctionSubstitute & TryToExpandArgumentedFunctionSubstitute & TryToExpandPropertySubstitute; -} - -export type OmitProxyMethods = Omit; -export type ObjectSubstitute = ObjectSubstituteTransformation & { - received(amount?: number): TerminatingObject; - didNotReceive(): TerminatingObject; - mimick(instance: OmitProxyMethods): void; - clearSubstitute(clearType?: ClearType): void; -} -export type DisabledSubstituteObject = T extends ObjectSubstitute ? K : never; diff --git a/src/Types.ts b/src/Types.ts deleted file mode 100644 index 1fe75b6..0000000 --- a/src/Types.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { RecordedArguments } from './RecordedArguments' - -export type PropertyType = 'method' | 'property' -export type AccessorType = 'get' | 'set' -export type AssertionMethod = 'received' | 'didNotReceive' -export type ConfigurationMethod = 'clearSubstitute' | 'mimick' -export type SubstitutionMethod = 'mimicks' | 'throws' | 'returns' | 'resolves' | 'rejects' - -export type FirstLevelMethod = AssertionMethod | ConfigurationMethod -export type SubstituteMethod = FirstLevelMethod | SubstitutionMethod -export type SubstituteContext = SubstituteMethod | 'none' - -export type ClearType = 'all' | 'receivedCalls' | 'substituteValues' - -export type SubstituteExceptionType = 'CallCountMismatch' | 'PropertyNotMocked' - -export type FilterFunction = (item: T) => boolean - -export type SubstituteNodeModel = { - propertyType: PropertyType - property: PropertyKey - context: SubstituteContext - recordedArguments: RecordedArguments - stack?: string -} \ No newline at end of file diff --git a/src/api/Arg.ts b/src/api/Arg.ts new file mode 100644 index 0000000..6798412 --- /dev/null +++ b/src/api/Arg.ts @@ -0,0 +1,56 @@ +import { Argument, AllArguments, type ArgumentOptions, type PredicateFunction } from '../shared' + +type Inversable = T & { not: T } +type ExtractFirstArg = T extends AllArguments ? TArgs[0] : T +type ReturnArg = Argument & T +const createInversable = (target: (arg: TArg, opt?: ArgumentOptions) => TReturn): Inversable<(arg: TArg) => TReturn> => { + const inversable = (arg: TArg) => target(arg) + inversable.not = (arg: TArg) => target(arg, { inverseMatch: true }) + return inversable +} + +const toStringify = (obj: any) => { + if (typeof obj.inspect === 'function') return obj.inspect() + if (typeof obj.toString === 'function') return obj.toString() + return obj +} +const isFunction = (predicate: PredicateFunction>, options?: ArgumentOptions) => new Argument( + `Arg.is{${toStringify(predicate)}}`, predicate, options +) +type Is = (predicate: PredicateFunction>) => ReturnArg> + +type MapAnyReturn = T extends 'any' ? +ReturnArg : T extends 'string' ? +ReturnArg : T extends 'number' ? +ReturnArg : T extends 'boolean' ? +ReturnArg : T extends 'symbol' ? +ReturnArg : T extends 'undefined' ? +ReturnArg : T extends 'object' ? +ReturnArg : T extends 'function' ? +ReturnArg : T extends 'array' ? +ReturnArg : any + +type AnyType = 'string' | 'number' | 'boolean' | 'symbol' | 'undefined' | 'object' | 'function' | 'array' | 'any' +type Any = (type?: T) => MapAnyReturn + +const anyFunction = (type: AnyType = 'any', options?: ArgumentOptions) => { + const description = `Arg.any{${type}}` + const predicate = (x: any) => { + switch (type) { + case 'any': + return true + case 'array': + return Array.isArray(x) + default: + return typeof x === type + } + } + + return new Argument(description, predicate, options) +} + +export const Arg = { + all: (): AllArguments => new AllArguments(), + is: createInversable(isFunction) as Inversable, + any: createInversable(anyFunction) as Inversable +} diff --git a/src/api/Constants.ts b/src/api/Constants.ts new file mode 100644 index 0000000..d53a809 --- /dev/null +++ b/src/api/Constants.ts @@ -0,0 +1,13 @@ +import { constants as sharedConstants } from '../shared' + +const received: typeof sharedConstants.CONTEXT.received.symbol = sharedConstants.CONTEXT.received.symbol +const didNotReceive: typeof sharedConstants.CONTEXT.didNotReceive.symbol = sharedConstants.CONTEXT.didNotReceive.symbol +const clearReceivedCalls: typeof sharedConstants.CONTEXT.clearReceivedCalls.symbol = sharedConstants.CONTEXT.clearReceivedCalls.symbol +const mimick: typeof sharedConstants.CONTEXT.mimick.symbol = sharedConstants.CONTEXT.mimick.symbol +const mimicks: typeof sharedConstants.CONTEXT.mimicks.symbol = sharedConstants.CONTEXT.mimicks.symbol +const throws: typeof sharedConstants.CONTEXT.throws.symbol = sharedConstants.CONTEXT.throws.symbol +const returns: typeof sharedConstants.CONTEXT.returns.symbol = sharedConstants.CONTEXT.returns.symbol +const resolves: typeof sharedConstants.CONTEXT.resolves.symbol = sharedConstants.CONTEXT.resolves.symbol +const rejects: typeof sharedConstants.CONTEXT.rejects.symbol = sharedConstants.CONTEXT.rejects.symbol + +export { received, didNotReceive, clearReceivedCalls, mimick, mimicks, throws, returns, resolves, rejects } diff --git a/src/api/Substitute.ts b/src/api/Substitute.ts new file mode 100644 index 0000000..384ec39 --- /dev/null +++ b/src/api/Substitute.ts @@ -0,0 +1,11 @@ +import { ObjectSubstitute } from './types' +import { SubstituteNode } from '../internals' + +export type SubstituteOf = ObjectSubstitute & T + +export class Substitute { + public static for(): SubstituteOf { + const substitute = SubstituteNode.createRoot() + return substitute.proxy as unknown as SubstituteOf + } +} diff --git a/src/api/index.ts b/src/api/index.ts new file mode 100644 index 0000000..eb6396c --- /dev/null +++ b/src/api/index.ts @@ -0,0 +1,3 @@ +export * from './Arg' +export * from './Substitute' +export * from './types' diff --git a/src/api/types/FunctionSubstitute.ts b/src/api/types/FunctionSubstitute.ts new file mode 100644 index 0000000..872faec --- /dev/null +++ b/src/api/types/FunctionSubstitute.ts @@ -0,0 +1,48 @@ +import { AllArguments } from '../../shared' +import { MockObjectMixin, NoArgumentMockObjectMixin } from './SubstitutionLevel' + +type TerminatingFunction = ((...args: TArguments) => void) & ((arg: AllArguments) => void) +export type FunctionSubstitute = + ((...args: TArguments) => (TReturnType & MockObjectMixin)) & + ((allArguments: AllArguments) => (TReturnType & MockObjectMixin)) + +export type FunctionSubstituteWithOverloads = + TFunc extends { + (...args: infer A1): infer R1; + (...args: infer A2): infer R2; + (...args: infer A3): infer R3; + (...args: infer A4): infer R4; + (...args: infer A5): infer R5; + } ? + FunctionHandler & FunctionHandler & + FunctionHandler & FunctionHandler + & FunctionHandler : TFunc extends { + (...args: infer A1): infer R1; + (...args: infer A2): infer R2; + (...args: infer A3): infer R3; + (...args: infer A4): infer R4; + } ? + FunctionHandler & FunctionHandler & + FunctionHandler & FunctionHandler : TFunc extends { + (...args: infer A1): infer R1; + (...args: infer A2): infer R2; + (...args: infer A3): infer R3; + } ? + FunctionHandler & FunctionHandler + & FunctionHandler : TFunc extends { + (...args: infer A1): infer R1; + (...args: infer A2): infer R2; + } ? + FunctionHandler & FunctionHandler : TFunc extends { + (...args: infer A1): infer R1; + } ? + FunctionHandler : never; + +type Equals = (() => T extends A ? 1 : 2) extends (() => T extends B ? 1 : 2) ? true : false; +type FunctionHandler = + Equals extends true ? + {} : Terminating extends true ? + TerminatingFunction : + FunctionSubstitute + +export type NoArgumentFunctionSubstitute = () => TReturnType & NoArgumentMockObjectMixin diff --git a/src/api/types/Substitute.ts b/src/api/types/Substitute.ts new file mode 100644 index 0000000..6921940 --- /dev/null +++ b/src/api/types/Substitute.ts @@ -0,0 +1,38 @@ +import { NoArgumentMockObjectMixin } from './SubstitutionLevel' +import { FunctionSubstituteWithOverloads, NoArgumentFunctionSubstitute } from './FunctionSubstitute' + +export type PropertySubstitute = + TReturnType & + NoArgumentMockObjectMixin; + +export type TryToExpandNonArgumentedTerminatingFunction = + TObject[TProperty] extends (...args: []) => unknown ? + () => void : + {} + +export type TryToExpandArgumentedTerminatingFunction = + TObject[TProperty] extends (...args: any) => any ? + FunctionSubstituteWithOverloads : + {} + +type TryToExpandNonArgumentedFunctionSubstitute = + TObject[TProperty] extends (...args: []) => infer R ? + NoArgumentFunctionSubstitute : + {} + +type TryToExpandArgumentedFunctionSubstitute = + TObject[TProperty] extends (...args: infer F) => any ? + F extends [] ? + {} : + FunctionSubstituteWithOverloads : + {} + +type TryToExpandPropertySubstitute = + PropertySubstitute + +export type ObjectSubstituteTransformation> = { + [P in keyof T]: + TryToExpandNonArgumentedFunctionSubstitute & + TryToExpandArgumentedFunctionSubstitute & + TryToExpandPropertySubstitute; +} diff --git a/src/api/types/SubstituteMethods.ts b/src/api/types/SubstituteMethods.ts new file mode 100644 index 0000000..e059418 --- /dev/null +++ b/src/api/types/SubstituteMethods.ts @@ -0,0 +1,29 @@ +import { constants } from '../../shared' +import { + TryToExpandNonArgumentedTerminatingFunction, + TryToExpandArgumentedTerminatingFunction +} from './Substitute' + +type TerminatingObject = { + [P in keyof T]: + TryToExpandNonArgumentedTerminatingFunction & + TryToExpandArgumentedTerminatingFunction & + T[P] +} + +export const received: typeof constants.CONTEXT.received.symbol = constants.CONTEXT.received.symbol +export const didNotReceive: typeof constants.CONTEXT.didNotReceive.symbol = constants.CONTEXT.didNotReceive.symbol +export const mimick: typeof constants.CONTEXT.mimick.symbol = constants.CONTEXT.mimick.symbol +export const clearReceivedCalls: typeof constants.CONTEXT.clearReceivedCalls.symbol = constants.CONTEXT.clearReceivedCalls.symbol + +export type ObjectSubstituteMethods = + (T extends { received: any } ? + { [received](amount?: number): TerminatingObject } : + { received(amount?: number): TerminatingObject }) & + (T extends { didNotReceive: any } ? + { [didNotReceive](): TerminatingObject } : + { didNotReceive(): TerminatingObject }) & + (T extends { mimick: any } ? + { [mimick](instance: T): void } : + { mimick(instance: T): void }) & + { [clearReceivedCalls](): void } diff --git a/src/api/types/SubstitutionLevel.ts b/src/api/types/SubstitutionLevel.ts new file mode 100644 index 0000000..8cf326d --- /dev/null +++ b/src/api/types/SubstitutionLevel.ts @@ -0,0 +1,41 @@ +import { constants } from '../../shared' + +export const returns: typeof constants.CONTEXT.returns.symbol = constants.CONTEXT.returns.symbol +export const throws: typeof constants.CONTEXT.throws.symbol = constants.CONTEXT.throws.symbol +export const resolves: typeof constants.CONTEXT.resolves.symbol = constants.CONTEXT.resolves.symbol +export const rejects: typeof constants.CONTEXT.rejects.symbol = constants.CONTEXT.rejects.symbol +export const mimicks: typeof constants.CONTEXT.mimicks.symbol = constants.CONTEXT.mimicks.symbol + +type OneArgumentRequiredFunction = (requiredInput: TArgs, ...restInputs: TArgs[]) => TReturnType; + +type MockObjectPromise = TReturnType extends Promise ? ( + (TReturnType extends { resolves: any } ? + { [resolves]: OneArgumentRequiredFunction } : + { resolves: OneArgumentRequiredFunction }) & + (TReturnType extends { rejects: any } ? + { [rejects]: OneArgumentRequiredFunction } : + { rejects: OneArgumentRequiredFunction }) +) : {} + +type BaseMockObjectMixin = + MockObjectPromise & + ( + (TObject extends { returns: any } ? + { [returns]: OneArgumentRequiredFunction } : + { returns: OneArgumentRequiredFunction }) & + (TObject extends { throws: any } ? + { [throws]: OneArgumentRequiredFunction } : + { throws: OneArgumentRequiredFunction }) + ) + +export type NoArgumentMockObjectMixin = + BaseMockObjectMixin & + (TObject extends { mimicks: any } ? + { [mimicks]: OneArgumentRequiredFunction<() => TReturnType, void> } : + { mimicks: OneArgumentRequiredFunction<() => TReturnType, void> }) + +export type MockObjectMixin = + BaseMockObjectMixin & + (TReturnType extends { mimicks: any } ? + { [mimicks]: OneArgumentRequiredFunction<(...args: TArguments) => TReturnType, void> } : + { mimicks: OneArgumentRequiredFunction<(...args: TArguments) => TReturnType, void> }) diff --git a/src/api/types/index.ts b/src/api/types/index.ts new file mode 100644 index 0000000..ef1e2ce --- /dev/null +++ b/src/api/types/index.ts @@ -0,0 +1,9 @@ +import { ObjectSubstituteTransformation } from './Substitute' +import { ObjectSubstituteMethods } from './SubstituteMethods' + +export type ObjectSubstitute = + ObjectSubstituteMethods & + ObjectSubstituteTransformation + +export { received, didNotReceive, clearReceivedCalls, mimick } from './SubstituteMethods' +export { returns, throws, resolves, rejects, mimicks } from './SubstitutionLevel' diff --git a/src/index.ts b/src/index.ts index 66a2325..75f54fb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,9 +1,3 @@ -import { Substitute, SubstituteOf } from './Substitute' -import { constants } from './utilities' -const clear = constants.CLEAR - -export { Arg } from './Arguments' -export { Substitute, SubstituteOf } -export { clear as ClearType } - -export default Substitute \ No newline at end of file +import { Substitute } from './api' +export * from './api' +export default Substitute diff --git a/src/internals/Constants.ts b/src/internals/Constants.ts new file mode 100644 index 0000000..5d40f45 --- /dev/null +++ b/src/internals/Constants.ts @@ -0,0 +1,18 @@ +const method = Symbol('method') +const property = Symbol('property') +const propertyTypes = { method, property } as const + +const get = Symbol('get') +const set = Symbol('set') +const accessorTypes = { get, set } as const + +const substituteExceptionTypes = { + callCountMismatch: 'CallCountMismatch', + propertyNotMocked: 'PropertyNotMocked' +} as const + +export const constants = { + PROPERTY: propertyTypes, + ACCESSOR: accessorTypes, + EXCEPTION: substituteExceptionTypes +} as const diff --git a/src/RecordedArguments.ts b/src/internals/RecordedArguments.ts similarity index 98% rename from src/RecordedArguments.ts rename to src/internals/RecordedArguments.ts index 3ea8910..470d489 100644 --- a/src/RecordedArguments.ts +++ b/src/internals/RecordedArguments.ts @@ -1,5 +1,5 @@ import { inspect, InspectOptions, isDeepStrictEqual } from 'util' -import { Argument, AllArguments } from './Arguments' +import { Argument, AllArguments } from '../shared' type ArgumentsClass = 'plain' | 'with-predicate' | 'wildcard' const argumentsClassDigitMapper: Record = { @@ -83,4 +83,4 @@ export class RecordedArguments { ? `(${inspectedValues.join(', ')})` : inspectedValues[0] } -} \ No newline at end of file +} diff --git a/src/Recorder.ts b/src/internals/Recorder.ts similarity index 99% rename from src/Recorder.ts rename to src/internals/Recorder.ts index bc6b97c..c6e3540 100644 --- a/src/Recorder.ts +++ b/src/internals/Recorder.ts @@ -70,4 +70,4 @@ export class Recorder { indexedRecord.delete(record) if (indexedRecord.size === 0) this.indexedRecords.delete(id) } -} \ No newline at end of file +} diff --git a/src/RecordsSet.ts b/src/internals/RecordsSet.ts similarity index 99% rename from src/RecordsSet.ts rename to src/internals/RecordsSet.ts index cc8026e..06fdab3 100644 --- a/src/RecordsSet.ts +++ b/src/internals/RecordsSet.ts @@ -72,4 +72,4 @@ export class RecordsSet extends Set { } } } -} \ No newline at end of file +} diff --git a/src/SubstituteException.ts b/src/internals/SubstituteException.ts similarity index 94% rename from src/SubstituteException.ts rename to src/internals/SubstituteException.ts index b396057..d84706e 100644 --- a/src/SubstituteException.ts +++ b/src/internals/SubstituteException.ts @@ -1,5 +1,6 @@ import { SubstituteNodeModel, SubstituteExceptionType } from './Types' -import { stringify, TextBuilder, constants } from './utilities' +import { stringify, TextBuilder } from './utilities' +import { constants } from './Constants' export class SubstituteException extends Error { public type?: SubstituteExceptionType @@ -43,4 +44,4 @@ export class SubstituteException extends Error { public static generic(message: string) { return new this(message) } -} \ No newline at end of file +} diff --git a/src/SubstituteNode.ts b/src/internals/SubstituteNode.ts similarity index 64% rename from src/SubstituteNode.ts rename to src/internals/SubstituteNode.ts index 3abc044..d549b2b 100644 --- a/src/SubstituteNode.ts +++ b/src/internals/SubstituteNode.ts @@ -2,47 +2,60 @@ import { inspect, InspectOptions, types } from 'util' import { SubstituteNodeBase } from './SubstituteNodeBase' import { RecordedArguments } from './RecordedArguments' -import { constants, is, stringify } from './utilities' import { SubstituteException } from './SubstituteException' -import type { FilterFunction, SubstituteContext, SubstitutionMethod, ClearType, PropertyType, SubstituteNodeModel, AccessorType } from './Types' -import type { ObjectSubstitute } from './Transformations' - -const instance = Symbol('Substitute:Instance') -const clearTypeToFilterMap: Record> = { - all: () => true, - receivedCalls: node => is.CONTEXT.none(node.context), - substituteValues: node => is.CONTEXT.substitution(node.context) -} +import { is, stringify, transform } from './utilities' + +import { constants } from './Constants' +import type { SubstituteContext, PropertyType, SubstituteNodeModel, AccessorType, SubstituteMethod, SubstitutionMethod, AssertionMethod } from './Types' +import { constants as sharedConstants } from '../shared/Constants' + + +export const instance = Symbol('Substitute:Instance') type SpecialProperty = typeof instance | typeof inspect.custom | typeof Symbol.toPrimitive | 'then' | 'toJSON' -type RootContext = { substituteMethodsEnabled: boolean } +type TT = Exclude +type ObjectSubstitute = { + [P in typeof sharedConstants.CONTEXT[TT]['raw'] | typeof sharedConstants.CONTEXT[TT]['symbol']]: + (...args: any[]) => T | void | Promise | Promise +} export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitute, SubstituteNodeModel { private _proxy: SubstituteNode - private _rootContext: RootContext private _propertyType: PropertyType = constants.PROPERTY.property private _accessorType: AccessorType = constants.ACCESSOR.get private _recordedArguments: RecordedArguments = RecordedArguments.none() - private _context: SubstituteContext = constants.CONTEXT.none + private _context: SubstituteContext = sharedConstants.CONTEXT.none.symbol private _retrySubstitutionExecutionAttempt: boolean = false public stack?: string private constructor(key: PropertyKey, parent?: SubstituteNode) { super(key, parent) - if (this.isRoot()) this._rootContext = { substituteMethodsEnabled: true } - else this._rootContext = this.root.rootContext + this._proxy = new Proxy( this, { get: function (target, property) { - if (target.isSpecialProperty(property)) return target.evaluateSpecialProperty(property) - if (target._retrySubstitutionExecutionAttempt) return target.reattemptSubstitutionExecution()[property] + if (target.isSpecialProperty(property)) { + return target.evaluateSpecialProperty(property) + } + + if (target._retrySubstitutionExecutionAttempt) { + return target.reattemptSubstitutionExecution()[property] + } + const newNode = SubstituteNode.createChild(property, target) if (target.isAssertion) newNode.executeAssertion() - if (target.isRoot() && target.rootContext.substituteMethodsEnabled && (is.method.assertion(property) || is.method.configuration(property))) { + const unresolvedAssertionFollowedBySubstitution = !target.hasContext && is.method.assertion(target.property) && !is.method.substitution(newNode.property) + if (target.hasDepthOfAtLeast(1) && unresolvedAssertionFollowedBySubstitution) { + target.assignContext(target.property) + target[target.context as AssertionMethod](...Array.isArray(target.recordedArguments.value) ? target.recordedArguments.value : [undefined]) + if (target.isAssertion) newNode.executeAssertion() + // if (target.isConfiguration) newNode.executeConfiguration() + } + if (target.isRoot() && is.method.contextValue(property) && (is.method.assertion(property) || is.method.configuration(property))) { newNode.assignContext(property) return newNode[property].bind(newNode) } @@ -52,7 +65,15 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu set: function (target, property, value) { const newNode = SubstituteNode.createChild(property, target) newNode.handleSetter(value) - if (target.isAssertion) newNode.executeAssertion() + if (target.isAssertion) + newNode.executeAssertion() + + if (target.hasDepthOfAtLeast(1) && !target.hasContext && is.method.assertion(target.property)) { + target.assignContext(target.property) + target[target.property](...Array.isArray(target.recordedArguments.value) ? target.recordedArguments.value : [undefined]) + if (target.isAssertion) newNode.executeAssertion() + } + return true }, apply: function (target, _thisArg, rawArguments) { @@ -68,7 +89,21 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu ) } - public static instance: typeof instance = instance + public received(amount?: number | undefined) { + return this[sharedConstants.CONTEXT.received.symbol](amount); + } + + public didNotReceive() { + return this[sharedConstants.CONTEXT.didNotReceive.symbol](); + } + + public mimick(instance: unknown) { + return this[sharedConstants.CONTEXT.mimick.symbol](instance); + } + + public clearReceivedCalls() { + return this[sharedConstants.CONTEXT.clearReceivedCalls.symbol](); + } public static createRoot(): SubstituteNode { return new this('*Substitute') @@ -82,24 +117,20 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu return this._proxy } - public get rootContext(): RootContext { - return this._rootContext - } - get context(): SubstituteContext { return this._context } get hasContext(): boolean { - return this.context !== 'none' + return this.context !== sharedConstants.CONTEXT.none.symbol } get isSubstitution(): boolean { - return is.method.substitution(this.context) + return is.CONTEXT.substitution(this.context) } get isAssertion(): boolean { - return is.method.assertion(this.context) + return is.CONTEXT.assertion(this.context) } get property(): PropertyKey { @@ -118,23 +149,24 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu return this._recordedArguments } - public received(amount?: number): SubstituteNode { + public [sharedConstants.CONTEXT.received.symbol](amount?: number): SubstituteNode { this.handleMethod([amount]) return this.proxy } - public didNotReceive(): SubstituteNode { + public [sharedConstants.CONTEXT.didNotReceive.symbol](): SubstituteNode { this.handleMethod([0]) return this.proxy } - public mimick() { + public [sharedConstants.CONTEXT.mimick.symbol](_instance: unknown) { throw new Error('Mimick is not implemented yet') } - public clearSubstitute(clearType: ClearType = constants.CLEAR.all): void { - this.handleMethod([clearType]) - const filter = clearTypeToFilterMap[clearType] + public [sharedConstants.CONTEXT.clearReceivedCalls.symbol](): void { + this.handleMethod([]) + + const filter = (node: SubstituteNode) => is.CONTEXT.none(node.context) this.recorder.clearRecords(filter) } @@ -142,9 +174,10 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu return types.isProxy(this) ? this[inspect.custom](...args) : this.printableForm(...args) } - private assignContext(context: SubstituteContext): void { - if (!is.method.substitute(context)) throw new Error(`Cannot assign context for property ${context.toString()}`) - this._context = context + private assignContext(context: SubstituteMethod): void { + this._context = typeof context === 'string' ? + transform.rawSymbolContextMap[context] : + context } private reattemptSubstitutionExecution(): SubstituteNode | any { @@ -161,24 +194,32 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu } private executeSubstitution(contextArguments: RecordedArguments) { - if (!this.hasChild()) throw new TypeError('Substitue node has no child') - if (!this.child.recordedArguments.hasArguments()) throw new TypeError('Child args') + if (!this.hasChild()) + throw new TypeError('Substitue node has no child') + + if (!this.child.recordedArguments.hasArguments()) + throw new TypeError('Child args') const substitutionMethod = this.context as SubstitutionMethod const substitutionValue = this.child.recordedArguments.value.length > 1 ? this.child.recordedArguments.value?.shift() : this.child.recordedArguments.value[0] switch (substitutionMethod) { + case sharedConstants.CONTEXT.throws.symbol: case 'throws': throw substitutionValue + case sharedConstants.CONTEXT.mimicks.symbol: case 'mimicks': if (is.PROPERTY.property(this.propertyType)) return substitutionValue() if (!contextArguments.hasArguments()) throw new TypeError('Context arguments cannot be undefined') return substitutionValue(...contextArguments.value) + case sharedConstants.CONTEXT.resolves.symbol: case 'resolves': return Promise.resolve(substitutionValue) + case sharedConstants.CONTEXT.rejects.symbol: case 'rejects': return Promise.reject(substitutionValue) + case sharedConstants.CONTEXT.returns.symbol: case 'returns': return substitutionValue default: @@ -187,17 +228,24 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu } private executeAssertion(): void | never { - if (!this.hasDepthOfAtLeast(2)) throw new Error('Not possible') - if (!this.parent.recordedArguments.hasArguments()) throw new TypeError('Parent args') - const expectedCount: number | undefined = this.parent.recordedArguments.value[0] ?? undefined + if (!this.hasDepthOfAtLeast(2)) + throw new Error('Depth is less than 2') + + if (!this.parent.recordedArguments.hasArguments()) + throw new Error('No parent args present') + + const expectedCount = this.parent.recordedArguments.value[0] ?? undefined const finiteExpectation = expectedCount !== undefined - if (finiteExpectation && (!Number.isInteger(expectedCount) || expectedCount < 0)) throw new Error('Expected count has to be a positive integer') + if (finiteExpectation && (!Number.isInteger(expectedCount) || expectedCount < 0)) { + return + } - const siblings = [...this.getAllSiblings().filter(n => !n.hasContext && n.accessorType === this.accessorType)] + // const withContext = this.parent.property === sharedConstants.CONTEXT.received.symbol + const withContext = false + const siblings = [...this.getAllSiblings().filter(n => (withContext || !n.hasContext) && n.accessorType === this.accessorType)] const hasBeenCalled = siblings.length > 0 const hasSiblingOfSamePropertyType = siblings.some(sibling => sibling.propertyType === this.propertyType) const allRecordedArguments = siblings.map(sibling => sibling.recordedArguments) - if ( !hasBeenCalled && (!finiteExpectation || expectedCount > 0) @@ -254,30 +302,35 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu const potentialSuitableSubstitutions = [...potentialSuitableSubstitutionsSet] const hasSuitableSubstitutions = strictSuitableSubstitutions.length > 0 const onlySubstitutionsWithThisNodePropertyType = potentialSuitableSubstitutions.length === 0 - if (onlySubstitutionsWithThisNodePropertyType && hasSuitableSubstitutions) return RecordedArguments.sort(strictSuitableSubstitutions)[0] - if (!onlySubstitutionsWithThisNodePropertyType) this._retrySubstitutionExecutionAttempt = true + if (onlySubstitutionsWithThisNodePropertyType && hasSuitableSubstitutions) + return RecordedArguments.sort(strictSuitableSubstitutions)[0] + + if (!onlySubstitutionsWithThisNodePropertyType) + this._retrySubstitutionExecutionAttempt = true } private isSpecialProperty(property: PropertyKey): property is SpecialProperty { - return property === SubstituteNode.instance || property === inspect.custom || property === Symbol.toPrimitive || property === 'then' || property === 'toJSON' + return property === instance || property === inspect.custom || property === Symbol.toPrimitive || property === 'then' || property === 'toJSON' } private evaluateSpecialProperty(property: SpecialProperty) { switch (property) { - case SubstituteNode.instance: + case instance: return this case 'toJSON': case inspect.custom: case Symbol.toPrimitive: return this.printableForm.bind(this) + case 'then': return + default: - throw SubstituteException.generic(`Evaluation of special property ${property} is not implemented`) + throw SubstituteException.generic(`Evaluation of special property ${property} is not implemented.`) } } private printableForm(_: number, options: InspectOptions): string { return this.isRoot() ? stringify.rootNode(this, inspect(this.recorder, options)) : stringify.node(this, this.child, options) } -} \ No newline at end of file +} diff --git a/src/SubstituteNodeBase.ts b/src/internals/SubstituteNodeBase.ts similarity index 100% rename from src/SubstituteNodeBase.ts rename to src/internals/SubstituteNodeBase.ts diff --git a/src/internals/Types.ts b/src/internals/Types.ts new file mode 100644 index 0000000..560cf01 --- /dev/null +++ b/src/internals/Types.ts @@ -0,0 +1,42 @@ +import { RecordedArguments } from './RecordedArguments' +import type { constants } from './Constants' +import type { constants as sharedConstants } from '../shared' + +type ContextMap = typeof sharedConstants.CONTEXT +type Unfold = T[keyof T] + +export type ContextReceived = Unfold +export type ContextDidNotReceive = Unfold +export type ContextClearReceivedCalls = Unfold +export type ContextMimick = Unfold +export type ContextMimicks = Unfold +export type ContextThrows = Unfold +export type ContextReturns = Unfold +export type ContextResolves = Unfold +export type ContextRejects = Unfold + +export type AssertionMethod = ContextReceived | ContextDidNotReceive +export type ConfigurationMethod = ContextClearReceivedCalls | ContextMimick +export type SubstitutionMethod = ContextMimicks | ContextThrows | ContextReturns | ContextResolves | ContextRejects +export type ContextNone = Unfold + +export type SubstituteMethod = AssertionMethod | ConfigurationMethod | SubstitutionMethod +export type SubstituteContext = Exclude +// export type SubstituteContext2 = ContextMap[keyof ContextMap]['symbol'] +// export type ClearType = typeof constants.CLEAR[keyof typeof constants.CLEAR]['raw'] + +// export type ClearType = 'all' | 'receivedCalls' | 'substituteValues' +type PropertyType = typeof constants.PROPERTY.method | typeof constants.PROPERTY.property +type AccessorType = typeof constants.ACCESSOR.get | typeof constants.ACCESSOR.set +type SubstituteExceptionType = typeof constants.EXCEPTION.callCountMismatch | typeof constants.EXCEPTION.propertyNotMocked + +export type FilterFunction = (item: T) => boolean + +export type { PropertyType, AccessorType, SubstituteExceptionType } +export type SubstituteNodeModel = { + propertyType: PropertyType + property: PropertyKey + context: SubstituteContext + recordedArguments: RecordedArguments + stack?: string +} diff --git a/src/internals/index.ts b/src/internals/index.ts new file mode 100644 index 0000000..87c8170 --- /dev/null +++ b/src/internals/index.ts @@ -0,0 +1 @@ +export * from './SubstituteNode' diff --git a/src/internals/utilities/Guards.ts b/src/internals/utilities/Guards.ts new file mode 100644 index 0000000..bb6baa0 --- /dev/null +++ b/src/internals/utilities/Guards.ts @@ -0,0 +1,73 @@ +import { AssertionMethod, ConfigurationMethod, SubstituteMethod, SubstitutionMethod, SubstituteContext, PropertyType, ContextNone, ContextReceived, ContextDidNotReceive, ContextClearReceivedCalls, ContextMimick, ContextMimicks, ContextThrows, ContextReturns, ContextResolves, ContextRejects } from '../Types' +import { constants } from '../Constants' +import { constants as sharedConstants } from '../../shared' + +const isAssertionMethod = (property: PropertyKey): property is AssertionMethod => + property === sharedConstants.CONTEXT.received.raw || + property === sharedConstants.CONTEXT.received.symbol || + property === sharedConstants.CONTEXT.didNotReceive.raw || + property === sharedConstants.CONTEXT.didNotReceive.symbol +const isConfigurationMethod = (property: PropertyKey): property is ConfigurationMethod => + property === sharedConstants.CONTEXT.clearReceivedCalls.raw || + property === sharedConstants.CONTEXT.clearReceivedCalls.symbol || + property === sharedConstants.CONTEXT.mimick.raw || + property === sharedConstants.CONTEXT.mimick.symbol +const isSubstitutionMethod = (property: PropertyKey): property is SubstitutionMethod => + property === sharedConstants.CONTEXT.mimicks.raw || + property === sharedConstants.CONTEXT.mimicks.symbol || + property === sharedConstants.CONTEXT.returns.raw || + property === sharedConstants.CONTEXT.returns.symbol || + property === sharedConstants.CONTEXT.throws.raw || + property === sharedConstants.CONTEXT.throws.symbol || + property === sharedConstants.CONTEXT.resolves.raw || + property === sharedConstants.CONTEXT.resolves.symbol || + property === sharedConstants.CONTEXT.rejects.raw || + property === sharedConstants.CONTEXT.rejects.symbol +const isSubstituteMethod = (property: PropertyKey): property is SubstituteMethod => + isSubstitutionMethod(property) || isConfigurationMethod(property) || isAssertionMethod(property) + +const isPropertyProperty = (value: PropertyType): value is (typeof constants['PROPERTY']['property']) => value === constants.PROPERTY.property +const isPropertyMethod = (value: PropertyType): value is (typeof constants['PROPERTY']['method']) => value === constants.PROPERTY.method + +const isContextNone = (value: SubstituteContext): value is Exclude => value === sharedConstants.CONTEXT.none.symbol +const isContextReceived = (value: SubstituteContext): value is Exclude => value === sharedConstants.CONTEXT.received.symbol +const isContextDidNotReceive = (value: SubstituteContext): value is Exclude => value === sharedConstants.CONTEXT.didNotReceive.symbol +const isContextClearSubstitute = (value: SubstituteContext): value is Exclude => value === sharedConstants.CONTEXT.clearReceivedCalls.symbol +const isContextMimick = (value: SubstituteContext): value is Exclude => value === sharedConstants.CONTEXT.mimick.symbol +const isContextMimicks = (value: SubstituteContext): value is Exclude => value === sharedConstants.CONTEXT.mimicks.symbol +const isContextThrows = (value: SubstituteContext): value is Exclude => value === sharedConstants.CONTEXT.throws.symbol +const isContextReturns = (value: SubstituteContext): value is Exclude => value === sharedConstants.CONTEXT.returns.symbol +const isContextResolves = (value: SubstituteContext): value is Exclude => value === sharedConstants.CONTEXT.resolves.symbol +const isContextRejects = (value: SubstituteContext): value is Exclude => value === sharedConstants.CONTEXT.rejects.symbol +const isContextSubstitution = (value: SubstituteContext): value is Exclude => typeof value !== 'string' && isSubstitutionMethod(value) +const isContextAssertion = (value: SubstituteContext): value is Exclude => typeof value !== 'string' && isAssertionMethod(value) + +const isContextValue = (property: PropertyKey): property is SubstituteContext => typeof property !== 'string' && isSubstituteMethod(property) + +export const method = { + assertion: isAssertionMethod, + configuration: isConfigurationMethod, + substitution: isSubstitutionMethod, + substitute: isSubstituteMethod, + contextValue: isContextValue +} + +export const PROPERTY = { + property: isPropertyProperty, + method: isPropertyMethod +} + +export const CONTEXT = { + none: isContextNone, + received: isContextReceived, + didNotReceive: isContextDidNotReceive, + clearSubstitute: isContextClearSubstitute, + mimick: isContextMimick, + mimicks: isContextMimicks, + throws: isContextThrows, + returns: isContextReturns, + resolves: isContextResolves, + rejects: isContextRejects, + substitution: isContextSubstitution, + assertion: isContextAssertion +} diff --git a/src/utilities/Stringify.ts b/src/internals/utilities/Stringify.ts similarity index 95% rename from src/utilities/Stringify.ts rename to src/internals/utilities/Stringify.ts index b4ec0bb..099d7d9 100644 --- a/src/utilities/Stringify.ts +++ b/src/internals/utilities/Stringify.ts @@ -40,7 +40,7 @@ const stringifyExpectation = (expected: { count: number | undefined, call: Subst const textBuilder = new TextBuilder() textBuilder.add(expected.count === undefined ? '1 or more' : expected.count.toString(), t => t.bold()) .add(' ') - .add(expected.call.propertyType, t => t.bold()) + .add(expected.call.propertyType.description!, t => t.bold()) .add(plurify(' call', expected.count), t => t.bold()) .add(' matching ') .addParts(...stringifyCall({ callPath: expected.call.property.toString() })(expected.call).map(t => t.bold())) @@ -76,7 +76,7 @@ const stringifyNode = (node: SubstituteNodeModel, childNode: SubstituteNodeModel '' const s = hasContext ? `${label}${inspect(childNode?.recordedArguments, options)}` : '' - return `${node.propertyType}<${node.property.toString()}>: ${args}${s}` + return `${node.propertyType.description}<${node.property.toString()}>: ${args}${s}` } export const stringify = { diff --git a/src/utilities/TextBuilder.ts b/src/internals/utilities/TextBuilder.ts similarity index 100% rename from src/utilities/TextBuilder.ts rename to src/internals/utilities/TextBuilder.ts diff --git a/src/internals/utilities/Transformations.ts b/src/internals/utilities/Transformations.ts new file mode 100644 index 0000000..d593e98 --- /dev/null +++ b/src/internals/utilities/Transformations.ts @@ -0,0 +1,17 @@ +import { constants as sharedConstants } from '../../shared' + +type A = typeof sharedConstants.CONTEXT[Exclude] +type B = A['raw'] +type C = A['symbol'] + +export const rawSymbolContextMap: Record = { + [sharedConstants.CONTEXT.received.raw]: sharedConstants.CONTEXT.received.symbol, + [sharedConstants.CONTEXT.didNotReceive.raw]: sharedConstants.CONTEXT.didNotReceive.symbol, + [sharedConstants.CONTEXT.clearReceivedCalls.raw]: sharedConstants.CONTEXT.clearReceivedCalls.symbol, + [sharedConstants.CONTEXT.mimick.raw]: sharedConstants.CONTEXT.mimick.symbol, + [sharedConstants.CONTEXT.mimicks.raw]: sharedConstants.CONTEXT.mimicks.symbol, + [sharedConstants.CONTEXT.throws.raw]: sharedConstants.CONTEXT.throws.symbol, + [sharedConstants.CONTEXT.returns.raw]: sharedConstants.CONTEXT.returns.symbol, + [sharedConstants.CONTEXT.resolves.raw]: sharedConstants.CONTEXT.resolves.symbol, + [sharedConstants.CONTEXT.rejects.raw]: sharedConstants.CONTEXT.rejects.symbol, +} diff --git a/src/utilities/index.ts b/src/internals/utilities/index.ts similarity index 65% rename from src/utilities/index.ts rename to src/internals/utilities/index.ts index 6448fa3..4c92f76 100644 --- a/src/utilities/index.ts +++ b/src/internals/utilities/index.ts @@ -1,4 +1,4 @@ export * from './TextBuilder' export * from './Stringify' -export * from './Constants' export * as is from './Guards' +export * as transform from './Transformations' diff --git a/src/shared/Arguments.ts b/src/shared/Arguments.ts new file mode 100644 index 0000000..267c69c --- /dev/null +++ b/src/shared/Arguments.ts @@ -0,0 +1,44 @@ +export type PredicateFunction = (arg: T) => boolean +export type ArgumentOptions = { + inverseMatch?: boolean +} +class BaseArgument { + private _description: string + constructor( + description: string, + private _matchingFunction: PredicateFunction, + private _options?: ArgumentOptions + ) { + this._description = `${this._options?.inverseMatch ? 'Not ' : ''}${description}` + } + + matches(arg: T) { + const inverseMatch = this._options?.inverseMatch ?? false + return inverseMatch ? !this._matchingFunction(arg) : this._matchingFunction(arg) + } + + toString() { + return this._description + } + + [Symbol.for('nodejs.util.inspect.custom')]() { + return this._description + } +} + +export class Argument extends BaseArgument { + private readonly _type = 'SingleArgument'; + get type(): 'SingleArgument' { + return this._type + } +} + +export class AllArguments extends BaseArgument { + private readonly _type = 'AllArguments'; + constructor() { + super('Arg.all{}', () => true, {}) + } + get type(): 'AllArguments' { + return this._type // TODO: Needed? + } +} diff --git a/src/shared/Constants.ts b/src/shared/Constants.ts new file mode 100644 index 0000000..2ba6616 --- /dev/null +++ b/src/shared/Constants.ts @@ -0,0 +1,75 @@ +type ValueToMap = { [key in T as Uncapitalize]: key } + +export type AssertionMethodRaw = 'received' | 'didNotReceive' +export type ConfigurationMethodRaw = 'clearReceivedCalls' | 'mimick' +export type SubstitutionMethodRaw = 'mimicks' | 'throws' | 'returns' | 'resolves' | 'rejects' + +const contextMethodTypes: ValueToMap = { + received: 'received', + didNotReceive: 'didNotReceive', + clearReceivedCalls: 'clearReceivedCalls', + mimick: 'mimick', + mimicks: 'mimicks', + throws: 'throws', + returns: 'returns', + resolves: 'resolves', + rejects: 'rejects' +} + +const received = Symbol(contextMethodTypes.received) +const didNotReceive = Symbol(contextMethodTypes.didNotReceive) +const clearReceivedCalls = Symbol(contextMethodTypes.clearReceivedCalls) +const mimick = Symbol(contextMethodTypes.mimick) +const mimicks = Symbol(contextMethodTypes.mimicks) +const throws = Symbol(contextMethodTypes.throws) +const returns = Symbol(contextMethodTypes.returns) +const resolves = Symbol(contextMethodTypes.resolves) +const rejects = Symbol(contextMethodTypes.rejects) +const none = Symbol('none') + +const contextTypes = { + none: { + raw: 'none', + symbol: none + }, + received: { + raw: contextMethodTypes.received, + symbol: received + }, + didNotReceive: { + raw: contextMethodTypes.didNotReceive, + symbol: didNotReceive + }, + clearReceivedCalls: { + raw: contextMethodTypes.clearReceivedCalls, + symbol: clearReceivedCalls + }, + mimick: { + raw: contextMethodTypes.mimick, + symbol: mimick + }, + mimicks: { + raw: contextMethodTypes.mimicks, + symbol: mimicks + }, + throws: { + raw: contextMethodTypes.throws, + symbol: throws + }, + returns: { + raw: contextMethodTypes.returns, + symbol: returns + }, + resolves: { + raw: contextMethodTypes.resolves, + symbol: resolves + }, + rejects: { + raw: contextMethodTypes.rejects, + symbol: rejects + } +} as const + +export const constants = { + CONTEXT: contextTypes +} diff --git a/src/shared/index.ts b/src/shared/index.ts new file mode 100644 index 0000000..c827a99 --- /dev/null +++ b/src/shared/index.ts @@ -0,0 +1,2 @@ +export * from './Constants' +export * from './Arguments' diff --git a/src/utilities/Constants.ts b/src/utilities/Constants.ts deleted file mode 100644 index ae7f42f..0000000 --- a/src/utilities/Constants.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { AccessorType, ClearType, PropertyType, SubstituteContext, SubstituteExceptionType } from '../Types' - -type ValueToMap = { [key in T as Uncapitalize]: key } -const propertyTypes: ValueToMap = { - method: 'method', - property: 'property' -} -const accessorTypes: ValueToMap = { - get: 'get', - set: 'set' -} -const clearTypes: ValueToMap = { - all: 'all', - receivedCalls: 'receivedCalls', - substituteValues: 'substituteValues' -} -const contextTypes: ValueToMap = { - none: 'none', - received: 'received', - didNotReceive: 'didNotReceive', - clearSubstitute: 'clearSubstitute', - mimick: 'mimick', - mimicks: 'mimicks', - throws: 'throws', - returns: 'returns', - resolves: 'resolves', - rejects: 'rejects' -} -const SubstituteExceptionTypes: ValueToMap = { - callCountMismatch: 'CallCountMismatch', - propertyNotMocked: 'PropertyNotMocked' -} - -export const constants = { - PROPERTY: propertyTypes, - ACCESSOR: accessorTypes, - CLEAR: clearTypes, - CONTEXT: contextTypes, - EXCEPTION: SubstituteExceptionTypes -} \ No newline at end of file diff --git a/src/utilities/Guards.ts b/src/utilities/Guards.ts deleted file mode 100644 index 26db312..0000000 --- a/src/utilities/Guards.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { AssertionMethod, ClearType, ConfigurationMethod, PropertyType, SubstituteMethod, SubstitutionMethod, SubstituteContext } from '../Types' -import { constants } from './Constants' - -const isAssertionMethod = (property: PropertyKey): property is AssertionMethod => - property === 'received' || property === 'didNotReceive' -const isConfigurationMethod = (property: PropertyKey): property is ConfigurationMethod => property === 'clearSubstitute' || property === 'mimick' -const isSubstitutionMethod = (property: PropertyKey): property is SubstitutionMethod => - property === 'mimicks' || property === 'returns' || property === 'throws' || property === 'resolves' || property === 'rejects' -const isSubstituteMethod = (property: PropertyKey): property is SubstituteMethod => - isSubstitutionMethod(property) || isConfigurationMethod(property) || isAssertionMethod(property) - -const isPropertyProperty = (value: PropertyType): value is (typeof constants['PROPERTY']['property']) => value === constants.PROPERTY.property -const isPropertyMethod = (value: PropertyType): value is (typeof constants['PROPERTY']['method']) => value === constants.PROPERTY.method - -const isClearAll = (value: ClearType): value is (typeof constants['CLEAR']['all']) => value === constants.CLEAR.all -const isClearReceivedCalls = (value: ClearType): value is (typeof constants['CLEAR']['receivedCalls']) => value === constants.CLEAR.receivedCalls -const isClearSubstituteValues = (value: ClearType): value is (typeof constants['CLEAR']['substituteValues']) => value === constants.CLEAR.substituteValues - -const isContextNone = (value: SubstituteContext): value is (typeof constants['CONTEXT']['none']) => value === constants.CONTEXT.none -const isContextReceived = (value: SubstituteContext): value is (typeof constants['CONTEXT']['received']) => value === constants.CONTEXT.received -const isContextDidNotReceive = (value: SubstituteContext): value is (typeof constants['CONTEXT']['didNotReceive']) => value === constants.CONTEXT.didNotReceive -const isContextClearSubstitute = (value: SubstituteContext): value is (typeof constants['CONTEXT']['clearSubstitute']) => value === constants.CONTEXT.clearSubstitute -const isContextMimick = (value: SubstituteContext): value is (typeof constants['CONTEXT']['mimick']) => value === constants.CONTEXT.mimick -const isContextMimicks = (value: SubstituteContext): value is (typeof constants['CONTEXT']['mimicks']) => value === constants.CONTEXT.mimicks -const isContextThrows = (value: SubstituteContext): value is (typeof constants['CONTEXT']['throws']) => value === constants.CONTEXT.throws -const isContextReturns = (value: SubstituteContext): value is (typeof constants['CONTEXT']['returns']) => value === constants.CONTEXT.returns -const isContextResolves = (value: SubstituteContext): value is (typeof constants['CONTEXT']['resolves']) => value === constants.CONTEXT.resolves -const isContextRejects = (value: SubstituteContext): value is (typeof constants['CONTEXT']['rejects']) => value === constants.CONTEXT.rejects -const isContextSubstitution = (value: SubstituteContext): value is SubstitutionMethod => isSubstitutionMethod(value) -const isContextAssertion = (value: SubstituteContext): value is AssertionMethod => isAssertionMethod(value) - -export const method = { - assertion: isAssertionMethod, - configuration: isConfigurationMethod, - substitution: isSubstitutionMethod, - substitute: isSubstituteMethod, -} - -export const PROPERTY = { - property: isPropertyProperty, - method: isPropertyMethod -} - -export const CLEAR = { - all: isClearAll, - receivedCalls: isClearReceivedCalls, - substituteValues: isClearSubstituteValues -} - -export const CONTEXT = { - none: isContextNone, - received: isContextReceived, - didNotReceive: isContextDidNotReceive, - clearSubstitute: isContextClearSubstitute, - mimick: isContextMimick, - mimicks: isContextMimicks, - throws: isContextThrows, - returns: isContextReturns, - resolves: isContextResolves, - rejects: isContextRejects, - substitution: isContextSubstitution, - assertion: isContextAssertion -} - From 87c76e805b011957822fdffcad07b8a5aafdf0b6 Mon Sep 17 00:00:00 2001 From: Mathias Lykkegaard Lorenzen Date: Fri, 19 Sep 2025 07:50:39 +0200 Subject: [PATCH 46/46] Bump version to release properly --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cca6f69..f03b6ba 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@fluffy-spoon/substitute", - "version": "2.0.0-beta.4", + "version": "2.0.1", "description": "TypeScript port of NSubstitute, which aims to provide a much more fluent mocking opportunity for strong-typed languages", "license": "MIT", "funding": {