From cfa0b9fdb8738adaccf8b279089d23c0fdceecdb Mon Sep 17 00:00:00 2001 From: Peter Barnum Date: Fri, 16 Aug 2024 12:07:12 -0600 Subject: [PATCH 01/14] init --- .gitignore | 2 + .mocharc.js | 7 + package-lock.json | 1250 ++++++++++++++++++++++++++++++++ package.json | 24 + src/global.d.ts | 1 + src/ts.ts | 251 +++++++ tests/fixtures/basicTypes.ts | 9 + tests/fixtures/complexTypes.ts | 2 + tests/tsAssertions.test.ts | 201 +++++ tsconfig.json | 31 + 10 files changed, 1778 insertions(+) create mode 100644 .gitignore create mode 100644 .mocharc.js create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 src/global.d.ts create mode 100644 src/ts.ts create mode 100644 tests/fixtures/basicTypes.ts create mode 100644 tests/fixtures/complexTypes.ts create mode 100644 tests/tsAssertions.test.ts create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f06235c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules +dist diff --git a/.mocharc.js b/.mocharc.js new file mode 100644 index 0000000..2a5067a --- /dev/null +++ b/.mocharc.js @@ -0,0 +1,7 @@ +/** @type {import('mocha').MochaOptions} */ +module.exports = { + require: 'ts-node/register', + spec: ['tests/**/*.test.ts'], + 'watch-files': ['src/**/*.ts', 'tests/**/*.ts'], + timeout: 10000, +}; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..443fe0b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1250 @@ +{ + "name": "course.typescript", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "course.typescript", + "version": "1.0.0", + "license": "ISC", + "devDependencies": { + "@types/chai": "^4.3.17", + "@types/mocha": "^10.0.7", + "@types/node": "^22.3.0", + "chai": "^4.5.0", + "cross-env": "^7.0.3", + "mocha": "^10.7.3", + "ts-node": "^10.9.2", + "typescript": "^5.5.4" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "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/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, + "node_modules/@types/chai": { + "version": "4.3.17", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.17.tgz", + "integrity": "sha512-zmZ21EWzR71B4Sscphjief5djsLre50M6lI622OSySTmn9DB3j+C3kWroHfBQWXbOBwbgg/M8CG/hUxDLIloow==", + "dev": true + }, + "node_modules/@types/mocha": { + "version": "10.0.7", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.7.tgz", + "integrity": "sha512-GN8yJ1mNTcFcah/wKEFIJckJx9iJLoMSzWcfRRuxz/Jk+U6KQNnml+etbtxFK8lPjzOw3zp4Ha/kjSst9fsHYw==", + "dev": true + }, + "node_modules/@types/node": { + "version": "22.3.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.3.0.tgz", + "integrity": "sha512-nrWpWVaDZuaVc5X84xJ0vNrLvomM205oQyLsRt7OHNZbSHslcWsvgFR7O7hire2ZonjLrWBbedmotmIlJDVd6g==", + "dev": true, + "dependencies": { + "undici-types": "~6.18.2" + } + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", + "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", + "dev": true, + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "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/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/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/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "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/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/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.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.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/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/chai": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", + "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", + "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.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "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/chalk/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/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.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "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" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "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/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/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "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/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "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/deep-eql": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", + "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/diff": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "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/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": "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/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "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/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.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/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-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/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/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/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/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "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/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-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": "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/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-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/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-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/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/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/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/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/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.7.3.tgz", + "integrity": "sha512-uQWxAu44wwiACGqjbPYmjo7Lg8sFrS3dQe7PP2FQI+woptP4vZXSMcfMyFL/e1yFEeEpV4RtyTpZROOKmxis+A==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.3", + "browser-stdout": "^1.3.1", + "chokidar": "^3.5.3", + "debug": "^4.3.5", + "diff": "^5.2.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.1.6", + "ms": "^2.1.3", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^6.5.1", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.9", + "yargs-unparser": "^2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "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==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "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/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/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/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/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/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-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/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/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/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/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/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/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "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/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/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/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/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/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/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/type-detect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/typescript": { + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.18.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.18.2.tgz", + "integrity": "sha512-5ruQbENj95yDYJNS3TvcaxPMshV7aizdv/hWYjGIKoANWKjhWNBsr2YEuYZKodQulB1b8l7ILOuDQep3afowQQ==", + "dev": true + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "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/workerpool": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", + "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", + "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/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/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/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/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==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "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/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "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/package.json b/package.json new file mode 100644 index 0000000..4e6560a --- /dev/null +++ b/package.json @@ -0,0 +1,24 @@ +{ + "name": "course.typescript", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "test": "cross-env TS_NODE_PROJECT=tsconfig.json mocha", + "test:dev": "cross-env TS_NODE_PROJECT=tsconfig.json mocha --watch", + "dev": "ts-node tests/ts.ts" + }, + "keywords": [], + "author": "Operation Spark", + "license": "ISC", + "description": "Learn the basics of typescript", + "devDependencies": { + "@types/chai": "^4.3.17", + "@types/mocha": "^10.0.7", + "@types/node": "^22.3.0", + "chai": "^4.5.0", + "cross-env": "^7.0.3", + "mocha": "^10.7.3", + "ts-node": "^10.9.2", + "typescript": "^5.5.4" + } +} diff --git a/src/global.d.ts b/src/global.d.ts new file mode 100644 index 0000000..c6a1dc4 --- /dev/null +++ b/src/global.d.ts @@ -0,0 +1 @@ +type FILL_ME_IN = TypeError; diff --git a/src/ts.ts b/src/ts.ts new file mode 100644 index 0000000..bc2b6c4 --- /dev/null +++ b/src/ts.ts @@ -0,0 +1,251 @@ +import assert from 'assert'; +import fsSync from 'fs'; +import path from 'path'; +import ts from 'typescript'; + +type LibVersions = + | 'esnext' + | 'es6' + | 'es5' + | 'es2023' + | 'es2022' + | 'es2021' + | 'es2020' + | 'es2019' + | 'es2018' + | 'es2017' + | 'es2016' + | 'es2015' + | 'dom'; + +type CompilationResult = { + code?: string; + diagnostics: ts.Diagnostic[]; +}; + +type CodeCheckerOptions = { + pathname?: string; + globalTypes?: string; +}; + +/** + * Test typescript types against a specific block of code + * + * @example + * ```ts + * // Create a new CodeChecker instance + * const checker = new CodeChecker({ + * filepath: 'path/to/input/file' + * }); + * + * // Assert that the code is valid; throws an error if the code is *not* valid + * const isValid = checker.assert( + * `const str: string = 'test';` + * ).isValid(); + * + * // Assert that the code is not valid; throws an error if the code *is* valid + * const isNotValid = checker.assert( + * `const str: string = 1;` + * ).isNotValid(); + * + * // Returns true if the code *is* valid + * const isValid = checker.test( + * `const str: string = 'test';` + * ); + * + * // Returns false if the code is *not* valid + * const isNotValid = checker.test( + * `const str: string = 1;` + * ); + * ``` + */ +export class CodeChecker { + private _pathname: string; + private _globalTypes = ''; + private code = ''; + private _types = new Map(); + + constructor(options: CodeCheckerOptions = {}) { + const { pathname, globalTypes } = options; + this._pathname = pathname ?? ''; + this._globalTypes = globalTypes ?? ''; + this.init(); + } + + private init() { + this.fetchCode(); + this.extractTypesAsStrings(); + } + + private extractTypesAsStrings() { + const node = ts.createSourceFile( + 'extractTypes.ts', // fileName + this.code, // sourceText + ts.ScriptTarget.Latest + ); + + const typeNodes: ts.TypeAliasDeclaration[] = []; + + node.forEachChild(child => { + if (ts.isTypeAliasDeclaration(child)) { + typeNodes.push(child); + } + }); + const codeBuffer = Buffer.from(this.code); + + typeNodes.forEach((node: ts.TypeAliasDeclaration) => { + const { pos, end } = node; + + const type = codeBuffer.subarray(pos, end).toString('utf-8'); + this.types.set(node.name.text, type); + }); + } + + private fetchCode() { + if (!this.pathname) { + this.code = ''; + return ''; + } + try { + const code = fsSync.readFileSync(this.pathname, 'utf-8'); + this.code = code; + return code; + } catch (err) { + throw new Error(`Cannot read file: '${this.pathname}'`); + } + } + + private compileTypeScriptCode( + filename: string, + code: string, + lib: LibVersions + ): CompilationResult { + const options = ts.getDefaultCompilerOptions(); + const realHost = ts.createCompilerHost(options, true); + + const sourceFile = ts.createSourceFile( + filename, + code, + ts.ScriptTarget.Latest + ); + let outputCode: string | undefined = undefined; + + const host: ts.CompilerHost = { + fileExists: filePath => + filePath === filename || realHost.fileExists(filePath), + directoryExists: realHost.directoryExists?.bind(realHost), + getCurrentDirectory: realHost.getCurrentDirectory.bind(realHost), + getDirectories: realHost.getDirectories?.bind(realHost), + getCanonicalFileName: realHost.getCanonicalFileName.bind(realHost), + getNewLine: realHost.getNewLine.bind(realHost), + getDefaultLibFileName: realHost.getDefaultLibFileName.bind(realHost), + getSourceFile: (sourceFilename, ...args) => { + if (sourceFilename === filename) { + return sourceFile; + } + return realHost.getSourceFile(sourceFilename, ...args); + }, + readFile: filePath => { + if (filePath === filename) { + return code; + } + realHost.readFile(filePath); + }, + useCaseSensitiveFileNames: () => realHost.useCaseSensitiveFileNames(), + writeFile: (_fileName, data) => (outputCode = data) + }; + + const rootName = require.resolve(`typescript/lib/lib.${lib}.d.ts`); + const globalPath = path.resolve(__dirname, 'global.d.ts'); + const program = ts.createProgram( + [rootName, filename, globalPath], + options, + host + ); + const emitResult = program.emit(); + const diagnostics = ts.getPreEmitDiagnostics(program); + return { + code: outputCode, + diagnostics: emitResult.diagnostics.concat(diagnostics) + }; + } + + private _test(testCode: string, typeName?: TypeNames) { + const selectedType = typeName && this.types.get(typeName); + if (typeName && !selectedType) { + throw new Error( + `Type '${typeName}' not found in file '${this.pathname}'` + ); + } + + const code = selectedType ?? this.code; + + /** Initial global types passed in */ + const globalTypes = this.globalTypes ? `${this.globalTypes}\n` : ''; + + const messages = this.compileTypeScriptCode( + 'temp.ts', + `${globalTypes}${code}\n${testCode}`, + 'es2022' + ).diagnostics.map(diagnostic => diagnostic.messageText); + + return { + valid: !messages.length, + messages: messages as string[] + }; + } + + public set pathname(pathname: string) { + this._pathname = pathname; + this.init(); + } + + public get pathname() { + return this._pathname; + } + + public get types() { + return this._types; + } + + public get globalTypes() { + return this._globalTypes; + } + + public set globalTypes(types: string) { + this._globalTypes = types; + } + + public restore(pathname?: string) { + this.pathname = pathname ?? this.pathname; + + this.init(); + } + + public test(testCode: string, typeName?: TypeNames) { + const { valid } = this._test(testCode, typeName); + + return valid; + } + + public assert(testCode: string, typeName?: TypeNames) { + const { valid, messages } = this._test(testCode, typeName); + + return { + isValid: (msg?: string) => { + assert( + valid, + new TypeError([...messages, msg].filter(Boolean).join('\n')) + ); + }, + isNotValid: (msg?: string) => { + assert( + !valid, + `Expected code '${testCode}' to be invalid${ + msg ? `\n - ${msg}` : '' + }` + ); + } + }; + } +} diff --git a/tests/fixtures/basicTypes.ts b/tests/fixtures/basicTypes.ts new file mode 100644 index 0000000..ad9396e --- /dev/null +++ b/tests/fixtures/basicTypes.ts @@ -0,0 +1,9 @@ +export type StringType = string; + +export type NumberType = number; + +export type BooleanType = boolean; + +export type EnumType = 'a' | 'b' | 'c'; + +export type ObjectType = { a: string; b: number }; diff --git a/tests/fixtures/complexTypes.ts b/tests/fixtures/complexTypes.ts new file mode 100644 index 0000000..ede3e89 --- /dev/null +++ b/tests/fixtures/complexTypes.ts @@ -0,0 +1,2 @@ +// export type AddFunction = FILL_ME_IN; +export type AddFunction = (a: number, b: number) => number; diff --git a/tests/tsAssertions.test.ts b/tests/tsAssertions.test.ts new file mode 100644 index 0000000..88db56a --- /dev/null +++ b/tests/tsAssertions.test.ts @@ -0,0 +1,201 @@ +import fs from 'fs/promises'; +import { expect } from 'chai'; +import { CodeChecker } from '../src/ts'; + +type TypeNames = + | 'StringType' + | 'NumberType' + | 'BooleanType' + | 'EnumType' + | 'ObjectType'; + +describe('ts-assertions', () => { + it('should instantiate a CodeChecker instance without a pathname', () => { + const checker = new CodeChecker(); + expect(checker).to.be.instanceOf(CodeChecker); + expect(checker).to.have.property('pathname').to.be.empty; + + expect(checker.test('const s: string = "hello";')).to.be.true; + expect(checker.test('const s: string = 1;')).to.be.false; + }); + + it('should instantiate a CodeChecker instance with a pathname', async () => { + const pathname = 'tests/fixtures/basicTypes.ts'; + const code = await fs.readFile(pathname, 'utf-8'); + + const checker = new CodeChecker({ pathname }); + expect(checker).to.be.instanceOf(CodeChecker); + expect(checker).to.have.property('pathname').to.equal(pathname); + expect(checker).to.have.property('globalTypes').to.be.empty; + expect(checker).to.have.property('code').to.equal(code); + expect(checker.types.size).to.be.greaterThan(0); + }); + + it('should parse types when instantiated with a pathname', () => { + const pathname = 'tests/fixtures/basicTypes.ts'; + + const checker = new CodeChecker({ pathname }); + + const types = new Map(); + + types.set('StringType', 'export type StringType = string;'); + types.set('NumberType', 'export type NumberType = number;'); + types.set('BooleanType', 'export type BooleanType = boolean;'); + types.set('EnumType', "export type EnumType = 'a' | 'b' | 'c';"); + types.set( + 'ObjectType', + 'export type ObjectType = { a: string; b: number };' + ); + types.forEach((value, key) => { + expect(checker.types.get(key)).to.include(value); + }); + }); + + it('should have access to default global types', () => { + const checker = new CodeChecker(); + + expect(checker.test('const err: FILL_ME_IN = new TypeError();')).to.be.true; + expect(checker.test('const err: FILL_ME_IN = "Invalid";')).to.be.false; + }); + + it('should include globalTypes when set during instantiation', () => { + const globalTypes = `type SHOULD_HAVE_ACCESS = TypeError;`; + const checker = new CodeChecker({ globalTypes }); + const expectTrue = 'const err: SHOULD_HAVE_ACCESS = new TypeError();'; + const expectFalse = 'const err: SHOULD_HAVE_ACCESS = "Invalid";'; + + expect(checker.globalTypes).to.include(globalTypes); + expect(checker.test(expectTrue)).to.be.true; + expect(checker.test(expectFalse)).to.be.false; + }); + + it('should include globalTypes when set after instantiation', () => { + const checker = new CodeChecker(); + const globalTypes = `type SHOULD_HAVE_ACCESS = TypeError;`; + checker.globalTypes = globalTypes; + const expectTrue = 'const err: SHOULD_HAVE_ACCESS = new TypeError();'; + const expectFalse = 'const err: SHOULD_HAVE_ACCESS = "Invalid";'; + + expect(checker.globalTypes).to.include(globalTypes); + expect(checker.test(expectTrue)).to.be.true; + expect(checker.test(expectFalse)).to.be.false; + }); + + it('should not overwrite default global types when setting globalTypes', () => { + const checker = new CodeChecker(); + const globalTypes = `type SHOULD_HAVE_ACCESS = TypeError;`; + checker.globalTypes = globalTypes; + + expect(checker.globalTypes).to.include(globalTypes); + + expect(checker.test('const err: FILL_ME_IN = new TypeError();')).to.be.true; + expect(checker.test('const err: SHOULD_HAVE_ACCESS = new TypeError();')).to + .be.true; + + expect(checker.test('const err: FILL_ME_IN = "Invalid";')).to.be.false; + expect(checker.test('const err: SHOULD_HAVE_ACCESS = "Invalid";')).to.be + .false; + }); + + it('should "test" code snippets (return boolean)', () => { + const checker = new CodeChecker(); + expect(checker.test('const str: string = "test";')).to.be.true; + expect(checker.test('const str: string = 1;')).to.be.false; + }); + + it('should "assert" code snippets (assertions)', () => { + const checker = new CodeChecker(); + checker.assert('const str: string = "test";').isValid(); + checker.assert('const str: string = 1;').isNotValid(); + }); + + it('should allow for updating global types', () => { + const checker = new CodeChecker(); + checker.globalTypes = `type SHOULD_HAVE_ACCESS = TypeError;`; + + expect(checker.test('const err: SHOULD_HAVE_ACCESS = new TypeError();')).to + .be.true; + expect(checker.test('const err: SHOULD_HAVE_ACCESS = "Invalid";')).to.be + .false; + + checker.globalTypes = `type SHOULD_HAVE_ACCESS = 'Invalid';`; + + expect(checker.test('const err: SHOULD_HAVE_ACCESS = new TypeError();')).to + .be.false; + expect(checker.test('const err: SHOULD_HAVE_ACCESS = "Invalid";')).to.be + .true; + }); + + describe('Code snippets with default types', () => { + const checker = new CodeChecker(); + + const types: { type: string; validCode: string; invalidCode: string }[] = [ + { + type: 'string', + validCode: 'const str: string = "test";', + invalidCode: 'const str: string = 1;' + }, + { + type: 'number', + validCode: 'const num: number = 1;', + invalidCode: 'const num: number = "test";' + }, + { + type: 'boolean', + validCode: 'const bool: boolean = true;', + invalidCode: 'const bool: boolean = 1;' + } + ]; + types.forEach(({ type, validCode, invalidCode }) => { + it(`should test/assert code snippets with custom type '${type}'`, () => { + expect(checker.test(validCode)).to.be.true; + expect(checker.test(invalidCode)).to.be.false; + checker.assert(validCode).isValid(); + checker.assert(invalidCode).isNotValid(); + }); + }); + }); + describe('Code snippets with custom types', () => { + const checker = new CodeChecker({ + pathname: 'tests/fixtures/basicTypes.ts', + globalTypes: `type FILL_ME_IN = TypeError;` + }); + + const types: { name: TypeNames; validCode: string; invalidCode: string }[] = + [ + { + name: 'StringType', + validCode: 'const str: StringType = "test";', + invalidCode: 'const str: StringType = 1;' + }, + { + name: 'NumberType', + validCode: 'const num: NumberType = 1;', + invalidCode: 'const num: NumberType = "test";' + }, + { + name: 'BooleanType', + validCode: 'const bool: BooleanType = true;', + invalidCode: 'const bool: BooleanType = 1;' + }, + { + name: 'EnumType', + validCode: 'const enumValue: EnumType = "a";', + invalidCode: 'const enumValue: EnumType = "d";' + }, + { + name: 'ObjectType', + validCode: 'const obj: ObjectType = { a: "test", b: 1 };', + invalidCode: 'const obj: ObjectType = { a: 1, b: "test" };' + } + ]; + types.forEach(({ name, validCode, invalidCode }) => { + it(`should test/assert code snippets with custom type '${name}'`, () => { + expect(checker.test(validCode, name)).to.be.true; + expect(checker.test(invalidCode, name)).to.be.false; + checker.assert(validCode, name).isValid(); + checker.assert(invalidCode, name).isNotValid(); + }); + }); + }); +}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..5f5b5c2 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,31 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + + /* Language and Environment */ + /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + "target": "ES2022", + /* Modules */ + /* Specify what module code is generated. */ + "module": "CommonJS", + + /* Output */ + "outDir": "./dist", + + "moduleResolution": "node", + /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + "esModuleInterop": true, + + /* Ensure that casing is correct in imports. */ + "forceConsistentCasingInFileNames": true, + + /* Type Checking */ + /* Enable all strict type-checking options. */ + "strict": true, + + /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + "noImplicitAny": true + }, + "include": ["src/**/*.ts", "tests/**/*.ts"], + "exclude": ["node_modules"] +} From 00de43873f968fbd31d87ebc8bdcef5cea63e5ab Mon Sep 17 00:00:00 2001 From: Peter Barnum Date: Fri, 16 Aug 2024 12:16:24 -0600 Subject: [PATCH 02/14] clear types when reassigned + add additional tests --- src/ts.ts | 1 + .../fixtures/{basicTypes.ts => fixtures1.ts} | 0 .../{complexTypes.ts => fixtures2.ts} | 0 tests/tsAssertions.test.ts | 29 +++++++++++++++---- 4 files changed, 25 insertions(+), 5 deletions(-) rename tests/fixtures/{basicTypes.ts => fixtures1.ts} (100%) rename tests/fixtures/{complexTypes.ts => fixtures2.ts} (100%) diff --git a/src/ts.ts b/src/ts.ts index bc2b6c4..f98cd17 100644 --- a/src/ts.ts +++ b/src/ts.ts @@ -78,6 +78,7 @@ export class CodeChecker { } private extractTypesAsStrings() { + this._types.clear(); const node = ts.createSourceFile( 'extractTypes.ts', // fileName this.code, // sourceText diff --git a/tests/fixtures/basicTypes.ts b/tests/fixtures/fixtures1.ts similarity index 100% rename from tests/fixtures/basicTypes.ts rename to tests/fixtures/fixtures1.ts diff --git a/tests/fixtures/complexTypes.ts b/tests/fixtures/fixtures2.ts similarity index 100% rename from tests/fixtures/complexTypes.ts rename to tests/fixtures/fixtures2.ts diff --git a/tests/tsAssertions.test.ts b/tests/tsAssertions.test.ts index 88db56a..e3e5ca4 100644 --- a/tests/tsAssertions.test.ts +++ b/tests/tsAssertions.test.ts @@ -20,7 +20,7 @@ describe('ts-assertions', () => { }); it('should instantiate a CodeChecker instance with a pathname', async () => { - const pathname = 'tests/fixtures/basicTypes.ts'; + const pathname = 'tests/fixtures/fixtures1.ts'; const code = await fs.readFile(pathname, 'utf-8'); const checker = new CodeChecker({ pathname }); @@ -32,7 +32,7 @@ describe('ts-assertions', () => { }); it('should parse types when instantiated with a pathname', () => { - const pathname = 'tests/fixtures/basicTypes.ts'; + const pathname = 'tests/fixtures/fixtures1.ts'; const checker = new CodeChecker({ pathname }); @@ -51,6 +51,20 @@ describe('ts-assertions', () => { }); }); + it('should parse types when pathname is updated', () => { + const initialPathname = 'tests/fixtures/fixtures1.ts'; + + const checker = new CodeChecker({ pathname: initialPathname }); + + expect(checker.types.size).to.equal(5); + + const updatedPathname = 'tests/fixtures/fixtures2.ts'; + + checker.pathname = updatedPathname; + + expect(checker.types.size).to.equal(1); + }); + it('should have access to default global types', () => { const checker = new CodeChecker(); @@ -147,17 +161,20 @@ describe('ts-assertions', () => { } ]; types.forEach(({ type, validCode, invalidCode }) => { - it(`should test/assert code snippets with custom type '${type}'`, () => { + it(`should test code snippets with custom type '${type}'`, () => { expect(checker.test(validCode)).to.be.true; expect(checker.test(invalidCode)).to.be.false; + }); + it(`should assert code snippets with custom type '${type}'`, () => { checker.assert(validCode).isValid(); checker.assert(invalidCode).isNotValid(); }); }); }); + describe('Code snippets with custom types', () => { const checker = new CodeChecker({ - pathname: 'tests/fixtures/basicTypes.ts', + pathname: 'tests/fixtures/fixtures1.ts', globalTypes: `type FILL_ME_IN = TypeError;` }); @@ -190,9 +207,11 @@ describe('ts-assertions', () => { } ]; types.forEach(({ name, validCode, invalidCode }) => { - it(`should test/assert code snippets with custom type '${name}'`, () => { + it(`should test code snippets with custom type '${name}'`, () => { expect(checker.test(validCode, name)).to.be.true; expect(checker.test(invalidCode, name)).to.be.false; + }); + it(`should assert code snippets with custom type '${name}'`, () => { checker.assert(validCode, name).isValid(); checker.assert(invalidCode, name).isNotValid(); }); From 48f97dc85ea024819e7df3e1c12cc3e5014851ca Mon Sep 17 00:00:00 2001 From: Peter Barnum Date: Fri, 16 Aug 2024 12:18:31 -0600 Subject: [PATCH 03/14] cleanup ts file --- tsconfig.json | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index 5f5b5c2..1ad40d9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,29 +1,12 @@ { "compilerOptions": { - /* Visit https://aka.ms/tsconfig to read more about this file */ - - /* Language and Environment */ - /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ "target": "ES2022", - /* Modules */ - /* Specify what module code is generated. */ "module": "CommonJS", - - /* Output */ "outDir": "./dist", - "moduleResolution": "node", - /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ "esModuleInterop": true, - - /* Ensure that casing is correct in imports. */ "forceConsistentCasingInFileNames": true, - - /* Type Checking */ - /* Enable all strict type-checking options. */ "strict": true, - - /* Enable error reporting for expressions and declarations with an implied 'any' type. */ "noImplicitAny": true }, "include": ["src/**/*.ts", "tests/**/*.ts"], From 4b97ebae9b1aec3f3a4b3b9540c7c68fa9ef52ee Mon Sep 17 00:00:00 2001 From: Peter Barnum Date: Fri, 16 Aug 2024 13:21:02 -0600 Subject: [PATCH 04/14] add license + setup build --- .gitignore | 1 + .mocharc.js | 3 +- .npmignore | 7 + .npmrc | 1 + .vscode/settings.json | 3 + LICENSE | 21 + README.md | 55 +- package-lock.json | 1689 +++++++++++++++++++++++++++++++++++- package.json | 32 +- src/{ts.ts => index.ts} | 11 +- tests/tsAssertions.test.ts | 2 +- tsconfig.json | 2 +- tsup.config.ts | 10 + 13 files changed, 1782 insertions(+), 55 deletions(-) create mode 100644 .npmignore create mode 100644 .npmrc create mode 100644 .vscode/settings.json create mode 100644 LICENSE rename src/{ts.ts => index.ts} (97%) create mode 100644 tsup.config.ts diff --git a/.gitignore b/.gitignore index f06235c..29f8e79 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules dist +DS_Store diff --git a/.mocharc.js b/.mocharc.js index 2a5067a..2a56993 100644 --- a/.mocharc.js +++ b/.mocharc.js @@ -1,7 +1,8 @@ /** @type {import('mocha').MochaOptions} */ +// process.env.TS_NODE_PROJECT = 'tsconfig.json'; module.exports = { require: 'ts-node/register', spec: ['tests/**/*.test.ts'], 'watch-files': ['src/**/*.ts', 'tests/**/*.ts'], - timeout: 10000, + timeout: 10000 }; diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..4e99d34 --- /dev/null +++ b/.npmignore @@ -0,0 +1,7 @@ +tests +.github +.vscode +node_modules +tsconfig.json +tsup.config.ts +mocharc.js diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..ee4c38d --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +@operationspark.org/ts-assertion:registry=https://npm.pkg.github.com diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..49f7845 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "cSpell.words": ["tsup"] +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c2a5db9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Operation Spark + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 20f786b..2f1815d 100644 --- a/README.md +++ b/README.md @@ -5,5 +5,58 @@ This library provides assertions for testing types ## Installation ```sh -npm install +npm install -D @operationspark.org/ts-assertion +``` + +## Usage + +### `CodeCheckerOptions` + +| Name | Description | Optional | +| ------------- | ---------------------------------- | -------- | +| `pathname` | Pathname to input file | true | +| `globalTypes` | string of globally available types | true | + +```ts +// Without file +import { CodeChecker } from '@operationspark.org/ts-assertion'; + +const checker = new CodeChecker(); + +expect(checker.test('const str: string = "test";')).to.be.true; +expect(checker.test('const str: string = 1;')).to.be.false; + +checker.assert('const str: string = "test";').isValid(); +checker.assert('const str: string = 1;').isNotValid(); +``` + +```ts +import { CodeChecker } from '@operationspark.org/ts-assertion'; + +const options: = { + pathname: 'path/to/file.ts', + globalTypes: 'type PrimitiveType = string | number | boolean;', +}; +type TypeNames = 'StringType' | 'NumberType' | 'BooleanType' | 'EnumType'; +const checker = new CodeChecker(options); + +// file.ts +/* +export type StringType = string; +export type NumberType = number; +export type BooleanType = boolean; +export type EnumType = 'a' | 'b' | 'c'; +*/ + +// Test returns true if the code is valid +expect(checker.test('const str: StringType = "test";')).to.be.true; +expect(checker.test('const str: string = 1;')).to.be.false; + +// Assert throws an error if the code is not valid/invalid +checker.assert('const str: StringType = "test";').isValid(); +checker.assert('const str: string = 1;').isNotValid(); + +// Or more specifically, just test the type in the file +expect(checker.test('const str: StringType = "test";'), 'StringType').to.be.true; +checker.assert('const str: StringType = "test";', 'StringType').isValid(); ``` diff --git a/package-lock.json b/package-lock.json index 443fe0b..69b6aa8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,16 +7,18 @@ "": { "name": "course.typescript", "version": "1.0.0", - "license": "ISC", + "license": "MIT", + "dependencies": { + "typescript": "^5.5.4" + }, "devDependencies": { "@types/chai": "^4.3.17", "@types/mocha": "^10.0.7", "@types/node": "^22.3.0", "chai": "^4.5.0", - "cross-env": "^7.0.3", "mocha": "^10.7.3", "ts-node": "^10.9.2", - "typescript": "^5.5.4" + "tsup": "^8.2.4" } }, "node_modules/@cspotcode/source-map-support": { @@ -31,6 +33,510 @@ "node": ">=12" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.0.tgz", + "integrity": "sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.0.tgz", + "integrity": "sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.0.tgz", + "integrity": "sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.0.tgz", + "integrity": "sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.0.tgz", + "integrity": "sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.0.tgz", + "integrity": "sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.0.tgz", + "integrity": "sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.0.tgz", + "integrity": "sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.0.tgz", + "integrity": "sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.0.tgz", + "integrity": "sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.0.tgz", + "integrity": "sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.0.tgz", + "integrity": "sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.0.tgz", + "integrity": "sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.0.tgz", + "integrity": "sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.0.tgz", + "integrity": "sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.0.tgz", + "integrity": "sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.0.tgz", + "integrity": "sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.0.tgz", + "integrity": "sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.0.tgz", + "integrity": "sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.0.tgz", + "integrity": "sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.0.tgz", + "integrity": "sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.0.tgz", + "integrity": "sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.0.tgz", + "integrity": "sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.0.tgz", + "integrity": "sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/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/@isaacs/cliui/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/@isaacs/cliui/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/@isaacs/cliui/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/@isaacs/cliui/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/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "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/gen-mapping/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/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", @@ -40,21 +546,283 @@ "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.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "dev": true }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "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/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.20.0.tgz", + "integrity": "sha512-TSpWzflCc4VGAUJZlPpgAJE1+V60MePDQnBd7PPkpuEmOy8i87aL6tinFGKBFKuEDikYpig72QzdT3QPYIi+oA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.20.0.tgz", + "integrity": "sha512-u00Ro/nok7oGzVuh/FMYfNoGqxU5CPWz1mxV85S2w9LxHR8OoMQBuSk+3BKVIDYgkpeOET5yXkx90OYFc+ytpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.20.0.tgz", + "integrity": "sha512-uFVfvzvsdGtlSLuL0ZlvPJvl6ZmrH4CBwLGEFPe7hUmf7htGAN+aXo43R/V6LATyxlKVC/m6UsLb7jbG+LG39Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.20.0.tgz", + "integrity": "sha512-xbrMDdlev53vNXexEa6l0LffojxhqDTBeL+VUxuuIXys4x6xyvbKq5XqTXBCEUA8ty8iEJblHvFaWRJTk/icAQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.20.0.tgz", + "integrity": "sha512-jMYvxZwGmoHFBTbr12Xc6wOdc2xA5tF5F2q6t7Rcfab68TT0n+r7dgawD4qhPEvasDsVpQi+MgDzj2faOLsZjA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.20.0.tgz", + "integrity": "sha512-1asSTl4HKuIHIB1GcdFHNNZhxAYEdqML/MW4QmPS4G0ivbEcBr1JKlFLKsIRqjSwOBkdItn3/ZDlyvZ/N6KPlw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.20.0.tgz", + "integrity": "sha512-COBb8Bkx56KldOYJfMf6wKeYJrtJ9vEgBRAOkfw6Ens0tnmzPqvlpjZiLgkhg6cA3DGzCmLmmd319pmHvKWWlQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.20.0.tgz", + "integrity": "sha512-+it+mBSyMslVQa8wSPvBx53fYuZK/oLTu5RJoXogjk6x7Q7sz1GNRsXWjn6SwyJm8E/oMjNVwPhmNdIjwP135Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.20.0.tgz", + "integrity": "sha512-yAMvqhPfGKsAxHN8I4+jE0CpLWD8cv4z7CK7BMmhjDuz606Q2tFKkWRY8bHR9JQXYcoLfopo5TTqzxgPUjUMfw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.20.0.tgz", + "integrity": "sha512-qmuxFpfmi/2SUkAw95TtNq/w/I7Gpjurx609OOOV7U4vhvUhBcftcmXwl3rqAek+ADBwSjIC4IVNLiszoj3dPA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.20.0.tgz", + "integrity": "sha512-I0BtGXddHSHjV1mqTNkgUZLnS3WtsqebAXv11D5BZE/gfw5KoyXSAXVqyJximQXNvNzUo4GKlCK/dIwXlz+jlg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.20.0.tgz", + "integrity": "sha512-y+eoL2I3iphUg9tN9GB6ku1FA8kOfmF4oUEWhztDJ4KXJy1agk/9+pejOuZkNFhRwHAOxMsBPLbXPd6mJiCwew==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.20.0.tgz", + "integrity": "sha512-hM3nhW40kBNYUkZb/r9k2FKK+/MnKglX7UYd4ZUy5DJs8/sMsIbqWK2piZtVGE3kcXVNj3B2IrUYROJMMCikNg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.20.0.tgz", + "integrity": "sha512-psegMvP+Ik/Bg7QRJbv8w8PAytPA7Uo8fpFjXyCRHWm6Nt42L+JtoqH8eDQ5hRP7/XW2UiIriy1Z46jf0Oa1kA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.20.0.tgz", + "integrity": "sha512-GabekH3w4lgAJpVxkk7hUzUf2hICSQO0a/BLFA11/RMxQT92MabKAqyubzDZmMOC/hcJNlc+rrypzNzYl4Dx7A==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.20.0.tgz", + "integrity": "sha512-aJ1EJSuTdGnM6qbVC4B5DSmozPTqIag9fSzXRNNo+humQLG89XpPgdt16Ia56ORD7s+H8Pmyx44uczDQ0yDzpg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] }, "node_modules/@tsconfig/node10": { "version": "1.0.11", @@ -86,6 +854,12 @@ "integrity": "sha512-zmZ21EWzR71B4Sscphjief5djsLre50M6lI622OSySTmn9DB3j+C3kWroHfBQWXbOBwbgg/M8CG/hUxDLIloow==", "dev": true }, + "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/mocha": { "version": "10.0.7", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.7.tgz", @@ -158,6 +932,12 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true + }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -183,6 +963,15 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, + "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/assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", @@ -237,6 +1026,30 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "node_modules/bundle-require": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-5.0.0.tgz", + "integrity": "sha512-GuziW3fSSmopcx4KRymQEJVbZUfqlCqcq7dvs6TYwKRZiegK/2buMxQTPs6MGlNv50wms1699qYO54R8XfRX4w==", + "dev": true, + "dependencies": { + "load-tsconfig": "^0.2.3" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "esbuild": ">=0.18" + } + }, + "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/camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", @@ -360,30 +1173,30 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/consola": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz", + "integrity": "sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==", + "dev": true, + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true }, - "node_modules/cross-env": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", - "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "bin": { - "cross-env": "src/bin/cross-env.js", - "cross-env-shell": "src/bin/cross-env-shell.js" - }, - "engines": { - "node": ">=10.14", - "npm": ">=6", - "yarn": ">=1" - } - }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -454,12 +1267,69 @@ "node": ">=0.3.1" } }, + "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/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/esbuild": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.0.tgz", + "integrity": "sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.23.0", + "@esbuild/android-arm": "0.23.0", + "@esbuild/android-arm64": "0.23.0", + "@esbuild/android-x64": "0.23.0", + "@esbuild/darwin-arm64": "0.23.0", + "@esbuild/darwin-x64": "0.23.0", + "@esbuild/freebsd-arm64": "0.23.0", + "@esbuild/freebsd-x64": "0.23.0", + "@esbuild/linux-arm": "0.23.0", + "@esbuild/linux-arm64": "0.23.0", + "@esbuild/linux-ia32": "0.23.0", + "@esbuild/linux-loong64": "0.23.0", + "@esbuild/linux-mips64el": "0.23.0", + "@esbuild/linux-ppc64": "0.23.0", + "@esbuild/linux-riscv64": "0.23.0", + "@esbuild/linux-s390x": "0.23.0", + "@esbuild/linux-x64": "0.23.0", + "@esbuild/netbsd-x64": "0.23.0", + "@esbuild/openbsd-arm64": "0.23.0", + "@esbuild/openbsd-x64": "0.23.0", + "@esbuild/sunos-x64": "0.23.0", + "@esbuild/win32-arm64": "0.23.0", + "@esbuild/win32-ia32": "0.23.0", + "@esbuild/win32-x64": "0.23.0" + } + }, "node_modules/escalade": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", @@ -481,6 +1351,54 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "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-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/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/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -518,6 +1436,34 @@ "flat": "cli.js" } }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/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/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -556,6 +1502,38 @@ "node": "*" } }, + "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": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "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", @@ -568,6 +1546,41 @@ "node": ">= 6" } }, + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -586,6 +1599,24 @@ "he": "bin/he" } }, + "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.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -663,6 +1694,18 @@ "node": ">=8" } }, + "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": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", @@ -681,6 +1724,30 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -693,6 +1760,33 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "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-tsconfig": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz", + "integrity": "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -708,6 +1802,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "dev": true + }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -733,12 +1833,55 @@ "get-func-name": "^2.0.1" } }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, "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/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.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "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": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", @@ -751,6 +1894,15 @@ "node": ">=10" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/mocha": { "version": "10.7.3", "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.7.3.tgz", @@ -806,16 +1958,48 @@ "url": "https://github.com/sponsors/isaacs" } }, - "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/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "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/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "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/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" @@ -830,6 +2014,21 @@ "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-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -860,6 +2059,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "dev": true + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -878,6 +2083,31 @@ "node": ">=8" } }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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/pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", @@ -887,6 +2117,12 @@ "node": "*" } }, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "dev": true + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -899,6 +2135,86 @@ "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/postcss-load-config": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "lilconfig": "^3.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "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", @@ -929,6 +2245,83 @@ "node": ">=0.10.0" } }, + "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/rollup": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.20.0.tgz", + "integrity": "sha512-6rbWBChcnSGzIlXeIdNIZTopKYad8ZG8ajhl78lGRLsI2rX8IkaotQhVas2Ma+GPxJav19wrSzvRvuiv0YKzWw==", + "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.20.0", + "@rollup/rollup-android-arm64": "4.20.0", + "@rollup/rollup-darwin-arm64": "4.20.0", + "@rollup/rollup-darwin-x64": "4.20.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.20.0", + "@rollup/rollup-linux-arm-musleabihf": "4.20.0", + "@rollup/rollup-linux-arm64-gnu": "4.20.0", + "@rollup/rollup-linux-arm64-musl": "4.20.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.20.0", + "@rollup/rollup-linux-riscv64-gnu": "4.20.0", + "@rollup/rollup-linux-s390x-gnu": "4.20.0", + "@rollup/rollup-linux-x64-gnu": "4.20.0", + "@rollup/rollup-linux-x64-musl": "4.20.0", + "@rollup/rollup-win32-arm64-msvc": "4.20.0", + "@rollup/rollup-win32-ia32-msvc": "4.20.0", + "@rollup/rollup-win32-x64-msvc": "4.20.0", + "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", @@ -979,6 +2372,33 @@ "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/source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "dev": true, + "dependencies": { + "whatwg-url": "^7.0.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -993,6 +2413,21 @@ "node": ">=8" } }, + "node_modules/string-width-cjs": { + "name": "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/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -1005,6 +2440,28 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "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/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", @@ -1017,6 +2474,28 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -1032,6 +2511,27 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -1044,6 +2544,30 @@ "node": ">=8.0" } }, + "node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true + }, "node_modules/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", @@ -1096,6 +2620,57 @@ "node": ">=0.3.1" } }, + "node_modules/tsup": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/tsup/-/tsup-8.2.4.tgz", + "integrity": "sha512-akpCPePnBnC/CXgRrcy72ZSntgIEUa1jN0oJbbvpALWKNOz1B7aM+UVDWGRGIO/T/PZugAESWDJUAb5FD48o8Q==", + "dev": true, + "dependencies": { + "bundle-require": "^5.0.0", + "cac": "^6.7.14", + "chokidar": "^3.6.0", + "consola": "^3.2.3", + "debug": "^4.3.5", + "esbuild": "^0.23.0", + "execa": "^5.1.1", + "globby": "^11.1.0", + "joycon": "^3.1.1", + "picocolors": "^1.0.1", + "postcss-load-config": "^6.0.1", + "resolve-from": "^5.0.0", + "rollup": "^4.19.0", + "source-map": "0.8.0-beta.0", + "sucrase": "^3.35.0", + "tree-kill": "^1.2.2" + }, + "bin": { + "tsup": "dist/cli-default.js", + "tsup-node": "dist/cli-node.js" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@microsoft/api-extractor": "^7.36.0", + "@swc/core": "^1", + "postcss": "^8.4.12", + "typescript": ">=4.5.0" + }, + "peerDependenciesMeta": { + "@microsoft/api-extractor": { + "optional": true + }, + "@swc/core": { + "optional": true + }, + "postcss": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, "node_modules/type-detect": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", @@ -1109,7 +2684,6 @@ "version": "5.5.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", - "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -1130,6 +2704,23 @@ "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", "dev": true }, + "node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -1168,6 +2759,24 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs": { + "name": "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/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/package.json b/package.json index 4e6560a..81cc7a7 100644 --- a/package.json +++ b/package.json @@ -1,24 +1,36 @@ { - "name": "course.typescript", + "name": "ts-assertion", "version": "1.0.0", - "main": "index.js", + "main": "dist/index.js", "scripts": { - "test": "cross-env TS_NODE_PROJECT=tsconfig.json mocha", - "test:dev": "cross-env TS_NODE_PROJECT=tsconfig.json mocha --watch", - "dev": "ts-node tests/ts.ts" + "test": "mocha", + "test:dev": "mocha --watch", + "build": "tsup src/index.ts", + "prepublish": "npm test && npm run build", + "publish": "npm publish --access public" }, - "keywords": [], + "keywords": [ + "typescript", + "assertion", + "testing" + ], "author": "Operation Spark", - "license": "ISC", - "description": "Learn the basics of typescript", + "license": "MIT", + "description": "Assertion library for testing typescript validity", + "repository": { + "type": "git", + "url": "git+OperationSpark/typescript-assertion.git" + }, + "dependencies": { + "typescript": "^5.5.4" + }, "devDependencies": { "@types/chai": "^4.3.17", "@types/mocha": "^10.0.7", "@types/node": "^22.3.0", "chai": "^4.5.0", - "cross-env": "^7.0.3", "mocha": "^10.7.3", "ts-node": "^10.9.2", - "typescript": "^5.5.4" + "tsup": "^8.2.4" } } diff --git a/src/ts.ts b/src/index.ts similarity index 97% rename from src/ts.ts rename to src/index.ts index f98cd17..d4ecbd0 100644 --- a/src/ts.ts +++ b/src/index.ts @@ -62,8 +62,9 @@ type CodeCheckerOptions = { export class CodeChecker { private _pathname: string; private _globalTypes = ''; - private code = ''; private _types = new Map(); + private _version: LibVersions = 'es2022'; + private code = ''; constructor(options: CodeCheckerOptions = {}) { const { pathname, globalTypes } = options; @@ -217,6 +218,14 @@ export class CodeChecker { this._globalTypes = types; } + public get version() { + return this._version; + } + + public set version(version: LibVersions) { + this._version = version; + } + public restore(pathname?: string) { this.pathname = pathname ?? this.pathname; diff --git a/tests/tsAssertions.test.ts b/tests/tsAssertions.test.ts index e3e5ca4..9ee1f2f 100644 --- a/tests/tsAssertions.test.ts +++ b/tests/tsAssertions.test.ts @@ -1,6 +1,6 @@ import fs from 'fs/promises'; import { expect } from 'chai'; -import { CodeChecker } from '../src/ts'; +import { CodeChecker } from '../src'; type TypeNames = | 'StringType' diff --git a/tsconfig.json b/tsconfig.json index 1ad40d9..2c5f40a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,6 +9,6 @@ "strict": true, "noImplicitAny": true }, - "include": ["src/**/*.ts", "tests/**/*.ts"], + "include": ["src/**/*.ts"], "exclude": ["node_modules"] } diff --git a/tsup.config.ts b/tsup.config.ts new file mode 100644 index 0000000..886068a --- /dev/null +++ b/tsup.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from 'tsup'; + +export default defineConfig({ + entry: ['src/index.ts'], + format: ['cjs', 'esm'], // Build for commonJS and ESmodules + dts: true, // Generate declaration file (.d.ts) + splitting: false, + sourcemap: true, + clean: true +}); From 1945c26fac418d84f2a7bddee8aca79338cf45e8 Mon Sep 17 00:00:00 2001 From: Peter Barnum Date: Fri, 16 Aug 2024 13:51:19 -0600 Subject: [PATCH 05/14] update git url --- package.json | 4 ++-- src/index.ts | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 81cc7a7..59e89aa 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "ts-assertion", + "name": "@operationspark.org/ts-assertion", "version": "1.0.0", "main": "dist/index.js", "scripts": { @@ -19,7 +19,7 @@ "description": "Assertion library for testing typescript validity", "repository": { "type": "git", - "url": "git+OperationSpark/typescript-assertion.git" + "url": "https://github.com/OperationSpark/typescript-assertion.git" }, "dependencies": { "typescript": "^5.5.4" diff --git a/src/index.ts b/src/index.ts index d4ecbd0..de66464 100644 --- a/src/index.ts +++ b/src/index.ts @@ -24,7 +24,16 @@ type CompilationResult = { }; type CodeCheckerOptions = { + /** Pathname to input file */ pathname?: string; + /** + * Global types to include + * + * @example + * ```ts + * type GLOBAL_ACCESS = TypeError; + * ``` + */ globalTypes?: string; }; From f2800eecbf4e84549e28e1beb44c8d08ff9d7a46 Mon Sep 17 00:00:00 2001 From: Peter Barnum Date: Fri, 16 Aug 2024 13:51:46 -0600 Subject: [PATCH 06/14] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 59e89aa..7a2d1e9 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "description": "Assertion library for testing typescript validity", "repository": { "type": "git", - "url": "https://github.com/OperationSpark/typescript-assertion.git" + "url": "https://github.com/OperationSpark/ts-assertion.git" }, "dependencies": { "typescript": "^5.5.4" From 05cc06c8dc1b4cf5bc4754fa2ab9fd8aa594c7e6 Mon Sep 17 00:00:00 2001 From: Peter Barnum Date: Fri, 16 Aug 2024 17:04:37 -0600 Subject: [PATCH 07/14] update readme + cleanup --- .npmignore | 4 +- README.md | 102 ++++++++++++++++++----- package.json | 4 +- src/index.ts | 163 ++++++++++++++++++++++++++----------- {src => tests}/global.d.ts | 0 tests/tsAssertions.test.ts | 3 + 6 files changed, 207 insertions(+), 69 deletions(-) rename {src => tests}/global.d.ts (100%) diff --git a/.npmignore b/.npmignore index 4e99d34..c51aca4 100644 --- a/.npmignore +++ b/.npmignore @@ -1,7 +1,9 @@ tests +src .github .vscode node_modules tsconfig.json tsup.config.ts -mocharc.js +.mocharc.js +README.md diff --git a/README.md b/README.md index 2f1815d..cbd168b 100644 --- a/README.md +++ b/README.md @@ -12,51 +12,113 @@ npm install -D @operationspark.org/ts-assertion ### `CodeCheckerOptions` -| Name | Description | Optional | -| ------------- | ---------------------------------- | -------- | -| `pathname` | Pathname to input file | true | -| `globalTypes` | string of globally available types | true | +| Name | Description | | +| ------------- | ---------------------------------- | ---------- | +| `pathname` | Pathname to input file | `Optional` | +| `globalTypes` | string of globally available types | `Optional` | +| `globalPaths` | string of globally available paths | `Optional` | + +### `CodeChecker` Methods + +| Name | Description | Returns | +| -------- | -------------------------------------------------------------- | ------- | +| `test` | Test the code string and return a boolean if the code is valid | boolean | +| `assert` | Test the code string. Chain `isValid()` or `isNotValid()` | void | + +### `CodeChecker` global config + +Set global configurations for all instances of `CodeChecker` + +```ts +import { CodeChecker } from '@operationspark.org/ts-assertion'; + +CodeChecker.config.setGlobalPaths([ + 'path/to/file.ts', + 'path/to/other/file.d.ts' +]); // default is [] +CodeChecker.config.setVerbose(true); // default: false +``` + +### Basic Usage (No Options) ```ts -// Without file import { CodeChecker } from '@operationspark.org/ts-assertion'; const checker = new CodeChecker(); -expect(checker.test('const str: string = "test";')).to.be.true; -expect(checker.test('const str: string = 1;')).to.be.false; +// Test returns boolean. `true` if the code is valid +checker.test('const str: string = "test";'); // true +checker.test('const str: string = 1;'); // false +// Assert throws an error if the code is not valid checker.assert('const str: string = "test";').isValid(); + +// Assert throws an error if the code is valid checker.assert('const str: string = 1;').isNotValid(); ``` +### Advanced Usage (With Options) + +> `path/to/file.ts` +> +> ```ts +> export type StringType = string; +> export type NumberType = number; +> export type BooleanType = boolean; +> ``` + ```ts import { CodeChecker } from '@operationspark.org/ts-assertion'; const options: = { pathname: 'path/to/file.ts', globalTypes: 'type PrimitiveType = string | number | boolean;', + globalPaths: ['path/to/file.ts', 'path/to/other/file.d.ts'], }; -type TypeNames = 'StringType' | 'NumberType' | 'BooleanType' | 'EnumType'; +type TypeNames = 'StringType' | 'NumberType' | 'BooleanType'; const checker = new CodeChecker(options); -// file.ts -/* -export type StringType = string; -export type NumberType = number; -export type BooleanType = boolean; -export type EnumType = 'a' | 'b' | 'c'; -*/ -// Test returns true if the code is valid -expect(checker.test('const str: StringType = "test";')).to.be.true; -expect(checker.test('const str: string = 1;')).to.be.false; +// Test returns boolean. `true` if the code is valid +checker.test('const str: StringType = "test";') // true +checker.test('const str: string = 1;') // false // Assert throws an error if the code is not valid/invalid checker.assert('const str: StringType = "test";').isValid(); checker.assert('const str: string = 1;').isNotValid(); // Or more specifically, just test the type in the file -expect(checker.test('const str: StringType = "test";'), 'StringType').to.be.true; -checker.assert('const str: StringType = "test";', 'StringType').isValid(); +checker.test( + 'const str: StringType = "test";', + 'StringType' +) // true +checker.assert( + 'const str: StringType = "test";', 'StringType' +).isValid(); +``` + +## Development + +### Setup + +```sh +npm install +``` + +### Test + +```sh +npm test +``` + +#### Watch + +```sh +npm run test:dev +``` + +### Publish + +```sh +npm run publish:npm ``` diff --git a/package.json b/package.json index 7a2d1e9..64dfa97 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,13 @@ { "name": "@operationspark.org/ts-assertion", - "version": "1.0.0", + "version": "1.0.4", "main": "dist/index.js", "scripts": { "test": "mocha", "test:dev": "mocha --watch", "build": "tsup src/index.ts", "prepublish": "npm test && npm run build", - "publish": "npm publish --access public" + "publish:npm": "npm publish --access public" }, "keywords": [ "typescript", diff --git a/src/index.ts b/src/index.ts index de66464..ca50a58 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,5 @@ import assert from 'assert'; import fsSync from 'fs'; -import path from 'path'; import ts from 'typescript'; type LibVersions = @@ -18,25 +17,37 @@ type LibVersions = | 'es2015' | 'dom'; -type CompilationResult = { - code?: string; - diagnostics: ts.Diagnostic[]; -}; - type CodeCheckerOptions = { /** Pathname to input file */ pathname?: string; + /** + * Global types to include during instantiation + * ```ts + * options.globalPaths = ['path/to/global.d.ts', ...] + * ``` + */ + globalPaths?: string[]; /** * Global types to include * * @example * ```ts - * type GLOBAL_ACCESS = TypeError; + * `type GLOBAL_ACCESS = TypeError;` * ``` */ globalTypes?: string; }; +type Config = { + defaultGlobalPaths: string[]; + verbose: boolean; +}; + +const config: Config = { + defaultGlobalPaths: [], + verbose: false +}; + /** * Test typescript types against a specific block of code * @@ -71,14 +82,18 @@ type CodeCheckerOptions = { export class CodeChecker { private _pathname: string; private _globalTypes = ''; + private _globalPaths = new Set(config.defaultGlobalPaths); private _types = new Map(); private _version: LibVersions = 'es2022'; private code = ''; constructor(options: CodeCheckerOptions = {}) { - const { pathname, globalTypes } = options; - this._pathname = pathname ?? ''; - this._globalTypes = globalTypes ?? ''; + const { pathname = '', globalTypes = '', globalPaths = [] } = options; + + this._pathname = pathname; + this._globalTypes = globalTypes; + this._globalPaths = new Set([...globalPaths, ...config.defaultGlobalPaths]); + this.init(); } @@ -130,55 +145,30 @@ export class CodeChecker { filename: string, code: string, lib: LibVersions - ): CompilationResult { + ): ts.Diagnostic[] { const options = ts.getDefaultCompilerOptions(); - const realHost = ts.createCompilerHost(options, true); const sourceFile = ts.createSourceFile( filename, code, ts.ScriptTarget.Latest ); - let outputCode: string | undefined = undefined; - - const host: ts.CompilerHost = { - fileExists: filePath => - filePath === filename || realHost.fileExists(filePath), - directoryExists: realHost.directoryExists?.bind(realHost), - getCurrentDirectory: realHost.getCurrentDirectory.bind(realHost), - getDirectories: realHost.getDirectories?.bind(realHost), - getCanonicalFileName: realHost.getCanonicalFileName.bind(realHost), - getNewLine: realHost.getNewLine.bind(realHost), - getDefaultLibFileName: realHost.getDefaultLibFileName.bind(realHost), - getSourceFile: (sourceFilename, ...args) => { - if (sourceFilename === filename) { - return sourceFile; - } - return realHost.getSourceFile(sourceFilename, ...args); - }, - readFile: filePath => { - if (filePath === filename) { - return code; - } - realHost.readFile(filePath); - }, - useCaseSensitiveFileNames: () => realHost.useCaseSensitiveFileNames(), - writeFile: (_fileName, data) => (outputCode = data) - }; + + const host = createVirtualHost(sourceFile); const rootName = require.resolve(`typescript/lib/lib.${lib}.d.ts`); - const globalPath = path.resolve(__dirname, 'global.d.ts'); + const program = ts.createProgram( - [rootName, filename, globalPath], + [rootName, filename, ...this.globalPaths], options, host ); + const emitResult = program.emit(); const diagnostics = ts.getPreEmitDiagnostics(program); - return { - code: outputCode, - diagnostics: emitResult.diagnostics.concat(diagnostics) - }; + config.verbose && logCodeBlock(sourceFile.getFullText()); + + return emitResult.diagnostics.concat(diagnostics); } private _test(testCode: string, typeName?: TypeNames) { @@ -197,8 +187,8 @@ export class CodeChecker { const messages = this.compileTypeScriptCode( 'temp.ts', `${globalTypes}${code}\n${testCode}`, - 'es2022' - ).diagnostics.map(diagnostic => diagnostic.messageText); + this.version + ).map(diagnostic => diagnostic.messageText); return { valid: !messages.length, @@ -227,6 +217,14 @@ export class CodeChecker { this._globalTypes = types; } + public get globalPaths() { + return [...this._globalPaths]; + } + + public set globalPaths(paths: string[]) { + this._globalPaths = new Set([...paths, ...config.defaultGlobalPaths]); + } + public get version() { return this._version; } @@ -267,4 +265,77 @@ export class CodeChecker { } }; } + public static get config() { + return { + setGlobalPaths: (paths: string[]) => { + config.defaultGlobalPaths = paths; + }, + setVerbose: (verbose: boolean) => { + config.verbose = verbose; + }, + get current() { + return { ...config }; + } + }; + } +} + +/** Create typescript compiler host to interpret code 'in-memory' instead of writing file */ +function createVirtualHost(sourceFile: ts.SourceFile) { + const filename = 'temp.ts'; + const options = ts.getDefaultCompilerOptions(); + const realHost = ts.createCompilerHost(options, true); + + const host: ts.CompilerHost = { + fileExists: filePath => + filePath === filename || realHost.fileExists(filePath), + directoryExists: realHost.directoryExists?.bind(realHost), + getCurrentDirectory: realHost.getCurrentDirectory.bind(realHost), + getDirectories: realHost.getDirectories?.bind(realHost), + getCanonicalFileName: realHost.getCanonicalFileName.bind(realHost), + getNewLine: realHost.getNewLine.bind(realHost), + getDefaultLibFileName: realHost.getDefaultLibFileName.bind(realHost), + getSourceFile: (sourceFilename, ...args) => { + if (sourceFilename === filename) { + return sourceFile; + } + return realHost.getSourceFile(sourceFilename, ...args); + }, + readFile: filePath => { + if (filePath === filename) { + return sourceFile.text; + } + realHost.readFile(filePath); + }, + useCaseSensitiveFileNames: () => realHost.useCaseSensitiveFileNames(), + writeFile: (_fileName, _data) => { + /** Optionally do something with compiled code here */ + } + }; + + return host; +} + +function logCodeBlock(text: string) { + if (!text) { + return; + } + let longestLine = 0; + + const formatted = text + .split('\n') + .map((line, index) => { + if (line.length > longestLine) { + longestLine = line.length; + } + + return `${index + 1} │ ${line}`; + }) + .join('\n'); + + const line = '─'.repeat(longestLine + 3); + const topLine = `┬${line}`.padStart(longestLine + 6, '─'); + const bottomLine = `┴${line}`.padStart(longestLine + 6, '─'); + + console.info(`${topLine}\n${formatted}\n${bottomLine}`); } diff --git a/src/global.d.ts b/tests/global.d.ts similarity index 100% rename from src/global.d.ts rename to tests/global.d.ts diff --git a/tests/tsAssertions.test.ts b/tests/tsAssertions.test.ts index 9ee1f2f..e3206f2 100644 --- a/tests/tsAssertions.test.ts +++ b/tests/tsAssertions.test.ts @@ -9,6 +9,9 @@ type TypeNames = | 'EnumType' | 'ObjectType'; +CodeChecker.config.setGlobalPaths(['tests/global.d.ts']); +// CodeChecker.config.setVerbose(true); + describe('ts-assertions', () => { it('should instantiate a CodeChecker instance without a pathname', () => { const checker = new CodeChecker(); From 2cf30c322dbdcf4318fe880f971c1fd706f8f494 Mon Sep 17 00:00:00 2001 From: Peter Barnum Date: Fri, 16 Aug 2024 17:16:49 -0600 Subject: [PATCH 08/14] minor update --- package.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 64dfa97..4993314 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,12 @@ { "name": "@operationspark.org/ts-assertion", - "version": "1.0.4", + "version": "1.0.5", "main": "dist/index.js", "scripts": { "test": "mocha", "test:dev": "mocha --watch", "build": "tsup src/index.ts", - "prepublish": "npm test && npm run build", - "publish:npm": "npm publish --access public" + "publish:npm": "npm test && npm run build && npm publish --access public" }, "keywords": [ "typescript", From 2e4a69cb4e102b85473336d674161232b427d8b1 Mon Sep 17 00:00:00 2001 From: Peter Barnum Date: Sun, 18 Aug 2024 17:10:53 -0600 Subject: [PATCH 09/14] improve error logs --- src/index.ts | 4 +++- tests/fixtures/fixtures2.ts | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index ca50a58..b3cd5d8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -188,7 +188,9 @@ export class CodeChecker { 'temp.ts', `${globalTypes}${code}\n${testCode}`, this.version - ).map(diagnostic => diagnostic.messageText); + ).map(diagnostic => + ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n\n', 2) + ); return { valid: !messages.length, diff --git a/tests/fixtures/fixtures2.ts b/tests/fixtures/fixtures2.ts index ede3e89..dc6bf71 100644 --- a/tests/fixtures/fixtures2.ts +++ b/tests/fixtures/fixtures2.ts @@ -1,2 +1 @@ -// export type AddFunction = FILL_ME_IN; export type AddFunction = (a: number, b: number) => number; From c2c54f042fa5c978d63131c8a74c07b2bc4fd7d4 Mon Sep 17 00:00:00 2001 From: Peter Barnum Date: Sun, 18 Aug 2024 17:14:10 -0600 Subject: [PATCH 10/14] update version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4993314..21eb9ca 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@operationspark.org/ts-assertion", - "version": "1.0.5", + "version": "1.0.6", "main": "dist/index.js", "scripts": { "test": "mocha", From 383c5e9932812230b16737850301b7a650efd456 Mon Sep 17 00:00:00 2001 From: Peter Barnum Date: Sun, 18 Aug 2024 17:25:17 -0600 Subject: [PATCH 11/14] oops. left an extra `\n` --- package.json | 2 +- src/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 21eb9ca..1a8c270 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@operationspark.org/ts-assertion", - "version": "1.0.6", + "version": "1.0.7", "main": "dist/index.js", "scripts": { "test": "mocha", diff --git a/src/index.ts b/src/index.ts index b3cd5d8..d2c7ec8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -189,7 +189,7 @@ export class CodeChecker { `${globalTypes}${code}\n${testCode}`, this.version ).map(diagnostic => - ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n\n', 2) + ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n', 2) ); return { From 37b414bd96ce4817a67e8609f6cb2e065bc569d7 Mon Sep 17 00:00:00 2001 From: Peter Barnum Date: Sun, 18 Aug 2024 17:30:54 -0600 Subject: [PATCH 12/14] increase tab size --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index d2c7ec8..3a8c63b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -189,7 +189,7 @@ export class CodeChecker { `${globalTypes}${code}\n${testCode}`, this.version ).map(diagnostic => - ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n', 2) + ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n', 4) ); return { From 1f5cc3b549e82508a20d69bc41b7f0ea0e404a55 Mon Sep 17 00:00:00 2001 From: Peter Barnum Date: Mon, 19 Aug 2024 14:45:30 -0600 Subject: [PATCH 13/14] separate files + add helper to convert js to string (not stringify) --- package-lock.json | 8 +- src/codeChecker.ts | 386 ++++++++++++++++++++++++++++++++++++ src/helpers.ts | 127 ++++++++++++ src/index.ts | 345 +------------------------------- tests/fixtures/fixtures3.ts | 14 ++ tests/tsAssertions.test.ts | 38 ++++ 6 files changed, 573 insertions(+), 345 deletions(-) create mode 100644 src/codeChecker.ts create mode 100644 src/helpers.ts create mode 100644 tests/fixtures/fixtures3.ts diff --git a/package-lock.json b/package-lock.json index 69b6aa8..5f9d620 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { - "name": "course.typescript", - "version": "1.0.0", + "name": "@operationspark.org/ts-assertion", + "version": "1.0.7", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "course.typescript", - "version": "1.0.0", + "name": "@operationspark.org/ts-assertion", + "version": "1.0.7", "license": "MIT", "dependencies": { "typescript": "^5.5.4" diff --git a/src/codeChecker.ts b/src/codeChecker.ts new file mode 100644 index 0000000..56ab0d3 --- /dev/null +++ b/src/codeChecker.ts @@ -0,0 +1,386 @@ +import assert from 'assert'; +import fsSync from 'fs'; +import ts from 'typescript'; +import { CodeType, toJsString, toTypedString } from './helpers'; + +type LibVersions = + | 'esnext' + | 'es6' + | 'es5' + | 'es2023' + | 'es2022' + | 'es2021' + | 'es2020' + | 'es2019' + | 'es2018' + | 'es2017' + | 'es2016' + | 'es2015' + | 'dom'; + +type TestCode = + | string + | { + /** Actual javascript code */ + code: CodeType; + /** Name of the variable */ + name?: string; + /** + * Type name to test against (assigns to variable) + * @example + * ```ts + * type TypedObject = { a: string; b: number; c: (a: number, b: number) => number }; + * + * test({ + * code: { a: 'test', b: 1, c: (a, b) => a + b }, + * name: 'typedObject', + * typeName: 'TypedObject' + * }); + * // returns string => `const typedObject = { a: 'test', b: 1, c: (a, b) => a + b }`; + * ``` + */ + typeName?: string; + }; + +type CodeCheckerOptions = { + /** Pathname to input file */ + pathname?: string; + /** + * Global types to include during instantiation + * ```ts + * options.globalPaths = ['path/to/global.d.ts', ...] + * ``` + */ + globalPaths?: string[]; + /** + * Global types to include + * + * @example + * ```ts + * `type GLOBAL_ACCESS = TypeError;` + * ``` + */ + globalTypes?: string; +}; + +type Config = { + defaultGlobalPaths: string[]; + verbose: boolean; +}; + +const config: Config = { + defaultGlobalPaths: [], + verbose: false +}; + +/** + * Test typescript types against a specific block of code + * + * @example + * ```ts + * // Create a new CodeChecker instance + * const checker = new CodeChecker({ + * filepath: 'path/to/input/file' + * }); + * + * // Assert that the code is valid; throws an error if the code is *not* valid + * const isValid = checker.assert( + * `const str: string = 'test';` + * ).isValid(); + * + * // Assert that the code is not valid; throws an error if the code *is* valid + * const isNotValid = checker.assert( + * `const str: string = 1;` + * ).isNotValid(); + * + * // Returns true if the code *is* valid + * const isValid = checker.test( + * `const str: string = 'test';` + * ); + * + * // Returns false if the code is *not* valid + * const isNotValid = checker.test( + * `const str: string = 1;` + * ); + * ``` + */ +export class CodeChecker { + private _pathname: string; + private _globalTypes = ''; + private _globalPaths = new Set(config.defaultGlobalPaths); + private _types = new Map(); + private _version: LibVersions = 'es2022'; + private code = ''; + + constructor(options: CodeCheckerOptions = {}) { + const { pathname = '', globalTypes = '', globalPaths = [] } = options; + + this._pathname = pathname; + this._globalTypes = globalTypes; + this._globalPaths = new Set([...globalPaths, ...config.defaultGlobalPaths]); + + this.init(); + } + + private init() { + this.fetchCode(); + this.extractTypesAsStrings(); + } + + private extractTypesAsStrings() { + this._types.clear(); + const node = ts.createSourceFile( + 'extractTypes.ts', // fileName + this.code, // sourceText + ts.ScriptTarget.Latest + ); + + const typeNodes: ts.TypeAliasDeclaration[] = []; + + node.forEachChild(child => { + if (ts.isTypeAliasDeclaration(child)) { + typeNodes.push(child); + } + }); + const codeBuffer = Buffer.from(this.code); + + typeNodes.forEach((node: ts.TypeAliasDeclaration) => { + const { pos, end } = node; + + const type = codeBuffer.subarray(pos, end).toString('utf-8'); + this.types.set(node.name.text, type); + }); + } + + private fetchCode() { + if (!this.pathname) { + this.code = ''; + return ''; + } + try { + const code = fsSync.readFileSync(this.pathname, 'utf-8'); + this.code = code; + return code; + } catch (err) { + throw new Error(`Cannot read file: '${this.pathname}'`); + } + } + + private compileTypeScriptCode( + filename: string, + code: string, + lib: LibVersions + ): ts.Diagnostic[] { + const options = ts.getDefaultCompilerOptions(); + + const sourceFile = ts.createSourceFile( + filename, + code, + ts.ScriptTarget.Latest + ); + + const host = createVirtualHost(sourceFile); + + const rootName = require.resolve(`typescript/lib/lib.${lib}.d.ts`); + + const program = ts.createProgram( + [rootName, filename, ...this.globalPaths], + options, + host + ); + + const emitResult = program.emit(); + const diagnostics = ts.getPreEmitDiagnostics(program); + config.verbose && logCodeBlock(sourceFile.getFullText()); + + return emitResult.diagnostics.concat(diagnostics); + } + + private _test(testCode: TestCode, typeName?: TypeNames) { + if (typeof testCode !== 'string') { + const { code, name, typeName } = testCode; + + testCode = + name && typeName + ? toTypedString(code, name, typeName) + : toJsString(code); + } + + const selectedType = typeName && this.types.get(typeName); + if (typeName && !selectedType) { + throw new Error( + `Type '${typeName}' not found in file '${this.pathname}'` + ); + } + + const code = selectedType ?? this.code; + + /** Initial global types passed in */ + const globalTypes = this.globalTypes ? `${this.globalTypes}\n` : ''; + + const messages = this.compileTypeScriptCode( + 'temp.ts', + `${globalTypes}${code}\n${testCode}`, + this.version + ).map(diagnostic => + ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n', 4) + ); + + return { + valid: !messages.length, + messages: messages as string[] + }; + } + + public set pathname(pathname: string) { + this._pathname = pathname; + this.init(); + } + + public get pathname() { + return this._pathname; + } + + public get types() { + return this._types; + } + + public get globalTypes() { + return this._globalTypes; + } + + public set globalTypes(types: string) { + this._globalTypes = types; + } + + public get globalPaths() { + return [...this._globalPaths]; + } + + public set globalPaths(paths: string[]) { + this._globalPaths = new Set([...paths, ...config.defaultGlobalPaths]); + } + + public get version() { + return this._version; + } + + public set version(version: LibVersions) { + this._version = version; + } + + public restore(pathname?: string) { + this.pathname = pathname ?? this.pathname; + + this.init(); + } + + public test(testCode: TestCode, typeName?: TypeNames) { + const { valid } = this._test(testCode, typeName); + + return valid; + } + + public assert(testCode: TestCode, typeName?: TypeNames) { + const { valid, messages } = this._test(testCode, typeName); + + return { + isValid: (msg?: string) => { + assert( + valid, + new TypeError([...messages, msg].filter(Boolean).join('\n')) + ); + }, + isNotValid: (msg?: string) => { + assert( + !valid, + `Expected code '${testCode}' to be invalid${ + msg ? `\n - ${msg}` : '' + }` + ); + } + }; + } + public static get config() { + return { + setGlobalPaths: (paths: string[]) => { + config.defaultGlobalPaths = paths; + }, + setVerbose: (verbose: boolean) => { + config.verbose = verbose; + }, + get current() { + return { ...config }; + } + }; + } + public static get version() { + return ts.version; + } + + public static toJsString = toJsString; + public static toTypedString = toTypedString; + + public toJsString = toJsString; + public toTypedString = toTypedString; +} + +/** Create typescript compiler host to interpret code 'in-memory' instead of writing file */ +function createVirtualHost(sourceFile: ts.SourceFile) { + const filename = 'temp.ts'; + const options = ts.getDefaultCompilerOptions(); + const realHost = ts.createCompilerHost(options, true); + + const host: ts.CompilerHost = { + fileExists: filePath => + filePath === filename || realHost.fileExists(filePath), + directoryExists: realHost.directoryExists?.bind(realHost), + getCurrentDirectory: realHost.getCurrentDirectory.bind(realHost), + getDirectories: realHost.getDirectories?.bind(realHost), + getCanonicalFileName: realHost.getCanonicalFileName.bind(realHost), + getNewLine: realHost.getNewLine.bind(realHost), + getDefaultLibFileName: realHost.getDefaultLibFileName.bind(realHost), + getSourceFile: (sourceFilename, ...args) => { + if (sourceFilename === filename) { + return sourceFile; + } + return realHost.getSourceFile(sourceFilename, ...args); + }, + readFile: filePath => { + if (filePath === filename) { + return sourceFile.text; + } + realHost.readFile(filePath); + }, + useCaseSensitiveFileNames: () => realHost.useCaseSensitiveFileNames(), + writeFile: (_fileName, _data) => { + /** Optionally do something with compiled code here */ + } + }; + + return host; +} + +function logCodeBlock(text: string) { + if (!text) { + return; + } + let longestLine = 0; + + const formatted = text + .split('\n') + .map((line, index) => { + if (line.length > longestLine) { + longestLine = line.length; + } + + return `${index + 1} │ ${line}`; + }) + .join('\n'); + + const line = '─'.repeat(longestLine + 3); + const topLine = `┬${line}`.padStart(longestLine + 6, '─'); + const bottomLine = `┴${line}`.padStart(longestLine + 6, '─'); + + console.info(`${topLine}\n${formatted}\n${bottomLine}`); +} diff --git a/src/helpers.ts b/src/helpers.ts new file mode 100644 index 0000000..4d38136 --- /dev/null +++ b/src/helpers.ts @@ -0,0 +1,127 @@ +export type CodeType = + | string + | number + | boolean + | null + | Date + | RegExp + | Set + | Map + | Error + | any[] + | Record; + +const getIndentStr = (indent: number) => ' '.repeat(indent); + +const arrToString = (arr: CodeType[], indent: number) => { + const indentStr = getIndentStr(indent + 2); + const array = arr.map( + value => `${indentStr}${codeToString(value, indent + 4)}` + ); + if (arr.length === 0) { + return '[]'; + } + + if (arr.length <= 3 && typeof arr[0] !== 'object') { + return `[ ${array.map(v => v.trim()).join(', ')} ]`; + } + + return `[\n${array.join(',\n')}\n${indentStr.slice(2)}]`; +}; + +const objToString = (obj: Record, indent: number) => { + const indentStr = getIndentStr(indent + 2); + const entries = Object.entries(obj); + const object = entries.map( + ([key, value]): string => + `${indentStr}${key}: ${codeToString(value, indent + 2)}` + ); + + if (entries.length === 0) { + return '{}'; + } + + if (entries.length <= 3) { + return `{ ${object.map(v => v.trim()).join(', ')} }`; + } + + return `{\n${object.join(',\n')}\n${indentStr.slice(2)}}`; +}; + +const mapToString = (map: Map, indent: number) => { + const indentStr = getIndentStr(indent + 2); + const endIndentStr = indentStr.slice(2); + const entries = [...map.entries()] + .map(([key, value]) => { + const k = codeToString(key, indent); + const v = codeToString(value, indent); + return `${indentStr}[${k}, ${v}]`; + }) + .join(',\n'); + return `new Map([\n${entries}\n${endIndentStr}])`; +}; + +const setToString = (set: Set, indent: number) => { + return `new Set(${arrToString([...set], indent)})`; +}; + +const errorToString = (err: Error) => { + return `new ${err.name}('${err.message}')`; +}; + +const codeToString = (code: CodeType, indent?: number): string => { + if (typeof code === 'number' || typeof code === 'boolean' || code === null) { + return `${code}`; + } + + if (typeof code === 'string') { + return `'${code}'`; + } + + if (typeof code === 'function') { + return code.toString(); + } + + if (code instanceof Date) { + return `new Date('${code.toISOString()}')`; + } + + if (code instanceof RegExp) { + return code.toString(); + } + + if (code instanceof Set) { + return setToString(code, indent ?? 0); + } + + if (code instanceof Map) { + return mapToString(code, indent ?? 0); + } + + if (code instanceof Error) { + return errorToString(code); + } + + if (Array.isArray(code)) { + return arrToString(code, indent ?? 0); + } + + if (typeof code === 'object') { + return objToString(code, indent ?? 0); + } + + return code; +}; + +export const toTypedString = ( + code: any, + name: string, + typeName: string +): string => { + const object = codeToString(code); + return `const ${name}: ${typeName} = ${object};`; +}; + +export const toJsString = (code: CodeType): string => { + return codeToString(code); +}; diff --git a/src/index.ts b/src/index.ts index 3a8c63b..4c6e216 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,343 +1,6 @@ -import assert from 'assert'; -import fsSync from 'fs'; -import ts from 'typescript'; +import { CodeChecker } from './codeChecker'; -type LibVersions = - | 'esnext' - | 'es6' - | 'es5' - | 'es2023' - | 'es2022' - | 'es2021' - | 'es2020' - | 'es2019' - | 'es2018' - | 'es2017' - | 'es2016' - | 'es2015' - | 'dom'; +export * from './helpers'; +export { CodeChecker } from './codeChecker'; -type CodeCheckerOptions = { - /** Pathname to input file */ - pathname?: string; - /** - * Global types to include during instantiation - * ```ts - * options.globalPaths = ['path/to/global.d.ts', ...] - * ``` - */ - globalPaths?: string[]; - /** - * Global types to include - * - * @example - * ```ts - * `type GLOBAL_ACCESS = TypeError;` - * ``` - */ - globalTypes?: string; -}; - -type Config = { - defaultGlobalPaths: string[]; - verbose: boolean; -}; - -const config: Config = { - defaultGlobalPaths: [], - verbose: false -}; - -/** - * Test typescript types against a specific block of code - * - * @example - * ```ts - * // Create a new CodeChecker instance - * const checker = new CodeChecker({ - * filepath: 'path/to/input/file' - * }); - * - * // Assert that the code is valid; throws an error if the code is *not* valid - * const isValid = checker.assert( - * `const str: string = 'test';` - * ).isValid(); - * - * // Assert that the code is not valid; throws an error if the code *is* valid - * const isNotValid = checker.assert( - * `const str: string = 1;` - * ).isNotValid(); - * - * // Returns true if the code *is* valid - * const isValid = checker.test( - * `const str: string = 'test';` - * ); - * - * // Returns false if the code is *not* valid - * const isNotValid = checker.test( - * `const str: string = 1;` - * ); - * ``` - */ -export class CodeChecker { - private _pathname: string; - private _globalTypes = ''; - private _globalPaths = new Set(config.defaultGlobalPaths); - private _types = new Map(); - private _version: LibVersions = 'es2022'; - private code = ''; - - constructor(options: CodeCheckerOptions = {}) { - const { pathname = '', globalTypes = '', globalPaths = [] } = options; - - this._pathname = pathname; - this._globalTypes = globalTypes; - this._globalPaths = new Set([...globalPaths, ...config.defaultGlobalPaths]); - - this.init(); - } - - private init() { - this.fetchCode(); - this.extractTypesAsStrings(); - } - - private extractTypesAsStrings() { - this._types.clear(); - const node = ts.createSourceFile( - 'extractTypes.ts', // fileName - this.code, // sourceText - ts.ScriptTarget.Latest - ); - - const typeNodes: ts.TypeAliasDeclaration[] = []; - - node.forEachChild(child => { - if (ts.isTypeAliasDeclaration(child)) { - typeNodes.push(child); - } - }); - const codeBuffer = Buffer.from(this.code); - - typeNodes.forEach((node: ts.TypeAliasDeclaration) => { - const { pos, end } = node; - - const type = codeBuffer.subarray(pos, end).toString('utf-8'); - this.types.set(node.name.text, type); - }); - } - - private fetchCode() { - if (!this.pathname) { - this.code = ''; - return ''; - } - try { - const code = fsSync.readFileSync(this.pathname, 'utf-8'); - this.code = code; - return code; - } catch (err) { - throw new Error(`Cannot read file: '${this.pathname}'`); - } - } - - private compileTypeScriptCode( - filename: string, - code: string, - lib: LibVersions - ): ts.Diagnostic[] { - const options = ts.getDefaultCompilerOptions(); - - const sourceFile = ts.createSourceFile( - filename, - code, - ts.ScriptTarget.Latest - ); - - const host = createVirtualHost(sourceFile); - - const rootName = require.resolve(`typescript/lib/lib.${lib}.d.ts`); - - const program = ts.createProgram( - [rootName, filename, ...this.globalPaths], - options, - host - ); - - const emitResult = program.emit(); - const diagnostics = ts.getPreEmitDiagnostics(program); - config.verbose && logCodeBlock(sourceFile.getFullText()); - - return emitResult.diagnostics.concat(diagnostics); - } - - private _test(testCode: string, typeName?: TypeNames) { - const selectedType = typeName && this.types.get(typeName); - if (typeName && !selectedType) { - throw new Error( - `Type '${typeName}' not found in file '${this.pathname}'` - ); - } - - const code = selectedType ?? this.code; - - /** Initial global types passed in */ - const globalTypes = this.globalTypes ? `${this.globalTypes}\n` : ''; - - const messages = this.compileTypeScriptCode( - 'temp.ts', - `${globalTypes}${code}\n${testCode}`, - this.version - ).map(diagnostic => - ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n', 4) - ); - - return { - valid: !messages.length, - messages: messages as string[] - }; - } - - public set pathname(pathname: string) { - this._pathname = pathname; - this.init(); - } - - public get pathname() { - return this._pathname; - } - - public get types() { - return this._types; - } - - public get globalTypes() { - return this._globalTypes; - } - - public set globalTypes(types: string) { - this._globalTypes = types; - } - - public get globalPaths() { - return [...this._globalPaths]; - } - - public set globalPaths(paths: string[]) { - this._globalPaths = new Set([...paths, ...config.defaultGlobalPaths]); - } - - public get version() { - return this._version; - } - - public set version(version: LibVersions) { - this._version = version; - } - - public restore(pathname?: string) { - this.pathname = pathname ?? this.pathname; - - this.init(); - } - - public test(testCode: string, typeName?: TypeNames) { - const { valid } = this._test(testCode, typeName); - - return valid; - } - - public assert(testCode: string, typeName?: TypeNames) { - const { valid, messages } = this._test(testCode, typeName); - - return { - isValid: (msg?: string) => { - assert( - valid, - new TypeError([...messages, msg].filter(Boolean).join('\n')) - ); - }, - isNotValid: (msg?: string) => { - assert( - !valid, - `Expected code '${testCode}' to be invalid${ - msg ? `\n - ${msg}` : '' - }` - ); - } - }; - } - public static get config() { - return { - setGlobalPaths: (paths: string[]) => { - config.defaultGlobalPaths = paths; - }, - setVerbose: (verbose: boolean) => { - config.verbose = verbose; - }, - get current() { - return { ...config }; - } - }; - } -} - -/** Create typescript compiler host to interpret code 'in-memory' instead of writing file */ -function createVirtualHost(sourceFile: ts.SourceFile) { - const filename = 'temp.ts'; - const options = ts.getDefaultCompilerOptions(); - const realHost = ts.createCompilerHost(options, true); - - const host: ts.CompilerHost = { - fileExists: filePath => - filePath === filename || realHost.fileExists(filePath), - directoryExists: realHost.directoryExists?.bind(realHost), - getCurrentDirectory: realHost.getCurrentDirectory.bind(realHost), - getDirectories: realHost.getDirectories?.bind(realHost), - getCanonicalFileName: realHost.getCanonicalFileName.bind(realHost), - getNewLine: realHost.getNewLine.bind(realHost), - getDefaultLibFileName: realHost.getDefaultLibFileName.bind(realHost), - getSourceFile: (sourceFilename, ...args) => { - if (sourceFilename === filename) { - return sourceFile; - } - return realHost.getSourceFile(sourceFilename, ...args); - }, - readFile: filePath => { - if (filePath === filename) { - return sourceFile.text; - } - realHost.readFile(filePath); - }, - useCaseSensitiveFileNames: () => realHost.useCaseSensitiveFileNames(), - writeFile: (_fileName, _data) => { - /** Optionally do something with compiled code here */ - } - }; - - return host; -} - -function logCodeBlock(text: string) { - if (!text) { - return; - } - let longestLine = 0; - - const formatted = text - .split('\n') - .map((line, index) => { - if (line.length > longestLine) { - longestLine = line.length; - } - - return `${index + 1} │ ${line}`; - }) - .join('\n'); - - const line = '─'.repeat(longestLine + 3); - const topLine = `┬${line}`.padStart(longestLine + 6, '─'); - const bottomLine = `┴${line}`.padStart(longestLine + 6, '─'); - - console.info(`${topLine}\n${formatted}\n${bottomLine}`); -} +export default CodeChecker; diff --git a/tests/fixtures/fixtures3.ts b/tests/fixtures/fixtures3.ts new file mode 100644 index 0000000..c6859a9 --- /dev/null +++ b/tests/fixtures/fixtures3.ts @@ -0,0 +1,14 @@ +export type ComplexObject = { + a: string; + b: number; + c: boolean; + d: string[]; + e: number[]; + f: boolean[]; + g: { a: string; b: number }; + h: { a: string; b: number }[]; + i: (a: number, b: number) => number; + j: Map; + k: Set; + l: Date; +}; diff --git a/tests/tsAssertions.test.ts b/tests/tsAssertions.test.ts index e3206f2..587cb7d 100644 --- a/tests/tsAssertions.test.ts +++ b/tests/tsAssertions.test.ts @@ -220,4 +220,42 @@ describe('ts-assertions', () => { }); }); }); + + describe('toJsString & toTypedString', () => { + const checker = new CodeChecker({ + pathname: 'tests/fixtures/fixtures3.ts' + }); + + it('should create a string version of an object', () => { + const obj = { + a: 'test', + b: 1, + c: true, + d: ['test'], + e: [1], + f: [true], + g: { a: 'test', b: 1 }, + h: [{ a: 'test', b: 1 }], + i: (a: number, b: number) => a + b, + j: new Map([ + ['a', 1], + ['b', 2] + ]), + k: new Set([1, 2, 3]), + l: new Date() + }; + + checker + .assert({ code: obj, name: 'obj', typeName: 'ComplexObject' }) + .isValid(); + + checker + .assert({ + code: { ...obj, m: 'invalid' }, + name: 'obj', + typeName: 'ComplexObject' + }) + .isNotValid(); + }); + }); }); From 749a5b931a5497f9edacae2b20cfc417654a32bd Mon Sep 17 00:00:00 2001 From: Peter Barnum Date: Mon, 19 Aug 2024 14:48:18 -0600 Subject: [PATCH 14/14] update to v1.0.8 --- 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 5f9d620..9ce987c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@operationspark.org/ts-assertion", - "version": "1.0.7", + "version": "1.0.8", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@operationspark.org/ts-assertion", - "version": "1.0.7", + "version": "1.0.8", "license": "MIT", "dependencies": { "typescript": "^5.5.4" diff --git a/package.json b/package.json index 1a8c270..bfd4245 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@operationspark.org/ts-assertion", - "version": "1.0.7", + "version": "1.0.8", "main": "dist/index.js", "scripts": { "test": "mocha",