From 9dab6839826d47f721a7a17821acfa5a120fbcb9 Mon Sep 17 00:00:00 2001 From: knowledgecode Date: Sun, 1 Nov 2026 16:43:59 +0900 Subject: [PATCH 1/9] ci: run type check and build before tests Building first lets tests/build/ check the CJS interop and .d.cts output instead of skipping when dist/ is missing. --- .github/workflows/test.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f230b7b..426ffe0 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -33,6 +33,12 @@ jobs: - name: Run linter run: npm run lint + - name: Run type check + run: npm run ts + + - name: Build + run: npm run build + - name: Run tests run: npm test From cefa47ba7c42f22e0fdfb10b02ec86ba8899c205 Mon Sep 17 00:00:00 2001 From: knowledgecode Date: Sun, 1 Nov 2026 16:44:02 +0900 Subject: [PATCH 2/9] ci: pin codecov-action and scope Pages permissions to jobs Move pages: write and id-token: write off the workflow level so only the deploy job holds them; the build job gets read-only access. --- .github/workflows/deploy-docs.yml | 5 +++-- .github/workflows/test.yml | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index d9a5bac..c52fb97 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -12,8 +12,6 @@ on: permissions: contents: read - pages: write - id-token: write concurrency: group: pages @@ -23,6 +21,9 @@ jobs: build: runs-on: ubuntu-latest timeout-minutes: 10 + permissions: + contents: read + pages: read steps: - name: Checkout uses: actions/checkout@v7.0.1 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 426ffe0..6d5d9a0 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -66,7 +66,7 @@ jobs: run: npm run test:coverage - name: Upload coverage to Codecov - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@v5.5.5 with: token: ${{ secrets.CODECOV_TOKEN }} files: coverage/lcov.info From d240b2428bbaaff4a8f90d9a6c1080873b5b99ae Mon Sep 17 00:00:00 2001 From: knowledgecode Date: Sun, 1 Nov 2026 16:44:11 +0900 Subject: [PATCH 3/9] chore(deps): update devDependencies --- package-lock.json | 718 ++++++++++++++++++++++++---------------------- package.json | 14 +- 2 files changed, 376 insertions(+), 356 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4787a46..1ba55d4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,23 +9,23 @@ "version": "4.7.0", "license": "MIT", "devDependencies": { - "@astrojs/starlight": "^0.42.7", + "@astrojs/starlight": "^0.42.8", "@eslint/js": "^10.0.1", "@rollup/plugin-alias": "^6.0.1", "@rollup/plugin-terser": "^1.0.2", "@stylistic/eslint-plugin": "^5.10.0", - "@types/node": "^26.6.5", + "@types/node": "^26.6.6", "@vitest/coverage-v8": "^5.0.5", - "astro": "^7.4.2", - "eslint": "^10.13.0", - "glob": "^13.0.6", + "astro": "^7.4.4", + "eslint": "^10.14.0", + "glob": "^14.0.3", "prettier": "^3.9.10", - "rollup": "^4.65.0", + "rollup": "^4.67.3", "rollup-plugin-dts": "^6.5.1", "rollup-plugin-esbuild": "^6.2.1", "tsx": "^4.23.15", "typescript": "^6.0.3", - "typescript-eslint": "^8.72.0", + "typescript-eslint": "^8.72.1", "vitest": "^5.0.5" }, "engines": { @@ -269,27 +269,27 @@ } }, "node_modules/@astrojs/markdown-satteri": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/@astrojs/markdown-satteri/-/markdown-satteri-0.4.5.tgz", - "integrity": "sha512-0IeGdoFbv0f+442KJhYS44Wg8F3MuHmRsxIEYuFyqkjRubc6dPBFZ7azor5t4AeXLQoT5A5h9HyViKpd70Dl9w==", + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/@astrojs/markdown-satteri/-/markdown-satteri-0.4.6.tgz", + "integrity": "sha512-6biKp2lEAYycF3jhv91br+Otyf4EgDFkF1oRL9ks0u/m/YRGmI7XkGQ2MgaM35DslT03f7NtozKtlqfBNkp6bw==", "dev": true, "license": "MIT", "dependencies": { "@astrojs/internal-helpers": "0.13.0", - "@astrojs/prism": "4.1.1", + "@astrojs/prism": "4.1.2", "github-slugger": "^2.0.0", "satteri": "^0.10.5" } }, "node_modules/@astrojs/mdx": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@astrojs/mdx/-/mdx-8.1.1.tgz", - "integrity": "sha512-jEJUJsO2KqmKfBXaKeDHDCCj+Kerj1Fj+XndHznF9wxahvs+1onYCBeKmieM28N2+uA6mW57DOQQw5YaDLdBnA==", + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/@astrojs/mdx/-/mdx-8.1.2.tgz", + "integrity": "sha512-ZIUVfosVtK4SKcFrGOH+1+HwG0encjxQOxu76M9VuTqeQNZWQ//2eY2Iz+W1eq87AOT5JD4wOHyZ8xFwlcFteg==", "dev": true, "license": "MIT", "dependencies": { "@astrojs/internal-helpers": "0.13.0", - "@astrojs/markdown-satteri": "0.4.5", + "@astrojs/markdown-satteri": "0.4.6", "es-module-lexer": "^3.0.3" }, "engines": { @@ -307,9 +307,9 @@ } }, "node_modules/@astrojs/prism": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-4.1.1.tgz", - "integrity": "sha512-sXlAXJX6t4QfuLg+CuCDzpg7NoxWcyb4paFprgtFppLeisCBmh935h+tJ5CWXfsXEoW2IDy/ihbRMtiu28Chjw==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-4.1.2.tgz", + "integrity": "sha512-jMrUEpFDarDO1KWPvVc9eSa8DSfwBlwEOHwX+8zvZQpiqXRGDxFnOXHsYqV6DP7w+0qIgTr98gS1GdQlm8ypWg==", "dev": true, "license": "MIT", "dependencies": { @@ -331,9 +331,9 @@ } }, "node_modules/@astrojs/starlight": { - "version": "0.42.7", - "resolved": "https://registry.npmjs.org/@astrojs/starlight/-/starlight-0.42.7.tgz", - "integrity": "sha512-mlbit5iRjLx5eIcLf84Q2CwkrrsEgZrQwKKBK+vRf+ZGiSrwy1UGdT1hUfAIaHrMfcvkDpL+gw3aua7HobiKFg==", + "version": "0.42.8", + "resolved": "https://registry.npmjs.org/@astrojs/starlight/-/starlight-0.42.8.tgz", + "integrity": "sha512-BGP8bmTbdky4OFCV9BNWZedLuzONyUtz754q+hie+li/2TQ5XJ6nvfO8fhRhIMcCpUEsA5Ynf4qTTFf/ft/3Pg==", "dev": true, "license": "MIT", "dependencies": { @@ -377,9 +377,9 @@ } }, "node_modules/@astrojs/telemetry": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.4.1.tgz", - "integrity": "sha512-SMkvMsGOpM0FMAoT5pzhgI3LZC0JSPWf7Evwop+fZ3N6UkusPM7lI+sOJjMNI5OJrVoiei1/AGo1cY7sikTc5A==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.4.2.tgz", + "integrity": "sha512-2JOMRUxJrBSfiVDfeKLv1wBmvSIx1Y6u2YEO8awZ9qSq3u/rNAiUyFdOYi8dHv91kHrmYEQX7pRDw0J4xyj3UA==", "dev": true, "license": "MIT", "dependencies": { @@ -439,9 +439,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.29.11", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.11.tgz", - "integrity": "sha512-OZ6+oaK7GMyg3IfCpj8JOmn8n+w2rJbDT0LLfVDTLb1ZFeKDh3AiNELgCMUw175IJHSkLl74hG0M0VLsvx+gag==", + "version": "7.29.12", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.12.tgz", + "integrity": "sha512-WJ7JBp/Q4+z/ImydtI7jS6NVco5++632ExBemSX+Ysb+G1lCwQ5BVo3SY+jGGOcZXI4ZccbZSUSJLNBW6eEpJg==", "dev": true, "license": "MIT", "dependencies": { @@ -723,9 +723,9 @@ } }, "node_modules/@ctrl/tinycolor": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-4.2.1.tgz", - "integrity": "sha512-Vh5uy9Y1JBMId6J1f68TMXnZrTCvNdo9Fu2k0d1YnJngR+sM5kWTKl441c/3TFs+cG0NWOjRWgQ/iaWhbYx+7A==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-4.2.2.tgz", + "integrity": "sha512-9rQHijqB2Rq6qOEC/xHaA6aPlsKGi5kmCQW50O1asn9g63XFeD5NmBwysriistW5Xx0JPafyD/TA7yk2S3pXGQ==", "dev": true, "license": "MIT", "engines": { @@ -2027,6 +2027,13 @@ "url": "https://opencollective.com/libvips" } }, + "node_modules/@isaacs/nonrecursive-glob-match": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@isaacs/nonrecursive-glob-match/-/nonrecursive-glob-match-1.0.3.tgz", + "integrity": "sha512-SI7kyKHq4XXDRozw+r9GlRZkia1ZkFrpLW98r2IC2Bpr8YkFGE3fvjzmxCG0x78A++69HmDNrDvSMYBZmHGpKA==", + "dev": true, + "license": "BlueOak-1.0.0" + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", @@ -2133,9 +2140,9 @@ } }, "node_modules/@napi-rs/wasm-runtime": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.5.tgz", - "integrity": "sha512-HshSvXzmBxNzqejd3k/KemgQ3hdREUYFRRrgxOZ+gPljDIsO2SDZrVZMd4Z/HsxudQbE62OVyVFE8z9BCurfjA==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.6.tgz", + "integrity": "sha512-mRyDmEw9/fCDXCGfL1sbgIw/GUK0PVxRW4YwgPN61F3LQ+fSyoBFarJVzgGyhF6kRzEQZ0FejDqm4WLXSeqQmw==", "dev": true, "license": "MIT", "optional": true, @@ -2150,8 +2157,8 @@ "url": "https://github.com/sponsors/Brooooooklyn" }, "peerDependencies": { - "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4", - "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4" + "@emnapi/core": "^1.7.1 || 2.0.0-beta.2", + "@emnapi/runtime": "^1.7.1 || 2.0.0-beta.2" } }, "node_modules/@oslojs/encoding": { @@ -2162,9 +2169,9 @@ "license": "MIT" }, "node_modules/@oxc-project/types": { - "version": "0.155.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.155.0.tgz", - "integrity": "sha512-SeE8JPwW1xs1tHeNycjUtUBdhorRa8o4jlvjwk49R7/Z291i+4DQa7JJIgOm/TaYQZx+QrPQbVJ/9c8dMIZN8Q==", + "version": "0.156.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.156.0.tgz", + "integrity": "sha512-1Duyg48TdJNdyhEB8Xn1L36bT9Pv6GUtlKjHxOys8xkaF/rQq3XJE+bAurSK/AgIz5mGFsb77cn9Pb20+WCScw==", "dev": true, "license": "MIT", "funding": { @@ -2277,9 +2284,9 @@ ] }, "node_modules/@rolldown/binding-android-arm-eabi": { - "version": "1.2.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.15.tgz", - "integrity": "sha512-aLcgK9gIJ3YRvrrtfSBbRa27F5WrpiTaPulnFpsHPxpUHgFlSgnU4854MHwoRGEBhfRJDWCS2WQ7lIjskE9Olw==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.16.tgz", + "integrity": "sha512-ia3DwAs0OsMGS7+IConptSiyk9pEXkOx/AbJ2n/lAGxH3QkWQus1t8d7gnAT38FCU2sQu8lUbeR6AiZFv4JxaA==", "cpu": [ "arm" ], @@ -2294,9 +2301,9 @@ } }, "node_modules/@rolldown/binding-android-arm64": { - "version": "1.2.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.15.tgz", - "integrity": "sha512-xD7DdZCrbThKuxNg7ooQmvp07ys4J/pnSEMTG3/OdOWl6daC67m/Q4fL78sRHMxTH/N4fGUbYhcPM0MF5WFHkg==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.16.tgz", + "integrity": "sha512-kx5wBiMB6E7TEvpl2B9gjLU004BkvEm2Dr941BFjx/SontPwSzNuQUIoVKxHHoSjpFIfHMmcguyLOtyn0hObRg==", "cpu": [ "arm64" ], @@ -2311,9 +2318,9 @@ } }, "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.2.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.15.tgz", - "integrity": "sha512-m2WuQ6r0B4OTYxyPpNLtXaMRbRDUbG8YQV2Q3KTdSSK8Th6KHCnC8jVCJt8bvYeSB5WivkkNbc85mKadaSdOxA==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.16.tgz", + "integrity": "sha512-qslZrXnKJU4cUpjoAmtAo/KQM9e2IRMlmpig6Zpwj+8KWxW8v+nkAf9216Bsek9lOC1jvg2yCjygCFo2f83msQ==", "cpu": [ "arm64" ], @@ -2328,9 +2335,9 @@ } }, "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.2.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.15.tgz", - "integrity": "sha512-5RtnsHM36nodM9WbMy+zip0LGS/G+y5wro5RHrpOlr4ac24+1zSi9kiV2MP1myZeZ/ifEHfulQcWjnAXzc2C2A==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.16.tgz", + "integrity": "sha512-FdF+y48ND13eAyM2mQn+85kvAqNlvRWROy2rhgA463X/0Gv4vGtazZtfaF1mRBLscYvtOlh4QnLjOWiFzX69OQ==", "cpu": [ "x64" ], @@ -2345,9 +2352,9 @@ } }, "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.2.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.15.tgz", - "integrity": "sha512-g3l09pyFqhu+135JKkbkwiKGQmwU5hUMUPJ4VdBADvuqR8d33L6H578rh8m7rtxbdp+VmX/+nzI7nvhSZlzpUQ==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.16.tgz", + "integrity": "sha512-ddjqFM5e95AgLbUPtKIS7V1KTVlA0RUgCVr5mn+/IEhsdy3pr+Vuj/HZ7nlMN2FyxIwUktOH1LEPIQXO1v9y1Q==", "cpu": [ "x64" ], @@ -2362,9 +2369,9 @@ } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.2.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.15.tgz", - "integrity": "sha512-nIe3VugI97nGQtspPxDqA4sXMUpeiocKIP/CqpY/u/vgbT+alX+cVxu1C/oVBPKg4feNTmYovE91v4DgXvXNwQ==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.16.tgz", + "integrity": "sha512-tHdKWbFkFBI687iim3LIyIvyL7j66VvQYkDPss5Stn/qyE2tWkR1YD0dXmXPFKKqT/o5ZEJVsaRsWS2meQwGOA==", "cpu": [ "arm" ], @@ -2379,9 +2386,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.2.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.15.tgz", - "integrity": "sha512-iTBjXx+B5QSvgI89lJfmqh4wTh8NabR1YZIIN3hNx4zSG0EVfVqkOvLulNpG4251pbd6/IAmZ/LefVk1Y4rPhw==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.16.tgz", + "integrity": "sha512-FJiLGAblPBMlBEdbOqw6kW6QcXDWAf/oJu7gYs9ZJZwmg+K+/zjFLxPTIY9izJUzxzc24FHvmseyA0IvJSl17w==", "cpu": [ "arm64" ], @@ -2399,9 +2406,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.2.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.15.tgz", - "integrity": "sha512-uN26XOnVR7rqQupG3V9oAG2EGGatWjcJHOeDOHUFCh4TBWmP2tHTFoVN13aYbwfm0aHqJAEmcwhAu6sooIjfqQ==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.16.tgz", + "integrity": "sha512-hrJpblMsrQ58U9veWpbXzkhV5zStunds6HWLprqq1qauvgBr1E6P+24kLj6lSLI9vjRn/RYpjprhkHQPKGWpNg==", "cpu": [ "arm64" ], @@ -2419,9 +2426,9 @@ } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.2.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.15.tgz", - "integrity": "sha512-9nWkcdd+H+XhaA3fQIwpHnKIrfx/PQ6rO0pivr78Og07tXlUlctBBJoEYLPfhTmCR/QxEVdn6uPjHV5SymPhdw==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.16.tgz", + "integrity": "sha512-qJd/dC6j6CwLG9/s/RP2nb1RZ0GIgj7Ioj7x/SYa3RzjVrlzrmH0fhIOpfvqQDeIsdP0loi+kHaMhJzY1PBIaA==", "cpu": [ "ppc64" ], @@ -2439,9 +2446,9 @@ } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.2.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.15.tgz", - "integrity": "sha512-Ggh0ciFjLwIusLSLz7LZYEaGdxOAUJXI+Qu5JCbhPJJHEt8vP+IjRATTJheiJsdzzTYgUiHUiw3X1Ea3ZpMBdA==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.16.tgz", + "integrity": "sha512-Vx7Xg5uUJuNcujJjI70OICaH0EYj80BtOLZTSN7uOYg8QOLlyKnaG0IW7Fn/J0IpJsaKzmDKMhOQv1JBM9m9vg==", "cpu": [ "s390x" ], @@ -2459,9 +2466,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.2.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.15.tgz", - "integrity": "sha512-FHg60rS6DBePAYZ9X9F67x+JObFdmgn6tupA1C/a3B+CufFmTD4mX+e8M75tCiAO3foR/6xwVBI0KQiI7sn/rw==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.16.tgz", + "integrity": "sha512-TNKhgE3uJTsTzatUSSYt0Kgo+Oa2uSlSjz4r1aEIea7HX6ULBym4fAlYUhG1i6pjNf2njfCUAfKwr6C3E9Xg1w==", "cpu": [ "x64" ], @@ -2479,9 +2486,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.2.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.15.tgz", - "integrity": "sha512-/cvV/7v5VGz/moiz0XKRj2dE8DzsKyhIu1KpOvJGPjRywg3yscON889UGvAe8zfiJLHup7VLjBduoGWi3HusWQ==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.16.tgz", + "integrity": "sha512-7chXdpjXZ8qG0+mIxECN3cT9kvhZ3/oZhMX6Pp876P7CDrIy8nJswva6Mq357JR7eYXfuskwZxMeV1SzoZdHrA==", "cpu": [ "x64" ], @@ -2499,9 +2506,9 @@ } }, "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.2.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.15.tgz", - "integrity": "sha512-MyzC5Hrv/sm+Z7TSGKP/j8001RO2xQm1zOpCNVL4j0cY/VhBZviludA2YFQ7i4lH6ZAXxQm0lcMdBzM+99mE7w==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.16.tgz", + "integrity": "sha512-Kwjt+7uNTJK5/MDkGWGVO2KQPnj8yAV75dMpfwyHZrJSXWHrniOB0aUEWlVYf3H1hOqFLIStLdM5QXq6bnKmOQ==", "cpu": [ "arm64" ], @@ -2516,9 +2523,9 @@ } }, "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.2.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.15.tgz", - "integrity": "sha512-+PgYiS+AH5omy6L45ZLxybasauJaj3M8buoT83D+nzPmCayXlxUV9hydhciCKVyIg0B/v0BtXPDE1uGqNwCPpg==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.16.tgz", + "integrity": "sha512-/LH6WfjDRXXJz/p5xl4TmU+jpcnwcxbKEQBW/GZE0JHfN0lGIyTtsUEGaQ/q/GikkGJ2yLKe6pwm7AnEWO8pdw==", "cpu": [ "arm64" ], @@ -2533,9 +2540,9 @@ } }, "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.2.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.15.tgz", - "integrity": "sha512-HFZd2QNQYn1JbIi+Hpd7H+r/lkWxcfIu28nirZ6eCn2LafuvmExMlb/P96Sfx5tf7pPArw39IdhmCF8vmV+NhQ==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.16.tgz", + "integrity": "sha512-1lv1KvX0Z871zfk7vw+dnXMMnHNyDwMzWG8Kv3HxDXMOhzCX4SHc7HK319fInP0i+0p9D8brkfzL7pJOaGl+tw==", "cpu": [ "x64" ], @@ -2598,9 +2605,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.65.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.65.0.tgz", - "integrity": "sha512-t2AnVba25baFdq7gczzS13JyVcdubLVbFX1X04mxrggDrTQPUXNv3XM0k9H1hr5tqvg7AVvtQ720QHAj0iYqhg==", + "version": "4.67.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.67.3.tgz", + "integrity": "sha512-o4kGHKu2YRn/jegh1XMs6+1/3SuX6AfWaACGEWavFvN5D6YZd9OrMEBqcIMj0uTeKZr6nTXPhlpkc0IXC6DMXQ==", "cpu": [ "arm" ], @@ -2612,9 +2619,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.65.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.65.0.tgz", - "integrity": "sha512-dNONUaEwPGhl/nuO2KV8VABWlcjYyU6KtZGN8dQv5OS5JU7JSCxPijVNKXbRJd0iuTzTiJ4TjPt/4bbvDRNiMQ==", + "version": "4.67.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.67.3.tgz", + "integrity": "sha512-vfEEFajQ0K5crrtAAyownI2ZFthoY+BTwGnjoMgd4+l3YPuAcweykaMqcMYXT1wJKCnMiSIpNnAroAWix2fJ3w==", "cpu": [ "arm64" ], @@ -2625,10 +2632,24 @@ "android" ] }, + "node_modules/@rollup/rollup-android-x64": { + "version": "4.67.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-x64/-/rollup-android-x64-4.67.3.tgz", + "integrity": "sha512-/oNPEUU5nVDZmp1CYGDMIGdUBzON5z5RQufJbtjnOD4+CZYt//2ECHRvvmJL3EXLHaqQ7Zjr1dSTlhLCxJJbGQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.65.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.65.0.tgz", - "integrity": "sha512-zWQqUH+9zavr2Bxuzfpuv2SIF3X31cr58TvSQC9o1GhpOvkqRwr60GkZdQcudyT/BEgdpdSafjgd2I13MbTL7g==", + "version": "4.67.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.67.3.tgz", + "integrity": "sha512-Otbw33hEDwrM/jUn3nib5JLJL0vyTE0ZlmU8L44sCS+AJm0JiZs3ZlNUYj141L4k7XxYmOWtf+9cN2Kqog7OzA==", "cpu": [ "arm64" ], @@ -2640,9 +2661,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.65.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.65.0.tgz", - "integrity": "sha512-RQYreBFWtO4//hIuOaZkYUnF/lPU4lz35dveDimDshWCJvVisVtJ/shmT9bkXK8wFJY+FJF89X6F3Cq1qI3LCw==", + "version": "4.67.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.67.3.tgz", + "integrity": "sha512-3CNtrc+6X9HL+fzSkKF0o3WkBdO6YBm5PhbLnR9PeQNKLLL7ir4MDtlx6gvP9ZM3Uxjue3xVysAX7+VjWX66Ng==", "cpu": [ "x64" ], @@ -2654,9 +2675,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.65.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.65.0.tgz", - "integrity": "sha512-A0NfMj6Cuh/9BE5k3awJKv6HoxFVXIcLAb6SZqAMoxUHPA1ZNNK4RsGuUPD/vL7nEAm9LG+ZzXWWTrnC0XtkpA==", + "version": "4.67.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.67.3.tgz", + "integrity": "sha512-KfHwLGjSfgOKHoyzhqqKNhohxNErfYRR2dNWXN6kn5iWMrDNldZopob+Ft/q6aurweYHRz+7M9HuFZ7nvYj5Xg==", "cpu": [ "arm64" ], @@ -2668,9 +2689,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.65.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.65.0.tgz", - "integrity": "sha512-BI6/H7q3aP0I7S7GOrjyxTjgEJlSnovXE38+bdxBpuKN6z+d//uF+T+VQ3Q7ltJL/71p17ufartARX9Ja5gOGQ==", + "version": "4.67.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.67.3.tgz", + "integrity": "sha512-fXWMWNshsQrNi9pq8FJIpTZfLjhLUqDCabW1hq2Qv1kxzz7I63fRjFRNAC0C49xK9CyUngL/tWbSYjpKo2+GRg==", "cpu": [ "x64" ], @@ -2682,9 +2703,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.65.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.65.0.tgz", - "integrity": "sha512-W1vUprf09RWaVWnsFP1vlUkEWJzTZlpObOEAYZXt9Fq0UVAOYEkeGr7wBX7McKqqIQskXdBnpiOMgwPujordgA==", + "version": "4.67.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.67.3.tgz", + "integrity": "sha512-22gepfGL1b0Aay36BYddC4mqvQoUgQwGU/5zrUK2BdJucWgWytbhxY4o3iSIbtZsSsFiiRlNT2xfAjrCsDQGQw==", "cpu": [ "arm" ], @@ -2699,9 +2720,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.65.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.65.0.tgz", - "integrity": "sha512-s8QTcZWgrl9haFzEGIqyE5BWyo89pFDGLMBFZ752WYxk8DJwNU/O1X6pZgPw829d9/sm6CCHyrMP3aurt76p1Q==", + "version": "4.67.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.67.3.tgz", + "integrity": "sha512-l04417gOo3y7xaQu52PeXGgy17dSPAa8qhs4iqxMDHKyAUpldNFsasy0kR+Z7CFifnTgwFGmyukDWLIZYEnyQQ==", "cpu": [ "arm" ], @@ -2716,9 +2737,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.65.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.65.0.tgz", - "integrity": "sha512-ke1f6dLRzkqveyjjF2fkEwQYZvxHtNNwjegY8nJrwcO0Bdqr8CzFO/pKE0Bns13cx0qz2Ba2Y0Hs3dSwMdnHxA==", + "version": "4.67.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.67.3.tgz", + "integrity": "sha512-0SEhbnWkUv29OhSANlnnOKQSWs5KFoJ0FTQ3ZhxZunUjgBagQzzUmLgxpulYSpldXAGOCK5XLvvspoPngjEWpQ==", "cpu": [ "arm64" ], @@ -2733,9 +2754,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.65.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.65.0.tgz", - "integrity": "sha512-926SMeUcy4y18Rz/w2aJiUKOnyAnm6czg72bXkQEaeemsll+Wr0hnsjb2BGRpHvWgwAMYy5ACJCotbvfLCfj0A==", + "version": "4.67.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.67.3.tgz", + "integrity": "sha512-2wLIbgSqKUcEc4DHrQDHOg9LSfgfSr+rAoBj9wromzLMLSclupvEKHTEugGSuGuklrF7wF0dzXo9R5VymKXgcg==", "cpu": [ "arm64" ], @@ -2750,9 +2771,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.65.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.65.0.tgz", - "integrity": "sha512-6T7JNRP1hc4hqF2dUsEoVLOt9K8tmODoCLldtQRYnrddGGQY8Gqe2pM/qMMUo7EMowpP7oa2N95k0/8sYK/ipw==", + "version": "4.67.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.67.3.tgz", + "integrity": "sha512-cV3cQixj3ILfdOmvJeXu6GedaH/Xlm4/qtNAUxvVK0tQnzICits97mwuvWY/DZs0lEZTkbCqZmpO/+ne6hs5iQ==", "cpu": [ "loong64" ], @@ -2767,9 +2788,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.65.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.65.0.tgz", - "integrity": "sha512-SImGFl1Je5kpyAgOCPONVT7h6ASV8mAUwGRjY7eZvVjPg//PfHOXgI+P241RF/+HqsA4PP3qD527ysWFKNQyhQ==", + "version": "4.67.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.67.3.tgz", + "integrity": "sha512-DTnriHdEmvrGgPWHVoV8LfwkLsmG2oK9GYvlfV6+beMcdVWVYnNC3R6+jL9DhTVOIpv+Ys9A+1i9rM8aeayOZw==", "cpu": [ "loong64" ], @@ -2784,9 +2805,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.65.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.65.0.tgz", - "integrity": "sha512-XeDTbmPF1Yu5asfXGPrMkWoxTDhgryQbmw5Q1+R582O51VNCk23J6f2pDrsAp5YkneBVBwtExx6ZGOb9D2aQ6A==", + "version": "4.67.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.67.3.tgz", + "integrity": "sha512-2+v1frx+8t084SIinkBBURODj1lpTqLZO53INfozQa0+bnCNEGtRFag8Gi6OMV9kEK67zIRIqncfyKe1eIYGHA==", "cpu": [ "ppc64" ], @@ -2801,9 +2822,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.65.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.65.0.tgz", - "integrity": "sha512-VS55JUI/1nsljmV/jfqNkLZXFw8uMO8nNlfoHmSevNf6fO3neuhyDvx9dv3c/Ytt8r/431SL8Qax1dpYvOMZTg==", + "version": "4.67.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.67.3.tgz", + "integrity": "sha512-vEi902pAjMHXPXOpU4Jr58jMMiZxTf8kkhis1xiLBtLtlm6oRaX+mgFjOsqMdbGt80lS+bfnTCEsAofbK9isLA==", "cpu": [ "ppc64" ], @@ -2818,9 +2839,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.65.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.65.0.tgz", - "integrity": "sha512-Vblw84TbX7RS4la1Y4+yQ7aore/oSyaNtFbppuBr5Vs/4LfBeXKq9dIfoExw6zOvRERqd2rRAjnZRaMhH/0x5w==", + "version": "4.67.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.67.3.tgz", + "integrity": "sha512-1Nm/kYmkKDcc9gJ9cRVsRPBrNUqLEaY5b2zDk2OsQMcWd2nJiFUpQf3q4T1IEVKgyUQSMuiVNDemLXcuKh/f9Q==", "cpu": [ "riscv64" ], @@ -2835,9 +2856,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.65.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.65.0.tgz", - "integrity": "sha512-7+gHjtONvKgwR9InTKFaLq53f6YzBJkgeMRBENdWTsQr+spahGqQm8HF5aXpq8i4JaRrOqYyv6Zn1WltDTxaZQ==", + "version": "4.67.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.67.3.tgz", + "integrity": "sha512-bx93yN/wit1aY9lja1lRh2jfRPFDBfeI9kHoytXDi1Jw6dWz2P2zd6B3oKnQOHa5fTtpHmX9/swWOA2+jWLjKw==", "cpu": [ "riscv64" ], @@ -2852,9 +2873,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.65.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.65.0.tgz", - "integrity": "sha512-KvNDC0J6s4vVHhtJ6KrDXU0Er0au/hmRIBq/+1maCV8TseGupeKizq0bWcrbp2HE1T8xoknvN0Q/KZ/YF0qX3w==", + "version": "4.67.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.67.3.tgz", + "integrity": "sha512-Nt1/uFKauyn2bwGcYaIcF9DA3TORW45XrtdhThm5QPu0TNDpDC5onMNSh8fzvB+klrnLKTCISCw8lR9xpxrEFA==", "cpu": [ "s390x" ], @@ -2869,9 +2890,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.65.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.65.0.tgz", - "integrity": "sha512-GExdD15WPvu/x/drELjVam7vX8EsPgvTMOa/iJL/p/4m/oOqzbb7JXZg8fXR4hlXtg/sF2zyTZ3bR0AEtEMlhQ==", + "version": "4.67.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.67.3.tgz", + "integrity": "sha512-K8HqIGH9CD57XmZFo/0T3pafDAzAoB9Iof02FEFvOXg7lBn7vlkLEjHgtZkYp+srWANrlxTSf8BolQM/27kiCw==", "cpu": [ "x64" ], @@ -2886,9 +2907,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.65.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.65.0.tgz", - "integrity": "sha512-8sT9PemIZfIMED4Vd4KGoOXVDj5CMSWNcGdbheRUx9TYS03yOWdT2Q0lXPyEyNBB9YTilwewIQKNIBk6Nxi0Kg==", + "version": "4.67.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.67.3.tgz", + "integrity": "sha512-6vTihCOamPjOpgcjkXOFB+Lh+LM4Eb95EPYNHjcovwxsnQrFRIJ7M664fLnGklKFOZutrhR9/o+NfgQLE4Zmdg==", "cpu": [ "x64" ], @@ -2903,9 +2924,9 @@ ] }, "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.65.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.65.0.tgz", - "integrity": "sha512-pO6Ehi0jo5yE0R6PltKhJhv9mlIiyzBJk5N5NUF2OF6xtVKI+1bdXxj/rb0jGXy3hck1ELVT0QPY3tzkAm360w==", + "version": "4.67.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.67.3.tgz", + "integrity": "sha512-k5XxCKgPGASSGyXOhXVQQJM6VIRHteqwHBsbwhW55EoimmI2jfkPebwgg/lwcjezpvgyLu8YTTCRsdSrvHKA7A==", "cpu": [ "x64" ], @@ -2917,9 +2938,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.65.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.65.0.tgz", - "integrity": "sha512-vo7N3/+cjjPDYr8vtxC+qSNgWa9sDvJ7g8N8R5SWqFY4WiNH1ULcAU70SKVyHeiIZOYYwNP9pTipmhN5sl1NPw==", + "version": "4.67.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.67.3.tgz", + "integrity": "sha512-WYqJUhonki85lB0iQ/Ro9BNJiGd7rG7GBZBiB/h4EUBWiUKyI3vq6EZ1aTyy5Y8qVuSIx4ZdqDyAXYiR59Vtvw==", "cpu": [ "arm64" ], @@ -2931,9 +2952,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.65.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.65.0.tgz", - "integrity": "sha512-ArwvgFAbjKcDM7qqotZ4OVYf+UMT9xH2YzkCzK4+AuZSDihMlz1Ekoe4INwBVXzn2mnJzuIYOcSx07iTBijGRQ==", + "version": "4.67.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.67.3.tgz", + "integrity": "sha512-WJgIOxBAnyZy2nXZdSk1xtDP0nmU41qfB47jCZ5VCxCipt2/aoImPtXMyPYB1fzXcpmNsAtYxBCY2d2WFYo00g==", "cpu": [ "arm64" ], @@ -2945,9 +2966,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.65.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.65.0.tgz", - "integrity": "sha512-QGMmK4/cxKE/36FoLMSHQBCyymv/eFTnsCvvsBF0rgmOvVbvX78VWZRerL3dHa77f4pM6Xcc2iGDhJ10w/svKQ==", + "version": "4.67.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.67.3.tgz", + "integrity": "sha512-C0vJ/s69Fll/puogTouGiFkn7kFI7nIAQc8/PTVawth9VNpNYIpv9xrZr6syRaFzSxVhTUt5zoXUFLELGs6vVA==", "cpu": [ "ia32" ], @@ -2959,9 +2980,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.65.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.65.0.tgz", - "integrity": "sha512-XfKYFWHIPs4HPODIMsGF1IKlS3H1e3WokUZIgpmn4+uNnZBlnRDDHEylNyazbQXwhMKZre68OjtRYbKqb5+j8w==", + "version": "4.67.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.67.3.tgz", + "integrity": "sha512-UFCIgrIBg2jU6Ajkrx+AwGz0EWpYCRTjr6wh+jBCY+A6r8pCDeeejTtMbbBszRdnmtUCzlXwwA4h/f4f3zPRSA==", "cpu": [ "x64" ], @@ -2973,9 +2994,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.65.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.65.0.tgz", - "integrity": "sha512-wPWi++K4Bs1VR4XihOhfGi4IGX6Cub7FlerTf8X2v+2BtDHddgSqWCXwGD+h2yAe4/niIhNDwAltioOC+wEogQ==", + "version": "4.67.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.67.3.tgz", + "integrity": "sha512-tlynfm3LIQtOCjFdT7kjyMnGrl0PbhyldgCfj7b1VxafD6uYiJFjd2ATzmYb+YnzNIzNezpK7XzFzDtPu37IeA==", "cpu": [ "x64" ], @@ -3162,9 +3183,9 @@ "license": "MIT" }, "node_modules/@types/estree": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", - "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.10.tgz", + "integrity": "sha512-lTyOMnOcmRBzdCv6/4zUZCrEhV0xrqQiUZBZtVcbmLHBXKLnN8q89v/wKRF/Q0HbwVsqbIG3o5HDoFl9sduM+g==", "dev": true, "license": "MIT" }, @@ -3230,9 +3251,9 @@ } }, "node_modules/@types/node": { - "version": "26.6.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-26.6.5.tgz", - "integrity": "sha512-uMzsv9stDdofIZBx4UGh4Z9ZgXnGC9seRDscilBcTHAeOFk67MZg/k9bWVfO+bk4qZmG+l52hRnLwUiH2LnJTg==", + "version": "26.6.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.6.6.tgz", + "integrity": "sha512-MzQj+8Kx3XI40OmUAE6Qoh58ZMNstNNMwn2nfd3qWsfe7nDNSqJNzes4njhz6AHwrSHOffSLwXU6yb474Q4aog==", "dev": true, "license": "MIT", "dependencies": { @@ -3257,17 +3278,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.72.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.72.0.tgz", - "integrity": "sha512-aysKgysPX9XOv/dk95UkvUDe++Q3n3dJPG9CEWT3RUccxfkPJ+Qn6nhKPDhZXU6Ofo9kgwGWwKyQCnZIXTgngg==", + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.72.1.tgz", + "integrity": "sha512-5CokTWXpmbylfFabsbvHC0CAw3XLaGnoa+nFJX5FR592h/LoZsENUE6p/rg5xvkKrFEXz6pYmgI29AgXc2N3BQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.72.0", - "@typescript-eslint/type-utils": "8.72.0", - "@typescript-eslint/utils": "8.72.0", - "@typescript-eslint/visitor-keys": "8.72.0", + "@typescript-eslint/scope-manager": "8.72.1", + "@typescript-eslint/type-utils": "8.72.1", + "@typescript-eslint/utils": "8.72.1", + "@typescript-eslint/visitor-keys": "8.72.1", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" @@ -3280,7 +3301,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.72.0", + "@typescript-eslint/parser": "^8.72.1", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } @@ -3296,16 +3317,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.72.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.72.0.tgz", - "integrity": "sha512-0O+x3ynciD6zuXb1CKSu165haQV6ey53DKhHHUnujP7U+XlltJG+/keT0Xhd1HXCze+IHf7Tvt39ovyepX/LNw==", + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.72.1.tgz", + "integrity": "sha512-ZGwZP4OCfyA0AQTpEAMWz+rtX01DRhQWW5hB0ucKDEIX5U7jdmPSaMx94rQfaPAQzIYz2BimOgKOJtjfpRFQ9g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.72.0", - "@typescript-eslint/types": "8.72.0", - "@typescript-eslint/typescript-estree": "8.72.0", - "@typescript-eslint/visitor-keys": "8.72.0", + "@typescript-eslint/scope-manager": "8.72.1", + "@typescript-eslint/types": "8.72.1", + "@typescript-eslint/typescript-estree": "8.72.1", + "@typescript-eslint/visitor-keys": "8.72.1", "debug": "^4.4.3" }, "engines": { @@ -3321,14 +3342,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.72.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.72.0.tgz", - "integrity": "sha512-bzHngBbmIgzj6TsTjVUCntGx6FFLgE7mPjpO0PzHycOaZHXqS43XnrkFIHRS16LLr/xO6FHSXG3GJFo/F4bSBQ==", + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.72.1.tgz", + "integrity": "sha512-fAuVMkwdO/huI8nyo/WKnNKf6Gag93S56Rh3Ts5mGcavwSdaN8tRg1gCeIGX8PF+nzp1BjGfO4gHhGzW1J6jTg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.72.0", - "@typescript-eslint/types": "^8.72.0", + "@typescript-eslint/tsconfig-utils": "^8.72.1", + "@typescript-eslint/types": "^8.72.1", "debug": "^4.4.3" }, "engines": { @@ -3343,14 +3364,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.72.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.72.0.tgz", - "integrity": "sha512-JewPyJOYcXBSAS7PIgufscHOwZqhTGyBRiQJhhuDln66tMchxvvt7nJ90JKKIoOelmdHA3kAQbm9cEUHc4JSEA==", + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.72.1.tgz", + "integrity": "sha512-lC/t6eMCZZQAAKZEYGL6RDVSuFehpdmMT6h+nJIjIa6oylN/PwDgDVtEIbB7O9xFfZYtZAYLoLlDNWKJhtF+uQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.72.0", - "@typescript-eslint/visitor-keys": "8.72.0" + "@typescript-eslint/types": "8.72.1", + "@typescript-eslint/visitor-keys": "8.72.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3361,9 +3382,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.72.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.72.0.tgz", - "integrity": "sha512-0vbxCf7xLVPSjcOdm6eQbgViH8EDJ8xnl1laLT9yoqSz2YmcSfSg5Vdl0JUvZf6rcuJ0ZivJIuMD4edTg8obaA==", + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.72.1.tgz", + "integrity": "sha512-e4D5R5vpeAEPBxT2BAzsFQL3sbwyeeeo5+aczgNSRK1V734jE7pTqaGFU+fXapWEQwnZbpFaTn32+Z8DwS6OTg==", "dev": true, "license": "MIT", "engines": { @@ -3378,15 +3399,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.72.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.72.0.tgz", - "integrity": "sha512-gEXxmmbSTSOVTC37IYYvremOM31v+UN2W772bJxmVYPhAOPSUxtacyb7wkm1EhkYKU6KzFJsdU44DCV4to0LWw==", + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.72.1.tgz", + "integrity": "sha512-iY2wlmyrXJmx4yxUGP3aYCFF3cA/6ShddOKmLU2dx7LnEykbAM8WThlxZEfd1NddqceF6eJmZUayxx9oKIYNlg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.72.0", - "@typescript-eslint/typescript-estree": "8.72.0", - "@typescript-eslint/utils": "8.72.0", + "@typescript-eslint/types": "8.72.1", + "@typescript-eslint/typescript-estree": "8.72.1", + "@typescript-eslint/utils": "8.72.1", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, @@ -3403,9 +3424,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.72.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.72.0.tgz", - "integrity": "sha512-Adfoy59kxNEjT5E5fnyrp7GpHYuWs8ONbdohu4ez6IU46qDq8LltG90tLmkucZB2uhYL8mqBjtXqGd8yhfjXqQ==", + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.72.1.tgz", + "integrity": "sha512-LmE5IhQet1BWOWEXqBrVtBPsMAOQ6Nzk35d+WLh3mk4EUF33sqlfxjio1MdYeSvKSG5skactKKuixBIKXhL4Rw==", "dev": true, "license": "MIT", "engines": { @@ -3417,16 +3438,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.72.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.72.0.tgz", - "integrity": "sha512-gwLfFgWcw15tN2KXDCJvxEOQjPn+P3j/n3eSqkZ5sX4VpW9Cosodr+tWwBZRvJT3TcKx6HnPRGZMCNAiP1Xhug==", + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.72.1.tgz", + "integrity": "sha512-DAlUoUV93hIvrtIQLwCbmZQYVZwOMhiHJrOVUUIWicFZaIYjTRqlY3I/NZevfkLmSqkNHRu2qYDcq9lrn16oOQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.72.0", - "@typescript-eslint/tsconfig-utils": "8.72.0", - "@typescript-eslint/types": "8.72.0", - "@typescript-eslint/visitor-keys": "8.72.0", + "@typescript-eslint/project-service": "8.72.1", + "@typescript-eslint/tsconfig-utils": "8.72.1", + "@typescript-eslint/types": "8.72.1", + "@typescript-eslint/visitor-keys": "8.72.1", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -3445,16 +3466,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.72.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.72.0.tgz", - "integrity": "sha512-0up3oArJZBYnzOaEXKo8DmI43QvMZyPoFEt9LWzRJcyl/RcJjfKKPebknN1VbTgXBf3M/KggUh5uUMdURLnseg==", + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.72.1.tgz", + "integrity": "sha512-5v5liypurJBFHCBNqh/RjsymAD+VWcE0djuGY/BUqp5fC3Qn+luWDEksjuTtWjPn6i5zQlUtkZCRG/CYG0yCkA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.72.0", - "@typescript-eslint/types": "8.72.0", - "@typescript-eslint/typescript-estree": "8.72.0" + "@typescript-eslint/scope-manager": "8.72.1", + "@typescript-eslint/types": "8.72.1", + "@typescript-eslint/typescript-estree": "8.72.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3469,13 +3490,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.72.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.72.0.tgz", - "integrity": "sha512-E2mroviasaWecDzTGiGMtuEguuLVOeRggnrIn93CJuxYJzQBHbyymlT08aVQydbBal5538o+JkBKXh2sRuCyIA==", + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.72.1.tgz", + "integrity": "sha512-SB8xqipSzZHUePCCLNeYxqnxq83X61/qzNhjQGbTfjxGZIeOEP7tBgWYX05Tcd6CgE02WdTJnh5b8kMZJ/+bnQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.72.0", + "@typescript-eslint/types": "8.72.1", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -3723,16 +3744,16 @@ } }, "node_modules/astro": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/astro/-/astro-7.4.2.tgz", - "integrity": "sha512-FAH4cdDlFaVnQGjazLTEIC5vJqGlo5XANc1wIbzQHIqAjJTll/RWTUs+SPNW1JdezG4YGxMZllaE5A41T2kzhA==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/astro/-/astro-7.4.4.tgz", + "integrity": "sha512-e+BzhGCaIY/H1tV/BQPTbOPZVZ8wuu6+bbpc+3oSMH2UgoB1l9peSGASk6nswtYra9PO9OoMREhldKtQkZ5TVw==", "dev": true, "license": "MIT", "dependencies": { "@astrojs/compiler-rs": "^0.5.1", "@astrojs/internal-helpers": "0.13.0", - "@astrojs/markdown-satteri": "0.4.5", - "@astrojs/telemetry": "3.4.1", + "@astrojs/markdown-satteri": "0.4.6", + "@astrojs/telemetry": "3.4.2", "@capsizecss/unpack": "^4.0.1", "@clack/prompts": "^1.8.1", "@oslojs/encoding": "^1.1.0", @@ -3764,7 +3785,7 @@ "package-manager-detector": "^1.9.0", "piccolore": "^0.1.3", "picomatch": "^4.0.7", - "rolldown": "^1.2.13", + "rolldown": "^1.2.14", "shiki": "^4.5.0", "smol-toml": "^1.9.1", "svgo": "^4.1.0", @@ -3776,7 +3797,7 @@ "unifont": "^1.0.3", "unstorage": "^1.17.5", "verkit": "^0.5.0", - "vite": "^8.3.4", + "vite": "^8.3.5", "vitefu": "^1.1.3", "xxhash-wasm": "^1.1.0", "yargs-parser": "^22.0.0", @@ -4486,9 +4507,9 @@ } }, "node_modules/eslint": { - "version": "10.13.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.13.0.tgz", - "integrity": "sha512-UohDjD4zSzEwhf58M3O7vc/ycc8O1I7dNlhtD0WxE8Px8EHNJKtUwzBqrzeGhisRuv2ag4sAYswszCJRgKXYUg==", + "version": "10.14.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.14.0.tgz", + "integrity": "sha512-T0pNsxkb9IKmtQjhpK3d7nWOpFv+YHuMbTJnSVMoQblF0onvXfErrtp4V1jHtsQPan7dKaGVD0q1WCXnzMF31A==", "dev": true, "license": "MIT", "workspaces": [ @@ -4501,7 +4522,7 @@ "@eslint/config-helpers": "^0.7.0", "@eslint/core": "^1.2.1", "@eslint/plugin-kit": "^0.7.3", - "@humanfs/node": "^0.16.6", + "@humanfs/node": "^0.16.8", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", @@ -4522,7 +4543,7 @@ "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "minimatch": "^10.2.5", + "minimatch": "^10.2.6", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, @@ -4909,15 +4930,15 @@ "license": "ISC" }, "node_modules/glob": { - "version": "13.0.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", - "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-14.0.3.tgz", + "integrity": "sha512-A1vjIwC3qpdCso45Iw127gnp7sPhqgY8lUQhDrArIs+GbmfaaVPFuoyy7WyLT9EPZCRZ7j7aLdwUhQmHWesEow==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { - "minimatch": "^10.2.2", + "minimatch": "^11.0.2", "minipass": "^7.1.3", - "path-scurry": "^2.0.2" + "path-scurry": "^3.0.0" }, "engines": { "node": "18 || 20 || >=22" @@ -4939,6 +4960,23 @@ "node": ">=10.13.0" } }, + "node_modules/glob/node_modules/minimatch": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-11.0.3.tgz", + "integrity": "sha512-iny/40PEGkNJQ5/Pv6z3nm6FbRAby32GeZRjCUJk2WnNDbgPSTcdI+DDvLqsgBdD4cD5sMtMheqPPnehCCa8Nw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/nonrecursive-glob-match": "^1.0.3", + "brace-expansion": "^5.0.12" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/h3": { "version": "1.15.11", "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.11.tgz", @@ -5126,9 +5164,9 @@ } }, "node_modules/hast-util-to-html": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", - "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.6.tgz", + "integrity": "sha512-1SZUxCN3TtJAE7e2BQN2MBHsoZ1gnmi9GoCP5Di59CSWptIezSAW09yDZyVbanb78V9eCwrKqdQsjtfVTxYHWA==", "dev": true, "license": "MIT", "dependencies": { @@ -5164,16 +5202,13 @@ } }, "node_modules/hast-util-to-text": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz", - "integrity": "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.3.tgz", + "integrity": "sha512-5yrlWOvGFs6CqHriUpSsNrjzT/Tdo+IOQudbznxOn8K5qblp18MJyzOg8IgDOKQ8MYgQcJA7SusuCjSpDr8mSA==", "dev": true, "license": "MIT", "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "hast-util-is-element": "^3.0.0", - "unist-util-find-after": "^5.0.0" + "@types/hast": "^3.0.0" }, "funding": { "type": "opencollective", @@ -5195,9 +5230,9 @@ } }, "node_modules/hastscript": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz", - "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.3.tgz", + "integrity": "sha512-1ALZXSmCGmW3h8AMz4R4+QKSKFi7sNgXLVwmwB8FYVtl1CwQ3WDkSAEY/d5tp1g/vbQgq2s1WlHgfO3jbw1TsA==", "dev": true, "license": "MIT", "dependencies": { @@ -5256,9 +5291,9 @@ "license": "BSD-2-Clause" }, "node_modules/i18next": { - "version": "26.5.7", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-26.5.7.tgz", - "integrity": "sha512-mY9cECbKtiOqpcB8d8ijNsiPZQoTFULehBlWXZzzURpTm9aLbE2c3T2FKdGZhdEjlTvXUGd0TvCisL06YafO0Q==", + "version": "26.6.0", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-26.6.0.tgz", + "integrity": "sha512-jpb1n5386s9mbBLNF6tSNIVhbBUUNiNeDyjWte+uxHP/Wr+CEy7WBM8q29TkfQ46VbwKeJFYdQJK3pSUhLp4CQ==", "dev": true, "funding": [ { @@ -5817,9 +5852,9 @@ } }, "node_modules/magic-string": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.4.3.tgz", - "integrity": "sha512-z12OxmaPGE0F4xlpGdjuAUckipLpQlTAuAmyGhNoD7ODpYUzvDfvtxUbjM/jwznyP178oju/KDdyi220wNJ0RQ==", + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.4.5.tgz", + "integrity": "sha512-oLLC2+YvQUfAa+vxoufE/yc1icb87M9iXIRqAoR/2EhE/8cb3SF/+Gi0c2By1B+5Vz2e2vQtUvHiu1+63Znh+w==", "dev": true, "license": "MIT", "dependencies": { @@ -5839,9 +5874,9 @@ } }, "node_modules/mdast-util-directive": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/mdast-util-directive/-/mdast-util-directive-3.1.1.tgz", - "integrity": "sha512-Gqpa3MHorXYEZ0VfbroyvBlVKUfz371V6mIERqOYMcb0W1D3LwmFq1ZW4O2TDrbn+4ZmGLwMWeFRJgYZ+bc5fQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-directive/-/mdast-util-directive-3.2.0.tgz", + "integrity": "sha512-Yxq+hH4pBEmtaLIJyMVcNbtBiCIKzdOK3HvDeM+JAqC8XVAT1e5PUYbHBpwFvQLIJuJfO2zCu7aNUXWoyZLmhw==", "dev": true, "license": "MIT", "dependencies": { @@ -5850,11 +5885,10 @@ "ccount": "^2.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.2.0", "micromark-util-character": "^2.0.0", "parse-entities": "^4.0.0", - "stringify-entities": "^4.0.0", - "unist-util-visit-parents": "^6.0.0" + "stringify-entities": "^4.0.0" }, "funding": { "type": "opencollective", @@ -5924,9 +5958,9 @@ } }, "node_modules/mdast-util-to-markdown": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.2.0.tgz", - "integrity": "sha512-2Jn/ADrHFFyyniBMi0bncTbJqU78K3/TEYvzvwrWWzD9MYPUa/Gm4r3nOeKFQg/PDM5BsbDYdc8ackW4NTY6NA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.2.1.tgz", + "integrity": "sha512-ThatlCBxG2GE+mljhNSfZPv56d3QrGiRh97jjYgIk80IzS4uU6d7cHAaexCYSAmUCCcOs3grJ07kX3oTGsFUOw==", "dev": true, "license": "MIT", "dependencies": { @@ -6831,9 +6865,9 @@ } }, "node_modules/path-scurry": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", - "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-3.0.0.tgz", + "integrity": "sha512-1pTbQqH1wIwMi/eleQ5leFTTCkzFsPcgXNjwOA8YGGW/W4/kHT3dssE7Z6NH+zuqNLOzOB0uaD61yl7cAcVhgg==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -6882,9 +6916,9 @@ } }, "node_modules/postcss": { - "version": "8.5.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.31.tgz", - "integrity": "sha512-YUbWYCgErwnMAVkjUnYa+KlMBzGpHwiIt/DE7f0G33AuX2LH9UcTk6KgWxd3zRU+pN3u/C+Xl3EnMLM4Hea7Sg==", + "version": "8.5.32", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.32.tgz", + "integrity": "sha512-LJlKCCAUFKOuZxipUdYw1NzIITEsPcgyOG9LkvRJvuKj/bRzbuRY0ARXvL0pWGpsZvn8jku+LMep2eU0seHp8g==", "dev": true, "funding": [ { @@ -7139,13 +7173,13 @@ } }, "node_modules/rolldown": { - "version": "1.2.15", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.15.tgz", - "integrity": "sha512-6odND+fel5zVw3I4Yc2e69gvguDnX0CAAGiNDZSq4ik5WUcaLrkD2GLuog0XcODbor31hZ5ayEMgVDno+KPV5g==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.16.tgz", + "integrity": "sha512-bWvlMpFKiTfDKfnK7FC2MPgPeWCf/Kpwsq49ApdW+FQaBZb6O6dZ4MAPbPUjp7hYQrw/RobqCzn64BRrQecGHw==", "dev": true, "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.155.0", + "@oxc-project/types": "=0.156.0", "@rolldown/pluginutils": "^1.0.0" }, "bin": { @@ -7155,31 +7189,31 @@ "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm-eabi": "1.2.15", - "@rolldown/binding-android-arm64": "1.2.15", - "@rolldown/binding-darwin-arm64": "1.2.15", - "@rolldown/binding-darwin-x64": "1.2.15", - "@rolldown/binding-freebsd-x64": "1.2.15", - "@rolldown/binding-linux-arm-gnueabihf": "1.2.15", - "@rolldown/binding-linux-arm64-gnu": "1.2.15", - "@rolldown/binding-linux-arm64-musl": "1.2.15", - "@rolldown/binding-linux-ppc64-gnu": "1.2.15", - "@rolldown/binding-linux-s390x-gnu": "1.2.15", - "@rolldown/binding-linux-x64-gnu": "1.2.15", - "@rolldown/binding-linux-x64-musl": "1.2.15", - "@rolldown/binding-openharmony-arm64": "1.2.15", - "@rolldown/binding-win32-arm64-msvc": "1.2.15", - "@rolldown/binding-win32-x64-msvc": "1.2.15" + "@rolldown/binding-android-arm-eabi": "1.2.16", + "@rolldown/binding-android-arm64": "1.2.16", + "@rolldown/binding-darwin-arm64": "1.2.16", + "@rolldown/binding-darwin-x64": "1.2.16", + "@rolldown/binding-freebsd-x64": "1.2.16", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.16", + "@rolldown/binding-linux-arm64-gnu": "1.2.16", + "@rolldown/binding-linux-arm64-musl": "1.2.16", + "@rolldown/binding-linux-ppc64-gnu": "1.2.16", + "@rolldown/binding-linux-s390x-gnu": "1.2.16", + "@rolldown/binding-linux-x64-gnu": "1.2.16", + "@rolldown/binding-linux-x64-musl": "1.2.16", + "@rolldown/binding-openharmony-arm64": "1.2.16", + "@rolldown/binding-win32-arm64-msvc": "1.2.16", + "@rolldown/binding-win32-x64-msvc": "1.2.16" } }, "node_modules/rollup": { - "version": "4.65.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.65.0.tgz", - "integrity": "sha512-QVCvQUTGDN6JRwi3jVGCY3H4aTHvi9rX0LyoBMkGUvdh/Z6O51CzcLz85BWZaTCDGhl6ySGqYZs+xI1jmPqGcw==", + "version": "4.67.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.67.3.tgz", + "integrity": "sha512-HJXOntSbeXzBfjUQ+YfgcOR+NV+8queObyCqWWOy2YL6bXDFE7vNRgVXlOUyrQqfJnxdXcL27PXlkC0O3ze6jQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.9" + "@types/estree": "^1.0.10" }, "bin": { "rollup": "dist/bin/rollup" @@ -7190,31 +7224,32 @@ }, "optionalDependencies": { "@napi-rs/lzma-linux-x64-gnu": "1.5.1", - "@rollup/rollup-android-arm-eabi": "4.65.0", - "@rollup/rollup-android-arm64": "4.65.0", - "@rollup/rollup-darwin-arm64": "4.65.0", - "@rollup/rollup-darwin-x64": "4.65.0", - "@rollup/rollup-freebsd-arm64": "4.65.0", - "@rollup/rollup-freebsd-x64": "4.65.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.65.0", - "@rollup/rollup-linux-arm-musleabihf": "4.65.0", - "@rollup/rollup-linux-arm64-gnu": "4.65.0", - "@rollup/rollup-linux-arm64-musl": "4.65.0", - "@rollup/rollup-linux-loong64-gnu": "4.65.0", - "@rollup/rollup-linux-loong64-musl": "4.65.0", - "@rollup/rollup-linux-ppc64-gnu": "4.65.0", - "@rollup/rollup-linux-ppc64-musl": "4.65.0", - "@rollup/rollup-linux-riscv64-gnu": "4.65.0", - "@rollup/rollup-linux-riscv64-musl": "4.65.0", - "@rollup/rollup-linux-s390x-gnu": "4.65.0", - "@rollup/rollup-linux-x64-gnu": "4.65.0", - "@rollup/rollup-linux-x64-musl": "4.65.0", - "@rollup/rollup-openbsd-x64": "4.65.0", - "@rollup/rollup-openharmony-arm64": "4.65.0", - "@rollup/rollup-win32-arm64-msvc": "4.65.0", - "@rollup/rollup-win32-ia32-msvc": "4.65.0", - "@rollup/rollup-win32-x64-gnu": "4.65.0", - "@rollup/rollup-win32-x64-msvc": "4.65.0", + "@rollup/rollup-android-arm-eabi": "4.67.3", + "@rollup/rollup-android-arm64": "4.67.3", + "@rollup/rollup-android-x64": "4.67.3", + "@rollup/rollup-darwin-arm64": "4.67.3", + "@rollup/rollup-darwin-x64": "4.67.3", + "@rollup/rollup-freebsd-arm64": "4.67.3", + "@rollup/rollup-freebsd-x64": "4.67.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.67.3", + "@rollup/rollup-linux-arm-musleabihf": "4.67.3", + "@rollup/rollup-linux-arm64-gnu": "4.67.3", + "@rollup/rollup-linux-arm64-musl": "4.67.3", + "@rollup/rollup-linux-loong64-gnu": "4.67.3", + "@rollup/rollup-linux-loong64-musl": "4.67.3", + "@rollup/rollup-linux-ppc64-gnu": "4.67.3", + "@rollup/rollup-linux-ppc64-musl": "4.67.3", + "@rollup/rollup-linux-riscv64-gnu": "4.67.3", + "@rollup/rollup-linux-riscv64-musl": "4.67.3", + "@rollup/rollup-linux-s390x-gnu": "4.67.3", + "@rollup/rollup-linux-x64-gnu": "4.67.3", + "@rollup/rollup-linux-x64-musl": "4.67.3", + "@rollup/rollup-openbsd-x64": "4.67.3", + "@rollup/rollup-openharmony-arm64": "4.67.3", + "@rollup/rollup-win32-arm64-msvc": "4.67.3", + "@rollup/rollup-win32-ia32-msvc": "4.67.3", + "@rollup/rollup-win32-x64-gnu": "4.67.3", + "@rollup/rollup-win32-x64-msvc": "4.67.3", "fsevents": "~2.3.2" } }, @@ -7741,9 +7776,9 @@ } }, "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.9.1.tgz", + "integrity": "sha512-a4Ux9VKuIMHsOS7ENbEq6hK2ZGYIT27Rtl0E4eD9KqwxhKiQeMZE/9xb3IdYwWaSOyIBQLExhQgXDTYoiCxnWA==", "dev": true, "license": "0BSD", "optional": true @@ -7795,16 +7830,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.72.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.72.0.tgz", - "integrity": "sha512-r26Fkc8As+mZvqp7SLsMmNFyYUup/6CjK7/eHBHmhOw6GH6n6YFxHVFrG0jN1c5CMpDzelLPxvgeCOzx7BjN+A==", + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.72.1.tgz", + "integrity": "sha512-3Li9FfPmQp45nxEtFD1ZCrYFI3cYK5kpyNtmm1H7lMagm8u9sy6PTjy3ytwQZs7KNukOyKFHAZ6z6GjYFeaeXw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.72.0", - "@typescript-eslint/parser": "8.72.0", - "@typescript-eslint/typescript-estree": "8.72.0", - "@typescript-eslint/utils": "8.72.0" + "@typescript-eslint/eslint-plugin": "8.72.1", + "@typescript-eslint/parser": "8.72.1", + "@typescript-eslint/typescript-estree": "8.72.1", + "@typescript-eslint/utils": "8.72.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -7889,21 +7924,6 @@ "undici": "^8.0.0" } }, - "node_modules/unist-util-find-after": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", - "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/unist-util-is": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", @@ -7947,15 +7967,15 @@ } }, "node_modules/unist-util-visit": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", - "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.2.0.tgz", + "integrity": "sha512-fpsYs/VVoZxfGY9/j3FQpZmN8wdLJaV1Pt38AaJNZu9uKIHcFU3halCdBveEq1HGKO1OEfJY65w1zvoFV1b3qQ==", "dev": true, "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" + "unist-util-visit-parents": "^6.1.0" }, "funding": { "type": "opencollective", @@ -7963,9 +7983,9 @@ } }, "node_modules/unist-util-visit-parents": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", - "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.1.0.tgz", + "integrity": "sha512-vKXxz6O38sKDj1mtx/k2cWvkkFBuYGx6uGrlzBkVeWCRF/F8sdI0j3Wbkz/5rVNRRuVc8UrgRdbCxNhmYXgP3w==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 64291de..3569c0d 100644 --- a/package.json +++ b/package.json @@ -122,23 +122,23 @@ "type": "module", "sideEffects": false, "devDependencies": { - "@astrojs/starlight": "^0.42.7", + "@astrojs/starlight": "^0.42.8", "@eslint/js": "^10.0.1", "@rollup/plugin-alias": "^6.0.1", "@rollup/plugin-terser": "^1.0.2", "@stylistic/eslint-plugin": "^5.10.0", - "@types/node": "^26.6.5", + "@types/node": "^26.6.6", "@vitest/coverage-v8": "^5.0.5", - "astro": "^7.4.2", - "eslint": "^10.13.0", - "glob": "^13.0.6", + "astro": "^7.4.4", + "eslint": "^10.14.0", + "glob": "^14.0.3", "prettier": "^3.9.10", - "rollup": "^4.65.0", + "rollup": "^4.67.3", "rollup-plugin-dts": "^6.5.1", "rollup-plugin-esbuild": "^6.2.1", "tsx": "^4.23.15", "typescript": "^6.0.3", - "typescript-eslint": "^8.72.0", + "typescript-eslint": "^8.72.1", "vitest": "^5.0.5" }, "allowScripts": { From 4107f4ad91be229e7a63e283299f5c196f9490c4 Mon Sep 17 00:00:00 2001 From: knowledgecode Date: Sun, 1 Nov 2026 16:44:15 +0900 Subject: [PATCH 4/9] fix(duration): round sub-millisecond parts to the nearest nanosecond Split the duration from an integer nanosecond count instead of truncating floating-point fractions, which dropped a unit for values like 1.001 that binary floating point stores slightly below their decimal form. Share the descriptor construction across the to*() methods. --- docs/api/subtract.md | 4 + src/duration.ts | 184 +++++++++++++++-------------------------- tests/duration.spec.ts | 55 ++++++++++++ 3 files changed, 125 insertions(+), 118 deletions(-) diff --git a/docs/api/subtract.md b/docs/api/subtract.md index d20243f..a87c89d 100644 --- a/docs/api/subtract.md +++ b/docs/api/subtract.md @@ -204,6 +204,10 @@ console.log(parts); // { days: 0, hours: -2, minutes: -15, seconds: 0, ... } console.log(duration.toDays().format('D[day], H:mm:ss')); // "-0day, 2:15:00" ``` +### Sub-millisecond Precision + +The millisecond value is rounded to the nearest nanosecond before it is split into units, so a fraction that binary floating point cannot store exactly keeps its last digit: `new Duration(1.001).toMilliseconds().toParts()` returns `{ milliseconds: 1, microseconds: 1, nanoseconds: 0 }`. + ## Immutability Both input Date objects remain unchanged: diff --git a/src/duration.ts b/src/duration.ts index 59321b4..1e667ee 100644 --- a/src/duration.ts +++ b/src/duration.ts @@ -12,39 +12,43 @@ interface DurationFormatter { F?: number; } -const nanosecondsPart = (parts: DurationFormatter, time: number) => { - parts.F = Math.trunc(time * 1000000); +const nanosecondsPart = (parts: DurationFormatter, nanoseconds: number) => { + parts.F = nanoseconds; return parts; }; -const microsecondsPart = (parts: DurationFormatter, time: number) => { - parts.f = Math.trunc(time * 1000); - return nanosecondsPart(parts, Math.abs(time) * 1000 % 1 / 1000); +const microsecondsPart = (parts: DurationFormatter, nanoseconds: number) => { + parts.f = Math.trunc(nanoseconds / 1000); + return nanosecondsPart(parts, Math.abs(nanoseconds % 1000)); }; -const millisecondsPart = (parts: DurationFormatter, time: number) => { - parts.S = Math.trunc(time); - return microsecondsPart(parts, Math.abs(time) % 1); +const millisecondsPart = (parts: DurationFormatter, nanoseconds: number) => { + parts.S = Math.trunc(nanoseconds / 1000000); + return microsecondsPart(parts, Math.abs(nanoseconds % 1000000)); }; -const secondsPart = (parts: DurationFormatter, time: number) => { - parts.s = Math.trunc(time / 1000); - return millisecondsPart(parts, Math.abs(time) % 1000); +const secondsPart = (parts: DurationFormatter, nanoseconds: number) => { + parts.s = Math.trunc(nanoseconds / 1000000000); + return millisecondsPart(parts, Math.abs(nanoseconds % 1000000000)); }; -const minutesPart = (parts: DurationFormatter, time: number) => { - parts.m = Math.trunc(time / 60000); - return secondsPart(parts, Math.abs(time) % 60000); +const minutesPart = (parts: DurationFormatter, nanoseconds: number) => { + parts.m = Math.trunc(nanoseconds / 60000000000); + return secondsPart(parts, Math.abs(nanoseconds % 60000000000)); }; -const hoursPart = (parts: DurationFormatter, time: number) => { - parts.H = Math.trunc(time / 3600000); - return minutesPart(parts, Math.abs(time) % 3600000); +const hoursPart = (parts: DurationFormatter, nanoseconds: number) => { + parts.H = Math.trunc(nanoseconds / 3600000000000); + return minutesPart(parts, Math.abs(nanoseconds % 3600000000000)); }; -const daysPart = (parts: DurationFormatter, time: number) => { - parts.D = Math.trunc(time / 86400000); - return hoursPart(parts, Math.abs(time) % 86400000); +const daysPart = (parts: DurationFormatter, nanoseconds: number) => { + parts.D = Math.trunc(nanoseconds / 86400000000000); + return hoursPart(parts, Math.abs(nanoseconds % 86400000000000)); +}; + +const toIntegerNanoseconds = (time: number) => { + return Math.sign(time) * Math.round(Math.abs(time) * 1000000); }; const sign = (time: number) => { @@ -113,6 +117,41 @@ export interface DurationDescriptor { toParts: () => T; } +const PART_NAMES = { + D: 'days', + H: 'hours', + m: 'minutes', + s: 'seconds', + S: 'milliseconds', + f: 'microseconds', + F: 'nanoseconds' +} as const; + +const createDescriptor = ( + time: number, + value: number, + decompose: (parts: DurationFormatter, nanoseconds: number) => DurationFormatter +): DurationDescriptor => { + return { + value, + format: (formatString: string, numeral?: Numeral) => { + return format(decompose({}, toIntegerNanoseconds(time)), formatString, numeral); + }, + toParts: () => { + const timeSign = Math.sign(time); + const parts = decompose({}, toIntegerNanoseconds(time)); + const keys = Object.keys(parts) as (keyof DurationFormatter)[]; + const result: Record = {}; + + // decompose() inserts the leading unit first and signs only that one; the smaller units are magnitudes. + keys.forEach((key, i) => { + result[PART_NAMES[key]] = (i ? timeSign : 1) * (parts[key] ?? 0) + 0; + }); + return result as T; + } + }; +}; + export class Duration { private readonly time: number; @@ -130,17 +169,7 @@ export class Duration { * the parts of the duration in nanoseconds. */ toNanoseconds (): DurationDescriptor { - return { - value: this.time * 1000000, - format: (formatString: string, numeral?: Numeral) => { - return format(nanosecondsPart({}, this.time), formatString, numeral); - }, - toParts: () => { - return { - nanoseconds: Math.trunc(this.time * 1000000) + 0 - }; - } - }; + return createDescriptor(this.time, this.time * 1000000, nanosecondsPart); } /** @@ -149,18 +178,7 @@ export class Duration { * the parts of the duration in microseconds and nanoseconds. */ toMicroseconds (): DurationDescriptor { - return { - value: this.time * 1000, - format: (formatString: string, numeral?: Numeral) => { - return format(microsecondsPart({}, this.time), formatString, numeral); - }, - toParts: () => { - return { - microseconds: Math.trunc(this.time * 1000) + 0, - nanoseconds: Math.trunc(this.time * 1000000 % 1000) + 0 - }; - } - }; + return createDescriptor(this.time, this.time * 1000, microsecondsPart); } /** @@ -169,19 +187,7 @@ export class Duration { * the parts of the duration in milliseconds, microseconds, and nanoseconds. */ toMilliseconds (): DurationDescriptor { - return { - value: this.time, - format: (formatString: string, numeral?: Numeral) => { - return format(millisecondsPart({}, this.time), formatString, numeral); - }, - toParts: () => { - return { - milliseconds: Math.trunc(this.time) + 0, - microseconds: Math.trunc(this.time * 1000 % 1000) + 0, - nanoseconds: Math.trunc(this.time * 1000000 % 1000) + 0 - }; - } - }; + return createDescriptor(this.time, this.time, millisecondsPart); } /** @@ -190,20 +196,7 @@ export class Duration { * the parts of the duration in seconds, milliseconds, microseconds, and nanoseconds. */ toSeconds (): DurationDescriptor { - return { - value: this.time / 1000, - format: (formatString: string, numeral?: Numeral) => { - return format(secondsPart({}, this.time), formatString, numeral); - }, - toParts: () => { - return { - seconds: Math.trunc(this.time / 1000) + 0, - milliseconds: Math.trunc(this.time % 1000) + 0, - microseconds: Math.trunc(this.time * 1000 % 1000) + 0, - nanoseconds: Math.trunc(this.time * 1000000 % 1000) + 0 - }; - } - }; + return createDescriptor(this.time, this.time / 1000, secondsPart); } /** @@ -212,21 +205,7 @@ export class Duration { * the parts of the duration in minutes, seconds, milliseconds, microseconds, and nanoseconds. */ toMinutes (): DurationDescriptor { - return { - value: this.time / 60000, - format: (formatString: string, numeral?: Numeral) => { - return format(minutesPart({}, this.time), formatString, numeral); - }, - toParts: () => { - return { - minutes: Math.trunc(this.time / 60000) + 0, - seconds: Math.trunc(this.time % 60000 / 1000) + 0, - milliseconds: Math.trunc(this.time % 1000) + 0, - microseconds: Math.trunc(this.time * 1000 % 1000) + 0, - nanoseconds: Math.trunc(this.time * 1000000 % 1000) + 0 - }; - } - }; + return createDescriptor(this.time, this.time / 60000, minutesPart); } /** @@ -235,22 +214,7 @@ export class Duration { * the parts of the duration in hours, minutes, seconds, milliseconds, microseconds, and nanoseconds. */ toHours (): DurationDescriptor { - return { - value: this.time / 3600000, - format: (formatString: string, numeral?: Numeral) => { - return format(hoursPart({}, this.time), formatString, numeral); - }, - toParts: () => { - return { - hours: Math.trunc(this.time / 3600000) + 0, - minutes: Math.trunc(this.time % 3600000 / 60000) + 0, - seconds: Math.trunc(this.time % 60000 / 1000) + 0, - milliseconds: Math.trunc(this.time % 1000) + 0, - microseconds: Math.trunc(this.time * 1000 % 1000) + 0, - nanoseconds: Math.trunc(this.time * 1000000 % 1000) + 0 - }; - } - }; + return createDescriptor(this.time, this.time / 3600000, hoursPart); } /** @@ -259,22 +223,6 @@ export class Duration { * the parts of the duration in days, hours, minutes, seconds, milliseconds, microseconds, and nanoseconds. */ toDays (): DurationDescriptor { - return { - value: this.time / 86400000, - format: (formatString: string, numeral?: Numeral) => { - return format(daysPart({}, this.time), formatString, numeral); - }, - toParts: () => { - return { - days: Math.trunc(this.time / 86400000) + 0, - hours: Math.trunc(this.time % 86400000 / 3600000) + 0, - minutes: Math.trunc(this.time % 3600000 / 60000) + 0, - seconds: Math.trunc(this.time % 60000 / 1000) + 0, - milliseconds: Math.trunc(this.time % 1000) + 0, - microseconds: Math.trunc(this.time * 1000 % 1000) + 0, - nanoseconds: Math.trunc(this.time * 1000000 % 1000) + 0 - }; - } - }; + return createDescriptor(this.time, this.time / 86400000, daysPart); } } diff --git a/tests/duration.spec.ts b/tests/duration.spec.ts index e04e246..54d3b0e 100644 --- a/tests/duration.spec.ts +++ b/tests/duration.spec.ts @@ -133,6 +133,61 @@ describe('Duration (Negative Zero)', () => { }); }); +// Each value is stored slightly below its decimal form (1.001 is 1.000999...), so truncation drops a unit. +describe('Duration (floating-point fractions)', () => { + test('toSeconds', () => { + const duration = 1001.001; + expect(new Duration(duration).toSeconds().toParts()).toEqual({ nanoseconds: 0, microseconds: 1, milliseconds: 1, seconds: 1 }); + expect(new Duration(duration).toSeconds().format('s.SSS.fff.FFF')).toBe('1.001.001.000'); + }); + + test('toMilliseconds', () => { + const duration = 1.001; + expect(new Duration(duration).toMilliseconds().toParts()).toEqual({ nanoseconds: 0, microseconds: 1, milliseconds: 1 }); + expect(new Duration(duration).toMilliseconds().format('S.fff')).toBe('1.001'); + }); + + test('toMilliseconds (nanoseconds)', () => { + const duration = 1.000001; + expect(new Duration(duration).toMilliseconds().toParts()).toEqual({ nanoseconds: 1, microseconds: 0, milliseconds: 1 }); + }); + + test('toMilliseconds (format only)', () => { + const duration = 4.35; + expect(new Duration(duration).toMilliseconds().format('SSS.fff.FFF')).toBe('004.350.000'); + }); + + test('toMilliseconds (minus)', () => { + const duration = -1.001; + expect(new Duration(duration).toMilliseconds().toParts()).toEqual({ nanoseconds: 0, microseconds: -1, milliseconds: -1 }); + }); + + test('toMicroseconds', () => { + const duration = 1.001; + expect(new Duration(duration).toMicroseconds().toParts()).toEqual({ nanoseconds: 0, microseconds: 1001 }); + }); + + test('toNanoseconds', () => { + const duration = 1.001; + expect(new Duration(duration).toNanoseconds().toParts()).toEqual({ nanoseconds: 1001000 }); + }); +}); + +// Fractions are rounded to the nearest nanosecond on the magnitude, so a tie rounds away from zero for either sign. +describe('Duration (nanosecond rounding)', () => { + test('toMilliseconds (half nanosecond)', () => { + expect(new Duration(12.2277645).toMilliseconds().toParts()).toEqual({ nanoseconds: 765, microseconds: 227, milliseconds: 12 }); + expect(new Duration(-12.2277645).toMilliseconds().toParts()).toEqual({ nanoseconds: -765, microseconds: -227, milliseconds: -12 }); + expect(new Duration(-12.2277645).toMilliseconds().format('S.fff.FFF')).toBe('-12.227.765'); + }); + + test('toMilliseconds (carry)', () => { + const duration = 0.9999999996; + expect(new Duration(duration).toMilliseconds().toParts()).toEqual({ nanoseconds: 0, microseconds: 0, milliseconds: 1 }); + expect(new Duration(duration).toMilliseconds().format('SSS.fff.FFF')).toBe('001.000.000'); + }); +}); + describe('Duration comments spanning line breaks', () => { test('[D\nH] D H', () => { expect(new Duration(90061001).toDays().format('[D\nH] D H')).toBe('D\nH 1 1'); From 2d23afebbd2602e1abc44e79889d4a42ebc340da Mon Sep 17 00:00:00 2001 From: knowledgecode Date: Sun, 1 Nov 2026 16:44:23 +0900 Subject: [PATCH 5/9] fix: truncate timezone offsets with seconds to whole minutes toParts() returned a fractional timezoneOffset for zones whose offset has seconds, such as Local Mean Time. Truncate it toward zero, as Date#getTimezoneOffset() does, so Z and ZZ print whole minutes. --- src/datetime.ts | 5 +++-- tests/format.spec.ts | 52 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/src/datetime.ts b/src/datetime.ts index 57e5740..7baa0c3 100644 --- a/src/datetime.ts +++ b/src/datetime.ts @@ -80,7 +80,7 @@ export const toParts = (dateObj: Date, zoneName: string): DateTimeParts => { const parts = dtfToParts(dtf, time); - parts.timezoneOffset = (time - fromParts(parts)) / 60000; + parts.timezoneOffset = Math.trunc((time - fromParts(parts)) / 60000); return parts; }; @@ -122,7 +122,8 @@ export interface DateLike { */ getTime(): number; /** - * Returns the timezone offset in minutes from UTC. + * Returns the timezone offset in minutes from UTC. Like `Date#getTimezoneOffset()`, it is a whole + * number of minutes; an offset with seconds, such as Local Mean Time, is truncated toward zero. */ getTimezoneOffset(): number; } diff --git a/tests/format.spec.ts b/tests/format.spec.ts index f9ec4ad..43a72c9 100644 --- a/tests/format.spec.ts +++ b/tests/format.spec.ts @@ -1,5 +1,8 @@ import { describe, expect, test, beforeAll } from 'vitest'; -import { format, compile } from '@/index.ts'; +import { format, compile, parse } from '@/index.ts'; +import Abidjan from '@/timezones/Africa/Abidjan.ts'; +import Addis_Ababa from '@/timezones/Africa/Addis_Ababa.ts'; +import Monrovia from '@/timezones/Africa/Monrovia.ts'; import Los_Angeles from '@/timezones/America/Los_Angeles.ts'; import Tokyo from '@/timezones/Asia/Tokyo.ts'; import { Los_Angeles as los_angeles, Tokyo as tokyo } from '@/timezone.ts'; @@ -609,6 +612,22 @@ describe('ZZ', () => { const now = new Date(9999, 12 - 1, 31, 23, 59, 59, 999); expect(format(now, 'ZZ', { timeZone: Tokyo })).toBe('+09:00'); }); + + // LMT offsets carry seconds; the seconds are truncated, as Date#getTimezoneOffset does. + test('-00:44 (LMT -00:44:30)', () => { + const now = new Date(Date.UTC(1960, 0, 1)); + expect(format(now, 'ZZ', { timeZone: Monrovia })).toBe('-00:44'); + }); + + test('-00:16 (LMT -00:16:08)', () => { + const now = new Date(Date.UTC(1900, 0, 1)); + expect(format(now, 'ZZ', { timeZone: Abidjan })).toBe('-00:16'); + }); + + test('+02:27 (LMT +02:27:16)', () => { + const now = new Date(Date.UTC(1900, 0, 1)); + expect(format(now, 'ZZ', { timeZone: Addis_Ababa })).toBe('+02:27'); + }); }); describe('Z', () => { @@ -628,6 +647,37 @@ describe('Z', () => { const now = new Date(9999, 12 - 1, 31, 23, 59, 59, 999); expect(format(now, 'Z', { timeZone: Tokyo })).toBe('+0900'); }); + + test('-0044 (LMT -00:44:30)', () => { + const now = new Date(Date.UTC(1960, 0, 1)); + expect(format(now, 'Z', { timeZone: Monrovia })).toBe('-0044'); + }); + + test('-0016 (LMT -00:16:08)', () => { + const now = new Date(Date.UTC(1900, 0, 1)); + expect(format(now, 'Z', { timeZone: Abidjan })).toBe('-0016'); + }); + + test('+0227 (LMT +02:27:16)', () => { + const now = new Date(Date.UTC(1900, 0, 1)); + expect(format(now, 'Z', { timeZone: Addis_Ababa })).toBe('+0227'); + }); +}); + +describe('ZZ round trip with LMT offsets', () => { + beforeAll(() => (process.env.TZ = 'UTC')); + + // ZZ cannot carry the seconds of an LMT offset, so the round trip is off by less than a minute. + test.each([ + ['Africa/Monrovia', Monrovia, 1960], + ['Africa/Abidjan', Abidjan, 1900], + ['Africa/Addis_Ababa', Addis_Ababa, 1900] + ])('%s', (_, timeZone, year) => { + const now = new Date(Date.UTC(year, 0, 1)); + const formatString = 'YYYY-MM-DD HH:mm:ss ZZ'; + const parsed = parse(format(now, formatString, { timeZone }), formatString); + expect(Math.abs(parsed.getTime() - now.getTime())).toBeLessThan(60000); + }); }); describe('comments', () => { From 7f36fe5b0e1b035ffe6df5bd7ce5834b4290bf2c Mon Sep 17 00:00:00 2001 From: knowledgecode Date: Sun, 1 Nov 2026 16:44:36 +0900 Subject: [PATCH 6/9] docs: document YYYY overflow above year 9999 and the Buddhist calendar range YYYY keeps only the last four digits of a year above 9999, which with the Buddhist calendar already happens after December 31, 9456. Document the Buddhist years parse() accepts, mirror both in the agent skill references, and pin the behavior with tests. --- docs/api/format.md | 4 ++++ docs/api/parse.md | 4 ++++ skills/date-and-time/references/options.md | 2 +- skills/date-and-time/references/tokens.md | 2 +- tests/format.spec.ts | 16 ++++++++++++++++ tests/parse.spec.ts | 6 ++++++ 6 files changed, 32 insertions(+), 2 deletions(-) diff --git a/docs/api/format.md b/docs/api/format.md index 14110ec..02bbf4b 100644 --- a/docs/api/format.md +++ b/docs/api/format.md @@ -55,6 +55,8 @@ format(now, 'hh:mm A [GMT]Z'); | `DD` | Day (01-31) | 02, 31 | | `D` | Day without zero padding | 2, 31 | +`YYYY` prints exactly four digits, so a year above 9999 keeps only its last four: `format(new Date(10000, 0, 1), 'YYYY')` returns `0000`. `Y` prints every digit (`10000`), but `parse()` cannot read either result back; see [Date Range Limitations](./parse#date-range-limitations). The year is counted in the selected [`calendar`](#calendar), so with `'buddhist'` this already happens for dates after December 31, 9456. + ### Day of Week Tokens | Token | Description | Output Examples | @@ -232,6 +234,8 @@ format(date, 'MMMM D, YYYY', { calendar: 'buddhist' }); // => August 23, 2568 ``` +With `'buddhist'`, `YYYY` prints the full year up to Buddhist year 9999, which ends on December 31, 9456 in the Gregorian calendar. Later dates are cut to four digits, as described under [Date Tokens](#date-tokens). + ### hour12 **Type**: `"h11" | "h12"` diff --git a/docs/api/parse.md b/docs/api/parse.md index fff235d..94cc8e0 100644 --- a/docs/api/parse.md +++ b/docs/api/parse.md @@ -236,6 +236,8 @@ parse('August 23, 2568', 'MMMM D, YYYY', { calendar: 'buddhist' }); // => Sat Aug 23 2025 00:00:00 GMT-0700 ``` +For the Buddhist years `parse()` accepts, see [Date Range Limitations](#date-range-limitations). + ### hour12 **Type**: `"h11" | "h12"` @@ -423,6 +425,8 @@ parse('Jan 1 0000', 'MMM D YYYY'); // => Invalid Date ``` +With `calendar: 'buddhist'`, the input year is a Buddhist year, and `YYYY` and `Y` read at most four digits. The parsable range is then `January 1, 0544` to `December 31, 9999` in Buddhist years, which is `January 1, 0001` to `December 31, 9456` in the Gregorian calendar. + ### UTC Input Parsing If the input string doesn't contain a timezone offset and no `timeZone` option is specified, the function treats the input as the local timezone. To parse input as UTC, set `timeZone: 'UTC'` in the options. diff --git a/skills/date-and-time/references/options.md b/skills/date-and-time/references/options.md index 93e7227..b04381d 100644 --- a/skills/date-and-time/references/options.md +++ b/skills/date-and-time/references/options.md @@ -33,7 +33,7 @@ interface ParserOptions { | `locale` | both | English (built in) | Month names, weekday names, and AM/PM text | | `timeZone` | both | local timezone | `format` converts the date to this zone first; `parse` reads the input as this zone | | `numeral` | both | `latn` | Digit system for output and input | -| `calendar` | both | `'gregory'` | `'buddhist'` adds 543 to the year (2025 becomes 2568) | +| `calendar` | both | `'gregory'` | `'buddhist'` adds 543 to the year (2025 becomes 2568); `YYYY` then prints up to Buddhist 9999 (Gregorian 9456), and `parse` accepts Buddhist 0544-9999 | | `hour12` | both | `'h12'` | `'h11'` shows the first hour after midnight as `0:30 AM`; `'h12'` as `12:30 AM` | | `hour24` | both | `'h23'` | `'h24'` shows the first hour after midnight as `24:30`; `'h23'` as `0:30` | | `ignoreCase` | parse | `false` | Case-insensitive month, weekday, and AM/PM names | diff --git a/skills/date-and-time/references/tokens.md b/skills/date-and-time/references/tokens.md index b259981..a21392a 100644 --- a/skills/date-and-time/references/tokens.md +++ b/skills/date-and-time/references/tokens.md @@ -8,7 +8,7 @@ Available without a plugin. "Parse" says whether the token can be used when read | Token | Meaning | Examples | Parse | |-------|---------|----------|-------| -| `YYYY` | 4-digit year | 0999, 2015 | yes | +| `YYYY` | 4-digit year; a year above 9999 keeps only its last 4 digits | 0999, 2015 | yes | | `YY` | 2-digit year | 99, 01, 15 | no (needs `two-digit-year`) | | `Y` | year without padding | 2, 44, 2015 | yes | | `MMMM` | full month name | January | yes | diff --git a/tests/format.spec.ts b/tests/format.spec.ts index 43a72c9..7250162 100644 --- a/tests/format.spec.ts +++ b/tests/format.spec.ts @@ -19,6 +19,11 @@ describe('YYYY', () => { const now = new Date(9999, 12 - 1, 31, 23, 59, 59, 999); expect(format(now, 'YYYY')).toBe('9999'); }); + + test('10000', () => { + const now = new Date(10000, 1 - 1, 1, 0, 0, 0, 0); + expect(format(now, 'YYYY')).toBe('0000'); + }); }); describe('YY', () => { @@ -47,6 +52,11 @@ describe('Y', () => { const now = new Date(9999, 12 - 1, 31, 23, 59, 59, 999); expect(format(now, 'Y')).toBe('9999'); }); + + test('10000', () => { + const now = new Date(10000, 1 - 1, 1, 0, 0, 0, 0); + expect(format(now, 'Y')).toBe('10000'); + }); }); describe('MMMM', () => { @@ -798,6 +808,12 @@ describe('options', () => { expect(format(new Date(9456, 1 - 1, 1, 0, 0, 0), 'Y-MM-DD HH', { calendar: 'buddhist' })).toBe('9999-01-01 00'); }); + test('calendar: buddhist (year above 9999)', () => { + expect(format(new Date(9456, 12 - 1, 31, 0, 0, 0), 'YYYY-MM-DD', { calendar: 'buddhist' })).toBe('9999-12-31'); + expect(format(new Date(9457, 1 - 1, 1, 0, 0, 0), 'YYYY-MM-DD', { calendar: 'buddhist' })).toBe('0000-01-01'); + expect(format(new Date(9457, 1 - 1, 1, 0, 0, 0), 'Y-MM-DD', { calendar: 'buddhist' })).toBe('10000-01-01'); + }); + test('timeZone', () => { const now = new Date(2025, 1 - 1, 1, 0); expect(format(now, 'YYYY-MM-DD HH:mm:ss.SSS Z dd', { timeZone: Los_Angeles })).toBe('2024-12-31 16:00:00.000 -0800 Tu'); diff --git a/tests/parse.spec.ts b/tests/parse.spec.ts index 3c0add6..0478231 100644 --- a/tests/parse.spec.ts +++ b/tests/parse.spec.ts @@ -539,6 +539,12 @@ describe('options', () => { expect(Number.isNaN(parse('0543-01-01 12:00 AM', 'YYYY-MM-DD hh:mm A', { calendar: 'buddhist' }).getTime())).toBe(true); }); + test('calendar: buddhist (year above 9999)', () => { + expect(parse('9999-12-31', 'YYYY-MM-DD', { calendar: 'buddhist' })).toEqual(new Date(9456, 12 - 1, 31)); + expect(Number.isNaN(parse('10000-01-01', 'YYYY-MM-DD', { calendar: 'buddhist' }).getTime())).toBe(true); + expect(Number.isNaN(parse('10000-01-01', 'Y-MM-DD', { calendar: 'buddhist' }).getTime())).toBe(true); + }); + test('timeZone', () => { const now = new Date(Date.UTC(2025, 1 - 1, 1, 0)); expect(parse('2024-12-31 16:00:00', 'YYYY-MM-DD HH:mm:ss', { timeZone: Los_Angeles })).toEqual(now); From 98f2438cf6aa7236164cb2e1dde18678a119f670 Mon Sep 17 00:00:00 2001 From: knowledgecode Date: Sun, 1 Nov 2026 16:44:36 +0900 Subject: [PATCH 7/9] docs: fix the RFC 2822 format and parse examples RFC 2822 offsets have no colon, so use Z instead of ZZ, and load the day-of-week parser plugin that the ddd token needs when parsing. --- docs/api/format.md | 4 ++-- docs/api/parse.md | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/api/format.md b/docs/api/format.md index 02bbf4b..b330bd9 100644 --- a/docs/api/format.md +++ b/docs/api/format.md @@ -359,8 +359,8 @@ format(date, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]', { timeZone: 'UTC' }); // => 2025-08-23T14:30:45.123Z // RFC 2822 format -format(date, 'ddd, DD MMM YYYY HH:mm:ss ZZ'); -// => Sat, 23 Aug 2025 14:30:45 +09:00 +format(date, 'ddd, DD MMM YYYY HH:mm:ss Z'); +// => Sat, 23 Aug 2025 14:30:45 +0900 // Log timestamp format(date, '\\[YYYY-MM-DD HH:mm:ss.SSS\\]'); diff --git a/docs/api/parse.md b/docs/api/parse.md index 94cc8e0..49799b2 100644 --- a/docs/api/parse.md +++ b/docs/api/parse.md @@ -536,13 +536,14 @@ parse('samedi, 23 août 2025 à 14:30:45', 'dddd, D MMMM YYYY [à] HH:mm:ss', { ```typescript import { parse } from 'date-and-time'; +import { parser as day_of_week } from 'date-and-time/plugins/day-of-week'; // ISO 8601 format parse('2025-08-23T14:30:45.123Z', 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]', { timeZone: 'UTC' }); // => Sat Aug 23 2025 14:30:45 GMT+0000 // RFC 2822 format -parse('Sat, 23 Aug 2025 14:30:45 +0900', 'ddd, DD MMM YYYY HH:mm:ss ZZ'); +parse('Sat, 23 Aug 2025 14:30:45 +0900', 'ddd, DD MMM YYYY HH:mm:ss Z', { plugins: [day_of_week] }); // => Sat Aug 23 2025 14:30:45 GMT+0900 // File naming format From c466bddef162719a2e913fb90b9c53fd490f2a70 Mon Sep 17 00:00:00 2001 From: knowledgecode Date: Sun, 1 Nov 2026 16:44:36 +0900 Subject: [PATCH 8/9] chore: bump version to 4.7.1 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1ba55d4..c0cab0d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "date-and-time", - "version": "4.7.0", + "version": "4.7.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "date-and-time", - "version": "4.7.0", + "version": "4.7.1", "license": "MIT", "devDependencies": { "@astrojs/starlight": "^0.42.8", diff --git a/package.json b/package.json index 3569c0d..00d7114 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "date-and-time", - "version": "4.7.0", + "version": "4.7.1", "description": "The simplest, most intuitive date and time library", "keywords": [ "date", From 957f7d8065febfca4481245f35a39e47a0a4d674 Mon Sep 17 00:00:00 2001 From: knowledgecode Date: Sun, 1 Nov 2026 17:06:56 +0900 Subject: [PATCH 9/9] refactor(duration): drop unreachable nullish fallbacks The token lookup in format() and the part lookup in toParts() always find a number, so their ?? 0 fallbacks never ran and showed up as partially covered branches. Compare the lookup against undefined in format() and read the values through Object.entries() in toParts() instead. --- src/duration.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/duration.ts b/src/duration.ts index 1e667ee..b1dc73c 100644 --- a/src/duration.ts +++ b/src/duration.ts @@ -58,8 +58,8 @@ const sign = (time: number) => { const format = (times: DurationFormatter, formatString: string, numeral: Numeral = latn) => { const pattern = compile(formatString).slice(1); const resolveToken = (token: string) => { - if (token[0] in times) { - const time = times[token[0] as keyof DurationFormatter] ?? 0; + const time = times[token[0] as keyof DurationFormatter]; + if (time !== undefined) { return numeral.encode(`${sign(time)}${String(Math.abs(time)).padStart(token.length, '0')}`); } return COMMENT.test(token) ? token.replace(COMMENT, '$1') : token; @@ -140,12 +140,12 @@ const createDescriptor = ( toParts: () => { const timeSign = Math.sign(time); const parts = decompose({}, toIntegerNanoseconds(time)); - const keys = Object.keys(parts) as (keyof DurationFormatter)[]; + const entries = Object.entries(parts) as [keyof DurationFormatter, number][]; const result: Record = {}; // decompose() inserts the leading unit first and signs only that one; the smaller units are magnitudes. - keys.forEach((key, i) => { - result[PART_NAMES[key]] = (i ? timeSign : 1) * (parts[key] ?? 0) + 0; + entries.forEach(([key, value], i) => { + result[PART_NAMES[key]] = (i ? timeSign : 1) * value + 0; }); return result as T; }