diff --git a/.github/workflows/audit-docs.yml b/.github/workflows/audit-docs.yml new file mode 100644 index 000000000..01c89e140 --- /dev/null +++ b/.github/workflows/audit-docs.yml @@ -0,0 +1,70 @@ +# Diffs the dropins-mcp registry against the microsite MDX documentation files +# and opens a PR with a DOCS-GAPS.md report when gaps are found. +# +# Runs automatically on a weekly schedule (Mondays) and can be triggered manually. +# Requires @dropins/mcp to be installed as a devDependency (provides the registry). + +name: Audit Documentation Coverage + +on: + workflow_dispatch: + schedule: + # Mondays 07:00 UTC + - cron: "0 7 * * 1" + +concurrency: + group: audit-docs + cancel-in-progress: true + +permissions: + contents: write + pull-requests: write + +jobs: + audit: + runs-on: ubuntu-latest + + steps: + - name: Checkout microsite + uses: actions/checkout@v4 + + - name: Install pnpm + uses: pnpm/action-setup@v3 + with: + version: 10 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version-file: ".nvmrc" + cache: "pnpm" + + - name: Install dependencies + run: pnpm install + + - name: Run doc audit + run: | + # Exit 1 means gaps found (expected); any other non-zero exit is a real error. + pnpm run audit:docs --output-path DOCS-GAPS.md || \ + { code=$?; [ $code -eq 1 ] && exit 0 || exit $code; } + + - name: Open or update PR with gap report + uses: peter-evans/create-pull-request@v7 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: "docs: update documentation gap report" + title: "docs: fix documentation gaps [auto]" + body: | + Automated gap report from the **Audit Documentation Coverage** workflow. + + The `DOCS-GAPS.md` file lists every prop, function, slot, event, and i18n key + that is present in the dropin registry but missing from the microsite docs (or vice versa). + + **To resolve:** fix the missing documentation entries, then re-run the workflow to confirm the gaps are cleared. + + > Generated by [`scripts/audit-docs.ts`](scripts/audit-docs.ts) + > Registry source: `@dropins/mcp` (installed devDependency) + branch: chore/docs-gaps-audit + delete-branch: true + add-paths: DOCS-GAPS.md + labels: "documentation,automated" diff --git a/package.json b/package.json index c62401505..d771f3573 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "update-all-versions": "npm run update-boilerplate-versions && npm run update-dropin-versions", "generate-all-docs": "node scripts/generate-all-docs.js", "generate-boilerplate-docs": "node scripts/@generate-boilerplate-docs.js", + "audit:docs": "tsx scripts/audit-docs.ts", "validate-diagrams": "node scripts/validate-diagrams.js", "verify-enrichments": "node scripts/verify-enrichments.js", "validate-b2b-enrichments": "node scripts/validate-b2b-enrichments.js", @@ -167,9 +168,11 @@ ] }, "devDependencies": { + "@dropins/mcp": "^0.1.0", "eslint-plugin-mdx": "^3.2.0", "jsdom": "^25.0.1", "playwright": "^1.57.0", + "tsx": "^4.21.0", "vite": "7.3.2" }, "engines": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0bad24dee..2b4f6a1e8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -24,10 +24,10 @@ importers: version: 0.9.8(prettier-plugin-astro@0.14.1)(prettier@3.8.3)(typescript@5.9.3) '@astrojs/react': specifier: 4.4.2 - version: 4.4.2(@types/node@25.6.0)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(lightningcss@1.32.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(terser@5.46.1)(yaml@2.8.3) + version: 4.4.2(@types/node@25.6.0)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(lightningcss@1.32.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(terser@5.46.1)(tsx@4.22.3)(yaml@2.8.3) '@astrojs/starlight': specifier: 0.37.7 - version: 0.37.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(typescript@5.9.3)(yaml@2.8.3)) + version: 0.37.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.22.3)(typescript@5.9.3)(yaml@2.8.3)) '@codesandbox/sandpack-client': specifier: ^2.19.8 version: 2.19.8 @@ -87,7 +87,7 @@ importers: version: 0.11.1(@types/node@25.6.0)(graphql@16.11.0) '@playform/compress': specifier: ^0.2.2 - version: 0.2.3(@types/node@25.6.0)(rollup@4.60.1)(typescript@5.9.3)(yaml@2.8.3) + version: 0.2.3(@types/node@25.6.0)(rollup@4.60.1)(tsx@4.22.3)(typescript@5.9.3)(yaml@2.8.3) '@types/hast': specifier: ^3.0.4 version: 3.0.4 @@ -111,7 +111,7 @@ importers: version: 8.58.2(eslint@10.2.0)(typescript@5.9.3) astro: specifier: 5.18.1 - version: 5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(typescript@5.9.3)(yaml@2.8.3) + version: 5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.22.3)(typescript@5.9.3)(yaml@2.8.3) cache: specifier: ^3.0.0 version: 3.0.0 @@ -186,16 +186,16 @@ importers: version: 0.34.5 starlight-heading-badges: specifier: 0.6.1 - version: 0.6.1(@astrojs/starlight@0.37.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(typescript@5.9.3)(yaml@2.8.3))) + version: 0.6.1(@astrojs/starlight@0.37.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.22.3)(typescript@5.9.3)(yaml@2.8.3))) starlight-image-zoom: specifier: 0.13.2 - version: 0.13.2(@astrojs/starlight@0.37.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(typescript@5.9.3)(yaml@2.8.3))) + version: 0.13.2(@astrojs/starlight@0.37.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.22.3)(typescript@5.9.3)(yaml@2.8.3))) starlight-links-validator: specifier: 0.19.2 - version: 0.19.2(@astrojs/starlight@0.37.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(typescript@5.9.3)(yaml@2.8.3)))(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(typescript@5.9.3)(yaml@2.8.3)) + version: 0.19.2(@astrojs/starlight@0.37.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.22.3)(typescript@5.9.3)(yaml@2.8.3)))(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.22.3)(typescript@5.9.3)(yaml@2.8.3)) starlight-sidebar-topics: specifier: 0.6.2 - version: 0.6.2(@astrojs/starlight@0.37.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(typescript@5.9.3)(yaml@2.8.3))) + version: 0.6.2(@astrojs/starlight@0.37.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.22.3)(typescript@5.9.3)(yaml@2.8.3))) storybook: specifier: ^10.2.10 version: 10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -206,15 +206,21 @@ importers: specifier: ^5.0.0 version: 5.1.0 devDependencies: + '@dropins/mcp': + specifier: ^0.1.0 + version: 0.1.0 jsdom: specifier: ^25.0.1 version: 25.0.1 playwright: specifier: ^1.57.0 version: 1.59.1 + tsx: + specifier: ^4.21.0 + version: 4.22.3 vite: specifier: 7.3.2 - version: 7.3.2(@types/node@25.6.0)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3) + version: 7.3.2(@types/node@25.6.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.22.3)(yaml@2.8.3) packages: @@ -444,6 +450,11 @@ packages: resolution: {integrity: sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==} engines: {node: '>=14'} + '@dropins/mcp@0.1.0': + resolution: {integrity: sha512-ygv4WYa5ZZk98kzjGQXKzw5azOTP/roWON5XRIHNvFMMYH9AiKYXR0Acx8+3MNAh2B2dXSgYNvVnyDNUwEh9bQ==} + engines: {node: '>=18.0.0'} + hasBin: true + '@dropins/storefront-account@3.2.1': resolution: {integrity: sha512-AvGXstY/JvOF1yxIwpCJYktmX6Fpy0WXJLmApqBDSDGtbB6V+hSW5W6JSHoNIXgCTkUnQ6cByItiFwiZM4yRvQ==} @@ -522,6 +533,12 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/aix-ppc64@0.28.0': + resolution: {integrity: sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + '@esbuild/android-arm64@0.25.12': resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} engines: {node: '>=18'} @@ -534,6 +551,12 @@ packages: cpu: [arm64] os: [android] + '@esbuild/android-arm64@0.28.0': + resolution: {integrity: sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm@0.25.12': resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} engines: {node: '>=18'} @@ -546,6 +569,12 @@ packages: cpu: [arm] os: [android] + '@esbuild/android-arm@0.28.0': + resolution: {integrity: sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + '@esbuild/android-x64@0.25.12': resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} engines: {node: '>=18'} @@ -558,6 +587,12 @@ packages: cpu: [x64] os: [android] + '@esbuild/android-x64@0.28.0': + resolution: {integrity: sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + '@esbuild/darwin-arm64@0.25.12': resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} engines: {node: '>=18'} @@ -570,6 +605,12 @@ packages: cpu: [arm64] os: [darwin] + '@esbuild/darwin-arm64@0.28.0': + resolution: {integrity: sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-x64@0.25.12': resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} engines: {node: '>=18'} @@ -582,6 +623,12 @@ packages: cpu: [x64] os: [darwin] + '@esbuild/darwin-x64@0.28.0': + resolution: {integrity: sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/freebsd-arm64@0.25.12': resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} engines: {node: '>=18'} @@ -594,6 +641,12 @@ packages: cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-arm64@0.28.0': + resolution: {integrity: sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-x64@0.25.12': resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} engines: {node: '>=18'} @@ -606,6 +659,12 @@ packages: cpu: [x64] os: [freebsd] + '@esbuild/freebsd-x64@0.28.0': + resolution: {integrity: sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/linux-arm64@0.25.12': resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} engines: {node: '>=18'} @@ -618,6 +677,12 @@ packages: cpu: [arm64] os: [linux] + '@esbuild/linux-arm64@0.28.0': + resolution: {integrity: sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm@0.25.12': resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} engines: {node: '>=18'} @@ -630,6 +695,12 @@ packages: cpu: [arm] os: [linux] + '@esbuild/linux-arm@0.28.0': + resolution: {integrity: sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + '@esbuild/linux-ia32@0.25.12': resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} engines: {node: '>=18'} @@ -642,6 +713,12 @@ packages: cpu: [ia32] os: [linux] + '@esbuild/linux-ia32@0.28.0': + resolution: {integrity: sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-loong64@0.25.12': resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} engines: {node: '>=18'} @@ -654,6 +731,12 @@ packages: cpu: [loong64] os: [linux] + '@esbuild/linux-loong64@0.28.0': + resolution: {integrity: sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-mips64el@0.25.12': resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} engines: {node: '>=18'} @@ -666,6 +749,12 @@ packages: cpu: [mips64el] os: [linux] + '@esbuild/linux-mips64el@0.28.0': + resolution: {integrity: sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-ppc64@0.25.12': resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} engines: {node: '>=18'} @@ -678,6 +767,12 @@ packages: cpu: [ppc64] os: [linux] + '@esbuild/linux-ppc64@0.28.0': + resolution: {integrity: sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-riscv64@0.25.12': resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} engines: {node: '>=18'} @@ -690,6 +785,12 @@ packages: cpu: [riscv64] os: [linux] + '@esbuild/linux-riscv64@0.28.0': + resolution: {integrity: sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-s390x@0.25.12': resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} engines: {node: '>=18'} @@ -702,6 +803,12 @@ packages: cpu: [s390x] os: [linux] + '@esbuild/linux-s390x@0.28.0': + resolution: {integrity: sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-x64@0.25.12': resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} engines: {node: '>=18'} @@ -714,6 +821,12 @@ packages: cpu: [x64] os: [linux] + '@esbuild/linux-x64@0.28.0': + resolution: {integrity: sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + '@esbuild/netbsd-arm64@0.25.12': resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} engines: {node: '>=18'} @@ -726,6 +839,12 @@ packages: cpu: [arm64] os: [netbsd] + '@esbuild/netbsd-arm64@0.28.0': + resolution: {integrity: sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + '@esbuild/netbsd-x64@0.25.12': resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} engines: {node: '>=18'} @@ -738,6 +857,12 @@ packages: cpu: [x64] os: [netbsd] + '@esbuild/netbsd-x64@0.28.0': + resolution: {integrity: sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + '@esbuild/openbsd-arm64@0.25.12': resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} engines: {node: '>=18'} @@ -750,6 +875,12 @@ packages: cpu: [arm64] os: [openbsd] + '@esbuild/openbsd-arm64@0.28.0': + resolution: {integrity: sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-x64@0.25.12': resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} engines: {node: '>=18'} @@ -762,6 +893,12 @@ packages: cpu: [x64] os: [openbsd] + '@esbuild/openbsd-x64@0.28.0': + resolution: {integrity: sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + '@esbuild/openharmony-arm64@0.25.12': resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} engines: {node: '>=18'} @@ -774,6 +911,12 @@ packages: cpu: [arm64] os: [openharmony] + '@esbuild/openharmony-arm64@0.28.0': + resolution: {integrity: sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + '@esbuild/sunos-x64@0.25.12': resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} engines: {node: '>=18'} @@ -786,6 +929,12 @@ packages: cpu: [x64] os: [sunos] + '@esbuild/sunos-x64@0.28.0': + resolution: {integrity: sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/win32-arm64@0.25.12': resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} engines: {node: '>=18'} @@ -798,6 +947,12 @@ packages: cpu: [arm64] os: [win32] + '@esbuild/win32-arm64@0.28.0': + resolution: {integrity: sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-ia32@0.25.12': resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} engines: {node: '>=18'} @@ -810,6 +965,12 @@ packages: cpu: [ia32] os: [win32] + '@esbuild/win32-ia32@0.28.0': + resolution: {integrity: sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-x64@0.25.12': resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} engines: {node: '>=18'} @@ -822,6 +983,12 @@ packages: cpu: [x64] os: [win32] + '@esbuild/win32-x64@0.28.0': + resolution: {integrity: sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@eslint-community/eslint-utils@4.9.1': resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -916,6 +1083,12 @@ packages: react: ^16 || ^17 || ^18 react-dom: ^16 || ^17 || ^18 + '@hono/node-server@1.19.14': + resolution: {integrity: sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==} + engines: {node: '>=18.14.1'} + peerDependencies: + hono: ^4 + '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -1116,6 +1289,16 @@ packages: '@mermaid-js/parser@1.1.0': resolution: {integrity: sha512-gxK9ZX2+Fex5zu8LhRQoMeMPEHbc73UKZ0FQ54YrQtUxE1VVhMwzeNtKRPAu5aXks4FasbMe4xB4bWrmq6Jlxw==} + '@modelcontextprotocol/sdk@1.29.0': + resolution: {integrity: sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==} + engines: {node: '>=18'} + peerDependencies: + '@cfworker/json-schema': ^4.1.1 + zod: ^3.25 || ^4.0 + peerDependenciesMeta: + '@cfworker/json-schema': + optional: true + '@motionone/animation@10.18.0': resolution: {integrity: sha512-9z2p5GFGCm0gBsZbi8rVMOAJCtw1WqBTIPw3ozk06gDvZInBPIsQcHgYogEJ4yuHJ+akuW8g1SEIOpTOvYs8hw==} @@ -2093,6 +2276,10 @@ packages: resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + accepts@2.0.0: + resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} + engines: {node: '>= 0.6'} + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -2115,6 +2302,14 @@ packages: ajv: optional: true + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + ajv@6.14.0: resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==} @@ -2228,6 +2423,10 @@ packages: bcp-47@2.1.0: resolution: {integrity: sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w==} + body-parser@2.2.2: + resolution: {integrity: sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==} + engines: {node: '>=18'} + boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} @@ -2261,6 +2460,10 @@ packages: resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} engines: {node: '>=18'} + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + cache@3.0.0: resolution: {integrity: sha512-sNoM5jithfalxIceo/uFFm5bOlGjux2y8jEvjNb0F/cACWQaMmWuEPTLl6GzLHdFcNsbWBBdqkBd9NyefZ5UQQ==} @@ -2268,6 +2471,10 @@ packages: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + camel-case@4.1.2: resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} @@ -2409,12 +2616,32 @@ packages: confbox@0.1.8: resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + content-disposition@1.1.0: + resolution: {integrity: sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==} + engines: {node: '>=18'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + + content-type@2.0.0: + resolution: {integrity: sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==} + engines: {node: '>=18'} + convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} cookie-es@1.2.3: resolution: {integrity: sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw==} + cookie-signature@1.2.2: + resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} + engines: {node: '>=6.6.0'} + + cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + engines: {node: '>= 0.6'} + cookie@1.1.1: resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} engines: {node: '>=18'} @@ -2422,6 +2649,10 @@ packages: copy-to-clipboard@3.3.3: resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==} + cors@2.8.6: + resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==} + engines: {node: '>= 0.10'} + cose-base@1.0.3: resolution: {integrity: sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==} @@ -2697,6 +2928,10 @@ packages: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} @@ -2779,6 +3014,9 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + electron-to-chromium@1.5.337: resolution: {integrity: sha512-15gKW9mRUNP9RdzhedJNypFUxtYWSXohFz2nTLzM272xbRXHws68kNDzyATG3qej+vUj/7Sn9hf5XTDh0XK6/w==} @@ -2794,6 +3032,10 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} @@ -2847,10 +3089,18 @@ packages: engines: {node: '>=18'} hasBin: true + esbuild@0.28.0: + resolution: {integrity: sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==} + engines: {node: '>=18'} + hasBin: true + escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} @@ -2966,9 +3216,31 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + eventemitter3@5.0.4: resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} + eventsource-parser@3.0.8: + resolution: {integrity: sha512-70QWGkr4snxr0OXLRWsFLeRBIRPuQOvt4s8QYjmUlmlkyTZkRqS7EDVRZtzU3TiyDbXSzaOeF0XUKy8PchzukQ==} + engines: {node: '>=18.0.0'} + + eventsource@3.0.7: + resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==} + engines: {node: '>=18.0.0'} + + express-rate-limit@8.5.2: + resolution: {integrity: sha512-5Kb34ipNX694DH48vN9irak1Qx30nb0PLYHXfJgw4YEjiC3ZEmZJhwOp+VfiCYwFzvFTdB9QkArYS5kXa2cx2A==} + engines: {node: '>= 16'} + peerDependencies: + express: '>= 4.11' + + express@5.2.1: + resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==} + engines: {node: '>= 18'} + expressive-code@0.41.7: resolution: {integrity: sha512-2wZjC8OQ3TaVEMcBtYY4Va3lo6J+Ai9jf3d4dbhURMJcU4Pbqe6EcHe424MIZI0VHUA1bR6xdpoHYi3yxokWqA==} @@ -3011,6 +3283,10 @@ packages: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} + finalhandler@2.1.1: + resolution: {integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==} + engines: {node: '>= 18.0.0'} + find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} @@ -3041,6 +3317,10 @@ packages: resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} engines: {node: '>= 6'} + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + framer-motion@6.5.1: resolution: {integrity: sha512-o1BGqqposwi7cgDrtg0dNONhkmPsUFDaLcKXigzuTFC5x58mE8iyTazxSudFzmT6MEyJKfjjU8ItoMe3W+3fiw==} peerDependencies: @@ -3050,6 +3330,10 @@ packages: framesync@6.0.1: resolution: {integrity: sha512-fUY88kXvGiIItgNC7wcTOl0SNRCVXMKSWW2Yzfmn7EKNc+MpCzcz9DhdHcdjbrtN3c6R4H5dTY2jiCpPdysEjA==} + fresh@2.0.0: + resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} + engines: {node: '>= 0.8'} + fsevents@2.3.2: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -3224,6 +3508,10 @@ packages: hey-listen@1.0.8: resolution: {integrity: sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==} + hono@4.12.23: + resolution: {integrity: sha512-eIaZ9qDgu7XV0pxOCrg7/WhnQ6Ivm22UcxhXx/A3dcbqbbYgBEkc6e/J/s7j2tS96zoB0S9VBdLwQNCWwUo4LA==} + engines: {node: '>=16.9.0'} + hosted-git-info@7.0.2: resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} engines: {node: ^16.14.0 || >=18.0.0} @@ -3249,6 +3537,10 @@ packages: http-cache-semantics@4.2.0: resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==} + http-errors@2.0.1: + resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} + engines: {node: '>= 0.8'} + http-proxy-agent@7.0.2: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} engines: {node: '>= 14'} @@ -3264,6 +3556,10 @@ packages: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} + iconv-lite@0.7.2: + resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} + engines: {node: '>=0.10.0'} + ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} @@ -3307,6 +3603,14 @@ packages: resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} engines: {node: '>=12'} + ip-address@10.2.0: + resolution: {integrity: sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==} + engines: {node: '>= 12'} + + ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + iron-webcrypto@1.2.1: resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==} @@ -3373,6 +3677,9 @@ packages: resolution: {integrity: sha512-GljRxhWvlCNRfZyORiH77FwdFwGcMO620o37EOYC0ORWdq+WYNVqW0w2Juzew4M+L81l6/QS3t5gkkihyRqv9w==} engines: {node: '>=0.10.0'} + is-promise@4.0.0: + resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} + is-wsl@3.1.1: resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==} engines: {node: '>=16'} @@ -3391,6 +3698,9 @@ packages: jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + jose@6.2.3: + resolution: {integrity: sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -3425,6 +3735,9 @@ packages: json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + json-schema-typed@8.0.2: + resolution: {integrity: sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==} + json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} @@ -3683,6 +3996,14 @@ packages: mdurl@2.0.0: resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} + media-typer@1.1.0: + resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} + engines: {node: '>= 0.8'} + + merge-descriptors@2.0.0: + resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==} + engines: {node: '>=18'} + merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} @@ -3823,6 +4144,10 @@ packages: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} + mime-types@3.0.2: + resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} + engines: {node: '>=18'} + min-indent@1.0.1: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} @@ -3860,6 +4185,10 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + negotiator@1.0.0: + resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} + engines: {node: '>= 0.6'} + neotraverse@0.6.18: resolution: {integrity: sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==} engines: {node: '>= 10'} @@ -3920,12 +4249,27 @@ packages: nwsapi@2.2.23: resolution: {integrity: sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==} + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + ofetch@1.5.1: resolution: {integrity: sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==} ohash@2.0.11: resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==} + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + oniguruma-parser@0.12.1: resolution: {integrity: sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==} @@ -3989,6 +4333,10 @@ packages: parse5@7.3.0: resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + pascal-case@3.1.2: resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} @@ -4010,6 +4358,9 @@ packages: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} + path-to-regexp@8.4.2: + resolution: {integrity: sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==} + pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} @@ -4031,6 +4382,10 @@ packages: resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} engines: {node: '>=12'} + pkce-challenge@5.0.1: + resolution: {integrity: sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==} + engines: {node: '>=16.20.0'} + pkg-types@1.3.1: resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} @@ -4111,6 +4466,10 @@ packages: property-information@7.1.0: resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==} + proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + punycode.js@2.3.1: resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} engines: {node: '>=6'} @@ -4119,12 +4478,24 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} + qs@6.15.2: + resolution: {integrity: sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==} + engines: {node: '>=0.6'} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} radix3@1.1.2: resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==} + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + raw-body@3.0.2: + resolution: {integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==} + engines: {node: '>= 0.10'} + react-compiler-runtime@19.0.0-beta-37ed2a7-20241206: resolution: {integrity: sha512-9e6rCpVylr9EnVocgYAjft7+2v01BDpajeHKRoO+oc9pKcAMTpstHtHvE/TSVbyf4FvzCGjfKcfHM9XGTXI6Tw==} peerDependencies: @@ -4318,6 +4689,10 @@ packages: roughjs@4.6.6: resolution: {integrity: sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==} + router@2.2.0: + resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} + engines: {node: '>= 18'} + rrweb-cssom@0.7.1: resolution: {integrity: sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==} @@ -4366,10 +4741,21 @@ packages: engines: {node: '>=10'} hasBin: true + send@1.2.1: + resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==} + engines: {node: '>= 18'} + + serve-static@2.2.1: + resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==} + engines: {node: '>= 18'} + set-value@4.1.0: resolution: {integrity: sha512-zTEg4HL0RwVrqcWs3ztF+x1vkxfm0lP+MQQFPiMJTKVceBwEV0A569Ou8l9IYQG8jOZdMVI1hGsc0tmeD2o/Lw==} engines: {node: '>=11.0'} + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + sharp@0.34.5: resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} @@ -4385,6 +4771,22 @@ packages: shiki@3.23.0: resolution: {integrity: sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA==} + side-channel-list@1.0.1: + resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} @@ -4459,6 +4861,10 @@ packages: static-browser-server@1.0.3: resolution: {integrity: sha512-ZUyfgGDdFRbZGGJQ1YhiM930Yczz5VlbJObrQLlk24+qNHVQx4OlLcYswEUo3bIyNAbQUIUR9Yr5/Hqjzqb4zA==} + statuses@2.0.2: + resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} + engines: {node: '>= 0.8'} + storybook@10.3.5: resolution: {integrity: sha512-uBSZu/GZa9aEIW3QMGvdQPMZWhGxSe4dyRWU8B3/Vd47Gy/XLC7tsBxRr13txmmPOEDHZR94uLuq0H50fvuqBw==} hasBin: true @@ -4595,6 +5001,10 @@ packages: toggle-selection@1.0.6: resolution: {integrity: sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==} + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + tough-cookie@5.1.2: resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} engines: {node: '>=16'} @@ -4632,6 +5042,11 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tsx@4.22.3: + resolution: {integrity: sha512-mdoNxBC/cSQObGGVQ5Bpn5i+yv7j68gk3Nfm3wFjcJg3Z0Mix9jzAFfP12prmm5eVGmDKtp0yyArrs0Q+8gZHg==} + engines: {node: '>=18.0.0'} + hasBin: true + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -4644,6 +5059,10 @@ packages: resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} engines: {node: '>=16'} + type-is@2.1.0: + resolution: {integrity: sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==} + engines: {node: '>= 18'} + typedarray@0.0.6: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} @@ -4721,6 +5140,10 @@ packages: unist-util-visit@5.1.0: resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==} + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + unstorage@1.17.5: resolution: {integrity: sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg==} peerDependencies: @@ -4831,6 +5254,10 @@ packages: resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + vfile-location@5.0.3: resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==} @@ -5093,6 +5520,9 @@ packages: resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} engines: {node: '>=18'} + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + ws@8.20.0: resolution: {integrity: sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==} engines: {node: '>=10.0.0'} @@ -5263,12 +5693,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@astrojs/mdx@4.3.14(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(typescript@5.9.3)(yaml@2.8.3))': + '@astrojs/mdx@4.3.14(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.22.3)(typescript@5.9.3)(yaml@2.8.3))': dependencies: '@astrojs/markdown-remark': 6.3.11 '@mdx-js/mdx': 3.1.1 acorn: 8.16.0 - astro: 5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(typescript@5.9.3)(yaml@2.8.3) + astro: 5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.22.3)(typescript@5.9.3)(yaml@2.8.3) es-module-lexer: 1.7.0 estree-util-visit: 2.0.0 hast-util-to-html: 9.0.5 @@ -5286,15 +5716,15 @@ snapshots: dependencies: prismjs: 1.30.0 - '@astrojs/react@4.4.2(@types/node@25.6.0)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(lightningcss@1.32.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(terser@5.46.1)(yaml@2.8.3)': + '@astrojs/react@4.4.2(@types/node@25.6.0)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(lightningcss@1.32.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(terser@5.46.1)(tsx@4.22.3)(yaml@2.8.3)': dependencies: '@types/react': 19.2.14 '@types/react-dom': 19.2.3(@types/react@19.2.14) - '@vitejs/plugin-react': 4.7.0(vite@6.4.2(@types/node@25.6.0)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3)) + '@vitejs/plugin-react': 4.7.0(vite@6.4.2(@types/node@25.6.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.22.3)(yaml@2.8.3)) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) ultrahtml: 1.6.0 - vite: 6.4.2(@types/node@25.6.0)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3) + vite: 6.4.2(@types/node@25.6.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.22.3)(yaml@2.8.3) transitivePeerDependencies: - '@types/node' - jiti @@ -5315,17 +5745,17 @@ snapshots: stream-replace-string: 1.1.1 zod: 4.3.6 - '@astrojs/starlight@0.37.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(typescript@5.9.3)(yaml@2.8.3))': + '@astrojs/starlight@0.37.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.22.3)(typescript@5.9.3)(yaml@2.8.3))': dependencies: '@astrojs/markdown-remark': 6.3.11 - '@astrojs/mdx': 4.3.14(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(typescript@5.9.3)(yaml@2.8.3)) + '@astrojs/mdx': 4.3.14(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.22.3)(typescript@5.9.3)(yaml@2.8.3)) '@astrojs/sitemap': 3.7.2 '@pagefind/default-ui': 1.5.2 '@types/hast': 3.0.4 '@types/js-yaml': 4.0.9 '@types/mdast': 4.0.4 - astro: 5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(typescript@5.9.3)(yaml@2.8.3) - astro-expressive-code: 0.41.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(typescript@5.9.3)(yaml@2.8.3)) + astro: 5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.22.3)(typescript@5.9.3)(yaml@2.8.3) + astro-expressive-code: 0.41.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.22.3)(typescript@5.9.3)(yaml@2.8.3)) bcp-47: 2.1.0 hast-util-from-html: 2.0.3 hast-util-select: 6.0.4 @@ -5556,6 +5986,15 @@ snapshots: '@ctrl/tinycolor@4.2.0': {} + '@dropins/mcp@0.1.0': + dependencies: + '@modelcontextprotocol/sdk': 1.29.0(zod@3.25.76) + zod: 3.25.76 + zod-to-json-schema: 3.25.2(zod@3.25.76) + transitivePeerDependencies: + - '@cfworker/json-schema' + - supports-color + '@dropins/storefront-account@3.2.1': {} '@dropins/storefront-auth@3.2.0': {} @@ -5622,156 +6061,234 @@ snapshots: '@esbuild/aix-ppc64@0.27.7': optional: true + '@esbuild/aix-ppc64@0.28.0': + optional: true + '@esbuild/android-arm64@0.25.12': optional: true '@esbuild/android-arm64@0.27.7': optional: true + '@esbuild/android-arm64@0.28.0': + optional: true + '@esbuild/android-arm@0.25.12': optional: true '@esbuild/android-arm@0.27.7': optional: true + '@esbuild/android-arm@0.28.0': + optional: true + '@esbuild/android-x64@0.25.12': optional: true '@esbuild/android-x64@0.27.7': optional: true + '@esbuild/android-x64@0.28.0': + optional: true + '@esbuild/darwin-arm64@0.25.12': optional: true '@esbuild/darwin-arm64@0.27.7': optional: true + '@esbuild/darwin-arm64@0.28.0': + optional: true + '@esbuild/darwin-x64@0.25.12': optional: true '@esbuild/darwin-x64@0.27.7': optional: true + '@esbuild/darwin-x64@0.28.0': + optional: true + '@esbuild/freebsd-arm64@0.25.12': optional: true '@esbuild/freebsd-arm64@0.27.7': optional: true + '@esbuild/freebsd-arm64@0.28.0': + optional: true + '@esbuild/freebsd-x64@0.25.12': optional: true '@esbuild/freebsd-x64@0.27.7': optional: true + '@esbuild/freebsd-x64@0.28.0': + optional: true + '@esbuild/linux-arm64@0.25.12': optional: true '@esbuild/linux-arm64@0.27.7': optional: true + '@esbuild/linux-arm64@0.28.0': + optional: true + '@esbuild/linux-arm@0.25.12': optional: true '@esbuild/linux-arm@0.27.7': optional: true + '@esbuild/linux-arm@0.28.0': + optional: true + '@esbuild/linux-ia32@0.25.12': optional: true '@esbuild/linux-ia32@0.27.7': optional: true + '@esbuild/linux-ia32@0.28.0': + optional: true + '@esbuild/linux-loong64@0.25.12': optional: true '@esbuild/linux-loong64@0.27.7': optional: true + '@esbuild/linux-loong64@0.28.0': + optional: true + '@esbuild/linux-mips64el@0.25.12': optional: true '@esbuild/linux-mips64el@0.27.7': optional: true + '@esbuild/linux-mips64el@0.28.0': + optional: true + '@esbuild/linux-ppc64@0.25.12': optional: true '@esbuild/linux-ppc64@0.27.7': optional: true + '@esbuild/linux-ppc64@0.28.0': + optional: true + '@esbuild/linux-riscv64@0.25.12': optional: true '@esbuild/linux-riscv64@0.27.7': optional: true + '@esbuild/linux-riscv64@0.28.0': + optional: true + '@esbuild/linux-s390x@0.25.12': optional: true '@esbuild/linux-s390x@0.27.7': optional: true + '@esbuild/linux-s390x@0.28.0': + optional: true + '@esbuild/linux-x64@0.25.12': optional: true '@esbuild/linux-x64@0.27.7': optional: true + '@esbuild/linux-x64@0.28.0': + optional: true + '@esbuild/netbsd-arm64@0.25.12': optional: true '@esbuild/netbsd-arm64@0.27.7': optional: true + '@esbuild/netbsd-arm64@0.28.0': + optional: true + '@esbuild/netbsd-x64@0.25.12': optional: true '@esbuild/netbsd-x64@0.27.7': optional: true + '@esbuild/netbsd-x64@0.28.0': + optional: true + '@esbuild/openbsd-arm64@0.25.12': optional: true '@esbuild/openbsd-arm64@0.27.7': optional: true + '@esbuild/openbsd-arm64@0.28.0': + optional: true + '@esbuild/openbsd-x64@0.25.12': optional: true '@esbuild/openbsd-x64@0.27.7': optional: true + '@esbuild/openbsd-x64@0.28.0': + optional: true + '@esbuild/openharmony-arm64@0.25.12': optional: true '@esbuild/openharmony-arm64@0.27.7': optional: true + '@esbuild/openharmony-arm64@0.28.0': + optional: true + '@esbuild/sunos-x64@0.25.12': optional: true '@esbuild/sunos-x64@0.27.7': optional: true + '@esbuild/sunos-x64@0.28.0': + optional: true + '@esbuild/win32-arm64@0.25.12': optional: true '@esbuild/win32-arm64@0.27.7': optional: true + '@esbuild/win32-arm64@0.28.0': + optional: true + '@esbuild/win32-ia32@0.25.12': optional: true '@esbuild/win32-ia32@0.27.7': optional: true + '@esbuild/win32-ia32@0.28.0': + optional: true + '@esbuild/win32-x64@0.25.12': optional: true '@esbuild/win32-x64@0.27.7': optional: true + '@esbuild/win32-x64@0.28.0': + optional: true + '@eslint-community/eslint-utils@4.9.1(eslint@10.2.0)': dependencies: eslint: 10.2.0 @@ -5904,6 +6421,10 @@ snapshots: react: 19.2.4 react-dom: 19.2.4(react@19.2.4) + '@hono/node-server@1.19.14(hono@4.12.23)': + dependencies: + hono: 4.12.23 + '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.7': @@ -6098,6 +6619,28 @@ snapshots: dependencies: langium: 4.2.2 + '@modelcontextprotocol/sdk@1.29.0(zod@3.25.76)': + dependencies: + '@hono/node-server': 1.19.14(hono@4.12.23) + ajv: 8.18.0 + ajv-formats: 3.0.1(ajv@8.18.0) + content-type: 1.0.5 + cors: 2.8.6 + cross-spawn: 7.0.6 + eventsource: 3.0.7 + eventsource-parser: 3.0.8 + express: 5.2.1 + express-rate-limit: 8.5.2(express@5.2.1) + hono: 4.12.23 + jose: 6.2.3 + json-schema-typed: 8.0.2 + pkce-challenge: 5.0.1 + raw-body: 3.0.2 + zod: 3.25.76 + zod-to-json-schema: 3.25.2(zod@3.25.76) + transitivePeerDependencies: + - supports-color + '@motionone/animation@10.18.0': dependencies: '@motionone/easing': 10.18.0 @@ -6231,12 +6774,12 @@ snapshots: '@pkgr/core@0.2.9': {} - '@playform/compress@0.2.3(@types/node@25.6.0)(rollup@4.60.1)(typescript@5.9.3)(yaml@2.8.3)': + '@playform/compress@0.2.3(@types/node@25.6.0)(rollup@4.60.1)(tsx@4.22.3)(typescript@5.9.3)(yaml@2.8.3)': dependencies: '@playform/pipe': 0.1.5 '@types/csso': 5.0.4 '@types/html-minifier-terser': 7.0.2 - astro: 5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(typescript@5.9.3)(yaml@2.8.3) + astro: 5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.22.3)(typescript@5.9.3)(yaml@2.8.3) commander: 14.0.3 csso: 5.0.5 deepmerge-ts: 7.1.5 @@ -7103,7 +7646,7 @@ snapshots: d3-selection: 3.0.0 d3-transition: 3.0.1(d3-selection@3.0.0) - '@vitejs/plugin-react@4.7.0(vite@6.4.2(@types/node@25.6.0)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))': + '@vitejs/plugin-react@4.7.0(vite@6.4.2(@types/node@25.6.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.22.3)(yaml@2.8.3))': dependencies: '@babel/core': 7.29.0 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) @@ -7111,7 +7654,7 @@ snapshots: '@rolldown/pluginutils': 1.0.0-beta.27 '@types/babel__core': 7.20.5 react-refresh: 0.17.0 - vite: 6.4.2(@types/node@25.6.0)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3) + vite: 6.4.2(@types/node@25.6.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.22.3)(yaml@2.8.3) transitivePeerDependencies: - supports-color @@ -7191,6 +7734,11 @@ snapshots: abbrev@2.0.0: {} + accepts@2.0.0: + dependencies: + mime-types: 3.0.2 + negotiator: 1.0.0 + acorn-jsx@5.3.2(acorn@8.16.0): dependencies: acorn: 8.16.0 @@ -7203,6 +7751,10 @@ snapshots: optionalDependencies: ajv: 8.18.0 + ajv-formats@3.0.1(ajv@8.18.0): + optionalDependencies: + ajv: 8.18.0 + ajv@6.14.0: dependencies: fast-deep-equal: 3.1.3 @@ -7266,12 +7818,12 @@ snapshots: astring@1.9.0: {} - astro-expressive-code@0.41.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(typescript@5.9.3)(yaml@2.8.3)): + astro-expressive-code@0.41.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.22.3)(typescript@5.9.3)(yaml@2.8.3)): dependencies: - astro: 5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(typescript@5.9.3)(yaml@2.8.3) + astro: 5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.22.3)(typescript@5.9.3)(yaml@2.8.3) rehype-expressive-code: 0.41.7 - astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(typescript@5.9.3)(yaml@2.8.3): + astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.22.3)(typescript@5.9.3)(yaml@2.8.3): dependencies: '@astrojs/compiler': 2.13.1 '@astrojs/internal-helpers': 0.7.6 @@ -7328,8 +7880,8 @@ snapshots: unist-util-visit: 5.1.0 unstorage: 1.17.5 vfile: 6.0.3 - vite: 6.4.2(@types/node@25.6.0)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3) - vitefu: 1.1.3(vite@6.4.2(@types/node@25.6.0)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3)) + vite: 6.4.2(@types/node@25.6.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.22.3)(yaml@2.8.3) + vitefu: 1.1.3(vite@6.4.2(@types/node@25.6.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.22.3)(yaml@2.8.3)) xxhash-wasm: 1.1.0 yargs-parser: 21.1.1 yocto-spinner: 0.2.3 @@ -7397,6 +7949,20 @@ snapshots: is-alphanumerical: 2.0.1 is-decimal: 2.0.1 + body-parser@2.2.2: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 4.4.3 + http-errors: 2.0.1 + iconv-lite: 0.7.2 + on-finished: 2.4.1 + qs: 6.15.2 + raw-body: 3.0.2 + type-is: 2.1.0 + transitivePeerDependencies: + - supports-color + boolbase@1.0.0: {} boxen@8.0.1: @@ -7441,6 +8007,8 @@ snapshots: dependencies: run-applescript: 7.1.0 + bytes@3.1.2: {} + cache@3.0.0: dependencies: ds: 1.4.2 @@ -7450,6 +8018,11 @@ snapshots: es-errors: 1.3.0 function-bind: 1.1.2 + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + camel-case@4.1.2: dependencies: pascal-case: 3.1.2 @@ -7569,16 +8142,31 @@ snapshots: confbox@0.1.8: {} + content-disposition@1.1.0: {} + + content-type@1.0.5: {} + + content-type@2.0.0: {} + convert-source-map@2.0.0: {} cookie-es@1.2.3: {} + cookie-signature@1.2.2: {} + + cookie@0.7.2: {} + cookie@1.1.1: {} copy-to-clipboard@3.3.3: dependencies: toggle-selection: 1.0.6 + cors@2.8.6: + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + cose-base@1.0.3: dependencies: layout-base: 1.0.2 @@ -7864,6 +8452,8 @@ snapshots: delayed-stream@1.0.0: {} + depd@2.0.0: {} + dequal@2.0.3: {} destr@2.0.5: {} @@ -7935,6 +8525,8 @@ snapshots: eastasianwidth@0.2.0: {} + ee-first@1.1.1: {} + electron-to-chromium@1.5.337: {} emmet@2.4.11: @@ -7948,6 +8540,8 @@ snapshots: emoji-regex@9.2.2: {} + encodeurl@2.0.0: {} + entities@4.5.0: {} entities@6.0.1: {} @@ -8049,8 +8643,39 @@ snapshots: '@esbuild/win32-ia32': 0.27.7 '@esbuild/win32-x64': 0.27.7 + esbuild@0.28.0: + optionalDependencies: + '@esbuild/aix-ppc64': 0.28.0 + '@esbuild/android-arm': 0.28.0 + '@esbuild/android-arm64': 0.28.0 + '@esbuild/android-x64': 0.28.0 + '@esbuild/darwin-arm64': 0.28.0 + '@esbuild/darwin-x64': 0.28.0 + '@esbuild/freebsd-arm64': 0.28.0 + '@esbuild/freebsd-x64': 0.28.0 + '@esbuild/linux-arm': 0.28.0 + '@esbuild/linux-arm64': 0.28.0 + '@esbuild/linux-ia32': 0.28.0 + '@esbuild/linux-loong64': 0.28.0 + '@esbuild/linux-mips64el': 0.28.0 + '@esbuild/linux-ppc64': 0.28.0 + '@esbuild/linux-riscv64': 0.28.0 + '@esbuild/linux-s390x': 0.28.0 + '@esbuild/linux-x64': 0.28.0 + '@esbuild/netbsd-arm64': 0.28.0 + '@esbuild/netbsd-x64': 0.28.0 + '@esbuild/openbsd-arm64': 0.28.0 + '@esbuild/openbsd-x64': 0.28.0 + '@esbuild/openharmony-arm64': 0.28.0 + '@esbuild/sunos-x64': 0.28.0 + '@esbuild/win32-arm64': 0.28.0 + '@esbuild/win32-ia32': 0.28.0 + '@esbuild/win32-x64': 0.28.0 + escalade@3.2.0: {} + escape-html@1.0.3: {} + escape-string-regexp@4.0.0: {} escape-string-regexp@5.0.0: {} @@ -8214,8 +8839,54 @@ snapshots: esutils@2.0.3: {} + etag@1.8.1: {} + eventemitter3@5.0.4: {} + eventsource-parser@3.0.8: {} + + eventsource@3.0.7: + dependencies: + eventsource-parser: 3.0.8 + + express-rate-limit@8.5.2(express@5.2.1): + dependencies: + express: 5.2.1 + ip-address: 10.2.0 + + express@5.2.1: + dependencies: + accepts: 2.0.0 + body-parser: 2.2.2 + content-disposition: 1.1.0 + content-type: 1.0.5 + cookie: 0.7.2 + cookie-signature: 1.2.2 + debug: 4.4.3 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 2.1.1 + fresh: 2.0.0 + http-errors: 2.0.1 + merge-descriptors: 2.0.0 + mime-types: 3.0.2 + on-finished: 2.4.1 + once: 1.4.0 + parseurl: 1.3.3 + proxy-addr: 2.0.7 + qs: 6.15.2 + range-parser: 1.2.1 + router: 2.2.0 + send: 1.2.1 + serve-static: 2.2.1 + statuses: 2.0.2 + type-is: 2.1.0 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + expressive-code@0.41.7: dependencies: '@expressive-code/core': 0.41.7 @@ -8257,6 +8928,17 @@ snapshots: dependencies: to-regex-range: 5.0.1 + finalhandler@2.1.1: + dependencies: + debug: 4.4.3 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + find-up@5.0.0: dependencies: locate-path: 6.0.0 @@ -8292,6 +8974,8 @@ snapshots: hasown: 2.0.2 mime-types: 2.1.35 + forwarded@0.2.0: {} + framer-motion@6.5.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4): dependencies: '@motionone/dom': 10.12.0 @@ -8309,6 +8993,8 @@ snapshots: dependencies: tslib: 2.8.1 + fresh@2.0.0: {} + fsevents@2.3.2: optional: true @@ -8615,6 +9301,8 @@ snapshots: hey-listen@1.0.8: {} + hono@4.12.23: {} + hosted-git-info@7.0.2: dependencies: lru-cache: 10.4.3 @@ -8641,6 +9329,14 @@ snapshots: http-cache-semantics@4.2.0: {} + http-errors@2.0.1: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.2 + toidentifier: 1.0.1 + http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.4 @@ -8663,6 +9359,10 @@ snapshots: dependencies: safer-buffer: 2.1.2 + iconv-lite@0.7.2: + dependencies: + safer-buffer: 2.1.2 + ieee754@1.2.1: {} ignore@5.3.2: {} @@ -8687,6 +9387,10 @@ snapshots: internmap@2.0.3: {} + ip-address@10.2.0: {} + + ipaddr.js@1.9.1: {} + iron-webcrypto@1.2.1: {} is-absolute-url@4.0.1: {} @@ -8732,6 +9436,8 @@ snapshots: is-primitive@3.0.1: {} + is-promise@4.0.0: {} + is-wsl@3.1.1: dependencies: is-inside-container: 1.0.0 @@ -8748,6 +9454,8 @@ snapshots: optionalDependencies: '@pkgjs/parseargs': 0.11.0 + jose@6.2.3: {} + js-tokens@4.0.0: {} js-yaml@4.1.1: @@ -8792,6 +9500,8 @@ snapshots: json-schema-traverse@1.0.0: {} + json-schema-typed@8.0.2: {} + json-stable-stringify-without-jsonify@1.0.1: {} json5@2.2.3: {} @@ -9142,6 +9852,10 @@ snapshots: mdurl@2.0.0: {} + media-typer@1.1.0: {} + + merge-descriptors@2.0.0: {} + merge2@1.4.1: {} mermaid@11.14.0: @@ -9459,6 +10173,10 @@ snapshots: dependencies: mime-db: 1.52.0 + mime-types@3.0.2: + dependencies: + mime-db: 1.54.0 + min-indent@1.0.1: {} minimatch@10.2.5: @@ -9488,6 +10206,8 @@ snapshots: natural-compare@1.4.0: {} + negotiator@1.0.0: {} + neotraverse@0.6.18: {} nlcst-to-string@4.0.0: @@ -9550,6 +10270,10 @@ snapshots: nwsapi@2.2.23: {} + object-assign@4.1.1: {} + + object-inspect@1.13.4: {} + ofetch@1.5.1: dependencies: destr: 2.0.5 @@ -9558,6 +10282,14 @@ snapshots: ohash@2.0.11: {} + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + oniguruma-parser@0.12.1: {} oniguruma-to-es@4.3.5: @@ -9653,6 +10385,8 @@ snapshots: dependencies: entities: 6.0.1 + parseurl@1.3.3: {} + pascal-case@3.1.2: dependencies: no-case: 3.0.4 @@ -9671,6 +10405,8 @@ snapshots: lru-cache: 10.4.3 minipass: 7.1.3 + path-to-regexp@8.4.2: {} + pathe@2.0.3: {} pathval@2.0.1: {} @@ -9683,6 +10419,8 @@ snapshots: picomatch@4.0.4: {} + pkce-challenge@5.0.1: {} + pkg-types@1.3.1: dependencies: confbox: 0.1.8 @@ -9761,14 +10499,32 @@ snapshots: property-information@7.1.0: {} + proxy-addr@2.0.7: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + punycode.js@2.3.1: {} punycode@2.3.1: {} + qs@6.15.2: + dependencies: + side-channel: 1.1.0 + queue-microtask@1.2.3: {} radix3@1.1.2: {} + range-parser@1.2.1: {} + + raw-body@3.0.2: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.1 + iconv-lite: 0.7.2 + unpipe: 1.0.0 + react-compiler-runtime@19.0.0-beta-37ed2a7-20241206(react@19.2.4): dependencies: react: 19.2.4 @@ -10058,6 +10814,16 @@ snapshots: points-on-curve: 0.2.0 points-on-path: 0.2.1 + router@2.2.0: + dependencies: + debug: 4.4.3 + depd: 2.0.0 + is-promise: 4.0.0 + parseurl: 1.3.3 + path-to-regexp: 8.4.2 + transitivePeerDependencies: + - supports-color + rrweb-cssom@0.7.1: {} rrweb-cssom@0.8.0: {} @@ -10092,11 +10858,38 @@ snapshots: semver@7.7.4: {} + send@1.2.1: + dependencies: + debug: 4.4.3 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 2.0.0 + http-errors: 2.0.1 + mime-types: 3.0.2 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + + serve-static@2.2.1: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 1.2.1 + transitivePeerDependencies: + - supports-color + set-value@4.1.0: dependencies: is-plain-object: 2.0.4 is-primitive: 3.0.1 + setprototypeof@1.2.0: {} + sharp@0.34.5: dependencies: '@img/colour': 1.1.0 @@ -10145,6 +10938,34 @@ snapshots: '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.4 + side-channel-list@1.0.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.1 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + signal-exit@4.1.0: {} sisteransi@1.0.5: {} @@ -10185,19 +11006,19 @@ snapshots: spdx-license-ids@3.0.23: {} - starlight-heading-badges@0.6.1(@astrojs/starlight@0.37.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(typescript@5.9.3)(yaml@2.8.3))): + starlight-heading-badges@0.6.1(@astrojs/starlight@0.37.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.22.3)(typescript@5.9.3)(yaml@2.8.3))): dependencies: '@astrojs/markdown-remark': 6.3.11 - '@astrojs/starlight': 0.37.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(typescript@5.9.3)(yaml@2.8.3)) + '@astrojs/starlight': 0.37.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.22.3)(typescript@5.9.3)(yaml@2.8.3)) github-slugger: 2.0.0 mdast-util-directive: 3.1.0 unist-util-visit: 5.1.0 transitivePeerDependencies: - supports-color - starlight-image-zoom@0.13.2(@astrojs/starlight@0.37.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(typescript@5.9.3)(yaml@2.8.3))): + starlight-image-zoom@0.13.2(@astrojs/starlight@0.37.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.22.3)(typescript@5.9.3)(yaml@2.8.3))): dependencies: - '@astrojs/starlight': 0.37.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(typescript@5.9.3)(yaml@2.8.3)) + '@astrojs/starlight': 0.37.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.22.3)(typescript@5.9.3)(yaml@2.8.3)) mdast-util-mdx-jsx: 3.2.0 rehype-raw: 7.0.0 unist-util-visit: 5.1.0 @@ -10205,11 +11026,11 @@ snapshots: transitivePeerDependencies: - supports-color - starlight-links-validator@0.19.2(@astrojs/starlight@0.37.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(typescript@5.9.3)(yaml@2.8.3)))(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(typescript@5.9.3)(yaml@2.8.3)): + starlight-links-validator@0.19.2(@astrojs/starlight@0.37.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.22.3)(typescript@5.9.3)(yaml@2.8.3)))(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.22.3)(typescript@5.9.3)(yaml@2.8.3)): dependencies: - '@astrojs/starlight': 0.37.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(typescript@5.9.3)(yaml@2.8.3)) + '@astrojs/starlight': 0.37.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.22.3)(typescript@5.9.3)(yaml@2.8.3)) '@types/picomatch': 3.0.2 - astro: 5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(typescript@5.9.3)(yaml@2.8.3) + astro: 5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.22.3)(typescript@5.9.3)(yaml@2.8.3) github-slugger: 2.0.0 hast-util-from-html: 2.0.3 hast-util-has-property: 3.0.0 @@ -10223,9 +11044,9 @@ snapshots: transitivePeerDependencies: - supports-color - starlight-sidebar-topics@0.6.2(@astrojs/starlight@0.37.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(typescript@5.9.3)(yaml@2.8.3))): + starlight-sidebar-topics@0.6.2(@astrojs/starlight@0.37.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.22.3)(typescript@5.9.3)(yaml@2.8.3))): dependencies: - '@astrojs/starlight': 0.37.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(typescript@5.9.3)(yaml@2.8.3)) + '@astrojs/starlight': 0.37.7(astro@5.18.1(@types/node@25.6.0)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.22.3)(typescript@5.9.3)(yaml@2.8.3)) picomatch: 4.0.4 static-browser-server@1.0.3: @@ -10235,6 +11056,8 @@ snapshots: mime-db: 1.54.0 outvariant: 1.4.0 + statuses@2.0.2: {} + storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.4(react@19.2.4))(react@19.2.4): dependencies: '@storybook/global': 5.0.0 @@ -10393,6 +11216,8 @@ snapshots: toggle-selection@1.0.6: {} + toidentifier@1.0.1: {} + tough-cookie@5.1.2: dependencies: tldts: 6.1.86 @@ -10417,6 +11242,12 @@ snapshots: tslib@2.8.1: {} + tsx@4.22.3: + dependencies: + esbuild: 0.28.0 + optionalDependencies: + fsevents: 2.3.3 + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 @@ -10425,6 +11256,12 @@ snapshots: type-fest@4.41.0: {} + type-is@2.1.0: + dependencies: + content-type: 2.0.0 + media-typer: 1.1.0 + mime-types: 3.0.2 + typedarray@0.0.6: {} typesafe-path@0.2.2: {} @@ -10542,6 +11379,8 @@ snapshots: unist-util-is: 6.0.1 unist-util-visit-parents: 6.0.2 + unpipe@1.0.0: {} + unstorage@1.17.5: dependencies: anymatch: 3.1.3 @@ -10593,6 +11432,8 @@ snapshots: validate-npm-package-name@5.0.1: {} + vary@1.1.2: {} + vfile-location@5.0.3: dependencies: '@types/unist': 3.0.3 @@ -10629,7 +11470,7 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 - vite@6.4.2(@types/node@25.6.0)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3): + vite@6.4.2(@types/node@25.6.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.22.3)(yaml@2.8.3): dependencies: esbuild: 0.25.12 fdir: 6.5.0(picomatch@4.0.4) @@ -10642,9 +11483,10 @@ snapshots: fsevents: 2.3.3 lightningcss: 1.32.0 terser: 5.46.1 + tsx: 4.22.3 yaml: 2.8.3 - vite@7.3.2(@types/node@25.6.0)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3): + vite@7.3.2(@types/node@25.6.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.22.3)(yaml@2.8.3): dependencies: esbuild: 0.27.7 fdir: 6.5.0(picomatch@4.0.4) @@ -10657,11 +11499,12 @@ snapshots: fsevents: 2.3.3 lightningcss: 1.32.0 terser: 5.46.1 + tsx: 4.22.3 yaml: 2.8.3 - vitefu@1.1.3(vite@6.4.2(@types/node@25.6.0)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3)): + vitefu@1.1.3(vite@6.4.2(@types/node@25.6.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.22.3)(yaml@2.8.3)): optionalDependencies: - vite: 6.4.2(@types/node@25.6.0)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3) + vite: 6.4.2(@types/node@25.6.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.22.3)(yaml@2.8.3) volar-service-css@0.0.70(@volar/language-service@2.4.28): dependencies: @@ -10817,6 +11660,8 @@ snapshots: string-width: 7.2.0 strip-ansi: 7.2.0 + wrappy@1.0.2: {} + ws@8.20.0: {} wsl-utils@0.1.0: diff --git a/scripts/audit-docs.ts b/scripts/audit-docs.ts new file mode 100644 index 000000000..e24da25e2 --- /dev/null +++ b/scripts/audit-docs.ts @@ -0,0 +1,145 @@ +#!/usr/bin/env node +/** + * audit-docs.ts + * + * Diffs the dropins-mcp registry (containers.json, api-functions.json, + * events.json) against the microsite MDX documentation files and writes a + * DOCS-GAPS.md report to the microsite root. + * + * Usage: + * npx tsx scripts/audit-docs.ts [--microsite-path ] [--registry-path ] + * + * --registry-path Path to the dropins-mcp registry directory. + * Defaults to node_modules/@dropins/mcp/dist/registry + * (i.e. the installed npm package). + * + * Exits 1 when gaps are found, 0 when documentation is in sync. + */ + +import { existsSync, writeFileSync, unlinkSync } from 'fs'; +import { join, resolve } from 'path'; +import { fileURLToPath } from 'url'; +import { dirname } from 'path'; +import type { + ContainersRegistry, + ApiFunctionsRegistry, + EventsRegistry, + I18nRegistry, + DropinGaps, +} from './audit-docs/types.js'; +import { isSdkEvent } from './audit-docs/mdx-parsers.js'; +import { auditDropin, auditSdkEvents, readJson, DROPIN_PATH_MAP } from './audit-docs/audit.js'; +import { hasGaps, renderGapsReport } from './audit-docs/report.js'; + +const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url)); +const PROJECT_ROOT = resolve(SCRIPT_DIR, '..'); + +// --------------------------------------------------------------------------- +// CLI args +// --------------------------------------------------------------------------- + +const args = process.argv.slice(2); + +function requireArg(flag: string): string | undefined { + const idx = args.indexOf(flag); + if (idx === -1) return undefined; + if (args[idx + 1] === undefined) { + console.error(`[audit-docs] Error: ${flag} requires a value.`); + process.exit(1); + } + return args[idx + 1]; +} + +const MICROSITE_PATH = resolve(requireArg('--microsite-path') ?? PROJECT_ROOT); +const REGISTRY_PATH = resolve( + requireArg('--registry-path') ?? + join(PROJECT_ROOT, 'node_modules', '@dropins', 'mcp', 'dist', 'registry') +); +const OUTPUT_PATH = resolve(requireArg('--output-path') ?? join(MICROSITE_PATH, 'DOCS-GAPS.md')); + +// --------------------------------------------------------------------------- +// Main +// --------------------------------------------------------------------------- + +function main(): void { + const log = (msg: string) => process.stderr.write(`[audit-docs] ${msg}\n`); + + log(`Microsite path: ${MICROSITE_PATH}`); + log(`Registry path: ${REGISTRY_PATH}`); + + if (!existsSync(MICROSITE_PATH)) { + process.stderr.write( + `[audit-docs] ERROR: Microsite not found at ${MICROSITE_PATH}\n` + + `Pass --microsite-path to override.\n` + ); + process.exit(2); + } + + if (!existsSync(REGISTRY_PATH)) { + process.stderr.write( + `[audit-docs] ERROR: Registry not found at ${REGISTRY_PATH}\n` + + `Pass --registry-path to override, or install @dropins/mcp as a devDependency.\n` + ); + process.exit(2); + } + + const containersRegistry = readJson(join(REGISTRY_PATH, 'containers.json')); + const apiFunctionsRegistry = readJson( + join(REGISTRY_PATH, 'api-functions.json') + ); + const eventsRegistry = readJson(join(REGISTRY_PATH, 'events.json')); + const i18nRegistry = readJson(join(REGISTRY_PATH, 'i18n.json')); + + const allEvents = eventsRegistry.events ?? []; + const sdkEvents = new Set(allEvents.filter(isSdkEvent).map((e) => e.name)); + + log(`SDK-level events (no storefront-* emitter): ${[...sdkEvents].join(', ') || 'none'}`); + + const sdkGaps = auditSdkEvents(allEvents, MICROSITE_PATH); + log( + `common-events.mdx: ${sdkGaps.missingFromDocs.length} missing, ${sdkGaps.phantomInDocs.length} phantom` + ); + + const allGaps: Record = {}; + let totalDropinsAudited = 0; + + for (const [dropinKey] of Object.entries(DROPIN_PATH_MAP)) { + const containers = containersRegistry.dropins[dropinKey]?.containers ?? []; + const functions = apiFunctionsRegistry.dropins[dropinKey]?.functions ?? []; + const i18nKeys = i18nRegistry.dropins[dropinKey]?.keys ?? {}; + + log( + `Auditing ${dropinKey} (${containers.length} containers, ${functions.length} functions, ${Object.keys(i18nKeys).length} i18n keys)` + ); + + allGaps[dropinKey] = auditDropin( + MICROSITE_PATH, + dropinKey, + containers, + functions, + allEvents, + sdkEvents, + i18nKeys + ); + totalDropinsAudited++; + } + + log(`Audited ${totalDropinsAudited} drop-ins`); + + const report = renderGapsReport(allGaps, sdkGaps); + const sdkHasGaps = sdkGaps.missingFromDocs.length > 0 || sdkGaps.phantomInDocs.length > 0; + const anyGaps = sdkHasGaps || Object.values(allGaps).some(hasGaps); + + if (anyGaps) { + writeFileSync(OUTPUT_PATH, report, 'utf8'); + log(`Gaps found — report written to ${OUTPUT_PATH}`); + process.stdout.write(report); + process.exit(1); + } else { + if (existsSync(OUTPUT_PATH)) unlinkSync(OUTPUT_PATH); + log('No documentation gaps found.'); + process.exit(0); + } +} + +main(); diff --git a/scripts/audit-docs/audit.ts b/scripts/audit-docs/audit.ts new file mode 100644 index 000000000..94880bad3 --- /dev/null +++ b/scripts/audit-docs/audit.ts @@ -0,0 +1,309 @@ +import { readFileSync, existsSync } from 'fs'; +import { join } from 'path'; +import type { + ContainerEntry, + DropinGaps, + EventEntry, + FunctionEntry, + SdkEventGaps, +} from './types.js'; +import { + isSdkEvent, + toKebab, + parseMdxProps, + parseMdxFunctions, + parseMdxEvents, + parseMdxDictionaryKeys, + parseMdxSlots, + parseSdkEventNames, +} from './mdx-parsers.js'; +import { + KNOWN_PROP_OMISSIONS, + KNOWN_FUNCTION_ALIASES, + KNOWN_EXTRACTOR_GAPS_FUNCTIONS, + KNOWN_EXTRACTOR_GAPS_EVENTS, + KNOWN_EXTRACTOR_GAPS_SLOTS, +} from './omissions.js'; + +/** Maps dropin package names to their microsite documentation path segments. */ +export const DROPIN_PATH_MAP: Record = { + 'storefront-account': 'dropins/user-account', + 'storefront-auth': 'dropins/user-auth', + 'storefront-cart': 'dropins/cart', + 'storefront-checkout': 'dropins/checkout', + 'storefront-order': 'dropins/order', + 'storefront-payment-services': 'dropins/payment-services', + 'storefront-pdp': 'dropins/product-details', + 'storefront-personalization': 'dropins/personalization', + 'storefront-recommendations': 'dropins/recommendations', + 'storefront-product-discovery': 'dropins/product-discovery', + 'storefront-wishlist': 'dropins/wishlist', + 'storefront-company-management': 'dropins-b2b/company-management', + 'storefront-company-switcher': 'dropins-b2b/company-switcher', + 'storefront-purchase-order': 'dropins-b2b/purchase-order', + 'storefront-quick-order': 'dropins-b2b/quick-order', + 'storefront-quote-management': 'dropins-b2b/quote-management', + 'storefront-requisition-list': 'dropins-b2b/requisition-list', +}; + +export function readJson(path: string): T { + return JSON.parse(readFileSync(path, 'utf8')) as T; +} + +export function micrositeDocPath( + micrositePath: string, + dropinKey: string, + ...segments: string[] +): string { + const docPath = DROPIN_PATH_MAP[dropinKey]; + if (!docPath) return ''; + return join(micrositePath, 'src', 'content', 'docs', docPath, ...segments); +} + +/** Returns true for entries that are TypeScript enums misclassified as functions. */ +function isEnumEntry(fn: FunctionEntry): boolean { + return !!fn.signature?.match(/\(\.\.\.args\):\s*unknown$/); +} + +export function auditDropin( + micrositePath: string, + dropinKey: string, + containers: ContainerEntry[], + functions: FunctionEntry[], + events: EventEntry[], + sdkEvents: Set, + i18nKeys: Record +): DropinGaps { + const gaps: DropinGaps = { + missingContainerPages: [], + missingProps: [], + phantomProps: [], + missingFunctions: [], + phantomFunctions: [], + missingEvents: [], + phantomEvents: [], + missingI18nKeys: [], + phantomI18nKeys: [], + missingSlots: [], + phantomSlots: [], + }; + + const FRAMEWORK_PROPS = new Set(['initialData', 'children', 'scope', 'className']); + + // --- Props per container --- + for (const container of containers) { + container.props = Object.fromEntries( + Object.entries(container.props).filter( + ([prop]) => + !prop.startsWith('__test') && !prop.startsWith('_test') && !FRAMEWORK_PROPS.has(prop) + ) + ); + const containerFile = micrositeDocPath( + micrositePath, + dropinKey, + 'containers', + `${toKebab(container.name)}.mdx` + ); + + if (!existsSync(containerFile)) { + const hasContent = Object.keys(container.props).length > 0 || container.slotNames.length > 0; + if (hasContent) gaps.missingContainerPages.push(container.name); + continue; + } + + const mdxContent = readFileSync(containerFile, 'utf8'); + const docProps = parseMdxProps(mdxContent); + const registryProps = new Set(Object.keys(container.props)); + const PHANTOM_SKIP = new Set([...FRAMEWORK_PROPS, 'slots', 'className']); + + for (const prop of registryProps) { + if ( + !docProps.has(prop) && + !KNOWN_PROP_OMISSIONS.has(`${dropinKey}/${container.name}/${prop}`) + ) { + gaps.missingProps.push({ + container: container.name, + prop, + type: container.props[prop], + reason: 'missing', + }); + } + } + for (const prop of docProps) { + if (!registryProps.has(prop) && !PHANTOM_SKIP.has(prop)) { + gaps.phantomProps.push({ container: container.name, prop, reason: 'phantom' }); + } + } + } + + // --- Functions --- + const publicFunctions = functions.filter( + (f) => + !f.name.startsWith('_') && + !isEnumEntry(f) && + !KNOWN_FUNCTION_ALIASES.has(`${dropinKey}/${f.name}`) + ); + + const functionsFile = micrositeDocPath(micrositePath, dropinKey, 'functions.mdx'); + if (existsSync(functionsFile)) { + const mdxContent = readFileSync(functionsFile, 'utf8'); + const docFunctions = parseMdxFunctions(mdxContent); + const registryFunctions = new Set(publicFunctions.map((f) => f.name)); + + for (const fn of registryFunctions) { + if (!docFunctions.has(fn)) gaps.missingFunctions.push({ fn, reason: 'missing' }); + } + for (const fn of docFunctions) { + if (!registryFunctions.has(fn) && !KNOWN_EXTRACTOR_GAPS_FUNCTIONS.has(`${dropinKey}/${fn}`)) { + gaps.phantomFunctions.push({ fn, reason: 'phantom' }); + } + } + } else if (publicFunctions.length > 0) { + for (const fn of publicFunctions) { + gaps.missingFunctions.push({ fn: fn.name, reason: 'missing' }); + } + } + + // --- Events --- + const eventsFile = micrositeDocPath(micrositePath, dropinKey, 'events.mdx'); + + const emittedEvents = new Set( + events + .filter((e) => !sdkEvents.has(e.name) && e.emittedBy.some((b) => b.dropin === dropinKey)) + .map((e) => e.name) + ); + + if (existsSync(eventsFile)) { + const mdxContent = readFileSync(eventsFile, 'utf8'); + const docEvents = parseMdxEvents(mdxContent); + + const relatedEvents = new Set( + events + .filter( + (e) => + !sdkEvents.has(e.name) && + (e.emittedBy.some((b) => b.dropin === dropinKey) || + e.consumedBy.some((b) => b.dropin === dropinKey)) + ) + .map((e) => e.name) + ); + + for (const ev of emittedEvents) { + if (!docEvents.has(ev)) gaps.missingEvents.push({ event: ev, reason: 'missing' }); + } + for (const ev of docEvents) { + if (!relatedEvents.has(ev) && !KNOWN_EXTRACTOR_GAPS_EVENTS.has(`${dropinKey}/${ev}`)) { + gaps.phantomEvents.push({ event: ev, reason: 'phantom' }); + } + } + } else if (emittedEvents.size > 0) { + for (const ev of emittedEvents) { + gaps.missingEvents.push({ event: ev, reason: 'missing' }); + } + } + + // --- Slots --- + const slotsFile = micrositeDocPath(micrositePath, dropinKey, 'slots.mdx'); + const missingPageSet = new Set(gaps.missingContainerPages); + const containersWithSlots = containers.filter( + (c) => c.slotNames.length > 0 && !missingPageSet.has(c.name) + ); + const registrySlotMap = new Map(containers.map((c) => [c.name, new Set(c.slotNames)])); + + if (existsSync(slotsFile)) { + const mdxContent = readFileSync(slotsFile, 'utf8'); + const docSlots = parseMdxSlots(mdxContent); + + for (const container of containersWithSlots) { + const registrySlots = registrySlotMap.get(container.name)!; + const docContainerSlots = docSlots.get(container.name) ?? new Set(); + for (const slot of registrySlots) { + if (!docContainerSlots.has(slot)) { + gaps.missingSlots.push({ container: container.name, slot, reason: 'missing' }); + } + } + } + for (const [containerName, docContainerSlots] of docSlots) { + const registrySlots = registrySlotMap.get(containerName) ?? new Set(); + for (const slot of docContainerSlots) { + if ( + !registrySlots.has(slot) && + !KNOWN_EXTRACTOR_GAPS_SLOTS.has(`${dropinKey}/${containerName}/${slot}`) + ) { + gaps.phantomSlots.push({ container: containerName, slot, reason: 'phantom' }); + } + } + } + } else if (containersWithSlots.length > 0) { + for (const container of containersWithSlots) { + for (const slot of container.slotNames) { + gaps.missingSlots.push({ container: container.name, slot, reason: 'missing' }); + } + } + } + + // --- Dictionary / i18n keys --- + const dictionaryFile = micrositeDocPath(micrositePath, dropinKey, 'dictionary.mdx'); + const registryI18nKeys = new Set(Object.keys(i18nKeys)); + + if (registryI18nKeys.size > 0) { + if (!existsSync(dictionaryFile)) { + for (const key of registryI18nKeys) { + gaps.missingI18nKeys.push({ key, value: i18nKeys[key], reason: 'missing' }); + } + } else { + const mdxContent = readFileSync(dictionaryFile, 'utf8'); + const docKeys = parseMdxDictionaryKeys(mdxContent); + for (const key of registryI18nKeys) { + if (!docKeys.has(key)) + gaps.missingI18nKeys.push({ key, value: i18nKeys[key], reason: 'missing' }); + } + for (const key of docKeys) { + if (!registryI18nKeys.has(key)) gaps.phantomI18nKeys.push({ key, reason: 'phantom' }); + } + } + } + + return gaps; +} + +/** + * Audit the shared common-events.mdx page against the registry. + * + * Two checks: + * 1. Missing — SDK-level events (no storefront-* emitter, 2+ consumers) must appear in common-events.mdx. + * 2. Phantom — events in common-events.mdx must exist somewhere in the registry. + */ +export function auditSdkEvents(allEvents: EventEntry[], micrositePath: string): SdkEventGaps { + const gaps: SdkEventGaps = { missingFromDocs: [], phantomInDocs: [] }; + + const commonEventsFile = join( + micrositePath, + 'src', + 'content', + 'docs', + 'dropins', + 'all', + 'common-events.mdx' + ); + + const sdkRegistryEvents = new Set(allEvents.filter(isSdkEvent).map((e) => e.name)); + const allRegistryEventNames = new Set(allEvents.map((e) => e.name)); + + if (!existsSync(commonEventsFile)) { + for (const name of sdkRegistryEvents) gaps.missingFromDocs.push(name); + return gaps; + } + + const content = readFileSync(commonEventsFile, 'utf8'); + const docEvents = parseSdkEventNames(content); + + for (const name of sdkRegistryEvents) { + if (!docEvents.has(name)) gaps.missingFromDocs.push(name); + } + for (const name of docEvents) { + if (!allRegistryEventNames.has(name)) gaps.phantomInDocs.push(name); + } + + return gaps; +} diff --git a/scripts/audit-docs/mdx-parsers.ts b/scripts/audit-docs/mdx-parsers.ts new file mode 100644 index 000000000..6a70320fa --- /dev/null +++ b/scripts/audit-docs/mdx-parsers.ts @@ -0,0 +1,220 @@ +import type { EventEntry } from './types.js'; + +/** + * Returns true if the event is SDK-level: fired by the host/boilerplate layer + * (no registry-tracked emitter) and consumed by 2+ distinct storefront-* drop-ins. + * These events have no single owning drop-in and must be documented in common-events.mdx. + */ +export function isSdkEvent(e: EventEntry): boolean { + if (e.emittedBy.length > 0) return false; + const uniqueConsumers = new Set( + e.consumedBy.filter((b) => b.dropin.startsWith('storefront-')).map((b) => b.dropin) + ); + return uniqueConsumers.size >= 2; +} + +/** PascalCase → kebab-case */ +export function toKebab(name: string): string { + return name.replace(/([A-Z])/g, (m, c, idx) => (idx === 0 ? c : '-' + c)).toLowerCase(); +} + +/** + * Parse prop names from MDX content. Handles two formats used in the microsite: + * + * 1. Standard markdown table with `| Parameter |` or `| Prop |` header + * (used by newer drop-in docs and TableWrapper-wrapped tables) + * + * 2. OptionsTable component with array syntax: + * options={[ + * ['Options', 'Type', 'Req?', 'Description'], ← header row, skipped + * ['propName', 'string', 'No', 'description'], ← data rows + * ]} + */ +export function parseMdxProps(content: string): Set { + const props = new Set(); + + // --- Format 1: standard markdown table --- + const headerRe = + /\|\s*(?:Parameter|Prop|Name|Option[s]?)\s*\|[^\n]*\n\|[-| ]+\|([\s\S]*?)(?=\n##|\n<\/TableWrapper>|$)/gi; + let tableMatch: RegExpExecArray | null; + while ((tableMatch = headerRe.exec(content)) !== null) { + const tableBody = tableMatch[1]; + const rowRe = /^\|\s*`?([a-zA-Z_][a-zA-Z0-9_]*)`?\s*\|/gm; + let rowMatch: RegExpExecArray | null; + while ((rowMatch = rowRe.exec(tableBody)) !== null) { + props.add(rowMatch[1]); + } + } + + // --- Format 2: OptionsTable array syntax --- + const optionsBlockRe = /options=\{\[([\s\S]*?)\]\}/g; + let blockMatch: RegExpExecArray | null; + while ((blockMatch = optionsBlockRe.exec(content)) !== null) { + const block = blockMatch[1]; + const rowRe = /\[\s*['"`]([^'"`\]]+)['"`]/g; + let rowMatch: RegExpExecArray | null; + let isFirst = true; + while ((rowMatch = rowRe.exec(block)) !== null) { + const name = rowMatch[1].trim(); + if (isFirst) { + isFirst = false; + continue; + } + if (name.includes('[') || name.includes(']')) continue; + if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) { + props.add(name); + } + } + } + + return props; +} + +/** + * Parse function names from the overview table in a functions.mdx file. + * + * The overview table appears at the top of the file before any per-function + * `## functionName` sections and has a `| Function |` header. We stop parsing + * at the first `## ` heading to avoid matching parameter names from per-function + * detail tables further down the file. + */ +export function parseMdxFunctions(content: string): Set { + const fns = new Set(); + + const firstSectionBreak = content.search(/\n## [a-z]/); + const overviewSection = firstSectionBreak > 0 ? content.slice(0, firstSectionBreak) : content; + + const tableRe = /\|\s*Function\s*\|[^\n]*\n\|[-| ]+\|([\s\S]*?)(?=\n##|\n<\/TableWrapper>|$)/i; + const tableMatch = tableRe.exec(overviewSection); + if (!tableMatch) return fns; + + const tableBody = tableMatch[1]; + const rowRe = /^\|\s*\[?\`([a-zA-Z_][a-zA-Z0-9_]*)`\]?[^|]*\|/gm; + let match: RegExpExecArray | null; + while ((match = rowRe.exec(tableBody)) !== null) { + fns.add(match[1]); + } + return fns; +} + +/** + * Parse event names from an events.mdx file. + * + * Anchors on the Direction column to distinguish event rows from payload-field + * rows or other tables in the same file. Accepted direction values: + * - "Emits" + * - "Listens" + * - "Emits and listens" + * + * Matches table rows in the form: + * | [`event/name`](#anchor) | Emits | description | + * | [event/name](#anchor) | Listens | description | + * | `event/name` | Emits and listens | description | + */ +export function parseMdxEvents(content: string): Set { + const events = new Set(); + const rowRe = + /^\|\s*\[?\`?([a-z][a-zA-Z0-9/_-]*)`?\]?(?:\([^)]*\))?\s*\|\s*(?:Emits and listens|Emits|Listens)/gim; + let match: RegExpExecArray | null; + while ((match = rowRe.exec(content)) !== null) { + events.add(match[1].trim()); + } + return events; +} + +/** Recursively flattens a nested JSON object into dot-notation key-value pairs. */ +export function flattenKeys(obj: Record, prefix = ''): Record { + const result: Record = {}; + for (const [key, value] of Object.entries(obj)) { + const fullKey = prefix ? `${prefix}.${key}` : key; + if (typeof value === 'string') { + result[fullKey] = value; + } else if (value !== null && typeof value === 'object' && !Array.isArray(value)) { + Object.assign(result, flattenKeys(value as Record, fullKey)); + } + } + return result; +} + +/** + * Parse i18n keys from a dictionary.mdx file. + * + * Each dictionary.mdx contains a fenced JSON code block (```json title="en_US.json") + * with the full nested dictionary. We extract and flatten it to dot-notation keys for + * comparison against the registry. + */ +export function parseMdxDictionaryKeys(content: string): Set { + const keys = new Set(); + + const jsonBlockRe = /```json[^\n]*\n([\s\S]*?)```/; + const match = jsonBlockRe.exec(content); + if (!match) return keys; + + try { + const parsed = JSON.parse(match[1]) as Record; + const flat = flattenKeys(parsed); + for (const key of Object.keys(flat)) { + keys.add(key); + } + } catch { + // Malformed JSON — return empty set; the audit will flag everything as missing. + } + + return keys; +} + +/** + * Parse slot names from a slots.mdx file. + * + * The summary table at the top of every slots.mdx associates containers with + * their slot names. Format: + * | [`ContainerName`](#anchor) | `Slot1`, `Slot2`, `Slot3` | + * | [`ContainerName`](#anchor) | None | + * + * Returns a Map of containerName → Set of slot names. + * Containers documented as "None" map to an empty Set. + */ +export function parseMdxSlots(content: string): Map> { + const result = new Map>(); + + const tableRe = + /\|\s*Container\s*\|\s*Slots\s*\|[^\n]*\n\|[-| ]+\|([\s\S]*?)(?=\n##|\n<\/TableWrapper>|$)/i; + const tableMatch = tableRe.exec(content); + if (!tableMatch) return result; + + const tableBody = tableMatch[1]; + const rowRe = /^\|\s*\[`?(\w+)`?\]\([^)]+\)[^|]*\|\s*(.*?)\s*\|/gm; + let rowMatch: RegExpExecArray | null; + + while ((rowMatch = rowRe.exec(tableBody)) !== null) { + const containerName = rowMatch[1]; + const slotsStr = rowMatch[2].trim(); + const slots = new Set(); + + if (slotsStr.toLowerCase() !== 'none' && slotsStr !== '') { + const slotRe = /`([^`]+)`/g; + let slotMatch: RegExpExecArray | null; + while ((slotMatch = slotRe.exec(slotsStr)) !== null) { + slots.add(slotMatch[1]); + } + } + result.set(containerName, slots); + } + + return result; +} + +/** + * Extract event names from the shared common-events.mdx page. + * Each event has a dedicated `## eventName` section heading. + */ +export function parseSdkEventNames(content: string): Set { + const events = new Set(); + // Match level-2 headings that look like event names (may contain camelCase segments, / or -) + const re = /^##\s+[`]?([a-z][a-zA-Z0-9/_-]*)[`]?\s*$/gm; + let match: RegExpExecArray | null; + while ((match = re.exec(content)) !== null) { + events.add(match[1]); + } + return events; +} diff --git a/scripts/audit-docs/omissions.ts b/scripts/audit-docs/omissions.ts new file mode 100644 index 000000000..b5bb97a5d --- /dev/null +++ b/scripts/audit-docs/omissions.ts @@ -0,0 +1,32 @@ +/** + * Props that are present in the TypeScript type but deliberately not documented + * because the container does not expose them as a public API surface. + * Key format: "dropin-key/ContainerName/propName" + */ +export const KNOWN_PROP_OMISSIONS = new Set([ + 'storefront-order/CustomerDetails/withHeader', + 'storefront-account/AddressForm/handleRenderForm', +]); + +/** + * Functions that are re-export aliases of another documented function. + * The registry extracts both the canonical name and the alias; the alias is + * documented inline within the canonical function's page, so flagging it as + * missing would be a false positive. + * Key format: "dropin-key/functionName" + */ +export const KNOWN_FUNCTION_ALIASES = new Set([ + 'storefront-checkout/setShippingMethodsOnCart', // alias of setShippingMethods +]); + +/** + * Functions and events that exist in the drop-in source code but are not yet + * picked up by the registry extractor. The docs are correct; these entries + * should not be flagged as phantom until the extractor is fixed. + * Key format: "dropin-key/name" + */ +export const KNOWN_EXTRACTOR_GAPS_FUNCTIONS = new Set(['storefront-company-management/initialize']); + +export const KNOWN_EXTRACTOR_GAPS_EVENTS = new Set(); + +export const KNOWN_EXTRACTOR_GAPS_SLOTS = new Set(); diff --git a/scripts/audit-docs/report.ts b/scripts/audit-docs/report.ts new file mode 100644 index 000000000..95150b3de --- /dev/null +++ b/scripts/audit-docs/report.ts @@ -0,0 +1,213 @@ +import type { DropinGaps, SdkEventGaps } from './types.js'; + +export function hasGaps(gaps: DropinGaps): boolean { + return ( + gaps.missingProps.length > 0 || + gaps.phantomProps.length > 0 || + gaps.missingFunctions.length > 0 || + gaps.phantomFunctions.length > 0 || + gaps.missingContainerPages.length > 0 || + gaps.missingEvents.length > 0 || + gaps.phantomEvents.length > 0 || + gaps.missingI18nKeys.length > 0 || + gaps.phantomI18nKeys.length > 0 || + gaps.missingSlots.length > 0 || + gaps.phantomSlots.length > 0 + ); +} + +export function renderGapsReport( + allGaps: Record, + sdkGaps: SdkEventGaps +): string { + const date = new Date().toISOString().split('T')[0]; + const lines: string[] = [ + `# Documentation Gaps — Storefront Drop-ins`, + `> Generated: ${date}`, + `> Source: dropins-mcp registry vs microsite MDX files`, + '', + ]; + + let totalGaps = 0; + + // --- SDK / common events section --- + const sdkTotal = sdkGaps.missingFromDocs.length + sdkGaps.phantomInDocs.length; + if (sdkTotal > 0) { + totalGaps += sdkTotal; + lines.push(`## common-events.mdx (${sdkTotal} gaps)`); + lines.push(''); + if (sdkGaps.missingFromDocs.length > 0) { + lines.push('### Missing SDK Events'); + lines.push( + 'Events present in the registry (no storefront-* emitter) but absent from `dropins/all/common-events.mdx`.' + ); + lines.push(''); + lines.push('| Event |'); + lines.push('|---|'); + for (const ev of sdkGaps.missingFromDocs) lines.push(`| \`${ev}\` |`); + lines.push(''); + } + if (sdkGaps.phantomInDocs.length > 0) { + lines.push('### Phantom SDK Events'); + lines.push('Events documented in `common-events.mdx` but absent from the registry.'); + lines.push(''); + lines.push('| Event |'); + lines.push('|---|'); + for (const ev of sdkGaps.phantomInDocs) lines.push(`| \`${ev}\` |`); + lines.push(''); + } + } + + for (const [dropin, gaps] of Object.entries(allGaps)) { + if (!hasGaps(gaps)) continue; + + const dropinTotal = + gaps.missingContainerPages.length + + gaps.missingProps.length + + gaps.phantomProps.length + + gaps.missingFunctions.length + + gaps.phantomFunctions.length + + gaps.missingEvents.length + + gaps.phantomEvents.length + + gaps.missingI18nKeys.length + + gaps.phantomI18nKeys.length + + gaps.missingSlots.length + + gaps.phantomSlots.length; + + totalGaps += dropinTotal; + lines.push(`## ${dropin} (${dropinTotal} gaps)`); + lines.push(''); + + if (gaps.missingContainerPages.length > 0) { + lines.push('### Missing Container Pages'); + lines.push( + 'Containers present in the registry but with no corresponding MDX documentation page.' + ); + lines.push(''); + lines.push('| Container |'); + lines.push('|---|'); + for (const name of gaps.missingContainerPages) lines.push(`| \`${name}\` |`); + lines.push(''); + } + + if (gaps.missingSlots.length > 0) { + lines.push('### Missing Slots'); + lines.push('Slots present in the registry but absent from slots.mdx.'); + lines.push(''); + lines.push('| Container | Slot |'); + lines.push('|---|---|'); + for (const { container, slot } of gaps.missingSlots) + lines.push(`| \`${container}\` | \`${slot}\` |`); + lines.push(''); + } + + if (gaps.phantomSlots.length > 0) { + lines.push('### Phantom Slots'); + lines.push('Slots documented in slots.mdx but not found in the registry.'); + lines.push(''); + lines.push('| Container | Slot |'); + lines.push('|---|---|'); + for (const { container, slot } of gaps.phantomSlots) + lines.push(`| \`${container}\` | \`${slot}\` |`); + lines.push(''); + } + + if (gaps.missingProps.length > 0) { + lines.push('### Missing Props'); + lines.push('Props present in the registry but absent from the container MDX file.'); + lines.push(''); + lines.push('| Container | Prop | Type |'); + lines.push('|---|---|---|'); + for (const { container, prop, type } of gaps.missingProps) { + lines.push(`| \`${container}\` | \`${prop}\` | \`${type ?? ''}\` |`); + } + lines.push(''); + } + + if (gaps.phantomProps.length > 0) { + lines.push('### Phantom Props'); + lines.push( + 'Props documented in MDX but not found in the registry. Verify whether these are valid props or should be removed.' + ); + lines.push(''); + lines.push('| Container | Prop |'); + lines.push('|---|---|'); + for (const { container, prop } of gaps.phantomProps) + lines.push(`| \`${container}\` | \`${prop}\` |`); + lines.push(''); + } + + if (gaps.missingFunctions.length > 0) { + lines.push('### Missing Functions'); + lines.push('Functions present in the registry but absent from functions.mdx.'); + lines.push(''); + lines.push('| Function |'); + lines.push('|---|'); + for (const { fn } of gaps.missingFunctions) lines.push(`| \`${fn}\` |`); + lines.push(''); + } + + if (gaps.phantomFunctions.length > 0) { + lines.push('### Phantom Functions'); + lines.push('Functions documented in MDX but not found in the registry.'); + lines.push(''); + lines.push('| Function |'); + lines.push('|---|'); + for (const { fn } of gaps.phantomFunctions) lines.push(`| \`${fn}\` |`); + lines.push(''); + } + + if (gaps.missingEvents.length > 0) { + lines.push('### Missing Events'); + lines.push('Events present in the registry but absent from events.mdx.'); + lines.push(''); + lines.push('| Event |'); + lines.push('|---|'); + for (const { event } of gaps.missingEvents) lines.push(`| \`${event}\` |`); + lines.push(''); + } + + if (gaps.phantomEvents.length > 0) { + lines.push('### Phantom Events'); + lines.push('Events documented in MDX but not found in the registry.'); + lines.push(''); + lines.push('| Event |'); + lines.push('|---|'); + for (const { event } of gaps.phantomEvents) lines.push(`| \`${event}\` |`); + lines.push(''); + } + + if (gaps.missingI18nKeys.length > 0) { + lines.push('### Missing Dictionary Keys'); + lines.push('i18n keys present in the registry but absent from dictionary.mdx.'); + lines.push(''); + lines.push('| Key | Default Value |'); + lines.push('|---|---|'); + for (const { key, value } of gaps.missingI18nKeys) { + const escaped = (value ?? '').replace(/\\/g, '\\\\').replace(/\|/g, '\\|'); + lines.push(`| \`${key}\` | ${escaped} |`); + } + lines.push(''); + } + + if (gaps.phantomI18nKeys.length > 0) { + lines.push('### Phantom Dictionary Keys'); + lines.push('i18n keys documented in dictionary.mdx but not found in the registry.'); + lines.push(''); + lines.push('| Key |'); + lines.push('|---|'); + for (const { key } of gaps.phantomI18nKeys) lines.push(`| \`${key}\` |`); + lines.push(''); + } + } + + if (totalGaps === 0) { + lines.push( + 'No documentation gaps found. All registry entries are reflected in the microsite docs.' + ); + } else { + lines.unshift(`> **Total gaps: ${totalGaps}**`, ''); + } + + return lines.join('\n'); +} diff --git a/scripts/audit-docs/types.ts b/scripts/audit-docs/types.ts new file mode 100644 index 000000000..03ffec0d9 --- /dev/null +++ b/scripts/audit-docs/types.ts @@ -0,0 +1,104 @@ +// --------------------------------------------------------------------------- +// Registry types (subset used for auditing) +// --------------------------------------------------------------------------- + +export interface ContainerEntry { + name: string; + props: Record; + slotNames: string[]; +} + +export interface DropinContainers { + version: string; + containers: ContainerEntry[]; +} + +export interface ContainersRegistry { + dropins: Record; +} + +export interface FunctionEntry { + name: string; + signature?: string; +} + +export interface DropinFunctions { + version: string; + functions: FunctionEntry[]; +} + +export interface ApiFunctionsRegistry { + dropins: Record; +} + +export interface EventEntry { + name: string; + emittedBy: { dropin: string }[]; + consumedBy: { dropin: string }[]; +} + +export interface EventsRegistry { + events: EventEntry[]; +} + +export interface I18nDropinEntry { + version: string; + keyCount: number; + keys: Record; +} + +export interface I18nRegistry { + dropins: Record; +} + +// --------------------------------------------------------------------------- +// Gap types +// --------------------------------------------------------------------------- + +export interface PropGap { + container: string; + prop: string; + type?: string; + reason: 'missing' | 'phantom'; +} + +export interface FunctionGap { + fn: string; + reason: 'missing' | 'phantom'; +} + +export interface EventGap { + event: string; + reason: 'missing' | 'phantom'; +} + +export interface I18nGap { + key: string; + value?: string; + reason: 'missing' | 'phantom'; +} + +export interface SlotGap { + container: string; + slot: string; + reason: 'missing' | 'phantom'; +} + +export interface DropinGaps { + missingContainerPages: string[]; + missingProps: PropGap[]; + phantomProps: PropGap[]; + missingFunctions: FunctionGap[]; + phantomFunctions: FunctionGap[]; + missingEvents: EventGap[]; + phantomEvents: EventGap[]; + missingI18nKeys: I18nGap[]; + phantomI18nKeys: I18nGap[]; + missingSlots: SlotGap[]; + phantomSlots: SlotGap[]; +} + +export interface SdkEventGaps { + missingFromDocs: string[]; // in registry (SDK-level) but absent from common-events.mdx + phantomInDocs: string[]; // in common-events.mdx but absent from registry +}