diff --git a/.husky/commit-msg b/.husky/commit-msg index b2a74a3f..7647c0ad 100644 --- a/.husky/commit-msg +++ b/.husky/commit-msg @@ -1 +1 @@ -pnpm exec commitlint --edit $1 \ No newline at end of file +git stripspace --strip-comments < "$1" | node scripts/lint-git-commit-msg.mts \ No newline at end of file diff --git a/package.json b/package.json index fab4398a..e8ebc0be 100644 --- a/package.json +++ b/package.json @@ -18,18 +18,20 @@ "format": "pnpm oxfmt", "format:check": "pnpm oxfmt --check", "install:chromium": "pnpm --filter=@solidmaterial/material exec playwright install chromium --with-deps", - "install:webkit": "pnpm --filter=@solidmaterial/material exec playwright install webkit --with-deps" + "install:webkit": "pnpm --filter=@solidmaterial/material exec playwright install webkit --with-deps", + "scripts:test": "vitest run --coverage --project scripts" }, "devDependencies": { - "@commitlint/cli": "21.2.1", - "@commitlint/config-conventional": "21.2.0", "@tsconfig/strictest": "2.0.8", + "@types/node": "24.13.2", + "@vitest/coverage-istanbul": "catalog:vitest", "husky": "9.1.7", "oxfmt": "0.56.0", "oxlint": "1.71.0", "oxlint-tsgolint": "0.23.0", "turbo": "2.10.11", - "typescript": "6.0.2" + "typescript": "6.0.2", + "vitest": "catalog:vitest" }, "devEngines": { "packageManager": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bfe62e1c..dc303469 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -259,15 +259,15 @@ importers: .: devDependencies: - '@commitlint/cli': - specifier: 21.2.1 - version: 21.2.1(@types/node@24.13.2)(conventional-commits-parser@7.1.0)(typescript@6.0.2) - '@commitlint/config-conventional': - specifier: 21.2.0 - version: 21.2.0 '@tsconfig/strictest': specifier: 2.0.8 version: 2.0.8 + '@types/node': + specifier: 24.13.2 + version: 24.13.2 + '@vitest/coverage-istanbul': + specifier: catalog:vitest + version: 4.1.11(supports-color@7.2.0)(vitest@4.1.11) husky: specifier: 9.1.7 version: 9.1.7 @@ -286,6 +286,9 @@ importers: typescript: specifier: 6.0.2 version: 6.0.2 + vitest: + specifier: catalog:vitest + version: 4.1.11(@types/node@24.13.2)(@vitest/browser-playwright@4.1.11)(@vitest/coverage-istanbul@4.1.11)(vite@8.1.5(@types/node@24.13.2)(esbuild@0.28.1)(jiti@2.6.1)) apps/calculator: dependencies: @@ -497,7 +500,7 @@ importers: version: 1.9.14 tsdown: specifier: catalog:tsdown - version: 0.22.5(@tsdown/css@0.22.5)(oxc-resolver@11.19.1)(typescript@6.0.2) + version: 0.22.5(@tsdown/css@0.22.5)(oxc-resolver@11.19.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1))(typescript@6.0.2) vite: specifier: catalog:vite version: 8.1.5(@types/node@24.13.2)(esbuild@0.28.1)(jiti@2.6.1) @@ -595,91 +598,6 @@ packages: '@blazediff/core@1.9.1': resolution: {integrity: sha512-ehg3jIkYKulZh+8om/O25vkvSsXXwC+skXmyA87FFx6A/45eqOkZsBltMw/TVteb0mloiGT8oGRTcjRAz66zaA==} - '@commitlint/cli@21.2.1': - resolution: {integrity: sha512-blsZGe29hJ72VGEFVl72IVYX+1vsfINpjA9yWQA6i7OKD/McGEOXg08sKIRKjFk4JvzhV/9n0l3i6NooPLTNfg==} - engines: {node: '>=22.12.0'} - hasBin: true - - '@commitlint/config-conventional@21.2.0': - resolution: {integrity: sha512-Qf8WRDVcyVd14if6VTWenebxFbKnVnbzPUJjlzjkyJGeHK2xCGd63Dr1XZzj0plXKQb9P0BfOxoc1HVeCo2BWQ==} - engines: {node: '>=22.12.0'} - - '@commitlint/config-validator@21.2.0': - resolution: {integrity: sha512-t7AzNHAKeIdo/3NRGwzpufKHsKkPHmFs/56N2Fnsh0/r0rGtnQzTxk6vnFgjaGr4hdSQKNB50/KAhR9Yk4LJKA==} - engines: {node: '>=22.12.0'} - - '@commitlint/ensure@21.2.0': - resolution: {integrity: sha512-76IF9vDNS13lAzEEik9eKwzt8f9hYhWiwVXZ2AnyLCz5/f511FsEQ3pw1X3/zSQpdRLQU7i5qDMVKyXi1GWjSg==} - engines: {node: '>=22.12.0'} - - '@commitlint/execute-rule@21.0.1': - resolution: {integrity: sha512-RifH+FmImozKBE6mozhF4K3r2RRKP7SMi/Q/zLCmExtp5e05lhHOUYqGBlFBAGNHaZxU/WYw1XuugYK9jQzqnA==} - engines: {node: '>=22.12.0'} - - '@commitlint/format@21.2.0': - resolution: {integrity: sha512-c4q64xaav2U83t7k7RyzJerBZurPer7FxUOY0RL5L/6CZijZ7K+s6HIBGIghj0ey1P2+seRX0J9XQYtDued6tg==} - engines: {node: '>=22.12.0'} - - '@commitlint/is-ignored@21.2.0': - resolution: {integrity: sha512-4/eB0vBN7L88O/oC4ajAEqi7j2ZfNgxl/+11RfAV9YosejZgDXhY2C9VcHnHJhOzPLoSy5P3Mg/46kqeyJfXKw==} - engines: {node: '>=22.12.0'} - - '@commitlint/lint@21.2.0': - resolution: {integrity: sha512-ceO5dp9pLjEZ6y6qbq/uXWXDPykqqlTsyzoQ0NzecpisSJhK3kTy9qzQoPeJuWG/IMNdV1lO0RgmzqoAlSi1uw==} - engines: {node: '>=22.12.0'} - - '@commitlint/load@21.2.0': - resolution: {integrity: sha512-RjlzWQqruRwIenJEfZtq7kG97co97nKoHpflE5YnF61tDLXxHPrdWImgzw6VL6MlFyaOcVlk74eBV8ZQmc3oIA==} - engines: {node: '>=22.12.0'} - - '@commitlint/message@21.2.0': - resolution: {integrity: sha512-YxGoiXD/HXNXLJPrQwE5poXa+XH0CBEm+mdvbHQP0g6MV/dmJyUFCzPNzZbxL93GvZ70TmtTK0Z0/IBpAqHv8g==} - engines: {node: '>=22.12.0'} - - '@commitlint/parse@21.2.0': - resolution: {integrity: sha512-QHWxG4d0PLTF634/AdyZ0MQS+CLn5YOuJlCFhMMlSGKFxzYGUetkHBj18xgBD+6fVzUrA2lrCdi/vlS2f/oYXg==} - engines: {node: '>=22.12.0'} - - '@commitlint/read@21.2.1': - resolution: {integrity: sha512-hUW7EJQnNTL0vPOmVMNK4CrnrNBN0nN+JJHReFkdHO5y4iyHeEmTBwuC15OCqUTjxWo7idnH1LftfpWVIaPWIA==} - engines: {node: '>=22.12.0'} - - '@commitlint/resolve-extends@21.2.0': - resolution: {integrity: sha512-4O/1j51+79Wth9s/MGxt/5gs0XYLDgNlYpltQfhAvLE0itusLKs9zruxbiNg1oOkmkb9L9L4USYGjEj7n87NxA==} - engines: {node: '>=22.12.0'} - - '@commitlint/rules@21.2.0': - resolution: {integrity: sha512-C2yXMNpiB8ETZKfx5JD8+ExgF8vTU1VQMKPSUUYwqKpw9oJWQBrlXBpdU038mj2WPjof7o9UzFpmTyBeGMZwZg==} - engines: {node: '>=22.12.0'} - - '@commitlint/to-lines@21.0.1': - resolution: {integrity: sha512-bd1BFII7p1EQZre9Kaj+kKaMFP3cFCdt21K7DItVux9XP5WjLgJ0/Uy1pJJh9aPwVJ6SKg62PxqlZaHI8hQAXw==} - engines: {node: '>=22.12.0'} - - '@commitlint/top-level@21.2.0': - resolution: {integrity: sha512-Y5gmQ+KxzqCrBFJfLvFEPvvwD3LDiNZoTT2yeFBm96M8qhmqSzQc5DvX3rheAaAMjyIvMXOCLS/mWfdpONsjyQ==} - engines: {node: '>=22.12.0'} - - '@commitlint/types@21.2.0': - resolution: {integrity: sha512-7zVFCDB2reMvJH5dmbKnOQPjZEvjdJTH8jc0U/PIPU1r3/+vf5pD1HlfitV2MWsWXrvu7u39iY1lyLUPOaN0Gw==} - engines: {node: '>=22.12.0'} - - '@conventional-changelog/git-client@3.1.0': - resolution: {integrity: sha512-Tqa/gHco2WJWa740NRjOrfKVvzIqxkZpecb8bemaQ8sKM5PXb1UK4uTyTb/1wIqNuOVaDOFxyBdhTIQZn6gdjQ==} - engines: {node: '>=22'} - peerDependencies: - conventional-commits-filter: ^6.0.1 - conventional-commits-parser: ^7.0.1 - peerDependenciesMeta: - conventional-commits-filter: - optional: true - conventional-commits-parser: - optional: true - - '@conventional-changelog/template@1.2.1': - resolution: {integrity: sha512-TzlTVpKPjaqW6qOYjQcYUDuGsLCNsvFHVBXkYGTAnf5V37jCWrE5haKNXzz0WZUtVHjrpV76L1buANjwXMfT8w==} - engines: {node: '>=22'} - '@emnapi/core@1.11.1': resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==} @@ -1523,14 +1441,6 @@ packages: '@rolldown/pluginutils@1.0.1': resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} - '@simple-libs/child-process-utils@2.0.0': - resolution: {integrity: sha512-dvNoRKLijXnD0XoJAz94pbNuB5GQgDr55UhpSPhffDkTT0Cmcqh9jSCOtwfT2d4H6MI9E7c4SgtMuJXZ6F3c6A==} - engines: {node: '>=22'} - - '@simple-libs/stream-utils@2.0.0': - resolution: {integrity: sha512-fCTuZK4QBa+39Oz9l4OGfJfz+GpwCp3AqO7Zch3to99xHPgstVsRFpeQ8LNd2o1Gv8raL2mCFwiaHh7bFSp5DQ==} - engines: {node: '>=22'} - '@solid-primitives/active-element@2.1.6': resolution: {integrity: sha512-kChC9c21g+/n0bfy2b5pkcGAgfiA4G/wcCSxVbrCXlnHfROw9PJi8x4ilYxOYSAnWvpI5pZXvK2McPXYE0y0oA==} peerDependencies: @@ -2035,36 +1945,18 @@ packages: engines: {node: '>=0.4.0'} hasBin: true - ajv@8.20.0: - resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} - ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - ansi-regex@6.2.2: - resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} - engines: {node: '>=12'} - ansi-styles@5.2.0: resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} engines: {node: '>=10'} - ansi-styles@6.2.3: - resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} - engines: {node: '>=12'} - ansis@4.3.1: resolution: {integrity: sha512-BJ8/l4R5LRE7hW9WdSuGYrLSHi2ynxeFpDFbH0K/CgNeY/tyhk+vO6TYxXC5r5CpUhNVX310xzPsN/H9lCdfOA==} engines: {node: '>=14'} - argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - - argue-cli@3.1.0: - resolution: {integrity: sha512-DhBpBfXL4SS2uC0N922MMajKR3CdrTG0u2or1PNYgXMsrSzViJrbtvT0nCLlLGUI0plam/ZZCs7aAauHtW9thw==} - engines: {node: '>=22'} - aria-query@5.3.0: resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} @@ -2116,10 +2008,6 @@ packages: resolution: {integrity: sha512-tixWYgm5ZoOD+3g6UTea91eow5z6AAHaho3g0V9CNSNb45gM8SmflpAc+GRd1InC4AqN/07Unrgp56Y94N9hJQ==} engines: {node: '>=20.19.0'} - callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - caniuse-lite@1.0.30001809: resolution: {integrity: sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ==} @@ -2135,43 +2023,9 @@ packages: resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} engines: {node: '>= 16'} - cliui@9.0.1: - resolution: {integrity: sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==} - engines: {node: '>=20'} - - conventional-changelog-angular@9.2.1: - resolution: {integrity: sha512-oWSL6ZhnXbYraOFTK3PgRAQJ8fADDAEv5K6AdeyQPLvjFmhG8+ejL0jZZp/R7vTmGJaBvZEE+sE7dB4bCv7sAw==} - engines: {node: '>=22'} - - conventional-changelog-conventionalcommits@10.2.1: - resolution: {integrity: sha512-n4Kr1HFMTf3iMbES0TMxKIcYtUUv4rKqyQQp2JwfOEfFCOfGT3Tq4mCyJ8S9/YPyWhydjfKrrvnyl+gCjA+mJQ==} - engines: {node: '>=22'} - - conventional-commits-parser@7.1.0: - resolution: {integrity: sha512-DPp6hkUjvwIivxbkrTiLXeRswNv1A/4GFA2X6scXma0AMa9632V3TwxmrlkUIEtUktiM3Ln+RrSH2xlP3/jUTw==} - engines: {node: '>=22'} - hasBin: true - convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - cosmiconfig-typescript-loader@6.3.0: - resolution: {integrity: sha512-Akr82WH1Wfqatyiqpj8HDkO2o2KmJRu1FhKfSNJP3K4IdXwHfEyL7MOb62i1AGQVLtIQM+iCE9CGOtrfhR+mmA==} - engines: {node: '>=v18'} - peerDependencies: - '@types/node': '*' - cosmiconfig: '>=9' - typescript: '>=5' - - cosmiconfig@9.0.1: - resolution: {integrity: sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==} - engines: {node: '>=14'} - peerDependencies: - typescript: '>=4.9.5' - peerDependenciesMeta: - typescript: - optional: true - css.escape@1.5.1: resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} @@ -2235,9 +2089,6 @@ packages: electron-to-chromium@1.5.409: resolution: {integrity: sha512-ChI4N44d0B4A6C8prnNjMOaGgE59fUyEVYcRYm2XEXIjMbbvF5i9UL1cblDbpGqiU0uS8FE8UcKxqZqTXdmzbQ==} - emoji-regex@10.6.0: - resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} - empathic@2.0.1: resolution: {integrity: sha512-YGRs8knHhKHVShLkFET/rWAU8kmHbOV5LwN938RHI0pljAJ1Gf6SzXsSmRaEzcXTtOOmVqJ5+WtQPL5uigY50Q==} engines: {node: '>=14'} @@ -2246,19 +2097,9 @@ packages: resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} engines: {node: '>=0.12'} - env-paths@2.2.1: - resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} - engines: {node: '>=6'} - - error-ex@1.3.4: - resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} - es-module-lexer@2.1.0: resolution: {integrity: sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==} - es-toolkit@1.47.0: - resolution: {integrity: sha512-n1GuoD0WEQZMBk5tttoZSqwgyLx01oqa5XsBmCHwPyNe1S9jPBEmtR2pSgp2kJuWE3ciFZ6yRHmY4pM4C3OOkw==} - esbuild@0.28.1: resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==} engines: {node: '>=18'} @@ -2280,12 +2121,6 @@ packages: resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} engines: {node: '>=12.0.0'} - fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - - fast-uri@3.1.6: - resolution: {integrity: sha512-7Ical1vFEMr0onbVzEDIreM22I4khW+fzyQPwvAFWBp1iwdshSZRsL4jjRvPG9JP1uiqMHRto+YU6R2/CzDz5Q==} - fdir@6.5.0: resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} engines: {node: '>=12.0.0'} @@ -2309,22 +2144,10 @@ packages: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} - get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - - get-east-asian-width@1.6.0: - resolution: {integrity: sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==} - engines: {node: '>=18'} - get-tsconfig@5.0.0-beta.5: resolution: {integrity: sha512-/6gFNr0N04nob252sTQxyFLi3eKFRqIg1I87YcqAMT1i6SQrSF6KujUEQrtrjMV0H/eejTCltLdDSTEMzHbnsQ==} engines: {node: '>=20.20.0'} - global-directory@5.0.0: - resolution: {integrity: sha512-1pgFdhK3J2LeM+dVf2Pd424yHx2ou338lC0ErNP2hPx4j8eW1Sp0XqSjNxtk6Tc4Kr5wlWtSvz8cn2yb7/SG/w==} - engines: {node: '>=20'} - has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} @@ -2343,10 +2166,6 @@ packages: engines: {node: '>=18'} hasBin: true - import-fresh@3.3.1: - resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} - engines: {node: '>=6'} - import-without-cache@0.4.0: resolution: {integrity: sha512-NkJQA7oZ4YHQhd2+H3BoRFKF3d/XNsiKpHZCQEMH9pDX27hQQLsTyOocyRgaIVtf8gHX3Nt3LPkR4e5EdtPAGQ==} engines: {node: ^22.18.0 || >=24.0.0} @@ -2355,13 +2174,6 @@ packages: resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} engines: {node: '>=8'} - ini@6.0.0: - resolution: {integrity: sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ==} - engines: {node: ^20.17.0 || >=22.9.0} - - is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - is-docker@3.0.0: resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -2372,10 +2184,6 @@ packages: engines: {node: '>=14.16'} hasBin: true - is-plain-obj@4.1.0: - resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} - engines: {node: '>=12'} - is-what@4.1.16: resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} engines: {node: '>=12.13'} @@ -2403,21 +2211,11 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - js-yaml@4.3.2: - resolution: {integrity: sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==} - hasBin: true - jsesc@3.1.0: resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} engines: {node: '>=6'} hasBin: true - json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - - json-schema-traverse@1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - json5@2.2.3: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} @@ -2501,9 +2299,6 @@ packages: resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} engines: {node: '>=14'} - lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - lit-element@4.2.2: resolution: {integrity: sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w==} @@ -2602,14 +2397,6 @@ packages: vite-plus: optional: true - parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - - parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} - parse5@7.3.0: resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} @@ -2693,18 +2480,6 @@ packages: resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} engines: {node: '>=8'} - require-from-string@2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - - resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - - resolve-from@5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} @@ -2817,14 +2592,6 @@ packages: vite-plus: optional: true - string-width@7.2.0: - resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} - engines: {node: '>=18'} - - strip-ansi@7.2.0: - resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} - engines: {node: '>=12'} - strip-indent@3.0.0: resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} engines: {node: '>=8'} @@ -2935,7 +2702,7 @@ packages: resolution: {integrity: sha512-ZZ61DsRsOnakl74HAmp3oSN4aXUmEWXf+i/yv0h7tIBfICc3VdrFErQKUUKPgu3AMsTUMbcongALEN4l6GSUrQ==} hasBin: true peerDependencies: - browserslist: ^4.28.7 + browserslist: '>= 4.21.0' use-sync-external-store@1.6.0: resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==} @@ -3055,10 +2822,6 @@ packages: engines: {node: '>=8'} hasBin: true - wrap-ansi@9.0.2: - resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} - engines: {node: '>=18'} - ws@8.21.0: resolution: {integrity: sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==} engines: {node: '>=10.0.0'} @@ -3075,21 +2838,9 @@ packages: resolution: {integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==} engines: {node: '>=18'} - y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - yargs-parser@22.0.0: - resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==} - engines: {node: ^20.19.0 || ^22.12.0 || >=23} - - yargs@18.0.0: - resolution: {integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==} - engines: {node: ^20.19.0 || ^22.12.0 || >=23} - yuku-ast@0.1.7: resolution: {integrity: sha512-2RiMEWv500TixY5rJy6OZd4fSy9WYZKWh6gGbIJ7y7vAGcuCugWOWwOLGaQcRZrXcPUfqtLtvpaJ3SdXtWlhKA==} @@ -3218,125 +2969,6 @@ snapshots: '@blazediff/core@1.9.1': {} - '@commitlint/cli@21.2.1(@types/node@24.13.2)(conventional-commits-parser@7.1.0)(typescript@6.0.2)': - dependencies: - '@commitlint/config-conventional': 21.2.0 - '@commitlint/format': 21.2.0 - '@commitlint/lint': 21.2.0 - '@commitlint/load': 21.2.0(@types/node@24.13.2)(typescript@6.0.2) - '@commitlint/read': 21.2.1(conventional-commits-parser@7.1.0) - '@commitlint/types': 21.2.0 - tinyexec: 1.2.4 - yargs: 18.0.0 - transitivePeerDependencies: - - '@types/node' - - conventional-commits-filter - - conventional-commits-parser - - typescript - - '@commitlint/config-conventional@21.2.0': - dependencies: - '@commitlint/types': 21.2.0 - conventional-changelog-conventionalcommits: 10.2.1 - - '@commitlint/config-validator@21.2.0': - dependencies: - '@commitlint/types': 21.2.0 - ajv: 8.20.0 - - '@commitlint/ensure@21.2.0': - dependencies: - '@commitlint/types': 21.2.0 - es-toolkit: 1.47.0 - - '@commitlint/execute-rule@21.0.1': {} - - '@commitlint/format@21.2.0': - dependencies: - '@commitlint/types': 21.2.0 - picocolors: 1.1.1 - - '@commitlint/is-ignored@21.2.0': - dependencies: - '@commitlint/types': 21.2.0 - semver: 7.8.5 - - '@commitlint/lint@21.2.0': - dependencies: - '@commitlint/is-ignored': 21.2.0 - '@commitlint/parse': 21.2.0 - '@commitlint/rules': 21.2.0 - '@commitlint/types': 21.2.0 - - '@commitlint/load@21.2.0(@types/node@24.13.2)(typescript@6.0.2)': - dependencies: - '@commitlint/config-validator': 21.2.0 - '@commitlint/execute-rule': 21.0.1 - '@commitlint/resolve-extends': 21.2.0 - '@commitlint/types': 21.2.0 - cosmiconfig: 9.0.1(typescript@6.0.2) - cosmiconfig-typescript-loader: 6.3.0(@types/node@24.13.2)(cosmiconfig@9.0.1(typescript@6.0.2))(typescript@6.0.2) - es-toolkit: 1.47.0 - is-plain-obj: 4.1.0 - picocolors: 1.1.1 - transitivePeerDependencies: - - '@types/node' - - typescript - - '@commitlint/message@21.2.0': {} - - '@commitlint/parse@21.2.0': - dependencies: - '@commitlint/types': 21.2.0 - conventional-changelog-angular: 9.2.1 - conventional-commits-parser: 7.1.0 - - '@commitlint/read@21.2.1(conventional-commits-parser@7.1.0)': - dependencies: - '@commitlint/top-level': 21.2.0 - '@commitlint/types': 21.2.0 - '@conventional-changelog/git-client': 3.1.0(conventional-commits-parser@7.1.0) - tinyexec: 1.2.4 - transitivePeerDependencies: - - conventional-commits-filter - - conventional-commits-parser - - '@commitlint/resolve-extends@21.2.0': - dependencies: - '@commitlint/config-validator': 21.2.0 - '@commitlint/types': 21.2.0 - es-toolkit: 1.47.0 - global-directory: 5.0.0 - resolve-from: 5.0.0 - - '@commitlint/rules@21.2.0': - dependencies: - '@commitlint/ensure': 21.2.0 - '@commitlint/message': 21.2.0 - '@commitlint/to-lines': 21.0.1 - '@commitlint/types': 21.2.0 - - '@commitlint/to-lines@21.0.1': {} - - '@commitlint/top-level@21.2.0': - dependencies: - escalade: 3.2.0 - - '@commitlint/types@21.2.0': - dependencies: - conventional-commits-parser: 7.1.0 - picocolors: 1.1.1 - - '@conventional-changelog/git-client@3.1.0(conventional-commits-parser@7.1.0)': - dependencies: - '@simple-libs/child-process-utils': 2.0.0 - '@simple-libs/stream-utils': 2.0.0 - semver: 7.8.5 - optionalDependencies: - conventional-commits-parser: 7.1.0 - - '@conventional-changelog/template@1.2.1': {} - '@emnapi/core@1.11.1': dependencies: '@emnapi/wasi-threads': 1.2.2 @@ -3491,11 +3123,6 @@ snapshots: '@types/react': 19.2.15 react: 19.2.6 - '@napi-rs/wasm-runtime@1.1.6': - dependencies: - '@tybys/wasm-util': 0.10.3 - optional: true - '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': dependencies: '@emnapi/core': 1.11.1 @@ -3626,14 +3253,6 @@ snapshots: '@oxc-resolver/binding-openharmony-arm64@11.19.1': optional: true - '@oxc-resolver/binding-wasm32-wasi@11.19.1': - dependencies: - '@napi-rs/wasm-runtime': 1.1.6 - transitivePeerDependencies: - - '@emnapi/core' - - '@emnapi/runtime' - optional: true - '@oxc-resolver/binding-wasm32-wasi@11.19.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': dependencies: '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) @@ -3840,12 +3459,6 @@ snapshots: '@rolldown/pluginutils@1.0.1': {} - '@simple-libs/child-process-utils@2.0.0': - dependencies: - '@simple-libs/stream-utils': 2.0.0 - - '@simple-libs/stream-utils@2.0.0': {} - '@solid-primitives/active-element@2.1.6(solid-js@1.9.14)': dependencies: '@solid-primitives/event-listener': 2.4.6(solid-js@1.9.14) @@ -4319,27 +3932,12 @@ snapshots: acorn@8.16.0: {} - ajv@8.20.0: - dependencies: - fast-deep-equal: 3.1.3 - fast-uri: 3.1.6 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - ansi-regex@5.0.1: {} - ansi-regex@6.2.2: {} - ansi-styles@5.2.0: {} - ansi-styles@6.2.3: {} - ansis@4.3.1: {} - argparse@2.0.1: {} - - argue-cli@3.1.0: {} - aria-query@5.3.0: dependencies: dequal: 2.0.3 @@ -4386,8 +3984,6 @@ snapshots: cac@7.0.0: {} - callsites@3.1.0: {} - caniuse-lite@1.0.30001809: {} chai@5.3.3: @@ -4402,43 +3998,8 @@ snapshots: check-error@2.1.3: {} - cliui@9.0.1: - dependencies: - string-width: 7.2.0 - strip-ansi: 7.2.0 - wrap-ansi: 9.0.2 - - conventional-changelog-angular@9.2.1: - dependencies: - '@conventional-changelog/template': 1.2.1 - - conventional-changelog-conventionalcommits@10.2.1: - dependencies: - '@conventional-changelog/template': 1.2.1 - - conventional-commits-parser@7.1.0: - dependencies: - '@simple-libs/stream-utils': 2.0.0 - argue-cli: 3.1.0 - convert-source-map@2.0.0: {} - cosmiconfig-typescript-loader@6.3.0(@types/node@24.13.2)(cosmiconfig@9.0.1(typescript@6.0.2))(typescript@6.0.2): - dependencies: - '@types/node': 24.13.2 - cosmiconfig: 9.0.1(typescript@6.0.2) - jiti: 2.6.1 - typescript: 6.0.2 - - cosmiconfig@9.0.1(typescript@6.0.2): - dependencies: - env-paths: 2.2.1 - import-fresh: 3.3.1 - js-yaml: 4.3.2 - parse-json: 5.2.0 - optionalDependencies: - typescript: 6.0.2 - css.escape@1.5.1: {} csstype@3.2.3: {} @@ -4476,28 +4037,14 @@ snapshots: optionalDependencies: oxc-resolver: 11.19.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) - dts-resolver@3.0.0(oxc-resolver@11.19.1): - optionalDependencies: - oxc-resolver: 11.19.1 - electron-to-chromium@1.5.409: {} - emoji-regex@10.6.0: {} - empathic@2.0.1: {} entities@6.0.1: {} - env-paths@2.2.1: {} - - error-ex@1.3.4: - dependencies: - is-arrayish: 0.2.1 - es-module-lexer@2.1.0: {} - es-toolkit@1.47.0: {} - esbuild@0.28.1: optionalDependencies: '@esbuild/aix-ppc64': 0.28.1 @@ -4537,10 +4084,6 @@ snapshots: expect-type@1.3.0: {} - fast-deep-equal@3.1.3: {} - - fast-uri@3.1.6: {} - fdir@6.5.0(picomatch@4.0.5): optionalDependencies: picomatch: 4.0.5 @@ -4553,18 +4096,10 @@ snapshots: gensync@1.0.0-beta.2: {} - get-caller-file@2.0.5: {} - - get-east-asian-width@1.6.0: {} - get-tsconfig@5.0.0-beta.5: dependencies: resolve-pkg-maps: 1.0.0 - global-directory@5.0.0: - dependencies: - ini: 6.0.0 - has-flag@4.0.0: {} hookable@6.1.1: {} @@ -4575,27 +4110,16 @@ snapshots: husky@9.1.7: {} - import-fresh@3.3.1: - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - import-without-cache@0.4.0: {} indent-string@4.0.0: {} - ini@6.0.0: {} - - is-arrayish@0.2.1: {} - is-docker@3.0.0: {} is-inside-container@1.0.0: dependencies: is-docker: 3.0.0 - is-plain-obj@4.1.0: {} - is-what@4.1.16: {} is-wsl@3.1.1: @@ -4615,20 +4139,13 @@ snapshots: html-escaper: 2.0.2 istanbul-lib-report: 3.0.1 - jiti@2.6.1: {} + jiti@2.6.1: + optional: true js-tokens@4.0.0: {} - js-yaml@4.3.2: - dependencies: - argparse: 2.0.1 - jsesc@3.1.0: {} - json-parse-even-better-errors@2.3.1: {} - - json-schema-traverse@1.0.0: {} - json5@2.2.3: {} lightningcss-android-arm64@1.32.0: @@ -4682,8 +4199,6 @@ snapshots: lilconfig@3.1.3: {} - lines-and-columns@1.2.4: {} - lit-element@4.2.2: dependencies: '@lit-labs/ssr-dom-shim': 1.6.0 @@ -4770,33 +4285,6 @@ snapshots: '@oxc-parser/binding-win32-ia32-msvc': 0.127.0 '@oxc-parser/binding-win32-x64-msvc': 0.127.0 - oxc-resolver@11.19.1: - optionalDependencies: - '@oxc-resolver/binding-android-arm-eabi': 11.19.1 - '@oxc-resolver/binding-android-arm64': 11.19.1 - '@oxc-resolver/binding-darwin-arm64': 11.19.1 - '@oxc-resolver/binding-darwin-x64': 11.19.1 - '@oxc-resolver/binding-freebsd-x64': 11.19.1 - '@oxc-resolver/binding-linux-arm-gnueabihf': 11.19.1 - '@oxc-resolver/binding-linux-arm-musleabihf': 11.19.1 - '@oxc-resolver/binding-linux-arm64-gnu': 11.19.1 - '@oxc-resolver/binding-linux-arm64-musl': 11.19.1 - '@oxc-resolver/binding-linux-ppc64-gnu': 11.19.1 - '@oxc-resolver/binding-linux-riscv64-gnu': 11.19.1 - '@oxc-resolver/binding-linux-riscv64-musl': 11.19.1 - '@oxc-resolver/binding-linux-s390x-gnu': 11.19.1 - '@oxc-resolver/binding-linux-x64-gnu': 11.19.1 - '@oxc-resolver/binding-linux-x64-musl': 11.19.1 - '@oxc-resolver/binding-openharmony-arm64': 11.19.1 - '@oxc-resolver/binding-wasm32-wasi': 11.19.1 - '@oxc-resolver/binding-win32-arm64-msvc': 11.19.1 - '@oxc-resolver/binding-win32-ia32-msvc': 11.19.1 - '@oxc-resolver/binding-win32-x64-msvc': 11.19.1 - transitivePeerDependencies: - - '@emnapi/core' - - '@emnapi/runtime' - optional: true - oxc-resolver@11.19.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1): optionalDependencies: '@oxc-resolver/binding-android-arm-eabi': 11.19.1 @@ -4879,17 +4367,6 @@ snapshots: '@oxlint/binding-win32-x64-msvc': 1.71.0 oxlint-tsgolint: 0.23.0 - parent-module@1.0.1: - dependencies: - callsites: 3.1.0 - - parse-json@5.2.0: - dependencies: - '@babel/code-frame': 7.29.7 - error-ex: 1.3.4 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - parse5@7.3.0: dependencies: entities: 6.0.1 @@ -4957,12 +4434,6 @@ snapshots: indent-string: 4.0.0 strip-indent: 3.0.0 - require-from-string@2.0.2: {} - - resolve-from@4.0.0: {} - - resolve-from@5.0.0: {} - resolve-pkg-maps@1.0.0: {} rolldown-plugin-dts@0.27.6(oxc-resolver@11.19.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1))(rolldown@1.1.5)(typescript@6.0.2): @@ -4979,20 +4450,6 @@ snapshots: transitivePeerDependencies: - oxc-resolver - rolldown-plugin-dts@0.27.6(oxc-resolver@11.19.1)(rolldown@1.1.5)(typescript@6.0.2): - dependencies: - dts-resolver: 3.0.0(oxc-resolver@11.19.1) - get-tsconfig: 5.0.0-beta.5 - obug: 2.1.3 - rolldown: 1.1.5 - yuku-ast: 0.1.7 - yuku-codegen: 0.5.48 - yuku-parser: 0.5.48 - optionalDependencies: - typescript: 6.0.2 - transitivePeerDependencies: - - oxc-resolver - rolldown@1.1.5: dependencies: '@oxc-project/types': 0.139.0 @@ -5105,16 +4562,6 @@ snapshots: - react-dom - utf-8-validate - string-width@7.2.0: - dependencies: - emoji-regex: 10.6.0 - get-east-asian-width: 1.6.0 - strip-ansi: 7.2.0 - - strip-ansi@7.2.0: - dependencies: - ansi-regex: 6.2.2 - strip-indent@3.0.0: dependencies: min-indent: 1.0.1 @@ -5174,32 +4621,6 @@ snapshots: - oxc-resolver - vue-tsc - tsdown@0.22.5(@tsdown/css@0.22.5)(oxc-resolver@11.19.1)(typescript@6.0.2): - dependencies: - ansis: 4.3.1 - cac: 7.0.0 - defu: 6.1.7 - empathic: 2.0.1 - hookable: 6.1.1 - import-without-cache: 0.4.0 - obug: 2.1.3 - picomatch: 4.0.5 - rolldown: 1.1.5 - rolldown-plugin-dts: 0.27.6(oxc-resolver@11.19.1)(rolldown@1.1.5)(typescript@6.0.2) - semver: 7.8.5 - tinyexec: 1.2.4 - tinyglobby: 0.2.17 - tree-kill: 1.2.2 - unconfig-core: 7.5.0 - optionalDependencies: - '@tsdown/css': 0.22.5(jiti@2.6.1)(postcss@8.5.26)(tsdown@0.22.5) - typescript: 6.0.2 - transitivePeerDependencies: - - '@ts-macro/tsc' - - '@typescript/native-preview' - - oxc-resolver - - vue-tsc - tslib@2.8.1: {} turbo@2.10.11: @@ -5307,33 +4728,14 @@ snapshots: siginfo: 2.0.0 stackback: 0.0.2 - wrap-ansi@9.0.2: - dependencies: - ansi-styles: 6.2.3 - string-width: 7.2.0 - strip-ansi: 7.2.0 - ws@8.21.0: {} wsl-utils@0.1.0: dependencies: is-wsl: 3.1.1 - y18n@5.0.8: {} - yallist@3.1.1: {} - yargs-parser@22.0.0: {} - - yargs@18.0.0: - dependencies: - cliui: 9.0.1 - escalade: 3.2.0 - get-caller-file: 2.0.5 - string-width: 7.2.0 - y18n: 5.0.8 - yargs-parser: 22.0.0 - yuku-ast@0.1.7: dependencies: '@yuku-toolchain/types': 0.5.43 @@ -5371,8 +4773,6 @@ snapshots: '@yuku-parser/binding-win32-x64': 0.5.48 time: - '@commitlint/cli@21.2.1': '2026-07-08T07:48:07.331Z' - '@commitlint/config-conventional@21.2.0': '2026-06-30T09:53:56.373Z' '@fontsource-variable/roboto-flex@5.2.8': '2025-09-17T09:19:50.613Z' '@fontsource/google-sans-flex@5.2.3': '2026-04-05T02:07:03.914Z' '@material/material-color-utilities@0.4.0': '2026-01-21T18:35:58.484Z' diff --git a/scripts/helpers/lint-git-commit-msg.ts b/scripts/helpers/lint-git-commit-msg.ts new file mode 100644 index 00000000..730b7f92 --- /dev/null +++ b/scripts/helpers/lint-git-commit-msg.ts @@ -0,0 +1,74 @@ +const isLowerCase = (value: string): boolean => value.toLowerCase() === value; + +// Written by Gemma 4 31B, modified to fix lint warnings + +const HEADER_REGEX = /^(?[a-zA-Z]+)(?:\((?[a-zA-Z0-9-]+)\))?(?!)?: (?.+)$/u; + +export type Config = { + readonly MAX_SUBJECT_LENGTH: number; + readonly MAX_BODY_LINE_LENGTH: number; + readonly ALLOWED_TYPES: Set; + readonly ALLOWED_SCOPES: Set; +}; + +export type ProcessExit = { + exit: 0 | 1; + error?: string; +}; + +const error = (message: string): ProcessExit => ({ + exit: 1, + error: message +}); + +export const validate = (content: string, config: Config): ProcessExit => { + const lines = content.split(/\n/u).map(l => l.trimEnd()); + const [header, blank, ...body] = lines; + + // oxlint-disable-next-line typescript/strict-boolean-expressions + if (!header) { + return error('commit message is empty'); + } + + if (header.length > config.MAX_SUBJECT_LENGTH) { + return error(`header exceeds ${config.MAX_SUBJECT_LENGTH} characters`); + } + + const groups = HEADER_REGEX.exec(header)?.groups; + + if (!groups) { + return error("header must match '[()][!]: '"); + } + + const { type, scope, description } = groups; + + if (type !== undefined && !config.ALLOWED_TYPES.has(type)) { + return error(`type '${type}' is not allowed; allowed types: ${[...config.ALLOWED_TYPES].join(', ')}`); + } + + if (scope !== undefined && !config.ALLOWED_SCOPES.has(scope)) { + return error(`scope '${scope}' is not allowed; allowed scopes: ${[...config.ALLOWED_SCOPES].join(', ')}`); + } + + if (description !== undefined) { + if (description.endsWith('.')) { + return error('description must not end with a period'); + } + + if (description.length > 0 && !isLowerCase(description[0]!)) { + return error('description must start with a lower case character'); + } + } + + if (blank !== undefined && blank !== '') { + return error('blank line required between header and body'); + } + + for (const [index, line] of body.entries()) { + if (line && line.length > config.MAX_BODY_LINE_LENGTH) { + return error(`body line ${index + 3} exceeds ${config.MAX_BODY_LINE_LENGTH} characters`); + } + } + + return { exit: 0 }; +}; diff --git a/scripts/lint-git-commit-msg.mts b/scripts/lint-git-commit-msg.mts new file mode 100644 index 00000000..5756e4c0 --- /dev/null +++ b/scripts/lint-git-commit-msg.mts @@ -0,0 +1,40 @@ +/// + +// oxlint-disable-next-line import/no-nodejs-modules +import fs from 'node:fs'; +// oxlint-disable-next-line import/no-nodejs-modules +import process from 'node:process'; + +import type { Config } from './helpers/lint-git-commit-msg'; + +import { validate } from './helpers/lint-git-commit-msg.ts'; + +const getPackageNames = (): string[] => ['apps', 'packages'].flatMap(name => fs.readdirSync(name)); + +const CONFIG: Config = { + MAX_SUBJECT_LENGTH: 72, + MAX_BODY_LINE_LENGTH: 79, + ALLOWED_TYPES: new Set([ + 'feat', + 'fix', + 'docs', + 'style', + 'refactor', + 'perf', + 'test', + 'build', + 'ci', + 'chore', + 'revert' + ]), + ALLOWED_SCOPES: new Set(getPackageNames()) +} as const; + +const result = validate(fs.readFileSync(0, 'utf8'), CONFIG); + +if (result.error !== undefined) { + process.stderr.write(`ERROR: ${result.error}\n`); +} + +// oxlint-disable-next-line unicorn/no-process-exit +process.exit(result.exit); diff --git a/scripts/lint-git-commit-msg.test.ts b/scripts/lint-git-commit-msg.test.ts new file mode 100644 index 00000000..1329bbf4 --- /dev/null +++ b/scripts/lint-git-commit-msg.test.ts @@ -0,0 +1,159 @@ +import { describe, expect, it } from 'vitest'; + +import type { Config } from './helpers/lint-git-commit-msg'; + +import { validate } from './helpers/lint-git-commit-msg'; + +const CONFIG: Config = { + MAX_SUBJECT_LENGTH: 72, + MAX_BODY_LINE_LENGTH: 79, + ALLOWED_TYPES: new Set([ + 'feat', + 'fix', + 'docs', + 'style', + 'refactor', + 'perf', + 'test', + 'build', + 'ci', + 'chore', + 'revert' + ]), + ALLOWED_SCOPES: new Set(['valid-scope']) +} as const; + +// Written by Gemma 4 31B, modified to fix lint warnings + +describe('Lint Git commit message', () => { + describe('Happy Path', () => { + it('should accept a simple valid header', () => { + const { exit } = validate('feat: add user authentication', CONFIG); + expect(exit).toBe(0); + }); + + it('should accept a header with a valid scope', () => { + const { exit } = validate(`fix(valid-scope): resolve memory leak`, CONFIG); + expect(exit).toBe(0); + }); + + it('should accept a breaking change with scope', () => { + const { exit } = validate(`refactor(valid-scope)!: rewrite button API`, CONFIG); + expect(exit).toBe(0); + }); + + it('should accept a breaking change without scope', () => { + const { exit } = validate('feat!: remove deprecated endpoints', CONFIG); + expect(exit).toBe(0); + }); + + it('should accept a valid header and body', () => { + const { exit } = validate('chore: update dependencies\n\nBump package to v1.2.3', CONFIG); + expect(exit).toBe(0); + }); + + it('should accept a multi-line body', () => { + const { exit } = validate('docs: update readme\n\nLine 1\nLine 2', CONFIG); + expect(exit).toBe(0); + }); + }); + + describe('Header Validation', () => { + it('should fail on empty input', () => { + const { exit, error } = validate('', CONFIG); + expect(exit).toBe(1); + expect(error).toContain('commit message is empty'); + }); + + it('should fail if header exceeds 72 characters', () => { + const { exit, error } = validate(`feat: ${'a'.repeat(67)}`, CONFIG); + expect(exit).toBe(1); + expect(error).toContain('header exceeds 72 characters'); + }); + + it('should fail on invalid format (missing colon)', () => { + const { exit, error } = validate('this is a random commit message', CONFIG); + expect(exit).toBe(1); + expect(error).toContain('header must match'); + }); + + it('should fail on unsupported type', () => { + const { exit, error } = validate('update(web): change logic', CONFIG); + expect(exit).toBe(1); + expect(error).toContain("type 'update' is not allowed"); + }); + + it('should fail on unsupported scope', () => { + const { exit, error } = validate('feat(nonexistent-scope): add endpoint', CONFIG); + expect(exit).toBe(1); + expect(error).toContain("scope 'nonexistent-scope' is not allowed"); + }); + + it('should fail on uppercase type', () => { + const { exit, error } = validate('Feat: add login', CONFIG); + expect(exit).toBe(1); + expect(error).toContain("type 'Feat' is not allowed"); + }); + }); + + describe('Description Rules', () => { + it('should fail if description ends with a period', () => { + const { exit, error } = validate('fix: resolve bug.', CONFIG); + expect(exit).toBe(1); + expect(error).toContain('description must not end with a period'); + }); + + it('should fail if description starts with upper case character', () => { + const { exit, error } = validate('feat: Add new feature', CONFIG); + expect(exit).toBe(1); + expect(error).toContain('description must start with a lower case character'); + }); + + it('should succeed if description starts with a number', () => { + const { exit } = validate('feat: 123 fix issue', CONFIG); + expect(exit).toBe(0); + }); + }); + + describe('Body and Spacing', () => { + it('should fail if blank line is missing between header and body', () => { + const { exit, error } = validate('feat: add login\nImmediately starting body', CONFIG); + expect(exit).toBe(1); + expect(error).toContain('blank line required'); + }); + + it('should fail if body line exceeds 79 characters', () => { + const { exit, error } = validate(`feat: add login\n\n${'a'.repeat(80)}`, CONFIG); + expect(exit).toBe(1); + expect(error).toContain('body line 3 exceeds 79 characters'); + }); + + it('should report correct line number for body errors', () => { + const { exit, error } = validate(`feat: add login\n\nShort line\n${'a'.repeat(80)}`, CONFIG); + expect(exit).toBe(1); + expect(error).toContain('body line 4 exceeds 79 characters'); + }); + }); + + describe('Edge Cases', () => { + it('should handle unicode/emojis in description', () => { + const { exit } = validate(`feat: add 🚀 emoji support`, CONFIG); + expect(exit).toBe(0); + }); + + it('should ignore trailing whitespace in header for length checks', () => { + const { exit } = validate(`feat: add login${' '.repeat(70)}`, CONFIG); + expect(exit).toBe(0); + }); + + it('should accept a commit with only a header', () => { + const { exit } = validate('feat: add login', CONFIG); + expect(exit).toBe(0); + }); + + it('should allow empty lines within the body', () => { + const { exit } = validate('feat: add login\n\nLine 1\n\nLine 3', CONFIG); + expect(exit).toBe(0); + }); + }); +}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..5a61a971 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.base.json", + "compilerOptions": { + "types": [], + "rootDir": "scripts", + "allowImportingTsExtensions": true, + "noEmit": true + }, + "include": ["scripts"] +} diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 00000000..6f3031a0 --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,25 @@ +import { defineConfig } from 'vitest/config'; + +// oxlint-disable-next-line import/no-default-export +export default defineConfig({ + test: { + environment: 'node', + globals: true, + reporters: ['default', 'junit'], + outputFile: 'coverage/tests.junit.xml', + coverage: { + provider: 'istanbul', + reporter: [['cobertura', { file: 'coverage.xml' }], ['text']], + reportOnFailure: true + }, + projects: [ + { + extends: true, + test: { + name: 'scripts', + include: ['scripts/*.test.ts'] + } + } + ] + } +});