From 55c715cc022ac9c6d1063a355a2e23324aeb27c5 Mon Sep 17 00:00:00 2001 From: Radoslav Karaivanov Date: Wed, 2 Sep 2026 09:56:09 +0300 Subject: [PATCH] refactor(scripts): single-process wrapper generation The four build-* scripts each spawned npm + tsx and built a TypeScript program over all of src/**, re-parsing the wrappers the previous step had just written. They are configs now; generate.ts runs them together and resolves every type entry in one program. ~10s -> ~2.5s, byte-identical output. - remove the undeclared `glob` import and unused `rimraf` - type-check scripts/ for the first time (typecheck:scripts) - add check:manifests: published ranges must admit installed versions - read custom-elements.json rather than import it; tsc was inferring a literal type for 4.5MB of JSON nothing used (typecheck 3.9s -> 1.5s) - warn on config tags matching no declaration; drop two stale ignores - stop mutating the shared manifest in createEvents/parseElementsJSON - resolve template config into one predicate, dropping the igc-chat branch - CI: static gates before the build in both pipelines; cache Playwright - rename build-* npm scripts to generate:* - update igniteui-webcomponents to 7.3.1, grid-lite to 0.10.0 --- .azure-pipelines/setup-build-test-steps.yml | 31 +- .github/actions/setup-build-test/action.yml | 25 +- package-lock.json | 1093 +++++++++---------- package.json | 46 +- scripts/build-dm.ts | 32 +- scripts/build-grid-lite.ts | 37 +- scripts/build-grids.ts | 39 +- scripts/build-wc.ts | 94 +- scripts/check-manifests.ts | 134 +++ scripts/components.package.json | 4 +- scripts/config.ts | 103 ++ scripts/generate.ts | 84 ++ scripts/npm-packlist.d.ts | 19 + scripts/paths.ts | 23 + scripts/tsconfig.json | 22 + scripts/types.ts | 9 +- scripts/typescript-utils.ts | 51 +- scripts/utils.ts | 290 ++--- scripts/validate-dist.ts | 36 +- tests/web-components/Chat.spec.tsx | 27 +- 20 files changed, 1285 insertions(+), 914 deletions(-) create mode 100644 scripts/check-manifests.ts create mode 100644 scripts/config.ts create mode 100644 scripts/generate.ts create mode 100644 scripts/npm-packlist.d.ts create mode 100644 scripts/paths.ts create mode 100644 scripts/tsconfig.json diff --git a/.azure-pipelines/setup-build-test-steps.yml b/.azure-pipelines/setup-build-test-steps.yml index 1b8cb12..0b94b3e 100644 --- a/.azure-pipelines/setup-build-test-steps.yml +++ b/.azure-pipelines/setup-build-test-steps.yml @@ -23,6 +23,29 @@ steps: command: 'ci' verbose: ${{ parameters.verbose }} +# Static gates first: none of them need a build, so a lint, type or manifest error +# fails in seconds instead of after the full build + validate cycle. +- task: Npm@1 + displayName: 'Lint' + inputs: + command: 'custom' + verbose: ${{ parameters.verbose }} + customCommand: 'run lint' + +- task: Npm@1 + displayName: 'Type-check build scripts' + inputs: + command: 'custom' + verbose: ${{ parameters.verbose }} + customCommand: 'run typecheck:scripts' + +- task: Npm@1 + displayName: 'Check publish manifests' + inputs: + command: 'custom' + verbose: ${{ parameters.verbose }} + customCommand: 'run check:manifests' + - task: Npm@1 displayName: 'Build' inputs: @@ -41,14 +64,6 @@ steps: verbose: ${{ parameters.verbose }} customCommand: 'run validate:dist' - -- task: Npm@1 - displayName: 'Lint' - inputs: - command: 'custom' - verbose: ${{ parameters.verbose }} - customCommand: 'run lint' - - script: npx playwright install chromium-headless-shell displayName: 'Install Playwright browsers' diff --git a/.github/actions/setup-build-test/action.yml b/.github/actions/setup-build-test/action.yml index 22c0ced..a68f74c 100644 --- a/.github/actions/setup-build-test/action.yml +++ b/.github/actions/setup-build-test/action.yml @@ -24,6 +24,20 @@ runs: shell: bash run: npm ci ${{ inputs.verbose == 'true' && '--loglevel verbose' || '' }} + # Static gates first: none of them need a build, so a lint, type or manifest error + # fails in seconds instead of after the full build + validate cycle. + - name: Lint + shell: bash + run: npm run lint ${{ inputs.verbose == 'true' && '--loglevel verbose' || '' }} + + - name: Type-check build scripts + shell: bash + run: npm run typecheck:scripts + + - name: Check publish manifests + shell: bash + run: npm run check:manifests + - name: Build shell: bash run: npm run build ${{ inputs.verbose == 'true' && '--loglevel verbose' || '' }} @@ -35,9 +49,14 @@ runs: shell: bash run: npm run validate:dist ${{ inputs.verbose == 'true' && '--loglevel verbose' || '' }} - - name: Lint - shell: bash - run: npm run lint ${{ inputs.verbose == 'true' && '--loglevel verbose' || '' }} + # ~100MB download per run otherwise. Keyed on the lockfile, so the cache is + # rebuilt whenever the resolved playwright version can have changed. + - name: Cache Playwright browsers + uses: actions/cache@v4 + with: + path: ~/.cache/ms-playwright + key: ${{ runner.os }}-playwright-${{ hashFiles('package-lock.json') }} + restore-keys: ${{ runner.os }}-playwright- - name: Install Playwright browsers shell: bash diff --git a/package-lock.json b/package-lock.json index 07b3aa5..d3800ce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,49 +10,49 @@ "dependencies": { "@lit/react": "^1.0.8", "igniteui-dockmanager": "~2.1.3", - "igniteui-grid-lite": "~0.9.0", - "igniteui-webcomponents": "~7.2.4", + "igniteui-grid-lite": "~0.10.0", + "igniteui-webcomponents": "~7.3.1", "igniteui-webcomponents-grids": "~7.2.1", "lit": "^3.3.3" }, "devDependencies": { "@arethetypeswrong/cli": "^0.18.5", - "@biomejs/biome": "~2.5.6", - "@types/node": "^26.1.2", + "@biomejs/biome": "~2.5.11", + "@types/node": "^26.4.0", "@types/react": "^19.2.18", - "@types/react-dom": "^19.2.4", - "@vitejs/plugin-react": "^6.0.5", - "@vitest/browser": "^4.1.10", - "@vitest/browser-playwright": "^4.1.10", - "@vitest/coverage-v8": "^4.1.10", + "@types/react-dom": "^19.2.5", + "@vitejs/plugin-react": "^6.1.1", + "@vitest/browser": "^4.1.11", + "@vitest/browser-playwright": "^4.1.11", + "@vitest/coverage-v8": "^4.1.11", "cross-env": "^10.1.0", - "dompurify": "^3.4.13", + "dompurify": "^3.4.14", "ig-typedoc-theme": "^7.0.1", - "lefthook": "^2.1.10", - "marked": "^17.0.3", + "lefthook": "^2.1.12", + "marked": "^18.0.11", "marked-shiki": "^1.2.1", "npm-packlist": "^11.3.0", "playwright": "^1.62.1", "prettier": "^3.9.6", "react": "^19.2.8", "react-dom": "^19.2.8", - "rimraf": "^6.1.3", - "shiki": "^3.23.0", - "tsx": "^4.23.1", + "shiki": "^4.4.3", + "tsx": "^4.23.13", "typedoc": "^0.28.20", "typedoc-plugin-localization": "^3.1.0", "typedoc-plugin-merge-modules": "^7.0.0", "typescript": "^6.0.3", - "vite": "^8.2.0", - "vitest": "^4.1.10", + "vite": "^8.2.2", + "vitest": "^4.1.11", "vitest-browser-react": "^2.2.0" } }, "node_modules/@andrewbranch/untar.js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@andrewbranch/untar.js/-/untar.js-1.0.3.tgz", - "integrity": "sha512-Jh15/qVmrLGhkKJBdXlK1+9tY4lZruYjsgkDFj08ZmDiWVBLJcqkok7Z0/R0In+i1rScBpJlSvrTS2Lm41Pbnw==", - "dev": true + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@andrewbranch/untar.js/-/untar.js-1.0.4.tgz", + "integrity": "sha512-pVXSwPsLuw8IGLo2Di0EaOfsk+ntVvpkk942J/sHYIkwvtKUakEcPh7HBgZ6tuimgzKSEHgCvO4XgQ05DEbwDw==", + "dev": true, + "license": "MIT" }, "node_modules/@arethetypeswrong/cli": { "version": "0.18.5", @@ -77,9 +77,9 @@ } }, "node_modules/@arethetypeswrong/cli/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.3.0.tgz", + "integrity": "sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==", "dev": true, "license": "MIT", "engines": { @@ -192,13 +192,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", - "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz", + "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.29.7" + "@babel/types": "^7.29.8" }, "bin": { "parser": "bin/babel-parser.js" @@ -208,9 +208,9 @@ } }, "node_modules/@babel/types": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", - "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", "dev": true, "license": "MIT", "dependencies": { @@ -232,9 +232,9 @@ } }, "node_modules/@biomejs/biome": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.5.6.tgz", - "integrity": "sha512-lxVNjv7UF6KfhMJfL9gaUHbWdJdHbsAj6OSmwSYNdhRuG67NxNQ4Xdvh3TUxsSK9sBzJBQhEJj3AopmmNJ5pSA==", + "version": "2.5.11", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.5.11.tgz", + "integrity": "sha512-Tj0dnkLPdW0ASjHfj2D/ZkkvPU2wrFmnE1jWTD2xzV1ycapV1DutbYXk4NDnR3rYTi1ZCbNFD4G2gRMEY65WaA==", "dev": true, "license": "MIT OR Apache-2.0", "bin": { @@ -248,20 +248,20 @@ "url": "https://opencollective.com/biome" }, "optionalDependencies": { - "@biomejs/cli-darwin-arm64": "2.5.6", - "@biomejs/cli-darwin-x64": "2.5.6", - "@biomejs/cli-linux-arm64": "2.5.6", - "@biomejs/cli-linux-arm64-musl": "2.5.6", - "@biomejs/cli-linux-x64": "2.5.6", - "@biomejs/cli-linux-x64-musl": "2.5.6", - "@biomejs/cli-win32-arm64": "2.5.6", - "@biomejs/cli-win32-x64": "2.5.6" + "@biomejs/cli-darwin-arm64": "2.5.11", + "@biomejs/cli-darwin-x64": "2.5.11", + "@biomejs/cli-linux-arm64": "2.5.11", + "@biomejs/cli-linux-arm64-musl": "2.5.11", + "@biomejs/cli-linux-x64": "2.5.11", + "@biomejs/cli-linux-x64-musl": "2.5.11", + "@biomejs/cli-win32-arm64": "2.5.11", + "@biomejs/cli-win32-x64": "2.5.11" } }, "node_modules/@biomejs/cli-darwin-arm64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.5.6.tgz", - "integrity": "sha512-zMOLZP4oMrjh6m1zcSj1ud2awUPgTuMVbmQhYYWL7J8HwCnbHHBvTm7VBTRuY7epT5bez76IpKYQ11ZAqHFlnw==", + "version": "2.5.11", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.5.11.tgz", + "integrity": "sha512-6SGZxoKbXvUjMn1t6A98HqWISPnGNbYs0R/Rt2JarmXBSev+lva4QxUMWEBX9lX1Wo1XTJ78uk5xVDtG58SRZg==", "cpu": [ "arm64" ], @@ -276,9 +276,9 @@ } }, "node_modules/@biomejs/cli-darwin-x64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.5.6.tgz", - "integrity": "sha512-JAC1VqzvO7Th5ZplU0G2uGfkZbxEe9uDDektPAhF0JLusoz1w+T4okp2bkykI0bbaO2vslKiRfj4gU43JaGreA==", + "version": "2.5.11", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.5.11.tgz", + "integrity": "sha512-nYkXY7tLBEgnGbYapDKAyKzgt44ZEyG+AKalvTXtCWKYgepI9dw327q+cVgedxm+Udi1ZzHKUyZrIusHi/KQbw==", "cpu": [ "x64" ], @@ -293,9 +293,9 @@ } }, "node_modules/@biomejs/cli-linux-arm64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.5.6.tgz", - "integrity": "sha512-6XsYwCFkp5sMxl85ffhgeGpGgs6A7dRYFnkceZ7WVxvycuTnGdD5xa534Z3xfrBQ0JCMK/mujT6ZNPJoghedwg==", + "version": "2.5.11", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.5.11.tgz", + "integrity": "sha512-3PVLSTD9RR73rvVPt5G3T1gc+ycggWEGfTD7RvzzbtcDPD27NxgxBbAFfpm7DXJKW6VLHWE1lLMGvFt2Qxjcow==", "cpu": [ "arm64" ], @@ -313,9 +313,9 @@ } }, "node_modules/@biomejs/cli-linux-arm64-musl": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.5.6.tgz", - "integrity": "sha512-eUa3jeeYvfMt19LBeh6E5PUZpxnTC4JqNWo+EDjTtQjAr2xLGnWaxACtVU1DQqmHYbvThlJzLX+ZsYgrqh2qVw==", + "version": "2.5.11", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.5.11.tgz", + "integrity": "sha512-qhyZUMyCbWYFV2bAwRNVvfMVZ+hv7WYl6mossGrxC+uiQQXhvsuWWU8zz6jYX0mChZd9MgQZbm4vozTmG/5iGw==", "cpu": [ "arm64" ], @@ -333,9 +333,9 @@ } }, "node_modules/@biomejs/cli-linux-x64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.5.6.tgz", - "integrity": "sha512-Pop9VXCFUhFTMfFefZ39S+u2rOPyNp5iHlxbZRwXGACHLy2r0jjiRgJHmaEKJzL3SyxlVeGShXhvvElvWowonA==", + "version": "2.5.11", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.5.11.tgz", + "integrity": "sha512-JOytptlsgM33B2MMFUg8iBrb4IKpbD5JnJrSeYiaFEeAj4vuXx0iQSQZ4qK7sqyMtfjZxxPdNdMZZVL4y/mFyA==", "cpu": [ "x64" ], @@ -353,9 +353,9 @@ } }, "node_modules/@biomejs/cli-linux-x64-musl": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.5.6.tgz", - "integrity": "sha512-2Vp13QdKysH3HIWLaYLhUUwbK+jbZonJD1K+Lr0d0RO4wH7mkYd43vJixEDm8cUWrowoRz4UUHF1nm9Ae7ym8A==", + "version": "2.5.11", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.5.11.tgz", + "integrity": "sha512-oRRlrchG5EfrEL/EmtT1qUjSNHk3/5LGeZhQqADBBAJF1b1ET6964xEKe7aGlGARzDfza8H/seEsFJl7S6Ql9w==", "cpu": [ "x64" ], @@ -373,9 +373,9 @@ } }, "node_modules/@biomejs/cli-win32-arm64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.5.6.tgz", - "integrity": "sha512-tDGshcm6BdkZOCGnTDX0Y8/U4IfBSlnUU7T56nNDuPEfed+aHg+u8G36NB43fJVl0Os6+QURXIE1yuD7AaEofA==", + "version": "2.5.11", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.5.11.tgz", + "integrity": "sha512-e49E6K9hzH/ohJNx8Y26mY8HaV4I4ZViIeoqhKsmoXLKHhQnMeBAVqCgsGf2Wa3lXlS7RkporDXMHHWkzvZzFw==", "cpu": [ "arm64" ], @@ -390,9 +390,9 @@ } }, "node_modules/@biomejs/cli-win32-x64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.5.6.tgz", - "integrity": "sha512-WN05KwXnTO/2J45RQPvzZMXf7tZUIofHoR35xIPfCo7pQ2RFidxI8sfb5mGsaTxdMmEOzHzOPRCdA5/fCpc7xQ==", + "version": "2.5.11", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.5.11.tgz", + "integrity": "sha512-QSQr/KjOgXA7OzXJUWS+oguKyAZ3Q0l/lnlDGbu397eKo83atuWUjBPJrsqbKNF6CARGw8XXJLGzpHC8Ryhd4Q==", "cpu": [ "x64" ], @@ -431,40 +431,6 @@ "node": ">=0.1.90" } }, - "node_modules/@emnapi/core": { - "version": "2.0.0-alpha.3", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-2.0.0-alpha.3.tgz", - "integrity": "sha512-AZypUeJ/yByuxyS7BlSNRDOMLMlROYtjYdIAuBmJssVz1UJDSeYxLrdizhXCFYhedC5bqd/ASy8EuNXbVVXp9g==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "2.0.1", - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/runtime": { - "version": "2.0.0-alpha.3", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-2.0.0-alpha.3.tgz", - "integrity": "sha512-hFPAhMUjJD9BSyCANEISPOogeXC9Zo9ZQl7L6vKnaVsMkCtzznaW/naYypeyl0Gv5rYfWYsZbpixTMpjDJzQeA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/wasi-threads": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-2.0.1.tgz", - "integrity": "sha512-9DsSk+o5NBX0CCJT8s0EROGSGxjR/tKu6aBTaVyq+SjAEQH4XcdcRxPBRzsBLizTTJ49MJjF+jgu3qnO9GLQcQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@epic-web/invariant": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@epic-web/invariant/-/invariant-1.0.0.tgz", @@ -473,9 +439,9 @@ "license": "MIT" }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", - "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", + "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", "cpu": [ "ppc64" ], @@ -490,9 +456,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", - "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz", + "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", "cpu": [ "arm" ], @@ -507,9 +473,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", - "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", + "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", "cpu": [ "arm64" ], @@ -524,9 +490,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", - "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz", + "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", "cpu": [ "x64" ], @@ -541,9 +507,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", - "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", + "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", "cpu": [ "arm64" ], @@ -558,9 +524,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", - "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", + "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", "cpu": [ "x64" ], @@ -575,9 +541,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", - "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", + "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", "cpu": [ "arm64" ], @@ -592,9 +558,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", - "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", + "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", "cpu": [ "x64" ], @@ -609,9 +575,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", - "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", + "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", "cpu": [ "arm" ], @@ -626,9 +592,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", - "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", + "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", "cpu": [ "arm64" ], @@ -643,9 +609,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", - "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", + "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", "cpu": [ "ia32" ], @@ -660,9 +626,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", - "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", + "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", "cpu": [ "loong64" ], @@ -677,9 +643,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", - "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", + "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", "cpu": [ "mips64el" ], @@ -694,9 +660,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", - "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", + "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", "cpu": [ "ppc64" ], @@ -711,9 +677,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", - "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", + "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", "cpu": [ "riscv64" ], @@ -728,9 +694,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", - "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", + "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", "cpu": [ "s390x" ], @@ -745,9 +711,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", - "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", + "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", "cpu": [ "x64" ], @@ -762,9 +728,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", - "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", + "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", "cpu": [ "arm64" ], @@ -779,9 +745,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", - "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", + "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", "cpu": [ "x64" ], @@ -796,9 +762,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", - "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", + "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", "cpu": [ "arm64" ], @@ -813,9 +779,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", - "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", + "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", "cpu": [ "x64" ], @@ -830,9 +796,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", - "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", + "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", "cpu": [ "arm64" ], @@ -847,9 +813,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", - "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", + "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", "cpu": [ "x64" ], @@ -864,9 +830,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", - "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", + "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", "cpu": [ "arm64" ], @@ -881,9 +847,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", - "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", + "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", "cpu": [ "ia32" ], @@ -898,9 +864,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", - "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", + "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", "cpu": [ "x64" ], @@ -953,6 +919,48 @@ "@shikijs/vscode-textmate": "^10.0.2" } }, + "node_modules/@gerrit0/mini-shiki/node_modules/@shikijs/engine-oniguruma": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.23.0.tgz", + "integrity": "sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.23.0", + "@shikijs/vscode-textmate": "^10.0.2" + } + }, + "node_modules/@gerrit0/mini-shiki/node_modules/@shikijs/langs": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.23.0.tgz", + "integrity": "sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.23.0" + } + }, + "node_modules/@gerrit0/mini-shiki/node_modules/@shikijs/themes": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.23.0.tgz", + "integrity": "sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.23.0" + } + }, + "node_modules/@gerrit0/mini-shiki/node_modules/@shikijs/types": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.23.0.tgz", + "integrity": "sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", @@ -964,9 +972,9 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz", + "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==", "dev": true, "license": "MIT" }, @@ -1034,32 +1042,10 @@ "@braidai/lang": "^1.0.0" } }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.2.tgz", - "integrity": "sha512-JfB4kuJQjaoHuCTseIINHtHWeJnvgEcxjwA5t/Y00ZgaOO1Crz3fjT/p8kT28zA/Caz7oiUMn3d6H2yOVCVwuw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@tybys/wasm-util": "^0.10.3" - }, - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=23.5.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - }, - "peerDependencies": { - "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.3", - "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.3" - } - }, "node_modules/@oxc-project/types": { - "version": "0.142.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.142.0.tgz", - "integrity": "sha512-7W+2q5AKQVU36fkaryontrHn3YDt1RyUYXatw9i5H8ocYe2sPKSFB6eS8WNPeRKiN1qAWWZUPm7gwFzJGrccqQ==", + "version": "0.147.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.147.0.tgz", + "integrity": "sha512-IJ3s6ltHLp45S0bh7phkX+gJO7A1Wuz2EaqpAhb8WjqDwbzMiWKHhyyT42tskaWjEYXtHtVCPpnBJVT9+dcRLg==", "dev": true, "license": "MIT", "funding": { @@ -1073,10 +1059,27 @@ "dev": true, "license": "MIT" }, + "node_modules/@rolldown/binding-android-arm-eabi": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.6.tgz", + "integrity": "sha512-b+jTcARdTiFLI6jB4a5XjTm0RWd6KcRfQj/I2356fxUZemiho9zQLxo0RtCuMDAyKcLo6cEltkgbQp6d1+sjjQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, "node_modules/@rolldown/binding-android-arm64": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.1.tgz", - "integrity": "sha512-02hOeOSryYxVrOIphmLAsqnCJWxwlzFk+pEt/N/i6OgT3lShHO7xGCU5cpgchRDHboAEbSjzgGh+O/u1GswQmA==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.6.tgz", + "integrity": "sha512-lkWU8ZJaRk9q3CIEY1Tc7vIFALp3Xw5NfGJo2hQg5oIqNgxWi1zI+IiDEK3r70BF5Dzol1tcXsnzsRc8NLhG+Q==", "cpu": [ "arm64" ], @@ -1091,9 +1094,9 @@ } }, "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.1.tgz", - "integrity": "sha512-fMsTOnN0OjFm3CyppWPitKnc8UlliVARUULW6cfU6AIqjdtgmSFWSk9vecHzZduv/yMWIHDlRhM1e8Iff9uAfA==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.6.tgz", + "integrity": "sha512-dgR56NYnvAszm7Ob1B2/Vn0e8bUQYZH2UjVaMMtMVOCKFSfjhfLmuA/9+O+F+ajUdG6B/bSssrKW6JJYASa8jA==", "cpu": [ "arm64" ], @@ -1108,9 +1111,9 @@ } }, "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.1.tgz", - "integrity": "sha512-1wjKdz/XLGKHaTNHjQveQ/B23TKx4ItAqm1JbyVuvNPc4Ze0Fb48s49TAd/2zcplPl8okE/UbTgmlVfwT7eFeQ==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.6.tgz", + "integrity": "sha512-vpVxFvUCFioJqug7OTvqptkc4yb8UX0AwfDmJpaR/0sWz+BUmqSVAf7c8JkUgnN8YLspb4a/N6NhTyMAmdyQ7Q==", "cpu": [ "x64" ], @@ -1125,9 +1128,9 @@ } }, "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.1.tgz", - "integrity": "sha512-Fa0jHR07E7YBN4vOEsbVf2briYNsuOowfLJaXULZM0ldMlaCaj2LJgLMbMe4iacRyZmvR8efFhgR9wKuGclQUg==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.6.tgz", + "integrity": "sha512-h1wG6Y6K3JlRswxsI64qQJqBAy4vrLuHgRbc8CZMGSWTOFRY6ghMApM1NKzB2I0n5xV1fjkE18SuVl2QpLeNpA==", "cpu": [ "x64" ], @@ -1142,9 +1145,9 @@ } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.1.tgz", - "integrity": "sha512-pzkgu1SSHGgRRyRZ4fbmSgmajbVt+epaLP99NDjFft69v/ypfTi6swBMiVdh2EkQ0OSnHE1lZDM7DRGkyAzUpA==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.6.tgz", + "integrity": "sha512-tbCiqub0q2MVWJKgF5PoAlNWCtQydiOYSLIkd8sByqK/6MMYLJRcSXSYodqYtd0O+Fw7QaVmKKlS4oL94YRZ0w==", "cpu": [ "arm" ], @@ -1159,9 +1162,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.1.tgz", - "integrity": "sha512-QI5SEDY8cbiYWHx0VO4vIc3UlS6a32vXHjU8Qy/17adEmZIPuByJg13UEvo9c/UCiUkdcVWY83C+b+JrwnNyUg==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.6.tgz", + "integrity": "sha512-oxK9+baEBPhZG5HB4URY+uU04zJWeZlH6Tb9rB5DK4DF9XR1uXNLXt5Q5ZsugTKayNCNLhkcwz/ye74hRI98dg==", "cpu": [ "arm64" ], @@ -1179,9 +1182,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.1.tgz", - "integrity": "sha512-Sm41FyCeXqmYcERoYOCbGIL5hNfd8w9LQ7Y61Bev48HkcjaJqV/iiVOaiDxjVTRMS+QKrZmD8cfPt4uMVnvM+A==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.6.tgz", + "integrity": "sha512-muWCk27FVBEZtv0MsK8gnfSmgczA8KQ0uRVJbTABKhkRfQc38aUrcb7fhi3BNiyseFmgcRsoMfQsSNJ+DbZdSw==", "cpu": [ "arm64" ], @@ -1199,9 +1202,9 @@ } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.1.tgz", - "integrity": "sha512-2x+WhXTGl9yJYPbltW/BSEPTVz9OIWQyER4N+gJEDWkkn904eRcBzELqh/Hf7K0w/ubGbKNMv0ZC+94QK/IFEg==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.6.tgz", + "integrity": "sha512-eWDoSfU7Co2qj3vgB3Dt4lj1mG6CoWbcJQkRMP3XJplyCMtuaq3LHvPFjS9QIPvMGWVadJC04Xiy0IdcVPtnwQ==", "cpu": [ "ppc64" ], @@ -1219,9 +1222,9 @@ } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.1.tgz", - "integrity": "sha512-eEjmQpuRQayHPWWnywaWHkFT3ToPbP3RYy42VVd/B9aBGDA+Ol25EIWHxKQST3IiWJjikCWUF7KtbfqwZrzVwQ==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.6.tgz", + "integrity": "sha512-2bWNjRSIayvupRKxXUY2tWG9fYdoUlTqWywHRvE8Eq3GvuQ+f2HeIkve697fIt+IQs/PV8yFsdWuhp1aJ1PdnA==", "cpu": [ "s390x" ], @@ -1239,9 +1242,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.1.tgz", - "integrity": "sha512-/Orga1fZYkLc/56jBICcHrKchl8Z2UKdDSr3LG9ToWO1lQ6a4Livk9Xz+9WN91zsz5QR3XQz2NNoSDEvP6qadw==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.6.tgz", + "integrity": "sha512-KekI0gS0wLxe1UBSQSjenBVwou/JkcQPDzBPICGZjxUv9k3RteHDPBQaiOicZUFKRIH2wKEimGwVpnJsbPzu7w==", "cpu": [ "x64" ], @@ -1259,9 +1262,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.1.tgz", - "integrity": "sha512-xxBJRL+0q0Kce7orznGWLuylHDY65vuARXZRpX+hPdv+DqK2c3NlCsVA98tlWzWNEE7yPqA/1NQ5nnCrj49Y5A==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.6.tgz", + "integrity": "sha512-TvtPnfVr+HtyGiDmPK4VWmlNm7QhNNAcK5Q9A7aOXsI8545yCyaoMaicXrFZ72JzeYjaUVk7yT243zT0jzjFKQ==", "cpu": [ "x64" ], @@ -1279,9 +1282,9 @@ } }, "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.1.tgz", - "integrity": "sha512-M6AdXIXw3s+/8XpKMzdGDEXGS1S7kwUsy+rcTIUIOx5Ge4nXKCtAFHFV9YKkXvGcC5WMoTjAteLzlsQROVI0Yw==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.6.tgz", + "integrity": "sha512-iOo0VEay2XFhaCcH0sps5XIimkSuOnNaZrf6+ZkoSOQBJPKNU48RkmJv0/lSpipexu5P+ouFgafe5IGr/DiQfg==", "cpu": [ "arm64" ], @@ -1295,26 +1298,10 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.2.1.tgz", - "integrity": "sha512-/TX0SoRGojHzSAHpfVBbavRVSazg5U3h3Y3VXfcc0cdugq6kxdqw8LPGFiPr+/7gE/60zRcsOY2Vi9b9eT0jww==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "2.0.0-alpha.3", - "@emnapi/runtime": "2.0.0-alpha.3", - "@napi-rs/wasm-runtime": "^1.2.0" - }, - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=23.5.0" - } - }, "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.1.tgz", - "integrity": "sha512-EvRrivJieyHG+AO9lleZWgq+g0+S7oV2C51yuqlcyU/R9net+sI4Pj0F+lUoP2bEr6TWX3SqFaaS0SzfLxSzkw==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.6.tgz", + "integrity": "sha512-y5NTmmasMS455JlOCO4ZM9krIchv3Mvm1crL1iUPGOPgEzSkves9n0SdC5Sjz6+qWDFhd8/JpfWMH8NSWNHe+A==", "cpu": [ "arm64" ], @@ -1329,9 +1316,9 @@ } }, "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.1.tgz", - "integrity": "sha512-Z4eCmn5QJ/5+azF9knpLWKfVd9aidn0mAe9TpJgvBLId9Ax3t0+JVxBmT25Bv7NBbVW1TZyKjQjQReouMeH5UQ==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.6.tgz", + "integrity": "sha512-np8iZSLfXlAD4kWhiyq/u0Yt8oZDtRQ8lGhQaCXo2rl37KNjeU0GjJuwr4P3oeZ++ROfofsKNBqR5LTO8aXyWQ==", "cpu": [ "x64" ], @@ -1353,70 +1340,104 @@ "license": "MIT" }, "node_modules/@shikijs/core": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.23.0.tgz", - "integrity": "sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-4.4.3.tgz", + "integrity": "sha512-QCR4q2ZO/ILJEuwiBMel4wdcTDb1JGwfjKTxPDF6x8ixOaluPrVqIn06C99AcRPhmYlBR56d/Fb+GN58GzExpg==", "devOptional": true, "license": "MIT", "dependencies": { - "@shikijs/types": "3.23.0", + "@shikijs/primitive": "4.4.3", + "@shikijs/types": "4.4.3", "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4", + "@types/hast": "^3.0.5", "hast-util-to-html": "^9.0.5" + }, + "engines": { + "node": ">=20" } }, "node_modules/@shikijs/engine-javascript": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.23.0.tgz", - "integrity": "sha512-aHt9eiGFobmWR5uqJUViySI1bHMqrAgamWE1TYSUoftkAeCCAiGawPMwM+VCadylQtF4V3VNOZ5LmfItH5f3yA==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-4.4.3.tgz", + "integrity": "sha512-FbOjFJp9VLdo1Wevs10BBtVxiTWwNLqZh5Gkhjgda/ioL15YOgeSl9n+6XMa3qRlPQzfhFNe641SrynFHYG0nQ==", "devOptional": true, "license": "MIT", "dependencies": { - "@shikijs/types": "3.23.0", + "@shikijs/types": "4.4.3", "@shikijs/vscode-textmate": "^10.0.2", - "oniguruma-to-es": "^4.3.4" + "oniguruma-to-es": "^4.3.6" + }, + "engines": { + "node": ">=20" } }, "node_modules/@shikijs/engine-oniguruma": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.23.0.tgz", - "integrity": "sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-4.4.3.tgz", + "integrity": "sha512-EcOQkxdxGQrc1Row/cC2c96/v1dbZqGnEVu1qTuT/MJmp6+cXCvQussowVmCv5Tqr3KuY3c7IbM6HTW3LJ1k9w==", "devOptional": true, "license": "MIT", "dependencies": { - "@shikijs/types": "3.23.0", + "@shikijs/types": "4.4.3", "@shikijs/vscode-textmate": "^10.0.2" + }, + "engines": { + "node": ">=20" } }, "node_modules/@shikijs/langs": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.23.0.tgz", - "integrity": "sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.4.3.tgz", + "integrity": "sha512-ePic0yfAJGOF83D5wBHK/00EjK65oahBYxFk5epgq33WRv7X9UuxLEV8PtR0szC0z8dl7INIpIodB99JRFlR+A==", "devOptional": true, "license": "MIT", "dependencies": { - "@shikijs/types": "3.23.0" + "@shikijs/types": "4.4.3" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/primitive": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/primitive/-/primitive-4.4.3.tgz", + "integrity": "sha512-m0wBeLDQDeIxRdUmrCPdQqfuUamDwRL5isCfYbguKD6NiaKpVbsv+3J81DyIKgNW5h4WAIIr8T4EkgQrBBxvaQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.4.3", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.5" + }, + "engines": { + "node": ">=20" } }, "node_modules/@shikijs/themes": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.23.0.tgz", - "integrity": "sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.4.3.tgz", + "integrity": "sha512-w8UHjeUnIR965KMWJHUPXOc2mNJUnK3vpVLYLvw5IYU2mnTTJ89E24OrJDBNiJDQ0qzb0tc4l7mrIXx5cFeIyw==", "devOptional": true, "license": "MIT", "dependencies": { - "@shikijs/types": "3.23.0" + "@shikijs/types": "4.4.3" + }, + "engines": { + "node": ">=20" } }, "node_modules/@shikijs/types": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.23.0.tgz", - "integrity": "sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.4.3.tgz", + "integrity": "sha512-UEJxmRR++MAGR6hugn0vgVS2W/6lWAts84FFSrnlH9sP0LNol7E5+NQ792pH8liWUhyMyjhTgSUH3k7iD7tc5g==", "devOptional": true, "license": "MIT", "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4" + "@types/hast": "^3.0.5" + }, + "engines": { + "node": ">=20" } }, "node_modules/@shikijs/vscode-textmate": { @@ -1446,17 +1467,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@tybys/wasm-util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", - "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@types/chai": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", @@ -1503,9 +1513,9 @@ } }, "node_modules/@types/node": { - "version": "26.1.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.2.tgz", - "integrity": "sha512-Vu4a5UFA9rIIFJ7rB/Vaafh9lrCQszopTCx6KjFboXTGQbPNasehVR5TEiithSDGyd1DEiUByggTZsg8jukeIg==", + "version": "26.4.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.4.0.tgz", + "integrity": "sha512-faiGnoIrLH/V8cibOMEAZ8pMw6oXqSukl29ra4mN8GdaB2ZewzeaLj+INpV5N+Z1eKWzY+IzaIZH2EIR6YZRNQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1522,9 +1532,9 @@ } }, "node_modules/@types/react-dom": { - "version": "19.2.4", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.4.tgz", - "integrity": "sha512-Bsc+QHgp+P/F02XDzNCY9jnZNCUuLki36KT7VKrTXXLdHf+vHMNZnW1rVu5DNW/rCK+fya3DATySbLM4yhtKUw==", + "version": "19.2.5", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.5.tgz", + "integrity": "sha512-fMPwH9v7r/pp43yUd2/Mbiex5KouJwwR3dzHkhLREUC6764VyDsqxhAxv6OFEYR1RhjOyD1naqba8ECDBe7ZQg==", "dev": true, "license": "MIT", "peerDependencies": { @@ -1545,16 +1555,16 @@ "license": "MIT" }, "node_modules/@ungap/structured-clone": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.3.tgz", - "integrity": "sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.4.0.tgz", + "integrity": "sha512-1mEZtMKPM09vDmQt5y7YvmN2+DFTP7Tg0EWXdic8/C6VRnpb33e4ghisCIE3WZjsE2N8mf+QV1Zqh7ZFYLWInQ==", "devOptional": true, "license": "ISC" }, "node_modules/@vitejs/plugin-react": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.5.tgz", - "integrity": "sha512-BOVzne/NL162sMdResB25mUv+vWMF5NoAjNf09TeGlE7ZpszZWSD3winycicLJw72yeVsoCn/2kOhEuCvEShMA==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.1.1.tgz", + "integrity": "sha512-yxLaQV9gkhS8ezJqCM6+ndU7mDY6gqAg75NQ+0IjwEI8IYOmQCgkRwHKVSfWXW076DsqMo0Dk+0FK1U+M5RgFw==", "dev": true, "license": "MIT", "dependencies": { @@ -1566,6 +1576,7 @@ "peerDependencies": { "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", "babel-plugin-react-compiler": "^1.0.0", + "oxc-transform-react": "^0.145.0", "vite": "^8.0.0" }, "peerDependenciesMeta": { @@ -1574,19 +1585,22 @@ }, "babel-plugin-react-compiler": { "optional": true + }, + "oxc-transform-react": { + "optional": true } } }, "node_modules/@vitest/browser": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-4.1.10.tgz", - "integrity": "sha512-UDwuWGwXj646CBx/bQHOaJSX7np0I8JL/UKQYa1e4QrVHH8VdWtx8eaOuf8sy0ShwDgR6NjJAsp5eF6vjF6qng==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-4.1.11.tgz", + "integrity": "sha512-bwMovvAeuTFOK5kIFevw4VEf+1gVEICv4SYK4k3knJOxl6b1zEWud8mYKD73e1B0odAn174h1MofURy2TPWf3w==", "dev": true, "license": "MIT", "dependencies": { "@blazediff/core": "1.9.1", - "@vitest/mocker": "4.1.10", - "@vitest/utils": "4.1.10", + "@vitest/mocker": "4.1.11", + "@vitest/utils": "4.1.11", "magic-string": "^0.30.21", "pngjs": "^7.0.0", "sirv": "^3.0.2", @@ -1597,18 +1611,18 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "vitest": "4.1.10" + "vitest": "4.1.11" } }, "node_modules/@vitest/browser-playwright": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/browser-playwright/-/browser-playwright-4.1.10.tgz", - "integrity": "sha512-nMoXGEiRpT7m3W7NsbvrM2aKNwiNHZf+zEpUCvMteGjZFvfT96Q9fh7QyB98dvDWXiKvrLxA7bJ1mCOOv+JQPw==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/browser-playwright/-/browser-playwright-4.1.11.tgz", + "integrity": "sha512-riLBxPqwnJ0lWs2DN2WeUfYeKLoAjbP2Xx8cLQdSddzMi20sksIa6K2mPz79DyMZKKVKH2ksOC2yJvtNcZg8cg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/browser": "4.1.10", - "@vitest/mocker": "4.1.10", + "@vitest/browser": "4.1.11", + "@vitest/mocker": "4.1.11", "tinyrainbow": "^3.1.0" }, "funding": { @@ -1616,7 +1630,7 @@ }, "peerDependencies": { "playwright": "*", - "vitest": "4.1.10" + "vitest": "4.1.11" }, "peerDependenciesMeta": { "playwright": { @@ -1625,14 +1639,14 @@ } }, "node_modules/@vitest/coverage-v8": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.10.tgz", - "integrity": "sha512-IM49HmthevbgAO4anp1hwtoT9wYe59w0LR00gr+eagHE+ZJ5lK4sLPeO0ubgoJcwLk6dehU3R24N+FbEEKDc8g==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.11.tgz", + "integrity": "sha512-8MVGEFnJIcdGjcbfKmeq8z0pZHH0JlVtoVZH9Q/qwUp6wyFnEJUBMrw9DCaj+ra3vShGmhavjalMIhPNxZAUcw==", "dev": true, "license": "MIT", "dependencies": { "@bcoe/v8-coverage": "^1.0.2", - "@vitest/utils": "4.1.10", + "@vitest/utils": "4.1.11", "ast-v8-to-istanbul": "^1.0.0", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", @@ -1646,8 +1660,8 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "4.1.10", - "vitest": "4.1.10" + "@vitest/browser": "4.1.11", + "vitest": "4.1.11" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -1656,16 +1670,16 @@ } }, "node_modules/@vitest/expect": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.10.tgz", - "integrity": "sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.11.tgz", + "integrity": "sha512-VX2x5vNJXET47KAFzwERI+KRMtTTCSWTfSMKsW7JsUsXV4psq++e3DvZpuTDOpHcxytiDs6p2nhVb2tVDiiUYw==", "dev": true, "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", - "@vitest/spy": "4.1.10", - "@vitest/utils": "4.1.10", + "@vitest/spy": "4.1.11", + "@vitest/utils": "4.1.11", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" }, @@ -1674,13 +1688,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.10.tgz", - "integrity": "sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.11.tgz", + "integrity": "sha512-2XJVD55d1o5AZous5CCGKS74g/riOj9odEt2bQpCVZeblHyHdnMeFl4jl0XjU21stf4mbjUkew2eXQZt65g5CQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "4.1.10", + "@vitest/spy": "4.1.11", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, @@ -1701,9 +1715,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.10.tgz", - "integrity": "sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.11.tgz", + "integrity": "sha512-yiZzPbGTS9Sr/JpFl8zHrcIkAofNbFV6k21vIgQN/cY/oxZeXhJv5sc/MBJ5jFKWmWs+oJHw0UXLZjmf931+Vw==", "dev": true, "license": "MIT", "dependencies": { @@ -1714,13 +1728,13 @@ } }, "node_modules/@vitest/runner": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.10.tgz", - "integrity": "sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.11.tgz", + "integrity": "sha512-LztvUgdwMNJMIkj3hQnnxiC2Xy1zNxq928W/xhjCLaNCzqTZOudjwbQf6v9IntZGPw132i2Lq2rgTRZHD3JHNw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "4.1.10", + "@vitest/utils": "4.1.11", "pathe": "^2.0.3" }, "funding": { @@ -1728,14 +1742,14 @@ } }, "node_modules/@vitest/snapshot": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.10.tgz", - "integrity": "sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.11.tgz", + "integrity": "sha512-pN7ikn1ON7h8ee4gIAp4AzyK+zBtJPzVbqOgu5LCEh4VaJVbPQcgYQYJIMGQPXVeJJq1fnfazis7a5pFNPahog==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.1.10", - "@vitest/utils": "4.1.10", + "@vitest/pretty-format": "4.1.11", + "@vitest/utils": "4.1.11", "magic-string": "^0.30.21", "pathe": "^2.0.3" }, @@ -1744,9 +1758,9 @@ } }, "node_modules/@vitest/spy": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.10.tgz", - "integrity": "sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.11.tgz", + "integrity": "sha512-apNa/prQy2qCeywhnixOHPRCgGNhvg7T4Dapfl1GahLp/R+uhBm5cPyFoNVyqsNd2h1nJxL6BqqdIjiABL60YA==", "dev": true, "license": "MIT", "funding": { @@ -1754,13 +1768,13 @@ } }, "node_modules/@vitest/utils": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.10.tgz", - "integrity": "sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.11.tgz", + "integrity": "sha512-zTCVGpyFsGWBhllOyKlTw/vnr6D9qxsfSDyfbyZmTyjHw5N/VuvzHpHoQjm2ZJzn4RJgx5w4r7V0er69CmLgPQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.1.10", + "@vitest/pretty-format": "4.1.11", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" }, @@ -2118,9 +2132,9 @@ } }, "node_modules/dompurify": { - "version": "3.4.13", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.13.tgz", - "integrity": "sha512-2vmYIoqjze2d+kakP8S/nS5shfsl587kzwEjcGlTdiksUVgFHnFCsLYDVj/JNqJVOQZGSYBTmuycv0PodwmnMQ==", + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.14.tgz", + "integrity": "sha512-dVoH9z+MY+C9IilgGCk3YfFqjLi3fChm2OiKJMzh6axrJ5qwxqWaZamgmHrpv22CN/KdbZJuGEGgfQoL00LTdg==", "devOptional": true, "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { @@ -2168,16 +2182,16 @@ } }, "node_modules/es-module-lexer": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.1.tgz", - "integrity": "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.2.tgz", + "integrity": "sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==", "dev": true, "license": "MIT" }, "node_modules/esbuild": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", - "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", + "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -2188,32 +2202,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.28.1", - "@esbuild/android-arm": "0.28.1", - "@esbuild/android-arm64": "0.28.1", - "@esbuild/android-x64": "0.28.1", - "@esbuild/darwin-arm64": "0.28.1", - "@esbuild/darwin-x64": "0.28.1", - "@esbuild/freebsd-arm64": "0.28.1", - "@esbuild/freebsd-x64": "0.28.1", - "@esbuild/linux-arm": "0.28.1", - "@esbuild/linux-arm64": "0.28.1", - "@esbuild/linux-ia32": "0.28.1", - "@esbuild/linux-loong64": "0.28.1", - "@esbuild/linux-mips64el": "0.28.1", - "@esbuild/linux-ppc64": "0.28.1", - "@esbuild/linux-riscv64": "0.28.1", - "@esbuild/linux-s390x": "0.28.1", - "@esbuild/linux-x64": "0.28.1", - "@esbuild/netbsd-arm64": "0.28.1", - "@esbuild/netbsd-x64": "0.28.1", - "@esbuild/openbsd-arm64": "0.28.1", - "@esbuild/openbsd-x64": "0.28.1", - "@esbuild/openharmony-arm64": "0.28.1", - "@esbuild/sunos-x64": "0.28.1", - "@esbuild/win32-arm64": "0.28.1", - "@esbuild/win32-ia32": "0.28.1", - "@esbuild/win32-x64": "0.28.1" + "@esbuild/aix-ppc64": "0.28.2", + "@esbuild/android-arm": "0.28.2", + "@esbuild/android-arm64": "0.28.2", + "@esbuild/android-x64": "0.28.2", + "@esbuild/darwin-arm64": "0.28.2", + "@esbuild/darwin-x64": "0.28.2", + "@esbuild/freebsd-arm64": "0.28.2", + "@esbuild/freebsd-x64": "0.28.2", + "@esbuild/linux-arm": "0.28.2", + "@esbuild/linux-arm64": "0.28.2", + "@esbuild/linux-ia32": "0.28.2", + "@esbuild/linux-loong64": "0.28.2", + "@esbuild/linux-mips64el": "0.28.2", + "@esbuild/linux-ppc64": "0.28.2", + "@esbuild/linux-riscv64": "0.28.2", + "@esbuild/linux-s390x": "0.28.2", + "@esbuild/linux-x64": "0.28.2", + "@esbuild/netbsd-arm64": "0.28.2", + "@esbuild/netbsd-x64": "0.28.2", + "@esbuild/openbsd-arm64": "0.28.2", + "@esbuild/openbsd-x64": "0.28.2", + "@esbuild/openharmony-arm64": "0.28.2", + "@esbuild/sunos-x64": "0.28.2", + "@esbuild/win32-arm64": "0.28.2", + "@esbuild/win32-ia32": "0.28.2", + "@esbuild/win32-x64": "0.28.2" } }, "node_modules/escalade": { @@ -2449,14 +2463,14 @@ } }, "node_modules/igniteui-grid-lite": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/igniteui-grid-lite/-/igniteui-grid-lite-0.9.0.tgz", - "integrity": "sha512-pW6MPniC0Up5YmbdB2QVTpPdIp0lkapPfQbnQQmqhtrvGO8Cpf84FQf1s7uMxatCC6FV5w7fgGpriy3t88yNng==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/igniteui-grid-lite/-/igniteui-grid-lite-0.10.0.tgz", + "integrity": "sha512-frMjK3jIdsu76SoKjxKw7U9aFbFAoqWapCelL4CXf75MF80UyQR+g22iMkUR1Nu2/PsQkmJP1hmC4R/4+PmtDA==", "license": "MIT", "dependencies": { "@lit-labs/virtualizer": "~2.1.0", "@lit/context": "~1.1.5", - "igniteui-webcomponents": "~7.2.0", + "igniteui-webcomponents": "~7.3.0", "lit": "^3.3.0" }, "engines": { @@ -2487,13 +2501,12 @@ } }, "node_modules/igniteui-webcomponents": { - "version": "7.2.4", - "resolved": "https://registry.npmjs.org/igniteui-webcomponents/-/igniteui-webcomponents-7.2.4.tgz", - "integrity": "sha512-h5hrroBn0kSYCYpj5OH4sKXkFZvdOeqpYnNTKMB5PsqsWexhQICkH5xKjDDj3VPbd135OvzWX5XQN0Nclj2qAQ==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/igniteui-webcomponents/-/igniteui-webcomponents-7.3.1.tgz", + "integrity": "sha512-hZINim/Bvb4T6GuYArrsHqYxH9t6Pl97bHEJhGULveqm45GfQfYS3w9U66t353bbpJ+CJ5VHbS+NJWFMb22CkQ==", "license": "MIT", "dependencies": { - "@floating-ui/dom": "^1.7.0", - "@lit-labs/virtualizer": "^2.1.0", + "@floating-ui/dom": "^1.8.0", "@lit/context": "^1.1.0", "igniteui-i18n-core": "^1.0.5", "lit": "^3.3.0" @@ -2502,11 +2515,11 @@ "node": ">=22" }, "peerDependencies": { - "dompurify": "^3.3.0", + "dompurify": "^3.4.0", "igniteui-i18n-resources": "^1.0.5", - "marked": "^17.0.0", + "marked": "^18.0.0", "marked-shiki": "^1.2.0", - "shiki": "^3.20.0" + "shiki": "^4.3.0" }, "peerDependenciesMeta": { "dompurify": { @@ -2635,9 +2648,9 @@ } }, "node_modules/lefthook": { - "version": "2.1.10", - "resolved": "https://registry.npmjs.org/lefthook/-/lefthook-2.1.10.tgz", - "integrity": "sha512-K7mM4WoqMwqfXYK11EHy+lSH1uW8XHni3Yn/bSqyerPkUPygGdf3xn18JoV5HyA06xuQL3ofGAOjG01QX9oJ4w==", + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/lefthook/-/lefthook-2.1.12.tgz", + "integrity": "sha512-2uOexfsrrRhCiTUWdGyDySxVHHhOFJ8MQejs27dM3hugrQB48/z1ZVlaNoxpZ1SnzQ1GaDIbO5rAvicwyiknYQ==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -2645,22 +2658,22 @@ "lefthook": "bin/index.js" }, "optionalDependencies": { - "lefthook-darwin-arm64": "2.1.10", - "lefthook-darwin-x64": "2.1.10", - "lefthook-freebsd-arm64": "2.1.10", - "lefthook-freebsd-x64": "2.1.10", - "lefthook-linux-arm64": "2.1.10", - "lefthook-linux-x64": "2.1.10", - "lefthook-openbsd-arm64": "2.1.10", - "lefthook-openbsd-x64": "2.1.10", - "lefthook-windows-arm64": "2.1.10", - "lefthook-windows-x64": "2.1.10" + "lefthook-darwin-arm64": "2.1.12", + "lefthook-darwin-x64": "2.1.12", + "lefthook-freebsd-arm64": "2.1.12", + "lefthook-freebsd-x64": "2.1.12", + "lefthook-linux-arm64": "2.1.12", + "lefthook-linux-x64": "2.1.12", + "lefthook-openbsd-arm64": "2.1.12", + "lefthook-openbsd-x64": "2.1.12", + "lefthook-windows-arm64": "2.1.12", + "lefthook-windows-x64": "2.1.12" } }, "node_modules/lefthook-darwin-arm64": { - "version": "2.1.10", - "resolved": "https://registry.npmjs.org/lefthook-darwin-arm64/-/lefthook-darwin-arm64-2.1.10.tgz", - "integrity": "sha512-nw+X8wRNDoUUV6WSteyKBbcLySq+fsmZt5WV/s50ZJpysmsDKJOUMln6SllNfP+60dzUahAO7REco/2633BsLg==", + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/lefthook-darwin-arm64/-/lefthook-darwin-arm64-2.1.12.tgz", + "integrity": "sha512-GSUjqaCuxAYlPOovbjXEWE3HAIa/xOQkTTmZ937zieQldjPLTaC7+s5FHoxKywn+D9riBlofkDqG7Z4f5zzmPA==", "cpu": [ "arm64" ], @@ -2672,9 +2685,9 @@ ] }, "node_modules/lefthook-darwin-x64": { - "version": "2.1.10", - "resolved": "https://registry.npmjs.org/lefthook-darwin-x64/-/lefthook-darwin-x64-2.1.10.tgz", - "integrity": "sha512-KQ/bHmvpkFdHMn4pZnUdTf+GuSC+aBBgBTxZT4GW+6cSf+qbErKZBhK7cH6BmILsvx43+VzEArvHYY7YOfRFOQ==", + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/lefthook-darwin-x64/-/lefthook-darwin-x64-2.1.12.tgz", + "integrity": "sha512-qAUHSSw/7Afi5wxkoLkxORxSicCeTBXyVLnRgD6YZra6udviozpK3Aok9Z6FIWeKc5FBijRMSNDxGPTREhsjcQ==", "cpu": [ "x64" ], @@ -2686,9 +2699,9 @@ ] }, "node_modules/lefthook-freebsd-arm64": { - "version": "2.1.10", - "resolved": "https://registry.npmjs.org/lefthook-freebsd-arm64/-/lefthook-freebsd-arm64-2.1.10.tgz", - "integrity": "sha512-8su6DwydP7+pv7kG0zCtjphqsw4ouOnfexRUErapy5GTxYBoUOhYz3RSHTSWNRsK6W4jva7FPUh2Lp5/PSn30w==", + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/lefthook-freebsd-arm64/-/lefthook-freebsd-arm64-2.1.12.tgz", + "integrity": "sha512-FHZRfKliFNbyz54zsoGdVe9muq67cNjBTZ6jrPPUjI7xUuyCwSpzA+1OpiwJT00L9pP5ZGONBqnGZKnrpC+7Uw==", "cpu": [ "arm64" ], @@ -2700,9 +2713,9 @@ ] }, "node_modules/lefthook-freebsd-x64": { - "version": "2.1.10", - "resolved": "https://registry.npmjs.org/lefthook-freebsd-x64/-/lefthook-freebsd-x64-2.1.10.tgz", - "integrity": "sha512-GeAJEFxko3Lk+AsnS3NleAFrpyMLFUKOlgJvPKuU0xHwVEI/z+ZoCcmuO0BX+4CS0NLbZhC/YQAvBASqDvvVdQ==", + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/lefthook-freebsd-x64/-/lefthook-freebsd-x64-2.1.12.tgz", + "integrity": "sha512-HYQZPGy2DDEx7dbuotusJpujY5q9igOLgx36qeeQcNQuvvdGHPj2ZGSIsGKhoJ0dw5Qa4knKJoPAHEZQWdV/og==", "cpu": [ "x64" ], @@ -2714,9 +2727,9 @@ ] }, "node_modules/lefthook-linux-arm64": { - "version": "2.1.10", - "resolved": "https://registry.npmjs.org/lefthook-linux-arm64/-/lefthook-linux-arm64-2.1.10.tgz", - "integrity": "sha512-1sHTCmpTWjVMs+yKPBLRNT1kuuIr1yjietlk7rCB6wFPVOS6Ph3o2zPFH2AvW1UymHlqwyHXzBr9EtDpQ7j1mQ==", + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/lefthook-linux-arm64/-/lefthook-linux-arm64-2.1.12.tgz", + "integrity": "sha512-ipjOri2PB/sk4noPrHQuM5fcpNBjmlKo4qMtXyLnxeOxGYHWZzf0Xi0OtrXHQ//tOprcv40ADvhUuSdcGqigLw==", "cpu": [ "arm64" ], @@ -2728,9 +2741,9 @@ ] }, "node_modules/lefthook-linux-x64": { - "version": "2.1.10", - "resolved": "https://registry.npmjs.org/lefthook-linux-x64/-/lefthook-linux-x64-2.1.10.tgz", - "integrity": "sha512-z/VlRB3bh6mBvW3r1rwnJ5vP8z+Krx5gJzkZ4veDXh+6FlRTx8wtd3g3fllOv/yZMxkgmL3fQoFXv05Esa7vBQ==", + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/lefthook-linux-x64/-/lefthook-linux-x64-2.1.12.tgz", + "integrity": "sha512-DmU6xfvqVoFdW+STyc70YI4Ry8vkHGKHx+IJ1Js/Gacq5dv+fiwNzwle3bi28EkL6P8xY67B/CfQfRj4SRU4tg==", "cpu": [ "x64" ], @@ -2742,9 +2755,9 @@ ] }, "node_modules/lefthook-openbsd-arm64": { - "version": "2.1.10", - "resolved": "https://registry.npmjs.org/lefthook-openbsd-arm64/-/lefthook-openbsd-arm64-2.1.10.tgz", - "integrity": "sha512-430zL8sSIKw5P0YXGG6PB+eAhHa06n0PXuaERaAQE4Ss3odfqwnl5Mq9hQmkEnOS1EGiQEKkd0UHv/i4PtMNIQ==", + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/lefthook-openbsd-arm64/-/lefthook-openbsd-arm64-2.1.12.tgz", + "integrity": "sha512-vb0J7bElLvoaCWQmna3HntsvoNqMsGAhfjjC99ss1OdCteufZKM3RxCVoMBEbD50Itv2c1Ua2AFVToltVFTy1Q==", "cpu": [ "arm64" ], @@ -2756,9 +2769,9 @@ ] }, "node_modules/lefthook-openbsd-x64": { - "version": "2.1.10", - "resolved": "https://registry.npmjs.org/lefthook-openbsd-x64/-/lefthook-openbsd-x64-2.1.10.tgz", - "integrity": "sha512-bgkO8PphGZVDhQgCJ524aYYPI5491pVmCiLPGjBIo1AvOSlIyw4N1Y+1C3QfqwEmechzw+Aq16SNc8pqv6UuXg==", + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/lefthook-openbsd-x64/-/lefthook-openbsd-x64-2.1.12.tgz", + "integrity": "sha512-QOmhDWqPPK4+99scanfEmbJjUR+JYC93qhr/0bp5Dj3LaR3kVFNWc6zOQUsOTPy/LC6PG759Lej/mr/BtjUL2Q==", "cpu": [ "x64" ], @@ -2770,9 +2783,9 @@ ] }, "node_modules/lefthook-windows-arm64": { - "version": "2.1.10", - "resolved": "https://registry.npmjs.org/lefthook-windows-arm64/-/lefthook-windows-arm64-2.1.10.tgz", - "integrity": "sha512-5Q6etF0Fla2DDA4ilDySrdNgiR5+W7cJZwnZ69Je3kvWCaWm4wnkuc8FEdjp3kiL2x3ZXipdI00f5vpO8aWmog==", + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/lefthook-windows-arm64/-/lefthook-windows-arm64-2.1.12.tgz", + "integrity": "sha512-eErEyr9AHkRFj6TxpCQeKGd0s6IrtL/VEIZ/ssg8dNfG+ycR4jAW/IAlrJSw6/ZQXb3WtWLaQ6QA5c+TLh7vmg==", "cpu": [ "arm64" ], @@ -2784,9 +2797,9 @@ ] }, "node_modules/lefthook-windows-x64": { - "version": "2.1.10", - "resolved": "https://registry.npmjs.org/lefthook-windows-x64/-/lefthook-windows-x64-2.1.10.tgz", - "integrity": "sha512-c/XH8YZtylG4XaxzqFfXluvq2LXq2W/p54Bnzn3+Z7E5X2Fk3JlFJAibulMbIt2+w8T7UI/r97ok5GqE4kGaeA==", + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/lefthook-windows-x64/-/lefthook-windows-x64-2.1.12.tgz", + "integrity": "sha512-0h+WmDVdDriTjloD/UbjPq/ZtqaaJlPAdGcVwMCEdAxfbF0FTgDbKX3igui9g2U/qG2y6QpVhtz1jeiRe7ctaw==", "cpu": [ "x64" ], @@ -3177,9 +3190,9 @@ } }, "node_modules/markdown-it": { - "version": "14.3.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.3.0.tgz", - "integrity": "sha512-RCEsPjR+sr0x+AuYp601tKTkgFG4YEPLCzHST3cQ/fhlJkqAkz1L2/Qbp1j9qw5SBwQHFBoW8+hoN5xssOF0Tw==", + "version": "14.3.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.3.1.tgz", + "integrity": "sha512-4Ej49aYTDFIQ+uBkfX8GBvJGccoARxxPep+7aWTs55ozbjQJpW9M26Fe53vnGgvLeVzva/amzjQQaQu9w0vMhA==", "dev": true, "funding": [ { @@ -3205,9 +3218,9 @@ } }, "node_modules/marked": { - "version": "17.0.6", - "resolved": "https://registry.npmjs.org/marked/-/marked-17.0.6.tgz", - "integrity": "sha512-gB0gkNafnonOw0obSTEGZTT86IuhILt2Wfx0mWH/1Au83kybTayroZ/V6nS25mN7u8ASy+5fMhgB3XPNrOZdmA==", + "version": "18.0.11", + "resolved": "https://registry.npmjs.org/marked/-/marked-18.0.11.tgz", + "integrity": "sha512-HnslJfsZkRPBDJRHvVtAaWlZHEpSu7u8LgQuJCELjRKuWR+hpq4A7sLq3p8HaI9ypVoXDXxV34CsQJEe1+J5Aw==", "devOptional": true, "license": "MIT", "bin": { @@ -3400,9 +3413,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.16", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz", - "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==", + "version": "3.3.18", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", "dev": true, "funding": [ { @@ -3492,13 +3505,6 @@ "regex-recursion": "^6.0.2" } }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "dev": true, - "license": "BlueOak-1.0.0" - }, "node_modules/parse5": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", @@ -3565,9 +3571,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", - "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", "dev": true, "license": "MIT", "engines": { @@ -3620,9 +3626,9 @@ } }, "node_modules/postcss": { - "version": "8.5.25", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.25.tgz", - "integrity": "sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==", + "version": "8.5.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", + "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", "dev": true, "funding": [ { @@ -3640,7 +3646,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.16", + "nanoid": "^3.3.17", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -3755,34 +3761,14 @@ "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.3.tgz", - "integrity": "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "glob": "^13.0.3", - "package-json-from-dist": "^1.0.1" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/rolldown": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.1.tgz", - "integrity": "sha512-4FKJhg8d3OiyQOA6Q1Q0hoFFpW9/OoX+VsHzpECsdsIZoOArrAK90gl59YK/Z+gnDel45bgJZK03ozH/9bCqEw==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.6.tgz", + "integrity": "sha512-vMM4q3aixf46GiF1Kok8jDPFsEpXgFWGjUHXNkNHNm+Y2adXAG2dbX91jkti3i0ZRsOlcmbuzAz1poObSHCmUA==", "dev": true, "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.142.0", + "@oxc-project/types": "=0.147.0", "@rolldown/pluginutils": "^1.0.0" }, "bin": { @@ -3792,21 +3778,21 @@ "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.2.1", - "@rolldown/binding-darwin-arm64": "1.2.1", - "@rolldown/binding-darwin-x64": "1.2.1", - "@rolldown/binding-freebsd-x64": "1.2.1", - "@rolldown/binding-linux-arm-gnueabihf": "1.2.1", - "@rolldown/binding-linux-arm64-gnu": "1.2.1", - "@rolldown/binding-linux-arm64-musl": "1.2.1", - "@rolldown/binding-linux-ppc64-gnu": "1.2.1", - "@rolldown/binding-linux-s390x-gnu": "1.2.1", - "@rolldown/binding-linux-x64-gnu": "1.2.1", - "@rolldown/binding-linux-x64-musl": "1.2.1", - "@rolldown/binding-openharmony-arm64": "1.2.1", - "@rolldown/binding-wasm32-wasi": "1.2.1", - "@rolldown/binding-win32-arm64-msvc": "1.2.1", - "@rolldown/binding-win32-x64-msvc": "1.2.1" + "@rolldown/binding-android-arm-eabi": "1.2.6", + "@rolldown/binding-android-arm64": "1.2.6", + "@rolldown/binding-darwin-arm64": "1.2.6", + "@rolldown/binding-darwin-x64": "1.2.6", + "@rolldown/binding-freebsd-x64": "1.2.6", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.6", + "@rolldown/binding-linux-arm64-gnu": "1.2.6", + "@rolldown/binding-linux-arm64-musl": "1.2.6", + "@rolldown/binding-linux-ppc64-gnu": "1.2.6", + "@rolldown/binding-linux-s390x-gnu": "1.2.6", + "@rolldown/binding-linux-x64-gnu": "1.2.6", + "@rolldown/binding-linux-x64-musl": "1.2.6", + "@rolldown/binding-openharmony-arm64": "1.2.6", + "@rolldown/binding-win32-arm64-msvc": "1.2.6", + "@rolldown/binding-win32-x64-msvc": "1.2.6" } }, "node_modules/scheduler": { @@ -3853,20 +3839,23 @@ } }, "node_modules/shiki": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.23.0.tgz", - "integrity": "sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-4.4.3.tgz", + "integrity": "sha512-Mb/GvXPHBAXdgGIcnfU5L3ldpn1XcxrGkPHwqgRx17/I2XRfqlFKk2vGkHWINn1kdXvzJZeuO3is6I9KLPFm0g==", "devOptional": true, "license": "MIT", "dependencies": { - "@shikijs/core": "3.23.0", - "@shikijs/engine-javascript": "3.23.0", - "@shikijs/engine-oniguruma": "3.23.0", - "@shikijs/langs": "3.23.0", - "@shikijs/themes": "3.23.0", - "@shikijs/types": "3.23.0", + "@shikijs/core": "4.4.3", + "@shikijs/engine-javascript": "4.4.3", + "@shikijs/engine-oniguruma": "4.4.3", + "@shikijs/langs": "4.4.3", + "@shikijs/themes": "4.4.3", + "@shikijs/types": "4.4.3", "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4" + "@types/hast": "^3.0.5" + }, + "engines": { + "node": ">=20" } }, "node_modules/siginfo": { @@ -4043,9 +4032,9 @@ "license": "MIT" }, "node_modules/tinyexec": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz", - "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.0.tgz", + "integrity": "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==", "dev": true, "license": "MIT", "engines": { @@ -4107,9 +4096,9 @@ "license": "0BSD" }, "node_modules/tsx": { - "version": "4.23.1", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.1.tgz", - "integrity": "sha512-GQHnkIfxyx1wYCOS/wonik5MVRZU9hi1TEZmzGZSCJB1y9YgoZ8H6itNE/u4suE+yLmOzuE4E5S4TZ/ZX2wcWQ==", + "version": "4.23.13", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.13.tgz", + "integrity": "sha512-BL5MGkRln6aDYhb0xbQlEAGw743BaZYWdbWtdJOBriYJboKgUUYCadFp2/FpBBZquBC/ezNBn7wMMPx7FDZUDw==", "dev": true, "license": "MIT", "dependencies": { @@ -4346,16 +4335,16 @@ } }, "node_modules/vite": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.0.tgz", - "integrity": "sha512-pn+CFpM0lwDeKwmOq1ZaBK/9sjorZcgqxki6MbY/jPEVd9vichIlmlD4HmQ5wdP5EgqQCFRaACBxMC7uEGc6lQ==", + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.2.tgz", + "integrity": "sha512-cFKLV/PRgAUlIRm5WjMjJ86jrftzpqcgH+Us+DS8mI3CDNiH30Whrz8uHL3+MOLPAgqbMBAqWdAHAphOAM+z/Q==", "dev": true, "license": "MIT", "dependencies": { "lightningcss": "^1.33.0", "picomatch": "^4.0.5", - "postcss": "^8.5.23", - "rolldown": "~1.2.0", + "postcss": "^8.5.26", + "rolldown": "~1.2.4", "tinyglobby": "^0.2.17" }, "bin": { @@ -4372,7 +4361,7 @@ }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", - "@vitejs/devtools": "^0.4.0", + "@vitejs/devtools": "^0.4.0 || ^0.5.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", @@ -4439,19 +4428,19 @@ } }, "node_modules/vitest": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.10.tgz", - "integrity": "sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.11.tgz", + "integrity": "sha512-fhACrNXUidIbGSBr5FlbuBkO7VWC1ZyLl0DO4CU2DrQoAPxX84Ysxs+HeGQpii5lZWV1Q4gBZTTu49mF+A6Edw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "4.1.10", - "@vitest/mocker": "4.1.10", - "@vitest/pretty-format": "4.1.10", - "@vitest/runner": "4.1.10", - "@vitest/snapshot": "4.1.10", - "@vitest/spy": "4.1.10", - "@vitest/utils": "4.1.10", + "@vitest/expect": "4.1.11", + "@vitest/mocker": "4.1.11", + "@vitest/pretty-format": "4.1.11", + "@vitest/runner": "4.1.11", + "@vitest/snapshot": "4.1.11", + "@vitest/spy": "4.1.11", + "@vitest/utils": "4.1.11", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", @@ -4479,12 +4468,12 @@ "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "4.1.10", - "@vitest/browser-preview": "4.1.10", - "@vitest/browser-webdriverio": "4.1.10", - "@vitest/coverage-istanbul": "4.1.10", - "@vitest/coverage-v8": "4.1.10", - "@vitest/ui": "4.1.10", + "@vitest/browser-playwright": "4.1.11", + "@vitest/browser-preview": "4.1.11", + "@vitest/browser-webdriverio": "4.1.11", + "@vitest/coverage-istanbul": "4.1.11", + "@vitest/coverage-v8": "4.1.11", + "@vitest/ui": "4.1.11", "happy-dom": "*", "jsdom": "*", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" @@ -4605,9 +4594,9 @@ } }, "node_modules/ws": { - "version": "8.21.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.1.tgz", - "integrity": "sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw==", + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz", + "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==", "dev": true, "license": "MIT", "engines": { diff --git a/package.json b/package.json index eb1cd32..5e52cb9 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "type": "module", "scripts": { "dev": "vite", - "build": "npm run build-wc && npm run build-dm && npm run build-grids && npm run build-grid-lite && tsc && vite build", + "build": "npm run generate && tsc && vite build", "build:docs:dev": "cross-env NODE_ENV=\"development\" npm run build:typedoc", "build:docs:staging": "cross-env NODE_ENV=\"staging\" npm run build:typedoc", "build:docs:prod": "cross-env NODE_ENV=\"production\" npm run build:typedoc", @@ -18,10 +18,13 @@ "build:plugin:watch": "tsc --project ./plugins/typedoc-plugin-react-components/tsconfig.json --watch", "build:plugin:prod": "tsc --project ./plugins/typedoc-plugin-react-components/tsconfig.prod.json", "preview": "vite preview", - "build-wc": "tsx ./scripts/build-wc.ts", - "build-dm": "tsx ./scripts/build-dm.ts", - "build-grids": "tsx ./scripts/build-grids.ts", - "build-grid-lite": "tsx ./scripts/build-grid-lite.ts", + "generate": "tsx ./scripts/generate.ts", + "generate:wc": "tsx ./scripts/generate.ts wc", + "generate:dm": "tsx ./scripts/generate.ts dm", + "generate:grids": "tsx ./scripts/generate.ts grids", + "generate:grid-lite": "tsx ./scripts/generate.ts grid-lite", + "typecheck:scripts": "tsc --project ./scripts/tsconfig.json", + "check:manifests": "tsx ./scripts/check-manifests.ts", "validate:dist": "tsx ./scripts/validate-dist.ts", "test:browser": "vitest", "test:ci": "vitest --run --coverage", @@ -31,41 +34,40 @@ "dependencies": { "@lit/react": "^1.0.8", "igniteui-dockmanager": "~2.1.3", - "igniteui-grid-lite": "~0.9.0", - "igniteui-webcomponents": "~7.2.4", + "igniteui-grid-lite": "~0.10.0", + "igniteui-webcomponents": "~7.3.1", "igniteui-webcomponents-grids": "~7.2.1", "lit": "^3.3.3" }, "devDependencies": { "@arethetypeswrong/cli": "^0.18.5", - "@biomejs/biome": "~2.5.6", - "@types/node": "^26.1.2", + "@biomejs/biome": "~2.5.11", + "@types/node": "^26.4.0", "@types/react": "^19.2.18", - "@types/react-dom": "^19.2.4", - "@vitejs/plugin-react": "^6.0.5", - "@vitest/browser": "^4.1.10", - "@vitest/browser-playwright": "^4.1.10", - "@vitest/coverage-v8": "^4.1.10", + "@types/react-dom": "^19.2.5", + "@vitejs/plugin-react": "^6.1.1", + "@vitest/browser": "^4.1.11", + "@vitest/browser-playwright": "^4.1.11", + "@vitest/coverage-v8": "^4.1.11", "cross-env": "^10.1.0", - "dompurify": "^3.4.13", + "dompurify": "^3.4.14", "ig-typedoc-theme": "^7.0.1", - "lefthook": "^2.1.10", - "marked": "^17.0.3", + "lefthook": "^2.1.12", + "marked": "^18.0.11", "marked-shiki": "^1.2.1", "npm-packlist": "^11.3.0", "playwright": "^1.62.1", "prettier": "^3.9.6", "react": "^19.2.8", "react-dom": "^19.2.8", - "rimraf": "^6.1.3", - "shiki": "^3.23.0", - "tsx": "^4.23.1", + "shiki": "^4.4.3", + "tsx": "^4.23.13", "typedoc": "^0.28.20", "typedoc-plugin-localization": "^3.1.0", "typedoc-plugin-merge-modules": "^7.0.0", "typescript": "^6.0.3", - "vite": "^8.2.0", - "vitest": "^4.1.10", + "vite": "^8.2.2", + "vitest": "^4.1.11", "vitest-browser-react": "^2.2.0" }, "allowScripts": { diff --git a/scripts/build-dm.ts b/scripts/build-dm.ts index 9b56e93..034225f 100644 --- a/scripts/build-dm.ts +++ b/scripts/build-dm.ts @@ -1,24 +1,14 @@ -import { join } from 'node:path'; -import manifest from '../node_modules/igniteui-dockmanager/custom-elements.json'; -import pkg from '../node_modules/igniteui-dockmanager/package.json'; -import type { ClassField, Package } from './schema'; -import { type CustomElementWithPath, getPackageJsonTypesEntry, wrapWebComponents } from './utils'; +import { defineWrapperConfig } from './config'; -const pkgScope = process.env.IG_LICENSED_BUILD ? '@infragistics/' : ''; -const config = { +export default defineWrapperConfig({ path: '../src/dock-manager', - imports: { - default: `${pkgScope}igniteui-dockmanager`, - types: `${pkgScope}igniteui-dockmanager`, - }, + package: 'igniteui-dockmanager', + scoped: true, types: { - entry: join('node_modules/igniteui-dockmanager', getPackageJsonTypesEntry(pkg)), - ignoreExports: new Set([ - // Now deprecated, so keeping previous ignore for React until removed - 'addResourceStrings', - ]), + // Now deprecated, so keeping previous ignore for React until removed + ignoreExports: ['addResourceStrings'], }, - ignore: new Set([ + ignore: [ // TODO: Cleanup custom-elements.json... 'igc-button-component', 'igc-context-menu', @@ -40,10 +30,6 @@ const config = { 'igc-split-pane', 'igc-splitter-component', 'igc-unpinned-pane-header', - ]), - ignoreEvents: new Set(), - templatesFilter: (_prop: ClassField, _declaration: CustomElementWithPath) => false, + ], typedocModuleName: 'igniteui-react-dockmanager', -} as const; - -await wrapWebComponents(manifest as Package, config); +}); diff --git a/scripts/build-grid-lite.ts b/scripts/build-grid-lite.ts index 4f876f6..333e7c7 100644 --- a/scripts/build-grid-lite.ts +++ b/scripts/build-grid-lite.ts @@ -1,32 +1,15 @@ -import { join } from 'node:path'; -import manifest from '../node_modules/igniteui-grid-lite/custom-elements.json'; -import pkg from '../node_modules/igniteui-grid-lite/package.json'; -import type { ClassField, Package } from './schema'; -import { type CustomElementWithPath, getPackageJsonTypesEntry, wrapWebComponents } from './utils'; +import { defineWrapperConfig } from './config'; -const config = { +// TODO: Emit wrapped component type alias as: +// export type IgrGridLiteColumn = Component; +export default defineWrapperConfig({ path: '../src/grid-lite', - imports: { - default: 'igniteui-grid-lite', - types: 'igniteui-grid-lite', - }, + package: 'igniteui-grid-lite', types: { - entry: join('node_modules/igniteui-grid-lite', getPackageJsonTypesEntry(pkg)), - ignoreExports: new Set(['defineComponents', 'defineAllComponents']), + ignoreExports: ['defineComponents', 'defineAllComponents'], + }, + renderProps: { + 'igc-grid-lite-column': ['cellTemplate', 'headerTemplate'], }, - ignoreEvents: new Set([]), - ignore: new Set([]), - templates: new Map>( - Object.entries({ - 'igc-grid-lite-column': ['cellTemplate', 'headerTemplate'], - }), - ), - templatesFilter: (prop: ClassField, declaration: CustomElementWithPath) => - config.templates.has(declaration.tagName!) && - config.templates.get(declaration.tagName!)!.includes(prop.name), typedocModuleName: 'igniteui-react/grid-lite', -} as const; - -// TODO: Emit wrapped component type alias as: -// export type IgrGridLiteColumn = Component; -await wrapWebComponents(manifest as Package, config); +}); diff --git a/scripts/build-grids.ts b/scripts/build-grids.ts index fa75076..662fe63 100644 --- a/scripts/build-grids.ts +++ b/scripts/build-grids.ts @@ -1,33 +1,22 @@ -import manifest from '../node_modules/igniteui-webcomponents-grids/custom-elements.json'; -import type { ClassField, Package } from './schema'; -import { type CustomElementWithPath, wrapWebComponents } from './utils'; +import { join } from 'node:path'; +import { defineWrapperConfig } from './config'; +import { NODE_MODULES } from './paths'; const TEMPLATE_TYPE = 'IgcRenderFunction'; -const pkgScope = process.env.IG_LICENSED_BUILD ? '@infragistics/' : ''; -const config = { + +export default defineWrapperConfig({ path: '../src/grids', - imports: { - // TODO: use direct /grids/index.js until package is updated; CRA/Webpack can't resolve (possibly ESM mode) - default: `${pkgScope}igniteui-webcomponents-grids/grids/index.js`, - types: `${pkgScope}igniteui-webcomponents-grids/grids/index.js`, - }, + package: 'igniteui-webcomponents-grids', + // TODO: use direct /grids/index.js until package is updated; CRA/Webpack can't resolve (possibly ESM mode) + specifier: 'igniteui-webcomponents-grids/grids/index.js', + scoped: true, types: { // `/grids` entry not in package.json & not exported from main.d.ts (which also includes DataGrid) - // entry: join('node_modules/igniteui-webcomponents-grids', getPackageJsonTypesEntry(pkg)), - entry: 'node_modules/igniteui-webcomponents-grids/grids/index.d.ts', - ignoreExports: new Set([ - 'defineComponents', - 'defineAllComponents', - TEMPLATE_TYPE, - 'TemplateContent', - ]), + entry: join(NODE_MODULES, 'igniteui-webcomponents-grids/grids/index.d.ts'), + ignoreExports: ['defineComponents', 'defineAllComponents', TEMPLATE_TYPE, 'TemplateContent'], }, - templatesFilter: (prop: ClassField, _declaration: CustomElementWithPath) => - !!prop.type?.text.startsWith(TEMPLATE_TYPE), - ignore: new Set(), - ignoreEvents: new Set(), + // grids expose templates by property type rather than by a known set of names + templatesFilter: (prop) => !!prop.type?.text.startsWith(TEMPLATE_TYPE), moveBackOnDelete: true, typedocModuleName: 'igniteui-react-grids', -} as const; - -await wrapWebComponents(manifest as Package, config); +}); diff --git a/scripts/build-wc.ts b/scripts/build-wc.ts index b73d5ab..490c9f9 100644 --- a/scripts/build-wc.ts +++ b/scripts/build-wc.ts @@ -1,53 +1,34 @@ -import { join } from 'node:path'; -import manifest from '../node_modules/igniteui-webcomponents/custom-elements.json'; -import pkg from '../node_modules/igniteui-webcomponents/package.json'; -import type { ClassField, Package } from './schema'; -import { type CustomElementWithPath, getPackageJsonTypesEntry, wrapWebComponents } from './utils'; +import { defineWrapperConfig } from './config'; -const config = { +export default defineWrapperConfig({ path: '../src/components', - imports: { - default: 'igniteui-webcomponents', - types: 'igniteui-webcomponents', - }, + package: 'igniteui-webcomponents', types: { - entry: join('node_modules/igniteui-webcomponents', getPackageJsonTypesEntry(pkg)), - ignoreExports: new Set([ - 'defineComponents', - 'defineAllComponents', - 'IgcSplitterResizeEventDetail', - ]), + ignoreExports: ['defineComponents', 'defineAllComponents', 'IgcSplitterResizeEventDetail'], }, - ignoreEvents: new Set(['igc-step']), - extraEvents: new Map([ - [ - 'igc-radio-group', - [{ name: 'igcChange', type: { text: '' }, delegateFrom: 'IgcRadioComponent' }], + ignoreEvents: ['igc-step'], + extraEvents: { + 'igc-radio-group': [ + { name: 'igcChange', type: { text: '' }, delegateFrom: 'IgcRadioComponent' }, ], - [ - 'igc-tile-manager', - [ - { name: 'igcTileFullscreen', type: { text: '' }, delegateFrom: 'IgcTileComponent' }, - { name: 'igcTileMaximize', type: { text: '' }, delegateFrom: 'IgcTileComponent' }, - { name: 'igcTileDragStart', type: { text: '' }, delegateFrom: 'IgcTileComponent' }, - { name: 'igcTileDragEnd', type: { text: '' }, delegateFrom: 'IgcTileComponent' }, - { name: 'igcTileDragCancel', type: { text: '' }, delegateFrom: 'IgcTileComponent' }, - { name: 'igcTileResizeStart', type: { text: '' }, delegateFrom: 'IgcTileComponent' }, - { name: 'igcTileResizeEnd', type: { text: '' }, delegateFrom: 'IgcTileComponent' }, - { name: 'igcTileResizeCancel', type: { text: '' }, delegateFrom: 'IgcTileComponent' }, - ], + 'igc-tile-manager': [ + { name: 'igcTileFullscreen', type: { text: '' }, delegateFrom: 'IgcTileComponent' }, + { name: 'igcTileMaximize', type: { text: '' }, delegateFrom: 'IgcTileComponent' }, + { name: 'igcTileDragStart', type: { text: '' }, delegateFrom: 'IgcTileComponent' }, + { name: 'igcTileDragEnd', type: { text: '' }, delegateFrom: 'IgcTileComponent' }, + { name: 'igcTileDragCancel', type: { text: '' }, delegateFrom: 'IgcTileComponent' }, + { name: 'igcTileResizeStart', type: { text: '' }, delegateFrom: 'IgcTileComponent' }, + { name: 'igcTileResizeEnd', type: { text: '' }, delegateFrom: 'IgcTileComponent' }, + { name: 'igcTileResizeCancel', type: { text: '' }, delegateFrom: 'IgcTileComponent' }, ], - [ - 'igc-accordion', - [ - { name: 'igcOpening', type: { text: '' }, delegateFrom: 'IgcExpansionPanelComponent' }, - { name: 'igcOpened', type: { text: '' }, delegateFrom: 'IgcExpansionPanelComponent' }, - { name: 'igcClosing', type: { text: '' }, delegateFrom: 'IgcExpansionPanelComponent' }, - { name: 'igcClosed', type: { text: '' }, delegateFrom: 'IgcExpansionPanelComponent' }, - ], + 'igc-accordion': [ + { name: 'igcOpening', type: { text: '' }, delegateFrom: 'IgcExpansionPanelComponent' }, + { name: 'igcOpened', type: { text: '' }, delegateFrom: 'IgcExpansionPanelComponent' }, + { name: 'igcClosing', type: { text: '' }, delegateFrom: 'IgcExpansionPanelComponent' }, + { name: 'igcClosed', type: { text: '' }, delegateFrom: 'IgcExpansionPanelComponent' }, ], - ]), - ignore: new Set([ + }, + ignore: [ 'igc-popover', 'igc-focus-trap', 'igc-days-view', @@ -55,18 +36,18 @@ const config = { 'igc-years-view', 'igc-carousel-indicator-container', 'igc-validator', - 'igc-resize', 'igc-predefined-ranges-area', 'igc-chat-input', 'igc-chat-message', - 'igc-message-attachments', 'igc-visually-hidden', - ]), - templates: new Map>( - Object.entries({ - 'igc-combo': ['itemTemplate', 'groupHeaderTemplate'], - 'igc-chat': [ - `{ + 'igc-picker-canvas', + ], + renderProps: { + 'igc-combo': ['itemTemplate', 'groupHeaderTemplate'], + 'igc-virtual-scroll': ['itemTemplate'], + }, + rawRenderProps: { + 'igc-chat': `{ "options": { "renderers": { "attachment": "attachment", @@ -89,13 +70,6 @@ const config = { } } }`, - ], - }), - ), - templatesFilter: (prop: ClassField, declaration: CustomElementWithPath) => - config.templates.has(declaration.tagName!) && - config.templates.get(declaration.tagName!)!.includes(prop.name), + }, typedocModuleName: 'igniteui-react', -} as const; - -await wrapWebComponents(manifest as Package, config); +}); diff --git a/scripts/check-manifests.ts b/scripts/check-manifests.ts new file mode 100644 index 0000000..77a23fd --- /dev/null +++ b/scripts/check-manifests.ts @@ -0,0 +1,134 @@ +/** + * Checks that the publish manifests under `scripts/*.package.json` declare dependency + * ranges satisfied by the versions actually installed - and therefore built and tested + * against. + * + * The manifests are hand-maintained separately from the root `package.json`. Bumping a + * dependency for the build without widening the published range ships a package whose + * declared range excludes the code it was compiled against, which surfaces as duplicated + * or mismatched packages in consumer installs. That drift has to be caught before publish, + * not after. + * + * Ranges intentionally stay looser than the root's (a published `lit: ^3.3.0` while + * developing against `3.3.3` is a supported-floor statement), so only satisfaction is + * enforced - not equality. + * + * Usage: `npm run check:manifests` + */ + +import { existsSync } from 'node:fs'; +import { join } from 'node:path'; +import { NODE_MODULES, publishManifests, readJson, SCRIPTS } from './paths'; +import type { PackageJson } from './types'; + +type Version = [major: number, minor: number, patch: number]; + +/** Parses `x.y.z`, ignoring any prerelease/build metadata. */ +function parseVersion(value: string): Version | null { + const match = /^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/.exec(value.trim()); + return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : null; +} + +function compare(a: Version, b: Version): number { + return a[0] - b[0] || a[1] - b[1] || a[2] - b[2]; +} + +/** + * Whether `version` satisfies `range`. + * + * Supports the exact, `~` and `^` forms the publish manifests use. Anything else throws + * rather than silently passing, so an unhandled range can't quietly disable the check. + */ +function satisfies(version: Version, range: string): boolean { + const trimmed = range.trim(); + const operator = trimmed.startsWith('^') || trimmed.startsWith('~') ? trimmed[0] : ''; + const base = parseVersion(operator ? trimmed.slice(1) : trimmed); + + if (!base) { + throw new Error(`Unsupported version range "${range}" - extend satisfies() to handle it.`); + } + + const toBase = compare(version, base); + if (toBase < 0) { + return false; + } + if (!operator) { + return toBase === 0; + } + + const [major, minor, patch] = base; + // `~1.2.3` -> <1.3.0; `^1.2.3` -> <2.0.0, with caret pinned tighter below 1.0.0 + let upper: Version; + if (operator === '~') { + upper = [major, minor + 1, 0]; + } else if (major !== 0) { + upper = [major + 1, 0, 0]; + } else if (minor !== 0) { + upper = [0, minor + 1, 0]; + } else { + upper = [0, 0, patch + 1]; + } + + return compare(version, upper) < 0; +} + +/** + * The version of `name` currently installed under `node_modules`. + * + * Read straight off disk rather than through `require`, since several of these packages + * don't expose `./package.json` in their `exports`. + */ +function installedVersion(name: string): string | null { + const file = join(NODE_MODULES, name, 'package.json'); + return existsSync(file) ? (readJson(file).version ?? null) : null; +} + +function checkManifest(file: string): string[] { + const manifest = readJson(join(SCRIPTS, file)); + const errors: string[] = []; + + const declared = { + ...manifest.dependencies, + ...manifest.peerDependencies, + }; + + for (const [name, range] of Object.entries(declared)) { + const installed = installedVersion(name); + + if (!installed) { + errors.push(`${manifest.name}: "${name}" is published but not installed - cannot verify.`); + continue; + } + + const version = parseVersion(installed); + if (!version) { + errors.push(`${manifest.name}: cannot parse installed version "${installed}" of ${name}.`); + continue; + } + + if (!satisfies(version, range)) { + errors.push( + `${manifest.name}: "${name}": "${range}" does not allow the installed ${installed}. ` + + 'Widen the range in the publish manifest or align the root dependency.', + ); + } + } + + return errors; +} + +const manifests = publishManifests(); +const errors = manifests.flatMap(checkManifest); + +for (const error of errors) { + console.error(` ✗ ${error}`); +} + +if (errors.length) { + console.error('\nPublish manifest check failed.'); + process.exit(1); +} + +console.log( + `Publish manifests are consistent with installed versions (${manifests.length} checked).`, +); diff --git a/scripts/components.package.json b/scripts/components.package.json index 5781af2..d77d47c 100644 --- a/scripts/components.package.json +++ b/scripts/components.package.json @@ -29,11 +29,11 @@ }, "dependencies": { "@lit/react": "^1.0.7", - "igniteui-webcomponents": "~7.2.1", + "igniteui-webcomponents": "~7.3.1", "lit": "^3.3.0" }, "peerDependencies": { - "igniteui-grid-lite": "~0.9.0" + "igniteui-grid-lite": "~0.10.0" }, "peerDependenciesMeta": { "igniteui-grid-lite": { diff --git a/scripts/config.ts b/scripts/config.ts new file mode 100644 index 0000000..9cbed35 --- /dev/null +++ b/scripts/config.ts @@ -0,0 +1,103 @@ +import { join } from 'node:path'; +import { NODE_MODULES, readJson } from './paths'; +import type { ClassField } from './schema'; +import type { PackageDelegateEvent, PackageJson } from './types'; +import { + type CustomElementWithPath, + getPackageJsonTypesEntry, + type WebComponentsConfig, +} from './utils'; + +/** Scope prefix for the packages republished under `@infragistics` in licensed builds. */ +const LICENSED_SCOPE = process.env.IG_LICENSED_BUILD ? '@infragistics/' : ''; + +/** Resolves the declaration entry of an installed package from its `package.json`. */ +function typesEntry(name: string): string { + const pkg = readJson(join(NODE_MODULES, name, 'package.json')); + return join(NODE_MODULES, name, getPackageJsonTypesEntry(pkg)); +} + +type WrapperConfigInput = Pick< + WebComponentsConfig, + 'path' | 'moveBackOnDelete' | 'typedocModuleName' +> & { + /** Directory of the package under `node_modules`; the manifest and types are read from it. */ + readonly package: string; + /** Bare specifier the wrappers import from. Defaults to the package name. */ + readonly specifier?: string; + /** + * Whether the package is republished under the `@infragistics` scope, in which case the + * scope is prepended to the emitted specifiers for licensed builds. + */ + readonly scoped?: boolean; + readonly types: { + /** Declaration entry point. Defaults to the one the package's `package.json` declares. */ + readonly entry?: string; + readonly ignoreExports?: readonly string[]; + }; + /** Component tag names to skip entirely. */ + readonly ignore?: readonly string[]; + /** Component tag names whose events should not be wired up. */ + readonly ignoreEvents?: readonly string[]; + /** Events delegated from child components, which the manifest does not list. */ + readonly extraEvents?: Readonly>; + /** Template member names per component tag name. */ + readonly renderProps?: Readonly>; + /** Render props emitted verbatim; see {@link WebComponentsConfig.rawRenderProps}. */ + readonly rawRenderProps?: Readonly>; + /** + * Detects template members by inspecting the member itself, for packages that mark + * templates by property type rather than by a known set of names. Mutually exclusive + * with {@link WrapperConfigInput.renderProps}. + */ + readonly templatesFilter?: (prop: ClassField, declaration: CustomElementWithPath) => boolean; +}; + +/** + * Fills in the defaults for a generator config, so each `build-*.ts` only declares what is + * actually specific to its package. + */ +export function defineWrapperConfig(input: WrapperConfigInput): WebComponentsConfig { + const { + package: pkg, + specifier, + scoped, + types, + ignore, + ignoreEvents, + extraEvents, + ...rest + } = input; + const { renderProps, rawRenderProps, templatesFilter, ...common } = rest; + + if (templatesFilter && renderProps) { + throw new Error( + `${pkg}: use either "renderProps" or "templatesFilter" - the predicate would shadow the names.`, + ); + } + + const names = new Map(Object.entries(renderProps ?? {})); + const raw = new Map(Object.entries(rawRenderProps ?? {})); + + const both = [...names.keys()].filter((tag) => raw.has(tag)); + if (both.length) { + throw new Error(`${pkg}: ${both.join(', ')} set both "renderProps" and "rawRenderProps".`); + } + + const scopedSpecifier = `${scoped ? LICENSED_SCOPE : ''}${specifier ?? pkg}`; + + return { + ...common, + manifest: join(NODE_MODULES, pkg, 'custom-elements.json'), + imports: { default: scopedSpecifier, types: scopedSpecifier }, + types: { entry: types.entry ?? typesEntry(pkg), ignoreExports: new Set(types.ignoreExports) }, + ignore: new Set(ignore), + ignoreEvents: new Set(ignoreEvents), + extraEvents: extraEvents && new Map(Object.entries(extraEvents)), + rawRenderProps: raw.size ? raw : undefined, + renderPropNames: new Set(names.keys()), + isTemplate: + templatesFilter ?? + ((prop, declaration) => !!names.get(declaration.tagName)?.includes(prop.name)), + }; +} diff --git a/scripts/generate.ts b/scripts/generate.ts new file mode 100644 index 0000000..774f231 --- /dev/null +++ b/scripts/generate.ts @@ -0,0 +1,84 @@ +/** + * Generates the React wrappers for every Ignite UI package. + * + * Usage: + * tsx ./scripts/generate.ts # all packages + * tsx ./scripts/generate.ts wc grid-lite # only the given ones + */ + +import { readJson } from './paths'; +import type { Package } from './schema'; +import { getExports } from './typescript-utils'; +import { type WebComponentsConfig, type WrapResult, wrapWebComponents } from './utils'; + +type Target = { default: WebComponentsConfig }; + +/** Package configs, loaded lazily so a partial run only imports what it needs. */ +const TARGETS: Record Promise> = { + wc: () => import('./build-wc'), + dm: () => import('./build-dm'), + grids: () => import('./build-grids'), + 'grid-lite': () => import('./build-grid-lite'), +}; + +function parseTargets(argv: string[]): string[] { + if (!argv.length) { + return Object.keys(TARGETS); + } + + const unknown = argv.filter((name) => !(name in TARGETS)); + if (unknown.length) { + console.error( + `Unknown target(s): ${unknown.join(', ')}. Valid targets: ${Object.keys(TARGETS).join(', ')}`, + ); + process.exit(1); + } + + return argv; +} + +function report(result: WrapResult): void { + console.log( + ` ${result.name.padEnd(14)} ${String(result.components).padStart(3)} components, ` + + `${String(result.typeExports).padStart(3)} type exports ` + + `(${(result.duration / 1000).toFixed(2)}s)`, + ); +} + +const targets = parseTargets(process.argv.slice(2)); +const started = performance.now(); + +const configs = await Promise.all(targets.map(async (name) => (await TARGETS[name]()).default)); + +// One TypeScript program for every entry - the packages share most of their declaration +// closure, so resolving them together roughly halves the parsing. +const resolving = performance.now(); +const pkgExports = getExports(configs.map((config) => config.types.entry)); +console.log(` resolved type exports (${((performance.now() - resolving) / 1000).toFixed(2)}s)`); + +const outcomes = await Promise.allSettled( + configs.map((config) => + wrapWebComponents( + readJson(config.manifest), + config, + pkgExports.get(config.types.entry)!, + ), + ), +); + +for (const [index, outcome] of outcomes.entries()) { + if (outcome.status === 'fulfilled') { + report(outcome.value); + } else { + console.error(` \u2717 ${targets[index]} failed:`, outcome.reason); + } +} + +const total = `${((performance.now() - started) / 1000).toFixed(2)}s`; + +if (outcomes.some((outcome) => outcome.status === 'rejected')) { + console.error(`\nWrapper generation failed after ${total}.`); + process.exit(1); +} + +console.log(`\nGenerated wrappers for ${targets.length} package(s) in ${total}.`); diff --git a/scripts/npm-packlist.d.ts b/scripts/npm-packlist.d.ts new file mode 100644 index 0000000..88f1eff --- /dev/null +++ b/scripts/npm-packlist.d.ts @@ -0,0 +1,19 @@ +/** + * Minimal ambient types for `npm-packlist`, which ships untyped. + * Only the surface `validate-dist.ts` uses is declared. + */ +declare module 'npm-packlist' { + /** The arborist-style tree npm-packlist reads the `files` allowlist from. */ + export interface PacklistTree { + /** Parsed `package.json` of the package being packed. */ + package: object; + /** Absolute path to the package root. */ + path: string; + isProjectRoot?: boolean; + /** Dependency edges; empty for packages without bundled deps. */ + edgesOut?: Map; + } + + /** Resolves the paths, relative to the package root, that `npm pack` would include. */ + export default function packlist(tree: PacklistTree): Promise; +} diff --git a/scripts/paths.ts b/scripts/paths.ts new file mode 100644 index 0000000..6c6c3cd --- /dev/null +++ b/scripts/paths.ts @@ -0,0 +1,23 @@ +import { readdirSync, readFileSync } from 'node:fs'; +import { join, resolve } from 'node:path'; + +export const ROOT = resolve(import.meta.dirname, '..'); +export const SCRIPTS = join(ROOT, 'scripts'); +export const DIST = join(ROOT, 'dist'); +export const NODE_MODULES = join(ROOT, 'node_modules'); + +/** + * The publish manifests under `scripts/`, sorted so the order is stable across platforms. + * + * Discovered rather than listed, so a new package can't be picked up by one publish gate + * and silently skipped by the other. + */ +export function publishManifests(): string[] { + return readdirSync(SCRIPTS) + .filter((file) => file.endsWith('.package.json')) + .sort(); +} + +export function readJson(file: string): T { + return JSON.parse(readFileSync(file, 'utf8')) as T; +} diff --git a/scripts/tsconfig.json b/scripts/tsconfig.json new file mode 100644 index 0000000..6a5d670 --- /dev/null +++ b/scripts/tsconfig.json @@ -0,0 +1,22 @@ +// Type-checks the build tooling, which the root tsconfig (src only) never covered. +// Also covers vite.config.ts, the one other build file outside src. +{ + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "lib": ["ESNext"], + "moduleResolution": "bundler", + "types": ["node"], + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "esModuleInterop": true, + "skipLibCheck": true, + "noEmit": true, + + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["**/*.ts", "../vite.config.ts"] +} diff --git a/scripts/types.ts b/scripts/types.ts index d8439ad..ceaf1d2 100644 --- a/scripts/types.ts +++ b/scripts/types.ts @@ -4,10 +4,15 @@ export type PackageDelegateEvent = PackageEvent & { delegateFrom?: string }; export type ExportMeta = { name: string; type: 'js' | 'type' }; -/** Very basic typing for package.json just to access types entries */ -export type PackageJsonTypes = { +/** Partial `package.json`, covering only the fields the build scripts read. */ +export type PackageJson = { name: string; + version?: string; + main?: string; + module?: string; types?: string; typings?: string; exports?: { [key: string]: { types?: string } | string } | string; + dependencies?: Record; + peerDependencies?: Record; }; diff --git a/scripts/typescript-utils.ts b/scripts/typescript-utils.ts index 32ecd70..05da78d 100644 --- a/scripts/typescript-utils.ts +++ b/scripts/typescript-utils.ts @@ -1,4 +1,3 @@ -import { glob } from 'glob'; import { createProgram, isExportSpecifier, @@ -10,27 +9,41 @@ import { import type { ExportMeta } from './types'; /** - * Resolves exports meta for an entry - * @param entry path to declaration entry point + * Resolves the exports of each declaration entry, keyed by entry path. + * + * @remarks + * One program covers every entry. The packages share most of their declaration closure + * (lit, `@lit/react`, and the components package itself, which the grid packages pull in), + * so a program per entry re-parses roughly half the graph - measurably about twice the work. + * + * Only the entry is needed to enumerate a module's exports; the wrappers under `src/` are + * generated *from* this data, so including them only made the program grow with every + * package that had already run. */ -export async function getExports(entry: string): Promise { - // grab any and all files under src that reference wc packages - const files = await glob('src/**/*{.ts,.tsx}'); - // add entry to ensure package is resolved if no file picks it up - files.push(entry); - // default options will also load the root tsconfig - const program = createProgram(files, {}); +export function getExports(entries: string[]): Map { + const program = createProgram(entries, {}); const checker = program.getTypeChecker(); - const entrySource = program.getSourceFile(entry); - const entrySymbol = entrySource && checker.getSymbolAtLocation(entrySource); - if (entrySymbol) { - return checker.getExportsOfModule(entrySymbol).map((x) => { - // try to respect both package export specifiers and types that just transpile away: - const type = isTypeOnlyExport(x) || wouldBeElided(x, checker) ? 'type' : 'js'; - return { name: x.name, type }; - }); + const resolved = new Map(); + + for (const entry of entries) { + const source = program.getSourceFile(entry); + const symbol = source && checker.getSymbolAtLocation(source); + + if (!symbol) { + throw new Error(`Failed to resolve types entry "${entry}". Are dependencies installed?`); + } + + resolved.set( + entry, + checker.getExportsOfModule(symbol).map((x) => ({ + name: x.name, + // try to respect both package export specifiers and types that just transpile away: + type: isTypeOnlyExport(x) || wouldBeElided(x, checker) ? 'type' : 'js', + })), + ); } - return []; + + return resolved; } /** diff --git a/scripts/utils.ts b/scripts/utils.ts index cc1ac34..077ad1e 100644 --- a/scripts/utils.ts +++ b/scripts/utils.ts @@ -1,8 +1,7 @@ -import { mkdir, writeFile } from 'node:fs/promises'; -import { join } from 'node:path'; +import { mkdir, rm, writeFile } from 'node:fs/promises'; +import { basename, join } from 'node:path'; import { fileURLToPath } from 'node:url'; import { format, type Options } from 'prettier'; -import { rimraf } from 'rimraf'; import type { ClassField, ClassMember, @@ -11,8 +10,7 @@ import type { Package, Event as PackageEvent, } from './schema'; -import type { ExportMeta, PackageDelegateEvent, PackageJsonTypes } from './types'; -import { getExports } from './typescript-utils'; +import type { ExportMeta, PackageDelegateEvent, PackageJson } from './types'; /** * CustomElementDeclaration with a `path` property added for convenience @@ -33,42 +31,48 @@ export interface CustomElementWithPath extends CustomElementDeclaration { /** * Returns whether the given declaration is an actual custom element */ -function isCustomElement(declaration: Declaration): declaration is CustomElementDeclaration { +function isCustomElement( + declaration: Declaration, +): declaration is CustomElementDeclaration & { tagName: string } { return declaration.kind === 'class' && 'tagName' in declaration; } /** * Returns whether the given declaration member is a field */ -export function isField(member: ClassMember): member is ClassField { +function isField(member: ClassMember): member is ClassField { return member.kind === 'field'; } -export function hasEvents(events?: PackageEvent[]): events is PackageEvent[] { - return !!events?.filter((x) => x.name).length; +function hasEvents(events?: T[]): events is T[] { + return !!events?.some((x) => x.name); } -export function isNonNullable(x: any): x is NonNullable { +function isNonNullable(x: T): x is NonNullable { return x !== null && x !== undefined; } -export function indent(string: string) { +function indent(string: string) { return string.replace(/^(.*)/, '* $1'); } -export function toReactName(string: string) { +function toReactName(string: string) { return string.replace(/^Igc/, 'Igr').replace(/Component$/, ''); } -export function toReactEventName(string: string) { +function toReactEventName(string: string) { const name = string.replace(/^igc/, ''); return `on${name.at(0)?.toLocaleUpperCase()}${name.slice(1)}`; } /** Gets either the main export entry (`'.'`) or root types/typings path*/ -export function getPackageJsonTypesEntry(pkg: PackageJsonTypes): string { +export function getPackageJsonTypesEntry(pkg: PackageJson): string { + // `exports` may be a bare specifier string, in which case there is no `.` condition to read + const mainExport = typeof pkg.exports === 'object' ? pkg.exports['.'] : undefined; + const mainTypes = typeof mainExport === 'object' ? mainExport.types : undefined; + // either main entry or root types - const entry = pkg.exports?.['.']?.types || pkg.types || pkg.typings; + const entry = mainTypes || pkg.types || pkg.typings; if (!entry) { throw new Error(`Failed to get types entry from ${pkg.name}'s package.json`); } @@ -77,22 +81,18 @@ export function getPackageJsonTypesEntry(pkg: PackageJsonTypes): string { /** * Parses a custom-elements.json file and returns all custom elements from it + * + * @remarks + * Declarations are copied rather than augmented in place - the manifest is an imported JSON + * module shared for the lifetime of the process and must stay pristine. */ -export function parseElementsJSON(json: Package) { - return json.modules - .flatMap(({ declarations, path }) => { - if (!declarations) { - return null; - } - - return declarations.flatMap((declaration) => { - return isCustomElement(declaration) ? Object.assign(declaration, { path }) : null; - }); - }) - .filter((declaration) => Boolean(declaration)) as CustomElementWithPath[]; +function parseElementsJSON(json: Package): CustomElementWithPath[] { + return json.modules.flatMap(({ declarations, path }) => + (declarations ?? []).filter(isCustomElement).map((declaration) => ({ ...declaration, path })), + ); } -export function createJSDoc({ +function createJSDoc({ description, events, slots, @@ -140,32 +140,42 @@ export function createJSDoc({ export type WebComponentsConfig = { readonly path: string; + /** Absolute path to the package's `custom-elements.json`. */ + readonly manifest: string; readonly imports: { readonly default: string; readonly types: string; }; readonly types: { readonly entry: string; - readonly ignoreExports: Set; + readonly ignoreExports: ReadonlySet; }; - readonly ignoreEvents: Set; - readonly extraEvents?: Map; - readonly ignore: Set; - readonly templatesFilter: (prop: ClassField, declaration: CustomElementWithPath) => boolean; + readonly ignoreEvents: ReadonlySet; + readonly extraEvents?: ReadonlyMap; + readonly ignore: ReadonlySet; + /** + * Render props emitted verbatim, per component tag name, for renderers whose shape the + * generated `{ prop: 'prop' }` map can't express (e.g. `igc-chat`'s nested renderers). + */ + readonly rawRenderProps?: ReadonlyMap; + /** + * Identifies the template members of a declaration. Resolved by `defineWrapperConfig`, + * either from the configured render-prop names or from an explicit predicate. + */ + readonly isTemplate: (prop: ClassField, declaration: CustomElementWithPath) => boolean; + /** Tags that configured render props by name, kept so they can be checked for staleness. */ + readonly renderPropNames: ReadonlySet; readonly moveBackOnDelete?: boolean; readonly typedocModuleName?: string; }; -export function createEvents( - { events, name: component, tagName }: CustomElementWithPath, - config: WebComponentsConfig, -) { +function createEvents(declaration: CustomElementWithPath, config: WebComponentsConfig) { + const { name: component, tagName } = declaration; const buffer: string[] = []; - if (config.extraEvents?.has(tagName)) { - events ??= []; - events.push(...config.extraEvents.get(tagName)!); - } + // build a new array - pushing would mutate the shared manifest declaration + const extraEvents = config.extraEvents?.get(tagName); + const events = extraEvents ? [...(declaration.events ?? []), ...extraEvents] : declaration.events; if (hasEvents(events) && !config.ignoreEvents.has(tagName)) { for (const { name, delegateFrom } of events) { @@ -180,7 +190,7 @@ export function createEvents( return buffer.length ? `events: {${buffer.join(',\n')}},` : ''; } -export function createImports( +function createImports( { name, events, tagName }: CustomElementWithPath, config: WebComponentsConfig, ) { @@ -193,30 +203,41 @@ export function createImports( if (hasEvents(events) && !config.ignoreEvents.has(tagName)) { eventMaps.push(`${name}EventMap`); } - if (config.extraEvents?.has(tagName)) { - eventMaps?.push( - ...new Set( - config.extraEvents - .get(tagName)! - .map((x) => x.delegateFrom?.concat('EventMap')) - .filter(isNonNullable), - ), + const extraEvents = config.extraEvents?.get(tagName); + if (extraEvents) { + eventMaps.push( + ...new Set(extraEvents.map((x) => x.delegateFrom?.concat('EventMap')).filter(isNonNullable)), ); } - eventMaps.length - ? buffer.push( - ...[ - `import type { ${eventMaps.join(', ')} } from '${config.imports.types}'`, - "import { type EventName, createComponent} from '../react-props.js'", - ], - ) - : buffer.push("import { createComponent } from '../react-props.js'"); + if (eventMaps.length) { + buffer.push( + `import type { ${eventMaps.join(', ')} } from '${config.imports.types}'`, + "import { type EventName, createComponent} from '../react-props.js'", + ); + } else { + buffer.push("import { createComponent } from '../react-props.js'"); + } return buffer.join('\n'); } -export function createTypeExports( +function createTemplates(declaration: CustomElementWithPath, config: WebComponentsConfig) { + const raw = config.rawRenderProps?.get(declaration.tagName); + if (raw) { + return `renderProps: ${raw}`; + } + + const templateProps = (declaration.members ?? []).filter( + (member): member is ClassField => isField(member) && config.isTemplate(member, declaration), + ); + + const buffer = templateProps.map((prop) => `${prop.name}: '${prop.name}'`); + + return buffer.length ? `renderProps: {${buffer.join(',\n')}}` : ''; +} + +function createTypeExports( pkgExports: ExportMeta[], ignore: string[], config: WebComponentsConfig, @@ -234,14 +255,8 @@ export function createTypeExports( return name.startsWith('Igc'); } - function toAlias(name: string, force = false) { - if (shouldAlias(name)) { - return name.replace('Igc', 'Igr'); - } - if (force) { - return `Igr${name}`; - } - return name; + function toAlias(name: string) { + return shouldAlias(name) ? name.replace('Igc', 'Igr') : name; } for (const { name, type } of relevantExports) { @@ -251,7 +266,7 @@ export function createTypeExports( // Separate event args handling; TODO: mark such types with some meta if (name.endsWith('EventArgs')) { - const alias = toAlias(name, false); + const alias = toAlias(name); imports.push(`${typeKeyword}${name} as ${alias}Detail`); eventArgs.push(alias); exports.push(`${typeKeyword}${alias}Detail`); @@ -281,15 +296,7 @@ export function createTypeExports( return buffer.join('\n'); } -type ImportRendererParams = (declaration: CustomElementWithPath, config: T) => string; - -export function createFileContent( - declaration: CustomElementWithPath, - eventRenderer: ImportRendererParams, - importRenderer: ImportRendererParams, - templateRenderer: ImportRendererParams, - config: T, -) { +function createFileContent(declaration: CustomElementWithPath, config: WebComponentsConfig) { const name = toReactName(declaration.name); // TODO: Conditional? Not all components had modules exposed, but CEM doesn't have that meta @@ -299,12 +306,12 @@ export function createFileContent( const extraProps = [ config.moveBackOnDelete ? 'moveBackOnDelete: true,' : '', - eventRenderer(declaration, config), - templateRenderer(declaration, config), + createEvents(declaration, config), + createTemplates(declaration, config), ].filter((x) => x); return ` - ${importRenderer(declaration, config)} + ${createImports(declaration, config)} ${createJSDoc(declaration)} export const ${name} = /* @__PURE__ */ createComponent({ @@ -321,7 +328,7 @@ export function createFileContent( } /** Format source with prettier */ -export function formatSource(source: string) { +function formatSource(source: string) { const prettierConfig: Options = { parser: 'babel-ts', singleQuote: true, @@ -330,72 +337,91 @@ export function formatSource(source: string) { return format(source, prettierConfig); } -/** Main entry point generating wrapped component files from config */ -export async function wrapWebComponents(manifest: Package, config: WebComponentsConfig) { - const buffer: string[] = []; - const root = fileURLToPath(new URL(config.path, import.meta.url)); - - function createTemplates(declaration: CustomElementWithPath, config: WebComponentsConfig) { - const buffer: string[] = []; - const templateProps = - declaration.members?.filter((x) => isField(x) && config.templatesFilter(x, declaration)) || - []; - - if (declaration.tagName === 'igc-chat' && 'templates' in config) { - buffer.push(`renderProps: ${(config.templates as any).get(declaration.tagName)}`); - return buffer.join(',\n'); - } +/** Result of a single package generation pass, for build reporting. */ +export type WrapResult = { + /** Output directory name, e.g. `components`. */ + readonly name: string; + /** Number of wrapped components written. */ + readonly components: number; + /** Number of type exports re-exported from `types.ts`. */ + readonly typeExports: number; + /** Wall-clock duration in milliseconds. */ + readonly duration: number; +}; - for (const prop of templateProps) { - buffer.push(`${prop.name}: '${prop.name}'`); +/** + * Reports configured tag names that match no declaration in the manifest. + * + * The config is a set of unchecked references into the manifest, so an upstream rename or + * removal leaves entries behind silently - a stale `ignore` is harmless, but a stale + * `renderProps` or `extraEvents` key means that component quietly loses them. + */ +function reportStaleTags(config: WebComponentsConfig, declared: Set): void { + const configured = new Map>([ + ['ignore', config.ignore], + ['ignoreEvents', config.ignoreEvents], + ['extraEvents', config.extraEvents?.keys() ?? []], + ['rawRenderProps', config.rawRenderProps?.keys() ?? []], + ['renderProps', config.renderPropNames], + ]); + + for (const [field, tags] of configured) { + const stale = [...tags].filter((tag) => !declared.has(tag)); + if (stale.length) { + console.warn(` ! ${basename(config.path)}: ${field} has no such tag: ${stale.join(', ')}`); } - - return buffer.length ? `renderProps: {${buffer.join(',\n')}}` : ''; } +} - function getPaths(declaration: CustomElementWithPath) { - const fileName = declaration.tagName.replace(/^igc-/, ''); - return { - filePath: join(root, `${fileName}.ts`), - importPath: `./${fileName}.js`, - }; - } +/** Generates the wrapped component files for one package. */ +export async function wrapWebComponents( + manifest: Package, + config: WebComponentsConfig, + pkgExports: ExportMeta[], +): Promise { + const started = performance.now(); + const root = fileURLToPath(new URL(config.path, import.meta.url)); - await rimraf(root); + await rm(root, { recursive: true, force: true }); await mkdir(root, { recursive: true }); - const components = parseElementsJSON(manifest).filter( - (declaration) => !config.ignore.has(declaration.tagName), - ); + const declarations = parseElementsJSON(manifest); + reportStaleTags(config, new Set(declarations.map((declaration) => declaration.tagName))); - buffer.push(`/** - * @module ${config.typedocModuleName} - */`); + const components = declarations.filter((declaration) => !config.ignore.has(declaration.tagName)); const files = await Promise.all( - components.map(async (declaration) => { - const { filePath, importPath } = getPaths(declaration); - - buffer.push(`export * from '${importPath}'`); - const fileContent = await formatSource( - createFileContent(declaration, createEvents, createImports, createTemplates, config), - ); - - return { filePath, fileContent }; - }), + components.map(async (declaration) => ({ + fileName: declaration.tagName.replace(/^igc-/, ''), + content: await formatSource(createFileContent(declaration, config)), + })), ); - // types: - const pkgExports = await getExports(config.types.entry); - const typesContent = createTypeExports( + const types = createTypeExports( pkgExports, [...components.map((c) => c.name), ...config.types.ignoreExports], config, ); - await writeFile(join(root, 'types.ts'), await formatSource(typesContent), 'utf8'); - // TODO: split direct exports and export type: - buffer.push(`export * from './types.js';`); - await Promise.all(files.map(async (data) => writeFile(data.filePath, data.fileContent, 'utf8'))); - await writeFile(join(root, 'index.ts'), await formatSource(buffer.join('\n')), 'utf8'); + const index = [ + `/**\n * @module ${config.typedocModuleName}\n */`, + ...files.map(({ fileName }) => `export * from './${fileName}.js'`), + // TODO: split direct exports and export type: + `export * from './types.js';`, + ].join('\n'); + + await Promise.all([ + ...files.map(({ fileName, content }) => + writeFile(join(root, `${fileName}.ts`), content, 'utf8'), + ), + formatSource(types).then((source) => writeFile(join(root, 'types.ts'), source, 'utf8')), + formatSource(index).then((source) => writeFile(join(root, 'index.ts'), source, 'utf8')), + ]); + + return { + name: basename(root), + components: components.length, + typeExports: pkgExports.length, + duration: performance.now() - started, + }; } diff --git a/scripts/validate-dist.ts b/scripts/validate-dist.ts index 735d58a..8b8e5df 100644 --- a/scripts/validate-dist.ts +++ b/scripts/validate-dist.ts @@ -27,19 +27,13 @@ import { execSync } from 'node:child_process'; import { copyFileSync, existsSync, readFileSync, rmSync, writeFileSync } from 'node:fs'; -import { join, resolve } from 'node:path'; +import { join } from 'node:path'; import packlist from 'npm-packlist'; -import type { PackageJsonTypes } from './types'; +import { DIST, publishManifests, ROOT, readJson, SCRIPTS } from './paths'; +import type { PackageJson } from './types'; -const ROOT = resolve(import.meta.dirname, '..'); -const DIST = join(ROOT, 'dist'); const DIST_PKG = join(DIST, 'package.json'); -/** Manifests published from `dist/`, in the same order as the release pipeline. */ -const MANIFESTS = ['components.package.json', 'dock-manager.package.json', 'grids.package.json']; - -let failed = false; - /** Collect every string leaf from a nested `exports` value. */ function collectStrings(value: unknown, out: string[]): void { if (typeof value === 'string') { @@ -56,17 +50,16 @@ async function packedFiles(manifest: object): Promise> { // npm-packlist reads the allowlist from an in-memory tree; these packages // have no bundled deps, so a minimal tree (empty edgesOut) is all it needs. const tree = { package: manifest, path: DIST, isProjectRoot: true, edgesOut: new Map() }; - const files = (await packlist(tree)) as string[]; + const files = await packlist(tree); return new Set(files.map((file) => file.replace(/\\/g, '/'))); } -async function validate(manifest: string): Promise { - copyFileSync(join(ROOT, 'scripts', manifest), DIST_PKG); - const pkg = JSON.parse(readFileSync(DIST_PKG, 'utf8')) as PackageJsonTypes & { - main?: string; - module?: string; - }; +/** Returns whether the package described by `manifest` is publishable as built. */ +async function validate(manifest: string): Promise { + copyFileSync(join(SCRIPTS, manifest), DIST_PKG); + const pkg = readJson(DIST_PKG); console.log(`\n=== ${pkg.name} ===`); + let ok = true; // 1. attw: types + their JS must resolve for every entrypoint. try { @@ -75,7 +68,7 @@ async function validate(manifest: string): Promise { stdio: 'inherit', }); } catch { - failed = true; + ok = false; } // 2. Backstop: every JS entrypoint must be in the published file set. @@ -88,9 +81,11 @@ async function validate(manifest: string): Promise { } if (!packed.has(target.replace(/^\.\//, ''))) { console.error(` ✗ JS entry "${target}" is not in the published files.`); - failed = true; + ok = false; } } + + return ok; } async function main(): Promise { @@ -100,9 +95,10 @@ async function main(): Promise { } const backup = existsSync(DIST_PKG) ? readFileSync(DIST_PKG) : null; + let failed = false; try { - for (const manifest of MANIFESTS) { - await validate(manifest); + for (const manifest of publishManifests()) { + failed = !(await validate(manifest)) || failed; } } finally { if (backup) { diff --git a/tests/web-components/Chat.spec.tsx b/tests/web-components/Chat.spec.tsx index 2081e11..8c55337 100644 --- a/tests/web-components/Chat.spec.tsx +++ b/tests/web-components/Chat.spec.tsx @@ -43,41 +43,30 @@ test('Markdown support with default renderer', async () => { await userEvent.fill(input, '# Hello world'); await userEvent.keyboard('{Enter}'); - const messages = page.getByPart('message-item').all(); - expect(messages.length).toBe(2); - - // The default renderer is async so wait for the DOM to be ready - await nextFrame(); + await expect.poll(() => page.getByPart('message-item').all().length).toBe(2); + // The default renderer is async - assert on the rendered result rather than waiting a + // fixed number of frames. Shiki in particular resolves its grammar and theme lazily, so + // a single animation frame is not always enough for the highlighted block to appear. let message = page.getByText('Hello world'); - - expect(message).toBeVisible(); + await expect.element(message).toBeVisible(); expect(message.element().tagName).toMatch(/h1/i); await userEvent.fill(input, '```ts\nconst chat = document.createElement("igc-chat");\n```'); await userEvent.keyboard('{Enter}'); - await nextFrame(); message = page.getByText(/^const/); - expect(message).toBeVisible(); - - const shikiContainer = message.element().closest('pre'); - expect(shikiContainer?.classList.contains('shiki')).to.be.true; - expect(shikiContainer?.classList.contains('shiki')).to.be.true; + await expect.element(message).toBeVisible(); + await expect.poll(() => message.query()?.closest('pre')?.classList.contains('shiki')).toBe(true); await userEvent.fill(input, 'Powered by [Infragistics](https://infragistics.com/)'); await userEvent.keyboard('{Enter}'); - await nextFrame(); message = page.getByText(/Infragistics/); - expect(message).toBeVisible(); + await expect.element(message).toBeVisible(); expect(message.element().tagName).toMatch(/a/i); }); -async function nextFrame() { - return new Promise((resolve) => requestAnimationFrame(resolve)); -} - //#region Locator extension locators.extend({ getByPart(part: string) {