/tests/__mocks__/browser.ts"],
+ collectCoverageFrom: [
+ "src/core/engine/**/*.ts",
+ "src/platform/audio/**/*.ts",
+ ],
+ coverageDirectory: "coverage",
+ coverageReporters: ["text", "json", "html"],
+ verbose: true,
+};
diff --git a/Build/package-lock.json b/Build/package-lock.json
index e3894de..a9e4e21 100644
--- a/Build/package-lock.json
+++ b/Build/package-lock.json
@@ -49,6 +49,7 @@
"react-i18next": "^16.5.8",
"react-icons": "^5.6.0",
"sonner": "^2.0.7",
+ "tone": "^15.1.22",
"vite-plugin-singlefile": "^2.3.2",
"zustand": "^5.0.12"
},
@@ -68,8 +69,11 @@
"cross-env": "^10.1.0",
"eslint": "^9.39.4",
"eslint-plugin-react": "^7.37.5",
+ "jest": "^29.7.0",
+ "jest-environment-jsdom": "^30.3.0",
"npm-check-updates": "^19.6.3",
"prettier": "^3.8.1",
+ "ts-jest": "^29.1.2",
"vite": "^7.3.1",
"vite-plugin-pwa": "^1.2.0",
"vite-plugin-top-level-await": "^1.6.0",
@@ -77,6 +81,27 @@
"workbox-window": "^7.4.0"
}
},
+ "node_modules/@asamuzakjp/css-color": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz",
+ "integrity": "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@csstools/css-calc": "^2.1.3",
+ "@csstools/css-color-parser": "^3.0.9",
+ "@csstools/css-parser-algorithms": "^3.0.4",
+ "@csstools/css-tokenizer": "^3.0.3",
+ "lru-cache": "^10.4.3"
+ }
+ },
+ "node_modules/@asamuzakjp/css-color/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "dev": true,
+ "license": "ISC"
+ },
"node_modules/@babel/code-frame": {
"version": "7.29.0",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
@@ -368,9 +393,9 @@
}
},
"node_modules/@babel/helper-plugin-utils": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz",
- "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==",
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz",
+ "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==",
"dev": true,
"license": "MIT",
"engines": {
@@ -599,6 +624,61 @@
"@babel/core": "^7.0.0-0"
}
},
+ "node_modules/@babel/plugin-syntax-async-generators": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
+ "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-bigint": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz",
+ "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-class-properties": {
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
+ "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.12.13"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-class-static-block": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
+ "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
"node_modules/@babel/plugin-syntax-import-assertions": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.27.1.tgz",
@@ -631,6 +711,174 @@
"@babel/core": "^7.0.0-0"
}
},
+ "node_modules/@babel/plugin-syntax-import-meta": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
+ "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-json-strings": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
+ "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-jsx": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz",
+ "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+ "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+ "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-numeric-separator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+ "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-catch-binding": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
+ "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-chaining": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+ "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-private-property-in-object": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz",
+ "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-top-level-await": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
+ "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-typescript": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz",
+ "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
"node_modules/@babel/plugin-syntax-unicode-sets-regex": {
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz",
@@ -1703,6 +1951,13 @@
"node": ">=6.9.0"
}
},
+ "node_modules/@bcoe/v8-coverage": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
+ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@borewit/text-codec": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/@borewit/text-codec/-/text-codec-0.2.2.tgz",
@@ -1720,6 +1975,121 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@csstools/color-helpers": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz",
+ "integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "license": "MIT-0",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@csstools/css-calc": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz",
+ "integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@csstools/css-parser-algorithms": "^3.0.5",
+ "@csstools/css-tokenizer": "^3.0.4"
+ }
+ },
+ "node_modules/@csstools/css-color-parser": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz",
+ "integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@csstools/color-helpers": "^5.1.0",
+ "@csstools/css-calc": "^2.1.4"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@csstools/css-parser-algorithms": "^3.0.5",
+ "@csstools/css-tokenizer": "^3.0.4"
+ }
+ },
+ "node_modules/@csstools/css-parser-algorithms": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz",
+ "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@csstools/css-tokenizer": "^3.0.4"
+ }
+ },
+ "node_modules/@csstools/css-tokenizer": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz",
+ "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/@dnd-kit/accessibility": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.1.1.tgz",
@@ -2930,2835 +3300,7719 @@
"node": ">=12"
}
},
- "node_modules/@jest/diff-sequences": {
- "version": "30.0.1",
- "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz",
- "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==",
+ "node_modules/@istanbuljs/load-nyc-config": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
+ "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
"dev": true,
- "license": "MIT",
+ "license": "ISC",
+ "dependencies": {
+ "camelcase": "^5.3.1",
+ "find-up": "^4.1.0",
+ "get-package-type": "^0.1.0",
+ "js-yaml": "^3.13.1",
+ "resolve-from": "^5.0.0"
+ },
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=8"
}
},
- "node_modules/@jest/expect-utils": {
- "version": "30.2.0",
- "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.2.0.tgz",
- "integrity": "sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==",
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/get-type": "30.1.0"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "sprintf-js": "~1.0.2"
}
},
- "node_modules/@jest/get-type": {
- "version": "30.1.0",
- "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.1.0.tgz",
- "integrity": "sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==",
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=8"
}
},
- "node_modules/@jest/pattern": {
- "version": "30.0.1",
- "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.1.tgz",
- "integrity": "sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==",
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": {
+ "version": "3.14.2",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
+ "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@types/node": "*",
- "jest-regex-util": "30.0.1"
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
},
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
}
},
- "node_modules/@jest/schemas": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz",
- "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==",
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@sinclair/typebox": "^0.34.0"
+ "p-locate": "^4.1.0"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=8"
}
},
- "node_modules/@jest/types": {
- "version": "30.2.0",
- "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.2.0.tgz",
- "integrity": "sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==",
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/pattern": "30.0.1",
- "@jest/schemas": "30.0.5",
- "@types/istanbul-lib-coverage": "^2.0.6",
- "@types/istanbul-reports": "^3.0.4",
- "@types/node": "*",
- "@types/yargs": "^17.0.33",
- "chalk": "^4.1.2"
+ "p-try": "^2.0.0"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/@jridgewell/gen-mapping": {
- "version": "0.3.13",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
- "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
- "devOptional": true,
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@jridgewell/sourcemap-codec": "^1.5.0",
- "@jridgewell/trace-mapping": "^0.3.24"
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
}
},
- "node_modules/@jridgewell/remapping": {
- "version": "2.3.5",
- "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
- "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "@jridgewell/gen-mapping": "^0.3.5",
- "@jridgewell/trace-mapping": "^0.3.24"
+ "engines": {
+ "node": ">=8"
}
},
- "node_modules/@jridgewell/resolve-uri": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
- "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
- "devOptional": true,
+ "node_modules/@istanbuljs/schema": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
+ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
+ "dev": true,
"license": "MIT",
"engines": {
- "node": ">=6.0.0"
+ "node": ">=8"
}
},
- "node_modules/@jridgewell/source-map": {
- "version": "0.3.11",
- "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz",
- "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==",
- "devOptional": true,
+ "node_modules/@jest/console": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz",
+ "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@jridgewell/gen-mapping": "^0.3.5",
- "@jridgewell/trace-mapping": "^0.3.25"
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.5.5",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
- "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
- "devOptional": true,
- "license": "MIT"
+ "node_modules/@jest/console/node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@sinclair/typebox": "^0.27.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
},
- "node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.31",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
- "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
- "devOptional": true,
+ "node_modules/@jest/console/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@nisoku/satori-log": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/@nisoku/satori-log/-/satori-log-0.1.2.tgz",
- "integrity": "sha512-VlhKOByqy0DnG6b1EVuTAYJFHtBf7brwFD++3So07RTc5AyH43djtDLr0XuaD/NFiy2nCF+QQCbRo4JrMimqpg==",
+ "node_modules/@jest/console/node_modules/@sinclair/typebox": {
+ "version": "0.27.10",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
+ "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
+ "dev": true,
"license": "MIT"
},
- "node_modules/@quansync/fs": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/@quansync/fs/-/fs-0.1.5.tgz",
- "integrity": "sha512-lNS9hL2aS2NZgNW7BBj+6EBl4rOf8l+tQ0eRY6JWCI8jI2kc53gSoqbjojU0OnAWhzoXiOjFyGsHcDGePB3lhA==",
+ "node_modules/@jest/console/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "quansync": "^0.2.11"
+ "engines": {
+ "node": ">=10"
},
"funding": {
- "url": "https://github.com/sponsors/sxzz"
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/@radix-ui/number": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz",
- "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==",
- "license": "MIT"
- },
- "node_modules/@radix-ui/primitive": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz",
- "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==",
- "license": "MIT"
+ "node_modules/@jest/console/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
},
- "node_modules/@radix-ui/react-arrow": {
- "version": "1.1.7",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz",
- "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==",
+ "node_modules/@jest/console/node_modules/jest-message-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz",
+ "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/react-primitive": "2.1.3"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "@babel/code-frame": "^7.12.13",
+ "@jest/types": "^29.6.3",
+ "@types/stack-utils": "^2.0.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@radix-ui/react-collapsible": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.12.tgz",
- "integrity": "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==",
+ "node_modules/@jest/console/node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/primitive": "1.1.3",
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-id": "1.1.1",
- "@radix-ui/react-presence": "1.1.5",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-use-controllable-state": "1.2.2",
- "@radix-ui/react-use-layout-effect": "1.1.1"
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
},
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/console/node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/@radix-ui/react-collection": {
- "version": "1.1.7",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz",
- "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==",
+ "node_modules/@jest/console/node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-slot": "1.2.3"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
- "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "node_modules/@jest/core": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz",
+ "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/react-compose-refs": "1.1.2"
+ "@jest/console": "^29.7.0",
+ "@jest/reporters": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.9",
+ "jest-changed-files": "^29.7.0",
+ "jest-config": "^29.7.0",
+ "jest-haste-map": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-resolve-dependencies": "^29.7.0",
+ "jest-runner": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "jest-watcher": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
},
"peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
},
"peerDependenciesMeta": {
- "@types/react": {
+ "node-notifier": {
"optional": true
}
}
},
- "node_modules/@radix-ui/react-compose-refs": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
- "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==",
+ "node_modules/@jest/core/node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+ "dev": true,
"license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "dependencies": {
+ "@sinclair/typebox": "^0.27.8"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@radix-ui/react-context": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
- "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
+ "node_modules/@jest/core/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "dev": true,
"license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@radix-ui/react-dialog": {
- "version": "1.1.15",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz",
- "integrity": "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==",
+ "node_modules/@jest/core/node_modules/@sinclair/typebox": {
+ "version": "0.27.10",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
+ "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jest/core/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
"license": "MIT",
- "dependencies": {
- "@radix-ui/primitive": "1.1.3",
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-dismissable-layer": "1.1.11",
- "@radix-ui/react-focus-guards": "1.1.3",
- "@radix-ui/react-focus-scope": "1.1.7",
- "@radix-ui/react-id": "1.1.1",
- "@radix-ui/react-portal": "1.1.9",
- "@radix-ui/react-presence": "1.1.5",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-slot": "1.2.3",
- "@radix-ui/react-use-controllable-state": "1.2.2",
- "aria-hidden": "^1.2.4",
- "react-remove-scroll": "^2.6.3"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@jest/core/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@jest/core/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
}
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
}
},
- "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
- "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "node_modules/@jest/core/node_modules/jest-message-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz",
+ "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/react-compose-refs": "1.1.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "@babel/code-frame": "^7.12.13",
+ "@jest/types": "^29.6.3",
+ "@types/stack-utils": "^2.0.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@radix-ui/react-direction": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz",
- "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==",
+ "node_modules/@jest/core/node_modules/jest-regex-util": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz",
+ "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==",
+ "dev": true,
"license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@radix-ui/react-dismissable-layer": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz",
- "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==",
+ "node_modules/@jest/core/node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/primitive": "1.1.3",
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-use-callback-ref": "1.1.1",
- "@radix-ui/react-use-escape-keydown": "1.1.1"
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
},
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/core/node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/@radix-ui/react-dropdown-menu": {
- "version": "2.1.16",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.16.tgz",
- "integrity": "sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==",
+ "node_modules/@jest/core/node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/primitive": "1.1.3",
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-id": "1.1.1",
- "@radix-ui/react-menu": "2.1.16",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-use-controllable-state": "1.2.2"
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
},
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@radix-ui/react-focus-guards": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz",
- "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==",
+ "node_modules/@jest/core/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
"license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
+ "engines": {
+ "node": ">=8"
}
},
- "node_modules/@radix-ui/react-focus-scope": {
- "version": "1.1.7",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz",
- "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==",
+ "node_modules/@jest/diff-sequences": {
+ "version": "30.0.1",
+ "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz",
+ "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ }
+ },
+ "node_modules/@jest/environment": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz",
+ "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-use-callback-ref": "1.1.1"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-mock": "^29.7.0"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@radix-ui/react-id": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz",
- "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==",
+ "node_modules/@jest/environment-jsdom-abstract": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/@jest/environment-jsdom-abstract/-/environment-jsdom-abstract-30.3.0.tgz",
+ "integrity": "sha512-0hNFs5N6We3DMCwobzI0ydhkY10sT1tZSC0AAiy+0g2Dt/qEWgrcV5BrMxPczhe41cxW4qm6X+jqZaUdpZIajA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/react-use-layout-effect": "1.1.1"
+ "@jest/environment": "30.3.0",
+ "@jest/fake-timers": "30.3.0",
+ "@jest/types": "30.3.0",
+ "@types/jsdom": "^21.1.7",
+ "@types/node": "*",
+ "jest-mock": "30.3.0",
+ "jest-util": "30.3.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
},
"peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "canvas": "^3.0.0",
+ "jsdom": "*"
},
"peerDependenciesMeta": {
- "@types/react": {
+ "canvas": {
"optional": true
}
}
},
- "node_modules/@radix-ui/react-menu": {
- "version": "2.1.16",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.16.tgz",
- "integrity": "sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==",
+ "node_modules/@jest/environment-jsdom-abstract/node_modules/@jest/environment": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.3.0.tgz",
+ "integrity": "sha512-SlLSF4Be735yQXyh2+mctBOzNDx5s5uLv88/j8Qn1wH679PDcwy67+YdADn8NJnGjzlXtN62asGH/T4vWOkfaw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/primitive": "1.1.3",
- "@radix-ui/react-collection": "1.1.7",
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-direction": "1.1.1",
- "@radix-ui/react-dismissable-layer": "1.1.11",
- "@radix-ui/react-focus-guards": "1.1.3",
- "@radix-ui/react-focus-scope": "1.1.7",
- "@radix-ui/react-id": "1.1.1",
- "@radix-ui/react-popper": "1.2.8",
- "@radix-ui/react-portal": "1.1.9",
- "@radix-ui/react-presence": "1.1.5",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-roving-focus": "1.1.11",
- "@radix-ui/react-slot": "1.2.3",
- "@radix-ui/react-use-callback-ref": "1.1.1",
- "aria-hidden": "^1.2.4",
- "react-remove-scroll": "^2.6.3"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "@jest/fake-timers": "30.3.0",
+ "@jest/types": "30.3.0",
+ "@types/node": "*",
+ "jest-mock": "30.3.0"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-slot": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
- "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "node_modules/@jest/environment-jsdom-abstract/node_modules/@jest/fake-timers": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.3.0.tgz",
+ "integrity": "sha512-WUQDs8SOP9URStX1DzhD425CqbN/HxUYCTwVrT8sTVBfMvFqYt/s61EK5T05qnHu0po6RitXIvP9otZxYDzTGQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/react-compose-refs": "1.1.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "@jest/types": "30.3.0",
+ "@sinonjs/fake-timers": "^15.0.0",
+ "@types/node": "*",
+ "jest-message-util": "30.3.0",
+ "jest-mock": "30.3.0",
+ "jest-util": "30.3.0"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/@radix-ui/react-popper": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz",
- "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==",
+ "node_modules/@jest/environment-jsdom-abstract/node_modules/@jest/types": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.3.0.tgz",
+ "integrity": "sha512-JHm87k7bA33hpBngtU8h6UBub/fqqA9uXfw+21j5Hmk7ooPHlboRNxHq0JcMtC+n8VJGP1mcfnD3Mk+XKe1oSw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@floating-ui/react-dom": "^2.0.0",
- "@radix-ui/react-arrow": "1.1.7",
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-use-callback-ref": "1.1.1",
- "@radix-ui/react-use-layout-effect": "1.1.1",
- "@radix-ui/react-use-rect": "1.1.1",
- "@radix-ui/react-use-size": "1.1.1",
- "@radix-ui/rect": "1.1.1"
+ "@jest/pattern": "30.0.1",
+ "@jest/schemas": "30.0.5",
+ "@types/istanbul-lib-coverage": "^2.0.6",
+ "@types/istanbul-reports": "^3.0.4",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.33",
+ "chalk": "^4.1.2"
},
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ }
+ },
+ "node_modules/@jest/environment-jsdom-abstract/node_modules/@sinonjs/fake-timers": {
+ "version": "15.1.1",
+ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-15.1.1.tgz",
+ "integrity": "sha512-cO5W33JgAPbOh07tvZjUOJ7oWhtaqGHiZw+11DPbyqh2kHTBc3eF/CjJDeQ4205RLQsX6rxCuYOroFQwl7JDRw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@sinonjs/commons": "^3.0.1"
+ }
+ },
+ "node_modules/@jest/environment-jsdom-abstract/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/@radix-ui/react-portal": {
- "version": "1.1.9",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz",
- "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==",
+ "node_modules/@jest/environment-jsdom-abstract/node_modules/jest-message-util": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.3.0.tgz",
+ "integrity": "sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-use-layout-effect": "1.1.1"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "@babel/code-frame": "^7.27.1",
+ "@jest/types": "30.3.0",
+ "@types/stack-utils": "^2.0.3",
+ "chalk": "^4.1.2",
+ "graceful-fs": "^4.2.11",
+ "picomatch": "^4.0.3",
+ "pretty-format": "30.3.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.6"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/@radix-ui/react-presence": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz",
- "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==",
+ "node_modules/@jest/environment-jsdom-abstract/node_modules/jest-mock": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.3.0.tgz",
+ "integrity": "sha512-OTzICK8CpE+t4ndhKrwlIdbM6Pn8j00lvmSmq5ejiO+KxukbLjgOflKWMn3KE34EZdQm5RqTuKj+5RIEniYhog==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-use-layout-effect": "1.1.1"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "@jest/types": "30.3.0",
+ "@types/node": "*",
+ "jest-util": "30.3.0"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/@radix-ui/react-primitive": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
- "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
+ "node_modules/@jest/environment-jsdom-abstract/node_modules/jest-util": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz",
+ "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/react-slot": "1.2.3"
+ "@jest/types": "30.3.0",
+ "@types/node": "*",
+ "chalk": "^4.1.2",
+ "ci-info": "^4.2.0",
+ "graceful-fs": "^4.2.11",
+ "picomatch": "^4.0.3"
},
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ }
+ },
+ "node_modules/@jest/environment-jsdom-abstract/node_modules/pretty-format": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz",
+ "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "30.0.5",
+ "ansi-styles": "^5.2.0",
+ "react-is": "^18.3.1"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
- "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "node_modules/@jest/environment/node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/react-compose-refs": "1.1.2"
+ "@sinclair/typebox": "^0.27.8"
},
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/environment/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/environment/node_modules/@sinclair/typebox": {
+ "version": "0.27.10",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
+ "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jest/environment/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
}
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
}
},
- "node_modules/@radix-ui/react-roving-focus": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz",
- "integrity": "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==",
+ "node_modules/@jest/environment/node_modules/jest-mock": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz",
+ "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/primitive": "1.1.3",
- "@radix-ui/react-collection": "1.1.7",
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-direction": "1.1.1",
- "@radix-ui/react-id": "1.1.1",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-use-callback-ref": "1.1.1",
- "@radix-ui/react-use-controllable-state": "1.2.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-util": "^29.7.0"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@radix-ui/react-select": {
- "version": "2.2.6",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.6.tgz",
- "integrity": "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==",
+ "node_modules/@jest/environment/node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/number": "1.1.1",
- "@radix-ui/primitive": "1.1.3",
- "@radix-ui/react-collection": "1.1.7",
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-direction": "1.1.1",
- "@radix-ui/react-dismissable-layer": "1.1.11",
- "@radix-ui/react-focus-guards": "1.1.3",
- "@radix-ui/react-focus-scope": "1.1.7",
- "@radix-ui/react-id": "1.1.1",
- "@radix-ui/react-popper": "1.2.8",
- "@radix-ui/react-portal": "1.1.9",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-slot": "1.2.3",
- "@radix-ui/react-use-callback-ref": "1.1.1",
- "@radix-ui/react-use-controllable-state": "1.2.2",
- "@radix-ui/react-use-layout-effect": "1.1.1",
- "@radix-ui/react-use-previous": "1.1.1",
- "@radix-ui/react-visually-hidden": "1.2.3",
- "aria-hidden": "^1.2.4",
- "react-remove-scroll": "^2.6.3"
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
},
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/environment/node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-slot": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
- "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "node_modules/@jest/expect": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz",
+ "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/react-compose-refs": "1.1.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "expect": "^29.7.0",
+ "jest-snapshot": "^29.7.0"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@radix-ui/react-separator": {
- "version": "1.1.8",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.8.tgz",
- "integrity": "sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g==",
+ "node_modules/@jest/expect-utils": {
+ "version": "30.2.0",
+ "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.2.0.tgz",
+ "integrity": "sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/react-primitive": "2.1.4"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "@jest/get-type": "30.1.0"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-primitive": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz",
- "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==",
+ "node_modules/@jest/expect/node_modules/@jest/expect-utils": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz",
+ "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/react-slot": "1.2.4"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "jest-get-type": "^29.6.3"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@radix-ui/react-slider": {
- "version": "1.3.6",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.3.6.tgz",
- "integrity": "sha512-JPYb1GuM1bxfjMRlNLE+BcmBC8onfCi60Blk7OBqi2MLTFdS+8401U4uFjnwkOr49BLmXxLC6JHkvAsx5OJvHw==",
+ "node_modules/@jest/expect/node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/number": "1.1.1",
- "@radix-ui/primitive": "1.1.3",
- "@radix-ui/react-collection": "1.1.7",
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-direction": "1.1.1",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-use-controllable-state": "1.2.2",
- "@radix-ui/react-use-layout-effect": "1.1.1",
- "@radix-ui/react-use-previous": "1.1.1",
- "@radix-ui/react-use-size": "1.1.1"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "@sinclair/typebox": "^0.27.8"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@radix-ui/react-slot": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz",
- "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==",
+ "node_modules/@jest/expect/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/react-compose-refs": "1.1.2"
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
},
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/expect/node_modules/@sinclair/typebox": {
+ "version": "0.27.10",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
+ "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jest/expect/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@jest/expect/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
}
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
}
},
- "node_modules/@radix-ui/react-switch": {
- "version": "1.2.6",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.2.6.tgz",
- "integrity": "sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==",
+ "node_modules/@jest/expect/node_modules/expect": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz",
+ "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/primitive": "1.1.3",
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-use-controllable-state": "1.2.2",
- "@radix-ui/react-use-previous": "1.1.1",
- "@radix-ui/react-use-size": "1.1.1"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "@jest/expect-utils": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@radix-ui/react-tooltip": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.8.tgz",
- "integrity": "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==",
+ "node_modules/@jest/expect/node_modules/jest-diff": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz",
+ "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/primitive": "1.1.3",
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-dismissable-layer": "1.1.11",
- "@radix-ui/react-id": "1.1.1",
- "@radix-ui/react-popper": "1.2.8",
- "@radix-ui/react-portal": "1.1.9",
- "@radix-ui/react-presence": "1.1.5",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-slot": "1.2.3",
- "@radix-ui/react-use-controllable-state": "1.2.2",
- "@radix-ui/react-visually-hidden": "1.2.3"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "chalk": "^4.0.0",
+ "diff-sequences": "^29.6.3",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-slot": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
- "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "node_modules/@jest/expect/node_modules/jest-matcher-utils": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz",
+ "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/react-compose-refs": "1.1.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "chalk": "^4.0.0",
+ "jest-diff": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@radix-ui/react-use-callback-ref": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
- "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==",
+ "node_modules/@jest/expect/node_modules/jest-message-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz",
+ "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==",
+ "dev": true,
"license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "dependencies": {
+ "@babel/code-frame": "^7.12.13",
+ "@jest/types": "^29.6.3",
+ "@types/stack-utils": "^2.0.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@radix-ui/react-use-controllable-state": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz",
- "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==",
+ "node_modules/@jest/expect/node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/react-use-effect-event": "0.0.2",
- "@radix-ui/react-use-layout-effect": "1.1.1"
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
},
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/expect/node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/@radix-ui/react-use-effect-event": {
- "version": "0.0.2",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz",
- "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==",
+ "node_modules/@jest/expect/node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/react-use-layout-effect": "1.1.1"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@radix-ui/react-use-escape-keydown": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz",
- "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==",
+ "node_modules/@jest/fake-timers": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz",
+ "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/react-use-callback-ref": "1.1.1"
+ "@jest/types": "^29.6.3",
+ "@sinonjs/fake-timers": "^10.0.2",
+ "@types/node": "*",
+ "jest-message-util": "^29.7.0",
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0"
},
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/fake-timers/node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@sinclair/typebox": "^0.27.8"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@radix-ui/react-use-layout-effect": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
- "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
+ "node_modules/@jest/fake-timers/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "dev": true,
"license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@radix-ui/react-use-previous": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz",
- "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==",
+ "node_modules/@jest/fake-timers/node_modules/@sinclair/typebox": {
+ "version": "0.27.10",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
+ "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jest/fake-timers/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
"license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "engines": {
+ "node": ">=10"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@jest/fake-timers/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
}
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
}
},
- "node_modules/@radix-ui/react-use-rect": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz",
- "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==",
+ "node_modules/@jest/fake-timers/node_modules/jest-message-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz",
+ "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/rect": "1.1.1"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "@babel/code-frame": "^7.12.13",
+ "@jest/types": "^29.6.3",
+ "@types/stack-utils": "^2.0.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@radix-ui/react-use-size": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz",
- "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==",
+ "node_modules/@jest/fake-timers/node_modules/jest-mock": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz",
+ "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/react-use-layout-effect": "1.1.1"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-util": "^29.7.0"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@radix-ui/react-visually-hidden": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz",
- "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==",
+ "node_modules/@jest/fake-timers/node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@radix-ui/react-primitive": "2.1.3"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
},
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@radix-ui/rect": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz",
- "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==",
- "license": "MIT"
+ "node_modules/@jest/fake-timers/node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
},
- "node_modules/@reactour/mask": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@reactour/mask/-/mask-1.2.0.tgz",
- "integrity": "sha512-XLgBLWfKJybtZjNTSO5lt/SIvRlCZBadB6JfE/hO1ErqURRjYhnv+edC0Ki1haUCqMGFppWk3lwcPCjmK0xNog==",
+ "node_modules/@jest/fake-timers/node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@reactour/utils": "*"
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
},
- "peerDependencies": {
- "react": "16.x || 17.x || 18.x || 19.x"
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@reactour/popover": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/@reactour/popover/-/popover-1.3.0.tgz",
- "integrity": "sha512-YdyjSmHPvEeQEcJM4gcGFa5pI/Yf4nZGqwG4JnT+rK1SyUJBIPnm4Gkl/h7/+1g0KCFMkwNwagS3ZiXvZB7ThA==",
+ "node_modules/@jest/get-type": {
+ "version": "30.1.0",
+ "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.1.0.tgz",
+ "integrity": "sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ }
+ },
+ "node_modules/@jest/globals": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz",
+ "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@reactour/utils": "*"
+ "@jest/environment": "^29.7.0",
+ "@jest/expect": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "jest-mock": "^29.7.0"
},
- "peerDependencies": {
- "react": "16.x || 17.x || 18.x || 19.x"
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@reactour/tour": {
- "version": "3.8.0",
- "resolved": "https://registry.npmjs.org/@reactour/tour/-/tour-3.8.0.tgz",
- "integrity": "sha512-KZTFi1pAvoTVKKRdBN5+XCYxXBp4k4Ql/acZcXyPvec8VU24fkMSEeV+v8krfYQpoVcewxIu3gM6xWZZLjxi7w==",
+ "node_modules/@jest/globals/node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@reactour/mask": "*",
- "@reactour/popover": "*",
- "@reactour/utils": "*"
+ "@sinclair/typebox": "^0.27.8"
},
- "peerDependencies": {
- "react": "16.x || 17.x || 18.x || 19.x"
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@reactour/utils": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/@reactour/utils/-/utils-0.6.0.tgz",
- "integrity": "sha512-GqaLjQi7MJsgtAKjdiw2Eak1toFkADoLRnm1+HZpaD+yl+DkaHpC1N7JAl+kVOO5I17bWInPA+OFbXjO9Co8Qg==",
+ "node_modules/@jest/globals/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@rooks/use-mutation-observer": "^4.11.2",
- "resize-observer-polyfill": "^1.5.1"
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
},
- "peerDependencies": {
- "react": "16.x || 17.x || 18.x || 19.x"
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@rolldown/pluginutils": {
- "version": "1.0.0-rc.3",
- "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz",
- "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==",
+ "node_modules/@jest/globals/node_modules/@sinclair/typebox": {
+ "version": "0.27.10",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
+ "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
"dev": true,
"license": "MIT"
},
- "node_modules/@rollup/plugin-node-resolve": {
- "version": "15.3.1",
- "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.1.tgz",
- "integrity": "sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==",
+ "node_modules/@jest/globals/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
"dev": true,
- "license": "MIT",
- "dependencies": {
- "@rollup/pluginutils": "^5.0.1",
- "@types/resolve": "1.20.2",
- "deepmerge": "^4.2.2",
- "is-module": "^1.0.0",
- "resolve": "^1.22.1"
- },
- "engines": {
- "node": ">=14.0.0"
- },
- "peerDependencies": {
- "rollup": "^2.78.0||^3.0.0||^4.0.0"
- },
- "peerDependenciesMeta": {
- "rollup": {
- "optional": true
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
}
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
}
},
- "node_modules/@rollup/plugin-node-resolve/node_modules/resolve": {
- "version": "1.22.11",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz",
- "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==",
+ "node_modules/@jest/globals/node_modules/jest-mock": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz",
+ "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "is-core-module": "^2.16.1",
- "path-parse": "^1.0.7",
- "supports-preserve-symlinks-flag": "^1.0.0"
- },
- "bin": {
- "resolve": "bin/resolve"
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-util": "^29.7.0"
},
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@rollup/plugin-terser": {
- "version": "0.4.4",
- "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz",
- "integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==",
+ "node_modules/@jest/globals/node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "serialize-javascript": "^6.0.1",
- "smob": "^1.0.0",
- "terser": "^5.17.4"
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
},
"engines": {
- "node": ">=14.0.0"
- },
- "peerDependencies": {
- "rollup": "^2.0.0||^3.0.0||^4.0.0"
- },
- "peerDependenciesMeta": {
- "rollup": {
- "optional": true
- }
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@rollup/plugin-virtual": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/@rollup/plugin-virtual/-/plugin-virtual-3.0.2.tgz",
- "integrity": "sha512-10monEYsBp3scM4/ND4LNH5Rxvh3e/cVeL3jWTgZ2SrQ+BmUoQcopVQvnaMcOnykb1VkxUFuDAN+0FnpTFRy2A==",
+ "node_modules/@jest/globals/node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=14.0.0"
+ "node": ">=8.6"
},
- "peerDependencies": {
- "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/@jest/pattern": {
+ "version": "30.0.1",
+ "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.1.tgz",
+ "integrity": "sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "jest-regex-util": "30.0.1"
},
- "peerDependenciesMeta": {
- "rollup": {
- "optional": true
- }
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/@rollup/pluginutils": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz",
- "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==",
+ "node_modules/@jest/reporters": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz",
+ "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@types/estree": "^1.0.0",
- "estree-walker": "^2.0.2",
- "picomatch": "^4.0.2"
+ "@bcoe/v8-coverage": "^0.2.3",
+ "@jest/console": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "collect-v8-coverage": "^1.0.0",
+ "exit": "^0.1.2",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "istanbul-lib-coverage": "^3.0.0",
+ "istanbul-lib-instrument": "^6.0.0",
+ "istanbul-lib-report": "^3.0.0",
+ "istanbul-lib-source-maps": "^4.0.0",
+ "istanbul-reports": "^3.1.3",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "slash": "^3.0.0",
+ "string-length": "^4.0.1",
+ "strip-ansi": "^6.0.0",
+ "v8-to-istanbul": "^9.0.1"
},
"engines": {
- "node": ">=14.0.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
},
"peerDependencies": {
- "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
},
"peerDependenciesMeta": {
- "rollup": {
+ "node-notifier": {
"optional": true
}
}
},
- "node_modules/@rollup/rollup-android-arm-eabi": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz",
- "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==",
- "cpu": [
- "arm"
- ],
+ "node_modules/@jest/reporters/node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+ "dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "android"
- ]
+ "dependencies": {
+ "@sinclair/typebox": "^0.27.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
},
- "node_modules/@rollup/rollup-android-arm64": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz",
- "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==",
- "cpu": [
- "arm64"
- ],
+ "node_modules/@jest/reporters/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "android"
- ]
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
},
- "node_modules/@rollup/rollup-darwin-arm64": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz",
- "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ]
+ "node_modules/@jest/reporters/node_modules/@sinclair/typebox": {
+ "version": "0.27.10",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
+ "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
+ "dev": true,
+ "license": "MIT"
},
- "node_modules/@rollup/rollup-darwin-x64": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz",
- "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==",
- "cpu": [
- "x64"
- ],
+ "node_modules/@jest/reporters/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ]
+ "engines": {
+ "node": ">=8"
+ }
},
- "node_modules/@rollup/rollup-freebsd-arm64": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz",
- "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==",
- "cpu": [
- "arm64"
- ],
+ "node_modules/@jest/reporters/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ]
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
},
- "node_modules/@rollup/rollup-freebsd-x64": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz",
- "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==",
- "cpu": [
- "x64"
- ],
+ "node_modules/@jest/reporters/node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ]
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
},
- "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz",
- "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==",
- "cpu": [
- "arm"
+ "node_modules/@jest/reporters/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
],
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "engines": {
+ "node": ">=8"
+ }
},
- "node_modules/@rollup/rollup-linux-arm-musleabihf": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz",
- "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "node_modules/@jest/reporters/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
},
- "node_modules/@rollup/rollup-linux-arm64-gnu": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz",
- "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==",
- "cpu": [
- "arm64"
- ],
+ "node_modules/@jest/reporters/node_modules/jest-message-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz",
+ "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==",
+ "dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "dependencies": {
+ "@babel/code-frame": "^7.12.13",
+ "@jest/types": "^29.6.3",
+ "@types/stack-utils": "^2.0.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
},
- "node_modules/@rollup/rollup-linux-arm64-musl": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz",
- "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==",
- "cpu": [
- "arm64"
- ],
+ "node_modules/@jest/reporters/node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
+ "dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
},
- "node_modules/@rollup/rollup-linux-loong64-gnu": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz",
- "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==",
- "cpu": [
- "loong64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "node_modules/@jest/reporters/node_modules/minimatch": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
},
- "node_modules/@rollup/rollup-linux-loong64-musl": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz",
- "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==",
- "cpu": [
- "loong64"
- ],
+ "node_modules/@jest/reporters/node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
},
- "node_modules/@rollup/rollup-linux-ppc64-gnu": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz",
- "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==",
- "cpu": [
- "ppc64"
- ],
+ "node_modules/@jest/reporters/node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
},
- "node_modules/@rollup/rollup-linux-ppc64-musl": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz",
- "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==",
- "cpu": [
- "ppc64"
- ],
+ "node_modules/@jest/reporters/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
},
- "node_modules/@rollup/rollup-linux-riscv64-gnu": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz",
- "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==",
- "cpu": [
- "riscv64"
- ],
+ "node_modules/@jest/schemas": {
+ "version": "30.0.5",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz",
+ "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==",
+ "dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "dependencies": {
+ "@sinclair/typebox": "^0.34.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ }
},
- "node_modules/@rollup/rollup-linux-riscv64-musl": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz",
- "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==",
- "cpu": [
- "riscv64"
- ],
+ "node_modules/@jest/source-map": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz",
+ "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==",
+ "dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "callsites": "^3.0.0",
+ "graceful-fs": "^4.2.9"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
},
- "node_modules/@rollup/rollup-linux-s390x-gnu": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz",
- "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==",
- "cpu": [
- "s390x"
- ],
+ "node_modules/@jest/test-result": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz",
+ "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==",
+ "dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "dependencies": {
+ "@jest/console": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "collect-v8-coverage": "^1.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
},
- "node_modules/@rollup/rollup-linux-x64-gnu": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz",
- "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==",
- "cpu": [
- "x64"
- ],
+ "node_modules/@jest/test-result/node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+ "dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "dependencies": {
+ "@sinclair/typebox": "^0.27.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
},
- "node_modules/@rollup/rollup-linux-x64-musl": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz",
- "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==",
- "cpu": [
- "x64"
- ],
+ "node_modules/@jest/test-result/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
},
- "node_modules/@rollup/rollup-openbsd-x64": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz",
- "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==",
- "cpu": [
- "x64"
- ],
+ "node_modules/@jest/test-result/node_modules/@sinclair/typebox": {
+ "version": "0.27.10",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
+ "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jest/test-sequencer": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz",
+ "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==",
+ "dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ]
+ "dependencies": {
+ "@jest/test-result": "^29.7.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
},
- "node_modules/@rollup/rollup-openharmony-arm64": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz",
- "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==",
- "cpu": [
- "arm64"
- ],
+ "node_modules/@jest/transform": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz",
+ "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==",
+ "dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "openharmony"
- ]
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@jest/types": "^29.6.3",
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "babel-plugin-istanbul": "^6.1.1",
+ "chalk": "^4.0.0",
+ "convert-source-map": "^2.0.0",
+ "fast-json-stable-stringify": "^2.1.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "pirates": "^4.0.4",
+ "slash": "^3.0.0",
+ "write-file-atomic": "^4.0.2"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
},
- "node_modules/@rollup/rollup-win32-arm64-msvc": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz",
- "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==",
- "cpu": [
- "arm64"
- ],
+ "node_modules/@jest/transform/node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+ "dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
+ "dependencies": {
+ "@sinclair/typebox": "^0.27.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
},
- "node_modules/@rollup/rollup-win32-ia32-msvc": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz",
- "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==",
- "cpu": [
- "ia32"
- ],
+ "node_modules/@jest/transform/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
},
- "node_modules/@rollup/rollup-win32-x64-gnu": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz",
- "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==",
- "cpu": [
- "x64"
+ "node_modules/@jest/transform/node_modules/@sinclair/typebox": {
+ "version": "0.27.10",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
+ "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jest/transform/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
],
"license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@jest/transform/node_modules/jest-regex-util": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz",
+ "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/transform/node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/transform/node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/@jest/types": {
+ "version": "30.2.0",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.2.0.tgz",
+ "integrity": "sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/pattern": "30.0.1",
+ "@jest/schemas": "30.0.5",
+ "@types/istanbul-lib-coverage": "^2.0.6",
+ "@types/istanbul-reports": "^3.0.4",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.33",
+ "chalk": "^4.1.2"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.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",
+ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/remapping": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
+ "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/source-map": {
+ "version": "0.3.11",
+ "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz",
+ "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.25"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.31",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@nisoku/satori-log": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/@nisoku/satori-log/-/satori-log-0.1.2.tgz",
+ "integrity": "sha512-VlhKOByqy0DnG6b1EVuTAYJFHtBf7brwFD++3So07RTc5AyH43djtDLr0XuaD/NFiy2nCF+QQCbRo4JrMimqpg==",
+ "license": "MIT"
+ },
+ "node_modules/@quansync/fs": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/@quansync/fs/-/fs-0.1.5.tgz",
+ "integrity": "sha512-lNS9hL2aS2NZgNW7BBj+6EBl4rOf8l+tQ0eRY6JWCI8jI2kc53gSoqbjojU0OnAWhzoXiOjFyGsHcDGePB3lhA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "quansync": "^0.2.11"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sxzz"
+ }
+ },
+ "node_modules/@radix-ui/number": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz",
+ "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==",
+ "license": "MIT"
+ },
+ "node_modules/@radix-ui/primitive": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz",
+ "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==",
+ "license": "MIT"
+ },
+ "node_modules/@radix-ui/react-arrow": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz",
+ "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.1.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-collapsible": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.12.tgz",
+ "integrity": "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-collection": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz",
+ "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-slot": "1.2.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-compose-refs": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
+ "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-context": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
+ "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-dialog": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz",
+ "integrity": "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-dismissable-layer": "1.1.11",
+ "@radix-ui/react-focus-guards": "1.1.3",
+ "@radix-ui/react-focus-scope": "1.1.7",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-portal": "1.1.9",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-slot": "1.2.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "aria-hidden": "^1.2.4",
+ "react-remove-scroll": "^2.6.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-direction": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz",
+ "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-dismissable-layer": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz",
+ "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-escape-keydown": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-dropdown-menu": {
+ "version": "2.1.16",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.16.tgz",
+ "integrity": "sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-menu": "2.1.16",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-focus-guards": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz",
+ "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-focus-scope": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz",
+ "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-id": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz",
+ "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu": {
+ "version": "2.1.16",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.16.tgz",
+ "integrity": "sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-dismissable-layer": "1.1.11",
+ "@radix-ui/react-focus-guards": "1.1.3",
+ "@radix-ui/react-focus-scope": "1.1.7",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-popper": "1.2.8",
+ "@radix-ui/react-portal": "1.1.9",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-roving-focus": "1.1.11",
+ "@radix-ui/react-slot": "1.2.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "aria-hidden": "^1.2.4",
+ "react-remove-scroll": "^2.6.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-slot": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-popper": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz",
+ "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/react-dom": "^2.0.0",
+ "@radix-ui/react-arrow": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-layout-effect": "1.1.1",
+ "@radix-ui/react-use-rect": "1.1.1",
+ "@radix-ui/react-use-size": "1.1.1",
+ "@radix-ui/rect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-portal": {
+ "version": "1.1.9",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz",
+ "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-presence": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz",
+ "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-primitive": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
+ "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-slot": "1.2.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-roving-focus": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz",
+ "integrity": "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-select": {
+ "version": "2.2.6",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.6.tgz",
+ "integrity": "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/number": "1.1.1",
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-dismissable-layer": "1.1.11",
+ "@radix-ui/react-focus-guards": "1.1.3",
+ "@radix-ui/react-focus-scope": "1.1.7",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-popper": "1.2.8",
+ "@radix-ui/react-portal": "1.1.9",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-slot": "1.2.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1",
+ "@radix-ui/react-use-previous": "1.1.1",
+ "@radix-ui/react-visually-hidden": "1.2.3",
+ "aria-hidden": "^1.2.4",
+ "react-remove-scroll": "^2.6.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-slot": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-separator": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.8.tgz",
+ "integrity": "sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.1.4"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-primitive": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz",
+ "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-slot": "1.2.4"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-slider": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.3.6.tgz",
+ "integrity": "sha512-JPYb1GuM1bxfjMRlNLE+BcmBC8onfCi60Blk7OBqi2MLTFdS+8401U4uFjnwkOr49BLmXxLC6JHkvAsx5OJvHw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/number": "1.1.1",
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1",
+ "@radix-ui/react-use-previous": "1.1.1",
+ "@radix-ui/react-use-size": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-slot": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz",
+ "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-switch": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.2.6.tgz",
+ "integrity": "sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-use-previous": "1.1.1",
+ "@radix-ui/react-use-size": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-tooltip": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.8.tgz",
+ "integrity": "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-dismissable-layer": "1.1.11",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-popper": "1.2.8",
+ "@radix-ui/react-portal": "1.1.9",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-slot": "1.2.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-visually-hidden": "1.2.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-slot": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-callback-ref": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
+ "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-controllable-state": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz",
+ "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-effect-event": "0.0.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-effect-event": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz",
+ "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-escape-keydown": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz",
+ "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-callback-ref": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-layout-effect": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
+ "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-previous": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz",
+ "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-rect": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz",
+ "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/rect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-size": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz",
+ "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-visually-hidden": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz",
+ "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.1.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/rect": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz",
+ "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==",
+ "license": "MIT"
+ },
+ "node_modules/@reactour/mask": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@reactour/mask/-/mask-1.2.0.tgz",
+ "integrity": "sha512-XLgBLWfKJybtZjNTSO5lt/SIvRlCZBadB6JfE/hO1ErqURRjYhnv+edC0Ki1haUCqMGFppWk3lwcPCjmK0xNog==",
+ "dependencies": {
+ "@reactour/utils": "*"
+ },
+ "peerDependencies": {
+ "react": "16.x || 17.x || 18.x || 19.x"
+ }
+ },
+ "node_modules/@reactour/popover": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@reactour/popover/-/popover-1.3.0.tgz",
+ "integrity": "sha512-YdyjSmHPvEeQEcJM4gcGFa5pI/Yf4nZGqwG4JnT+rK1SyUJBIPnm4Gkl/h7/+1g0KCFMkwNwagS3ZiXvZB7ThA==",
+ "dependencies": {
+ "@reactour/utils": "*"
+ },
+ "peerDependencies": {
+ "react": "16.x || 17.x || 18.x || 19.x"
+ }
+ },
+ "node_modules/@reactour/tour": {
+ "version": "3.8.0",
+ "resolved": "https://registry.npmjs.org/@reactour/tour/-/tour-3.8.0.tgz",
+ "integrity": "sha512-KZTFi1pAvoTVKKRdBN5+XCYxXBp4k4Ql/acZcXyPvec8VU24fkMSEeV+v8krfYQpoVcewxIu3gM6xWZZLjxi7w==",
+ "dependencies": {
+ "@reactour/mask": "*",
+ "@reactour/popover": "*",
+ "@reactour/utils": "*"
+ },
+ "peerDependencies": {
+ "react": "16.x || 17.x || 18.x || 19.x"
+ }
+ },
+ "node_modules/@reactour/utils": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/@reactour/utils/-/utils-0.6.0.tgz",
+ "integrity": "sha512-GqaLjQi7MJsgtAKjdiw2Eak1toFkADoLRnm1+HZpaD+yl+DkaHpC1N7JAl+kVOO5I17bWInPA+OFbXjO9Co8Qg==",
+ "dependencies": {
+ "@rooks/use-mutation-observer": "^4.11.2",
+ "resize-observer-polyfill": "^1.5.1"
+ },
+ "peerDependencies": {
+ "react": "16.x || 17.x || 18.x || 19.x"
+ }
+ },
+ "node_modules/@rolldown/pluginutils": {
+ "version": "1.0.0-rc.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz",
+ "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@rollup/plugin-node-resolve": {
+ "version": "15.3.1",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.1.tgz",
+ "integrity": "sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@rollup/pluginutils": "^5.0.1",
+ "@types/resolve": "1.20.2",
+ "deepmerge": "^4.2.2",
+ "is-module": "^1.0.0",
+ "resolve": "^1.22.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "rollup": "^2.78.0||^3.0.0||^4.0.0"
+ },
+ "peerDependenciesMeta": {
+ "rollup": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@rollup/plugin-node-resolve/node_modules/resolve": {
+ "version": "1.22.11",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz",
+ "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-core-module": "^2.16.1",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/@rollup/plugin-terser": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz",
+ "integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "serialize-javascript": "^6.0.1",
+ "smob": "^1.0.0",
+ "terser": "^5.17.4"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "rollup": "^2.0.0||^3.0.0||^4.0.0"
+ },
+ "peerDependenciesMeta": {
+ "rollup": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@rollup/plugin-virtual": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-virtual/-/plugin-virtual-3.0.2.tgz",
+ "integrity": "sha512-10monEYsBp3scM4/ND4LNH5Rxvh3e/cVeL3jWTgZ2SrQ+BmUoQcopVQvnaMcOnykb1VkxUFuDAN+0FnpTFRy2A==",
+ "dev": true,
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
+ },
+ "peerDependenciesMeta": {
+ "rollup": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@rollup/pluginutils": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz",
+ "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "estree-walker": "^2.0.2",
+ "picomatch": "^4.0.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
+ },
+ "peerDependenciesMeta": {
+ "rollup": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz",
+ "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz",
+ "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz",
+ "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz",
+ "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-arm64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz",
+ "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-x64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz",
+ "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz",
+ "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz",
+ "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz",
+ "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz",
+ "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz",
+ "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==",
+ "cpu": [
+ "loong64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-musl": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz",
+ "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==",
+ "cpu": [
+ "loong64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz",
+ "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-musl": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz",
+ "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz",
+ "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz",
+ "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz",
+ "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz",
+ "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz",
+ "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-openbsd-x64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz",
+ "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-openharmony-arm64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz",
+ "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz",
+ "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz",
+ "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz",
+ "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz",
+ "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rooks/use-mutation-observer": {
+ "version": "4.11.2",
+ "resolved": "https://registry.npmjs.org/@rooks/use-mutation-observer/-/use-mutation-observer-4.11.2.tgz",
+ "integrity": "sha512-vpsdrZdr6TkB1zZJcHx+fR1YC/pHs2BaqcuYiEGjBVbwY5xcC49+h0hAUtQKHth3oJqXfIX/Ng8S7s5HFHdM/A==",
+ "peerDependencies": {
+ "react": ">=16.8.0"
+ }
+ },
+ "node_modules/@sinclair/typebox": {
+ "version": "0.34.41",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.41.tgz",
+ "integrity": "sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@sinonjs/commons": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
+ "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "type-detect": "4.0.8"
+ }
+ },
+ "node_modules/@sinonjs/fake-timers": {
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz",
+ "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@sinonjs/commons": "^3.0.0"
+ }
+ },
+ "node_modules/@surma/rollup-plugin-off-main-thread": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz",
+ "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "ejs": "^3.1.6",
+ "json5": "^2.2.0",
+ "magic-string": "^0.25.0",
+ "string.prototype.matchall": "^4.0.6"
+ }
+ },
+ "node_modules/@swc/core": {
+ "version": "1.15.8",
+ "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.15.8.tgz",
+ "integrity": "sha512-T8keoJjXaSUoVBCIjgL6wAnhADIb09GOELzKg10CjNg+vLX48P93SME6jTfte9MZIm5m+Il57H3rTSk/0kzDUw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "dependencies": {
+ "@swc/counter": "^0.1.3",
+ "@swc/types": "^0.1.25"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/swc"
+ },
+ "optionalDependencies": {
+ "@swc/core-darwin-arm64": "1.15.8",
+ "@swc/core-darwin-x64": "1.15.8",
+ "@swc/core-linux-arm-gnueabihf": "1.15.8",
+ "@swc/core-linux-arm64-gnu": "1.15.8",
+ "@swc/core-linux-arm64-musl": "1.15.8",
+ "@swc/core-linux-x64-gnu": "1.15.8",
+ "@swc/core-linux-x64-musl": "1.15.8",
+ "@swc/core-win32-arm64-msvc": "1.15.8",
+ "@swc/core-win32-ia32-msvc": "1.15.8",
+ "@swc/core-win32-x64-msvc": "1.15.8"
+ },
+ "peerDependencies": {
+ "@swc/helpers": ">=0.5.17"
+ },
+ "peerDependenciesMeta": {
+ "@swc/helpers": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@swc/core-darwin-arm64": {
+ "version": "1.15.8",
+ "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.8.tgz",
+ "integrity": "sha512-M9cK5GwyWWRkRGwwCbREuj6r8jKdES/haCZ3Xckgkl8MUQJZA3XB7IXXK1IXRNeLjg6m7cnoMICpXv1v1hlJOg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-darwin-x64": {
+ "version": "1.15.8",
+ "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.15.8.tgz",
+ "integrity": "sha512-j47DasuOvXl80sKJHSi2X25l44CMc3VDhlJwA7oewC1nV1VsSzwX+KOwE5tLnfORvVJJyeiXgJORNYg4jeIjYQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-arm-gnueabihf": {
+ "version": "1.15.8",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.15.8.tgz",
+ "integrity": "sha512-siAzDENu2rUbwr9+fayWa26r5A9fol1iORG53HWxQL1J8ym4k7xt9eME0dMPXlYZDytK5r9sW8zEA10F2U3Xwg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-arm64-gnu": {
+ "version": "1.15.8",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.15.8.tgz",
+ "integrity": "sha512-o+1y5u6k2FfPYbTRUPvurwzNt5qd0NTumCTFscCNuBksycloXY16J8L+SMW5QRX59n4Hp9EmFa3vpvNHRVv1+Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-arm64-musl": {
+ "version": "1.15.8",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.15.8.tgz",
+ "integrity": "sha512-koiCqL09EwOP1S2RShCI7NbsQuG6r2brTqUYE7pV7kZm9O17wZ0LSz22m6gVibpwEnw8jI3IE1yYsQTVpluALw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-x64-gnu": {
+ "version": "1.15.8",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.15.8.tgz",
+ "integrity": "sha512-4p6lOMU3bC+Vd5ARtKJ/FxpIC5G8v3XLoPEZ5s7mLR8h7411HWC/LmTXDHcrSXRC55zvAVia1eldy6zDLz8iFQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-x64-musl": {
+ "version": "1.15.8",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.15.8.tgz",
+ "integrity": "sha512-z3XBnbrZAL+6xDGAhJoN4lOueIxC/8rGrJ9tg+fEaeqLEuAtHSW2QHDHxDwkxZMjuF/pZ6MUTjHjbp8wLbuRLA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-win32-arm64-msvc": {
+ "version": "1.15.8",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.15.8.tgz",
+ "integrity": "sha512-djQPJ9Rh9vP8GTS/Df3hcc6XP6xnG5c8qsngWId/BLA9oX6C7UzCPAn74BG/wGb9a6j4w3RINuoaieJB3t+7iQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-win32-ia32-msvc": {
+ "version": "1.15.8",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.15.8.tgz",
+ "integrity": "sha512-/wfAgxORg2VBaUoFdytcVBVCgf1isWZIEXB9MZEUty4wwK93M/PxAkjifOho9RN3WrM3inPLabICRCEgdHpKKQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-win32-x64-msvc": {
+ "version": "1.15.8",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.15.8.tgz",
+ "integrity": "sha512-GpMePrh9Sl4d61o4KAHOOv5is5+zt6BEXCOCgs/H0FLGeii7j9bWDE8ExvKFy2GRRZVNR1ugsnzaGWHKM6kuzA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/counter": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
+ "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==",
+ "dev": true
+ },
+ "node_modules/@swc/types": {
+ "version": "0.1.25",
+ "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.25.tgz",
+ "integrity": "sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g==",
+ "dev": true,
+ "dependencies": {
+ "@swc/counter": "^0.1.3"
+ }
+ },
+ "node_modules/@swc/wasm": {
+ "version": "1.15.8",
+ "resolved": "https://registry.npmjs.org/@swc/wasm/-/wasm-1.15.8.tgz",
+ "integrity": "sha512-RG2BxGbbsjtddFCo1ghKH6A/BMXbY1eMBfpysV0lJMCpI4DZOjW1BNBnxvBt7YsYmlJtmy5UXIg9/4ekBTFFaQ==",
+ "dev": true
+ },
+ "node_modules/@tauri-apps/api": {
+ "version": "2.10.1",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.10.1.tgz",
+ "integrity": "sha512-hKL/jWf293UDSUN09rR69hrToyIXBb8CjGaWC7gfinvnQrBVvnLr08FeFi38gxtugAVyVcTa5/FD/Xnkb1siBw==",
+ "license": "Apache-2.0 OR MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/tauri"
+ }
+ },
+ "node_modules/@tauri-apps/cli": {
+ "version": "2.10.1",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.10.1.tgz",
+ "integrity": "sha512-jQNGF/5quwORdZSSLtTluyKQ+o6SMa/AUICfhf4egCGFdMHqWssApVgYSbg+jmrZoc8e1DscNvjTnXtlHLS11g==",
+ "dev": true,
+ "license": "Apache-2.0 OR MIT",
+ "bin": {
+ "tauri": "tauri.js"
+ },
+ "engines": {
+ "node": ">= 10"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/tauri"
+ },
+ "optionalDependencies": {
+ "@tauri-apps/cli-darwin-arm64": "2.10.1",
+ "@tauri-apps/cli-darwin-x64": "2.10.1",
+ "@tauri-apps/cli-linux-arm-gnueabihf": "2.10.1",
+ "@tauri-apps/cli-linux-arm64-gnu": "2.10.1",
+ "@tauri-apps/cli-linux-arm64-musl": "2.10.1",
+ "@tauri-apps/cli-linux-riscv64-gnu": "2.10.1",
+ "@tauri-apps/cli-linux-x64-gnu": "2.10.1",
+ "@tauri-apps/cli-linux-x64-musl": "2.10.1",
+ "@tauri-apps/cli-win32-arm64-msvc": "2.10.1",
+ "@tauri-apps/cli-win32-ia32-msvc": "2.10.1",
+ "@tauri-apps/cli-win32-x64-msvc": "2.10.1"
+ }
+ },
+ "node_modules/@tauri-apps/cli-darwin-arm64": {
+ "version": "2.10.1",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.10.1.tgz",
+ "integrity": "sha512-Z2OjCXiZ+fbYZy7PmP3WRnOpM9+Fy+oonKDEmUE6MwN4IGaYqgceTjwHucc/kEEYZos5GICve35f7ZiizgqEnQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 OR MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tauri-apps/cli-darwin-x64": {
+ "version": "2.10.1",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.10.1.tgz",
+ "integrity": "sha512-V/irQVvjPMGOTQqNj55PnQPVuH4VJP8vZCN7ajnj+ZS8Kom1tEM2hR3qbbIRoS3dBKs5mbG8yg1WC+97dq17Pw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 OR MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": {
+ "version": "2.10.1",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.10.1.tgz",
+ "integrity": "sha512-Hyzwsb4VnCWKGfTw+wSt15Z2pLw2f0JdFBfq2vHBOBhvg7oi6uhKiF87hmbXOBXUZaGkyRDkCHsdzJcIfoJC2w==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 OR MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tauri-apps/cli-linux-arm64-gnu": {
+ "version": "2.10.1",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.10.1.tgz",
+ "integrity": "sha512-OyOYs2t5GkBIvyWjA1+h4CZxTcdz1OZPCWAPz5DYEfB0cnWHERTnQ/SLayQzncrT0kwRoSfSz9KxenkyJoTelA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 OR MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tauri-apps/cli-linux-arm64-musl": {
+ "version": "2.10.1",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.10.1.tgz",
+ "integrity": "sha512-MIj78PDDGjkg3NqGptDOGgfXks7SYJwhiMh8SBoZS+vfdz7yP5jN18bNaLnDhsVIPARcAhE1TlsZe/8Yxo2zqg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 OR MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tauri-apps/cli-linux-riscv64-gnu": {
+ "version": "2.10.1",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-riscv64-gnu/-/cli-linux-riscv64-gnu-2.10.1.tgz",
+ "integrity": "sha512-X0lvOVUg8PCVaoEtEAnpxmnkwlE1gcMDTqfhbefICKDnOTJ5Est3qL0SrWxizDackIOKBcvtpejrSiVpuJI1kw==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 OR MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tauri-apps/cli-linux-x64-gnu": {
+ "version": "2.10.1",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.10.1.tgz",
+ "integrity": "sha512-2/12bEzsJS9fAKybxgicCDFxYD1WEI9kO+tlDwX5znWG2GwMBaiWcmhGlZ8fi+DMe9CXlcVarMTYc0L3REIRxw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 OR MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tauri-apps/cli-linux-x64-musl": {
+ "version": "2.10.1",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.10.1.tgz",
+ "integrity": "sha512-Y8J0ZzswPz50UcGOFuXGEMrxbjwKSPgXftx5qnkuMs2rmwQB5ssvLb6tn54wDSYxe7S6vlLob9vt0VKuNOaCIQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 OR MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tauri-apps/cli-win32-arm64-msvc": {
+ "version": "2.10.1",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.10.1.tgz",
+ "integrity": "sha512-iSt5B86jHYAPJa/IlYw++SXtFPGnWtFJriHn7X0NFBVunF6zu9+/zOn8OgqIWSl8RgzhLGXQEEtGBdR4wzpVgg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 OR MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tauri-apps/cli-win32-ia32-msvc": {
+ "version": "2.10.1",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.10.1.tgz",
+ "integrity": "sha512-gXyxgEzsFegmnWywYU5pEBURkcFN/Oo45EAwvZrHMh+zUSEAvO5E8TXsgPADYm31d1u7OQU3O3HsYfVBf2moHw==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 OR MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tauri-apps/cli-win32-x64-msvc": {
+ "version": "2.10.1",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.10.1.tgz",
+ "integrity": "sha512-6Cn7YpPFwzChy0ERz6djKEmUehWrYlM+xTaNzGPgZocw3BD7OfwfWHKVWxXzdjEW2KfKkHddfdxK1XXTYqBRLg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 OR MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tauri-apps/plugin-dialog": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-dialog/-/plugin-dialog-2.6.0.tgz",
+ "integrity": "sha512-q4Uq3eY87TdcYzXACiYSPhmpBA76shgmQswGkSVio4C82Sz2W4iehe9TnKYwbq7weHiL88Yw19XZm7v28+Micg==",
+ "license": "MIT OR Apache-2.0",
+ "dependencies": {
+ "@tauri-apps/api": "^2.8.0"
+ }
+ },
+ "node_modules/@tauri-apps/plugin-fs": {
+ "version": "2.4.5",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-fs/-/plugin-fs-2.4.5.tgz",
+ "integrity": "sha512-dVxWWGE6VrOxC7/jlhyE+ON/Cc2REJlM35R3PJX3UvFw2XwYhLGQVAIyrehenDdKjotipjYEVc4YjOl3qq90fA==",
+ "license": "MIT OR Apache-2.0",
+ "dependencies": {
+ "@tauri-apps/api": "^2.8.0"
+ }
+ },
+ "node_modules/@tauri-apps/plugin-notification": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-notification/-/plugin-notification-2.3.3.tgz",
+ "integrity": "sha512-Zw+ZH18RJb41G4NrfHgIuofJiymusqN+q8fGUIIV7vyCH+5sSn5coqRv/MWB9qETsUs97vmU045q7OyseCV3Qg==",
+ "license": "MIT OR Apache-2.0",
+ "dependencies": {
+ "@tauri-apps/api": "^2.8.0"
+ }
+ },
+ "node_modules/@tauri-apps/plugin-opener": {
+ "version": "2.5.3",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-opener/-/plugin-opener-2.5.3.tgz",
+ "integrity": "sha512-CCcUltXMOfUEArbf3db3kCE7Ggy1ExBEBl51Ko2ODJ6GDYHRp1nSNlQm5uNCFY5k7/ufaK5Ib3Du/Zir19IYQQ==",
+ "license": "MIT OR Apache-2.0",
+ "dependencies": {
+ "@tauri-apps/api": "^2.8.0"
+ }
+ },
+ "node_modules/@tokenizer/inflate": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.4.1.tgz",
+ "integrity": "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.4.3",
+ "token-types": "^6.1.1"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Borewit"
+ }
+ },
+ "node_modules/@tokenizer/token": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz",
+ "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==",
+ "license": "MIT"
+ },
+ "node_modules/@transloadit/prettier-bytes": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@transloadit/prettier-bytes/-/prettier-bytes-0.3.5.tgz",
+ "integrity": "sha512-xF4A3d/ZyX2LJWeQZREZQw+qFX4TGQ8bGVP97OLRt6sPO6T0TNHBFTuRHOJh7RNmYOBmQ9MHxpolD9bXihpuVA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
+ "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
+ "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.28.2"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+ "license": "MIT"
+ },
+ "node_modules/@types/graceful-fs": {
+ "version": "4.1.9",
+ "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz",
+ "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/istanbul-lib-coverage": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
+ "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/istanbul-lib-report": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz",
+ "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/istanbul-lib-coverage": "*"
+ }
+ },
+ "node_modules/@types/istanbul-reports": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz",
+ "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/istanbul-lib-report": "*"
+ }
+ },
+ "node_modules/@types/jasmine": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-6.0.0.tgz",
+ "integrity": "sha512-18lgGsLmEh3VJk9eZ5wAjTISxdqzl6YOwu8UdMpolajN57QOCNbl+AbHUd+Yu9ItrsFdB+c8LSZSGNg8nHaguw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/jest": {
+ "version": "30.0.0",
+ "resolved": "https://registry.npmjs.org/@types/jest/-/jest-30.0.0.tgz",
+ "integrity": "sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "expect": "^30.0.0",
+ "pretty-format": "^30.0.0"
+ }
+ },
+ "node_modules/@types/jsdom": {
+ "version": "21.1.7",
+ "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-21.1.7.tgz",
+ "integrity": "sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "@types/tough-cookie": "*",
+ "parse5": "^7.0.0"
+ }
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/lodash": {
+ "version": "4.17.24",
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.24.tgz",
+ "integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/node": {
+ "version": "25.5.0",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.0.tgz",
+ "integrity": "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~7.18.0"
+ }
+ },
+ "node_modules/@types/react": {
+ "version": "19.2.14",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz",
+ "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "csstype": "^3.2.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "19.2.3",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
+ "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
+ "devOptional": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "^19.2.0"
+ }
+ },
+ "node_modules/@types/resolve": {
+ "version": "1.20.2",
+ "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
+ "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/stack-utils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
+ "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/tough-cookie": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz",
+ "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/trusted-types": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
+ "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/yargs": {
+ "version": "17.0.33",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
+ "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "node_modules/@types/yargs-parser": {
+ "version": "21.0.3",
+ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz",
+ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.57.0.tgz",
+ "integrity": "sha512-qeu4rTHR3/IaFORbD16gmjq9+rEs9fGKdX0kF6BKSfi+gCuG3RCKLlSBYzn/bGsY9Tj7KE/DAQStbp8AHJGHEQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.12.2",
+ "@typescript-eslint/scope-manager": "8.57.0",
+ "@typescript-eslint/type-utils": "8.57.0",
+ "@typescript-eslint/utils": "8.57.0",
+ "@typescript-eslint/visitor-keys": "8.57.0",
+ "ignore": "^7.0.5",
+ "natural-compare": "^1.4.0",
+ "ts-api-utils": "^2.4.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^8.57.0",
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.57.0.tgz",
+ "integrity": "sha512-XZzOmihLIr8AD1b9hL9ccNMzEMWt/dE2u7NyTY9jJG6YNiNthaD5XtUHVF2uCXZ15ng+z2hT3MVuxnUYhq6k1g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "8.57.0",
+ "@typescript-eslint/types": "8.57.0",
+ "@typescript-eslint/typescript-estree": "8.57.0",
+ "@typescript-eslint/visitor-keys": "8.57.0",
+ "debug": "^4.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/project-service": {
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.57.0.tgz",
+ "integrity": "sha512-pR+dK0BlxCLxtWfaKQWtYr7MhKmzqZxuii+ZjuFlZlIGRZm22HnXFqa2eY+90MUz8/i80YJmzFGDUsi8dMOV5w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/tsconfig-utils": "^8.57.0",
+ "@typescript-eslint/types": "^8.57.0",
+ "debug": "^4.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.57.0.tgz",
+ "integrity": "sha512-nvExQqAHF01lUM66MskSaZulpPL5pgy5hI5RfrxviLgzZVffB5yYzw27uK/ft8QnKXI2X0LBrHJFr1TaZtAibw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.57.0",
+ "@typescript-eslint/visitor-keys": "8.57.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/tsconfig-utils": {
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.57.0.tgz",
+ "integrity": "sha512-LtXRihc5ytjJIQEH+xqjB0+YgsV4/tW35XKX3GTZHpWtcC8SPkT/d4tqdf1cKtesryHm2bgp6l555NYcT2NLvA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.57.0.tgz",
+ "integrity": "sha512-yjgh7gmDcJ1+TcEg8x3uWQmn8ifvSupnPfjP21twPKrDP/pTHlEQgmKcitzF/rzPSmv7QjJ90vRpN4U+zoUjwQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.57.0",
+ "@typescript-eslint/typescript-estree": "8.57.0",
+ "@typescript-eslint/utils": "8.57.0",
+ "debug": "^4.4.3",
+ "ts-api-utils": "^2.4.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.57.0.tgz",
+ "integrity": "sha512-dTLI8PEXhjUC7B9Kre+u0XznO696BhXcTlOn0/6kf1fHaQW8+VjJAVHJ3eTI14ZapTxdkOmc80HblPQLaEeJdg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.57.0.tgz",
+ "integrity": "sha512-m7faHcyVg0BT3VdYTlX8GdJEM7COexXxS6KqGopxdtkQRvBanK377QDHr4W/vIPAR+ah9+B/RclSW5ldVniO1Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/project-service": "8.57.0",
+ "@typescript-eslint/tsconfig-utils": "8.57.0",
+ "@typescript-eslint/types": "8.57.0",
+ "@typescript-eslint/visitor-keys": "8.57.0",
+ "debug": "^4.4.3",
+ "minimatch": "^10.2.2",
+ "semver": "^7.7.3",
+ "tinyglobby": "^0.2.15",
+ "ts-api-utils": "^2.4.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.57.0.tgz",
+ "integrity": "sha512-5iIHvpD3CZe06riAsbNxxreP+MuYgVUsV0n4bwLH//VJmgtt54sQeY2GszntJ4BjYCpMzrfVh2SBnUQTtys2lQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.9.1",
+ "@typescript-eslint/scope-manager": "8.57.0",
+ "@typescript-eslint/types": "8.57.0",
+ "@typescript-eslint/typescript-estree": "8.57.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.57.0.tgz",
+ "integrity": "sha512-zm6xx8UT/Xy2oSr2ZXD0pZo7Jx2XsCoID2IUh9YSTFRu7z+WdwYTRk6LhUftm1crwqbuoF6I8zAFeCMw0YjwDg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.57.0",
+ "eslint-visitor-keys": "^5.0.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
+ "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@uppy/components": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@uppy/components/-/components-1.2.0.tgz",
+ "integrity": "sha512-rtIr+77Rw/q5Vw++xazF1dCg2d4A4zT9CV+ZyN8Rsx8xiIr2CxCR4TaHHBy+WeC0b7Mk6yNuJ0wUa34tFJ6pKg==",
+ "license": "MIT",
+ "dependencies": {
+ "clsx": "^2.1.1",
+ "dequal": "^2.0.3",
+ "preact": "^10.26.10",
+ "pretty-bytes": "^6.1.1"
+ },
+ "peerDependencies": {
+ "@uppy/core": "^5.2.0",
+ "@uppy/image-editor": "^4.2.0",
+ "@uppy/screen-capture": "^5.1.0",
+ "@uppy/webcam": "^5.1.0"
+ },
+ "peerDependenciesMeta": {
+ "@uppy/image-editor": {
+ "optional": true
+ },
+ "@uppy/screen-capture": {
+ "optional": true
+ },
+ "@uppy/webcam": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@uppy/core": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@uppy/core/-/core-5.2.0.tgz",
+ "integrity": "sha512-uvfNyz4cnaplt7LYJmEZHuqOuav0tKp4a9WKJIaH6iIj7XiqYvS2J5SEByexAlUFlzefOAyjzj4Ja2dd/8aMrw==",
+ "license": "MIT",
+ "dependencies": {
+ "@transloadit/prettier-bytes": "^0.3.4",
+ "@uppy/store-default": "^5.0.0",
+ "@uppy/utils": "^7.1.4",
+ "lodash": "^4.17.21",
+ "mime-match": "^1.0.2",
+ "namespace-emitter": "^2.0.1",
+ "nanoid": "^5.0.9",
+ "preact": "^10.5.13"
+ }
+ },
+ "node_modules/@uppy/dashboard": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/@uppy/dashboard/-/dashboard-5.1.1.tgz",
+ "integrity": "sha512-6H/xVvhhdfwp1+FRMp2C+tudyaedqD5+LMDB8Iw20k9+QCL1eGzOh4wXm6MCqJtNfQ1tLaprGMG1jlo7yS/uyw==",
+ "license": "MIT",
+ "dependencies": {
+ "@transloadit/prettier-bytes": "^0.3.4",
+ "@uppy/provider-views": "^5.2.2",
+ "@uppy/thumbnail-generator": "^5.1.0",
+ "@uppy/utils": "^7.1.5",
+ "classnames": "^2.2.6",
+ "lodash": "^4.17.23",
+ "nanoid": "^5.0.9",
+ "preact": "^10.26.10",
+ "shallow-equal": "^3.0.0"
+ },
+ "peerDependencies": {
+ "@uppy/core": "^5.2.0"
+ }
+ },
+ "node_modules/@uppy/provider-views": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/@uppy/provider-views/-/provider-views-5.2.2.tgz",
+ "integrity": "sha512-NAazIJ5sjrAc6++CeJ/u9dB5gDaaAOLHrYeEmWs/HqLlftlIinRZOybnyzJRXwI8jWI/FK5moluzt2HXu6dPQQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@uppy/utils": "^7.1.5",
+ "classnames": "^2.2.6",
+ "lodash": "^4.17.21",
+ "nanoid": "^5.0.9",
+ "p-queue": "^8.0.0",
+ "preact": "^10.5.13"
+ },
+ "peerDependencies": {
+ "@uppy/core": "^5.2.0"
+ }
+ },
+ "node_modules/@uppy/react": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@uppy/react/-/react-5.2.0.tgz",
+ "integrity": "sha512-6lzPutg2XGavs7P6ALmqOBPitd/Jqi3r1jCJQD5nx8xtNlBRwvlBR6hrZgo8XOI9cR+OaNDrJ0vEFxXDWb04Ag==",
+ "license": "MIT",
+ "dependencies": {
+ "@uppy/components": "^1.2.0",
+ "preact": "^10.26.10",
+ "use-sync-external-store": "^1.3.0"
+ },
+ "peerDependencies": {
+ "@uppy/core": "^5.2.0",
+ "@uppy/dashboard": "^5.1.1",
+ "@uppy/screen-capture": "^5.1.0",
+ "@uppy/status-bar": "^5.1.0",
+ "@uppy/webcam": "^5.1.0",
+ "react": "^18.0.0 || ^19.0.0",
+ "react-dom": "^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@uppy/dashboard": {
+ "optional": true
+ },
+ "@uppy/screen-capture": {
+ "optional": true
+ },
+ "@uppy/status-bar": {
+ "optional": true
+ },
+ "@uppy/webcam": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@uppy/store-default": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/@uppy/store-default/-/store-default-5.0.0.tgz",
+ "integrity": "sha512-hQtCSQ1yGiaval/wVYUWquYGDJ+bpQ7e4FhUUAsRQz1x1K+o7NBtjfp63O9I4Ks1WRoKunpkarZ+as09l02cPw==",
+ "license": "MIT"
+ },
+ "node_modules/@uppy/thumbnail-generator": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@uppy/thumbnail-generator/-/thumbnail-generator-5.1.0.tgz",
+ "integrity": "sha512-QAKJHHkMrD/30GOyUb5U9HyJ7Ie3jiMLp4pVdw27PoA4pNV7fDQz0tyDeRPj2H+BWPEB1NsTSSfHI2pjHNI+OQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@uppy/utils": "^7.1.4",
+ "exifr": "^7.0.0"
+ },
+ "peerDependencies": {
+ "@uppy/core": "^5.2.0"
+ }
+ },
+ "node_modules/@uppy/utils": {
+ "version": "7.1.5",
+ "resolved": "https://registry.npmjs.org/@uppy/utils/-/utils-7.1.5.tgz",
+ "integrity": "sha512-Vz4WGTjef6WebECGur4clWjpkET4o3bdvPMj1m2sD5cL+dTt69m+FIE5h5JD3HBMLEPTXPVkrXGMIFcbOYC12Q==",
+ "license": "MIT",
+ "dependencies": {
+ "lodash": "^4.17.21",
+ "preact": "^10.5.13"
+ }
+ },
+ "node_modules/@vite-pwa/assets-generator": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@vite-pwa/assets-generator/-/assets-generator-1.0.2.tgz",
+ "integrity": "sha512-MCbrb508JZHqe7bUibmZj/lyojdhLRnfkmyXnkrCM2zVrjTgL89U8UEfInpKTvPeTnxsw2hmyZxnhsdNR6yhwg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cac": "^6.7.14",
+ "colorette": "^2.0.20",
+ "consola": "^3.4.2",
+ "sharp": "^0.33.5",
+ "sharp-ico": "^0.1.5",
+ "unconfig": "^7.3.1"
+ },
+ "bin": {
+ "pwa-assets-generator": "bin/pwa-assets-generator.mjs"
+ },
+ "engines": {
+ "node": ">=16.14.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/@vitejs/plugin-react": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.2.0.tgz",
+ "integrity": "sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.29.0",
+ "@babel/plugin-transform-react-jsx-self": "^7.27.1",
+ "@babel/plugin-transform-react-jsx-source": "^7.27.1",
+ "@rolldown/pluginutils": "1.0.0-rc.3",
+ "@types/babel__core": "^7.20.5",
+ "react-refresh": "^0.18.0"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "peerDependencies": {
+ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/@web-scrobbler/metadata-filter": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/@web-scrobbler/metadata-filter/-/metadata-filter-3.2.0.tgz",
+ "integrity": "sha512-K2Wkq9AOJkgj4Hk9g0flKnNWYkJy1GTPpHTgpNLU5OXaXgqPKLyrtb62M1cIxMN3ESH6XGvPKM92VEl/Gc3Rog==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.15.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
+ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
+ "devOptional": true,
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/agent-base": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
+ "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.14.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz",
+ "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "type-fest": "^0.21.3"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-escapes/node_modules/type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
+ "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/anymatch/node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true,
+ "license": "Python-2.0"
+ },
+ "node_modules/aria-hidden": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz",
+ "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/array-buffer-byte-length": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz",
+ "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "is-array-buffer": "^3.0.5"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-includes": {
+ "version": "3.1.9",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz",
+ "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.24.0",
+ "es-object-atoms": "^1.1.1",
+ "get-intrinsic": "^1.3.0",
+ "is-string": "^1.1.1",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.findlast": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz",
+ "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flat": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz",
+ "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flatmap": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz",
+ "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.tosorted": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz",
+ "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.3",
+ "es-errors": "^1.3.0",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/arraybuffer.prototype.slice": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz",
+ "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.1",
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "is-array-buffer": "^3.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/async": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
+ "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/async-function": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz",
+ "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/at-least-node": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
+ "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/automation-events": {
+ "version": "7.1.15",
+ "resolved": "https://registry.npmjs.org/automation-events/-/automation-events-7.1.15.tgz",
+ "integrity": "sha512-NsHJlve3twcgs8IyP4iEYph7Fzpnh6klN7G5LahwvypakBjFbsiGHJxrqTmeHKREdu/Tx6oZboqNI0tD4MnFlA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.28.6",
+ "tslib": "^2.8.1"
+ },
+ "engines": {
+ "node": ">=18.2.0"
+ }
+ },
+ "node_modules/available-typed-arrays": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
+ "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "possible-typed-array-names": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/babel-jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
+ "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/transform": "^29.7.0",
+ "@types/babel__core": "^7.1.14",
+ "babel-plugin-istanbul": "^6.1.1",
+ "babel-preset-jest": "^29.6.3",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.8.0"
+ }
+ },
+ "node_modules/babel-plugin-istanbul": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz",
+ "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@istanbuljs/load-nyc-config": "^1.0.0",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-instrument": "^5.0.4",
+ "test-exclude": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz",
+ "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/core": "^7.12.3",
+ "@babel/parser": "^7.14.7",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/babel-plugin-istanbul/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/babel-plugin-jest-hoist": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz",
+ "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.3.3",
+ "@babel/types": "^7.3.3",
+ "@types/babel__core": "^7.1.14",
+ "@types/babel__traverse": "^7.0.6"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-corejs2": {
+ "version": "0.4.14",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz",
+ "integrity": "sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/compat-data": "^7.27.7",
+ "@babel/helper-define-polyfill-provider": "^0.6.5",
+ "semver": "^6.3.1"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-corejs3": {
+ "version": "0.13.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz",
+ "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-define-polyfill-provider": "^0.6.5",
+ "core-js-compat": "^3.43.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-regenerator": {
+ "version": "0.6.5",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.5.tgz",
+ "integrity": "sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-define-polyfill-provider": "^0.6.5"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
+ }
+ },
+ "node_modules/babel-preset-current-node-syntax": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz",
+ "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/plugin-syntax-async-generators": "^7.8.4",
+ "@babel/plugin-syntax-bigint": "^7.8.3",
+ "@babel/plugin-syntax-class-properties": "^7.12.13",
+ "@babel/plugin-syntax-class-static-block": "^7.14.5",
+ "@babel/plugin-syntax-import-attributes": "^7.24.7",
+ "@babel/plugin-syntax-import-meta": "^7.10.4",
+ "@babel/plugin-syntax-json-strings": "^7.8.3",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-syntax-private-property-in-object": "^7.14.5",
+ "@babel/plugin-syntax-top-level-await": "^7.14.5"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0 || ^8.0.0-0"
+ }
+ },
+ "node_modules/babel-preset-jest": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz",
+ "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "babel-plugin-jest-hoist": "^29.6.3",
+ "babel-preset-current-node-syntax": "^1.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.9.11",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.11.tgz",
+ "integrity": "sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.js"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "license": "MIT",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz",
+ "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "baseline-browser-mapping": "^2.9.0",
+ "caniuse-lite": "^1.0.30001759",
+ "electron-to-chromium": "^1.5.263",
+ "node-releases": "^2.0.27",
+ "update-browserslist-db": "^1.2.0"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/bs-logger": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz",
+ "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-json-stable-stringify": "2.x"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/bser": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
+ "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "node-int64": "^0.4.0"
+ }
+ },
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/cac": {
+ "version": "6.7.14",
+ "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
+ "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
+ "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.0",
+ "es-define-property": "^1.0.0",
+ "get-intrinsic": "^1.2.4",
+ "set-function-length": "^1.2.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/call-bound": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
+ "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "get-intrinsic": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001762",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001762.tgz",
+ "integrity": "sha512-PxZwGNvH7Ak8WX5iXzoK1KPZttBXNPuaOvI2ZYU7NrlM+d9Ov+TUvlLOBNGzVXAntMSMMlJPd+jY6ovrVjSmUw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/char-regex": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
+ "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ci-info": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz",
+ "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cjs-module-lexer": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz",
+ "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/classnames": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz",
+ "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==",
+ "license": "MIT"
+ },
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/cliui/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cliui/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cliui/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cliui/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cliui/node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/cloc": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/cloc/-/cloc-2.11.0.tgz",
+ "integrity": "sha512-+mxuCHo7ESOQadlsyMjmPZ4hGBtvQzmNGHfLdBNvXKbnRhtmOTslU4XF2cyFSaOCHaaF26ba2CGjU6lpeIFB0w==",
+ "dev": true,
+ "license": "GPL-2.0",
+ "bin": {
+ "cloc": "lib/cloc"
+ }
+ },
+ "node_modules/clsx": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "iojs": ">= 1.0.0",
+ "node": ">= 0.12.0"
+ }
+ },
+ "node_modules/collect-v8-coverage": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz",
+ "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/color": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
+ "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1",
+ "color-string": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=12.5.0"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/color-string": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
+ "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "^1.0.0",
+ "simple-swizzle": "^0.2.2"
+ }
+ },
+ "node_modules/colorette": {
+ "version": "2.0.20",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
+ "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/common-tags": {
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz",
+ "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/consola": {
+ "version": "3.4.2",
+ "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz",
+ "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.18.0 || >=16.10.0"
+ }
+ },
+ "node_modules/content-type": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/core-js-compat": {
+ "version": "3.47.0",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.47.0.tgz",
+ "integrity": "sha512-IGfuznZ/n7Kp9+nypamBhvwdwLsW6KC8IOaURw2doAK5e98AG3acVLdh0woOnEqCfUtS+Vu882JE4k/DAm3ItQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "browserslist": "^4.28.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/core-js"
+ }
+ },
+ "node_modules/create-jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz",
+ "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.9",
+ "jest-config": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "prompts": "^2.0.1"
+ },
+ "bin": {
+ "create-jest": "bin/create-jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/create-jest/node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@sinclair/typebox": "^0.27.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/create-jest/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/create-jest/node_modules/@sinclair/typebox": {
+ "version": "0.27.10",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
+ "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/create-jest/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/create-jest/node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/create-jest/node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/cross-env": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-10.1.0.tgz",
+ "integrity": "sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@epic-web/invariant": "^1.0.0",
+ "cross-spawn": "^7.0.6"
+ },
+ "bin": {
+ "cross-env": "dist/bin/cross-env.js",
+ "cross-env-shell": "dist/bin/cross-env-shell.js"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/cross-fetch": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz",
+ "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==",
+ "license": "MIT",
+ "dependencies": {
+ "node-fetch": "^2.6.12"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/crypto-random-string": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
+ "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cssstyle": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.6.0.tgz",
+ "integrity": "sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@asamuzakjp/css-color": "^3.2.0",
+ "rrweb-cssom": "^0.8.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
+ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/data-urls": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz",
+ "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "whatwg-mimetype": "^4.0.0",
+ "whatwg-url": "^14.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/data-urls/node_modules/tr46": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz",
+ "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "punycode": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/data-urls/node_modules/webidl-conversions": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
+ "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/data-urls/node_modules/whatwg-url": {
+ "version": "14.2.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz",
+ "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tr46": "^5.1.0",
+ "webidl-conversions": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/data-view-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
+ "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/data-view-byte-length": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz",
+ "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/inspect-js"
+ }
+ },
+ "node_modules/data-view-byte-offset": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz",
+ "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/decimal.js": {
+ "version": "10.6.0",
+ "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz",
+ "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/decode-bmp": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/decode-bmp/-/decode-bmp-0.2.1.tgz",
+ "integrity": "sha512-NiOaGe+GN0KJqi2STf24hfMkFitDUaIoUU3eKvP/wAbLe8o6FuW5n/x7MHPR0HKvBokp6MQY/j7w8lewEeVCIA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@canvas/image-data": "^1.0.0",
+ "to-data-view": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/decode-ico": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/decode-ico/-/decode-ico-0.4.1.tgz",
+ "integrity": "sha512-69NZfbKIzux1vBOd31al3XnMnH+2mqDhEgLdpygErm4d60N+UwA5Sq5WFjmEDQzumgB9fElojGwWG0vybVfFmA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@canvas/image-data": "^1.0.0",
+ "decode-bmp": "^0.2.0",
+ "to-data-view": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/dedent": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.2.tgz",
+ "integrity": "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "babel-plugin-macros": "^3.1.0"
+ },
+ "peerDependenciesMeta": {
+ "babel-plugin-macros": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/deepmerge": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/define-data-property": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/define-properties": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
+ "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.0.1",
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/defu": {
+ "version": "6.1.4",
+ "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz",
+ "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/dequal": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
+ "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/detect-libc": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.1.tgz",
+ "integrity": "sha512-ecqj/sy1jcK1uWrwpR67UhYrIFQ+5WlGxth34WquCbamhFA6hkkwiu37o6J5xCHdo1oixJRfVRw+ywV+Hq/0Aw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/detect-newline": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
+ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/detect-node-es": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
+ "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==",
+ "license": "MIT"
+ },
+ "node_modules/diff-sequences": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
+ "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/dompurify": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.3.tgz",
+ "integrity": "sha512-Oj6pzI2+RqBfFG+qOaOLbFXLQ90ARpcGG6UePL82bJLtdsa6CYJD7nmiU8MW9nQNOtCHV3lZ/Bzq1X0QYbBZCA==",
+ "license": "(MPL-2.0 OR Apache-2.0)",
+ "optionalDependencies": {
+ "@types/trusted-types": "^2.0.7"
+ }
+ },
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/ejs": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz",
+ "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "jake": "^10.8.5"
+ },
+ "bin": {
+ "ejs": "bin/cli.js"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.267",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz",
+ "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/emittery": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz",
+ "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/emittery?sponsor=1"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/entities": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
+ "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/error-ex": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz",
+ "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "node_modules/error-ex/node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/es-abstract": {
+ "version": "1.24.0",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz",
+ "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.2",
+ "arraybuffer.prototype.slice": "^1.0.4",
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "data-view-buffer": "^1.0.2",
+ "data-view-byte-length": "^1.0.2",
+ "data-view-byte-offset": "^1.0.1",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "es-set-tostringtag": "^2.1.0",
+ "es-to-primitive": "^1.3.0",
+ "function.prototype.name": "^1.1.8",
+ "get-intrinsic": "^1.3.0",
+ "get-proto": "^1.0.1",
+ "get-symbol-description": "^1.1.0",
+ "globalthis": "^1.0.4",
+ "gopd": "^1.2.0",
+ "has-property-descriptors": "^1.0.2",
+ "has-proto": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "internal-slot": "^1.1.0",
+ "is-array-buffer": "^3.0.5",
+ "is-callable": "^1.2.7",
+ "is-data-view": "^1.0.2",
+ "is-negative-zero": "^2.0.3",
+ "is-regex": "^1.2.1",
+ "is-set": "^2.0.3",
+ "is-shared-array-buffer": "^1.0.4",
+ "is-string": "^1.1.1",
+ "is-typed-array": "^1.1.15",
+ "is-weakref": "^1.1.1",
+ "math-intrinsics": "^1.1.0",
+ "object-inspect": "^1.13.4",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.7",
+ "own-keys": "^1.0.1",
+ "regexp.prototype.flags": "^1.5.4",
+ "safe-array-concat": "^1.1.3",
+ "safe-push-apply": "^1.0.0",
+ "safe-regex-test": "^1.1.0",
+ "set-proto": "^1.0.0",
+ "stop-iteration-iterator": "^1.1.0",
+ "string.prototype.trim": "^1.2.10",
+ "string.prototype.trimend": "^1.0.9",
+ "string.prototype.trimstart": "^1.0.8",
+ "typed-array-buffer": "^1.0.3",
+ "typed-array-byte-length": "^1.0.3",
+ "typed-array-byte-offset": "^1.0.4",
+ "typed-array-length": "^1.0.7",
+ "unbox-primitive": "^1.1.0",
+ "which-typed-array": "^1.1.19"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-iterator-helpers": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz",
+ "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.6",
+ "es-errors": "^1.3.0",
+ "es-set-tostringtag": "^2.0.3",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.6",
+ "globalthis": "^1.0.4",
+ "gopd": "^1.2.0",
+ "has-property-descriptors": "^1.0.2",
+ "has-proto": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "internal-slot": "^1.1.0",
+ "iterator.prototype": "^1.1.4",
+ "safe-array-concat": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-shim-unscopables": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz",
+ "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-to-primitive": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz",
+ "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-callable": "^1.2.7",
+ "is-date-object": "^1.0.5",
+ "is-symbol": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz",
+ "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.27.2",
+ "@esbuild/android-arm": "0.27.2",
+ "@esbuild/android-arm64": "0.27.2",
+ "@esbuild/android-x64": "0.27.2",
+ "@esbuild/darwin-arm64": "0.27.2",
+ "@esbuild/darwin-x64": "0.27.2",
+ "@esbuild/freebsd-arm64": "0.27.2",
+ "@esbuild/freebsd-x64": "0.27.2",
+ "@esbuild/linux-arm": "0.27.2",
+ "@esbuild/linux-arm64": "0.27.2",
+ "@esbuild/linux-ia32": "0.27.2",
+ "@esbuild/linux-loong64": "0.27.2",
+ "@esbuild/linux-mips64el": "0.27.2",
+ "@esbuild/linux-ppc64": "0.27.2",
+ "@esbuild/linux-riscv64": "0.27.2",
+ "@esbuild/linux-s390x": "0.27.2",
+ "@esbuild/linux-x64": "0.27.2",
+ "@esbuild/netbsd-arm64": "0.27.2",
+ "@esbuild/netbsd-x64": "0.27.2",
+ "@esbuild/openbsd-arm64": "0.27.2",
+ "@esbuild/openbsd-x64": "0.27.2",
+ "@esbuild/openharmony-arm64": "0.27.2",
+ "@esbuild/sunos-x64": "0.27.2",
+ "@esbuild/win32-arm64": "0.27.2",
+ "@esbuild/win32-ia32": "0.27.2",
+ "@esbuild/win32-x64": "0.27.2"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "9.39.4",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz",
+ "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.8.0",
+ "@eslint-community/regexpp": "^4.12.1",
+ "@eslint/config-array": "^0.21.2",
+ "@eslint/config-helpers": "^0.4.2",
+ "@eslint/core": "^0.17.0",
+ "@eslint/eslintrc": "^3.3.5",
+ "@eslint/js": "9.39.4",
+ "@eslint/plugin-kit": "^0.4.1",
+ "@humanfs/node": "^0.16.6",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@humanwhocodes/retry": "^0.4.2",
+ "@types/estree": "^1.0.6",
+ "ajv": "^6.14.0",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.6",
+ "debug": "^4.3.2",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^8.4.0",
+ "eslint-visitor-keys": "^4.2.1",
+ "espree": "^10.4.0",
+ "esquery": "^1.5.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^8.0.0",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.5",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ },
+ "peerDependencies": {
+ "jiti": "*"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ }
+ }
},
- "node_modules/@rollup/rollup-win32-x64-msvc": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz",
- "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==",
- "cpu": [
- "x64"
- ],
+ "node_modules/eslint-plugin-react": {
+ "version": "7.37.5",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz",
+ "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==",
+ "dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@rooks/use-mutation-observer": {
- "version": "4.11.2",
- "resolved": "https://registry.npmjs.org/@rooks/use-mutation-observer/-/use-mutation-observer-4.11.2.tgz",
- "integrity": "sha512-vpsdrZdr6TkB1zZJcHx+fR1YC/pHs2BaqcuYiEGjBVbwY5xcC49+h0hAUtQKHth3oJqXfIX/Ng8S7s5HFHdM/A==",
+ "dependencies": {
+ "array-includes": "^3.1.8",
+ "array.prototype.findlast": "^1.2.5",
+ "array.prototype.flatmap": "^1.3.3",
+ "array.prototype.tosorted": "^1.1.4",
+ "doctrine": "^2.1.0",
+ "es-iterator-helpers": "^1.2.1",
+ "estraverse": "^5.3.0",
+ "hasown": "^2.0.2",
+ "jsx-ast-utils": "^2.4.1 || ^3.0.0",
+ "minimatch": "^3.1.2",
+ "object.entries": "^1.1.9",
+ "object.fromentries": "^2.0.8",
+ "object.values": "^1.2.1",
+ "prop-types": "^15.8.1",
+ "resolve": "^2.0.0-next.5",
+ "semver": "^6.3.1",
+ "string.prototype.matchall": "^4.0.12",
+ "string.prototype.repeat": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
"peerDependencies": {
- "react": ">=16.8.0"
+ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7"
}
},
- "node_modules/@sinclair/typebox": {
- "version": "0.34.41",
- "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.41.tgz",
- "integrity": "sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==",
+ "node_modules/eslint-plugin-react/node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
},
- "node_modules/@surma/rollup-plugin-off-main-thread": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz",
- "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==",
+ "node_modules/eslint-plugin-react/node_modules/minimatch": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
"dev": true,
- "license": "Apache-2.0",
+ "license": "ISC",
"dependencies": {
- "ejs": "^3.1.6",
- "json5": "^2.2.0",
- "magic-string": "^0.25.0",
- "string.prototype.matchall": "^4.0.6"
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
}
},
- "node_modules/@swc/core": {
- "version": "1.15.8",
- "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.15.8.tgz",
- "integrity": "sha512-T8keoJjXaSUoVBCIjgL6wAnhADIb09GOELzKg10CjNg+vLX48P93SME6jTfte9MZIm5m+Il57H3rTSk/0kzDUw==",
+ "node_modules/eslint-plugin-react/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
- "hasInstallScript": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
+ "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
- "@swc/counter": "^0.1.3",
- "@swc/types": "^0.1.25"
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
},
"engines": {
- "node": ">=10"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/swc"
- },
- "optionalDependencies": {
- "@swc/core-darwin-arm64": "1.15.8",
- "@swc/core-darwin-x64": "1.15.8",
- "@swc/core-linux-arm-gnueabihf": "1.15.8",
- "@swc/core-linux-arm64-gnu": "1.15.8",
- "@swc/core-linux-arm64-musl": "1.15.8",
- "@swc/core-linux-x64-gnu": "1.15.8",
- "@swc/core-linux-x64-musl": "1.15.8",
- "@swc/core-win32-arm64-msvc": "1.15.8",
- "@swc/core-win32-ia32-msvc": "1.15.8",
- "@swc/core-win32-x64-msvc": "1.15.8"
- },
- "peerDependencies": {
- "@swc/helpers": ">=0.5.17"
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
- "peerDependenciesMeta": {
- "@swc/helpers": {
- "optional": true
- }
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
- "node_modules/@swc/core-darwin-arm64": {
- "version": "1.15.8",
- "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.8.tgz",
- "integrity": "sha512-M9cK5GwyWWRkRGwwCbREuj6r8jKdES/haCZ3Xckgkl8MUQJZA3XB7IXXK1IXRNeLjg6m7cnoMICpXv1v1hlJOg==",
- "cpu": [
- "arm64"
- ],
+ "node_modules/eslint/node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
- "optional": true,
- "os": [
- "darwin"
- ],
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/eslint/node_modules/eslint-visitor-keys": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+ "dev": true,
+ "license": "Apache-2.0",
"engines": {
- "node": ">=10"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
- "node_modules/@swc/core-darwin-x64": {
- "version": "1.15.8",
- "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.15.8.tgz",
- "integrity": "sha512-j47DasuOvXl80sKJHSi2X25l44CMc3VDhlJwA7oewC1nV1VsSzwX+KOwE5tLnfORvVJJyeiXgJORNYg4jeIjYQ==",
- "cpu": [
- "x64"
- ],
+ "node_modules/eslint/node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
"dev": true,
- "optional": true,
- "os": [
- "darwin"
- ],
+ "license": "MIT",
"engines": {
- "node": ">=10"
+ "node": ">= 4"
}
},
- "node_modules/@swc/core-linux-arm-gnueabihf": {
- "version": "1.15.8",
- "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.15.8.tgz",
- "integrity": "sha512-siAzDENu2rUbwr9+fayWa26r5A9fol1iORG53HWxQL1J8ym4k7xt9eME0dMPXlYZDytK5r9sW8zEA10F2U3Xwg==",
- "cpu": [
- "arm"
- ],
+ "node_modules/eslint/node_modules/minimatch": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
"dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
"engines": {
- "node": ">=10"
+ "node": "*"
}
},
- "node_modules/@swc/core-linux-arm64-gnu": {
- "version": "1.15.8",
- "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.15.8.tgz",
- "integrity": "sha512-o+1y5u6k2FfPYbTRUPvurwzNt5qd0NTumCTFscCNuBksycloXY16J8L+SMW5QRX59n4Hp9EmFa3vpvNHRVv1+Q==",
- "cpu": [
- "arm64"
- ],
+ "node_modules/espree": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
+ "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
"dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "acorn": "^8.15.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^4.2.1"
+ },
"engines": {
- "node": ">=10"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
- "node_modules/@swc/core-linux-arm64-musl": {
- "version": "1.15.8",
- "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.15.8.tgz",
- "integrity": "sha512-koiCqL09EwOP1S2RShCI7NbsQuG6r2brTqUYE7pV7kZm9O17wZ0LSz22m6gVibpwEnw8jI3IE1yYsQTVpluALw==",
- "cpu": [
- "arm64"
- ],
+ "node_modules/espree/node_modules/eslint-visitor-keys": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
"dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
+ "license": "Apache-2.0",
"engines": {
- "node": ">=10"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
- "node_modules/@swc/core-linux-x64-gnu": {
- "version": "1.15.8",
- "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.15.8.tgz",
- "integrity": "sha512-4p6lOMU3bC+Vd5ARtKJ/FxpIC5G8v3XLoPEZ5s7mLR8h7411HWC/LmTXDHcrSXRC55zvAVia1eldy6zDLz8iFQ==",
- "cpu": [
- "x64"
- ],
+ "node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
"dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
+ "license": "BSD-2-Clause",
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
"engines": {
- "node": ">=10"
+ "node": ">=4"
}
},
- "node_modules/@swc/core-linux-x64-musl": {
- "version": "1.15.8",
- "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.15.8.tgz",
- "integrity": "sha512-z3XBnbrZAL+6xDGAhJoN4lOueIxC/8rGrJ9tg+fEaeqLEuAtHSW2QHDHxDwkxZMjuF/pZ6MUTjHjbp8wLbuRLA==",
- "cpu": [
- "x64"
- ],
+ "node_modules/esquery": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
+ "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
"dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
"engines": {
- "node": ">=10"
+ "node": ">=0.10"
}
},
- "node_modules/@swc/core-win32-arm64-msvc": {
- "version": "1.15.8",
- "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.15.8.tgz",
- "integrity": "sha512-djQPJ9Rh9vP8GTS/Df3hcc6XP6xnG5c8qsngWId/BLA9oX6C7UzCPAn74BG/wGb9a6j4w3RINuoaieJB3t+7iQ==",
- "cpu": [
- "arm64"
- ],
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
"dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
"engines": {
- "node": ">=10"
+ "node": ">=4.0"
}
},
- "node_modules/@swc/core-win32-ia32-msvc": {
- "version": "1.15.8",
- "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.15.8.tgz",
- "integrity": "sha512-/wfAgxORg2VBaUoFdytcVBVCgf1isWZIEXB9MZEUty4wwK93M/PxAkjifOho9RN3WrM3inPLabICRCEgdHpKKQ==",
- "cpu": [
- "ia32"
- ],
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
"dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
+ "license": "BSD-2-Clause",
"engines": {
- "node": ">=10"
+ "node": ">=4.0"
}
},
- "node_modules/@swc/core-win32-x64-msvc": {
- "version": "1.15.8",
- "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.15.8.tgz",
- "integrity": "sha512-GpMePrh9Sl4d61o4KAHOOv5is5+zt6BEXCOCgs/H0FLGeii7j9bWDE8ExvKFy2GRRZVNR1ugsnzaGWHKM6kuzA==",
- "cpu": [
- "x64"
- ],
+ "node_modules/estree-walker": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
+ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
+ "license": "MIT"
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
"engines": {
- "node": ">=10"
+ "node": ">=0.10.0"
}
},
- "node_modules/@swc/counter": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
- "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==",
- "dev": true
+ "node_modules/eventemitter3": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
+ "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
+ "license": "MIT"
},
- "node_modules/@swc/types": {
- "version": "0.1.25",
- "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.25.tgz",
- "integrity": "sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g==",
+ "node_modules/execa": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@swc/counter": "^0.1.3"
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.0",
+ "human-signals": "^2.1.0",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
+ "strip-final-newline": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
}
},
- "node_modules/@swc/wasm": {
- "version": "1.15.8",
- "resolved": "https://registry.npmjs.org/@swc/wasm/-/wasm-1.15.8.tgz",
- "integrity": "sha512-RG2BxGbbsjtddFCo1ghKH6A/BMXbY1eMBfpysV0lJMCpI4DZOjW1BNBnxvBt7YsYmlJtmy5UXIg9/4ekBTFFaQ==",
- "dev": true
+ "node_modules/execa/node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true,
+ "license": "ISC"
},
- "node_modules/@tauri-apps/api": {
- "version": "2.10.1",
- "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.10.1.tgz",
- "integrity": "sha512-hKL/jWf293UDSUN09rR69hrToyIXBb8CjGaWC7gfinvnQrBVvnLr08FeFi38gxtugAVyVcTa5/FD/Xnkb1siBw==",
- "license": "Apache-2.0 OR MIT",
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/tauri"
+ "node_modules/exifr": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/exifr/-/exifr-7.1.3.tgz",
+ "integrity": "sha512-g/aje2noHivrRSLbAUtBPWFbxKdKhgj/xr1vATDdUXPOFYJlQ62Ft0oy+72V6XLIpDJfHs6gXLbBLAolqOXYRw==",
+ "license": "MIT"
+ },
+ "node_modules/exit": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+ "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
}
},
- "node_modules/@tauri-apps/cli": {
- "version": "2.10.1",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.10.1.tgz",
- "integrity": "sha512-jQNGF/5quwORdZSSLtTluyKQ+o6SMa/AUICfhf4egCGFdMHqWssApVgYSbg+jmrZoc8e1DscNvjTnXtlHLS11g==",
+ "node_modules/expect": {
+ "version": "30.2.0",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-30.2.0.tgz",
+ "integrity": "sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==",
"dev": true,
- "license": "Apache-2.0 OR MIT",
- "bin": {
- "tauri": "tauri.js"
+ "license": "MIT",
+ "dependencies": {
+ "@jest/expect-utils": "30.2.0",
+ "@jest/get-type": "30.1.0",
+ "jest-matcher-utils": "30.2.0",
+ "jest-message-util": "30.2.0",
+ "jest-mock": "30.2.0",
+ "jest-util": "30.2.0"
},
"engines": {
- "node": ">= 10"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/tauri"
- },
- "optionalDependencies": {
- "@tauri-apps/cli-darwin-arm64": "2.10.1",
- "@tauri-apps/cli-darwin-x64": "2.10.1",
- "@tauri-apps/cli-linux-arm-gnueabihf": "2.10.1",
- "@tauri-apps/cli-linux-arm64-gnu": "2.10.1",
- "@tauri-apps/cli-linux-arm64-musl": "2.10.1",
- "@tauri-apps/cli-linux-riscv64-gnu": "2.10.1",
- "@tauri-apps/cli-linux-x64-gnu": "2.10.1",
- "@tauri-apps/cli-linux-x64-musl": "2.10.1",
- "@tauri-apps/cli-win32-arm64-msvc": "2.10.1",
- "@tauri-apps/cli-win32-ia32-msvc": "2.10.1",
- "@tauri-apps/cli-win32-x64-msvc": "2.10.1"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/@tauri-apps/cli-darwin-arm64": {
- "version": "2.10.1",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.10.1.tgz",
- "integrity": "sha512-Z2OjCXiZ+fbYZy7PmP3WRnOpM9+Fy+oonKDEmUE6MwN4IGaYqgceTjwHucc/kEEYZos5GICve35f7ZiizgqEnQ==",
- "cpu": [
- "arm64"
- ],
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"dev": true,
- "license": "Apache-2.0 OR MIT",
- "optional": true,
- "os": [
- "darwin"
+ "license": "MIT"
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-uri": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz",
+ "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
],
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/fb-watchman": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
+ "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "bser": "2.1.1"
+ }
+ },
+ "node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "license": "MIT",
"engines": {
- "node": ">= 10"
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
}
},
- "node_modules/@tauri-apps/cli-darwin-x64": {
- "version": "2.10.1",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.10.1.tgz",
- "integrity": "sha512-V/irQVvjPMGOTQqNj55PnQPVuH4VJP8vZCN7ajnj+ZS8Kom1tEM2hR3qbbIRoS3dBKs5mbG8yg1WC+97dq17Pw==",
- "cpu": [
- "x64"
- ],
+ "node_modules/file-entry-cache": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
"dev": true,
- "license": "Apache-2.0 OR MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
+ "license": "MIT",
+ "dependencies": {
+ "flat-cache": "^4.0.0"
+ },
"engines": {
- "node": ">= 10"
+ "node": ">=16.0.0"
}
},
- "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": {
- "version": "2.10.1",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.10.1.tgz",
- "integrity": "sha512-Hyzwsb4VnCWKGfTw+wSt15Z2pLw2f0JdFBfq2vHBOBhvg7oi6uhKiF87hmbXOBXUZaGkyRDkCHsdzJcIfoJC2w==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "Apache-2.0 OR MIT",
- "optional": true,
- "os": [
- "linux"
- ],
+ "node_modules/file-type": {
+ "version": "21.3.2",
+ "resolved": "https://registry.npmjs.org/file-type/-/file-type-21.3.2.tgz",
+ "integrity": "sha512-DLkUvGwep3poOV2wpzbHCOnSKGk1LzyXTv+aHFgN2VFl96wnp8YA9YjO2qPzg5PuL8q/SW9Pdi6WTkYOIh995w==",
+ "license": "MIT",
+ "dependencies": {
+ "@tokenizer/inflate": "^0.4.1",
+ "strtok3": "^10.3.4",
+ "token-types": "^6.1.1",
+ "uint8array-extras": "^1.4.0"
+ },
"engines": {
- "node": ">= 10"
+ "node": ">=20"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/file-type?sponsor=1"
}
},
- "node_modules/@tauri-apps/cli-linux-arm64-gnu": {
- "version": "2.10.1",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.10.1.tgz",
- "integrity": "sha512-OyOYs2t5GkBIvyWjA1+h4CZxTcdz1OZPCWAPz5DYEfB0cnWHERTnQ/SLayQzncrT0kwRoSfSz9KxenkyJoTelA==",
- "cpu": [
- "arm64"
- ],
+ "node_modules/filelist": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
+ "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==",
"dev": true,
- "license": "Apache-2.0 OR MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
+ "license": "Apache-2.0",
+ "dependencies": {
+ "minimatch": "^5.0.1"
}
},
- "node_modules/@tauri-apps/cli-linux-arm64-musl": {
- "version": "2.10.1",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.10.1.tgz",
- "integrity": "sha512-MIj78PDDGjkg3NqGptDOGgfXks7SYJwhiMh8SBoZS+vfdz7yP5jN18bNaLnDhsVIPARcAhE1TlsZe/8Yxo2zqg==",
- "cpu": [
- "arm64"
- ],
+ "node_modules/filelist/node_modules/minimatch": {
+ "version": "5.1.9",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz",
+ "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==",
"dev": true,
- "license": "Apache-2.0 OR MIT",
- "optional": true,
- "os": [
- "linux"
- ],
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
"engines": {
- "node": ">= 10"
+ "node": ">=10"
}
},
- "node_modules/@tauri-apps/cli-linux-riscv64-gnu": {
- "version": "2.10.1",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-riscv64-gnu/-/cli-linux-riscv64-gnu-2.10.1.tgz",
- "integrity": "sha512-X0lvOVUg8PCVaoEtEAnpxmnkwlE1gcMDTqfhbefICKDnOTJ5Est3qL0SrWxizDackIOKBcvtpejrSiVpuJI1kw==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "license": "Apache-2.0 OR MIT",
- "optional": true,
- "os": [
- "linux"
- ],
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "license": "MIT",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
"engines": {
- "node": ">= 10"
+ "node": ">=8"
}
},
- "node_modules/@tauri-apps/cli-linux-x64-gnu": {
- "version": "2.10.1",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.10.1.tgz",
- "integrity": "sha512-2/12bEzsJS9fAKybxgicCDFxYD1WEI9kO+tlDwX5znWG2GwMBaiWcmhGlZ8fi+DMe9CXlcVarMTYc0L3REIRxw==",
- "cpu": [
- "x64"
- ],
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
"dev": true,
- "license": "Apache-2.0 OR MIT",
- "optional": true,
- "os": [
- "linux"
- ],
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
"engines": {
- "node": ">= 10"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/@tauri-apps/cli-linux-x64-musl": {
- "version": "2.10.1",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.10.1.tgz",
- "integrity": "sha512-Y8J0ZzswPz50UcGOFuXGEMrxbjwKSPgXftx5qnkuMs2rmwQB5ssvLb6tn54wDSYxe7S6vlLob9vt0VKuNOaCIQ==",
- "cpu": [
- "x64"
- ],
+ "node_modules/flat-cache": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
+ "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
"dev": true,
- "license": "Apache-2.0 OR MIT",
- "optional": true,
- "os": [
- "linux"
- ],
+ "license": "MIT",
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.4"
+ },
"engines": {
- "node": ">= 10"
+ "node": ">=16"
}
},
- "node_modules/@tauri-apps/cli-win32-arm64-msvc": {
- "version": "2.10.1",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.10.1.tgz",
- "integrity": "sha512-iSt5B86jHYAPJa/IlYw++SXtFPGnWtFJriHn7X0NFBVunF6zu9+/zOn8OgqIWSl8RgzhLGXQEEtGBdR4wzpVgg==",
- "cpu": [
- "arm64"
- ],
+ "node_modules/flatted": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.1.tgz",
+ "integrity": "sha512-IxfVbRFVlV8V/yRaGzk0UVIcsKKHMSfYw66T/u4nTwlWteQePsxe//LjudR1AMX4tZW3WFCh3Zqa/sjlqpbURQ==",
"dev": true,
- "license": "Apache-2.0 OR MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 10"
- }
+ "license": "ISC"
},
- "node_modules/@tauri-apps/cli-win32-ia32-msvc": {
- "version": "2.10.1",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.10.1.tgz",
- "integrity": "sha512-gXyxgEzsFegmnWywYU5pEBURkcFN/Oo45EAwvZrHMh+zUSEAvO5E8TXsgPADYm31d1u7OQU3O3HsYfVBf2moHw==",
- "cpu": [
- "ia32"
- ],
+ "node_modules/for-each": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
+ "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
"dev": true,
- "license": "Apache-2.0 OR MIT",
- "optional": true,
- "os": [
- "win32"
- ],
+ "license": "MIT",
+ "dependencies": {
+ "is-callable": "^1.2.7"
+ },
"engines": {
- "node": ">= 10"
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/@tauri-apps/cli-win32-x64-msvc": {
- "version": "2.10.1",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.10.1.tgz",
- "integrity": "sha512-6Cn7YpPFwzChy0ERz6djKEmUehWrYlM+xTaNzGPgZocw3BD7OfwfWHKVWxXzdjEW2KfKkHddfdxK1XXTYqBRLg==",
- "cpu": [
- "x64"
- ],
+ "node_modules/foreground-child": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
+ "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
"dev": true,
- "license": "Apache-2.0 OR MIT",
- "optional": true,
- "os": [
- "win32"
- ],
+ "license": "ISC",
+ "dependencies": {
+ "cross-spawn": "^7.0.6",
+ "signal-exit": "^4.0.1"
+ },
"engines": {
- "node": ">= 10"
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/@tauri-apps/plugin-dialog": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-dialog/-/plugin-dialog-2.6.0.tgz",
- "integrity": "sha512-q4Uq3eY87TdcYzXACiYSPhmpBA76shgmQswGkSVio4C82Sz2W4iehe9TnKYwbq7weHiL88Yw19XZm7v28+Micg==",
- "license": "MIT OR Apache-2.0",
+ "node_modules/fs-extra": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
+ "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@tauri-apps/api": "^2.8.0"
+ "at-least-node": "^1.0.0",
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
}
},
- "node_modules/@tauri-apps/plugin-fs": {
- "version": "2.4.5",
- "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-fs/-/plugin-fs-2.4.5.tgz",
- "integrity": "sha512-dVxWWGE6VrOxC7/jlhyE+ON/Cc2REJlM35R3PJX3UvFw2XwYhLGQVAIyrehenDdKjotipjYEVc4YjOl3qq90fA==",
- "license": "MIT OR Apache-2.0",
- "dependencies": {
- "@tauri-apps/api": "^2.8.0"
- }
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true,
+ "license": "ISC"
},
- "node_modules/@tauri-apps/plugin-notification": {
+ "node_modules/fsevents": {
"version": "2.3.3",
- "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-notification/-/plugin-notification-2.3.3.tgz",
- "integrity": "sha512-Zw+ZH18RJb41G4NrfHgIuofJiymusqN+q8fGUIIV7vyCH+5sSn5coqRv/MWB9qETsUs97vmU045q7OyseCV3Qg==",
- "license": "MIT OR Apache-2.0",
- "dependencies": {
- "@tauri-apps/api": "^2.8.0"
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
- "node_modules/@tauri-apps/plugin-opener": {
- "version": "2.5.3",
- "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-opener/-/plugin-opener-2.5.3.tgz",
- "integrity": "sha512-CCcUltXMOfUEArbf3db3kCE7Ggy1ExBEBl51Ko2ODJ6GDYHRp1nSNlQm5uNCFY5k7/ufaK5Ib3Du/Zir19IYQQ==",
- "license": "MIT OR Apache-2.0",
- "dependencies": {
- "@tauri-apps/api": "^2.8.0"
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/@tokenizer/inflate": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.4.1.tgz",
- "integrity": "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==",
+ "node_modules/function.prototype.name": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz",
+ "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "debug": "^4.4.3",
- "token-types": "^6.1.1"
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "functions-have-names": "^1.2.3",
+ "hasown": "^2.0.2",
+ "is-callable": "^1.2.7"
},
"engines": {
- "node": ">=18"
+ "node": ">= 0.4"
},
"funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Borewit"
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/@tokenizer/token": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz",
- "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==",
- "license": "MIT"
- },
- "node_modules/@transloadit/prettier-bytes": {
- "version": "0.3.5",
- "resolved": "https://registry.npmjs.org/@transloadit/prettier-bytes/-/prettier-bytes-0.3.5.tgz",
- "integrity": "sha512-xF4A3d/ZyX2LJWeQZREZQw+qFX4TGQ8bGVP97OLRt6sPO6T0TNHBFTuRHOJh7RNmYOBmQ9MHxpolD9bXihpuVA==",
- "license": "MIT"
- },
- "node_modules/@types/babel__core": {
- "version": "7.20.5",
- "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
- "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+ "node_modules/functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "@babel/parser": "^7.20.7",
- "@babel/types": "^7.20.7",
- "@types/babel__generator": "*",
- "@types/babel__template": "*",
- "@types/babel__traverse": "*"
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/@types/babel__generator": {
- "version": "7.27.0",
- "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
- "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
+ "node_modules/generator-function": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz",
+ "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "@babel/types": "^7.0.0"
+ "engines": {
+ "node": ">= 0.4"
}
},
- "node_modules/@types/babel__template": {
- "version": "7.4.4",
- "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
- "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "@babel/parser": "^7.1.0",
- "@babel/types": "^7.0.0"
+ "engines": {
+ "node": ">=6.9.0"
}
},
- "node_modules/@types/babel__traverse": {
- "version": "7.28.0",
- "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
- "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.28.2"
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/@types/estree": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
- "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
- "license": "MIT"
+ "node_modules/get-nonce": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz",
+ "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
},
- "node_modules/@types/istanbul-lib-coverage": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
- "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==",
+ "node_modules/get-own-enumerable-property-symbols": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz",
+ "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==",
"dev": true,
- "license": "MIT"
+ "license": "ISC"
},
- "node_modules/@types/istanbul-lib-report": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz",
- "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==",
+ "node_modules/get-package-type": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
+ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "@types/istanbul-lib-coverage": "*"
+ "engines": {
+ "node": ">=8.0.0"
}
},
- "node_modules/@types/istanbul-reports": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz",
- "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==",
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@types/istanbul-lib-report": "*"
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
}
},
- "node_modules/@types/jasmine": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-6.0.0.tgz",
- "integrity": "sha512-18lgGsLmEh3VJk9eZ5wAjTISxdqzl6YOwu8UdMpolajN57QOCNbl+AbHUd+Yu9ItrsFdB+c8LSZSGNg8nHaguw==",
+ "node_modules/get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
},
- "node_modules/@types/jest": {
- "version": "30.0.0",
- "resolved": "https://registry.npmjs.org/@types/jest/-/jest-30.0.0.tgz",
- "integrity": "sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==",
+ "node_modules/get-symbol-description": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz",
+ "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "expect": "^30.0.0",
- "pretty-format": "^30.0.0"
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/glob": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz",
+ "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "foreground-child": "^3.3.1",
+ "jackspeak": "^4.1.1",
+ "minimatch": "^10.1.1",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^2.0.0"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
}
},
- "node_modules/@types/json-schema": {
- "version": "7.0.15",
- "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
- "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/lodash": {
- "version": "4.17.24",
- "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.24.tgz",
- "integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==",
+ "node_modules/globals": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
+ "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
"dev": true,
- "license": "MIT"
- },
- "node_modules/@types/node": {
- "version": "25.5.0",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.0.tgz",
- "integrity": "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==",
- "devOptional": true,
"license": "MIT",
- "dependencies": {
- "undici-types": "~7.18.0"
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/@types/react": {
- "version": "19.2.14",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz",
- "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==",
- "devOptional": true,
+ "node_modules/globalthis": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
+ "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "csstype": "^3.2.2"
+ "define-properties": "^1.2.1",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/@types/react-dom": {
- "version": "19.2.3",
- "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
- "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
- "devOptional": true,
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "dev": true,
"license": "MIT",
- "peerDependencies": {
- "@types/react": "^19.2.0"
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/@types/resolve": {
- "version": "1.20.2",
- "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
- "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/stack-utils": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
- "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"dev": true,
- "license": "MIT"
- },
- "node_modules/@types/trusted-types": {
- "version": "2.0.7",
- "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
- "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
- "devOptional": true,
- "license": "MIT"
+ "license": "ISC"
},
- "node_modules/@types/yargs": {
- "version": "17.0.33",
- "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
- "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==",
+ "node_modules/handlebars": {
+ "version": "4.7.8",
+ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz",
+ "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@types/yargs-parser": "*"
+ "minimist": "^1.2.5",
+ "neo-async": "^2.6.2",
+ "source-map": "^0.6.1",
+ "wordwrap": "^1.0.0"
+ },
+ "bin": {
+ "handlebars": "bin/handlebars"
+ },
+ "engines": {
+ "node": ">=0.4.7"
+ },
+ "optionalDependencies": {
+ "uglify-js": "^3.1.4"
}
},
- "node_modules/@types/yargs-parser": {
- "version": "21.0.3",
- "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz",
- "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
+ "node_modules/handlebars/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true,
- "license": "MIT"
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "node_modules/@typescript-eslint/eslint-plugin": {
- "version": "8.57.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.57.0.tgz",
- "integrity": "sha512-qeu4rTHR3/IaFORbD16gmjq9+rEs9fGKdX0kF6BKSfi+gCuG3RCKLlSBYzn/bGsY9Tj7KE/DAQStbp8AHJGHEQ==",
+ "node_modules/has-bigints": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz",
+ "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "@eslint-community/regexpp": "^4.12.2",
- "@typescript-eslint/scope-manager": "8.57.0",
- "@typescript-eslint/type-utils": "8.57.0",
- "@typescript-eslint/utils": "8.57.0",
- "@typescript-eslint/visitor-keys": "8.57.0",
- "ignore": "^7.0.5",
- "natural-compare": "^1.4.0",
- "ts-api-utils": "^2.4.0"
- },
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "node": ">= 0.4"
},
"funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "@typescript-eslint/parser": "^8.57.0",
- "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
- "typescript": ">=4.8.4 <6.0.0"
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/@typescript-eslint/parser": {
- "version": "8.57.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.57.0.tgz",
- "integrity": "sha512-XZzOmihLIr8AD1b9hL9ccNMzEMWt/dE2u7NyTY9jJG6YNiNthaD5XtUHVF2uCXZ15ng+z2hT3MVuxnUYhq6k1g==",
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "@typescript-eslint/scope-manager": "8.57.0",
- "@typescript-eslint/types": "8.57.0",
- "@typescript-eslint/typescript-estree": "8.57.0",
- "@typescript-eslint/visitor-keys": "8.57.0",
- "debug": "^4.4.3"
- },
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
- "typescript": ">=4.8.4 <6.0.0"
+ "node": ">=8"
}
},
- "node_modules/@typescript-eslint/project-service": {
- "version": "8.57.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.57.0.tgz",
- "integrity": "sha512-pR+dK0BlxCLxtWfaKQWtYr7MhKmzqZxuii+ZjuFlZlIGRZm22HnXFqa2eY+90MUz8/i80YJmzFGDUsi8dMOV5w==",
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/tsconfig-utils": "^8.57.0",
- "@typescript-eslint/types": "^8.57.0",
- "debug": "^4.4.3"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "es-define-property": "^1.0.0"
},
"funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4 <6.0.0"
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/@typescript-eslint/scope-manager": {
- "version": "8.57.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.57.0.tgz",
- "integrity": "sha512-nvExQqAHF01lUM66MskSaZulpPL5pgy5hI5RfrxviLgzZVffB5yYzw27uK/ft8QnKXI2X0LBrHJFr1TaZtAibw==",
+ "node_modules/has-proto": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz",
+ "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.57.0",
- "@typescript-eslint/visitor-keys": "8.57.0"
+ "dunder-proto": "^1.0.0"
},
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "node": ">= 0.4"
},
"funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/@typescript-eslint/tsconfig-utils": {
- "version": "8.57.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.57.0.tgz",
- "integrity": "sha512-LtXRihc5ytjJIQEH+xqjB0+YgsV4/tW35XKX3GTZHpWtcC8SPkT/d4tqdf1cKtesryHm2bgp6l555NYcT2NLvA==",
+ "node_modules/has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
"dev": true,
"license": "MIT",
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "node": ">= 0.4"
},
"funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4 <6.0.0"
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/@typescript-eslint/type-utils": {
- "version": "8.57.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.57.0.tgz",
- "integrity": "sha512-yjgh7gmDcJ1+TcEg8x3uWQmn8ifvSupnPfjP21twPKrDP/pTHlEQgmKcitzF/rzPSmv7QjJ90vRpN4U+zoUjwQ==",
+ "node_modules/has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.57.0",
- "@typescript-eslint/typescript-estree": "8.57.0",
- "@typescript-eslint/utils": "8.57.0",
- "debug": "^4.4.3",
- "ts-api-utils": "^2.4.0"
+ "has-symbols": "^1.0.3"
},
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "node": ">= 0.4"
},
"funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
- "typescript": ">=4.8.4 <6.0.0"
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/@typescript-eslint/types": {
- "version": "8.57.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.57.0.tgz",
- "integrity": "sha512-dTLI8PEXhjUC7B9Kre+u0XznO696BhXcTlOn0/6kf1fHaQW8+VjJAVHJ3eTI14ZapTxdkOmc80HblPQLaEeJdg==",
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"dev": true,
"license": "MIT",
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "dependencies": {
+ "function-bind": "^1.1.2"
},
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
+ "engines": {
+ "node": ">= 0.4"
}
},
- "node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.57.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.57.0.tgz",
- "integrity": "sha512-m7faHcyVg0BT3VdYTlX8GdJEM7COexXxS6KqGopxdtkQRvBanK377QDHr4W/vIPAR+ah9+B/RclSW5ldVniO1Q==",
+ "node_modules/html-encoding-sniffer": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz",
+ "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/project-service": "8.57.0",
- "@typescript-eslint/tsconfig-utils": "8.57.0",
- "@typescript-eslint/types": "8.57.0",
- "@typescript-eslint/visitor-keys": "8.57.0",
- "debug": "^4.4.3",
- "minimatch": "^10.2.2",
- "semver": "^7.7.3",
- "tinyglobby": "^0.2.15",
- "ts-api-utils": "^2.4.0"
+ "whatwg-encoding": "^3.1.1"
},
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4 <6.0.0"
+ "node": ">=18"
}
},
- "node_modules/@typescript-eslint/utils": {
- "version": "8.57.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.57.0.tgz",
- "integrity": "sha512-5iIHvpD3CZe06riAsbNxxreP+MuYgVUsV0n4bwLH//VJmgtt54sQeY2GszntJ4BjYCpMzrfVh2SBnUQTtys2lQ==",
+ "node_modules/html-escaper": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
"dev": true,
+ "license": "MIT"
+ },
+ "node_modules/html-parse-stringify": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz",
+ "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==",
"license": "MIT",
"dependencies": {
- "@eslint-community/eslint-utils": "^4.9.1",
- "@typescript-eslint/scope-manager": "8.57.0",
- "@typescript-eslint/types": "8.57.0",
- "@typescript-eslint/typescript-estree": "8.57.0"
+ "void-elements": "3.1.0"
+ }
+ },
+ "node_modules/http-proxy-agent": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
+ "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.0",
+ "debug": "^4.3.4"
},
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
- "typescript": ">=4.8.4 <6.0.0"
+ "node": ">= 14"
}
},
- "node_modules/@typescript-eslint/visitor-keys": {
- "version": "8.57.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.57.0.tgz",
- "integrity": "sha512-zm6xx8UT/Xy2oSr2ZXD0pZo7Jx2XsCoID2IUh9YSTFRu7z+WdwYTRk6LhUftm1crwqbuoF6I8zAFeCMw0YjwDg==",
+ "node_modules/https-proxy-agent": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
+ "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.57.0",
- "eslint-visitor-keys": "^5.0.0"
+ "agent-base": "^7.1.2",
+ "debug": "4"
},
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
+ "node": ">= 14"
}
},
- "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
- "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
+ "node_modules/human-signals": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
"dev": true,
"license": "Apache-2.0",
"engines": {
- "node": "^20.19.0 || ^22.13.0 || >=24"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
+ "node": ">=10.17.0"
}
},
- "node_modules/@uppy/components": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@uppy/components/-/components-1.2.0.tgz",
- "integrity": "sha512-rtIr+77Rw/q5Vw++xazF1dCg2d4A4zT9CV+ZyN8Rsx8xiIr2CxCR4TaHHBy+WeC0b7Mk6yNuJ0wUa34tFJ6pKg==",
+ "node_modules/i18next": {
+ "version": "25.8.18",
+ "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.8.18.tgz",
+ "integrity": "sha512-lzY5X83BiL5AP77+9DydbrqkQHFN9hUzWGjqjLpPcp5ZOzuu1aSoKaU3xbBLSjWx9dAzW431y+d+aogxOZaKRA==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://locize.com"
+ },
+ {
+ "type": "individual",
+ "url": "https://locize.com/i18next.html"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
+ }
+ ],
"license": "MIT",
"dependencies": {
- "clsx": "^2.1.1",
- "dequal": "^2.0.3",
- "preact": "^10.26.10",
- "pretty-bytes": "^6.1.1"
+ "@babel/runtime": "^7.28.6"
},
"peerDependencies": {
- "@uppy/core": "^5.2.0",
- "@uppy/image-editor": "^4.2.0",
- "@uppy/screen-capture": "^5.1.0",
- "@uppy/webcam": "^5.1.0"
+ "typescript": "^5"
},
"peerDependenciesMeta": {
- "@uppy/image-editor": {
- "optional": true
- },
- "@uppy/screen-capture": {
- "optional": true
- },
- "@uppy/webcam": {
+ "typescript": {
"optional": true
}
}
},
- "node_modules/@uppy/core": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/@uppy/core/-/core-5.2.0.tgz",
- "integrity": "sha512-uvfNyz4cnaplt7LYJmEZHuqOuav0tKp4a9WKJIaH6iIj7XiqYvS2J5SEByexAlUFlzefOAyjzj4Ja2dd/8aMrw==",
+ "node_modules/i18next-browser-languagedetector": {
+ "version": "8.2.1",
+ "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.2.1.tgz",
+ "integrity": "sha512-bZg8+4bdmaOiApD7N7BPT9W8MLZG+nPTOFlLiJiT8uzKXFjhxw4v2ierCXOwB5sFDMtuA5G4kgYZ0AznZxQ/cw==",
"license": "MIT",
"dependencies": {
- "@transloadit/prettier-bytes": "^0.3.4",
- "@uppy/store-default": "^5.0.0",
- "@uppy/utils": "^7.1.4",
- "lodash": "^4.17.21",
- "mime-match": "^1.0.2",
- "namespace-emitter": "^2.0.1",
- "nanoid": "^5.0.9",
- "preact": "^10.5.13"
+ "@babel/runtime": "^7.23.2"
}
},
- "node_modules/@uppy/dashboard": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/@uppy/dashboard/-/dashboard-5.1.1.tgz",
- "integrity": "sha512-6H/xVvhhdfwp1+FRMp2C+tudyaedqD5+LMDB8Iw20k9+QCL1eGzOh4wXm6MCqJtNfQ1tLaprGMG1jlo7yS/uyw==",
+ "node_modules/i18next-http-backend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-3.0.2.tgz",
+ "integrity": "sha512-PdlvPnvIp4E1sYi46Ik4tBYh/v/NbYfFFgTjkwFl0is8A18s7/bx9aXqsrOax9WUbeNS6mD2oix7Z0yGGf6m5g==",
"license": "MIT",
"dependencies": {
- "@transloadit/prettier-bytes": "^0.3.4",
- "@uppy/provider-views": "^5.2.2",
- "@uppy/thumbnail-generator": "^5.1.0",
- "@uppy/utils": "^7.1.5",
- "classnames": "^2.2.6",
- "lodash": "^4.17.23",
- "nanoid": "^5.0.9",
- "preact": "^10.26.10",
- "shallow-equal": "^3.0.0"
- },
- "peerDependencies": {
- "@uppy/core": "^5.2.0"
+ "cross-fetch": "4.0.0"
}
},
- "node_modules/@uppy/provider-views": {
- "version": "5.2.2",
- "resolved": "https://registry.npmjs.org/@uppy/provider-views/-/provider-views-5.2.2.tgz",
- "integrity": "sha512-NAazIJ5sjrAc6++CeJ/u9dB5gDaaAOLHrYeEmWs/HqLlftlIinRZOybnyzJRXwI8jWI/FK5moluzt2HXu6dPQQ==",
+ "node_modules/ico-endec": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/ico-endec/-/ico-endec-0.1.6.tgz",
+ "integrity": "sha512-ZdLU38ZoED3g1j3iEyzcQj+wAkY2xfWNkymszfJPoxucIUhK7NayQ+/C4Kv0nDFMIsbtbEHldv3V8PU494/ueQ==",
+ "dev": true,
+ "license": "MPL-2.0"
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@uppy/utils": "^7.1.5",
- "classnames": "^2.2.6",
- "lodash": "^4.17.21",
- "nanoid": "^5.0.9",
- "p-queue": "^8.0.0",
- "preact": "^10.5.13"
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
},
- "peerDependencies": {
- "@uppy/core": "^5.2.0"
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "node_modules/@uppy/react": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/@uppy/react/-/react-5.2.0.tgz",
- "integrity": "sha512-6lzPutg2XGavs7P6ALmqOBPitd/Jqi3r1jCJQD5nx8xtNlBRwvlBR6hrZgo8XOI9cR+OaNDrJ0vEFxXDWb04Ag==",
- "license": "MIT",
- "dependencies": {
- "@uppy/components": "^1.2.0",
- "preact": "^10.26.10",
- "use-sync-external-store": "^1.3.0"
- },
- "peerDependencies": {
- "@uppy/core": "^5.2.0",
- "@uppy/dashboard": "^5.1.1",
- "@uppy/screen-capture": "^5.1.0",
- "@uppy/status-bar": "^5.1.0",
- "@uppy/webcam": "^5.1.0",
- "react": "^18.0.0 || ^19.0.0",
- "react-dom": "^18.0.0 || ^19.0.0"
- },
- "peerDependenciesMeta": {
- "@uppy/dashboard": {
- "optional": true
- },
- "@uppy/screen-capture": {
- "optional": true
+ "node_modules/idb": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz",
+ "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
},
- "@uppy/status-bar": {
- "optional": true
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
},
- "@uppy/webcam": {
- "optional": true
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
}
- }
- },
- "node_modules/@uppy/store-default": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/@uppy/store-default/-/store-default-5.0.0.tgz",
- "integrity": "sha512-hQtCSQ1yGiaval/wVYUWquYGDJ+bpQ7e4FhUUAsRQz1x1K+o7NBtjfp63O9I4Ks1WRoKunpkarZ+as09l02cPw==",
- "license": "MIT"
+ ],
+ "license": "BSD-3-Clause"
},
- "node_modules/@uppy/thumbnail-generator": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/@uppy/thumbnail-generator/-/thumbnail-generator-5.1.0.tgz",
- "integrity": "sha512-QAKJHHkMrD/30GOyUb5U9HyJ7Ie3jiMLp4pVdw27PoA4pNV7fDQz0tyDeRPj2H+BWPEB1NsTSSfHI2pjHNI+OQ==",
- "license": "MIT",
- "dependencies": {
- "@uppy/utils": "^7.1.4",
- "exifr": "^7.0.0"
- },
- "peerDependencies": {
- "@uppy/core": "^5.2.0"
+ "node_modules/ignore": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
+ "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
}
},
- "node_modules/@uppy/utils": {
- "version": "7.1.5",
- "resolved": "https://registry.npmjs.org/@uppy/utils/-/utils-7.1.5.tgz",
- "integrity": "sha512-Vz4WGTjef6WebECGur4clWjpkET4o3bdvPMj1m2sD5cL+dTt69m+FIE5h5JD3HBMLEPTXPVkrXGMIFcbOYC12Q==",
+ "node_modules/import-fresh": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "lodash": "^4.17.21",
- "preact": "^10.5.13"
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/@vite-pwa/assets-generator": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/@vite-pwa/assets-generator/-/assets-generator-1.0.2.tgz",
- "integrity": "sha512-MCbrb508JZHqe7bUibmZj/lyojdhLRnfkmyXnkrCM2zVrjTgL89U8UEfInpKTvPeTnxsw2hmyZxnhsdNR6yhwg==",
+ "node_modules/import-local": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz",
+ "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "cac": "^6.7.14",
- "colorette": "^2.0.20",
- "consola": "^3.4.2",
- "sharp": "^0.33.5",
- "sharp-ico": "^0.1.5",
- "unconfig": "^7.3.1"
+ "pkg-dir": "^4.2.0",
+ "resolve-cwd": "^3.0.0"
},
"bin": {
- "pwa-assets-generator": "bin/pwa-assets-generator.mjs"
+ "import-local-fixture": "fixtures/cli.js"
},
"engines": {
- "node": ">=16.14.0"
+ "node": ">=8"
},
"funding": {
- "url": "https://github.com/sponsors/antfu"
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/@vitejs/plugin-react": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.2.0.tgz",
- "integrity": "sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw==",
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
"dev": true,
"license": "MIT",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
+ "dev": true,
+ "license": "ISC",
"dependencies": {
- "@babel/core": "^7.29.0",
- "@babel/plugin-transform-react-jsx-self": "^7.27.1",
- "@babel/plugin-transform-react-jsx-source": "^7.27.1",
- "@rolldown/pluginutils": "1.0.0-rc.3",
- "@types/babel__core": "^7.20.5",
- "react-refresh": "^0.18.0"
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/internal-slot": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
+ "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "hasown": "^2.0.2",
+ "side-channel": "^1.1.0"
},
"engines": {
- "node": "^20.19.0 || >=22.12.0"
- },
- "peerDependencies": {
- "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
+ "node": ">= 0.4"
}
},
- "node_modules/@web-scrobbler/metadata-filter": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/@web-scrobbler/metadata-filter/-/metadata-filter-3.2.0.tgz",
- "integrity": "sha512-K2Wkq9AOJkgj4Hk9g0flKnNWYkJy1GTPpHTgpNLU5OXaXgqPKLyrtb62M1cIxMN3ESH6XGvPKM92VEl/Gc3Rog==",
+ "node_modules/is-array-buffer": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
+ "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==",
+ "dev": true,
"license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "get-intrinsic": "^1.2.6"
+ },
"engines": {
- "node": ">=10.0.0"
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/acorn": {
- "version": "8.15.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
- "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
- "devOptional": true,
+ "node_modules/is-arrayish": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz",
+ "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/is-async-function": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz",
+ "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==",
+ "dev": true,
"license": "MIT",
- "bin": {
- "acorn": "bin/acorn"
+ "dependencies": {
+ "async-function": "^1.0.0",
+ "call-bound": "^1.0.3",
+ "get-proto": "^1.0.1",
+ "has-tostringtag": "^1.0.2",
+ "safe-regex-test": "^1.1.0"
},
"engines": {
- "node": ">=0.4.0"
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/acorn-jsx": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
- "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "node_modules/is-bigint": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz",
+ "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==",
"dev": true,
"license": "MIT",
- "peerDependencies": {
- "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ "dependencies": {
+ "has-bigints": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/ajv": {
- "version": "6.14.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz",
- "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==",
+ "node_modules/is-boolean-object": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz",
+ "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==",
"dev": true,
"license": "MIT",
"dependencies": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
- "type": "github",
- "url": "https://github.com/sponsors/epoberezkin"
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/ansi-regex": {
- "version": "6.2.2",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
- "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
+ "node_modules/is-callable": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=12"
+ "node": ">= 0.4"
},
"funding": {
- "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "node_modules/is-core-module": {
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
+ "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "color-convert": "^2.0.1"
+ "hasown": "^2.0.2"
},
"engines": {
- "node": ">=8"
+ "node": ">= 0.4"
},
"funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/argparse": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
- "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "node_modules/is-data-view": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz",
+ "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==",
"dev": true,
- "license": "Python-2.0"
- },
- "node_modules/aria-hidden": {
- "version": "1.2.6",
- "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz",
- "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==",
"license": "MIT",
"dependencies": {
- "tslib": "^2.0.0"
+ "call-bound": "^1.0.2",
+ "get-intrinsic": "^1.2.6",
+ "is-typed-array": "^1.1.13"
},
"engines": {
- "node": ">=10"
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/array-buffer-byte-length": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz",
- "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==",
+ "node_modules/is-date-object": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz",
+ "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.3",
- "is-array-buffer": "^3.0.5"
+ "call-bound": "^1.0.2",
+ "has-tostringtag": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
@@ -5767,21 +11021,24 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/array-includes": {
- "version": "3.1.9",
- "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz",
- "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==",
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-finalizationregistry": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz",
+ "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.4",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.24.0",
- "es-object-atoms": "^1.1.1",
- "get-intrinsic": "^1.3.0",
- "is-string": "^1.1.1",
- "math-intrinsics": "^1.1.0"
+ "call-bound": "^1.0.3"
},
"engines": {
"node": ">= 0.4"
@@ -5790,57 +11047,38 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/array.prototype.findlast": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz",
- "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==",
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.7",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.23.2",
- "es-errors": "^1.3.0",
- "es-object-atoms": "^1.0.0",
- "es-shim-unscopables": "^1.0.2"
- },
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": ">=8"
}
},
- "node_modules/array.prototype.flat": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz",
- "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==",
+ "node_modules/is-generator-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz",
+ "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.23.5",
- "es-shim-unscopables": "^1.0.2"
- },
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": ">=6"
}
},
- "node_modules/array.prototype.flatmap": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz",
- "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==",
+ "node_modules/is-generator-function": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz",
+ "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bind": "^1.0.8",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.23.5",
- "es-shim-unscopables": "^1.0.2"
+ "call-bound": "^1.0.4",
+ "generator-function": "^2.0.0",
+ "get-proto": "^1.0.1",
+ "has-tostringtag": "^1.0.2",
+ "safe-regex-test": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
@@ -5849,38 +11087,25 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/array.prototype.tosorted": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz",
- "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==",
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bind": "^1.0.7",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.23.3",
- "es-errors": "^1.3.0",
- "es-shim-unscopables": "^1.0.2"
+ "is-extglob": "^2.1.1"
},
"engines": {
- "node": ">= 0.4"
+ "node": ">=0.10.0"
}
},
- "node_modules/arraybuffer.prototype.slice": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz",
- "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==",
+ "node_modules/is-map": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
+ "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "array-buffer-byte-length": "^1.0.1",
- "call-bind": "^1.0.8",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.23.5",
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.6",
- "is-array-buffer": "^3.0.4"
- },
"engines": {
"node": ">= 0.4"
},
@@ -5888,41 +11113,44 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/async": {
- "version": "3.2.6",
- "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
- "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==",
+ "node_modules/is-module": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
+ "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==",
"dev": true,
"license": "MIT"
},
- "node_modules/async-function": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz",
- "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==",
+ "node_modules/is-negative-zero": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz",
+ "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/at-least-node": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
- "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
- "dev": true,
- "license": "ISC",
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "license": "MIT",
"engines": {
- "node": ">= 4.0.0"
+ "node": ">=0.12.0"
}
},
- "node_modules/available-typed-arrays": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
- "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
+ "node_modules/is-number-object": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz",
+ "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "possible-typed-array-names": "^1.0.0"
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
@@ -5931,160 +11159,151 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/babel-plugin-polyfill-corejs2": {
- "version": "0.4.14",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz",
- "integrity": "sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==",
+ "node_modules/is-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
+ "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "@babel/compat-data": "^7.27.7",
- "@babel/helper-define-polyfill-provider": "^0.6.5",
- "semver": "^6.3.1"
- },
- "peerDependencies": {
- "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "node_modules/is-potential-custom-element-name": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
+ "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==",
"dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- }
+ "license": "MIT"
},
- "node_modules/babel-plugin-polyfill-corejs3": {
- "version": "0.13.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz",
- "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==",
+ "node_modules/is-regex": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
+ "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-define-polyfill-provider": "^0.6.5",
- "core-js-compat": "^3.43.0"
+ "call-bound": "^1.0.2",
+ "gopd": "^1.2.0",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
},
- "peerDependencies": {
- "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/babel-plugin-polyfill-regenerator": {
- "version": "0.6.5",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.5.tgz",
- "integrity": "sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==",
+ "node_modules/is-regexp": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz",
+ "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "@babel/helper-define-polyfill-provider": "^0.6.5"
- },
- "peerDependencies": {
- "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "node_modules/is-set": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz",
+ "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
},
- "node_modules/baseline-browser-mapping": {
- "version": "2.9.11",
- "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.11.tgz",
- "integrity": "sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==",
+ "node_modules/is-shared-array-buffer": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz",
+ "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==",
"dev": true,
- "license": "Apache-2.0",
- "bin": {
- "baseline-browser-mapping": "dist/cli.js"
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/brace-expansion": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
- "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "node_modules/is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0"
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/braces": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
- "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "node_modules/is-string": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz",
+ "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "fill-range": "^7.1.1"
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
},
"engines": {
- "node": ">=8"
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/browserslist": {
- "version": "4.28.1",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz",
- "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==",
+ "node_modules/is-symbol": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz",
+ "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==",
"dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
"license": "MIT",
"dependencies": {
- "baseline-browser-mapping": "^2.9.0",
- "caniuse-lite": "^1.0.30001759",
- "electron-to-chromium": "^1.5.263",
- "node-releases": "^2.0.27",
- "update-browserslist-db": "^1.2.0"
- },
- "bin": {
- "browserslist": "cli.js"
+ "call-bound": "^1.0.2",
+ "has-symbols": "^1.1.0",
+ "safe-regex-test": "^1.1.0"
},
"engines": {
- "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/buffer-from": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
- "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
- "devOptional": true,
- "license": "MIT"
- },
- "node_modules/cac": {
- "version": "6.7.14",
- "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
- "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
+ "node_modules/is-typed-array": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
+ "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "which-typed-array": "^1.1.16"
+ },
"engines": {
- "node": ">=8"
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/call-bind": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
- "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
+ "node_modules/is-weakmap": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
+ "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.0",
- "es-define-property": "^1.0.0",
- "get-intrinsic": "^1.2.4",
- "set-function-length": "^1.2.2"
- },
"engines": {
"node": ">= 0.4"
},
@@ -6092,29 +11311,31 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/call-bind-apply-helpers": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
- "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "node_modules/is-weakref": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz",
+ "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==",
"dev": true,
"license": "MIT",
"dependencies": {
- "es-errors": "^1.3.0",
- "function-bind": "^1.1.2"
+ "call-bound": "^1.0.3"
},
"engines": {
"node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/call-bound": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
- "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+ "node_modules/is-weakset": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz",
+ "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bind-apply-helpers": "^1.0.2",
- "get-intrinsic": "^1.3.0"
+ "call-bound": "^1.0.3",
+ "get-intrinsic": "^1.2.6"
},
"engines": {
"node": ">= 0.4"
@@ -6123,1604 +11344,1673 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/callsites": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
- "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "node_modules/isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
"dev": true,
- "license": "MIT",
+ "license": "MIT"
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/istanbul-lib-coverage": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
+ "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
"engines": {
- "node": ">=6"
+ "node": ">=8"
}
},
- "node_modules/caniuse-lite": {
- "version": "1.0.30001762",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001762.tgz",
- "integrity": "sha512-PxZwGNvH7Ak8WX5iXzoK1KPZttBXNPuaOvI2ZYU7NrlM+d9Ov+TUvlLOBNGzVXAntMSMMlJPd+jY6ovrVjSmUw==",
+ "node_modules/istanbul-lib-instrument": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz",
+ "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==",
"dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "CC-BY-4.0"
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/core": "^7.23.9",
+ "@babel/parser": "^7.23.9",
+ "@istanbuljs/schema": "^0.1.3",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": ">=10"
+ }
},
- "node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "node_modules/istanbul-lib-report": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
+ "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
"dev": true,
- "license": "MIT",
+ "license": "BSD-3-Clause",
"dependencies": {
- "ansi-styles": "^4.1.0",
+ "istanbul-lib-coverage": "^3.0.0",
+ "make-dir": "^4.0.0",
"supports-color": "^7.1.0"
},
"engines": {
"node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-source-maps": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz",
+ "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "debug": "^4.1.1",
+ "istanbul-lib-coverage": "^3.0.0",
+ "source-map": "^0.6.1"
},
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
+ "engines": {
+ "node": ">=10"
}
},
- "node_modules/ci-info": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz",
- "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==",
+ "node_modules/istanbul-lib-source-maps/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/sibiraj-s"
- }
- ],
- "license": "MIT",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/istanbul-reports": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz",
+ "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "html-escaper": "^2.0.0",
+ "istanbul-lib-report": "^3.0.0"
+ },
"engines": {
"node": ">=8"
}
},
- "node_modules/classnames": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz",
- "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==",
- "license": "MIT"
+ "node_modules/iterator.prototype": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz",
+ "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.6",
+ "get-proto": "^1.0.0",
+ "has-symbols": "^1.1.0",
+ "set-function-name": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
},
- "node_modules/cloc": {
- "version": "2.11.0",
- "resolved": "https://registry.npmjs.org/cloc/-/cloc-2.11.0.tgz",
- "integrity": "sha512-+mxuCHo7ESOQadlsyMjmPZ4hGBtvQzmNGHfLdBNvXKbnRhtmOTslU4XF2cyFSaOCHaaF26ba2CGjU6lpeIFB0w==",
+ "node_modules/jackspeak": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz",
+ "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==",
"dev": true,
- "license": "GPL-2.0",
- "bin": {
- "cloc": "lib/cloc"
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/clsx": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
- "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
- "license": "MIT",
+ "node_modules/jake": {
+ "version": "10.9.4",
+ "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz",
+ "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "async": "^3.2.6",
+ "filelist": "^1.0.4",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "jake": "bin/cli.js"
+ },
"engines": {
- "node": ">=6"
+ "node": ">=10"
}
},
- "node_modules/color": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
- "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
+ "node_modules/jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz",
+ "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "color-convert": "^2.0.1",
- "color-string": "^1.9.0"
+ "@jest/core": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "import-local": "^3.0.2",
+ "jest-cli": "^29.7.0"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
},
"engines": {
- "node": ">=12.5.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
}
},
- "node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "node_modules/jest-changed-files": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz",
+ "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "color-name": "~1.1.4"
+ "execa": "^5.0.0",
+ "jest-util": "^29.7.0",
+ "p-limit": "^3.1.0"
},
"engines": {
- "node": ">=7.0.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/color-string": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
- "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
+ "node_modules/jest-changed-files/node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "color-name": "^1.0.0",
- "simple-swizzle": "^0.2.2"
+ "@sinclair/typebox": "^0.27.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/colorette": {
- "version": "2.0.20",
- "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
- "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/commander": {
- "version": "2.20.3",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
- "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
- "devOptional": true,
- "license": "MIT"
- },
- "node_modules/common-tags": {
- "version": "1.8.2",
- "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz",
- "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==",
+ "node_modules/jest-changed-files/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ },
"engines": {
- "node": ">=4.0.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "node_modules/jest-changed-files/node_modules/@sinclair/typebox": {
+ "version": "0.27.10",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
+ "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
"dev": true,
"license": "MIT"
},
- "node_modules/consola": {
- "version": "3.4.2",
- "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz",
- "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==",
+ "node_modules/jest-changed-files/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
"dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
"license": "MIT",
"engines": {
- "node": "^14.18.0 || >=16.10.0"
+ "node": ">=8"
}
},
- "node_modules/content-type": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
- "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+ "node_modules/jest-changed-files/node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
+ "dev": true,
"license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
+ },
"engines": {
- "node": ">= 0.6"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/convert-source-map": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
- "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/core-js-compat": {
- "version": "3.47.0",
- "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.47.0.tgz",
- "integrity": "sha512-IGfuznZ/n7Kp9+nypamBhvwdwLsW6KC8IOaURw2doAK5e98AG3acVLdh0woOnEqCfUtS+Vu882JE4k/DAm3ItQ==",
+ "node_modules/jest-changed-files/node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "browserslist": "^4.28.0"
+ "engines": {
+ "node": ">=8.6"
},
"funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/core-js"
+ "url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/cross-env": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-10.1.0.tgz",
- "integrity": "sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw==",
+ "node_modules/jest-circus": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz",
+ "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@epic-web/invariant": "^1.0.0",
- "cross-spawn": "^7.0.6"
- },
- "bin": {
- "cross-env": "dist/bin/cross-env.js",
- "cross-env-shell": "dist/bin/cross-env-shell.js"
+ "@jest/environment": "^29.7.0",
+ "@jest/expect": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "co": "^4.6.0",
+ "dedent": "^1.0.0",
+ "is-generator-fn": "^2.0.0",
+ "jest-each": "^29.7.0",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "p-limit": "^3.1.0",
+ "pretty-format": "^29.7.0",
+ "pure-rand": "^6.0.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
},
"engines": {
- "node": ">=20"
- }
- },
- "node_modules/cross-fetch": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz",
- "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==",
- "license": "MIT",
- "dependencies": {
- "node-fetch": "^2.6.12"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/cross-spawn": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
- "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "node_modules/jest-circus/node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "path-key": "^3.1.0",
- "shebang-command": "^2.0.0",
- "which": "^2.0.1"
+ "@sinclair/typebox": "^0.27.8"
},
"engines": {
- "node": ">= 8"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/crypto-random-string": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
- "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==",
+ "node_modules/jest-circus/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ },
"engines": {
- "node": ">=8"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/csstype": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
- "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
- "devOptional": true,
+ "node_modules/jest-circus/node_modules/@sinclair/typebox": {
+ "version": "0.27.10",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
+ "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
+ "dev": true,
"license": "MIT"
},
- "node_modules/data-view-buffer": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
- "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==",
+ "node_modules/jest-circus/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3",
- "es-errors": "^1.3.0",
- "is-data-view": "^1.0.2"
- },
"engines": {
- "node": ">= 0.4"
+ "node": ">=10"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/data-view-byte-length": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz",
- "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==",
+ "node_modules/jest-circus/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
"dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
"license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3",
- "es-errors": "^1.3.0",
- "is-data-view": "^1.0.2"
- },
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/inspect-js"
+ "node": ">=8"
}
},
- "node_modules/data-view-byte-offset": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz",
- "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==",
+ "node_modules/jest-circus/node_modules/jest-diff": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz",
+ "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.2",
- "es-errors": "^1.3.0",
- "is-data-view": "^1.0.1"
+ "chalk": "^4.0.0",
+ "diff-sequences": "^29.6.3",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
},
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/debug": {
- "version": "4.4.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
- "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "node_modules/jest-circus/node_modules/jest-matcher-utils": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz",
+ "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "ms": "^2.1.3"
+ "chalk": "^4.0.0",
+ "jest-diff": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
},
"engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/decode-bmp": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/decode-bmp/-/decode-bmp-0.2.1.tgz",
- "integrity": "sha512-NiOaGe+GN0KJqi2STf24hfMkFitDUaIoUU3eKvP/wAbLe8o6FuW5n/x7MHPR0HKvBokp6MQY/j7w8lewEeVCIA==",
+ "node_modules/jest-circus/node_modules/jest-message-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz",
+ "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@canvas/image-data": "^1.0.0",
- "to-data-view": "^1.1.0"
+ "@babel/code-frame": "^7.12.13",
+ "@jest/types": "^29.6.3",
+ "@types/stack-utils": "^2.0.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
},
"engines": {
- "node": ">=8.6.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/decode-ico": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/decode-ico/-/decode-ico-0.4.1.tgz",
- "integrity": "sha512-69NZfbKIzux1vBOd31al3XnMnH+2mqDhEgLdpygErm4d60N+UwA5Sq5WFjmEDQzumgB9fElojGwWG0vybVfFmA==",
+ "node_modules/jest-circus/node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@canvas/image-data": "^1.0.0",
- "decode-bmp": "^0.2.0",
- "to-data-view": "^1.1.0"
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
},
"engines": {
- "node": ">=8.6"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/deep-is": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
- "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/deepmerge": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
- "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "node_modules/jest-circus/node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=0.10.0"
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/define-data-property": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
- "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+ "node_modules/jest-circus/node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "es-define-property": "^1.0.0",
- "es-errors": "^1.3.0",
- "gopd": "^1.0.1"
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
},
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/define-properties": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
- "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
+ "node_modules/jest-cli": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz",
+ "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "define-data-property": "^1.0.1",
- "has-property-descriptors": "^1.0.0",
- "object-keys": "^1.1.1"
+ "@jest/core": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "create-jest": "^29.7.0",
+ "exit": "^0.1.2",
+ "import-local": "^3.0.2",
+ "jest-config": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "yargs": "^17.3.1"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
},
"engines": {
- "node": ">= 0.4"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
},
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
}
},
- "node_modules/defu": {
- "version": "6.1.4",
- "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz",
- "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==",
+ "node_modules/jest-cli/node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
"dev": true,
- "license": "MIT"
- },
- "node_modules/dequal": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
- "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
"license": "MIT",
+ "dependencies": {
+ "@sinclair/typebox": "^0.27.8"
+ },
"engines": {
- "node": ">=6"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/detect-libc": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.1.tgz",
- "integrity": "sha512-ecqj/sy1jcK1uWrwpR67UhYrIFQ+5WlGxth34WquCbamhFA6hkkwiu37o6J5xCHdo1oixJRfVRw+ywV+Hq/0Aw==",
+ "node_modules/jest-cli/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
"dev": true,
- "license": "Apache-2.0",
+ "license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ },
"engines": {
- "node": ">=8"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/detect-node-es": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
- "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==",
+ "node_modules/jest-cli/node_modules/@sinclair/typebox": {
+ "version": "0.27.10",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
+ "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
+ "dev": true,
"license": "MIT"
},
- "node_modules/doctrine": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
- "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "node_modules/jest-cli/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
"dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "esutils": "^2.0.2"
- },
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
"engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/dompurify": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.3.tgz",
- "integrity": "sha512-Oj6pzI2+RqBfFG+qOaOLbFXLQ90ARpcGG6UePL82bJLtdsa6CYJD7nmiU8MW9nQNOtCHV3lZ/Bzq1X0QYbBZCA==",
- "license": "(MPL-2.0 OR Apache-2.0)",
- "optionalDependencies": {
- "@types/trusted-types": "^2.0.7"
+ "node": ">=8"
}
},
- "node_modules/dunder-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
- "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "node_modules/jest-cli/node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bind-apply-helpers": "^1.0.1",
- "es-errors": "^1.3.0",
- "gopd": "^1.2.0"
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
},
"engines": {
- "node": ">= 0.4"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/eastasianwidth": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
- "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "node_modules/jest-cli/node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
},
- "node_modules/ejs": {
- "version": "3.1.10",
- "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz",
- "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==",
+ "node_modules/jest-config": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz",
+ "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==",
"dev": true,
- "license": "Apache-2.0",
+ "license": "MIT",
"dependencies": {
- "jake": "^10.8.5"
- },
- "bin": {
- "ejs": "bin/cli.js"
+ "@babel/core": "^7.11.6",
+ "@jest/test-sequencer": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "babel-jest": "^29.7.0",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "deepmerge": "^4.2.2",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "jest-circus": "^29.7.0",
+ "jest-environment-node": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-runner": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "parse-json": "^5.2.0",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-json-comments": "^3.1.1"
},
"engines": {
- "node": ">=0.10.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@types/node": "*",
+ "ts-node": ">=9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "ts-node": {
+ "optional": true
+ }
}
},
- "node_modules/electron-to-chromium": {
- "version": "1.5.267",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz",
- "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/emoji-regex": {
- "version": "9.2.2",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
- "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/es-abstract": {
- "version": "1.24.0",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz",
- "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==",
+ "node_modules/jest-config/node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "array-buffer-byte-length": "^1.0.2",
- "arraybuffer.prototype.slice": "^1.0.4",
- "available-typed-arrays": "^1.0.7",
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.4",
- "data-view-buffer": "^1.0.2",
- "data-view-byte-length": "^1.0.2",
- "data-view-byte-offset": "^1.0.1",
- "es-define-property": "^1.0.1",
- "es-errors": "^1.3.0",
- "es-object-atoms": "^1.1.1",
- "es-set-tostringtag": "^2.1.0",
- "es-to-primitive": "^1.3.0",
- "function.prototype.name": "^1.1.8",
- "get-intrinsic": "^1.3.0",
- "get-proto": "^1.0.1",
- "get-symbol-description": "^1.1.0",
- "globalthis": "^1.0.4",
- "gopd": "^1.2.0",
- "has-property-descriptors": "^1.0.2",
- "has-proto": "^1.2.0",
- "has-symbols": "^1.1.0",
- "hasown": "^2.0.2",
- "internal-slot": "^1.1.0",
- "is-array-buffer": "^3.0.5",
- "is-callable": "^1.2.7",
- "is-data-view": "^1.0.2",
- "is-negative-zero": "^2.0.3",
- "is-regex": "^1.2.1",
- "is-set": "^2.0.3",
- "is-shared-array-buffer": "^1.0.4",
- "is-string": "^1.1.1",
- "is-typed-array": "^1.1.15",
- "is-weakref": "^1.1.1",
- "math-intrinsics": "^1.1.0",
- "object-inspect": "^1.13.4",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.7",
- "own-keys": "^1.0.1",
- "regexp.prototype.flags": "^1.5.4",
- "safe-array-concat": "^1.1.3",
- "safe-push-apply": "^1.0.0",
- "safe-regex-test": "^1.1.0",
- "set-proto": "^1.0.0",
- "stop-iteration-iterator": "^1.1.0",
- "string.prototype.trim": "^1.2.10",
- "string.prototype.trimend": "^1.0.9",
- "string.prototype.trimstart": "^1.0.8",
- "typed-array-buffer": "^1.0.3",
- "typed-array-byte-length": "^1.0.3",
- "typed-array-byte-offset": "^1.0.4",
- "typed-array-length": "^1.0.7",
- "unbox-primitive": "^1.1.0",
- "which-typed-array": "^1.1.19"
+ "@sinclair/typebox": "^0.27.8"
},
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/es-define-property": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
- "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "node_modules/jest-config/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ },
"engines": {
- "node": ">= 0.4"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/es-errors": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
- "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "node_modules/jest-config/node_modules/@sinclair/typebox": {
+ "version": "0.27.10",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
+ "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/jest-config/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">= 0.4"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/es-iterator-helpers": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz",
- "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==",
+ "node_modules/jest-config/node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.3",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.23.6",
- "es-errors": "^1.3.0",
- "es-set-tostringtag": "^2.0.3",
- "function-bind": "^1.1.2",
- "get-intrinsic": "^1.2.6",
- "globalthis": "^1.0.4",
- "gopd": "^1.2.0",
- "has-property-descriptors": "^1.0.2",
- "has-proto": "^1.2.0",
- "has-symbols": "^1.1.0",
- "internal-slot": "^1.1.0",
- "iterator.prototype": "^1.1.4",
- "safe-array-concat": "^1.1.3"
- },
- "engines": {
- "node": ">= 0.4"
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
}
},
- "node_modules/es-object-atoms": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
- "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "node_modules/jest-config/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
"dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
"license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jest-config/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
+ "dev": true,
+ "license": "ISC",
"dependencies": {
- "es-errors": "^1.3.0"
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
},
"engines": {
- "node": ">= 0.4"
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/es-set-tostringtag": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
- "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "node_modules/jest-config/node_modules/jest-regex-util": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz",
+ "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.6",
- "has-tostringtag": "^1.0.2",
- "hasown": "^2.0.2"
- },
"engines": {
- "node": ">= 0.4"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/es-shim-unscopables": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz",
- "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==",
+ "node_modules/jest-config/node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "hasown": "^2.0.2"
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
},
"engines": {
- "node": ">= 0.4"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/es-to-primitive": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz",
- "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==",
+ "node_modules/jest-config/node_modules/minimatch": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
"dev": true,
- "license": "MIT",
+ "license": "ISC",
"dependencies": {
- "is-callable": "^1.2.7",
- "is-date-object": "^1.0.5",
- "is-symbol": "^1.0.4"
+ "brace-expansion": "^1.1.7"
},
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": "*"
}
},
- "node_modules/esbuild": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz",
- "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==",
- "hasInstallScript": true,
+ "node_modules/jest-config/node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
"license": "MIT",
- "bin": {
- "esbuild": "bin/esbuild"
- },
"engines": {
- "node": ">=18"
+ "node": ">=8.6"
},
- "optionalDependencies": {
- "@esbuild/aix-ppc64": "0.27.2",
- "@esbuild/android-arm": "0.27.2",
- "@esbuild/android-arm64": "0.27.2",
- "@esbuild/android-x64": "0.27.2",
- "@esbuild/darwin-arm64": "0.27.2",
- "@esbuild/darwin-x64": "0.27.2",
- "@esbuild/freebsd-arm64": "0.27.2",
- "@esbuild/freebsd-x64": "0.27.2",
- "@esbuild/linux-arm": "0.27.2",
- "@esbuild/linux-arm64": "0.27.2",
- "@esbuild/linux-ia32": "0.27.2",
- "@esbuild/linux-loong64": "0.27.2",
- "@esbuild/linux-mips64el": "0.27.2",
- "@esbuild/linux-ppc64": "0.27.2",
- "@esbuild/linux-riscv64": "0.27.2",
- "@esbuild/linux-s390x": "0.27.2",
- "@esbuild/linux-x64": "0.27.2",
- "@esbuild/netbsd-arm64": "0.27.2",
- "@esbuild/netbsd-x64": "0.27.2",
- "@esbuild/openbsd-arm64": "0.27.2",
- "@esbuild/openbsd-x64": "0.27.2",
- "@esbuild/openharmony-arm64": "0.27.2",
- "@esbuild/sunos-x64": "0.27.2",
- "@esbuild/win32-arm64": "0.27.2",
- "@esbuild/win32-ia32": "0.27.2",
- "@esbuild/win32-x64": "0.27.2"
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/escalade": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
- "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "node_modules/jest-config/node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
"engines": {
- "node": ">=6"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/escape-string-regexp": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
- "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "node_modules/jest-diff": {
+ "version": "30.2.0",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz",
+ "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==",
"dev": true,
"license": "MIT",
- "engines": {
- "node": ">=10"
+ "dependencies": {
+ "@jest/diff-sequences": "30.0.1",
+ "@jest/get-type": "30.1.0",
+ "chalk": "^4.1.2",
+ "pretty-format": "30.2.0"
},
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/eslint": {
- "version": "9.39.4",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz",
- "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==",
+ "node_modules/jest-docblock": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz",
+ "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@eslint-community/eslint-utils": "^4.8.0",
- "@eslint-community/regexpp": "^4.12.1",
- "@eslint/config-array": "^0.21.2",
- "@eslint/config-helpers": "^0.4.2",
- "@eslint/core": "^0.17.0",
- "@eslint/eslintrc": "^3.3.5",
- "@eslint/js": "9.39.4",
- "@eslint/plugin-kit": "^0.4.1",
- "@humanfs/node": "^0.16.6",
- "@humanwhocodes/module-importer": "^1.0.1",
- "@humanwhocodes/retry": "^0.4.2",
- "@types/estree": "^1.0.6",
- "ajv": "^6.14.0",
- "chalk": "^4.0.0",
- "cross-spawn": "^7.0.6",
- "debug": "^4.3.2",
- "escape-string-regexp": "^4.0.0",
- "eslint-scope": "^8.4.0",
- "eslint-visitor-keys": "^4.2.1",
- "espree": "^10.4.0",
- "esquery": "^1.5.0",
- "esutils": "^2.0.2",
- "fast-deep-equal": "^3.1.3",
- "file-entry-cache": "^8.0.0",
- "find-up": "^5.0.0",
- "glob-parent": "^6.0.2",
- "ignore": "^5.2.0",
- "imurmurhash": "^0.1.4",
- "is-glob": "^4.0.0",
- "json-stable-stringify-without-jsonify": "^1.0.1",
- "lodash.merge": "^4.6.2",
- "minimatch": "^3.1.5",
- "natural-compare": "^1.4.0",
- "optionator": "^0.9.3"
- },
- "bin": {
- "eslint": "bin/eslint.js"
+ "detect-newline": "^3.0.0"
},
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://eslint.org/donate"
- },
- "peerDependencies": {
- "jiti": "*"
- },
- "peerDependenciesMeta": {
- "jiti": {
- "optional": true
- }
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/eslint-plugin-react": {
- "version": "7.37.5",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz",
- "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==",
+ "node_modules/jest-each": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz",
+ "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "array-includes": "^3.1.8",
- "array.prototype.findlast": "^1.2.5",
- "array.prototype.flatmap": "^1.3.3",
- "array.prototype.tosorted": "^1.1.4",
- "doctrine": "^2.1.0",
- "es-iterator-helpers": "^1.2.1",
- "estraverse": "^5.3.0",
- "hasown": "^2.0.2",
- "jsx-ast-utils": "^2.4.1 || ^3.0.0",
- "minimatch": "^3.1.2",
- "object.entries": "^1.1.9",
- "object.fromentries": "^2.0.8",
- "object.values": "^1.2.1",
- "prop-types": "^15.8.1",
- "resolve": "^2.0.0-next.5",
- "semver": "^6.3.1",
- "string.prototype.matchall": "^4.0.12",
- "string.prototype.repeat": "^1.0.0"
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "pretty-format": "^29.7.0"
},
"engines": {
- "node": ">=4"
- },
- "peerDependencies": {
- "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/eslint-plugin-react/node_modules/brace-expansion": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
- "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "node_modules/jest-each/node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
+ "@sinclair/typebox": "^0.27.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/eslint-plugin-react/node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "node_modules/jest-each/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
"dev": true,
- "license": "ISC",
+ "license": "MIT",
"dependencies": {
- "brace-expansion": "^1.1.7"
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
},
"engines": {
- "node": "*"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/eslint-plugin-react/node_modules/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "node_modules/jest-each/node_modules/@sinclair/typebox": {
+ "version": "0.27.10",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
+ "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
"dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
+ "license": "MIT"
+ },
+ "node_modules/jest-each/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/eslint-scope": {
- "version": "8.4.0",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
- "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
+ "node_modules/jest-each/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jest-each/node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
"dev": true,
- "license": "BSD-2-Clause",
+ "license": "MIT",
"dependencies": {
- "esrecurse": "^4.3.0",
- "estraverse": "^5.2.0"
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
},
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/eslint-visitor-keys": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
- "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "node_modules/jest-each/node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
- "license": "Apache-2.0",
+ "license": "MIT",
"engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ "node": ">=8.6"
},
"funding": {
- "url": "https://opencollective.com/eslint"
+ "url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/eslint/node_modules/brace-expansion": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
- "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "node_modules/jest-each/node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/eslint/node_modules/eslint-visitor-keys": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
- "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+ "node_modules/jest-environment-jsdom": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-30.3.0.tgz",
+ "integrity": "sha512-RLEOJy6ip1lpw0yqJ8tB3i88FC7VBz7i00Zvl2qF71IdxjS98gC9/0SPWYIBVXHm5hgCYK0PAlSlnHGGy9RoMg==",
"dev": true,
- "license": "Apache-2.0",
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "30.3.0",
+ "@jest/environment-jsdom-abstract": "30.3.0",
+ "jsdom": "^26.1.0"
+ },
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
},
- "funding": {
- "url": "https://opencollective.com/eslint"
+ "peerDependencies": {
+ "canvas": "^3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "canvas": {
+ "optional": true
+ }
}
},
- "node_modules/eslint/node_modules/ignore": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
- "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "node_modules/jest-environment-jsdom/node_modules/@jest/environment": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.3.0.tgz",
+ "integrity": "sha512-SlLSF4Be735yQXyh2+mctBOzNDx5s5uLv88/j8Qn1wH679PDcwy67+YdADn8NJnGjzlXtN62asGH/T4vWOkfaw==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "@jest/fake-timers": "30.3.0",
+ "@jest/types": "30.3.0",
+ "@types/node": "*",
+ "jest-mock": "30.3.0"
+ },
"engines": {
- "node": ">= 4"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/eslint/node_modules/minimatch": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
- "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
+ "node_modules/jest-environment-jsdom/node_modules/@jest/fake-timers": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.3.0.tgz",
+ "integrity": "sha512-WUQDs8SOP9URStX1DzhD425CqbN/HxUYCTwVrT8sTVBfMvFqYt/s61EK5T05qnHu0po6RitXIvP9otZxYDzTGQ==",
"dev": true,
- "license": "ISC",
+ "license": "MIT",
"dependencies": {
- "brace-expansion": "^1.1.7"
+ "@jest/types": "30.3.0",
+ "@sinonjs/fake-timers": "^15.0.0",
+ "@types/node": "*",
+ "jest-message-util": "30.3.0",
+ "jest-mock": "30.3.0",
+ "jest-util": "30.3.0"
},
"engines": {
- "node": "*"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/espree": {
- "version": "10.4.0",
- "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
- "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
+ "node_modules/jest-environment-jsdom/node_modules/@jest/types": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.3.0.tgz",
+ "integrity": "sha512-JHm87k7bA33hpBngtU8h6UBub/fqqA9uXfw+21j5Hmk7ooPHlboRNxHq0JcMtC+n8VJGP1mcfnD3Mk+XKe1oSw==",
"dev": true,
- "license": "BSD-2-Clause",
+ "license": "MIT",
"dependencies": {
- "acorn": "^8.15.0",
- "acorn-jsx": "^5.3.2",
- "eslint-visitor-keys": "^4.2.1"
+ "@jest/pattern": "30.0.1",
+ "@jest/schemas": "30.0.5",
+ "@types/istanbul-lib-coverage": "^2.0.6",
+ "@types/istanbul-reports": "^3.0.4",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.33",
+ "chalk": "^4.1.2"
},
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/espree/node_modules/eslint-visitor-keys": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
- "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+ "node_modules/jest-environment-jsdom/node_modules/@sinonjs/fake-timers": {
+ "version": "15.1.1",
+ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-15.1.1.tgz",
+ "integrity": "sha512-cO5W33JgAPbOh07tvZjUOJ7oWhtaqGHiZw+11DPbyqh2kHTBc3eF/CjJDeQ4205RLQsX6rxCuYOroFQwl7JDRw==",
"dev": true,
- "license": "Apache-2.0",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@sinonjs/commons": "^3.0.1"
+ }
+ },
+ "node_modules/jest-environment-jsdom/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "license": "MIT",
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "node": ">=10"
},
"funding": {
- "url": "https://opencollective.com/eslint"
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/esquery": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
- "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
+ "node_modules/jest-environment-jsdom/node_modules/jest-message-util": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.3.0.tgz",
+ "integrity": "sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw==",
"dev": true,
- "license": "BSD-3-Clause",
+ "license": "MIT",
"dependencies": {
- "estraverse": "^5.1.0"
+ "@babel/code-frame": "^7.27.1",
+ "@jest/types": "30.3.0",
+ "@types/stack-utils": "^2.0.3",
+ "chalk": "^4.1.2",
+ "graceful-fs": "^4.2.11",
+ "picomatch": "^4.0.3",
+ "pretty-format": "30.3.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.6"
},
"engines": {
- "node": ">=0.10"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/esrecurse": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
- "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "node_modules/jest-environment-jsdom/node_modules/jest-mock": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.3.0.tgz",
+ "integrity": "sha512-OTzICK8CpE+t4ndhKrwlIdbM6Pn8j00lvmSmq5ejiO+KxukbLjgOflKWMn3KE34EZdQm5RqTuKj+5RIEniYhog==",
"dev": true,
- "license": "BSD-2-Clause",
+ "license": "MIT",
"dependencies": {
- "estraverse": "^5.2.0"
+ "@jest/types": "30.3.0",
+ "@types/node": "*",
+ "jest-util": "30.3.0"
},
"engines": {
- "node": ">=4.0"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/estraverse": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
- "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "node_modules/jest-environment-jsdom/node_modules/jest-util": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz",
+ "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==",
"dev": true,
- "license": "BSD-2-Clause",
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "30.3.0",
+ "@types/node": "*",
+ "chalk": "^4.1.2",
+ "ci-info": "^4.2.0",
+ "graceful-fs": "^4.2.11",
+ "picomatch": "^4.0.3"
+ },
"engines": {
- "node": ">=4.0"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/estree-walker": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
- "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/esutils": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
- "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "node_modules/jest-environment-jsdom/node_modules/pretty-format": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz",
+ "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==",
"dev": true,
- "license": "BSD-2-Clause",
+ "license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "30.0.5",
+ "ansi-styles": "^5.2.0",
+ "react-is": "^18.3.1"
+ },
"engines": {
- "node": ">=0.10.0"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/eventemitter3": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
- "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
- "license": "MIT"
- },
- "node_modules/exifr": {
- "version": "7.1.3",
- "resolved": "https://registry.npmjs.org/exifr/-/exifr-7.1.3.tgz",
- "integrity": "sha512-g/aje2noHivrRSLbAUtBPWFbxKdKhgj/xr1vATDdUXPOFYJlQ62Ft0oy+72V6XLIpDJfHs6gXLbBLAolqOXYRw==",
- "license": "MIT"
- },
- "node_modules/expect": {
- "version": "30.2.0",
- "resolved": "https://registry.npmjs.org/expect/-/expect-30.2.0.tgz",
- "integrity": "sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==",
+ "node_modules/jest-environment-node": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz",
+ "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/expect-utils": "30.2.0",
- "@jest/get-type": "30.1.0",
- "jest-matcher-utils": "30.2.0",
- "jest-message-util": "30.2.0",
- "jest-mock": "30.2.0",
- "jest-util": "30.2.0"
+ "@jest/environment": "^29.7.0",
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/fast-deep-equal": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
- "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "node_modules/jest-environment-node/node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "dependencies": {
+ "@sinclair/typebox": "^0.27.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
},
- "node_modules/fast-json-stable-stringify": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
- "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "node_modules/jest-environment-node/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
},
- "node_modules/fast-levenshtein": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
- "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "node_modules/jest-environment-node/node_modules/@sinclair/typebox": {
+ "version": "0.27.10",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
+ "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
"dev": true,
"license": "MIT"
},
- "node_modules/fast-uri": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz",
- "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==",
+ "node_modules/jest-environment-node/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
"dev": true,
"funding": [
{
"type": "github",
- "url": "https://github.com/sponsors/fastify"
- },
- {
- "type": "opencollective",
- "url": "https://opencollective.com/fastify"
+ "url": "https://github.com/sponsors/sibiraj-s"
}
],
- "license": "BSD-3-Clause"
- },
- "node_modules/fdir": {
- "version": "6.5.0",
- "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
- "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
"license": "MIT",
"engines": {
- "node": ">=12.0.0"
- },
- "peerDependencies": {
- "picomatch": "^3 || ^4"
+ "node": ">=8"
+ }
+ },
+ "node_modules/jest-environment-node/node_modules/jest-mock": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz",
+ "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-util": "^29.7.0"
},
- "peerDependenciesMeta": {
- "picomatch": {
- "optional": true
- }
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/file-entry-cache": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
- "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "node_modules/jest-environment-node/node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "flat-cache": "^4.0.0"
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
},
"engines": {
- "node": ">=16.0.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/file-type": {
- "version": "21.3.2",
- "resolved": "https://registry.npmjs.org/file-type/-/file-type-21.3.2.tgz",
- "integrity": "sha512-DLkUvGwep3poOV2wpzbHCOnSKGk1LzyXTv+aHFgN2VFl96wnp8YA9YjO2qPzg5PuL8q/SW9Pdi6WTkYOIh995w==",
+ "node_modules/jest-environment-node/node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
"license": "MIT",
- "dependencies": {
- "@tokenizer/inflate": "^0.4.1",
- "strtok3": "^10.3.4",
- "token-types": "^6.1.1",
- "uint8array-extras": "^1.4.0"
- },
"engines": {
- "node": ">=20"
+ "node": ">=8.6"
},
"funding": {
- "url": "https://github.com/sindresorhus/file-type?sponsor=1"
+ "url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/filelist": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
- "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==",
+ "node_modules/jest-get-type": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz",
+ "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==",
"dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "minimatch": "^5.0.1"
+ "license": "MIT",
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/filelist/node_modules/minimatch": {
- "version": "5.1.6",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
- "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+ "node_modules/jest-haste-map": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz",
+ "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==",
"dev": true,
- "license": "ISC",
+ "license": "MIT",
"dependencies": {
- "brace-expansion": "^2.0.1"
+ "@jest/types": "^29.6.3",
+ "@types/graceful-fs": "^4.1.3",
+ "@types/node": "*",
+ "anymatch": "^3.0.3",
+ "fb-watchman": "^2.0.0",
+ "graceful-fs": "^4.2.9",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "walker": "^1.0.8"
},
"engines": {
- "node": ">=10"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "^2.3.2"
}
},
- "node_modules/fill-range": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
- "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "node_modules/jest-haste-map/node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "to-regex-range": "^5.0.1"
+ "@sinclair/typebox": "^0.27.8"
},
"engines": {
- "node": ">=8"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/find-up": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
- "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "node_modules/jest-haste-map/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "locate-path": "^6.0.0",
- "path-exists": "^4.0.0"
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
},
"engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/flat-cache": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
- "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+ "node_modules/jest-haste-map/node_modules/@sinclair/typebox": {
+ "version": "0.27.10",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
+ "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
"dev": true,
+ "license": "MIT"
+ },
+ "node_modules/jest-haste-map/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
"license": "MIT",
- "dependencies": {
- "flatted": "^3.2.9",
- "keyv": "^4.5.4"
- },
"engines": {
- "node": ">=16"
+ "node": ">=8"
}
},
- "node_modules/flatted": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
- "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
+ "node_modules/jest-haste-map/node_modules/jest-regex-util": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz",
+ "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==",
"dev": true,
- "license": "ISC"
+ "license": "MIT",
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
},
- "node_modules/for-each": {
- "version": "0.3.5",
- "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
- "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
+ "node_modules/jest-haste-map/node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "is-callable": "^1.2.7"
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
},
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/foreground-child": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
- "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
+ "node_modules/jest-haste-map/node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
- "license": "ISC",
- "dependencies": {
- "cross-spawn": "^7.0.6",
- "signal-exit": "^4.0.1"
- },
+ "license": "MIT",
"engines": {
- "node": ">=14"
+ "node": ">=8.6"
},
"funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/fs-extra": {
- "version": "9.1.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
- "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
+ "node_modules/jest-leak-detector": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz",
+ "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "at-least-node": "^1.0.0",
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
},
"engines": {
- "node": ">=10"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "hasInstallScript": true,
+ "node_modules/jest-leak-detector/node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+ "dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
+ "dependencies": {
+ "@sinclair/typebox": "^0.27.8"
+ },
"engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/function-bind": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
- "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "node_modules/jest-leak-detector/node_modules/@sinclair/typebox": {
+ "version": "0.27.10",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
+ "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
"dev": true,
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
+ "license": "MIT"
},
- "node_modules/function.prototype.name": {
- "version": "1.1.8",
- "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz",
- "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==",
+ "node_modules/jest-leak-detector/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.3",
- "define-properties": "^1.2.1",
- "functions-have-names": "^1.2.3",
- "hasown": "^2.0.2",
- "is-callable": "^1.2.7"
- },
"engines": {
- "node": ">= 0.4"
+ "node": ">=10"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/functions-have-names": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
- "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "node_modules/jest-leak-detector/node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
"dev": true,
"license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/generator-function": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz",
- "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==",
+ "node_modules/jest-matcher-utils": {
+ "version": "30.2.0",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz",
+ "integrity": "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "@jest/get-type": "30.1.0",
+ "chalk": "^4.1.2",
+ "jest-diff": "30.2.0",
+ "pretty-format": "30.2.0"
+ },
"engines": {
- "node": ">= 0.4"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/gensync": {
- "version": "1.0.0-beta.2",
- "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
- "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "node_modules/jest-message-util": {
+ "version": "30.2.0",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz",
+ "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@jest/types": "30.2.0",
+ "@types/stack-utils": "^2.0.3",
+ "chalk": "^4.1.2",
+ "graceful-fs": "^4.2.11",
+ "micromatch": "^4.0.8",
+ "pretty-format": "30.2.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.6"
+ },
"engines": {
- "node": ">=6.9.0"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/get-intrinsic": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
- "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "node_modules/jest-mock": {
+ "version": "30.2.0",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.2.0.tgz",
+ "integrity": "sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bind-apply-helpers": "^1.0.2",
- "es-define-property": "^1.0.1",
- "es-errors": "^1.3.0",
- "es-object-atoms": "^1.1.1",
- "function-bind": "^1.1.2",
- "get-proto": "^1.0.1",
- "gopd": "^1.2.0",
- "has-symbols": "^1.1.0",
- "hasown": "^2.0.2",
- "math-intrinsics": "^1.1.0"
+ "@jest/types": "30.2.0",
+ "@types/node": "*",
+ "jest-util": "30.2.0"
},
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/get-nonce": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz",
- "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==",
+ "node_modules/jest-pnp-resolver": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz",
+ "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
- }
- },
- "node_modules/get-own-enumerable-property-symbols": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz",
- "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/get-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
- "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "dunder-proto": "^1.0.1",
- "es-object-atoms": "^1.0.0"
},
- "engines": {
- "node": ">= 0.4"
+ "peerDependencies": {
+ "jest-resolve": "*"
+ },
+ "peerDependenciesMeta": {
+ "jest-resolve": {
+ "optional": true
+ }
}
},
- "node_modules/get-symbol-description": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz",
- "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==",
+ "node_modules/jest-regex-util": {
+ "version": "30.0.1",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz",
+ "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3",
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.6"
- },
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/glob": {
- "version": "11.1.0",
- "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz",
- "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==",
+ "node_modules/jest-resolve": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz",
+ "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==",
"dev": true,
- "license": "BlueOak-1.0.0",
+ "license": "MIT",
"dependencies": {
- "foreground-child": "^3.3.1",
- "jackspeak": "^4.1.1",
- "minimatch": "^10.1.1",
- "minipass": "^7.1.2",
- "package-json-from-dist": "^1.0.0",
- "path-scurry": "^2.0.0"
- },
- "bin": {
- "glob": "dist/esm/bin.mjs"
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-pnp-resolver": "^1.2.2",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "resolve": "^1.20.0",
+ "resolve.exports": "^2.0.0",
+ "slash": "^3.0.0"
},
"engines": {
- "node": "20 || >=22"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/glob-parent": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
- "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "node_modules/jest-resolve-dependencies": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz",
+ "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==",
"dev": true,
- "license": "ISC",
+ "license": "MIT",
"dependencies": {
- "is-glob": "^4.0.3"
+ "jest-regex-util": "^29.6.3",
+ "jest-snapshot": "^29.7.0"
},
"engines": {
- "node": ">=10.13.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/globals": {
- "version": "14.0.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
- "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
+ "node_modules/jest-resolve-dependencies/node_modules/jest-regex-util": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz",
+ "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/globalthis": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
- "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==",
+ "node_modules/jest-resolve/node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "define-properties": "^1.2.1",
- "gopd": "^1.0.1"
+ "@sinclair/typebox": "^0.27.8"
},
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/gopd": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
- "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "node_modules/jest-resolve/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
"dev": true,
"license": "MIT",
- "engines": {
- "node": ">= 0.4"
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
},
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/graceful-fs": {
- "version": "4.2.11",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
- "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/has-bigints": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz",
- "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==",
+ "node_modules/jest-resolve/node_modules/@sinclair/typebox": {
+ "version": "0.27.10",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
+ "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
"dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
+ "license": "MIT"
},
- "node_modules/has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "node_modules/jest-resolve/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
"dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
"license": "MIT",
"engines": {
"node": ">=8"
}
},
- "node_modules/has-property-descriptors": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
- "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "es-define-property": "^1.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-proto": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz",
- "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==",
+ "node_modules/jest-resolve/node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "dunder-proto": "^1.0.0"
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
},
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/has-symbols": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
- "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "node_modules/jest-resolve/node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">= 0.4"
+ "node": ">=8.6"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/has-tostringtag": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
- "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "node_modules/jest-resolve/node_modules/resolve": {
+ "version": "1.22.11",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz",
+ "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "has-symbols": "^1.0.3"
+ "is-core-module": "^2.16.1",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
},
"engines": {
"node": ">= 0.4"
@@ -7729,773 +13019,1036 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/hasown": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
- "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "node_modules/jest-runner": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz",
+ "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "function-bind": "^1.1.2"
+ "@jest/console": "^29.7.0",
+ "@jest/environment": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "emittery": "^0.13.1",
+ "graceful-fs": "^4.2.9",
+ "jest-docblock": "^29.7.0",
+ "jest-environment-node": "^29.7.0",
+ "jest-haste-map": "^29.7.0",
+ "jest-leak-detector": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-resolve": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-watcher": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "p-limit": "^3.1.0",
+ "source-map-support": "0.5.13"
},
"engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/html-parse-stringify": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz",
- "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==",
- "license": "MIT",
- "dependencies": {
- "void-elements": "3.1.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/i18next": {
- "version": "25.8.18",
- "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.8.18.tgz",
- "integrity": "sha512-lzY5X83BiL5AP77+9DydbrqkQHFN9hUzWGjqjLpPcp5ZOzuu1aSoKaU3xbBLSjWx9dAzW431y+d+aogxOZaKRA==",
- "funding": [
- {
- "type": "individual",
- "url": "https://locize.com"
- },
- {
- "type": "individual",
- "url": "https://locize.com/i18next.html"
- },
- {
- "type": "individual",
- "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
- }
- ],
+ "node_modules/jest-runner/node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@babel/runtime": "^7.28.6"
+ "@sinclair/typebox": "^0.27.8"
},
- "peerDependencies": {
- "typescript": "^5"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/i18next-browser-languagedetector": {
- "version": "8.2.1",
- "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.2.1.tgz",
- "integrity": "sha512-bZg8+4bdmaOiApD7N7BPT9W8MLZG+nPTOFlLiJiT8uzKXFjhxw4v2ierCXOwB5sFDMtuA5G4kgYZ0AznZxQ/cw==",
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.23.2"
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/i18next-http-backend": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-3.0.2.tgz",
- "integrity": "sha512-PdlvPnvIp4E1sYi46Ik4tBYh/v/NbYfFFgTjkwFl0is8A18s7/bx9aXqsrOax9WUbeNS6mD2oix7Z0yGGf6m5g==",
+ "node_modules/jest-runner/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "cross-fetch": "4.0.0"
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/ico-endec": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/ico-endec/-/ico-endec-0.1.6.tgz",
- "integrity": "sha512-ZdLU38ZoED3g1j3iEyzcQj+wAkY2xfWNkymszfJPoxucIUhK7NayQ+/C4Kv0nDFMIsbtbEHldv3V8PU494/ueQ==",
+ "node_modules/jest-runner/node_modules/@sinclair/typebox": {
+ "version": "0.27.10",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
+ "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
"dev": true,
- "license": "MPL-2.0"
+ "license": "MIT"
},
- "node_modules/idb": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz",
- "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==",
+ "node_modules/jest-runner/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
"dev": true,
- "license": "ISC"
- },
- "node_modules/ieee754": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
- "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/jest-runner/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "dev": true,
+ "funding": [
{
- "type": "consulting",
- "url": "https://feross.org/support"
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
}
],
- "license": "BSD-3-Clause"
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
},
- "node_modules/ignore": {
- "version": "7.0.5",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
- "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
+ "node_modules/jest-runner/node_modules/jest-message-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz",
+ "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.12.13",
+ "@jest/types": "^29.6.3",
+ "@types/stack-utils": "^2.0.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
+ },
"engines": {
- "node": ">= 4"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/import-fresh": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
- "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "node_modules/jest-runner/node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "parent-module": "^1.0.0",
- "resolve-from": "^4.0.0"
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
},
"engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/imurmurhash": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "node_modules/jest-runner/node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=0.8.19"
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/internal-slot": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
- "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==",
+ "node_modules/jest-runner/node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "es-errors": "^1.3.0",
- "hasown": "^2.0.2",
- "side-channel": "^1.1.0"
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
},
"engines": {
- "node": ">= 0.4"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/is-array-buffer": {
- "version": "3.0.5",
- "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
- "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==",
+ "node_modules/jest-runner/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.3",
- "get-intrinsic": "^1.2.6"
- },
+ "license": "BSD-3-Clause",
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": ">=0.10.0"
}
},
- "node_modules/is-arrayish": {
- "version": "0.3.4",
- "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz",
- "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==",
+ "node_modules/jest-runner/node_modules/source-map-support": {
+ "version": "0.5.13",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
+ "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
},
- "node_modules/is-async-function": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz",
- "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==",
+ "node_modules/jest-runtime": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz",
+ "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "async-function": "^1.0.0",
- "call-bound": "^1.0.3",
- "get-proto": "^1.0.1",
- "has-tostringtag": "^1.0.2",
- "safe-regex-test": "^1.1.0"
+ "@jest/environment": "^29.7.0",
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/globals": "^29.7.0",
+ "@jest/source-map": "^29.6.3",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "cjs-module-lexer": "^1.0.0",
+ "collect-v8-coverage": "^1.0.0",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-mock": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-bom": "^4.0.0"
},
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/is-bigint": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz",
- "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==",
+ "node_modules/jest-runtime/node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "has-bigints": "^1.0.2"
+ "@sinclair/typebox": "^0.27.8"
},
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/is-boolean-object": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz",
- "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==",
+ "node_modules/jest-runtime/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.3",
- "has-tostringtag": "^1.0.2"
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
},
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/is-callable": {
- "version": "1.2.7",
- "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
- "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+ "node_modules/jest-runtime/node_modules/@sinclair/typebox": {
+ "version": "0.27.10",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
+ "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/jest-runtime/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">= 0.4"
+ "node": ">=10"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/is-core-module": {
- "version": "2.16.1",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
- "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
+ "node_modules/jest-runtime/node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "hasown": "^2.0.2"
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/jest-runtime/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jest-runtime/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
},
"engines": {
- "node": ">= 0.4"
+ "node": "*"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/is-data-view": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz",
- "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==",
+ "node_modules/jest-runtime/node_modules/jest-message-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz",
+ "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.2",
- "get-intrinsic": "^1.2.6",
- "is-typed-array": "^1.1.13"
+ "@babel/code-frame": "^7.12.13",
+ "@jest/types": "^29.6.3",
+ "@types/stack-utils": "^2.0.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
},
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/is-date-object": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz",
- "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==",
+ "node_modules/jest-runtime/node_modules/jest-mock": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz",
+ "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.2",
- "has-tostringtag": "^1.0.2"
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-util": "^29.7.0"
},
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/is-extglob": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "node_modules/jest-runtime/node_modules/jest-regex-util": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz",
+ "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=0.10.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/is-finalizationregistry": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz",
- "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==",
+ "node_modules/jest-runtime/node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.3"
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
},
"engines": {
- "node": ">= 0.4"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-runtime/node_modules/minimatch": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/jest-runtime/node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "node_modules/jest-runtime/node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
"engines": {
- "node": ">=8"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/is-generator-function": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz",
- "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==",
+ "node_modules/jest-snapshot": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz",
+ "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.4",
- "generator-function": "^2.0.0",
- "get-proto": "^1.0.1",
- "has-tostringtag": "^1.0.2",
- "safe-regex-test": "^1.1.0"
+ "@babel/core": "^7.11.6",
+ "@babel/generator": "^7.7.2",
+ "@babel/plugin-syntax-jsx": "^7.7.2",
+ "@babel/plugin-syntax-typescript": "^7.7.2",
+ "@babel/types": "^7.3.3",
+ "@jest/expect-utils": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "babel-preset-current-node-syntax": "^1.0.0",
+ "chalk": "^4.0.0",
+ "expect": "^29.7.0",
+ "graceful-fs": "^4.2.9",
+ "jest-diff": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "natural-compare": "^1.4.0",
+ "pretty-format": "^29.7.0",
+ "semver": "^7.5.3"
},
"engines": {
- "node": ">= 0.4"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-snapshot/node_modules/@jest/expect-utils": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz",
+ "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jest-get-type": "^29.6.3"
},
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/is-glob": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
- "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "node_modules/jest-snapshot/node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "is-extglob": "^2.1.1"
+ "@sinclair/typebox": "^0.27.8"
},
"engines": {
- "node": ">=0.10.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/is-map": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
- "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==",
+ "node_modules/jest-snapshot/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
"dev": true,
"license": "MIT",
- "engines": {
- "node": ">= 0.4"
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
},
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/is-module": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
- "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==",
+ "node_modules/jest-snapshot/node_modules/@sinclair/typebox": {
+ "version": "0.27.10",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
+ "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
"dev": true,
"license": "MIT"
},
- "node_modules/is-negative-zero": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz",
- "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==",
+ "node_modules/jest-snapshot/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">= 0.4"
+ "node": ">=10"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/is-number": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "node_modules/jest-snapshot/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
"license": "MIT",
"engines": {
- "node": ">=0.12.0"
+ "node": ">=8"
}
},
- "node_modules/is-number-object": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz",
- "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==",
+ "node_modules/jest-snapshot/node_modules/expect": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz",
+ "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.3",
- "has-tostringtag": "^1.0.2"
+ "@jest/expect-utils": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0"
},
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/is-obj": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
- "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==",
+ "node_modules/jest-snapshot/node_modules/jest-diff": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz",
+ "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "diff-sequences": "^29.6.3",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
+ },
"engines": {
- "node": ">=0.10.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/is-regex": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
- "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
+ "node_modules/jest-snapshot/node_modules/jest-matcher-utils": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz",
+ "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.2",
- "gopd": "^1.2.0",
- "has-tostringtag": "^1.0.2",
- "hasown": "^2.0.2"
+ "chalk": "^4.0.0",
+ "jest-diff": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
},
"engines": {
- "node": ">= 0.4"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-snapshot/node_modules/jest-message-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz",
+ "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.12.13",
+ "@jest/types": "^29.6.3",
+ "@types/stack-utils": "^2.0.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
},
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/is-regexp": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz",
- "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==",
+ "node_modules/jest-snapshot/node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
+ },
"engines": {
- "node": ">=0.10.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/is-set": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz",
- "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==",
+ "node_modules/jest-snapshot/node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">= 0.4"
+ "node": ">=8.6"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/is-shared-array-buffer": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz",
- "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==",
+ "node_modules/jest-snapshot/node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.3"
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
},
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/is-stream": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
- "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "node_modules/jest-util": {
+ "version": "30.2.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz",
+ "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==",
"dev": true,
"license": "MIT",
- "engines": {
- "node": ">=8"
+ "dependencies": {
+ "@jest/types": "30.2.0",
+ "@types/node": "*",
+ "chalk": "^4.1.2",
+ "ci-info": "^4.2.0",
+ "graceful-fs": "^4.2.11",
+ "picomatch": "^4.0.2"
},
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/is-string": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz",
- "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==",
+ "node_modules/jest-validate": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz",
+ "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.3",
- "has-tostringtag": "^1.0.2"
+ "@jest/types": "^29.6.3",
+ "camelcase": "^6.2.0",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.6.3",
+ "leven": "^3.1.0",
+ "pretty-format": "^29.7.0"
},
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/is-symbol": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz",
- "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==",
+ "node_modules/jest-validate/node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.2",
- "has-symbols": "^1.1.0",
- "safe-regex-test": "^1.1.0"
+ "@sinclair/typebox": "^0.27.8"
},
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/is-typed-array": {
- "version": "1.1.15",
- "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
- "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
+ "node_modules/jest-validate/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "which-typed-array": "^1.1.16"
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
},
"engines": {
- "node": ">= 0.4"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-validate/node_modules/@sinclair/typebox": {
+ "version": "0.27.10",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
+ "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/jest-validate/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/is-weakmap": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
- "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==",
+ "node_modules/jest-validate/node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">= 0.4"
+ "node": ">=10"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/is-weakref": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz",
- "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==",
+ "node_modules/jest-validate/node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.3"
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
},
"engines": {
- "node": ">= 0.4"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-watcher": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz",
+ "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "emittery": "^0.13.1",
+ "jest-util": "^29.7.0",
+ "string-length": "^4.0.1"
},
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/is-weakset": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz",
- "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==",
+ "node_modules/jest-watcher/node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.3",
- "get-intrinsic": "^1.2.6"
+ "@sinclair/typebox": "^0.27.8"
},
"engines": {
- "node": ">= 0.4"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-watcher/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
},
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/isarray": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
- "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+ "node_modules/jest-watcher/node_modules/@sinclair/typebox": {
+ "version": "0.27.10",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
+ "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
"dev": true,
"license": "MIT"
},
- "node_modules/isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "node_modules/jest-watcher/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
"dev": true,
- "license": "ISC"
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
},
- "node_modules/iterator.prototype": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz",
- "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==",
+ "node_modules/jest-watcher/node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "define-data-property": "^1.1.4",
- "es-object-atoms": "^1.0.0",
- "get-intrinsic": "^1.2.6",
- "get-proto": "^1.0.0",
- "has-symbols": "^1.1.0",
- "set-function-name": "^2.0.2"
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
},
"engines": {
- "node": ">= 0.4"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/jackspeak": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz",
- "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==",
+ "node_modules/jest-watcher/node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "@isaacs/cliui": "^8.0.2"
- },
+ "license": "MIT",
"engines": {
- "node": "20 || >=22"
+ "node": ">=8.6"
},
"funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/jake": {
- "version": "10.9.4",
- "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz",
- "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==",
+ "node_modules/jest-worker": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz",
+ "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==",
"dev": true,
- "license": "Apache-2.0",
+ "license": "MIT",
"dependencies": {
- "async": "^3.2.6",
- "filelist": "^1.0.4",
- "picocolors": "^1.1.1"
- },
- "bin": {
- "jake": "bin/cli.js"
+ "@types/node": "*",
+ "jest-util": "^29.7.0",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
},
"engines": {
- "node": ">=10"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/jest-diff": {
- "version": "30.2.0",
- "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz",
- "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==",
+ "node_modules/jest-worker/node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/diff-sequences": "30.0.1",
- "@jest/get-type": "30.1.0",
- "chalk": "^4.1.2",
- "pretty-format": "30.2.0"
+ "@sinclair/typebox": "^0.27.8"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/jest-matcher-utils": {
- "version": "30.2.0",
- "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz",
- "integrity": "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==",
+ "node_modules/jest-worker/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/get-type": "30.1.0",
- "chalk": "^4.1.2",
- "jest-diff": "30.2.0",
- "pretty-format": "30.2.0"
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/jest-message-util": {
- "version": "30.2.0",
- "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz",
- "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==",
+ "node_modules/jest-worker/node_modules/@sinclair/typebox": {
+ "version": "0.27.10",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
+ "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/jest-worker/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jest-worker/node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.27.1",
- "@jest/types": "30.2.0",
- "@types/stack-utils": "^2.0.3",
- "chalk": "^4.1.2",
- "graceful-fs": "^4.2.11",
- "micromatch": "^4.0.8",
- "pretty-format": "30.2.0",
- "slash": "^3.0.0",
- "stack-utils": "^2.0.6"
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/jest-mock": {
- "version": "30.2.0",
- "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.2.0.tgz",
- "integrity": "sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==",
+ "node_modules/jest-worker/node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/jest-worker/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/types": "30.2.0",
- "@types/node": "*",
- "jest-util": "30.2.0"
+ "has-flag": "^4.0.0"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
}
},
- "node_modules/jest-regex-util": {
- "version": "30.0.1",
- "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz",
- "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==",
+ "node_modules/jest/node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "@sinclair/typebox": "^0.27.8"
+ },
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/jest-util": {
- "version": "30.2.0",
- "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz",
- "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==",
+ "node_modules/jest/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/types": "30.2.0",
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
"@types/node": "*",
- "chalk": "^4.1.2",
- "ci-info": "^4.2.0",
- "graceful-fs": "^4.2.11",
- "picomatch": "^4.0.2"
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
+ "node_modules/jest/node_modules/@sinclair/typebox": {
+ "version": "0.27.10",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
+ "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/jiti": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
@@ -8526,6 +14079,83 @@
"js-yaml": "bin/js-yaml.js"
}
},
+ "node_modules/jsdom": {
+ "version": "26.1.0",
+ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz",
+ "integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cssstyle": "^4.2.1",
+ "data-urls": "^5.0.0",
+ "decimal.js": "^10.5.0",
+ "html-encoding-sniffer": "^4.0.0",
+ "http-proxy-agent": "^7.0.2",
+ "https-proxy-agent": "^7.0.6",
+ "is-potential-custom-element-name": "^1.0.1",
+ "nwsapi": "^2.2.16",
+ "parse5": "^7.2.1",
+ "rrweb-cssom": "^0.8.0",
+ "saxes": "^6.0.0",
+ "symbol-tree": "^3.2.4",
+ "tough-cookie": "^5.1.1",
+ "w3c-xmlserializer": "^5.0.0",
+ "webidl-conversions": "^7.0.0",
+ "whatwg-encoding": "^3.1.1",
+ "whatwg-mimetype": "^4.0.0",
+ "whatwg-url": "^14.1.1",
+ "ws": "^8.18.0",
+ "xml-name-validator": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "canvas": "^3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "canvas": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jsdom/node_modules/tr46": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz",
+ "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "punycode": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/jsdom/node_modules/webidl-conversions": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
+ "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/jsdom/node_modules/whatwg-url": {
+ "version": "14.2.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz",
+ "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tr46": "^5.1.0",
+ "webidl-conversions": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/jsesc": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
@@ -8546,6 +14176,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/json-schema": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
@@ -8629,6 +14266,16 @@
"json-buffer": "3.0.1"
}
},
+ "node_modules/kleur": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
+ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/leven": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
@@ -8653,6 +14300,13 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/locate-path": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
@@ -8681,6 +14335,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/lodash.memoize": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
+ "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
@@ -8737,6 +14398,39 @@
"sourcemap-codec": "^1.4.8"
}
},
+ "node_modules/make-dir": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
+ "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/make-error": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
+ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/makeerror": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
+ "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "tmpl": "1.0.5"
+ }
+ },
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@@ -8756,6 +14450,13 @@
"node": ">= 0.8"
}
},
+ "node_modules/merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/micromatch": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
@@ -8790,6 +14491,16 @@
"wildcard": "^1.1.0"
}
},
+ "node_modules/mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/minimatch": {
"version": "10.2.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz",
@@ -8829,6 +14540,16 @@
"node": "18 || 20 || >=22"
}
},
+ "node_modules/minimist": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/minipass": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
@@ -8907,6 +14628,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/neo-async": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
+ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/node-fetch": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
@@ -8927,6 +14655,13 @@
}
}
},
+ "node_modules/node-int64": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
+ "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/node-releases": {
"version": "2.0.27",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz",
@@ -8934,6 +14669,16 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/npm-check-updates": {
"version": "19.6.3",
"resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-19.6.3.tgz",
@@ -8949,6 +14694,26 @@
"npm": ">=8.12.1"
}
},
+ "node_modules/npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/nwsapi": {
+ "version": "2.2.23",
+ "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.23.tgz",
+ "integrity": "sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@@ -9057,6 +14822,32 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/optionator": {
"version": "0.9.4",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
@@ -9153,6 +14944,16 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/package-json-from-dist": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
@@ -9173,6 +14974,38 @@
"node": ">=6"
}
},
+ "node_modules/parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parse5": {
+ "version": "7.3.0",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
+ "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "entities": "^6.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -9183,6 +15016,16 @@
"node": ">=8"
}
},
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
@@ -9245,6 +15088,85 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
+ "node_modules/pirates": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz",
+ "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/pkg-dir": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "find-up": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/possible-typed-array-names": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
@@ -9376,6 +15298,20 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
+ "node_modules/prompts": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
+ "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "kleur": "^3.0.3",
+ "sisteransi": "^1.0.5"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/prop-types": {
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
@@ -9405,6 +15341,23 @@
"node": ">=6"
}
},
+ "node_modules/pure-rand": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz",
+ "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/dubzzz"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fast-check"
+ }
+ ],
+ "license": "MIT"
+ },
"node_modules/quansync": {
"version": "0.2.11",
"resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz",
@@ -9677,6 +15630,16 @@
"regjsparser": "bin/parser"
}
},
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/require-from-string": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
@@ -9710,6 +15673,29 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/resolve-cwd": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
+ "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/resolve-cwd/node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/resolve-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
@@ -9720,6 +15706,16 @@
"node": ">=4"
}
},
+ "node_modules/resolve.exports": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz",
+ "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/rollup": {
"version": "4.59.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz",
@@ -9764,6 +15760,13 @@
"fsevents": "~2.3.2"
}
},
+ "node_modules/rrweb-cssom": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz",
+ "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/safe-array-concat": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz",
@@ -9840,6 +15843,26 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/saxes": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz",
+ "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "xmlchars": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=v12.22.7"
+ }
+ },
"node_modules/scheduler": {
"version": "0.27.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
@@ -10098,6 +16121,13 @@
"is-arrayish": "^0.3.1"
}
},
+ "node_modules/sisteransi": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
+ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/slash": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
@@ -10206,6 +16236,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
"node_modules/stack-utils": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
@@ -10229,6 +16266,17 @@
"node": ">=8"
}
},
+ "node_modules/standardized-audio-context": {
+ "version": "25.3.77",
+ "resolved": "https://registry.npmjs.org/standardized-audio-context/-/standardized-audio-context-25.3.77.tgz",
+ "integrity": "sha512-Ki9zNz6pKcC5Pi+QPjPyVsD9GwJIJWgryji0XL9cAJXMGyn+dPOf6Qik1AHei0+UNVcc4BOCa0hWLBzlwqsW/A==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.25.6",
+ "automation-events": "^7.0.9",
+ "tslib": "^2.7.0"
+ }
+ },
"node_modules/stop-iteration-iterator": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz",
@@ -10243,6 +16291,43 @@
"node": ">= 0.4"
}
},
+ "node_modules/string-length": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
+ "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "char-regex": "^1.0.2",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/string-length/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-length/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/string-width": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
@@ -10460,6 +16545,16 @@
"node": ">=8"
}
},
+ "node_modules/strip-bom": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
+ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/strip-comments": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz",
@@ -10470,6 +16565,16 @@
"node": ">=10"
}
},
+ "node_modules/strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/strip-json-comments": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
@@ -10525,6 +16630,13 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/symbol-tree": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
+ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/temp-dir": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz",
@@ -10540,37 +16652,98 @@
"resolved": "https://registry.npmjs.org/tempy/-/tempy-0.6.0.tgz",
"integrity": "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==",
"dev": true,
- "license": "MIT",
+ "license": "MIT",
+ "dependencies": {
+ "is-stream": "^2.0.0",
+ "temp-dir": "^2.0.0",
+ "type-fest": "^0.16.0",
+ "unique-string": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/terser": {
+ "version": "5.44.0",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.0.tgz",
+ "integrity": "sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w==",
+ "devOptional": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "@jridgewell/source-map": "^0.3.3",
+ "acorn": "^8.15.0",
+ "commander": "^2.20.0",
+ "source-map-support": "~0.5.20"
+ },
+ "bin": {
+ "terser": "bin/terser"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/test-exclude": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
+ "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@istanbuljs/schema": "^0.1.2",
+ "glob": "^7.1.4",
+ "minimatch": "^3.0.4"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/test-exclude/node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/test-exclude/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
+ "dev": true,
+ "license": "ISC",
"dependencies": {
- "is-stream": "^2.0.0",
- "temp-dir": "^2.0.0",
- "type-fest": "^0.16.0",
- "unique-string": "^2.0.0"
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
},
"engines": {
- "node": ">=10"
+ "node": "*"
},
"funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/terser": {
- "version": "5.44.0",
- "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.0.tgz",
- "integrity": "sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w==",
- "devOptional": true,
- "license": "BSD-2-Clause",
+ "node_modules/test-exclude/node_modules/minimatch": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
+ "dev": true,
+ "license": "ISC",
"dependencies": {
- "@jridgewell/source-map": "^0.3.3",
- "acorn": "^8.15.0",
- "commander": "^2.20.0",
- "source-map-support": "~0.5.20"
- },
- "bin": {
- "terser": "bin/terser"
+ "brace-expansion": "^1.1.7"
},
"engines": {
- "node": ">=10"
+ "node": "*"
}
},
"node_modules/tinyglobby": {
@@ -10589,6 +16762,33 @@
"url": "https://github.com/sponsors/SuperchupuDev"
}
},
+ "node_modules/tldts": {
+ "version": "6.1.86",
+ "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz",
+ "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tldts-core": "^6.1.86"
+ },
+ "bin": {
+ "tldts": "bin/cli.js"
+ }
+ },
+ "node_modules/tldts-core": {
+ "version": "6.1.86",
+ "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz",
+ "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/tmpl": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
+ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
"node_modules/to-data-view": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/to-data-view/-/to-data-view-1.1.0.tgz",
@@ -10626,6 +16826,29 @@
"url": "https://github.com/sponsors/Borewit"
}
},
+ "node_modules/tone": {
+ "version": "15.1.22",
+ "resolved": "https://registry.npmjs.org/tone/-/tone-15.1.22.tgz",
+ "integrity": "sha512-TCScAGD4sLsama5DjvTUXlLDXSqPealhL64nsdV1hhr6frPWve0DeSo63AKnSJwgfg55fhvxj0iPPRwPN5o0ag==",
+ "license": "MIT",
+ "dependencies": {
+ "standardized-audio-context": "^25.3.70",
+ "tslib": "^2.3.1"
+ }
+ },
+ "node_modules/tough-cookie": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz",
+ "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "tldts": "^6.1.32"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
@@ -10645,6 +16868,72 @@
"typescript": ">=4.8.4"
}
},
+ "node_modules/ts-jest": {
+ "version": "29.4.6",
+ "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.6.tgz",
+ "integrity": "sha512-fSpWtOO/1AjSNQguk43hb/JCo16oJDnMJf3CdEGNkqsEX3t0KX96xvyX1D7PfLCpVoKu4MfVrqUkFyblYoY4lA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "bs-logger": "^0.2.6",
+ "fast-json-stable-stringify": "^2.1.0",
+ "handlebars": "^4.7.8",
+ "json5": "^2.2.3",
+ "lodash.memoize": "^4.1.2",
+ "make-error": "^1.3.6",
+ "semver": "^7.7.3",
+ "type-fest": "^4.41.0",
+ "yargs-parser": "^21.1.1"
+ },
+ "bin": {
+ "ts-jest": "cli.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": ">=7.0.0-beta.0 <8",
+ "@jest/transform": "^29.0.0 || ^30.0.0",
+ "@jest/types": "^29.0.0 || ^30.0.0",
+ "babel-jest": "^29.0.0 || ^30.0.0",
+ "jest": "^29.0.0 || ^30.0.0",
+ "jest-util": "^29.0.0 || ^30.0.0",
+ "typescript": ">=4.3 <6"
+ },
+ "peerDependenciesMeta": {
+ "@babel/core": {
+ "optional": true
+ },
+ "@jest/transform": {
+ "optional": true
+ },
+ "@jest/types": {
+ "optional": true
+ },
+ "babel-jest": {
+ "optional": true
+ },
+ "esbuild": {
+ "optional": true
+ },
+ "jest-util": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/ts-jest/node_modules/type-fest": {
+ "version": "4.41.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz",
+ "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
@@ -10664,6 +16953,16 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/type-detect": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
+ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/type-fest": {
"version": "0.16.0",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz",
@@ -10770,6 +17069,20 @@
"node": ">=14.17"
}
},
+ "node_modules/uglify-js": {
+ "version": "3.19.3",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz",
+ "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "optional": true,
+ "bin": {
+ "uglifyjs": "bin/uglifyjs"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
"node_modules/uint8array-extras": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.5.0.tgz",
@@ -11008,6 +17321,21 @@
"uuid": "dist/bin/uuid"
}
},
+ "node_modules/v8-to-istanbul": {
+ "version": "9.3.0",
+ "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz",
+ "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.12",
+ "@types/istanbul-lib-coverage": "^2.0.1",
+ "convert-source-map": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10.12.0"
+ }
+ },
"node_modules/vite": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz",
@@ -11163,12 +17491,59 @@
"node": ">=0.10.0"
}
},
+ "node_modules/w3c-xmlserializer": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz",
+ "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "xml-name-validator": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/walker": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
+ "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "makeerror": "1.0.12"
+ }
+ },
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
"license": "BSD-2-Clause"
},
+ "node_modules/whatwg-encoding": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
+ "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
+ "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "iconv-lite": "0.6.3"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/whatwg-mimetype": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
+ "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
@@ -11306,6 +17681,13 @@
"node": ">=0.10.0"
}
},
+ "node_modules/wordwrap": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+ "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/workbox-background-sync": {
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-7.4.0.tgz",
@@ -11458,9 +17840,9 @@
"license": "MIT"
},
"node_modules/workbox-build/node_modules/ajv": {
- "version": "8.17.1",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
- "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
+ "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -11515,9 +17897,9 @@
}
},
"node_modules/workbox-build/node_modules/rollup": {
- "version": "2.79.2",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz",
- "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==",
+ "version": "2.80.0",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.80.0.tgz",
+ "integrity": "sha512-cIFJOD1DESzpjOBl763Kp1AH7UE/0fcdHe6rZXUdQ9c50uvgigvW97u3IcSeBwOkgqL/PXPBktBCh0KEu5L8XQ==",
"dev": true,
"license": "MIT",
"bin": {
@@ -11762,6 +18144,83 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/write-file-atomic": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz",
+ "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.7"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/write-file-atomic/node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/ws": {
+ "version": "8.19.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz",
+ "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/xml-name-validator": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz",
+ "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/xmlchars": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
+ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/yallist": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
@@ -11769,6 +18228,80 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/yargs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/yargs/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/yargs/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
diff --git a/Build/package.json b/Build/package.json
index 25b3bf4..7efce76 100644
--- a/Build/package.json
+++ b/Build/package.json
@@ -14,7 +14,9 @@
"tauri": "tauri",
"start": "cd dist && python3 -m http.server 8000",
"preview": "vite preview",
- "test": "react-scripts test",
+ "test": "jest",
+ "test:run": "jest --passWithNoTests",
+ "test:watch": "jest --watch",
"lint": "eslint 'src/**/*.ts' 'src/**/*.tsx'",
"eject": "react-scripts eject",
"make-pretty": "prettier --write 'src/**/*.{ts,tsx,js,jsx,json,css,scss,md,html,cjs}'",
@@ -64,6 +66,7 @@
"react-i18next": "^16.5.8",
"react-icons": "^5.6.0",
"sonner": "^2.0.7",
+ "tone": "^15.1.22",
"vite-plugin-singlefile": "^2.3.2",
"zustand": "^5.0.12"
},
@@ -83,8 +86,11 @@
"cross-env": "^10.1.0",
"eslint": "^9.39.4",
"eslint-plugin-react": "^7.37.5",
+ "jest": "^29.7.0",
+ "jest-environment-jsdom": "^30.3.0",
"npm-check-updates": "^19.6.3",
"prettier": "^3.8.1",
+ "ts-jest": "^29.1.2",
"vite": "^7.3.1",
"vite-plugin-pwa": "^1.2.0",
"vite-plugin-top-level-await": "^1.6.0",
diff --git a/Build/privacy.html b/Build/privacy.html
new file mode 100644
index 0000000..374f09c
--- /dev/null
+++ b/Build/privacy.html
@@ -0,0 +1,34 @@
+
+
+
+
+
+ HTMLPlayer Privacy Policy
+
+
+
+
+
+
+
+
+
+
diff --git a/Build/public/privacy.html b/Build/public/privacy.html
deleted file mode 100644
index 1181ae2..0000000
--- a/Build/public/privacy.html
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
-
- HTMLPlayer Privacy Policy
-
-
-
- HTMLPlayer Privacy Policy
- Effective Date: 9/23/2025
-
- 1. Introduction
-
- HTMLPlayer respects your privacy. Since the App is primarily client-side,
- we do not collect personal data unless you interact with external services
- (e.g., Discord integration).
-
-
- 2. Data Collection
-
- The App does not collect personal information by default.
-
- Optional Discord integration may send limited information (username,
- current activity) to Discord's servers for the purpose of updating your
- music activity.
-
-
-
- 3. Cookies and Tracking
-
- HTMLPlayer does not use cookies or trackers for analytics or advertising.
-
-
- 4. Third-Party Services
-
- Discord integration is managed via OAuth; your authorization is handled by
- Discord directly. HTMLPlayer does not store Discord credentials or share
- data outside the Discord API.
-
-
- 5. Security
-
- All client-side operations run in your browser; no server-side storage of
- music or personal data occurs. We take no responsibility for security
- vulnerabilities in your browser or Discord.
-
-
- 6. Data Sharing
-
- HTMLPlayer does not sell, trade, or share personal information with third
- parties, except through authorized use of Discord features.
-
-
- 7. Updates to Privacy Policy
-
- We may update this Privacy Policy as HTMLPlayer evolves. Continued use
- indicates acceptance of the latest policy.
-
-
- 8. Contact
-
- For privacy questions, contact:
- nellowtcs@gmail.com
-
-
-
diff --git a/Build/public/tos.html b/Build/public/tos.html
deleted file mode 100644
index a3c61b6..0000000
--- a/Build/public/tos.html
+++ /dev/null
@@ -1,92 +0,0 @@
-
-
-
-
-
- HTMLPlayer Terms of Service
-
-
-
- HTMLPlayer Terms of Service (TOS)
- Effective Date: 9/23/2025
-
- 1. Acceptance of Terms
-
- By using HTMLPlayer (the "App"), you agree to these Terms of Service. If
- you do not agree, do not use the App.
-
-
- 2. Use of the App
-
- HTMLPlayer is a free, open-source music player.
-
- All core functionality runs client-side in your browser; we do not
- collect usage data except when explicitly interacting with external
- services like Discord.
-
- You may use the App for personal, non-commercial purposes.
-
-
- 3. Intellectual Property
-
- HTMLPlayer and its source code are licensed under the
- MIT License . You may copy, modify, or redistribute the App according to the MIT
- License terms.
-
-
- 4. Discord Integration
-
- The App may optionally integrate with Discord to display music activity.
- Access to Discord features requires you to authorize HTMLPlayer via
- Discord OAuth. HTMLPlayer does not store your Discord credentials.
-
-
- 5. Beta Disclaimer
-
- HTMLPlayer is currently in beta. Features may be unstable or incomplete.
- Use at your own risk.
-
-
- 6. No Warranty
-
- The App is provided "as-is" without warranty of any kind, either express
- or implied. The developers are not liable for any damages arising from the
- use or inability to use HTMLPlayer.
-
-
- 7. Limitation of Liability
-
- You use HTMLPlayer entirely at your own risk. Developers are not
- responsible for any loss, data corruption, or other issues resulting from
- your use of the App.
-
-
- 8. Modifications to Terms
-
- We may update these Terms at any time. Continued use constitutes
- acceptance of the updated Terms.
-
-
- 9. Contact
-
- For questions about these Terms, contact:
- nellowtcs@gmail.com
-
-
-
diff --git a/Build/src/components/Playlist.tsx b/Build/src/components/Playlist.tsx
deleted file mode 100644
index 5abfd98..0000000
--- a/Build/src/components/Playlist.tsx
+++ /dev/null
@@ -1,1070 +0,0 @@
-import {
- useState,
- useEffect,
- JSX,
- memo,
- useCallback,
- useMemo,
- useRef,
-} from "react";
-import { useTranslation } from "react-i18next";
-import { toast } from "sonner";
-import { DropZone, DraggableItem } from "./Draggable";
-import styles from "./Playlist.module.css";
-import { generatePlaylistImage } from "../helpers/playlistImageHelper";
-import modalStyles from "./Dialog.module.css";
-import { Button } from "./Button";
-import { Input } from "./Input";
-import {
- Dialog,
- DialogContent,
- DialogHeader,
- DialogTitle,
- DialogDescription,
- DialogFooter,
-} from "./Dialog";
-import {
- Collapsible,
- CollapsibleTrigger,
- CollapsibleContent,
-} from "./Collapsible";
-import {
- DropdownMenu,
- DropdownMenuTrigger,
- DropdownMenuContent,
- DropdownMenuItem,
- DropdownMenuSeparator,
- useRightClickMenu,
-} from "./DropdownMenu";
-import { ScrollText } from "./ScrollText";
-import { Icon } from "./Icon";
-import { musicIndexedDbHelper } from "../helpers/musicIndexedDbHelper";
-
-interface PlaylistProps {
- musicPlayerHook: ReturnType<
- typeof import("../hooks/musicPlayerHook").useMusicPlayer
- >;
-}
-
-export const PlaylistComponent = ({ musicPlayerHook }: PlaylistProps) => {
- const { t } = useTranslation();
- const [playlistSearchQuery, setPlaylistSearchQuery] = useState("");
- const [showCreatePlaylist, setShowCreatePlaylist] = useState(false);
- const [newPlaylistName, setNewPlaylistName] = useState("");
- const [playlistImages, setPlaylistImages] = useState>(
- {},
- );
- const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);
- const [playlistToDelete, setPlaylistToDelete] = useState<
- Playlist | PlaylistFolder | null
- >(null);
- const [openFolders, setOpenFolders] = useState>(new Set());
-
- const toggleFolder = useCallback((folderId: string) => {
- setOpenFolders((prev) => {
- const newSet = new Set(prev);
- if (newSet.has(folderId)) {
- newSet.delete(folderId);
- } else {
- newSet.add(folderId);
- }
- return newSet;
- });
- }, []);
-
- const [showMoveDialog, setShowMoveDialog] = useState(false);
- const [itemToMove, setItemToMove] = useState<
- Playlist | PlaylistFolder | null
- >(null);
- const [availableFolders, setAvailableFolders] = useState<
- { folder: PlaylistFolder; path: string[] }[]
- >([]);
- const [showRenameDialog, setShowRenameDialog] = useState(false);
- const [itemToRename, setItemToRename] = useState<
- Playlist | PlaylistFolder | null
- >(null);
- const [renameValue, setRenameValue] = useState("");
-
- const [showCreateFolderDialog, setShowCreateFolderDialog] = useState(false);
- const [newFolderName, setNewFolderName] = useState("");
-
- const {
- library,
- playSong,
- createPlaylist,
- createFolder,
- removePlaylist,
- moveToFolder,
- exportPlaylist,
- importPlaylist,
- navigateToSongs,
- } = musicPlayerHook;
-
- // Debounced and batched playlist image generation to prevent RAM spikes
- useEffect(() => {
- let isCancelled = false;
-
- const updatePlaylistImages = async () => {
- const newImages: Record = {};
-
- // Recursive function to find all playlists in the tree
- const findAllPlaylists = (
- items: (Playlist | PlaylistFolder)[],
- ): Playlist[] => {
- const result: Playlist[] = [];
- for (const item of items) {
- if ("children" in item) {
- // This is a folder, recurse into children
- result.push(...findAllPlaylists(item.children));
- } else if ("songs" in item) {
- // This is a playlist
- result.push(item);
- }
- }
- return result;
- };
-
- const allPlaylists = findAllPlaylists(library.playlists);
-
- // Process playlist images in batches to prevent RAM spikes
- const BATCH_SIZE = 5;
- const BATCH_DELAY = 50; // ms between batches
-
- for (let i = 0; i < allPlaylists.length; i += BATCH_SIZE) {
- if (isCancelled) return;
-
- const batch = allPlaylists.slice(i, i + BATCH_SIZE);
-
- // Process batch in parallel but limited
- await Promise.all(
- batch.map(async (playlist) => {
- if (playlist.id !== "all-songs") {
- try {
- const image = await generatePlaylistImage(playlist.songs);
- if (image && !isCancelled) {
- newImages[playlist.id] = image;
- }
- } catch (error) {
- console.warn(
- `Failed to generate image for playlist ${playlist.id}:`,
- error,
- );
- }
- }
- }),
- );
-
- // Update state incrementally to show progress and yield to main thread
- if (!isCancelled) {
- setPlaylistImages((prev) => ({ ...prev, ...newImages }));
- }
-
- // Yield to main thread between batches
- if (i + BATCH_SIZE < allPlaylists.length) {
- await new Promise((resolve) => setTimeout(resolve, BATCH_DELAY));
- }
- }
- };
-
- // Delay initial image generation to let the UI render first
- const timeoutId = setTimeout(updatePlaylistImages, 100);
-
- return () => {
- isCancelled = true;
- clearTimeout(timeoutId);
- };
- }, [library.playlists, library.songs]);
-
- const getAllPlaylists = useCallback(
- (items: (Playlist | PlaylistFolder)[]): (Playlist | PlaylistFolder)[] => {
- const result: (Playlist | PlaylistFolder)[] = [];
- for (const item of items) {
- result.push(item);
- if ("children" in item) {
- result.push(...getAllPlaylists(item.children));
- }
- }
- return result;
- },
- [],
- );
-
- const filteredPlaylists = useMemo(
- () =>
- library.playlists.filter(
- (item) =>
- item.id !== "all-songs" &&
- item.name.toLowerCase().includes(playlistSearchQuery.toLowerCase()),
- ),
- [library.playlists, playlistSearchQuery],
- );
-
- const handlePlaylistSearch = (query: string) => setPlaylistSearchQuery(query);
-
- const handlePlaylistSelect = useCallback(
- (playlist: Playlist) => {
- if (playlist.songs.length > 0) playSong(playlist.songs[0], playlist);
- },
- [playSong],
- );
-
- const handleAllSongsClick = useCallback(() => {
- const existingAllSongs = library.playlists.find(
- (p) => p.id === "all-songs",
- );
- if (
- existingAllSongs &&
- "songs" in existingAllSongs &&
- existingAllSongs.songs.length > 0
- ) {
- playSong(existingAllSongs.songs[0], existingAllSongs);
- navigateToSongs();
- } else if (library.songs.length > 0) {
- const allSongsPlaylist: Playlist = {
- id: "all-songs",
- name: t("allSongs"),
- songs: library.songs,
- };
- playSong(allSongsPlaylist.songs[0], allSongsPlaylist);
- navigateToSongs();
- }
- }, [library.playlists, library.songs, playSong, navigateToSongs]);
-
- const handleAddPlaylist = () => {
- setShowCreatePlaylist(true);
- setNewPlaylistName("");
- };
-
- const handleCreatePlaylistConfirm = useCallback(() => {
- if (!newPlaylistName.trim()) return;
-
- createPlaylist(newPlaylistName.trim());
- toast.success(
- t("playlist.playlistCreated", { name: newPlaylistName.trim() }),
- );
-
- setShowCreatePlaylist(false);
- setNewPlaylistName("");
- }, [newPlaylistName, createPlaylist]);
-
- const handleCreatePlaylistCancel = () => {
- setShowCreatePlaylist(false);
- setNewPlaylistName("");
- };
-
- const handleDeletePlaylist = async (playlist: Playlist) => {
- // Check if user has chosen not to show delete confirmation
- const shouldShow = await musicIndexedDbHelper.shouldShowDialog(
- "delete-playlist-confirmation",
- );
- if (!shouldShow) {
- // Delete directly without showing dialog
- removePlaylist(playlist.id);
- toast.success(t("playlist.playlistDeleted", { name: playlist.name }));
- return;
- }
-
- // Show confirmation dialog
- setPlaylistToDelete(playlist);
- setIsDeleteDialogOpen(true);
- };
-
- const handleDeleteConfirm = useCallback(() => {
- if (!playlistToDelete) return;
- removePlaylist(playlistToDelete.id);
- toast.success(
- t("playlist.playlistDeleted", { name: playlistToDelete.name }),
- );
- setIsDeleteDialogOpen(false);
- setPlaylistToDelete(null);
- }, [playlistToDelete, removePlaylist]);
-
- const handleSharePlaylist = useCallback((playlist: Playlist) => {
- // Share just the playlist info, not the URL
- const shareData = {
- title: t("playlist.playlistShareTitle", { name: playlist.name }),
- text: t("playlist.playlistShareText", {
- name: playlist.name,
- count: playlist.songs.length,
- }),
- };
-
- try {
- if (
- navigator.share &&
- navigator.canShare &&
- navigator.canShare(shareData)
- ) {
- navigator.share(shareData);
- toast.success(t("playlist.playlistShared"));
- } else {
- navigator.clipboard.writeText(`${shareData.title}\n${shareData.text}`);
- toast.success(t("playlist.playlistCopied"));
- }
- } catch {
- toast.error(t("playlist.playlistShareFailed"));
- }
- }, []);
-
- const handleExportPlaylist = useCallback(
- (playlist: Playlist, format: "json" | "m3u" = "json") => {
- exportPlaylist(playlist, format);
- },
- [exportPlaylist],
- );
-
- const getPlaylistIcon = useCallback((playlistName: string) => {
- if (playlistName.toLowerCase().includes("favorite")) {
- return ;
- }
- if (playlistName.toLowerCase().includes("made")) {
- return ;
- }
- return ;
- }, []);
-
- const handleImportPlaylist = () => {
- const input = document.createElement("input");
- input.type = "file";
- input.accept = ".json,.m3u,.m3u8";
- input.onchange = async (e) => {
- const file = (e.target as HTMLInputElement).files?.[0];
- if (file) {
- try {
- await importPlaylist(file);
- } catch (error) {
- // Error handling is done in the importPlaylist function
- error && setIsDeleteDialogOpen(false); // Dummy usage to avoid lint error
- }
- }
- };
- input.click();
- };
-
- const handleMoveToFolder = useCallback(
- (item: Playlist | PlaylistFolder) => {
- // Recursive function to get all folders
- const getAllFolders = (
- items: (Playlist | PlaylistFolder)[],
- path: string[] = [],
- ): { folder: PlaylistFolder; path: string[] }[] => {
- const folders: { folder: PlaylistFolder; path: string[] }[] = [];
- for (const item of items) {
- if ("children" in item) {
- folders.push({ folder: item, path: [...path] });
- folders.push(...getAllFolders(item.children, [...path, item.name]));
- }
- }
- return folders;
- };
-
- const allFolders = getAllFolders(library.playlists);
- // Always allow moving even if no folders, can move to root
- setAvailableFolders(allFolders);
- setItemToMove(item);
- setShowMoveDialog(true);
- },
- [library.playlists],
- );
-
- const handleRenameItem = useCallback((item: Playlist | PlaylistFolder) => {
- setItemToRename(item);
- setRenameValue(item.name);
- setShowRenameDialog(true);
- }, []);
-
- const playlistListRef = useRef(null);
-
- const renderPlaylistItem = (item: Playlist | PlaylistFolder, depth = 0) => {
- if ("songs" in item) {
- return ;
- } else {
- return (
-
- );
- }
- };
-
- const PlaylistItem = memo(
- ({ item, depth }: { item: Playlist; depth: number }) => {
- const { open, setOpen, containerRef } = useRightClickMenu(true);
-
- return (
-
-
-
-
- handlePlaylistSelect(item)}
- >
- {playlistImages[item.id] ? (
-
-
-
- ) : (
- getPlaylistIcon(item.name)
- )}
-
-
-
- {item.songs.length}
-
-
-
-
-
-
-
-
-
-
-
-
- handleRenameItem(item)}>
-
- {t("playlist.renamePlaylist")}
-
- handleSharePlaylist(item)}>
-
- {t("playlist.sharePlaylist")}
-
-
- handleMoveToFolder(item)}>
-
- {t("playlist.moveToFolder")}
-
- {
- moveToFolder(item.id, null); // Move to root
- toast.success(t("playlist.movedToRoot", { item: item.name }));
- }}
- >
-
- {t("playlist.moveToRoot")}
-
-
- handleExportPlaylist(item, "json")}
- >
-
- {t("playlist.exportJSON")}
-
- handleExportPlaylist(item, "m3u")}
- >
-
- {t("playlist.exportM3U")}
-
-
- handleDeletePlaylist(item)}
- className={styles.deleteMenuItem}
- >
-
- {t("playlist.deletePlaylist")}
-
-
-
-
- );
- },
- );
-
- const FolderItem = memo(
- ({
- item,
- depth,
- renderPlaylistItem,
- }: {
- item: PlaylistFolder;
- depth: number;
- renderPlaylistItem: (
- item: Playlist | PlaylistFolder,
- depth: number,
- ) => JSX.Element;
- }) => {
- const isOpen = openFolders.has(item.id);
- const { open, setOpen, containerRef } = useRightClickMenu(true);
-
- return (
- toggleFolder(item.id)}
- >
-
- {/* Folder header */}
-
-
-
-
-
-
-
-
-
-
-
- {item.children.length}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- handleRenameItem(item)}>
-
- {t("playlist.renameFolder")}
-
-
- handleMoveToFolder(item)}>
-
- {t("playlist.moveToFolder")}
-
- {
- moveToFolder(item.id, null); // Move to root
- toast.success(
- t("playlist.movedToRoot", { item: item.name }),
- );
- }}
- >
-
- {t("playlist.moveToRoot")}
-
-
- {
- // Check if user has chosen not to show delete confirmation
- const shouldShow =
- await musicIndexedDbHelper.shouldShowDialog(
- "delete-playlist-confirmation",
- );
- if (!shouldShow) {
- // Delete directly without showing dialog
- removePlaylist(item.id);
- toast.success(
- t("playlist.folderDeleted", { name: item.name }),
- );
- return;
- }
-
- // Show confirmation dialog
- setPlaylistToDelete(item);
- setIsDeleteDialogOpen(true);
- }}
- className={styles.deleteMenuItem}
- >
-
- {t("playlist.deleteFolder")}
-
-
-
-
-
-
- {item.children.map((child) =>
- renderPlaylistItem(child, depth + 1),
- )}
- {/* Empty folder, centered with i18n */}
- {item.children.length === 0 && (
-
- {t("playlist.emptyFolder")}
-
- )}
-
-
-
- );
- },
- );
-
- return (
-
-
-
-
-
-
-
handlePlaylistSearch(e.target.value)}
- />
-
-
-
-
-
-
-
-
-
-
- {t("playlist.addPlaylist")}
-
- setShowCreateFolderDialog(true)}>
-
- {t("playlist.addFolder")}
-
-
-
-
- {t("playlist.importPlaylist")}
-
-
-
-
-
-
- {/* All Songs */}
-
-
- {t("allSongs")}
- {library.songs.length}
-
-
- {/* Favorites */}
-
- handlePlaylistSelect({
- id: "favorites",
- name: t("favorites.favorites"),
- songs: library.songs.filter((s) =>
- library.favorites.includes(s.id),
- ),
- })
- }
- >
-
- {t("favorites.favorites")}
- {library.favorites.length}
-
-
- {/* User playlists and folders */}
- {filteredPlaylists.map((item) => renderPlaylistItem(item))}
-
- {filteredPlaylists.length === 0 && playlistSearchQuery && (
-
{t("noPlaylistsFound")}
- )}
-
-
- {/* Create Playlist Modal */}
-
-
-
- {t("playlist.createPlaylist")}
-
- {t("playlist.enterPlaylistName")}
-
-
-
- setNewPlaylistName(e.target.value)}
- onKeyDown={(e: any) => {
- if (e.key === "Enter") handleCreatePlaylistConfirm();
- }}
- autoFocus
- />
-
-
-
- {t("common.cancel")}
-
-
- {t("common.create")}
-
-
-
-
-
- {/* Move to Folder Dialog */}
-
-
-
- {t("playlist.moveToFolder")}
-
- {t("playlist.selectFolderToMove", { item: itemToMove?.name })}
-
-
-
- {/* Move to Root option */}
- {
- if (itemToMove) {
- moveToFolder(itemToMove.id, null);
- toast.success(
- t("playlist.movedToRoot", { item: itemToMove?.name }),
- );
- }
- setShowMoveDialog(false);
- setItemToMove(null);
- }}
- >
- 📁 {t("playlist.moveToRoot")}
-
- {availableFolders.map(({ folder, path }) => (
- {
- if (itemToMove) moveToFolder(itemToMove.id, folder.id);
- toast.success(
- t("playlist.movedToFolder", {
- item: itemToMove?.name,
- folder: folder.name,
- }),
- );
- setShowMoveDialog(false);
- setItemToMove(null);
- }}
- >
- {path.length > 0
- ? `${path.join(" / ")} / ${folder.name}`
- : folder.name}
-
- ))}
-
-
- setShowMoveDialog(false)}>
- {t("common.cancel")}
-
-
-
-
-
- {/* Rename Dialog */}
-
-
-
-
- {itemToRename && "songs" in itemToRename
- ? t("playlist.renamePlaylist")
- : t("playlist.renameFolder")}
-
- {t("playlist.enterNewName")}
-
-
- setRenameValue(e.target.value)}
- />
-
-
- setShowRenameDialog(false)}
- >
- {t("common.cancel")}
-
- {
- if (itemToRename && renameValue.trim()) {
- itemToRename.name = renameValue.trim();
- toast.success(
- itemToRename && "songs" in itemToRename
- ? t("playlist.playlistRenamed", {
- name: renameValue.trim(),
- })
- : t("playlist.folderRenamed", {
- name: renameValue.trim(),
- }),
- );
- setShowRenameDialog(false);
- setItemToRename(null);
- setRenameValue("");
- }
- }}
- >
- {t("common.save")}
-
-
-
-
-
- {/* Delete Confirmation */}
-
-
-
-
- {playlistToDelete && "songs" in playlistToDelete
- ? t("playlist.deletePlaylist")
- : t("playlist.deleteFolder")}
-
-
- {playlistToDelete
- ? "songs" in playlistToDelete
- ? t("playlist.deletePlaylistConfirmation", {
- name: playlistToDelete.name,
- })
- : t("playlist.deleteFolderConfirmation", {
- name: playlistToDelete.name,
- })
- : ""}
-
-
-
- setIsDeleteDialogOpen(false)}
- >
- {t("common.cancel")}
-
-
- {t("common.delete")}
-
-
-
-
-
- {/* Create Folder Dialog */}
-
-
-
- {t("playlist.createFolder")}
-
- {t("playlist.enterFolderName")}
-
-
-
- setNewFolderName(e.target.value)}
- />
-
-
- {
- setShowCreateFolderDialog(false);
- setNewFolderName("");
- }}
- >
- {t("common.cancel")}
-
- {
- if (newFolderName.trim()) {
- createFolder(newFolderName.trim());
- toast.success(
- t("playlist.folderCreated", { name: newFolderName.trim() }),
- );
- setShowCreateFolderDialog(false);
- setNewFolderName("");
- }
- }}
- >
- {t("common.create")}
-
-
-
-
-
- );
-};
-
-export default memo(PlaylistComponent, (prevProps, nextProps) => {
- // Only re-render if the library playlists or songs have actually changed
- return (
- prevProps.musicPlayerHook.library.playlists ===
- nextProps.musicPlayerHook.library.playlists &&
- prevProps.musicPlayerHook.library.songs ===
- nextProps.musicPlayerHook.library.songs &&
- prevProps.musicPlayerHook.library.favorites ===
- nextProps.musicPlayerHook.library.favorites
- );
-});
diff --git a/Build/src/components/Settings.tsx b/Build/src/components/Settings.tsx
deleted file mode 100644
index 46c8578..0000000
--- a/Build/src/components/Settings.tsx
+++ /dev/null
@@ -1,1107 +0,0 @@
-import {
- Sheet,
- SheetContent,
- SheetDescription,
- SheetFooter,
- SheetHeader,
- SheetTitle,
-} from "./Sheet";
-import { Button } from "./Button";
-import { Switch } from "./Switch";
-import { Slider } from "./Slider";
-import { Input } from "./Input";
-import {
- Select,
- SelectContent,
- SelectItem,
- SelectTrigger,
- SelectValue,
-} from "./Select";
-import { ThemeModeSwitch } from "./ThemeModeSwitch";
-import { ShortcutConfig } from "./ShortcutConfig";
-import styles from "./Settings.module.css";
-import { useThemeLoader } from "../helpers/themeLoader";
-import { useIconRegistry } from "../helpers/iconLoader";
-import { useWallpaperLoader } from "../helpers/wallpaperLoader";
-import { toast } from "sonner";
-import { useRef, useState, useEffect, JSX } from "react";
-import { useTranslation } from "react-i18next";
-import { languageNames } from "../types/supportedLanguages";
-import { isSafari } from "../helpers/safariHelper";
-import { Icon } from "./Icon";
-import { isTauri } from "@tauri-apps/api/core";
-
-import { resetAllDialogPreferences } from "../helpers/musicIndexedDbHelper";
-import {
- Dialog,
- DialogContent,
- DialogDescription,
- DialogFooter,
- DialogHeader,
- DialogTitle,
-} from "./Dialog";
-
-export interface SettingsProps {
- className?: string;
- open?: boolean;
- onOpenChange?: (open: boolean) => void;
- settings: PlayerSettings;
- onSettingsChange: (settings: Partial) => void;
- onShortcutsChanged?: () => void;
-}
-
-type SettingsCategory = "playback" | "interface" | "shortcuts" | "experimental";
-
-export const Settings = ({
- className,
- open,
- onOpenChange,
- settings,
- onSettingsChange,
- onShortcutsChanged,
-}: SettingsProps) => {
- const { t, i18n } = useTranslation();
-
- // State for dialog reset button
- const [dialogResetOpen, setDialogResetOpen] = useState(false);
- const [dialogResetLoading, setDialogResetLoading] = useState(false);
- const [activeCategory, setActiveCategory] =
- useState("playback");
-
- const handleDialogResetClose = () => setDialogResetOpen(false);
-
- // Use the persisted crossfadeBeforeGapless value, fallback to current crossfade
- const previousCrossfadeRef = useRef(
- settings.crossfadeBeforeGapless ?? settings.crossfade,
- );
-
- const { themes, currentTheme, setTheme } = useThemeLoader();
- const { iconSets, currentSet, setIconSet } = useIconRegistry();
- const { wallpapers, setWallpaper } = useWallpaperLoader();
-
- // Check if running on Safari
- const isOnSafari = isSafari();
-
- // Initialize Eruda if it was previously enabled
- useEffect(() => {
- if (settings.erudaEnabled && !(window as any).eruda) {
- loadEruda().catch(console.error);
- }
- }, [settings.erudaEnabled]);
-
- const handleResetSettings = async () => {
- const defaultThemeName = "Blue";
- try {
- await setTheme(defaultThemeName);
- onSettingsChange({
- volume: 0.75,
- crossfade: 3,
- crossfadeBeforeGapless: undefined,
- defaultShuffle: false,
- defaultRepeat: "off",
- autoPlayNext: true,
- compactMode: false,
- showAlbumArt: true,
- showLyrics: false,
- sessionRestore: true,
- gaplessPlayback: false,
- smartShuffle: true,
- colorTheme: defaultThemeName,
- wallpaper: "None",
- language: "English",
- tempo: 1,
- pitch: 0,
- discordEnabled: false,
- discordUserId: undefined,
- erudaEnabled: false,
- });
- } catch {
- toast.error(t("settings.resetError"));
- }
- };
-
- const handleVolumeChange = (newVolume: number[]) => {
- onSettingsChange({ volume: newVolume[0] / 100 });
- };
-
- const handleCrossfadeChange = (newCrossfade: number[]) => {
- // Prevent crossfade changes when gapless playback is enabled
- if (settings.gaplessPlayback) {
- return;
- }
- const newValue = newCrossfade[0];
- previousCrossfadeRef.current = newValue; // Update stored value
- onSettingsChange({
- crossfade: newValue,
- crossfadeBeforeGapless: undefined, // Clear stored value when manually changed
- });
- };
-
- // Get supported languages dynamically from i18next config
- let languages: string[] = [];
-
- // Only use filter if supportedLngs is an array
- if (Array.isArray(i18n.options.supportedLngs)) {
- languages = i18n.options.supportedLngs.filter((l) => l !== "cimode");
- }
-
- const handleLanguageChange = (lang: string) => {
- i18n.changeLanguage(lang);
- toast.success(
- t("settings.interface.languageSet", {
- language: languageNames[lang] || lang,
- }),
- );
- };
-
- const handleClearCache = async () => {
- try {
- // Clear all cache storage (service worker caches)
- if ("caches" in window) {
- const cacheNames = await caches.keys();
- await Promise.all(
- cacheNames.map((cacheName) => caches.delete(cacheName)),
- );
- }
-
- // Clear i18n resource cache
- if (i18n.services.resourceStore) {
- Object.keys(i18n.services.resourceStore.data).forEach((lang) => {
- i18n.services.resourceStore.data[lang] = {};
- });
- }
-
- // Reload i18n resources
- await i18n.reloadResources();
-
- toast.success(t("settings.cacheClearedSuccess"));
- } catch (error) {
- console.error("Failed to clear cache:", error);
- toast.error(t("settings.cacheClearedError"));
- }
- };
-
- const [discordRpcStatus, setDiscordRpcStatus] = useState<
- "unknown" | "available" | "unavailable" | "unsupported"
- >("unknown");
-
- const isTauriEnv = isTauri();
-
- const checkDiscordRpcStatus = async () => {
- if (!isTauriEnv) {
- setDiscordRpcStatus("unsupported");
- return;
- }
-
- try {
- const { invoke } = await import("@tauri-apps/api/core");
- const available = await invoke("is_discord_running");
- setDiscordRpcStatus(available ? "available" : "unavailable");
- } catch (error) {
- console.error("Failed to check Discord RPC status:", error);
- setDiscordRpcStatus("unavailable");
- }
- };
-
- useEffect(() => {
- if (settings.discordEnabled) {
- checkDiscordRpcStatus();
- } else {
- setDiscordRpcStatus("unknown");
- }
- }, [settings.discordEnabled]);
-
- // Dynamic Eruda loading/unloading functions
- const loadEruda = () => {
- return new Promise((resolve, reject) => {
- if ((window as any).eruda) {
- // Already loaded
- (window as any).eruda.init();
- resolve();
- return;
- }
-
- const script = document.createElement("script");
- script.src = "https://cdn.jsdelivr.net/npm/eruda";
- script.integrity =
- "sha384-F7xQBvh3l6dG/mMD6QPIeVmXtzWT4Ce3ZDu8ysPuzMWMx9bFOIMGnRPUhLuQipss";
- script.crossOrigin = "anonymous";
- script.onload = () => {
- try {
- (window as any).eruda.init();
- resolve();
- } catch (error) {
- reject(error);
- }
- };
- script.onerror = reject;
- document.head.appendChild(script);
- });
- };
-
- const unloadEruda = () => {
- if ((window as any).eruda) {
- try {
- (window as any).eruda.destroy();
- // Remove the script element
- const erudaScript = document.querySelector('script[src*="eruda"]');
- if (erudaScript) {
- erudaScript.remove();
- }
- // Clean up global reference
- delete (window as any).eruda;
- } catch (error) {
- console.warn("Failed to unload Eruda:", error);
- }
- }
- };
-
- // TODO: i18n-ize
- const handleErudaToggle = async (enabled: boolean) => {
- try {
- if (enabled) {
- await loadEruda();
- toast.success("Eruda debug console enabled");
- } else {
- unloadEruda();
- toast.success("Eruda debug console disabled");
- }
- onSettingsChange({ erudaEnabled: enabled });
- } catch (error) {
- console.error("Failed to toggle Eruda:", error);
- toast.error("Failed to toggle Eruda debug console");
- }
- };
-
- const audioSection = (
-
-
-
-
{t("settings.audio.title")}
-
-
-
-
- {t("settings.playback.tempo")}
-
- {Math.round(settings.tempo * 100)}%
-
-
-
{
- let newVal = val[0];
-
- if (Math.abs(newVal - 100) <= 3) {
- newVal = 100;
- }
-
- onSettingsChange({ tempo: newVal / 100 });
- }}
- min={50}
- max={150}
- step={1}
- className={styles.slider}
- />
-
-
-
-
- {t("settings.playback.pitch")}
-
- {(settings.pitch ?? 0) === 0
- ? "0"
- : (settings.pitch ?? 0) > 0
- ? `+${settings.pitch ?? 0}`
- : (settings.pitch ?? 0)}
-
-
-
{
- let newVal = val[0];
-
- if (Math.abs(newVal) <= 0.5) {
- newVal = 0;
- }
-
- onSettingsChange({ pitch: newVal });
- }}
- min={-48}
- max={48}
- step={1}
- className={styles.slider}
- />
-
-
-
-
- {t("player.volume")}
-
- {Math.round(settings.volume * 100)}%
-
-
-
-
-
- {!isOnSafari && (
-
-
-
- {t("settings.audio.crossfade")}
- {settings.gaplessPlayback && (
-
- {" "}
- ({t("settings.audio.crossfadeDisabled")})
-
- )}
-
-
- {settings.gaplessPlayback ? "0s" : `${settings.crossfade}s`}
-
-
-
-
- )}
-
- {!isOnSafari && (
-
-
-
- {t("settings.playback.gapless")}
-
-
- {t("settings.playback.gaplessDesc")}
-
-
-
{
- if (val) {
- const currentCrossfade = settings.crossfade;
- previousCrossfadeRef.current = currentCrossfade;
- onSettingsChange({
- gaplessPlayback: val,
- crossfade: 0,
- crossfadeBeforeGapless: currentCrossfade,
- });
- } else {
- const restoreValue =
- settings.crossfadeBeforeGapless ??
- previousCrossfadeRef.current;
- onSettingsChange({
- gaplessPlayback: val,
- crossfade: restoreValue,
- crossfadeBeforeGapless: undefined,
- });
- }
- }}
- />
-
- )}
-
- );
-
- const playbackSection = (
-
-
-
-
{t("settings.playback.title")}
-
-
-
-
-
- {t("settings.playback.shuffle")}
-
-
- {t("settings.playback.shuffleDesc")}
-
-
-
onSettingsChange({ defaultShuffle: val })}
- />
-
-
-
-
-
- {t("settings.playback.smartShuffle")}
-
-
- {t("settings.playback.smartShuffleDesc")}
-
-
-
onSettingsChange({ smartShuffle: val })}
- />
-
-
-
-
-
- {t("settings.playback.repeat")}
-
-
-
- onSettingsChange({
- defaultRepeat: val as PlayerSettings["defaultRepeat"],
- })
- }
- >
-
-
-
-
- {t("player.repeatOff")}
- {t("player.repeatTrack")}
- {t("player.repeatAll")}
-
-
-
-
-
-
-
- {t("settings.playback.autoPlay")}
-
-
- {t("settings.playback.autoPlayDesc")}
-
-
-
onSettingsChange({ autoPlayNext: val })}
- />
-
-
-
-
-
- {t("settings.playback.sessionRestore")}
-
-
- {t("settings.playback.sessionRestoreDesc")}
-
-
-
onSettingsChange({ sessionRestore: val })}
- />
-
-
- );
-
- const interfaceSection = (
-
-
-
-
{t("settings.interface.title")}
-
-
-
-
-
- {t("settings.interface.colorTheme")}
-
-
-
{
- try {
- await setTheme(val);
- onSettingsChange({ colorTheme: val });
- } catch {
- toast.error(t("settings.themeError"));
- }
- }}
- >
-
-
-
-
- {themes.map((theme) => (
-
- {theme.name}
-
- ))}
-
-
-
-
-
-
-
{t("settings.interface.iconSet")}
-
- {t("settings.interface.iconSetDesc")}
-
-
-
{
- try {
- setIconSet(val);
- toast.success(t("settings.interface.iconSetChanged"));
- } catch {
- toast.error(t("settings.interface.iconSetError"));
- }
- }}
- >
-
-
-
-
- {iconSets.map((iconSet) => (
-
- {iconSet.label}
-
- ))}
-
-
-
-
-
-
-
{t("settings.interface.wallpaper")}
-
- {t("settings.interface.wallpaperDesc")}
-
-
-
{
- try {
- if (val === "None") {
- await setWallpaper(val);
- onSettingsChange({ wallpaper: "None" });
- } else {
- await setWallpaper(val);
- onSettingsChange({ wallpaper: val });
- }
- } catch {
- toast.error(t("settings.interface.wallpaperError"));
- }
- }}
- >
-
-
-
-
-
- {t("settings.interface.wallpaperNone", "None")}
-
- {wallpapers?.map((wallpaper) => (
-
- {wallpaper.name}
-
- ))}
-
-
-
-
-
-
-
{t("settings.interface.themeMode")}
-
- {t("settings.interface.themeModeDesc")}
-
-
-
- onSettingsChange({
- themeMode: val as PlayerSettings["themeMode"],
- })
- }
- />
-
-
-
-
-
- {t("settings.interface.compact")}
-
-
- {t("settings.interface.compactDesc")}
-
-
-
onSettingsChange({ compactMode: val })}
- />
-
-
-
-
-
- {t("settings.interface.albumArt")}
-
-
- {t("settings.interface.albumArtDesc")}
-
-
-
onSettingsChange({ showAlbumArt: val })}
- />
-
-
-
-
-
{t("settings.interface.lyrics")}
-
- {t("settings.interface.lyricsDesc")}
-
-
-
onSettingsChange({ showLyrics: val })}
- />
-
-
-
-
-
- {t("settings.interface.language")}
-
-
- {t("settings.interface.languageDescription")}
-
-
-
-
-
- {languageNames[i18n.language] || i18n.language.toUpperCase()}
-
-
-
- {languages.map((lang) => (
-
- {languageNames[lang] || lang.toUpperCase()}
-
- ))}
-
-
-
-
-
-
-
{t("settings.interface.clearCache")}
-
- {t("settings.interface.clearCacheDesc")}
-
-
-
-
- {t("settings.interface.clearCacheButton")}
-
-
-
-
-
{t("settings.resetDialogs")}
-
- {t("settings.resetDialogsDescription")}
-
-
-
setDialogResetOpen(true)}
- >
-
- {t("settings.resetDialogsButton")}
-
-
-
-
- {t("settings.resetDialogsTitle")}
-
- {t("settings.resetDialogsDescription")}
-
-
-
-
- {t("common.cancel")}
-
- {
- setDialogResetLoading(true);
- try {
- await resetAllDialogPreferences();
- toast.success(t("settings.resetDialogsSuccess"));
- setDialogResetOpen(false);
- } catch (e: any) {
- toast.error(e?.message || t("settings.resetError"));
- } finally {
- setDialogResetLoading(false);
- }
- }}
- disabled={dialogResetLoading}
- variant="destructive"
- >
- {dialogResetLoading ? t("common.loading") : t("common.reset")}
-
-
-
-
-
-
- );
-
- const shortcutsSection = (
-
-
-
-
{t("settings.shortcuts.title")}
-
-
-
-
-
{t("settings.shortcuts.enabled")}
-
- {t("settings.shortcuts.enabledDesc")}
-
-
-
{}}
- />
-
-
-
-
- );
-
- const experimentalSection = (
-
-
-
-
Beta
-
-
-
-
-
- Enable Discord Integration (Broken Beta)
-
-
- Note: Discord's RPC API requires special approval. Currently
- logs track info for testing.
-
-
-
onSettingsChange({ discordEnabled: val })}
- />
-
-
- {settings.discordEnabled && (
- <>
-
-
-
{t("discord.connection")}
-
- {settings.discordUserId
- ? t("discord.connected", {
- userId: settings.discordUserId,
- })
- : t("discord.notConnected")}
-
-
-
{
- if (settings.discordUserId) {
- onSettingsChange({ discordUserId: undefined });
- toast.success(t("discord.disconnected"));
- } else {
- const discordOAuthUrl =
- "https://discord.com/oauth2/authorize?client_id=1419480226970341476&response_type=code&redirect_uri=https%3A%2F%2Fhtmlplayer-backend.onrender.com%2Foauth%2Fcallback&scope=identify";
- window.open(discordOAuthUrl, "_blank");
- toast.info(t("discord.completeAuth"));
- }
- }}
- >
- {settings.discordUserId
- ? t("discord.disconnect")
- : t("discord.connect")}
-
-
-
- {!settings.discordUserId && (
-
-
-
- {t("discord.manualUserId")}
-
-
- {t("discord.manualUserIdDescription")}
-
-
-
- {
- if (e.key === "Enter") {
- const input = e.target as HTMLInputElement;
- if (input.value.trim()) {
- onSettingsChange({
- discordUserId: input.value.trim(),
- });
- toast.success(t("discord.userIdSaved"));
- input.value = "";
- }
- }
- }}
- />
- {
- const input = (e.target as HTMLElement)
- .previousElementSibling as HTMLInputElement;
- if (input && input.value.trim()) {
- onSettingsChange({
- discordUserId: input.value.trim(),
- });
- toast.success(t("discord.userIdSaved"));
- input.value = "";
- }
- }}
- >
- {t("common.save")}
-
-
-
- )}
-
-
-
-
{t("discord.status")}
-
- {discordRpcStatus === "unknown" && t("discord.statusUnknown")}
- {discordRpcStatus === "unsupported" &&
- t("discord.statusUnsupported")}
- {discordRpcStatus === "available" &&
- t("discord.statusAvailable")}
- {discordRpcStatus === "unavailable" &&
- t("discord.statusUnavailable")}
-
-
-
- {t("discord.refreshStatus")}
-
-
- >
- )}
-
-
-
-
Enable Eruda Debug Console
-
- Eruda is a debug console for mobile browsers. Takes effect
- immediately.
-
-
-
-
-
- );
-
- const categoryPanels: Record = {
- playback: (
- <>
- {audioSection}
- {playbackSection}
- >
- ),
- interface: interfaceSection,
- shortcuts: shortcutsSection,
- experimental: experimentalSection,
- };
-
- const categoryList: Array<{
- id: SettingsCategory;
- label: string;
- description: string;
- icon: string;
- }> = [
- {
- id: "playback",
- label: t("settings.category.playback", "Playback"),
- description: t(
- "settings.category.playbackDescription",
- "Audio and playback behavior",
- ),
- icon: "music",
- },
- {
- id: "interface",
- label: t("settings.category.interface", "Interface"),
- description: t(
- "settings.category.interfaceDescription",
- "Themes, language, and appearance",
- ),
- icon: "palette",
- },
- {
- id: "shortcuts",
- label: t("settings.category.shortcuts", "Shortcuts"),
- description: t(
- "settings.category.shortcutsDescription",
- "Keyboard shortcut preferences",
- ),
- icon: "keyboard",
- },
- {
- id: "experimental",
- label: t("settings.category.experimental", "Beta"),
- description: t(
- "settings.category.experimentalDescription",
- "Early and experimental features",
- ),
- icon: "messageCircle",
- },
- ];
-
- return (
-
-
-
-
- {t("settings.title")}
- {t("settings.description")}
-
-
-
-
-
-
- {categoryList.map((category) => {
- const isActive = activeCategory === category.id;
- return (
- setActiveCategory(category.id)}
- aria-current={isActive ? "page" : undefined}
- >
-
-
-
- {category.label}
-
-
- {category.description}
-
-
-
- );
- })}
-
-
-
- {categoryPanels[activeCategory]}
-
-
-
-
-
-
-
- {t("settings.reset")}
-
-
-
-
-
- );
-};
diff --git a/Build/src/contexts/audioStore.ts b/Build/src/contexts/audioStore.ts
deleted file mode 100644
index d9212e4..0000000
--- a/Build/src/contexts/audioStore.ts
+++ /dev/null
@@ -1,303 +0,0 @@
-import { create } from "zustand";
-import { subscribeWithSelector } from "zustand/middleware";
-import { useEffect, useRef } from "react";
-import { SafariAudioManager } from "../helpers/safariHelper";
-
-export interface AudioEvent {
- type:
- | "play"
- | "pause"
- | "seek"
- | "volume"
- | "next"
- | "previous"
- | "timeUpdate"
- | "songChange";
- payload?: any;
- timestamp: number;
- source: "main" | "pip";
-}
-
-interface AudioState {
- // Current audio state
- isPlaying: boolean;
- currentTime: number;
- duration: number;
- volume: number;
- currentSong: Song | null;
-
- // Event handling
- lastEvent: AudioEvent | null;
-
- // Actions for state updates (internal use)
- setPlaying: (playing: boolean, source?: "main" | "pip") => void;
- setCurrentTime: (time: number, source?: "main" | "pip") => void;
- setVolume: (volume: number, source?: "main" | "pip") => void;
- setCurrentSong: (song: Song | null, source?: "main" | "pip") => void;
- setDuration: (duration: number, source?: "main" | "pip") => void;
-
- // Control actions that emit events
- play: (source?: "main" | "pip") => void;
- pause: (source?: "main" | "pip") => void;
- seek: (time: number, source?: "main" | "pip") => void;
- next: (source?: "main" | "pip") => void;
- previous: (source?: "main" | "pip") => void;
- updateTime: (time: number, source?: "main" | "pip") => void;
- changeVolume: (volume: number, source?: "main" | "pip") => void;
-}
-
-// Create BroadcastChannel for cross-window communication
-const audioChannel = new BroadcastChannel("audio-events");
-
-// Initialize Safari audio manager (only activates on Safari)
-const safariAudio = new SafariAudioManager();
-
-export const useAudioStore = create()(
- subscribeWithSelector((set, get) => ({
- // Initial state
- isPlaying: false,
- currentTime: 0,
- duration: 0,
- volume: 0.75,
- currentSong: null,
- lastEvent: null,
-
- // State setters (for internal sync, don't broadcast)
- setPlaying: (playing: boolean, _source: "main" | "pip" = "main") => {
- set({ isPlaying: playing });
- },
-
- setCurrentTime: (time: number, _source: "main" | "pip" = "main") => {
- set({ currentTime: time });
- },
-
- setVolume: (volume: number, _source: "main" | "pip" = "main") => {
- set({ volume });
- },
-
- setCurrentSong: (song: Song | null, source: "main" | "pip" = "main") => {
- set({ currentSong: song });
- // Broadcast song changes
- const event: AudioEvent = {
- type: "songChange",
- payload: { song },
- timestamp: Date.now(),
- source,
- };
- set({ lastEvent: event });
- audioChannel.postMessage(event);
-
- // NOTE: Don't set Safari audio source here - it will be set in playSong()
- // after the song is cached and we have a valid blob URL
- },
-
- setDuration: (duration: number, _source: "main" | "pip" = "main") => {
- set({ duration });
- },
-
- // Control actions (these broadcast events)
- play: (source: "main" | "pip" = "main") => {
- const event: AudioEvent = {
- type: "play",
- timestamp: Date.now(),
- source,
- };
- set({ lastEvent: event });
- audioChannel.postMessage(event);
-
- // Sync Safari audio element
- if (safariAudio.isActive()) {
- safariAudio.play();
- }
- },
-
- pause: (source: "main" | "pip" = "main") => {
- const event: AudioEvent = {
- type: "pause",
- timestamp: Date.now(),
- source,
- };
- set({ lastEvent: event });
- audioChannel.postMessage(event);
-
- // Sync Safari audio element
- if (safariAudio.isActive()) {
- safariAudio.pause();
- }
- },
-
- seek: (time: number, source: "main" | "pip" = "main") => {
- const event: AudioEvent = {
- type: "seek",
- payload: { time },
- timestamp: Date.now(),
- source,
- };
- set({ lastEvent: event });
- audioChannel.postMessage(event);
-
- // Sync Safari audio element
- if (safariAudio.isActive()) {
- safariAudio.seek(time);
- }
- },
-
- next: (source: "main" | "pip" = "main") => {
- const event: AudioEvent = {
- type: "next",
- timestamp: Date.now(),
- source,
- };
- set({ lastEvent: event });
- audioChannel.postMessage(event);
- },
-
- previous: (source: "main" | "pip" = "main") => {
- const event: AudioEvent = {
- type: "previous",
- timestamp: Date.now(),
- source,
- };
- set({ lastEvent: event });
- audioChannel.postMessage(event);
- },
-
- updateTime: (time: number, source: "main" | "pip" = "main") => {
- set({ currentTime: time });
- // Only broadcast time updates every 500ms to avoid spam
- const now = Date.now();
- const lastEvent = get().lastEvent;
- if (
- !lastEvent ||
- lastEvent.type !== "timeUpdate" ||
- now - lastEvent.timestamp > 500
- ) {
- const event: AudioEvent = {
- type: "timeUpdate",
- payload: { time },
- timestamp: now,
- source,
- };
- set({ lastEvent: event });
- audioChannel.postMessage(event);
- }
- },
-
- changeVolume: (volume: number, source: "main" | "pip" = "main") => {
- set({ volume });
- const event: AudioEvent = {
- type: "volume",
- payload: { volume },
- timestamp: Date.now(),
- source,
- };
- set({ lastEvent: event });
- audioChannel.postMessage(event);
-
- // Sync Safari audio element
- if (safariAudio.isActive()) {
- safariAudio.setVolume(volume);
- }
- },
- })),
-);
-
-// Listen for events from other windows/tabs
-audioChannel.onmessage = (event) => {
- const audioEvent: AudioEvent = event.data;
- const store = useAudioStore.getState();
-
- // Determine if this is the main window or PiP window
- const isMainWindow =
- typeof window !== "undefined" && window.parent === window;
- const currentSource = isMainWindow ? "main" : "pip";
-
- // Prevent infinite loops by checking source
- if (audioEvent.source === currentSource) {
- return;
- }
-
- console.log(
- `[${currentSource}] Received audio event:`,
- audioEvent.type,
- "from",
- audioEvent.source,
- );
-
- // Handle incoming events (update state without broadcasting)
- switch (audioEvent.type) {
- case "play":
- store.setPlaying(true, audioEvent.source);
- break;
- case "pause":
- store.setPlaying(false, audioEvent.source);
- break;
- case "volume":
- store.setVolume(audioEvent.payload.volume, audioEvent.source);
- break;
- case "seek":
- store.setCurrentTime(audioEvent.payload.time, audioEvent.source);
- break;
- case "timeUpdate":
- store.setCurrentTime(audioEvent.payload.time, audioEvent.source);
- break;
- case "songChange":
- store.setCurrentSong(audioEvent.payload.song, audioEvent.source);
- break;
- // next/previous are handled by the audio sync hook
- }
-};
-
-// Hook for subscribing to specific events
-export const useAudioEvents = (
- eventType: AudioEvent["type"],
- callback: (event: AudioEvent) => void,
-) => {
- const lastEvent = useAudioStore((state) => state.lastEvent);
- const lastProcessedEventRef = useRef(0);
-
- useEffect(() => {
- if (
- lastEvent &&
- lastEvent.type === eventType &&
- lastEvent.timestamp !== lastProcessedEventRef.current
- ) {
- // Simple deduplication: only process events that are recent (less than 1000ms old)
- const now = Date.now();
- if (now - lastEvent.timestamp < 1000) {
- lastProcessedEventRef.current = lastEvent.timestamp;
- callback(lastEvent);
- }
- }
- }, [lastEvent, eventType]); // Remove callback from dependencies to prevent infinite loops
-};
-
-// Hook for audio controls
-export const useAudioControls = () => {
- const { play, pause, seek, next, previous, changeVolume } = useAudioStore();
- const isPlaying = useAudioStore((state) => state.isPlaying);
-
- return {
- play,
- pause,
- seek,
- next,
- previous,
- setVolume: changeVolume,
- togglePlayPause: () => (isPlaying ? pause() : play()),
- };
-};
-
-// Hook for audio state
-export const useAudioState = () => {
- return useAudioStore((state) => ({
- isPlaying: state.isPlaying,
- currentTime: state.currentTime,
- duration: state.duration,
- volume: state.volume,
- currentSong: state.currentSong,
- }));
-};
-
-// Export Safari audio manager for direct access if needed
-export const getSafariAudioManager = () => safariAudio;
diff --git a/Build/src/core/engine/engine.ts b/Build/src/core/engine/engine.ts
new file mode 100644
index 0000000..c56133d
--- /dev/null
+++ b/Build/src/core/engine/engine.ts
@@ -0,0 +1,587 @@
+import type {
+ Track,
+ Playlist,
+ EngineSettings,
+ EngineState,
+ PlayerState,
+ EngineEventMap,
+ EngineError,
+} from "./types";
+import { KomorebiEvents } from "./events";
+import { StateMachine } from "./state";
+import {
+ QueueManager,
+ type WeightedRandomizer,
+ type ShuffleMode,
+} from "./queue";
+import { Scheduler } from "./scheduler";
+import type { IAudioBackend } from "../../platform/audio";
+
+export interface IAudioEngineConfig {
+ crossfade: {
+ enabled: boolean;
+ duration: number;
+ shape: "none" | "linear" | "equalpower";
+ };
+ gapless: {
+ enabled: boolean;
+ };
+ smartShuffle: boolean;
+ autoPlayNext: boolean;
+}
+
+const DEFAULT_SETTINGS: EngineSettings = {
+ volume: 1,
+ crossfade: 0,
+ crossfadeBeforeGapless: 3000,
+ autoPlayNext: true,
+ tempo: 1,
+ pitch: 0,
+ gaplessPlayback: true,
+ smartShuffle: true,
+ repeat: "off",
+ defaultShuffle: false,
+ defaultRepeat: "off",
+};
+
+export class KomorebiEngine {
+ private events = new KomorebiEvents();
+ private stateMachine = new StateMachine();
+ private queue = new QueueManager();
+ private scheduler = new Scheduler();
+
+ private backend: IAudioBackend | null = null;
+ private settings: EngineSettings = { ...DEFAULT_SETTINGS };
+ private currentTime = 0;
+ private duration = 0;
+ private currentError: EngineError | null = null;
+
+ private timeUpdateInterval: number | null = null;
+ private scheduledTransitionId: number | null = null;
+
+ constructor(config?: Partial) {
+ if (config?.crossfade) {
+ this.scheduler.setCrossfadeConfig({
+ enabled: config.crossfade.enabled,
+ duration: config.crossfade.duration,
+ shape: config.crossfade.shape,
+ });
+ this.settings.crossfade = config.crossfade.duration;
+ }
+
+ if (config?.gapless) {
+ this.scheduler.setGaplessConfig({ enabled: config.gapless.enabled });
+ this.settings.gaplessPlayback = config.gapless.enabled;
+ }
+
+ if (config?.smartShuffle !== undefined) {
+ this.settings.smartShuffle = config.smartShuffle;
+ }
+
+ if (config?.autoPlayNext !== undefined) {
+ this.settings.autoPlayNext = config.autoPlayNext;
+ }
+ }
+
+ setBackend(backend: IAudioBackend): void {
+ if (this.backend) {
+ this.backend.dispose();
+ }
+ this.backend = backend;
+
+ this.backend.onTimeUpdate((time) => {
+ this.handleTimeUpdate(time);
+ });
+
+ this.backend.onEnded(() => {
+ this.handleTrackEnded();
+ });
+
+ this.backend.onError((error) => {
+ this.handleError(error);
+ });
+ }
+
+ setWeightedRandomizer(randomizer: WeightedRandomizer | null): void {
+ this.queue.setWeightedRandomizer(randomizer);
+ if (this.settings.smartShuffle) {
+ this.queue.setShuffleMode("smart");
+ }
+ }
+
+ setShuffleMode(mode: ShuffleMode): void {
+ this.queue.setShuffleMode(mode);
+ this.settings.smartShuffle = mode === "smart";
+ }
+
+ getShuffleMode(): ShuffleMode {
+ return this.queue.getShuffleMode();
+ }
+
+ load(track: Track, playlist?: Playlist): void {
+ if (!this.backend) {
+ this.emitError("NO_BACKEND", "No audio backend configured");
+ return;
+ }
+
+ if (playlist) {
+ this.queue.setPlaylist(playlist);
+ }
+
+ this.queue.setCurrentIndex(
+ this.queue.getTracks().findIndex((t) => t.id === track.id),
+ );
+
+ this.stateMachine.transition("loading");
+ this.currentError = null;
+ this.events.emit("loading", { track });
+
+ this.backend
+ .load(track.url)
+ .then(() => {
+ this.duration = this.backend?.getDuration() ?? track.duration;
+ this.stateMachine.transition("ready");
+ this.events.emit("durationchange", { duration: this.duration });
+ this.events.emit("ready", { track });
+ this.emitStateChange();
+ })
+ .catch((error) => {
+ this.emitError("LOAD_ERROR", error.message, track);
+ });
+ }
+
+ async play(): Promise {
+ if (!this.backend) {
+ this.emitError("NO_BACKEND", "No audio backend configured");
+ return;
+ }
+
+ const state = this.stateMachine.getState();
+
+ if (state === "idle" || state === "error") {
+ const current = this.queue.getCurrentTrack();
+ if (current) {
+ this.load(current);
+ await this.waitForState("ready");
+ await this.play();
+ return;
+ }
+ return;
+ }
+
+ if (state === "ready" || state === "paused") {
+ try {
+ await this.backend.play();
+ this.stateMachine.transition("playing");
+ this.startTimeUpdates();
+ this.emitStateChange();
+
+ const track = this.queue.getCurrentTrack();
+ if (track) {
+ this.queue.updateHistory(track.id);
+ }
+ } catch (error) {
+ this.emitError("PLAY_ERROR", (error as Error).message);
+ }
+ }
+ }
+
+ pause(): void {
+ if (!this.backend) return;
+
+ if (this.stateMachine.isPlaying()) {
+ this.backend.pause();
+ this.stateMachine.transition("paused");
+ this.stopTimeUpdates();
+ this.emitStateChange();
+ }
+ }
+
+ stop(): void {
+ if (!this.backend) return;
+
+ this.backend.stop();
+ this.stateMachine.transition("idle");
+ this.currentTime = 0;
+ this.stopTimeUpdates();
+ this.emitStateChange();
+ }
+
+ async next(): Promise {
+ this.cancelScheduledTransition();
+
+ const nextTrack = this.queue.getNextTrack(this.settings.smartShuffle);
+ if (nextTrack) {
+ const currentTrack = this.queue.getCurrentTrack();
+ this.queue.setCurrentIndex(
+ this.queue.getNextIndex(this.settings.smartShuffle),
+ );
+
+ if (this.stateMachine.isPlaying()) {
+ this.loadAndPlay(nextTrack);
+ } else {
+ this.load(nextTrack);
+ }
+
+ this.emitTrackChange(currentTrack, nextTrack);
+ } else if (this.settings.repeat === "all") {
+ this.queue.setCurrentIndex(-1);
+ const firstTrack = this.queue.getNextTrack(this.settings.smartShuffle);
+ if (firstTrack) {
+ this.loadAndPlay(firstTrack);
+ this.emitTrackChange(null, firstTrack);
+ }
+ }
+ }
+
+ async previous(): Promise {
+ this.cancelScheduledTransition();
+
+ if (this.currentTime > 3) {
+ this.seek(0);
+ return;
+ }
+
+ const prevTrack = this.queue.getPreviousTrack(this.settings.smartShuffle);
+ if (prevTrack) {
+ const currentTrack = this.queue.getCurrentTrack();
+ this.queue.setCurrentIndex(
+ this.queue.getPreviousIndex(this.settings.smartShuffle),
+ );
+
+ if (this.stateMachine.isPlaying()) {
+ this.loadAndPlay(prevTrack);
+ } else {
+ this.load(prevTrack);
+ }
+
+ this.emitTrackChange(currentTrack, prevTrack);
+ }
+ }
+
+ seek(time: number): void {
+ if (!this.backend) return;
+
+ const clampedTime = Math.max(0, Math.min(time, this.duration));
+ this.backend.seek(clampedTime);
+ this.currentTime = clampedTime;
+ this.emitTimeUpdate();
+ }
+
+ setVolume(volume: number): void {
+ const clamped = Math.max(0, Math.min(1, volume));
+ this.settings.volume = clamped;
+
+ if (this.backend) {
+ this.backend.setVolume(clamped);
+ }
+
+ this.events.emit("volumechange", { volume: clamped });
+ }
+
+ setTempo(tempo: number): void {
+ const clamped = Math.max(0.25, Math.min(4, tempo));
+ this.settings.tempo = clamped;
+
+ if (this.backend) {
+ this.backend.setPlaybackRate(clamped);
+ }
+
+ this.events.emit("settingschange", { settings: { tempo: clamped } });
+ }
+
+ setPitch(semitones: number): void {
+ this.settings.pitch = semitones;
+ this.events.emit("settingschange", { settings: { pitch: semitones } });
+ }
+
+ toggleShuffle(): void {
+ if (this.queue.isShuffled()) {
+ this.queue.unshuffle();
+ } else {
+ this.queue.shuffle(true);
+ }
+
+ this.settings.defaultShuffle = this.queue.isShuffled();
+ this.events.emit("queuechange", { queue: this.queue.getState() });
+ }
+
+ toggleRepeat(): void {
+ const current = this.settings.repeat;
+ this.settings.repeat =
+ current === "off" ? "all" : current === "all" ? "one" : "off";
+ this.events.emit("settingschange", {
+ settings: { repeat: this.settings.repeat },
+ });
+ }
+
+ setCrossfade(duration: number): void {
+ this.settings.crossfade = duration;
+ this.scheduler.setCrossfadeConfig({ enabled: duration > 0, duration });
+ this.events.emit("settingschange", { settings: { crossfade: duration } });
+ }
+
+ setGapless(enabled: boolean): void {
+ this.settings.gaplessPlayback = enabled;
+ this.scheduler.setGaplessConfig({ enabled });
+ this.events.emit("settingschange", {
+ settings: { gaplessPlayback: enabled },
+ });
+ }
+
+ updateSettings(newSettings: Partial): void {
+ Object.assign(this.settings, newSettings);
+
+ if (newSettings.volume !== undefined) {
+ this.setVolume(newSettings.volume);
+ }
+ if (newSettings.tempo !== undefined) {
+ this.setTempo(newSettings.tempo);
+ }
+ if (newSettings.crossfade !== undefined) {
+ this.setCrossfade(newSettings.crossfade);
+ }
+ if (newSettings.gaplessPlayback !== undefined) {
+ this.setGapless(newSettings.gaplessPlayback);
+ }
+ if (newSettings.pitch !== undefined) {
+ this.setPitch(newSettings.pitch);
+ }
+
+ this.events.emit("settingschange", { settings: newSettings });
+ }
+
+ setPlaylist(playlist: Playlist): void {
+ this.queue.setPlaylist(playlist, false);
+ this.events.emit("queuechange", { queue: this.queue.getState() });
+ }
+
+ getState(): EngineState {
+ return {
+ state: this.stateMachine.getState(),
+ currentTrack: this.queue.getCurrentTrack(),
+ currentPlaylist: null,
+ queue: this.queue.getState(),
+ settings: { ...this.settings },
+ currentTime: this.currentTime,
+ duration: this.duration,
+ volume: this.settings.volume,
+ playHistory: this.queue.getAllHistory(),
+ error: this.currentError,
+ };
+ }
+
+ getCurrentTrack(): Track | null {
+ return this.queue.getCurrentTrack();
+ }
+
+ getQueue(): QueueManager {
+ return this.queue;
+ }
+
+ getScheduler(): Scheduler {
+ return this.scheduler;
+ }
+
+ on(
+ event: E,
+ callback: (data: EngineEventMap[E]) => void,
+ ): void {
+ this.events.on(event, callback);
+ }
+
+ off(
+ event: E,
+ callback: (data: EngineEventMap[E]) => void,
+ ): void {
+ this.events.off(event, callback);
+ }
+
+ dispose(): void {
+ this.stopTimeUpdates();
+ this.cancelScheduledTransition();
+ this.backend?.dispose();
+ this.events.removeAllListeners();
+ this.stateMachine.reset();
+ }
+
+ private async loadAndPlay(track: Track): Promise {
+ return new Promise((resolve, reject) => {
+ const onEndedHandler = () => {
+ this.backend?.offEnded(onEndedHandler);
+ this.play().then(resolve).catch(reject);
+ };
+
+ this.backend?.onEnded(onEndedHandler);
+ this.load(track);
+ });
+ }
+
+ private async waitForState(
+ targetState: PlayerState,
+ timeout = 5000,
+ ): Promise {
+ return new Promise((resolve, reject) => {
+ const checkState = () => {
+ if (this.stateMachine.getState() === targetState) {
+ resolve();
+ return true;
+ }
+ if (this.stateMachine.hasError()) {
+ reject(new Error("State transition failed"));
+ return true;
+ }
+ return false;
+ };
+
+ if (checkState()) return;
+
+ const timeoutId = setTimeout(() => {
+ this.events.off("statechange", stateHandler);
+ reject(new Error(`Timeout waiting for state: ${targetState}`));
+ }, timeout);
+
+ const stateHandler = () => {
+ if (checkState()) {
+ clearTimeout(timeoutId);
+ }
+ };
+
+ this.events.on("statechange", stateHandler);
+ });
+ }
+
+ private handleTimeUpdate(time: number): void {
+ this.currentTime = time;
+
+ if (this.stateMachine.isPlaying()) {
+ this.checkScheduledTransition(time);
+ }
+
+ this.emitTimeUpdate();
+ }
+
+ private checkScheduledTransition(currentTime: number): void {
+ const track = this.queue.getCurrentTrack();
+ if (!track) return;
+
+ if (this.scheduler.shouldTriggerTransition(currentTime, track)) {
+ this.scheduleTransition(track);
+ }
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ private scheduleTransition(_track: Track): void {
+ if (this.scheduledTransitionId !== null) return;
+
+ this.stateMachine.transition("transitioning");
+
+ const nextTrack = this.queue.getNextTrack(this.settings.smartShuffle);
+ if (!nextTrack) return;
+
+ const delay =
+ this.scheduler.getMode() === "gapless" ? 100 : this.settings.crossfade;
+
+ this.scheduledTransitionId = window.setTimeout(() => {
+ this.scheduledTransitionId = null;
+ this.executeTransition(nextTrack);
+ }, delay);
+ }
+
+ private executeTransition(nextTrack: Track): void {
+ const currentTrack = this.queue.getCurrentTrack();
+ this.queue.setCurrentIndex(
+ this.queue.getNextIndex(this.settings.smartShuffle),
+ );
+
+ this.load(nextTrack);
+ this.play();
+
+ this.emitTrackChange(currentTrack, nextTrack);
+
+ if (currentTrack) {
+ this.events.emit("ended", { track: currentTrack });
+ }
+
+ this.stateMachine.transition("playing");
+ }
+
+ private cancelScheduledTransition(): void {
+ if (this.scheduledTransitionId !== null) {
+ clearTimeout(this.scheduledTransitionId);
+ this.scheduledTransitionId = null;
+ }
+
+ if (this.stateMachine.isTransitioning()) {
+ this.stateMachine.transition("ready");
+ }
+ }
+
+ private handleTrackEnded(): void {
+ const track = this.queue.getCurrentTrack();
+ if (track) {
+ this.events.emit("ended", { track: track });
+ }
+
+ if (this.settings.repeat === "one") {
+ this.seek(0);
+ this.play();
+ return;
+ }
+
+ if (this.settings.autoPlayNext) {
+ this.next();
+ } else {
+ this.stateMachine.transition("ready");
+ this.emitStateChange();
+ }
+ }
+
+ private handleError(error: Error): void {
+ this.emitError("BACKEND_ERROR", error.message);
+ }
+
+ private startTimeUpdates(): void {
+ if (this.timeUpdateInterval) return;
+
+ this.timeUpdateInterval = window.setInterval(() => {
+ if (this.backend && this.stateMachine.isPlaying()) {
+ this.handleTimeUpdate(this.backend.getCurrentTime());
+ }
+ }, 100);
+ }
+
+ private stopTimeUpdates(): void {
+ if (this.timeUpdateInterval !== null) {
+ clearInterval(this.timeUpdateInterval);
+ this.timeUpdateInterval = null;
+ }
+ }
+
+ private emitStateChange(): void {
+ const prevState = this.stateMachine.getPreviousState();
+ const newState = this.stateMachine.getState();
+ this.events.emit("statechange", {
+ oldState: prevState ?? "idle",
+ newState,
+ });
+ }
+
+ private emitTrackChange(from: Track | null, to: Track | null): void {
+ this.events.emit("trackchange", { from, to });
+ }
+
+ private emitTimeUpdate(): void {
+ this.events.emit("timeupdate", {
+ currentTime: this.currentTime,
+ duration: this.duration,
+ });
+ }
+
+ private emitError(code: string, message: string, track?: Track): void {
+ this.currentError = { code, message, track };
+ this.stateMachine.transition("error");
+ this.events.emit("error", { error: this.currentError });
+ this.emitStateChange();
+ }
+}
diff --git a/Build/src/core/engine/events.ts b/Build/src/core/engine/events.ts
new file mode 100644
index 0000000..28dccdd
--- /dev/null
+++ b/Build/src/core/engine/events.ts
@@ -0,0 +1,57 @@
+import type { EngineEvent, EngineEventMap } from "./types";
+
+type EventCallback = (data: T) => void;
+
+export class KomorebiEvents {
+ private listeners: Map>> = new Map();
+
+ on(
+ event: E,
+ callback: EventCallback,
+ ): void {
+ if (!this.listeners.has(event)) {
+ this.listeners.set(event, new Set());
+ }
+ this.listeners.get(event)!.add(callback as EventCallback);
+ }
+
+ off(
+ event: E,
+ callback: EventCallback,
+ ): void {
+ const callbacks = this.listeners.get(event);
+ if (callbacks) {
+ callbacks.delete(callback as EventCallback);
+ }
+ }
+
+ emit(event: E, data: EngineEventMap[E]): void {
+ const callbacks = this.listeners.get(event);
+ if (callbacks) {
+ callbacks.forEach((cb) => cb(data));
+ }
+ }
+
+ once(
+ event: E,
+ callback: EventCallback,
+ ): void {
+ const wrapper: EventCallback = (data) => {
+ this.off(event, wrapper);
+ callback(data);
+ };
+ this.on(event, wrapper);
+ }
+
+ removeAllListeners(event?: EngineEvent): void {
+ if (event) {
+ this.listeners.delete(event);
+ } else {
+ this.listeners.clear();
+ }
+ }
+
+ listenerCount(event: EngineEvent): number {
+ return this.listeners.get(event)?.size ?? 0;
+ }
+}
diff --git a/Build/src/core/engine/index.ts b/Build/src/core/engine/index.ts
new file mode 100644
index 0000000..251036a
--- /dev/null
+++ b/Build/src/core/engine/index.ts
@@ -0,0 +1,8 @@
+export * from "./types";
+export * from "./events";
+export * from "./engine";
+export { StateMachine } from "./state";
+export { QueueManager } from "./queue";
+export { Scheduler, CrossfadeScheduler, GaplessScheduler } from "./scheduler";
+export type { IAudioBackend } from "../../platform/audio";
+export type { ScheduledTransition, TransitionCurve } from "./scheduler";
diff --git a/Build/src/core/engine/queue/index.ts b/Build/src/core/engine/queue/index.ts
new file mode 100644
index 0000000..4a5b24b
--- /dev/null
+++ b/Build/src/core/engine/queue/index.ts
@@ -0,0 +1,299 @@
+import type { Track, Playlist, QueueState, PlayHistory } from "../types";
+
+export type ShuffleMode = "random" | "smart";
+
+export interface WeightedRandomizer {
+ getWeightedRandomTrack(trackIds: string[]): string | null;
+}
+
+export class QueueManager {
+ private state: QueueState = {
+ tracks: [],
+ currentIndex: -1,
+ shuffled: false,
+ shuffleOrder: [],
+ };
+
+ private history: Map = new Map();
+ private maxHistorySize = 1000;
+ private weightedRandomizer: WeightedRandomizer | null = null;
+ private shuffleMode: ShuffleMode = "random";
+
+ setWeightedRandomizer(randomizer: WeightedRandomizer | null): void {
+ this.weightedRandomizer = randomizer;
+ }
+
+ getShuffleMode(): ShuffleMode {
+ return this.shuffleMode;
+ }
+
+ setShuffleMode(mode: ShuffleMode): void {
+ this.shuffleMode = mode;
+ }
+
+ setPlaylist(playlist: Playlist | null, preserveCurrent = true): void {
+ if (!playlist) {
+ this.state = {
+ tracks: [],
+ currentIndex: -1,
+ shuffled: this.state.shuffled,
+ shuffleOrder: [],
+ };
+ return;
+ }
+
+ const tracks = [...playlist.songs];
+ const currentTrack = preserveCurrent ? this.getCurrentTrack() : null;
+ const newIndex = currentTrack
+ ? tracks.findIndex((t) => t.id === currentTrack.id)
+ : -1;
+
+ this.state.tracks = tracks;
+ this.state.shuffleOrder = this.generateShuffleOrder(
+ tracks.length,
+ newIndex,
+ );
+ this.state.currentIndex = newIndex >= 0 ? newIndex : -1;
+ }
+
+ getCurrentTrack(): Track | null {
+ if (
+ this.state.currentIndex < 0 ||
+ this.state.currentIndex >= this.state.tracks.length
+ ) {
+ return null;
+ }
+ return this.state.tracks[this.state.currentIndex];
+ }
+
+ getCurrentIndex(): number {
+ return this.state.currentIndex;
+ }
+
+ setCurrentIndex(index: number): void {
+ if (index >= 0 && index < this.state.tracks.length) {
+ this.state.currentIndex = index;
+ }
+ }
+
+ getTracks(): Track[] {
+ return [...this.state.tracks];
+ }
+
+ getPlayOrder(): number[] {
+ if (!this.state.shuffled) {
+ return this.state.tracks.map((_, i) => i);
+ }
+ return [...this.state.shuffleOrder];
+ }
+
+ getNextIndex(_smartShuffle: boolean): number {
+ const order = this.getPlayOrder();
+ const currentPos = order.indexOf(this.state.currentIndex);
+
+ if (currentPos === -1) {
+ return order.length > 0 ? order[0] : -1;
+ }
+
+ const nextPos = currentPos + 1;
+ if (nextPos >= order.length) {
+ return order.length > 0 ? order[0] : -1;
+ }
+
+ return order[nextPos];
+ }
+
+ getPreviousIndex(_smartShuffle: boolean): number {
+ const order = this.getPlayOrder();
+ const currentPos = order.indexOf(this.state.currentIndex);
+
+ if (currentPos === -1) {
+ return order.length > 0 ? order[order.length - 1] : -1;
+ }
+
+ const prevPos = currentPos - 1;
+ if (prevPos < 0) {
+ return order.length > 0 ? order[order.length - 1] : -1;
+ }
+
+ return order[prevPos];
+ }
+
+ getNextTrack(smartShuffle: boolean): Track | null {
+ const nextIndex = this.getNextIndex(smartShuffle);
+ if (nextIndex < 0 || nextIndex >= this.state.tracks.length) {
+ return null;
+ }
+ return this.state.tracks[nextIndex];
+ }
+
+ getPreviousTrack(smartShuffle: boolean): Track | null {
+ const prevIndex = this.getPreviousIndex(smartShuffle);
+ if (prevIndex < 0 || prevIndex >= this.state.tracks.length) {
+ return null;
+ }
+ return this.state.tracks[prevIndex];
+ }
+
+ shuffle(preserveCurrent = true): void {
+ this.state.shuffled = true;
+
+ if (this.shuffleMode === "smart" && this.weightedRandomizer) {
+ this.state.shuffleOrder = this.generateSmartShuffleOrder(
+ this.state.tracks.length,
+ preserveCurrent ? this.state.currentIndex : -1,
+ );
+ } else {
+ this.state.shuffleOrder = this.generateShuffleOrder(
+ this.state.tracks.length,
+ preserveCurrent ? this.state.currentIndex : -1,
+ );
+ }
+ }
+
+ private generateSmartShuffleOrder(
+ length: number,
+ preserveIndex: number,
+ ): number[] {
+ if (length === 0) return [];
+
+ const trackIds = this.state.tracks.map((t) => t.id);
+ const selectedIds: string[] = [];
+ const availableIndices = Array.from({ length }, (_, i) => i);
+
+ while (availableIndices.length > 0) {
+ const availableTrackIds = availableIndices.map((i) => trackIds[i]);
+ const selectedId =
+ this.weightedRandomizer!.getWeightedRandomTrack(availableTrackIds);
+
+ if (!selectedId) break;
+
+ const selectedIndex = trackIds.indexOf(selectedId);
+ if (selectedIndex === -1) break;
+
+ const actualIndex = availableIndices.indexOf(selectedIndex);
+ if (actualIndex === -1) break;
+
+ selectedIds.push(selectedId);
+ availableIndices.splice(actualIndex, 1);
+ }
+
+ if (preserveIndex >= 0 && preserveIndex < length) {
+ const preserveId = trackIds[preserveIndex];
+ const idxInSelected = selectedIds.indexOf(preserveId);
+ if (idxInSelected > 0) {
+ selectedIds.splice(idxInSelected, 1);
+ selectedIds.unshift(preserveId);
+ }
+ }
+
+ return selectedIds.map((id) => trackIds.indexOf(id)).filter((i) => i >= 0);
+ }
+
+ unshuffle(): void {
+ this.state.shuffled = false;
+ this.state.shuffleOrder = [];
+ }
+
+ isShuffled(): boolean {
+ return this.state.shuffled;
+ }
+
+ private generateShuffleOrder(
+ length: number,
+ preserveIndex: number,
+ ): number[] {
+ if (length === 0) return [];
+
+ const indices = Array.from({ length }, (_, i) => i);
+
+ for (let i = indices.length - 1; i > 0; i--) {
+ const j = Math.floor(Math.random() * (i + 1));
+ [indices[i], indices[j]] = [indices[j], indices[i]];
+ }
+
+ if (preserveIndex >= 0 && preserveIndex < length) {
+ const currentInShuffle = indices.indexOf(preserveIndex);
+ if (currentInShuffle > 0) {
+ [indices[0], indices[currentInShuffle]] = [
+ indices[currentInShuffle],
+ indices[0],
+ ];
+ }
+ }
+
+ return indices;
+ }
+
+ updateHistory(trackId: string): void {
+ const existing = this.history.get(trackId);
+ if (existing) {
+ existing.lastPlayed = Date.now();
+ existing.playCount += 1;
+ } else {
+ this.history.set(trackId, {
+ trackId,
+ lastPlayed: Date.now(),
+ playCount: 1,
+ });
+ }
+
+ if (this.history.size > this.maxHistorySize) {
+ const sorted = Array.from(this.history.values()).sort(
+ (a, b) => a.lastPlayed - b.lastPlayed,
+ );
+ const toRemove = sorted.slice(0, this.history.size - this.maxHistorySize);
+ toRemove.forEach((h) => this.history.delete(h.trackId));
+ }
+ }
+
+ getPlayHistory(trackId: string): PlayHistory | undefined {
+ return this.history.get(trackId);
+ }
+
+ getAllHistory(): Map {
+ return new Map(this.history);
+ }
+
+ getState(): QueueState {
+ return { ...this.state, tracks: [...this.state.tracks] };
+ }
+
+ setState(state: Partial): void {
+ Object.assign(this.state, state);
+ }
+
+ addTrack(track: Track): void {
+ this.state.tracks.push(track);
+ if (this.state.shuffled) {
+ const newIndex = this.state.tracks.length - 1;
+ this.state.shuffleOrder.push(newIndex);
+ const insertPos =
+ Math.floor(Math.random() * (this.state.shuffleOrder.length - 1)) + 1;
+ this.state.shuffleOrder.splice(insertPos, 0, newIndex);
+ }
+ }
+
+ removeTrack(trackId: string): void {
+ const index = this.state.tracks.findIndex((t) => t.id === trackId);
+ if (index === -1) return;
+
+ this.state.tracks.splice(index, 1);
+
+ if (this.state.currentIndex > index) {
+ this.state.currentIndex--;
+ }
+
+ if (this.state.shuffled) {
+ this.state.shuffleOrder = this.state.shuffleOrder
+ .filter((i) => i !== index)
+ .map((i) => (i > index ? i - 1 : i));
+ }
+ }
+
+ clear(): void {
+ this.state.tracks = [];
+ this.state.currentIndex = -1;
+ this.state.shuffleOrder = [];
+ }
+}
diff --git a/Build/src/core/engine/scheduler/index.ts b/Build/src/core/engine/scheduler/index.ts
new file mode 100644
index 0000000..300e5f5
--- /dev/null
+++ b/Build/src/core/engine/scheduler/index.ts
@@ -0,0 +1,236 @@
+import type { CrossfadeConfig, GaplessConfig, Track } from "../types";
+
+export interface ScheduledTransition {
+ type: "crossfade" | "gapless";
+ fromTrack: Track;
+ toTrack: Track;
+ triggerTime: number;
+ duration: number;
+}
+
+export type TransitionCurve = "linear" | "equalpower";
+
+export class CrossfadeScheduler {
+ private config: CrossfadeConfig = {
+ enabled: false,
+ duration: 3000,
+ shape: "equalpower",
+ };
+
+ private activeTransition: ScheduledTransition | null = null;
+
+ setConfig(config: Partial): void {
+ this.config = { ...this.config, ...config };
+ }
+
+ getConfig(): CrossfadeConfig {
+ return { ...this.config };
+ }
+
+ isEnabled(): boolean {
+ return this.config.enabled && this.config.duration > 0;
+ }
+
+ calculateTriggerTime(
+ trackDuration: number,
+ currentTime: number,
+ ): number | null {
+ if (!this.isEnabled()) return null;
+
+ const durationSeconds = this.config.duration / 1000;
+ if (trackDuration <= durationSeconds) return null;
+
+ const triggerTime = trackDuration - durationSeconds;
+ if (currentTime >= triggerTime) {
+ return triggerTime;
+ }
+ return triggerTime;
+ }
+
+ shouldTrigger(currentTime: number, duration: number): boolean {
+ if (!this.isEnabled()) return false;
+
+ const triggerPoint = duration - this.config.duration;
+ return currentTime >= triggerPoint;
+ }
+
+ getCurve(): TransitionCurve {
+ return this.config.shape === "none" ? "linear" : this.config.shape;
+ }
+
+ calculateVolumes(progress: number): { fromVolume: number; toVolume: number } {
+ const { shape } = this.config;
+ const p = progress;
+
+ let fromVolume: number;
+ let toVolume: number;
+
+ switch (shape) {
+ case "equalpower":
+ fromVolume = Math.cos((p * Math.PI) / 2);
+ toVolume = Math.sin((p * Math.PI) / 2);
+ break;
+ case "linear":
+ fromVolume = 1 - p;
+ toVolume = p;
+ break;
+ default:
+ fromVolume = 1;
+ toVolume = 1;
+ }
+
+ return { fromVolume, toVolume };
+ }
+
+ createTransition(
+ fromTrack: Track,
+ toTrack: Track,
+ duration: number,
+ ): ScheduledTransition {
+ return {
+ type: "crossfade",
+ fromTrack,
+ toTrack,
+ triggerTime: Date.now(),
+ duration,
+ };
+ }
+
+ setActiveTransition(transition: ScheduledTransition | null): void {
+ this.activeTransition = transition;
+ }
+
+ getActiveTransition(): ScheduledTransition | null {
+ return this.activeTransition;
+ }
+
+ clearActiveTransition(): void {
+ this.activeTransition = null;
+ }
+}
+
+export class GaplessScheduler {
+ private config: GaplessConfig = {
+ enabled: true,
+ startOffset: 0,
+ endOffset: 0,
+ };
+
+ setConfig(config: Partial): void {
+ this.config = { ...this.config, ...config };
+ }
+
+ getConfig(): GaplessConfig {
+ return { ...this.config };
+ }
+
+ isEnabled(): boolean {
+ return this.config.enabled;
+ }
+
+ getStartOffset(track: Track): number {
+ return track.gapless?.encoderDelay ?? this.config.startOffset;
+ }
+
+ getEndOffset(track: Track): number {
+ return track.gapless?.encoderPadding ?? this.config.endOffset;
+ }
+
+ shouldPreload(currentTime: number, duration: number): boolean {
+ const preloadTime = 10;
+ return duration - currentTime <= preloadTime;
+ }
+
+ calculatePlayEnd(track: Track): number {
+ const offset = this.getEndOffset(track);
+ return track.duration - offset;
+ }
+
+ shouldTransition(currentTime: number, track: Track): boolean {
+ const playEnd = this.calculatePlayEnd(track);
+ const threshold = 0.1;
+ return currentTime >= playEnd - threshold;
+ }
+}
+
+export class Scheduler {
+ private crossfade: CrossfadeScheduler;
+ private gapless: GaplessScheduler;
+ private currentMode: "crossfade" | "gapless" | "none" = "none";
+
+ constructor() {
+ this.crossfade = new CrossfadeScheduler();
+ this.gapless = new GaplessScheduler();
+ }
+
+ setCrossfadeConfig(config: Partial): void {
+ this.crossfade.setConfig(config);
+ this.updateMode();
+ }
+
+ setGaplessConfig(config: Partial): void {
+ this.gapless.setConfig(config);
+ this.updateMode();
+ }
+
+ private updateMode(): void {
+ if (this.gapless.isEnabled() && this.gapless.getConfig().enabled) {
+ this.currentMode = "gapless";
+ } else if (this.crossfade.isEnabled()) {
+ this.currentMode = "crossfade";
+ } else {
+ this.currentMode = "none";
+ }
+ }
+
+ getMode(): "crossfade" | "gapless" | "none" {
+ return this.currentMode;
+ }
+
+ shouldPreload(currentTime: number, duration: number): boolean {
+ return this.gapless.shouldPreload(currentTime, duration);
+ }
+
+ shouldTriggerTransition(currentTime: number, track: Track): boolean {
+ switch (this.currentMode) {
+ case "crossfade":
+ return this.crossfade.shouldTrigger(currentTime, track.duration);
+ case "gapless":
+ return this.gapless.shouldTransition(currentTime, track);
+ default:
+ return false;
+ }
+ }
+
+ getTransitionParams(
+ currentTime: number,
+ track: Track,
+ ): {
+ triggerTime: number;
+ duration: number;
+ } | null {
+ switch (this.currentMode) {
+ case "crossfade":
+ const triggerTime = this.crossfade.calculateTriggerTime(
+ track.duration,
+ currentTime,
+ );
+ return triggerTime !== null
+ ? { triggerTime, duration: this.crossfade.getConfig().duration }
+ : null;
+ case "gapless":
+ const playEnd = this.gapless.calculatePlayEnd(track);
+ return { triggerTime: playEnd - 10, duration: 0 };
+ default:
+ return null;
+ }
+ }
+
+ getCrossfade(): CrossfadeScheduler {
+ return this.crossfade;
+ }
+
+ getGapless(): GaplessScheduler {
+ return this.gapless;
+ }
+}
diff --git a/Build/src/core/engine/state/index.ts b/Build/src/core/engine/state/index.ts
new file mode 100644
index 0000000..969c786
--- /dev/null
+++ b/Build/src/core/engine/state/index.ts
@@ -0,0 +1,79 @@
+import type { PlayerState } from "../types";
+
+const VALID_TRANSITIONS: Record = {
+ idle: ["loading", "ready"],
+ loading: ["ready", "error"],
+ ready: ["playing", "paused", "loading"],
+ playing: ["paused", "transitioning", "ready", "error"],
+ paused: ["playing", "ready", "loading", "error"],
+ transitioning: ["playing", "paused", "ready", "idle", "error"],
+ error: ["loading", "ready", "idle"],
+};
+
+export class StateMachine {
+ private state: PlayerState = "idle";
+ private history: PlayerState[] = [];
+
+ getState(): PlayerState {
+ return this.state;
+ }
+
+ canTransition(to: PlayerState): boolean {
+ return VALID_TRANSITIONS[this.state]?.includes(to) ?? false;
+ }
+
+ transition(to: PlayerState, force = false): boolean {
+ if (force || this.canTransition(to)) {
+ this.history.push(this.state);
+ if (this.history.length > 20) {
+ this.history.shift();
+ }
+ this.state = to;
+ return true;
+ }
+ return false;
+ }
+
+ isPlaying(): boolean {
+ return this.state === "playing";
+ }
+
+ isPaused(): boolean {
+ return this.state === "paused";
+ }
+
+ isIdle(): boolean {
+ return this.state === "idle";
+ }
+
+ isLoading(): boolean {
+ return this.state === "loading";
+ }
+
+ isReady(): boolean {
+ return this.state === "ready";
+ }
+
+ isTransitioning(): boolean {
+ return this.state === "transitioning";
+ }
+
+ hasError(): boolean {
+ return this.state === "error";
+ }
+
+ getPreviousState(): PlayerState | null {
+ return this.history.length > 0
+ ? this.history[this.history.length - 1]
+ : null;
+ }
+
+ getHistory(): PlayerState[] {
+ return [...this.history];
+ }
+
+ reset(): void {
+ this.state = "idle";
+ this.history = [];
+ }
+}
diff --git a/Build/src/core/engine/types.ts b/Build/src/core/engine/types.ts
new file mode 100644
index 0000000..72342ee
--- /dev/null
+++ b/Build/src/core/engine/types.ts
@@ -0,0 +1,165 @@
+export interface Track {
+ id: string;
+ title: string;
+ artist: string;
+ album: string;
+ duration: number;
+ url: string;
+ mimeType?: string;
+ hasStoredAudio?: boolean;
+ albumArt?: string;
+ hasAlbumArt?: boolean;
+ embeddedLyrics?: EmbeddedLyrics[];
+ encoding?: EncodingDetails;
+ gapless?: GaplessInfo;
+ replayGain?: ReplayGainInfo;
+}
+
+export interface EmbeddedLyrics {
+ synced: boolean;
+ language?: string;
+ description?: string;
+ text?: string;
+ lines?: LyricLine[];
+}
+
+export interface LyricLine {
+ text: string;
+ timestamp: number;
+}
+
+export interface EncodingDetails {
+ bitrate?: number;
+ codec?: string;
+ sampleRate?: number;
+ channels?: number;
+ bitsPerSample?: number;
+ container?: string;
+ lossless?: boolean;
+ profile?: string;
+}
+
+export interface GaplessInfo {
+ encoderDelay?: number;
+ encoderPadding?: number;
+}
+
+export interface ReplayGainInfo {
+ trackGain?: number;
+ trackPeak?: number;
+ albumGain?: number;
+ albumPeak?: number;
+ referenceLoudness?: number;
+}
+
+export interface Playlist {
+ id: string;
+ name: string;
+ songs: Track[];
+}
+
+export interface PlaylistFolder {
+ id: string;
+ name: string;
+ children: (Playlist | PlaylistFolder)[];
+}
+
+export type PlaylistItem = Playlist | PlaylistFolder;
+
+export interface QueueState {
+ tracks: Track[];
+ currentIndex: number;
+ shuffled: boolean;
+ shuffleOrder: number[];
+}
+
+export interface PlayHistory {
+ trackId: string;
+ lastPlayed: number;
+ playCount: number;
+}
+
+export interface EngineSettings {
+ volume: number;
+ crossfade: number;
+ crossfadeBeforeGapless: number;
+ autoPlayNext: boolean;
+ tempo: number;
+ pitch: number;
+ gaplessPlayback: boolean;
+ smartShuffle: boolean;
+ repeat: RepeatMode;
+ defaultShuffle: boolean;
+ defaultRepeat: RepeatMode;
+}
+
+export type RepeatMode = "off" | "one" | "all";
+
+export type PlayerState =
+ | "idle"
+ | "loading"
+ | "ready"
+ | "playing"
+ | "paused"
+ | "transitioning"
+ | "error";
+
+export interface EngineState {
+ state: PlayerState;
+ currentTrack: Track | null;
+ currentPlaylist: Playlist | null;
+ queue: QueueState;
+ settings: EngineSettings;
+ currentTime: number;
+ duration: number;
+ volume: number;
+ playHistory: Map;
+ error: EngineError | null;
+}
+
+export interface EngineError {
+ code: string;
+ message: string;
+ track?: Track;
+}
+
+export type EngineEvent =
+ | "statechange"
+ | "trackchange"
+ | "timeupdate"
+ | "durationchange"
+ | "volumechange"
+ | "queuechange"
+ | "settingschange"
+ | "ended"
+ | "loading"
+ | "ready"
+ | "error";
+
+export interface EngineEventMap {
+ statechange: { oldState: PlayerState; newState: PlayerState };
+ trackchange: { from: Track | null; to: Track | null };
+ timeupdate: { currentTime: number; duration: number };
+ durationchange: { duration: number };
+ volumechange: { volume: number };
+ queuechange: { queue: QueueState };
+ settingschange: { settings: Partial };
+ ended: { track: Track };
+ loading: { track: Track };
+ ready: { track: Track };
+ error: { error: EngineError };
+}
+
+export interface CrossfadeConfig {
+ enabled: boolean;
+ duration: number;
+ shape: CrossfadeShape;
+}
+
+export type CrossfadeShape = "none" | "linear" | "equalpower";
+
+export interface GaplessConfig {
+ enabled: boolean;
+ startOffset: number;
+ endOffset: number;
+}
diff --git a/Build/src/data/legal.ts b/Build/src/data/legal.ts
new file mode 100644
index 0000000..34aa52f
--- /dev/null
+++ b/Build/src/data/legal.ts
@@ -0,0 +1,120 @@
+export interface LegalSection {
+ heading: string;
+ content: string | string[];
+}
+
+export interface LegalDocument {
+ title: string;
+ effectiveDate: string;
+ sections: LegalSection[];
+ contact: string;
+}
+
+export const privacyPolicy: LegalDocument = {
+ title: "HTMLPlayer Privacy Policy",
+ effectiveDate: "9/23/2025",
+ sections: [
+ {
+ heading: "1. Introduction",
+ content: `HTMLPlayer respects your privacy. Since the App is primarily client-side,
+we do not collect personal data unless you interact with external services
+(e.g., Discord integration).`,
+ },
+ {
+ heading: "2. Data Collection",
+ content: [
+ "The App does not collect personal information by default.",
+ "Optional Discord integration may send limited information (username, current activity) to Discord's servers for the purpose of updating your music activity.",
+ ],
+ },
+ {
+ heading: "3. Cookies and Tracking",
+ content:
+ "HTMLPlayer does not use cookies or trackers for analytics or advertising.",
+ },
+ {
+ heading: "4. Third-Party Services",
+ content: `Discord integration is managed via OAuth; your authorization is handled by
+Discord directly. HTMLPlayer does not store Discord credentials or share
+data outside the Discord API.`,
+ },
+ {
+ heading: "5. Security",
+ content: `All client-side operations run in your browser; no server-side storage of
+music or personal data occurs. We take no responsibility for security
+vulnerabilities in your browser or Discord.`,
+ },
+ {
+ heading: "6. Data Sharing",
+ content:
+ "HTMLPlayer does not sell, trade, or share personal information with third parties, except through authorized use of Discord features.",
+ },
+ {
+ heading: "7. Updates to Privacy Policy",
+ content:
+ "We may update this Privacy Policy as HTMLPlayer evolves. Continued use indicates acceptance of the latest policy.",
+ },
+ {
+ heading: "8. Contact",
+ content: "For privacy questions, contact: nellowtcs@gmail.com",
+ },
+ ],
+ contact: "nellowtcs@gmail.com",
+};
+
+export const termsOfService: LegalDocument = {
+ title: "HTMLPlayer Terms of Service (TOS)",
+ effectiveDate: "9/23/2025",
+ sections: [
+ {
+ heading: "1. Acceptance of Terms",
+ content:
+ 'By using HTMLPlayer (the "App"), you agree to these Terms of Service. If you do not agree, do not use the App.',
+ },
+ {
+ heading: "2. Use of the App",
+ content: [
+ "HTMLPlayer is a free, open-source music player.",
+ "All core functionality runs client-side in your browser; we do not collect usage data except when explicitly interacting with external services like Discord.",
+ "You may use the App for personal, non-commercial purposes.",
+ ],
+ },
+ {
+ heading: "3. Intellectual Property",
+ content: `HTMLPlayer and its source code are licensed under the
+MIT License. You may copy, modify, or redistribute the App according to the MIT License terms.`,
+ },
+ {
+ heading: "4. Discord Integration",
+ content: `The App may optionally integrate with Discord to display music activity.
+Access to Discord features requires you to authorize HTMLPlayer via
+Discord OAuth. HTMLPlayer does not store your Discord credentials.`,
+ },
+ {
+ heading: "5. Beta Disclaimer",
+ content:
+ "HTMLPlayer is currently in beta. Features may be unstable or incomplete. Use at your own risk.",
+ },
+ {
+ heading: "6. No Warranty",
+ content: `The App is provided "as-is" without warranty of any kind, either express
+or implied. The developers are not liable for any damages arising from the
+use or inability to use HTMLPlayer.`,
+ },
+ {
+ heading: "7. Limitation of Liability",
+ content:
+ "You use HTMLPlayer entirely at your own risk. Developers are not responsible for any loss, data corruption, or other issues resulting from your use of the App.",
+ },
+ {
+ heading: "8. Modifications to Terms",
+ content:
+ "We may update these Terms at any time. Continued use constitutes acceptance of the updated Terms.",
+ },
+ {
+ heading: "9. Contact",
+ content: "For questions about these Terms, contact: nellowtcs@gmail.com",
+ },
+ ],
+ contact: "nellowtcs@gmail.com",
+};
diff --git a/Build/src/global.css b/Build/src/global.css
index e4278a0..188d725 100644
--- a/Build/src/global.css
+++ b/Build/src/global.css
@@ -75,6 +75,10 @@ body {
overflow: hidden;
}
+html {
+ overflow-y: auto;
+}
+
/* html {
background: var(--themegradient);
} */
diff --git a/Build/src/helpers/audioProcessor.ts b/Build/src/helpers/audioProcessor.ts
deleted file mode 100644
index c691d36..0000000
--- a/Build/src/helpers/audioProcessor.ts
+++ /dev/null
@@ -1,102 +0,0 @@
-import { toast } from "sonner";
-import { musicIndexedDbHelper } from "./musicIndexedDbHelper";
-import i18n from "i18next";
-import initFlo from "@flo-audio/libflo-audio";
-
-export const createAudioProcessor = () => {
- let floInitialized = false;
- const processAudioBatch = async (songs: Song[]): Promise => {
- // Ensure flo WASM is initialized before any decode
- if (!floInitialized) {
- await initFlo();
- floInitialized = true;
- }
- const processedSongs: Song[] = [];
- const totalSongs = songs.length;
- let processedCount = 0;
-
- // Show initial toast
- const toastId = toast.loading(
- i18n.t("audioProcessor.processingZero", { totalSongs }),
- );
-
- for (const song of songs) {
- if (song.url.startsWith("blob:")) {
- try {
- // Load the audio data
- const res = await fetch(song.url);
- const buf = await res.arrayBuffer();
- let mimeType = res.headers.get("content-type") || "audio/mpeg";
- const ext = song.url.split(".").pop()?.toLowerCase() || "";
-
- // If flo file, decode using @flo-audio/libflo-audio (placeholder)
- if (ext === "flo") {
- // TODO: Integrate @flo-audio/libflo-audio decoder here
- // Example:
- // import { decodeFlo } from '@flo-audio/libflo-audio';
- // const pcmData = await decodeFlo(buf);
- // ...convert pcmData to AudioBuffer and store/play as needed...
- mimeType = "audio/x-flo";
- }
-
- // Save to IndexedDB audio store
- await musicIndexedDbHelper.saveSongAudio(song.id, {
- fileData: buf,
- mimeType,
- });
-
- // Add processed song without the audio data
- processedSongs.push({
- ...song,
- hasStoredAudio: true,
- albumArt: song.albumArt, // Preserve album art when processing
- });
-
- processedCount++;
- // Update toast with progress
- toast.loading(
- i18n.t("audioProcessor.processing", { processedCount, totalSongs }),
- {
- id: toastId,
- description: i18n.t("audioProcessor.current", {
- songTitle: song.title,
- }),
- },
- );
- } catch (error) {
- const err = error as Error;
- console.error(
- i18n.t("audioProcessor.failedToProcess", { songTitle: song.title }),
- err,
- );
- toast.error(`Failed to process "${song.title}"`, {
- description: err.message || i18n.t("common.unknownError"),
- });
- processedSongs.push(song);
- }
- } else {
- processedSongs.push(song);
- processedCount++;
- }
- }
-
- // Show completion toast
- toast.success(i18n.t("audioProcessor.processed", { processedCount }), {
- id: toastId,
- });
-
- return processedSongs;
- };
-
- const getValidTempo = (tempo: number | undefined) => {
- if (typeof tempo !== "number" || !Number.isFinite(tempo) || tempo <= 0) {
- return 1; // fallback to normal speed
- }
- return tempo;
- };
-
- return {
- processAudioBatch,
- getValidTempo,
- };
-};
diff --git a/Build/src/helpers/cacheManager.ts b/Build/src/helpers/cacheManager.ts
deleted file mode 100644
index ac312c8..0000000
--- a/Build/src/helpers/cacheManager.ts
+++ /dev/null
@@ -1,444 +0,0 @@
-import { MutableRefObject, useCallback } from "react";
-import { musicIndexedDbHelper } from "./musicIndexedDbHelper";
-
-const CACHE_CONFIG = {
- PREV_SONGS: 1, // Number of previous songs to cache
- NEXT_SONGS: 2, // Number of next songs to cache
- CACHE_EXPIRY: 5 * 60 * 1000, // 5 minutes
- MAX_CACHE_SIZE: 15, // Maximum number of songs to cache
- PRELOAD_THRESHOLD: 7 * 1024 * 1024, // 7MB, only preload smaller files
-};
-
-// Cache management utilities with improved error handling and performance
-export const createCacheManager = (
- songCacheRef: MutableRefObject>,
-) => {
- const cacheSong = async (song: Song): Promise => {
- // Check if song is already cached and valid
- const existingCache = songCacheRef.current.get(song.id);
- if (existingCache) {
- // Check if cache is still valid
- const cacheAge = Date.now() - existingCache.loadedAt;
- if (cacheAge < CACHE_CONFIG.CACHE_EXPIRY) {
- // Update URL if it's from IndexedDB and needs refresh
- if (song.hasStoredAudio && song.url.startsWith("indexeddb://")) {
- try {
- const audioData = await musicIndexedDbHelper.loadSongAudio(song.id);
- if (audioData && !existingCache.url.startsWith("blob:")) {
- // Need to create new blob URL
- const newUrl = URL.createObjectURL(
- new Blob([audioData.fileData], { type: audioData.mimeType }),
- );
- // Revoke old URL if it was a blob
- if (existingCache.url.startsWith("blob:")) {
- URL.revokeObjectURL(existingCache.url);
- }
- // Update cache with new URL
- songCacheRef.current.set(song.id, {
- ...existingCache,
- url: newUrl,
- song: { ...song, url: newUrl },
- loadedAt: Date.now(),
- });
- }
- } catch (error) {
- console.warn(
- "Failed to refresh IndexedDB cache for song:",
- song.id,
- error,
- );
- }
- }
- // Already cached, no need to return anything
- } else {
- // Cache expired, remove it
- if (existingCache.url.startsWith("blob:")) {
- URL.revokeObjectURL(existingCache.url);
- }
- songCacheRef.current.delete(song.id);
- }
- }
-
- try {
- let audioData;
- let mimeType: string;
-
- // First try to load from IndexedDB
- if (song.hasStoredAudio) {
- console.log("CacheManager: Loading song from IndexedDB:", song.id);
- audioData = await musicIndexedDbHelper.loadSongAudio(song.id);
- if (audioData) {
- const url = URL.createObjectURL(
- new Blob([audioData.fileData], { type: audioData.mimeType }),
- );
- songCacheRef.current.set(song.id, {
- song: { ...song, url },
- url,
- loadedAt: Date.now(),
- });
- console.log(
- "CacheManager: Successfully cached song from IndexedDB:",
- song.title,
- );
- return; // Successfully loaded from IndexedDB, exit early
- } else {
- // Audio was marked as stored but not found in IndexedDB
- console.warn(
- "CacheManager: Song has stored audio but not found in IndexedDB:",
- song.id,
- );
- return; // Don't try to fetch if audio should be in IndexedDB
- }
- }
-
- if (
- !song.url ||
- song.url.startsWith("indexeddb://") ||
- song.url.includes("about:blank")
- ) {
- console.error(
- "CacheManager: No valid URL to fetch song from:",
- song.id,
- );
- return;
- }
-
- console.log("CacheManager: Fetching song from URL:", song.title);
-
- // Check if we should preload based on file size (if available)
- let shouldCache = true;
-
- try {
- const headResponse = await fetch(song.url, { method: "HEAD" });
- const contentLength = headResponse.headers.get("content-length");
- if (contentLength) {
- const fileSize = parseInt(contentLength);
- if (fileSize > CACHE_CONFIG.PRELOAD_THRESHOLD) {
- console.log(
- "CacheManager: Large file detected, skipping aggressive caching:",
- song.title,
- );
- shouldCache = false;
- }
- }
- } catch (headError) {
- // HEAD request failed, continue with normal caching
- console.warn(
- "CacheManager: HEAD request failed, continuing with caching:",
- headError,
- );
- }
-
- const response = await fetch(song.url);
- if (!response.ok) {
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
- }
-
- const buffer = await response.arrayBuffer();
- mimeType = response.headers.get("content-type") || "audio/mpeg";
- const url = URL.createObjectURL(new Blob([buffer], { type: mimeType }));
-
- // Cache in memory if appropriate
- if (shouldCache || buffer.byteLength <= CACHE_CONFIG.PRELOAD_THRESHOLD) {
- songCacheRef.current.set(song.id, {
- song: { ...song, url },
- url,
- loadedAt: Date.now(),
- });
- }
-
- // Always save to IndexedDB for future use (unless it came from there originally)
- if (!song.hasStoredAudio) {
- try {
- await musicIndexedDbHelper.saveSongAudio(song.id, {
- fileData: buffer,
- mimeType: mimeType,
- });
- console.log("CacheManager: Saved song to IndexedDB:", song.title);
- } catch (dbError) {
- console.warn("CacheManager: Failed to save to IndexedDB:", dbError);
- }
- }
-
- console.log(
- "CacheManager: Successfully cached song from URL:",
- song.title,
- );
- } catch (error) {
- console.error("CacheManager: Failed to cache song:", song.title, error);
- }
- };
-
- const getCachedSong = (songId: string): CachedSong | undefined => {
- const cached = songCacheRef.current.get(songId);
- if (cached) {
- // Check if cache is still valid
- const cacheAge = Date.now() - cached.loadedAt;
- if (cacheAge < CACHE_CONFIG.CACHE_EXPIRY) {
- return cached;
- } else {
- // Cache expired, remove it
- if (cached.url.startsWith("blob:")) {
- URL.revokeObjectURL(cached.url);
- }
- songCacheRef.current.delete(songId);
- }
- }
- return undefined;
- };
-
- const clearExpiredCache = () => {
- const now = Date.now();
- const expiredKeys: string[] = [];
-
- for (const [id, cached] of songCacheRef.current.entries()) {
- if (now - cached.loadedAt > CACHE_CONFIG.CACHE_EXPIRY) {
- expiredKeys.push(id);
- if (cached.url.startsWith("blob:")) {
- URL.revokeObjectURL(cached.url);
- }
- }
- }
-
- expiredKeys.forEach((key) => songCacheRef.current.delete(key));
-
- if (expiredKeys.length > 0) {
- console.log(
- `CacheManager: Cleared ${expiredKeys.length} expired cache entries`,
- );
- }
- };
-
- const enforceCacheSize = () => {
- if (songCacheRef.current.size <= CACHE_CONFIG.MAX_CACHE_SIZE) return;
-
- // Sort by last accessed time (oldest first)
- const entries = Array.from(songCacheRef.current.entries()).sort(
- (a, b) => a[1].loadedAt - b[1].loadedAt,
- );
-
- const toRemove = entries.slice(
- 0,
- songCacheRef.current.size - CACHE_CONFIG.MAX_CACHE_SIZE,
- );
-
- for (const [id, cached] of toRemove) {
- if (cached.url.startsWith("blob:")) {
- URL.revokeObjectURL(cached.url);
- }
- songCacheRef.current.delete(id);
- }
-
- console.log(
- `CacheManager: Removed ${toRemove.length} entries to enforce cache size limit`,
- );
- };
-
- // Helper to ensure playlist songs have correct URLs
- const prepareSongsForPlaylist = useCallback((songs: Song[]): Song[] => {
- return songs.map((song) => {
- if (song.hasStoredAudio) {
- // Always use indexeddb:// URL for stored songs
- return {
- ...song,
- url: `indexeddb://${song.id}`,
- };
- } else if (songCacheRef.current.has(song.id)) {
- // If song is in cache, use its cached URL
- const cached = songCacheRef.current.get(song.id);
- return {
- ...song,
- url: cached?.url || song.url,
- };
- }
- return song;
- });
- }, []);
-
- const updateSongCache = async (
- currentSong: Song | null,
- playlist: Playlist | null,
- playerStateRef: MutableRefObject,
- settingsRef: MutableRefObject,
- playHistoryRef: MutableRefObject<
- Map
- >,
- getSmartShuffledSong: (
- availableSongs: Song[],
- currentSongId: string,
- playHistory: Map,
- ) => Song | null,
- ) => {
- if (!currentSong || !playlist) return;
-
- // Periodic cleanup
- clearExpiredCache();
- enforceCacheSize();
-
- const currentIndex = playlist.songs.findIndex(
- (s) => s.id === currentSong.id,
- );
- if (currentIndex === -1) return;
-
- // Get the range of songs to cache (surrounding the current song)
- const start = Math.max(0, currentIndex - CACHE_CONFIG.PREV_SONGS);
- const end = Math.min(
- playlist.songs.length - 1,
- currentIndex + CACHE_CONFIG.NEXT_SONGS,
- );
-
- // Get next shuffled songs if shuffle is enabled (cache multiple for better performance)
- const nextShuffledSongs: Song[] = [];
- if (playerStateRef.current.shuffle) {
- const availableSongs = playlist.songs.filter(
- (_, i) => i !== currentIndex,
- );
-
- if (availableSongs.length > 0) {
- // Cache multiple potential next songs for shuffle
- const songsToGenerate = Math.min(3, availableSongs.length);
- const usedSongs = new Set();
-
- for (let i = 0; i < songsToGenerate; i++) {
- let nextSong: Song | null = null;
-
- if (settingsRef.current.smartShuffle) {
- // Use smart shuffle for caching
- const availableForThis = availableSongs.filter(
- (s) => !usedSongs.has(s.id),
- );
- nextSong = getSmartShuffledSong(
- availableForThis,
- currentSong.id,
- playHistoryRef.current,
- );
- } else {
- // Use regular shuffle for caching
- const availableForThis = availableSongs.filter(
- (s) => !usedSongs.has(s.id),
- );
- if (availableForThis.length > 0) {
- const randomIndex = Math.floor(
- Math.random() * availableForThis.length,
- );
- nextSong = availableForThis[randomIndex];
- }
- }
-
- if (nextSong && !usedSongs.has(nextSong.id)) {
- nextShuffledSongs.push(nextSong);
- usedSongs.add(nextSong.id);
- }
- }
- }
- }
-
- // Create a set of songs to cache (prioritize nearby songs and shuffled options)
- const songsToCache = new Set([
- ...playlist.songs.slice(start, end + 1),
- ...nextShuffledSongs,
- ]);
-
- // Cache new songs (prioritize current and next songs)
- const cachePromises: Promise[] = [];
- const songsArray = Array.from(songsToCache);
-
- // Sort by priority: current song first, then immediate neighbors, then shuffled options
- songsArray.sort((a, b) => {
- if (a.id === currentSong.id) return -1;
- if (b.id === currentSong.id) return 1;
-
- const aIndex = playlist.songs.findIndex((s) => s.id === a.id);
- const bIndex = playlist.songs.findIndex((s) => s.id === b.id);
-
- const aDistance = Math.abs(aIndex - currentIndex);
- const bDistance = Math.abs(bIndex - currentIndex);
-
- return aDistance - bDistance;
- });
-
- // Cache songs in priority order
- for (const song of songsArray) {
- if (!songCacheRef.current.has(song.id)) {
- cachePromises.push(cacheSong(song));
- }
- }
-
- // Remove songs that are no longer needed (but keep some buffer)
- const currentCacheIds = new Set(Array.from(songCacheRef.current.keys()));
- const keepIds = new Set(songsArray.map((song) => song.id));
-
- for (const cachedId of currentCacheIds) {
- if (!keepIds.has(cachedId)) {
- const cached = songCacheRef.current.get(cachedId);
- if (cached) {
- // Only remove if it's not recently accessed
- const age = Date.now() - cached.loadedAt;
- if (age > CACHE_CONFIG.CACHE_EXPIRY / 2) {
- if (cached.url.startsWith("blob:")) {
- URL.revokeObjectURL(cached.url);
- }
- songCacheRef.current.delete(cachedId);
- }
- }
- }
- }
-
- // Wait for priority caches to complete (don't block on all)
- try {
- const results = await Promise.allSettled(cachePromises);
- const successful = results.filter(
- (r) => r.status === "fulfilled" && r.value,
- ).length;
- console.log(
- `CacheManager: Successfully cached ${successful} of ${cachePromises.length} songs`,
- );
- } catch (error) {
- console.error("CacheManager: Error in batch caching:", error);
- }
- };
-
- const clearAllCache = () => {
- console.log("CacheManager: Clearing all cache");
-
- // Revoke all object URLs and clear the cache
- for (const [, cached] of songCacheRef.current.entries()) {
- if (cached.url.startsWith("blob:")) {
- URL.revokeObjectURL(cached.url);
- }
- }
- songCacheRef.current.clear();
- };
-
- const getCacheStats = () => {
- const now = Date.now();
- let validCount = 0;
- let expiredCount = 0;
-
- for (const [, cached] of songCacheRef.current.entries()) {
- if (now - cached.loadedAt < CACHE_CONFIG.CACHE_EXPIRY) {
- validCount++;
- } else {
- expiredCount++;
- }
- }
-
- return {
- total: songCacheRef.current.size,
- valid: validCount,
- expired: expiredCount,
- maxSize: CACHE_CONFIG.MAX_CACHE_SIZE,
- };
- };
-
- return {
- cacheSong,
- getCachedSong,
- clearExpiredCache,
- enforceCacheSize,
- prepareSongsForPlaylist,
- updateSongCache,
- clearAllCache,
- getCacheStats,
- };
-};
diff --git a/Build/src/helpers/crossfadeHelper.ts b/Build/src/helpers/crossfadeHelper.ts
deleted file mode 100644
index 9bf6fc7..0000000
--- a/Build/src/helpers/crossfadeHelper.ts
+++ /dev/null
@@ -1,541 +0,0 @@
-import i18n from "i18next";
-
-export interface CrossfadeOptions {
- duration: number;
- curve?: "linear" | "exponential" | "smooth";
-}
-
-export interface AudioSource {
- element: HTMLAudioElement;
- source: MediaElementAudioSourceNode;
- gainNode: GainNode;
- id: string;
-}
-
-/**
- * Validate and clamp pitch value
- */
-function getValidPitch(pitch: number | undefined): number {
- if (typeof pitch !== "number" || !Number.isFinite(pitch)) {
- return 0; // Default to no pitch shift
- }
- // Clamp to -48 to +48 semitones
- return Math.max(-48, Math.min(48, pitch));
-}
-
-export class CrossfadeManager {
- private audioContext: AudioContext;
- private masterGain: GainNode;
- private analyzerNode: AnalyserNode;
-
- private currentSource: AudioSource | null = null;
- private nextSource: AudioSource | null = null;
-
- private crossfadeInProgress = false;
- private crossfadeTimeout: number | null = null;
- private crossfadePromise: Promise | null = null;
-
- // Track which audio element is the "active" one for UI updates
- private activeElement: HTMLAudioElement | null = null;
-
- // Current pitch setting
- private currentPitch: number = 0;
-
- // Track the current song ended handler for cleanup
- private currentEndedHandler: (() => void) | null = null;
-
- constructor(audioContext: AudioContext) {
- this.audioContext = audioContext;
-
- // Create master gain node
- this.masterGain = audioContext.createGain();
- this.masterGain.connect(audioContext.destination);
-
- // Create analyzer for visualizations
- this.analyzerNode = audioContext.createAnalyser();
- this.analyzerNode.fftSize = 2048;
- this.masterGain.connect(this.analyzerNode);
- }
-
- /**
- * Create an audio source with proper Web Audio setup
- */
- createAudioSource(audioElement: HTMLAudioElement): AudioSource {
- // Check if this element already has an audio source
- const existingSource = (audioElement as any)._webAudioSource;
- if (existingSource && existingSource.source.mediaElement === audioElement) {
- return existingSource;
- }
-
- try {
- const source = this.audioContext.createMediaElementSource(audioElement);
- const gainNode = this.audioContext.createGain();
-
- // Connect: MediaElementSource -> GainNode -> MasterGain
- source.connect(gainNode);
- gainNode.connect(this.masterGain);
-
- const audioSource: AudioSource = {
- element: audioElement,
- source,
- gainNode,
- id: Math.random().toString(36).substr(2, 9),
- };
-
- // Store reference to prevent multiple sources for same element
- (audioElement as any)._webAudioSource = audioSource;
-
- return audioSource;
- } catch (error) {
- console.error("Failed to create audio source:", error);
- throw error;
- }
- }
-
- /**
- * Set the current playing source
- */
- setCurrentSource(source: AudioSource) {
- if (this.currentSource !== source) {
- this.currentSource = source;
- this.activeElement = source.element;
-
- // Set to full volume
- this.currentSource.gainNode.gain.setValueAtTime(
- 1,
- this.audioContext.currentTime,
- );
-
- // Mute any previous sources
- if (this.nextSource && this.nextSource !== source) {
- this.nextSource.gainNode.gain.setValueAtTime(
- 0,
- this.audioContext.currentTime,
- );
- }
- }
- }
-
- /**
- * Prepare the next source for crossfading
- */
- prepareNextSource(source: AudioSource) {
- this.nextSource = source;
- // Start muted
- this.nextSource.gainNode.gain.setValueAtTime(
- 0,
- this.audioContext.currentTime,
- );
- }
-
- /**
- * Start crossfade from current to next source
- */
- async startCrossfade(options: CrossfadeOptions): Promise {
- if (!this.currentSource || !this.nextSource) {
- throw new Error("Cannot start crossfade - missing audio sources");
- }
-
- if (this.crossfadeInProgress) {
- console.warn("Crossfade already in progress, cancelling previous");
- this.cancelCrossfade();
- }
-
- // Ensure audio context is running (may be suspended on mobile after tab switch)
- if (this.audioContext.state === "suspended") {
- console.log("Resuming suspended audio context before crossfade");
- await this.audioContext.resume();
- }
-
- this.crossfadeInProgress = true;
- const { duration, curve = "smooth" } = options;
- const now = this.audioContext.currentTime;
-
- console.log("Starting crossfade transition...");
-
- this.crossfadePromise = new Promise(async (resolve, reject) => {
- try {
- // Ensure next audio is ready to play
- if (this.nextSource!.element.readyState < 2) {
- await new Promise((loadResolve, loadReject) => {
- const timeout = setTimeout(() => {
- loadReject(
- new Error(i18n.t("crossfade.nextAudioFailedToLoadInTime")),
- );
- }, 5000);
-
- const cleanup = () => {
- clearTimeout(timeout);
- this.nextSource!.element.removeEventListener("canplay", onReady);
- this.nextSource!.element.removeEventListener(
- "loadeddata",
- onReady,
- );
- this.nextSource!.element.removeEventListener("error", onError);
- };
-
- const onReady = () => {
- cleanup();
- loadResolve();
- };
-
- const onError = () => {
- cleanup();
- loadReject(new Error(i18n.t("crossfade.nextAudioFailedToLoad")));
- };
-
- this.nextSource!.element.addEventListener("canplay", onReady);
- this.nextSource!.element.addEventListener("loadeddata", onReady);
- this.nextSource!.element.addEventListener("error", onError);
- });
- }
-
- // Start playing the next audio element
- await this.nextSource!.element.play();
-
- // Set up crossfade curves
- this.setupCrossfadeCurves(duration, curve, now);
-
- // Switch active element immediately so UI shows the new song
- this.activeElement = this.nextSource!.element;
-
- // Listen for current song ending
- const handleCurrentEnded = () => {
- if (this.crossfadeInProgress) {
- console.log("Current song ended during crossfade");
- this.currentEndedHandler = null; // Clear reference since it fired
- this.completeCrossfade();
- resolve();
- }
- };
-
- // Store handler reference for potential cleanup in cancelCrossfade
- this.currentEndedHandler = handleCurrentEnded;
-
- this.currentSource!.element.addEventListener(
- "ended",
- handleCurrentEnded,
- { once: true },
- );
-
- // Set timeout for crossfade completion
- this.crossfadeTimeout = window.setTimeout(
- () => {
- if (this.crossfadeInProgress) {
- this.currentSource!.element.removeEventListener(
- "ended",
- handleCurrentEnded,
- );
- this.completeCrossfade();
- resolve();
- }
- },
- duration * 1000 + 100,
- );
- } catch (error) {
- console.error("Crossfade failed:", error);
- this.crossfadeInProgress = false;
- this.clearCrossfadeTimeout();
- reject(error);
- }
- });
-
- return this.crossfadePromise;
- }
-
- /**
- * Set up crossfade curves using Web Audio gain automation
- */
- private setupCrossfadeCurves(
- duration: number,
- curve: string,
- startTime: number,
- ) {
- if (!this.currentSource || !this.nextSource) return;
-
- const currentGain = this.currentSource.gainNode.gain;
- const nextGain = this.nextSource.gainNode.gain;
-
- // Cancel any existing automation
- currentGain.cancelScheduledValues(startTime);
- nextGain.cancelScheduledValues(startTime);
-
- const endTime = startTime + duration;
-
- switch (curve) {
- case "linear":
- // Linear crossfade
- currentGain.setValueAtTime(1, startTime);
- currentGain.linearRampToValueAtTime(0, endTime);
-
- nextGain.setValueAtTime(0, startTime);
- nextGain.linearRampToValueAtTime(1, endTime);
- break;
-
- case "exponential":
- // Exponential crossfade (more natural for audio)
- currentGain.setValueAtTime(1, startTime);
- currentGain.exponentialRampToValueAtTime(0.001, endTime); // Can't ramp to exactly 0
-
- nextGain.setValueAtTime(0.001, startTime);
- nextGain.exponentialRampToValueAtTime(1, endTime);
- break;
-
- case "smooth":
- default:
- // Equal-power crossfade (best for music)
- const steps = 20;
- const stepDuration = duration / steps;
-
- for (let i = 0; i <= steps; i++) {
- const progress = i / steps;
- const time = startTime + i * stepDuration;
-
- // Equal-power curves: sqrt(1-x) and sqrt(x)
- const currentLevel = Math.sqrt(1 - progress);
- const nextLevel = Math.sqrt(progress);
-
- if (i === 0) {
- currentGain.setValueAtTime(currentLevel, time);
- nextGain.setValueAtTime(nextLevel, time);
- } else {
- currentGain.linearRampToValueAtTime(currentLevel, time);
- nextGain.linearRampToValueAtTime(nextLevel, time);
- }
- }
- break;
- }
- }
-
- /**
- * Complete the crossfade transition
- */
- private completeCrossfade() {
- if (!this.crossfadeInProgress) return;
-
- try {
- console.log("Completing crossfade transition");
-
- // Clear the ended handler reference (it either fired or will be removed by {once: true})
- this.currentEndedHandler = null;
-
- // Stop the old audio
- if (this.currentSource) {
- this.currentSource.element.pause();
- this.currentSource.element.currentTime = 0;
- this.currentSource.gainNode.gain.setValueAtTime(
- 0,
- this.audioContext.currentTime,
- );
- }
-
- // Ensure next source is at full volume
- if (this.nextSource) {
- this.nextSource.gainNode.gain.setValueAtTime(
- 1,
- this.audioContext.currentTime,
- );
- }
-
- // Swap sources
- this.currentSource = this.nextSource;
- this.nextSource = null;
-
- this.crossfadeInProgress = false;
- this.crossfadePromise = null;
- this.clearCrossfadeTimeout();
- } catch (error) {
- console.error("Error completing crossfade:", error);
- this.crossfadeInProgress = false;
- }
- }
-
- /**
- * Cancel an ongoing crossfade
- */
- cancelCrossfade() {
- if (!this.crossfadeInProgress) return;
-
- console.log("Cancelling crossfade");
-
- try {
- const now = this.audioContext.currentTime;
-
- // Remove the ended event listener if it hasn't fired yet
- if (this.currentEndedHandler && this.currentSource) {
- this.currentSource.element.removeEventListener(
- "ended",
- this.currentEndedHandler,
- );
- this.currentEndedHandler = null;
- }
-
- // Stop any scheduled gain changes
- if (this.currentSource) {
- this.currentSource.gainNode.gain.cancelScheduledValues(now);
- this.currentSource.gainNode.gain.setValueAtTime(1, now);
- }
-
- if (this.nextSource) {
- this.nextSource.gainNode.gain.cancelScheduledValues(now);
- this.nextSource.gainNode.gain.setValueAtTime(0, now);
- this.nextSource.element.pause();
- this.nextSource.element.currentTime = 0;
- }
-
- // Reset active element to current source
- if (this.currentSource) {
- this.activeElement = this.currentSource.element;
- }
-
- this.crossfadeInProgress = false;
- this.crossfadePromise = null;
- this.clearCrossfadeTimeout();
- } catch (error) {
- console.error("Error cancelling crossfade:", error);
- }
- }
-
- /**
- * Clear crossfade timeout
- */
- private clearCrossfadeTimeout() {
- if (this.crossfadeTimeout) {
- clearTimeout(this.crossfadeTimeout);
- this.crossfadeTimeout = null;
- }
- }
-
- /**
- * Set master volume
- */
- setMasterVolume(volume: number) {
- const clampedVolume = Math.max(0, Math.min(1, volume));
- const now = this.audioContext.currentTime;
-
- this.masterGain.gain.cancelScheduledValues(now);
- this.masterGain.gain.setValueAtTime(this.masterGain.gain.value, now);
- this.masterGain.gain.linearRampToValueAtTime(clampedVolume, now + 0.1);
- }
-
- /**
- * Get the active audio element (for UI synchronization)
- */
- getActiveElement(): HTMLAudioElement | null {
- return this.activeElement;
- }
-
- /**
- * Check if crossfade is active
- */
- isCrossfading(): boolean {
- return this.crossfadeInProgress;
- }
-
- /**
- * Get master gain node for analyzer connections
- */
- getMasterGainNode(): GainNode {
- return this.masterGain;
- }
-
- /**
- * Get analyzer node for visualizations
- */
- getAnalyzerNode(): AnalyserNode {
- return this.analyzerNode;
- }
-
- /**
- * Seek the active audio element
- */
- seekTo(time: number) {
- if (this.activeElement) {
- this.activeElement.currentTime = time;
- }
- }
-
- /**
- * Get current time from active element
- */
- getCurrentTime(): number {
- return this.activeElement?.currentTime || 0;
- }
-
- /**
- * Get duration from active element
- */
- getDuration(): number {
- return this.activeElement?.duration || 0;
- }
-
- /**
- * Check if active element is playing
- */
- isPlaying(): boolean {
- return this.activeElement ? !this.activeElement.paused : false;
- }
-
- /**
- * Play the active element
- */
- async play(): Promise {
- if (this.activeElement) {
- await this.activeElement.play();
- }
- }
-
- /**
- * Pause the active element
- */
- pause() {
- if (this.activeElement) {
- this.activeElement.pause();
- }
- }
-
- /**
- * Update pitch for all audio sources
- */
- setPitch(pitch: number) {
- this.currentPitch = getValidPitch(pitch);
- }
-
- /**
- * Get current pitch setting
- */
- getPitch(): number {
- return this.currentPitch;
- }
-
- /**
- * Clean up resources
- */
- destroy() {
- console.log("Destroying crossfade manager");
-
- this.cancelCrossfade();
-
- try {
- // Disconnect all nodes
- if (this.currentSource) {
- this.currentSource.source.disconnect();
- this.currentSource.gainNode.disconnect();
- }
-
- if (this.nextSource) {
- this.nextSource.source.disconnect();
- this.nextSource.gainNode.disconnect();
- }
-
- this.analyzerNode.disconnect();
- this.masterGain.disconnect();
- } catch (error) {
- console.error("Error during cleanup:", error);
- }
-
- this.currentSource = null;
- this.nextSource = null;
- this.activeElement = null;
- }
-}
diff --git a/Build/src/helpers/crossfadeUtils.ts b/Build/src/helpers/crossfadeUtils.ts
deleted file mode 100644
index 7b70588..0000000
--- a/Build/src/helpers/crossfadeUtils.ts
+++ /dev/null
@@ -1,542 +0,0 @@
-import { MutableRefObject } from "react";
-import { CrossfadeManager, AudioSource } from "./crossfadeHelper";
-import { calculateGaplessOffsets } from "./gaplessHelper";
-import { getValidPlaybackRate } from "./musicPlayerUtils";
-
-export const createCrossfadeManager = (
- audioRef: MutableRefObject,
- nextAudioRef: MutableRefObject,
- crossfadeManagerRef: MutableRefObject,
- currentAudioSourceRef: MutableRefObject,
- nextAudioSourceRef: MutableRefObject,
- gaplessAdvanceTriggeredRef?: MutableRefObject,
- gaplessStartAppliedRef?: MutableRefObject,
-) => {
- const setupCrossfadeManager = (audioContext: AudioContext) => {
- try {
- if (!crossfadeManagerRef.current) {
- console.log("CrossfadeUtils: Creating new crossfade manager");
- crossfadeManagerRef.current = new CrossfadeManager(audioContext);
- }
-
- // Setup current audio source
- if (!currentAudioSourceRef.current && audioRef.current) {
- console.log("CrossfadeUtils: Setting up current audio source");
- currentAudioSourceRef.current =
- crossfadeManagerRef.current.createAudioSource(audioRef.current);
- crossfadeManagerRef.current.setCurrentSource(
- currentAudioSourceRef.current,
- );
- }
-
- return crossfadeManagerRef.current;
- } catch (error) {
- console.error(
- "CrossfadeUtils: Failed to setup crossfade manager:",
- error,
- );
- return null;
- }
- };
-
- const getNextSongForCrossfade = (
- getAndCacheNextSong: () => Song | null,
- ): Song | null => {
- try {
- return getAndCacheNextSong();
- } catch (error) {
- console.error(
- "CrossfadeUtils: Failed to get next song for crossfade:",
- error,
- );
- return null;
- }
- };
-
- const prepareNextSongForCrossfade = async (
- nextSong: Song,
- cacheSong: (song: Song) => Promise,
- getCachedSong: (songId: string) => any,
- settingsRef: MutableRefObject,
- ): Promise => {
- if (!nextAudioRef.current || !crossfadeManagerRef.current) {
- throw new Error(
- "CrossfadeUtils: Missing audio elements for crossfade preparation",
- );
- }
-
- console.log(
- "CrossfadeUtils: Preparing next song for crossfade:",
- nextSong.title,
- );
-
- try {
- // Cache the song first
- console.log("CrossfadeUtils: Caching next song");
- await cacheSong(nextSong);
- const cachedSong = getCachedSong(nextSong.id);
-
- if (!cachedSong) {
- throw new Error(`Failed to cache next song: ${nextSong.title}`);
- }
-
- // Set up the next audio element
- nextAudioRef.current.pause();
- nextAudioRef.current.currentTime = 0;
- nextAudioRef.current.src = cachedSong.url;
- // Apply combined tempo and pitch rate, clamped to browser limits
- nextAudioRef.current.playbackRate = getValidPlaybackRate(
- settingsRef.current.tempo,
- settingsRef.current.pitch,
- );
-
- console.log("CrossfadeUtils: Waiting for next audio to be ready");
-
- // Wait for the audio to be ready with timeout
- await new Promise((resolve, reject) => {
- const timeout = setTimeout(() => {
- cleanup();
- reject(new Error("Timeout waiting for audio to load"));
- }, 10000);
-
- const cleanup = () => {
- clearTimeout(timeout);
- nextAudioRef.current?.removeEventListener("canplay", onCanPlay);
- nextAudioRef.current?.removeEventListener("loadeddata", onCanPlay);
- nextAudioRef.current?.removeEventListener("error", onError);
- };
-
- const onCanPlay = () => {
- console.log("CrossfadeUtils: Next audio is ready");
- cleanup();
- resolve();
- };
-
- const onError = (e: Event) => {
- console.error("CrossfadeUtils: Error loading next audio:", e);
- cleanup();
- reject(new Error("Failed to load next audio"));
- };
-
- // Check if already ready
- if (nextAudioRef.current!.readyState >= 2) {
- cleanup();
- resolve();
- return;
- }
-
- nextAudioRef.current!.addEventListener("canplay", onCanPlay);
- nextAudioRef.current!.addEventListener("loadeddata", onCanPlay);
- nextAudioRef.current!.addEventListener("error", onError);
-
- // Trigger loading
- nextAudioRef.current!.load();
- });
-
- const offsets = calculateGaplessOffsets(nextSong);
- if (offsets.start > 0 && offsets.start < nextAudioRef.current.duration) {
- try {
- nextAudioRef.current.currentTime = offsets.start;
- } catch (error) {
- console.warn(
- "CrossfadeUtils: Failed to apply gapless start offset to next track:",
- error,
- );
- }
- }
-
- // Create and prepare audio source for crossfade manager
- if (
- !nextAudioSourceRef.current ||
- nextAudioSourceRef.current.element !== nextAudioRef.current
- ) {
- nextAudioSourceRef.current =
- crossfadeManagerRef.current.createAudioSource(nextAudioRef.current);
- }
-
- crossfadeManagerRef.current.prepareNextSource(nextAudioSourceRef.current);
- console.log(
- "CrossfadeUtils: Next song prepared successfully for crossfade",
- );
- } catch (error) {
- console.error(
- "CrossfadeUtils: Failed to prepare next song for crossfade:",
- error,
- );
- throw error;
- }
- };
-
- const updatePlayerStateAfterCrossfade = (
- nextSong: Song,
- playerStateRef: MutableRefObject,
- playHistoryRef: MutableRefObject<
- Map
- >,
- updatePlayHistory: (
- playHistoryRef: MutableRefObject<
- Map
- >,
- songId: string,
- ) => void,
- setPlayerState: (updater: (prev: any) => any) => void,
- audioRef: MutableRefObject,
- nextAudioRef: MutableRefObject,
- currentAudioSourceRef: MutableRefObject,
- nextAudioSourceRef: MutableRefObject,
- invalidateNextSongCache?: () => void,
- ) => {
- console.log(
- "CrossfadeUtils: Updating player state after crossfade to:",
- nextSong.title,
- );
-
- try {
- // Update play history ONLY if we're in shuffle mode and have a current song
- if (
- playerStateRef.current.currentSong &&
- playerStateRef.current.shuffle
- ) {
- updatePlayHistory(
- playHistoryRef,
- playerStateRef.current.currentSong.id,
- );
- console.log("CrossfadeUtils: Updated play history for shuffle mode");
- }
-
- // Swap audio elements - next becomes current
- const tempAudio = audioRef.current;
- audioRef.current = nextAudioRef.current;
- nextAudioRef.current = tempAudio;
-
- // Swap audio sources
- const tempSource = currentAudioSourceRef.current;
- currentAudioSourceRef.current = nextAudioSourceRef.current;
- nextAudioSourceRef.current = tempSource;
-
- // Clean up the old audio element (now in nextAudioRef) to prevent memory leaks
- // Revoke blob URL if present, then clear source
- if (nextAudioRef.current) {
- const oldSrc = nextAudioRef.current.src;
- if (oldSrc && oldSrc.startsWith("blob:")) {
- try {
- URL.revokeObjectURL(oldSrc);
- console.log("CrossfadeUtils: Revoked blob URL from previous song");
- } catch (e) {
- // Ignore errors from revoking already-revoked URLs
- }
- }
- // Pause and reset the old element for reuse
- nextAudioRef.current.pause();
- nextAudioRef.current.currentTime = 0;
- // Don't clear src yet: the cacheManager may still reference it
- }
-
- // Get current time from the crossfade manager (which tracks the active element)
- const currentTime = crossfadeManagerRef.current?.getCurrentTime() || 0;
-
- // Update player state
- setPlayerState((prev: any) => {
- console.log(
- "CrossfadeUtils: Finalizing player state after crossfade:",
- nextSong.title,
- "currentTime:",
- currentTime,
- );
- return {
- ...prev,
- currentTime: currentTime,
- // currentSong and duration already set at crossfade start
- };
- });
-
- // Invalidate next song cache since we changed songs
- if (invalidateNextSongCache) {
- invalidateNextSongCache();
- console.log(
- "CrossfadeUtils: Invalidated next song cache after crossfade",
- );
- }
-
- console.log("CrossfadeUtils: Player state updated successfully");
- } catch (error) {
- console.error(
- "CrossfadeUtils: Error updating player state after crossfade:",
- error,
- );
- }
- };
-
- const preloadNextSong = async (
- getNextSongForCrossfadeFunc: () => Song | null,
- cacheSong: (song: Song) => Promise,
- getCachedSong: (songId: string) => any,
- settingsRef: MutableRefObject,
- ) => {
- if (!nextAudioRef.current || crossfadeManagerRef.current?.isCrossfading()) {
- console.log(
- "CrossfadeUtils: Skipping preload - no audio element or crossfade in progress",
- );
- return;
- }
-
- try {
- const nextSong = getNextSongForCrossfadeFunc();
- if (!nextSong) {
- console.log("CrossfadeUtils: No next song to preload");
- return;
- }
-
- console.log("CrossfadeUtils: Preloading next song:", nextSong.title);
-
- // Cache the next song
- await cacheSong(nextSong);
- const cachedSong = getCachedSong(nextSong.id);
-
- if (cachedSong) {
- // Pre-set the source but don't play yet
- nextAudioRef.current.src = cachedSong.url;
- // Apply combined tempo and pitch rate, clamped to browser limits
- nextAudioRef.current.playbackRate = getValidPlaybackRate(
- settingsRef.current.tempo,
- settingsRef.current.pitch,
- );
-
- // Preload the audio data
- nextAudioRef.current.preload = "auto";
- nextAudioRef.current.load();
-
- console.log("CrossfadeUtils: Successfully preloaded next song");
- }
- } catch (error) {
- console.warn("CrossfadeUtils: Failed to preload next song:", error);
- }
- };
-
- const startCrossfadeTransition = async (
- playNextRef: MutableRefObject<(() => void) | null>,
- getNextSongForCrossfadeFunc: () => Song | null,
- prepareNextSongForCrossfadeFunc: (nextSong: Song) => Promise,
- playerStateRef: MutableRefObject,
- playHistoryRef: MutableRefObject<
- Map
- >,
- updatePlayHistory: (
- playHistoryRef: MutableRefObject<
- Map
- >,
- songId: string,
- ) => void,
- setPlayerState: (updater: (prev: any) => any) => void,
- settingsRef: MutableRefObject,
- audioContextRef?: MutableRefObject,
- invalidateNextSongCache?: () => void,
- gaplessAdvanceTriggeredRefParam?: MutableRefObject,
- gaplessStartAppliedRefParam?: MutableRefObject,
- ) => {
- console.log("CrossfadeUtils: Starting crossfade transition...");
-
- if (!playNextRef.current) {
- console.warn("CrossfadeUtils: No playNext function available");
- throw new Error("No playNext function available for crossfade");
- }
-
- // Initialize crossfade manager if needed
- if (!crossfadeManagerRef.current) {
- if (audioContextRef?.current) {
- console.log("CrossfadeUtils: Initializing crossfade manager");
- const manager = setupCrossfadeManager(audioContextRef.current);
- if (!manager) {
- throw new Error("Failed to initialize crossfade manager");
- }
- } else {
- throw new Error("No audio context available for crossfade");
- }
- }
-
- if (!audioRef.current) {
- throw new Error("No current audio element available");
- }
-
- if (!nextAudioRef.current) {
- throw new Error("No next audio element available");
- }
-
- // Ensure current source is properly set up
- if (
- !currentAudioSourceRef.current ||
- currentAudioSourceRef.current.element !== audioRef.current
- ) {
- console.log("CrossfadeUtils: Setting up current audio source");
- currentAudioSourceRef.current =
- crossfadeManagerRef.current!.createAudioSource(audioRef.current);
- crossfadeManagerRef.current!.setCurrentSource(
- currentAudioSourceRef.current,
- );
- }
-
- // Cancel any existing crossfade
- if (
- crossfadeManagerRef.current &&
- crossfadeManagerRef.current.isCrossfading()
- ) {
- console.log("CrossfadeUtils: Cancelling existing crossfade");
- crossfadeManagerRef.current.cancelCrossfade();
- }
-
- try {
- // Get the next song
- const nextSong = getNextSongForCrossfadeFunc();
- if (!nextSong) {
- throw new Error("No next song available for crossfade");
- }
-
- console.log(
- "CrossfadeUtils: Preparing next song for crossfade:",
- nextSong.title,
- );
-
- // Prepare the next audio source
- await prepareNextSongForCrossfadeFunc(nextSong);
-
- const offsets = calculateGaplessOffsets(nextSong);
- const rawDuration =
- nextAudioRef.current && Number.isFinite(nextAudioRef.current.duration)
- ? nextAudioRef.current.duration
- : nextSong.duration || 0;
- const trimmedDuration = rawDuration - offsets.start - offsets.end;
- const effectiveDuration =
- Number.isFinite(trimmedDuration) && trimmedDuration > 0.1
- ? trimmedDuration
- : rawDuration;
-
- if (gaplessAdvanceTriggeredRefParam) {
- gaplessAdvanceTriggeredRefParam.current = false;
- } else if (gaplessAdvanceTriggeredRef) {
- gaplessAdvanceTriggeredRef.current = false;
- }
-
- if (gaplessStartAppliedRefParam) {
- gaplessStartAppliedRefParam.current = offsets.start > 0;
- } else if (gaplessStartAppliedRef) {
- gaplessStartAppliedRef.current = offsets.start > 0;
- }
-
- // Ensure audio context is running
- if (audioContextRef?.current?.state === "suspended") {
- console.log("CrossfadeUtils: Resuming audio context");
- await audioContextRef.current.resume();
- }
-
- const crossfadeDuration = Math.max(
- 0.5,
- Math.min(10, settingsRef.current.crossfade || 3),
- );
-
- // If there's less time remaining than the crossfade duration, shorten the crossfade
- const timeRemaining = audioRef.current
- ? audioRef.current.duration - audioRef.current.currentTime
- : crossfadeDuration;
- const effectiveCrossfadeDuration = Math.min(
- crossfadeDuration,
- Math.max(0.5, timeRemaining),
- );
-
- console.log(
- "CrossfadeUtils: Starting crossfade with effective duration:",
- effectiveCrossfadeDuration,
- "(requested:",
- crossfadeDuration,
- "time remaining:",
- timeRemaining.toFixed(1) + ")",
- );
-
- // Update player state immediately when crossfade starts
- console.log("CrossfadeUtils: Updating player state at crossfade start");
- setPlayerState((prev: any) => ({
- ...prev,
- currentSong: nextSong,
- currentTime: 0, // Start from beginning for the new song
- duration:
- effectiveDuration && effectiveDuration > 0
- ? effectiveDuration
- : nextSong.duration || 0,
- isPlaying: true,
- }));
-
- // Start the crossfade
- await crossfadeManagerRef.current!.startCrossfade({
- duration: effectiveCrossfadeDuration,
- curve: "smooth",
- });
-
- console.log(
- "CrossfadeUtils: Crossfade completed, finalizing player state",
- );
-
- // Finalize player state after crossfade completes (swap audio elements)
- updatePlayerStateAfterCrossfade(
- nextSong,
- playerStateRef,
- playHistoryRef,
- updatePlayHistory,
- setPlayerState,
- audioRef,
- nextAudioRef,
- currentAudioSourceRef,
- nextAudioSourceRef,
- invalidateNextSongCache,
- );
-
- console.log(
- "CrossfadeUtils: Crossfade transition completed successfully",
- );
- } catch (error) {
- console.error("CrossfadeUtils: Crossfade transition failed:", error);
-
- // Revert UI state back to current song since crossfade failed
- console.log("CrossfadeUtils: Reverting UI state after failed crossfade");
- setPlayerState((prev: any) => ({
- ...prev,
- currentSong: playerStateRef.current.currentSong, // Revert to the song that was actually playing
- currentTime: audioRef.current?.currentTime || prev.currentTime,
- duration: playerStateRef.current.currentSong?.duration || prev.duration,
- }));
-
- // Cleanup failed crossfade
- if (crossfadeManagerRef.current?.isCrossfading()) {
- crossfadeManagerRef.current.cancelCrossfade();
- }
-
- throw error; // Re-throw to be handled by caller
- }
- };
-
- const cleanupCrossfadeManager = () => {
- console.log("CrossfadeUtils: Cleaning up crossfade manager");
-
- try {
- if (crossfadeManagerRef.current) {
- crossfadeManagerRef.current.destroy();
- crossfadeManagerRef.current = null;
- }
-
- currentAudioSourceRef.current = null;
- nextAudioSourceRef.current = null;
-
- console.log("CrossfadeUtils: Cleanup completed");
- } catch (error) {
- console.error("CrossfadeUtils: Error during cleanup:", error);
- }
- };
-
- return {
- setupCrossfadeManager,
- getNextSongForCrossfade,
- prepareNextSongForCrossfade,
- updatePlayerStateAfterCrossfade,
- preloadNextSong,
- startCrossfadeTransition,
- cleanupCrossfadeManager,
- };
-};
diff --git a/Build/src/helpers/discordService_backup.ts b/Build/src/helpers/discordService_backup.ts
deleted file mode 100644
index 7c0e65e..0000000
--- a/Build/src/helpers/discordService_backup.ts
+++ /dev/null
@@ -1,104 +0,0 @@
-/**
- * Discord Rich Presence Service
- * Handles sending track updates to the Discord backend API
- */
-
-export interface DiscordPresenceData {
- userId: string;
- details: string; // Track name
- state: string; // Artist name
-}
-
-export class DiscordService {
- private static readonly API_BASE_URL =
- "https://htmlplayer-backend.onrender.com";
- private static instance: DiscordService | null = null;
-
- private constructor() {}
-
- public static getInstance(): DiscordService {
- if (!DiscordService.instance) {
- DiscordService.instance = new DiscordService();
- }
- return DiscordService.instance;
- }
-
- /**
- * Send track update to Discord backend
- */
- public async updatePresence(data: DiscordPresenceData): Promise {
- try {
- const response = await fetch(`${DiscordService.API_BASE_URL}/presence`, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify(data),
- });
-
- if (!response.ok) {
- console.error(
- "Failed to update Discord presence:",
- response.status,
- response.statusText,
- );
- return false;
- }
-
- return true;
- } catch (error) {
- console.error("Error updating Discord presence:", error);
- return false;
- }
- }
-
- /**
- * Clear Discord presence (when music stops)
- */
- public async clearPresence(userId: string): Promise {
- try {
- // Send empty details and state to clear presence
- return await this.updatePresence({
- userId,
- details: "",
- state: "",
- });
- } catch (error) {
- console.error("Error clearing Discord presence:", error);
- return false;
- }
- }
-
- /**
- * Parse Discord user ID from OAuth callback URL
- * This would be called when the OAuth callback is handled
- */
- public static parseUserIdFromCallback(url: string): string | null {
- try {
- const urlObj = new URL(url);
- const code = urlObj.searchParams.get("code");
-
- if (!code) {
- return null;
- }
-
- // In a real implementation, you would exchange the code for user info
- // For now, we'll need to handle this differently since the callback goes to the backend
- // The backend should provide the user ID somehow
-
- return null; // This will be handled by the OAuth callback flow
- } catch (error) {
- console.error("Error parsing Discord callback:", error);
- return null;
- }
- }
-
- /**
- * Check if Discord integration is available and user is connected
- */
- public static isDiscordAvailable(userId?: string): boolean {
- return Boolean(userId && userId.length > 0);
- }
-}
-
-export default DiscordService;
diff --git a/Build/src/helpers/filePickerHelper.tsx b/Build/src/helpers/filePickerHelper.tsx
deleted file mode 100644
index 3e872a6..0000000
--- a/Build/src/helpers/filePickerHelper.tsx
+++ /dev/null
@@ -1,1017 +0,0 @@
-import { toast } from "sonner";
-import { parseBlob, selectCover } from "music-metadata";
-import Uppy from "@uppy/core";
-import Dashboard from "@uppy/react/dashboard";
-import "@uppy/core/css/style.min.css";
-import "@uppy/dashboard/css/style.min.css";
-import { useState, useEffect, useRef } from "react";
-import {
- Dialog,
- DialogContent,
- DialogHeader,
- DialogTitle,
-} from "../components/Dialog";
-import ReactDOM from "react-dom/client";
-import { useTranslation } from "react-i18next";
-import i18n from "i18next";
-import { IconRegistryProvider } from "./iconLoader";
-import { importAudioFiles } from "./importAudioFiles";
-
-// Extend Window interface for File Handling API
-declare global {
- interface Window {
- launchQueue?: {
- setConsumer: (
- consumer: (launchParams: {
- files: FileSystemFileHandle[] | File[];
- }) => void,
- ) => void;
- };
- }
-}
-
-export interface AudioFile {
- file: File;
- name: string;
- size: number;
- type: string;
-}
-
-export interface AudioMetadata {
- title: string;
- artist: string;
- album: string;
- duration: number;
- albumArt?: string;
- embeddedLyrics?: EmbeddedLyrics[];
- encoding?: EncodingDetails;
- gapless?: GaplessInfo;
- metadataWarnings?: string[];
-}
-
-export interface EncodingDetails {
- bitrate?: number;
- codec?: string;
- sampleRate?: number;
- channels?: number;
- bitsPerSample?: number;
- container?: string;
- lossless?: boolean;
- profile?: string;
-}
-
-export interface GaplessInfo {
- encoderDelay?: number;
- encoderPadding?: number;
-}
-
-/**
- * Compress album art to reduce memory usage
- * Skips compression for animated images (WebP, GIF) to preserve animation
- */
-async function compressAlbumArt(
- base64: string,
- maxSize = 200,
-): Promise {
- // Check if it's an animated format
- const isAnimatedFormat =
- base64.startsWith("data:image/webp") || base64.startsWith("data:image/gif");
-
- if (isAnimatedFormat) {
- console.log("Skipping compression for animated image");
- return base64; // Return original to preserve animation
- }
-
- return new Promise((resolve, reject) => {
- const img = new Image();
-
- img.onerror = () => reject(new Error("Failed to load image"));
-
- img.onload = () => {
- const canvas = document.createElement("canvas");
- let width = img.width;
- let height = img.height;
-
- // Resize if too large (maintain aspect ratio)
- if (width > maxSize || height > maxSize) {
- if (width > height) {
- height = Math.round((height / width) * maxSize);
- width = maxSize;
- } else {
- width = Math.round((width / height) * maxSize);
- height = maxSize;
- }
- }
-
- canvas.width = width;
- canvas.height = height;
- const ctx = canvas.getContext("2d");
-
- if (!ctx) {
- reject(new Error("Failed to get canvas context"));
- return;
- }
-
- // Draw and compress
- ctx.drawImage(img, 0, 0, width, height);
-
- // Compress to JPEG at 70% quality
- const compressed = canvas.toDataURL("image/jpeg", 0.7);
-
- console.log(
- `Album art compressed: ${(base64.length / 1024).toFixed(1)}KB → ${(compressed.length / 1024).toFixed(1)}KB`,
- );
-
- // Clean up the canvas to free memory
- canvas.width = 0;
- canvas.height = 0;
-
- resolve(compressed);
- };
-
- img.src = base64;
- });
-}
-
-function buildEncodingDetails(format: any): EncodingDetails | undefined {
- if (!format) return undefined;
-
- const details: EncodingDetails = {
- bitrate: typeof format.bitrate === "number" ? format.bitrate : undefined,
- codec: typeof format.codec === "string" ? format.codec : undefined,
- sampleRate:
- typeof format.sampleRate === "number" ? format.sampleRate : undefined,
- channels:
- typeof format.numberOfChannels === "number"
- ? format.numberOfChannels
- : undefined,
- bitsPerSample:
- typeof format.bitsPerSample === "number"
- ? format.bitsPerSample
- : undefined,
- container:
- typeof format.container === "string" ? format.container : undefined,
- lossless:
- typeof format.lossless === "boolean" ? format.lossless : undefined,
- profile:
- typeof format.codecProfile === "string" ? format.codecProfile : undefined,
- };
-
- return Object.values(details).some((value) => value !== undefined)
- ? details
- : undefined;
-}
-
-function normaliseTagValue(value: unknown): string | null {
- if (typeof value === "string") return value;
- if (value instanceof Uint8Array) {
- try {
- return new TextDecoder("utf-8", { fatal: false }).decode(value);
- } catch {
- return null;
- }
- }
- if (Array.isArray(value) && value.length > 0) {
- return normaliseTagValue(value[0]);
- }
- return null;
-}
-
-function parseItunesGapless(value: unknown): GaplessInfo | null {
- const raw = normaliseTagValue(value);
- if (!raw) return null;
- const cleaned = raw.trim();
- if (!cleaned) return null;
-
- const hexMatches = cleaned.match(/[0-9A-Fa-f]{8}/g);
- if (!hexMatches || hexMatches.length < 3) return null;
-
- const delayHex = hexMatches[1];
- const paddingHex = hexMatches[2];
-
- const encoderDelay = Number.parseInt(delayHex, 16);
- const encoderPadding = Number.parseInt(paddingHex, 16);
-
- const result: GaplessInfo = {};
- if (Number.isFinite(encoderDelay) && encoderDelay > 0) {
- result.encoderDelay = encoderDelay;
- }
- if (Number.isFinite(encoderPadding) && encoderPadding > 0) {
- result.encoderPadding = encoderPadding;
- }
-
- return Object.keys(result).length > 0 ? result : null;
-}
-
-function buildGaplessInfo(metadata: any): GaplessInfo | undefined {
- if (!metadata) return undefined;
-
- let gapless: GaplessInfo | undefined;
- const format = metadata.format ?? {};
-
- const encoderDelay =
- typeof format.encoderDelay === "number" ? format.encoderDelay : undefined;
- if (
- typeof encoderDelay === "number" &&
- Number.isFinite(encoderDelay) &&
- encoderDelay > 0
- ) {
- gapless = { ...(gapless ?? {}), encoderDelay };
- }
-
- const encoderPadding =
- typeof format.encoderPadding === "number"
- ? format.encoderPadding
- : undefined;
- if (
- typeof encoderPadding === "number" &&
- Number.isFinite(encoderPadding) &&
- encoderPadding > 0
- ) {
- gapless = { ...(gapless ?? {}), encoderPadding };
- }
-
- for (const tagList of Object.values(metadata?.native ?? {})) {
- if (!Array.isArray(tagList)) continue;
- for (const tag of tagList) {
- const id = typeof tag?.id === "string" ? tag.id.toUpperCase() : "";
- if (!id) continue;
-
- if (id === "ITUNSMPB" || id.endsWith(":ITUNSMPB")) {
- const parsed = parseItunesGapless(tag?.value);
- if (parsed) gapless = { ...(gapless ?? {}), ...parsed };
- continue;
- }
-
- if (
- id === "MP4:----:COM.APPLE.ITUNES:ITUNSMPB" ||
- id === "----:COM.APPLE.ITUNES:ITUNSMPB"
- ) {
- const parsed = parseItunesGapless(tag?.value);
- if (parsed) gapless = { ...(gapless ?? {}), ...parsed };
- }
- }
- }
-
- return gapless;
-}
-
-export interface EmbeddedLyrics {
- synced: boolean;
- language?: string;
- description?: string;
- text?: string; // for unsynchronized lyrics
- lines?: Array<{
- // for synchronized lyrics
- text: string;
- timestamp: number;
- }>;
-}
-
-// Track processing state for beforeunload prompt
-let isProcessing = false;
-
-const handleBeforeUnload = (event: BeforeUnloadEvent) => {
- if (isProcessing) {
- event.preventDefault();
- event.returnValue = "";
- }
-};
-
-// Function to set processing state and manage beforeunload listener
-export function setProcessingState(processing: boolean) {
- isProcessing = processing;
- if (processing) {
- window.addEventListener("beforeunload", handleBeforeUnload);
- } else {
- window.removeEventListener("beforeunload", handleBeforeUnload);
- }
-}
-
-// Utility for promise with timeout and retries
-async function withTimeoutAndRetry(
- promise: Promise,
- timeoutMs: number,
- retries: number,
- errorMessage: string,
-): Promise {
- let lastError: Error | null = null;
- for (let attempt = 1; attempt <= retries; attempt++) {
- try {
- const timeoutPromise = new Promise((_, reject) => {
- setTimeout(
- () => reject(new Error(`Timeout: ${errorMessage}`)),
- timeoutMs,
- );
- });
- return await Promise.race([promise, timeoutPromise]);
- } catch (e) {
- lastError = e instanceof Error ? e : new Error(String(e));
- console.warn(`Attempt ${attempt} failed: ${lastError.message}`);
- if (attempt === retries) throw lastError;
- }
- }
- throw lastError || new Error("Unknown error after retries");
-}
-
-// ---------------------
-// pickAudioFiles (React Uppy version)
-// ---------------------
-export function pickAudioFiles(): Promise {
- return new Promise((resolve) => {
- const ReactUppyWrapper = () => {
- const { t } = useTranslation();
- const [uppy] = useState(
- () =>
- new Uppy({
- autoProceed: false,
- restrictions: {
- maxNumberOfFiles: null,
- allowedFileTypes: [
- ".mp3",
- ".wav",
- ".m4a",
- ".flac",
- ".aif",
- ".aiff",
- ".ogg",
- ".flo",
- "audio/*",
- ],
- },
- }),
- );
-
- const [open, setOpen] = useState(true); // modal open state
- const [theme, setTheme] = useState<"light" | "dark">(
- document.documentElement.classList.contains("dark") ? "dark" : "light",
- );
-
- // Watch for theme changes
- useEffect(() => {
- const observer = new MutationObserver(() => {
- const mode = document.documentElement.classList.contains("dark")
- ? "dark"
- : "light";
- setTheme(mode);
- });
- observer.observe(document.documentElement, {
- attributes: true,
- attributeFilter: ["class"],
- });
-
- return () => observer.disconnect();
- }, []);
-
- useEffect(() => {
- const audioFiles: AudioFile[] = [];
-
- const onFileAdded = (file: any) => {
- const processed = processFiles([file.data as File]);
- if (processed.length === 0) {
- uppy.removeFile(file.id);
- } else {
- audioFiles.push(...processed);
- }
- };
-
- const onComplete = () => {
- // resolve the outer promise
- resolve(audioFiles);
- setOpen(false);
- };
-
- uppy.on("file-added", onFileAdded);
- uppy.on("complete", onComplete);
-
- return () => {
- uppy.off("file-added", onFileAdded);
- uppy.off("complete", onComplete);
- uppy.cancelAll();
- };
- }, [uppy]);
-
- return (
-
- {
- setOpen(newOpen);
- if (!newOpen) {
- uppy.cancelAll();
- resolve([]); // resolves with [] if nothing selected
- }
- }}
- >
-
-
- {t("filePicker.selectAudioFiles")}
-
-
- {/* Force remount on theme change */}
-
-
-
-
-
-
- );
- };
-
- // Create a container div
- const container = document.createElement("div");
- document.body.appendChild(container);
- const root = ReactDOM.createRoot(container);
- root.render( );
- });
-}
-
-// ---------------------
-// Helper to filter valid audio files
-// ---------------------
-function processFiles(files: File[]): AudioFile[] {
- const valid: AudioFile[] = [];
- const audioTest = document.createElement("audio");
- const allowedExtensions = [
- "mp3",
- "wav",
- "m4a",
- "flac",
- "aif",
- "aiff",
- "ogg",
- "flo",
- ];
-
- for (const file of files) {
- const ext = file.name.split(".").pop()?.toLowerCase();
- if (
- !file.type.startsWith("audio/") &&
- !(ext && allowedExtensions.includes(ext))
- ) {
- // TODO: i18n-ize
- toast.error(`Skipping non-audio file: ${file.name}`);
- continue;
- }
- // For .flo files, skip browser canPlayType check (handled by custom decoder)
- if (ext !== "flo") {
- const canPlay = audioTest.canPlayType(file.type);
- if (canPlay !== "probably" && canPlay !== "maybe") {
- // TODO: i18n-ize
- toast.error(
- `Skipping unsupported audio format by browser: ${file.name} (${file.type})`,
- );
- continue;
- }
- }
- valid.push({ file, name: file.name, size: file.size, type: file.type });
- }
- return valid;
-}
-
-// ---------------------
-// Existing metadata extraction
-// ---------------------
-export async function extractAudioMetadata(file: File): Promise {
- setProcessingState(true);
-
- const ext = file.name.split(".").pop()?.toLowerCase();
-
- // Use flo-specific extraction for .flo files
- if (ext === "flo") {
- try {
- const arrayBuffer = await file.arrayBuffer();
- const { getFloMetadata, getFloCoverArt, getFloSyncedLyrics, getFloInfo } =
- await import("./floProcessor");
-
- // Get all flo data in parallel
- const [meta, cover, lyrics, info] = await Promise.all([
- getFloMetadata(arrayBuffer),
- getFloCoverArt(arrayBuffer),
- getFloSyncedLyrics(arrayBuffer),
- getFloInfo(arrayBuffer),
- ]);
-
- // Process album art if available
- let albumArt: string | undefined = undefined;
- if (cover && cover.data && cover.data.length > 0) {
- const blob = new Blob([cover.data], { type: cover.mime_type });
- albumArt = await new Promise((resolve, reject) => {
- const reader = new FileReader();
- reader.onloadend = () => resolve(reader.result as string);
- reader.onerror = () => reject(new Error("Failed to read album art"));
- reader.readAsDataURL(blob);
- });
- }
-
- // Convert synced lyrics to EmbeddedLyrics format
- let embeddedLyrics: EmbeddedLyrics[] | undefined = undefined;
- if (Array.isArray(lyrics) && lyrics.length > 0) {
- embeddedLyrics = [
- {
- synced: true,
- lines: lyrics.map((l) => ({
- text: l.text,
- timestamp: l.timestamp_ms / 1000, // Convert ms to seconds
- })),
- },
- ];
- }
-
- // Build encoding details from info
- const encoding: EncodingDetails = {
- bitrate: undefined, // flo doesn't provide bitrate directly
- codec: "flo",
- sampleRate: info?.sample_rate,
- channels: info?.channels,
- bitsPerSample: info?.bit_depth,
- container: "flo",
- lossless: !info?.is_lossy,
- profile: info?.is_lossy ? "lossy" : "lossless",
- };
-
- return {
- title: meta?.title || file.name.replace(/\.[^/.]+$/, ""),
- artist: meta?.artist || i18n.t("common.unknownArtist"),
- album: meta?.album || i18n.t("common.unknownAlbum"),
- duration: info?.duration_secs || 0,
- albumArt,
- embeddedLyrics,
- encoding,
- gapless: undefined, // flo doesn't expose gapless info currently
- metadataWarnings: undefined,
- };
- } catch (error) {
- console.error("Failed to extract flo metadata:", error);
- // Fallback to basic file info
- return {
- title: file.name.replace(/\.[^/.]+$/, ""),
- artist: i18n.t("common.unknownArtist"),
- album: i18n.t("common.unknownAlbum"),
- duration: 0,
- albumArt: undefined,
- embeddedLyrics: undefined,
- encoding: {
- codec: "flo",
- container: "flo",
- },
- gapless: undefined,
- };
- } finally {
- setProcessingState(false);
- }
- }
- // Fallback to original (music-metadata) for all other formats
- let MetadataWorkerType: typeof Worker;
- if (typeof __IS_SINGLE_FILE__ !== "undefined" && __IS_SINGLE_FILE__) {
- MetadataWorkerType = (
- await import("../workers/metadataWorker.ts?worker&inline")
- ).default;
- } else {
- MetadataWorkerType = (await import("../workers/metadataWorker.ts?worker"))
- .default;
- }
- const worker = new MetadataWorkerType();
-
- try {
- const result = await withTimeoutAndRetry(
- new Promise((resolve, reject) => {
- worker.onmessage = (event) => {
- const { metadata, albumArt, warnings, error } = event.data;
- if (error) reject(new Error(error));
- else {
- // Translate placeholder values from worker
- const translatedMetadata = {
- ...metadata,
- artist:
- metadata.artist === "__UNKNOWN_ARTIST__"
- ? i18n.t("common.unknownArtist")
- : metadata.artist,
- album:
- metadata.album === "__UNKNOWN_ALBUM__"
- ? i18n.t("common.unknownAlbum")
- : metadata.album,
- albumArt,
- metadataWarnings: Array.isArray(warnings) ? warnings : undefined,
- };
- if (Array.isArray(warnings) && warnings.length > 0) {
- for (const warning of warnings) {
- // Suppress repetitive ID3v2.3 warnings that spam the console
- if (
- warning.includes("Invalid ID3v2.3 frame-header-ID") ||
- warning.includes("id3v2.3 header has empty tag type")
- ) {
- continue;
- }
- console.warn(`Metadata warning for ${file.name}:`, warning);
- }
- }
- resolve(translatedMetadata);
- }
- };
- worker.onerror = (error) =>
- reject(new Error("Worker error: " + error.message));
- worker.postMessage({ file, fileName: file.name });
- }),
- 15000,
- 3,
- `Metadata extraction for ${file.name}`,
- );
- return result;
- } catch (e) {
- console.warn(`Failed to read metadata for ${file.name}:`, e);
- const fileName = file.name.replace(/\.[^/.]+$/, "");
- let title = fileName,
- artist = i18n.t("common.unknownArtist"),
- album = i18n.t("common.unknownAlbum"),
- duration = 0,
- albumArt: string | undefined,
- encoding: EncodingDetails | undefined,
- gapless: GaplessInfo | undefined;
-
- try {
- const metadata = await withTimeoutAndRetry(
- parseBlob(file, { skipCovers: false, duration: true }),
- 15000,
- 3,
- `Fallback metadata parsing for ${file.name}`,
- );
-
- if (metadata.common) {
- if (typeof metadata.common.artist === "string")
- artist = metadata.common.artist;
- if (typeof metadata.common.title === "string")
- title = metadata.common.title;
- if (typeof metadata.common.album === "string")
- album = metadata.common.album;
- duration = metadata.format.duration ?? 0;
- encoding = buildEncodingDetails(metadata.format);
- gapless = buildGaplessInfo(metadata);
-
- // Find this section in extractAudioMetadata (around line 420)
- const cover = selectCover(metadata.common.picture);
- if (cover && cover.data.length > 0) {
- const blob = new Blob([new Uint8Array(cover.data)], {
- type: cover.format,
- });
- albumArt = await new Promise((resolve, reject) => {
- const reader = new FileReader();
- reader.onloadend = async () => {
- try {
- const base64 = reader.result as string;
- // Compress album art to save memory
- const compressed = await compressAlbumArt(base64);
- resolve(compressed);
- } catch (error) {
- console.warn("Failed to compress album art:", error);
- // Fallback to original if compression fails
- resolve(reader.result as string);
- }
- };
- reader.onerror = () =>
- reject(new Error("Failed to read album art"));
- reader.readAsDataURL(blob);
- });
- }
- }
- } catch {
- if (fileName.includes(" - ")) {
- const parts = fileName.split(" - ");
- if (parts.length >= 2) {
- artist = parts[0].trim();
- title = parts[1].trim();
- }
- }
- }
-
- return { title, artist, album, duration, albumArt, encoding, gapless };
- } finally {
- worker.terminate();
- setProcessingState(false);
- }
-}
-
-// ---------------------
-// URL + ID helpers
-// ---------------------
-
-export function generateUniqueId(): string {
- return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
-}
-
-// ---------------------
-// File Handling API support for PWAs
-// ---------------------
-export interface FileHandlerResult {
- files: File[];
- successCount: number;
- errorCount: number;
-}
-
-export function setupFileHandler(
- onFilesReceived: (result: FileHandlerResult) => void,
-): () => void {
- if (
- !("launchQueue" in window) ||
- !window.launchQueue ||
- typeof window.launchQueue.setConsumer !== "function"
- ) {
- console.warn("File Handling API not supported in this browser");
- return () => {}; // Return empty cleanup function
- }
-
- const consumer = async (launchParams: any) => {
- if (!launchParams.files || launchParams.files.length === 0) {
- console.log("No files provided by File Handling or Share Target API");
- return;
- }
-
- const files: File[] = [];
- let successCount = 0;
- let errorCount = 0;
-
- for (const fileHandle of launchParams.files) {
- try {
- let file: File;
- if (fileHandle.getFile) {
- file = await fileHandle.getFile();
- } else {
- file = fileHandle;
- }
-
- const fileId = `${file.name}-${file.size}-${file.lastModified}`;
-
- // Check sessionStorage for processed files
- const processedFiles = JSON.parse(
- sessionStorage.getItem("processedFiles") || "[]",
- );
- if (processedFiles.includes(fileId)) {
- console.log("Skipping duplicate file:", file.name);
- continue;
- }
-
- const processed = processFiles([file]);
- if (processed.length > 0) {
- files.push(file);
- processedFiles.push(fileId);
- sessionStorage.setItem(
- "processedFiles",
- JSON.stringify(processedFiles),
- );
- successCount++;
- } else {
- errorCount++;
- }
- } catch (error) {
- console.error("Error processing file handle:", error);
- errorCount++;
- }
- }
-
- if (files.length > 0) {
- onFilesReceived({ files, successCount, errorCount });
- }
- };
-
- window.launchQueue.setConsumer(consumer);
-
- return () => {
- if (
- "launchQueue" in window &&
- window.launchQueue &&
- typeof window.launchQueue.setConsumer === "function"
- ) {
- try {
- window.launchQueue.setConsumer(() => {});
- } catch (e) {
- console.warn("Could not clear file handler consumer:", e);
- }
- }
- };
-}
-
-// ---------------------
-// Share Target API support for PWAs
-// ---------------------
-export interface ShareTargetResult {
- files: File[];
- title?: string;
- text?: string;
- url?: string;
- type: "files" | "search" | "none";
-}
-
-const SHARE_HANDLED_KEY = "last-shared-files";
-
-// Helper functions for duplicate tracking
-function getHandledShares(): Set {
- try {
- return new Set(
- JSON.parse(sessionStorage.getItem(SHARE_HANDLED_KEY) || "[]"),
- );
- } catch {
- return new Set();
- }
-}
-
-function markHandled(files: File[]) {
- const handled = getHandledShares();
- files.forEach((f) => handled.add(`${f.name}:${f.size}`));
- sessionStorage.setItem(
- SHARE_HANDLED_KEY,
- JSON.stringify(Array.from(handled)),
- );
-}
-
-export function clearHandledShares() {
- sessionStorage.removeItem(SHARE_HANDLED_KEY);
-}
-
-export function handleShareTarget(): ShareTargetResult | null {
- // Share targets can send data via URL parameters or launch queue
- if (typeof window === "undefined") {
- return null;
- }
-
- // Check URL parameters for share data
- const urlParams = new URLSearchParams(window.location.search);
- const title = urlParams.get("title") || undefined;
- const text = urlParams.get("text") || undefined;
- const url = urlParams.get("url") || undefined;
-
- // Determine what type of share this is
- // Files would typically come through launch queue or POST request
- if (title || text) {
- // Text-based share - could be song info to search for
- return {
- files: [],
- title,
- text,
- url,
- type: "search",
- };
- }
-
- return null;
-}
-
-// Hook to handle share targets and file shares
-export function useShareTarget(
- onShareReceived: (result: ShareTargetResult) => void,
-) {
- const hasProcessedRef = useRef(false);
-
- useEffect(() => {
- if (hasProcessedRef.current) return;
-
- async function processShare() {
- const urlParams = new URLSearchParams(window.location.search);
-
- // Multi-file support: attempt to load from cache with indexes
- if (urlParams.get("share-received") === "true") {
- try {
- const cache = await caches.open("incoming-shares");
- const files: File[] = [];
- // read /shared-file, /shared-file-1, /shared-file-2, etc
- let i = 0,
- foundAny = false;
- while (true) {
- const key = i === 0 ? "/shared-file" : `/shared-file-${i}`;
- const response = await cache.match(key);
- if (!response) break;
- const blob = await response.blob();
- const filenameRaw = response.headers.get("x-file-name");
- const filename = filenameRaw
- ? decodeURIComponent(filenameRaw)
- : `shared-audio${i ? "-" + i : ""}.mp3`;
- files.push(new File([blob], filename, { type: blob.type }));
- await cache.delete(key);
- foundAny = true;
- i++;
- }
-
- if (foundAny) {
- const handled = getHandledShares();
- const newFiles = files.filter(
- (f) => !handled.has(`${f.name}:${f.size}`),
- );
- if (newFiles.length === 0) {
- // all were previously handled
- return;
- }
- markHandled(newFiles);
-
- hasProcessedRef.current = true;
- onShareReceived({ files: newFiles, type: "files" });
-
- // cleanup share-received param
- const cleanUrl = new URL(window.location.href);
- cleanUrl.searchParams.delete("share-received");
- window.history.replaceState({}, "", cleanUrl.toString());
- return;
- }
- } catch (e) {
- console.error("Failed to retrieve shared file from cache", e);
- }
- }
-
- // Fallback to standard Text/URL share handling
- const shareResult = handleShareTarget();
- if (shareResult && shareResult.type !== "none") {
- hasProcessedRef.current = true;
- onShareReceived(shareResult);
-
- const url = new URL(window.location.href);
- ["title", "text", "url"].forEach((p) => url.searchParams.delete(p));
- window.history.replaceState({}, "", url.toString());
- }
- }
-
- processShare();
- }, [onShareReceived]);
-}
-
-export function useFileHandler(
- addSong: (song: Song) => Promise,
- t: any,
- isInitialized?: boolean,
-) {
- const [isSupported, setIsSupported] = useState(false);
- const processedFilesRef = useRef(new Set());
- const hasProcessedFilesRef = useRef(false);
- const pendingFilesRef = useRef([]);
-
- useEffect(() => {
- const supported =
- "launchQueue" in window &&
- typeof window.launchQueue?.setConsumer === "function";
- setIsSupported(supported);
-
- if (!supported) return;
-
- const cleanup = setupFileHandler(async (result) => {
- // Prevent processing if we've already handled files on this page load
- if (hasProcessedFilesRef.current) return;
-
- if (result.files.length > 0) {
- // If library is not initialized yet, queue the files
- if (isInitialized === false) {
- console.log(
- "Library not initialized, queuing files for later processing",
- );
- pendingFilesRef.current.push(...result.files);
- return;
- }
-
- hasProcessedFilesRef.current = true;
- toast.success(
- t("fileHandler.filesReceived", { count: result.successCount }),
- );
- await importAudioFiles(result.files, addSong, t);
- // Clear processed files after successful import to allow re-importing the same files
- processedFilesRef.current.clear();
- }
- if (result.errorCount > 0) {
- toast.error(
- t("fileHandler.filesSkipped", { count: result.errorCount }),
- );
- }
- });
-
- return cleanup;
- }, [addSong, t, isInitialized]);
-
- // Process queued files when library becomes initialized
- useEffect(() => {
- if (isInitialized && pendingFilesRef.current.length > 0) {
- console.log("Library initialized, processing queued files");
- const filesToProcess = [...pendingFilesRef.current];
- pendingFilesRef.current = [];
-
- // Process the queued files
- importAudioFiles(filesToProcess, addSong, t)
- .then(() => {
- hasProcessedFilesRef.current = true;
- processedFilesRef.current.clear();
- toast.success(
- t("fileHandler.filesReceived", { count: filesToProcess.length }),
- );
- })
- .catch((error) => {
- console.error("Failed to process queued files:", error);
- toast.error(
- t("filePicker.failedImport", { count: filesToProcess.length }),
- );
- });
- }
- }, [isInitialized, addSong, t]);
-
- return { isSupported };
-}
diff --git a/Build/src/helpers/floProcessor.ts b/Build/src/helpers/floProcessor.ts
deleted file mode 100644
index 701e728..0000000
--- a/Build/src/helpers/floProcessor.ts
+++ /dev/null
@@ -1,110 +0,0 @@
-// floProcessor.ts - Fixed flo audio processing
-import initFlo, * as flo from "@flo-audio/libflo-audio";
-
-let floInitialized = false;
-
-async function ensureFloInitialized() {
- if (!floInitialized) {
- await initFlo();
- floInitialized = true;
- }
-}
-
-// Decode a .flo file buffer to AudioBuffer using @flo-audio/libflo-audio
-export async function decodeFloToAudioBuffer(
- floData: ArrayBuffer,
- audioContext: AudioContext,
-): Promise {
- await ensureFloInitialized();
-
- const uint8Flo = new Uint8Array(floData);
-
- // Decode flo to interleaved Float32Array samples
- const samples = flo.decode(uint8Flo);
-
- // Get file info for audio properties
- const fileInfo = flo.info(uint8Flo);
- const { channels, sample_rate } = fileInfo;
-
- // Calculate number of frames
- const frameCount = samples.length / channels;
-
- // Create AudioBuffer
- const audioBuffer = audioContext.createBuffer(
- channels,
- frameCount,
- sample_rate,
- );
-
- // Deinterleave samples into separate channels
- for (let ch = 0; ch < channels; ch++) {
- const channelData = audioBuffer.getChannelData(ch);
- for (let i = 0; i < frameCount; i++) {
- channelData[i] = samples[i * channels + ch];
- }
- }
-
- return audioBuffer;
-}
-
-// Get flo file info (returns object with sample_rate, channels, bit_depth, etc.)
-export async function getFloInfo(floData: ArrayBuffer): Promise<{
- sample_rate: number;
- channels: number;
- bit_depth: number;
- duration_secs: number;
- is_lossy: boolean;
- compression_ratio?: number;
-}> {
- await ensureFloInitialized();
- const uint8Flo = new Uint8Array(floData);
- return flo.info(uint8Flo);
-}
-
-// Validate flo file integrity (CRC32)
-export async function validateFlo(floData: ArrayBuffer): Promise {
- await ensureFloInitialized();
- const uint8Flo = new Uint8Array(floData);
- return flo.validate(uint8Flo);
-}
-
-// Extract metadata as JS object (returns null if no metadata)
-export async function getFloMetadata(floData: ArrayBuffer): Promise<{
- title?: string;
- artist?: string;
- album?: string;
- [key: string]: any;
-} | null> {
- await ensureFloInitialized();
- const uint8Flo = new Uint8Array(floData);
- return flo.get_metadata(uint8Flo);
-}
-
-// Extract cover art (returns { mime_type, data } or null)
-export async function getFloCoverArt(
- floData: ArrayBuffer,
-): Promise<{ mime_type: string; data: Uint8Array } | null> {
- await ensureFloInitialized();
- const uint8Flo = new Uint8Array(floData);
- return flo.get_cover_art(uint8Flo);
-}
-
-// Extract synchronized lyrics (returns array of { timestamp_ms, text } or null)
-export async function getFloSyncedLyrics(
- floData: ArrayBuffer,
-): Promise | null> {
- await ensureFloInitialized();
- const uint8Flo = new Uint8Array(floData);
- return flo.get_synced_lyrics(uint8Flo);
-}
-
-// Create flo metadata from JS object (returns Uint8Array)
-export async function createFloMetadataFromObject(
- obj: any,
-): Promise {
- await ensureFloInitialized();
- return flo.create_metadata_from_object(obj);
-}
-
-// Export initialization function
-export { initFlo, ensureFloInitialized };
diff --git a/Build/src/helpers/gaplessHelper.ts b/Build/src/helpers/gaplessHelper.ts
deleted file mode 100644
index 435addf..0000000
--- a/Build/src/helpers/gaplessHelper.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-export interface GaplessOffsets {
- start: number;
- end: number;
-}
-
-export function calculateGaplessOffsets(song?: Song | null): GaplessOffsets {
- if (!song || !song.gapless || !song.encoding?.sampleRate) {
- return { start: 0, end: 0 };
- }
-
- const sampleRate = song.encoding.sampleRate;
- if (
- typeof sampleRate !== "number" ||
- !Number.isFinite(sampleRate) ||
- sampleRate <= 0
- ) {
- return { start: 0, end: 0 };
- }
-
- const delaySamples = song.gapless.encoderDelay ?? 0;
- const paddingSamples = song.gapless.encoderPadding ?? 0;
-
- const startSeconds =
- typeof delaySamples === "number" &&
- Number.isFinite(delaySamples) &&
- delaySamples > 0
- ? delaySamples / sampleRate
- : 0;
- const endSeconds =
- typeof paddingSamples === "number" &&
- Number.isFinite(paddingSamples) &&
- paddingSamples > 0
- ? paddingSamples / sampleRate
- : 0;
-
- return {
- start: Number.isFinite(startSeconds) && startSeconds > 0 ? startSeconds : 0,
- end: Number.isFinite(endSeconds) && endSeconds > 0 ? endSeconds : 0,
- };
-}
diff --git a/Build/src/helpers/iconLoader.tsx b/Build/src/helpers/iconLoader.tsx
deleted file mode 100644
index 42626b4..0000000
--- a/Build/src/helpers/iconLoader.tsx
+++ /dev/null
@@ -1,801 +0,0 @@
-import React, {
- createContext,
- useCallback,
- useContext,
- useEffect,
- useMemo,
- useRef,
- useState,
-} from "react";
-import {
- IconDefinition,
- IconDefinitionMap,
- IconLibraryConfigMap,
- IconLibraryMap,
- IconLookupOptions,
- IconPropTransformer,
- IconSetMetadata,
- IconSetModule,
- ResolvedIcon,
-} from "../types/icons";
-import { loadThemeJsonFromSourcePath } from "./themeMetadata";
-
-interface IconRegistrySet {
- id: string;
- label: string;
- themeName: string;
- metadata: IconSetMetadata & { id: string; label: string; themeName: string };
- icons: IconDefinitionMap;
- path: string;
- libraries?: IconLibraryMap;
- libraryConfig?: IconLibraryConfigMap;
-}
-
-interface IconDefinitionEntry {
- definition: IconDefinition;
- set: IconRegistrySet;
-}
-
-interface IconRegistryValue {
- iconSets: IconRegistrySet[];
- iconSetMap: Map;
- currentSet: IconRegistrySet | null;
- isLoading: boolean;
- iconsReady: boolean;
- error: string | null;
- setIconSet: (idOrName: string) => void;
- getIconDefinition: (
- name: string,
- options?: IconLookupOptions,
- ) => IconDefinition | undefined;
- loadIcon: (
- name: string,
- options?: IconLookupOptions,
- ) => Promise;
-}
-
-interface IconRegistryProviderProps {
- defaultSetId?: string;
- rememberSelection?: boolean;
- onSetChange?: (set: IconRegistrySet) => void;
- children: React.ReactNode;
-}
-
-const iconModuleLoaders = import.meta.glob("../themes/**/*.icons.{ts,tsx}");
-
-const builtinLibraryLoaders: Record<
- string,
- () => Promise>
-> = {
- lucide: async () => import("lucide-react"),
-};
-
-const IconRegistryContext = createContext(null);
-
-const LOCAL_STORAGE_KEY = "selected-icon-set";
-// LRU cache implementation for icons
-class LRUCache {
- private maxSize: number;
- private cache: Map;
-
- constructor(maxSize: number) {
- this.maxSize = maxSize;
- this.cache = new Map();
- }
-
- get(key: K): V | undefined {
- if (!this.cache.has(key)) return undefined;
- const value = this.cache.get(key)!;
- // Move to end (most recently used)
- this.cache.delete(key);
- this.cache.set(key, value);
- return value;
- }
-
- set(key: K, value: V): void {
- if (this.cache.has(key)) {
- this.cache.delete(key);
- }
- this.cache.set(key, value);
- if (this.cache.size > this.maxSize) {
- // Remove least recently used
- const lruKeyIter = this.cache.keys().next();
- if (!lruKeyIter.done) {
- const lruKey = lruKeyIter.value as K;
- this.cache.delete(lruKey);
- }
- }
- }
-
- clear(): void {
- this.cache.clear();
- }
-}
-
-const ICON_CACHE_SIZE = 128; // TODO: Tune
-const resolvedIconCache = new LRUCache(ICON_CACHE_SIZE);
-const libraryModuleCache = new LRUCache>(8); // Limit loaded libraries
-
-function deriveSetIdentity(
- path: string,
- metadata?: IconSetMetadata,
- themeJson?: any,
-): {
- id: string;
- label: string;
- themeName: string;
-} {
- const segments = path.split("/");
- const fileName = segments[segments.length - 1] ?? "";
- const baseName = fileName.replace(/\.icons\.(?:ts|tsx)$/, "");
-
- // Use theme JSON metadata if available
- const iconMeta = themeJson?.icons || {};
- const themeName =
- themeJson?.name ??
- metadata?.theme ??
- segments[segments.length - 2] ??
- baseName;
-
- // Priority: JSON metadata > TS metadata > derived values
- const derivedName =
- iconMeta.label ?? metadata?.label ?? metadata?.id ?? themeName ?? baseName;
- const normalizedId = (
- iconMeta.id ??
- metadata?.id ??
- themeName ??
- derivedName
- ).toLowerCase();
-
- return {
- id: normalizedId,
- label: iconMeta.label ?? metadata?.label ?? derivedName,
- themeName,
- };
-}
-
-const GLOBAL_LIBRARY_NAMESPACE = "__global";
-
-async function resolveLibraryModule(
- library: string,
- sourceSet?: IconRegistrySet,
-): Promise | null> {
- const cacheKey = `${sourceSet ? sourceSet.id : GLOBAL_LIBRARY_NAMESPACE}::${library}`;
- const cachedModule = libraryModuleCache.get(cacheKey);
- if (cachedModule) {
- return cachedModule;
- }
-
- // First check if the library is already available in the sourceSet
- let loaderCandidate = sourceSet?.libraries?.[library];
-
- if (!loaderCandidate) {
- // Check builtin loaders
- loaderCandidate = builtinLibraryLoaders[library];
- }
-
- if (!loaderCandidate) {
- // Try to load the library dynamically if it's a known library
- if (library === "lucide" && sourceSet?.id === "lucide") {
- try {
- const lucideModule = await import("lucide-react");
- libraryModuleCache.set(cacheKey, lucideModule);
- return lucideModule;
- } catch (error) {
- console.error(`Failed to dynamically load lucide-react`, error);
- return null;
- }
- }
- return null;
- }
-
- try {
- let module: Record;
- if (typeof loaderCandidate === "function") {
- const result = loaderCandidate();
- module = (result instanceof Promise ? await result : result) as Record<
- string,
- any
- >;
- } else {
- module = loaderCandidate as Record;
- }
-
- libraryModuleCache.set(cacheKey, module);
- return module;
- } catch (error) {
- console.error(`Failed to load icon library "${library}"`, error);
- return null;
- }
-}
-
-function getExportByPath(
- container: Record | undefined,
- path: string,
-): any {
- if (!container) return undefined;
- const segments = path.split(".");
- let current: any = container;
- for (const segment of segments) {
- if (current && typeof current === "object" && segment in current) {
- current = current[segment];
- } else {
- return undefined;
- }
- }
- return current;
-}
-
-async function loadLibraryIcon(
- library: string,
- iconName: string,
- sourceSet?: IconRegistrySet,
-): Promise> | null> {
- const module = await resolveLibraryModule(library, sourceSet);
-
- if (!module) {
- console.warn(
- `Unsupported icon library "${library}"${sourceSet ? ` for set "${sourceSet.label}"` : ""}`,
- );
- return null;
- }
-
- const candidateNames = new Set([iconName]);
- if (!iconName.includes(".") && !iconName.endsWith("Icon")) {
- candidateNames.add(`${iconName}Icon`);
- }
-
- const pascalCase = iconName.charAt(0).toUpperCase() + iconName.slice(1);
- const camelCase = iconName.charAt(0).toLowerCase() + iconName.slice(1);
- candidateNames.add(pascalCase);
- candidateNames.add(camelCase);
-
- const candidateContainers = [
- module,
- (module as any).default,
- (module as any).icons,
- (module as any).default?.icons,
- ].filter((container) => container && typeof container === "object");
-
- let resolvedExport: any;
- for (const container of candidateContainers) {
- for (const pathCandidate of candidateNames) {
- resolvedExport = getExportByPath(
- container as Record,
- pathCandidate,
- );
- if (resolvedExport) {
- break;
- }
- }
-
- if (resolvedExport) {
- break;
- }
- }
-
- if (
- resolvedExport &&
- typeof resolvedExport === "object" &&
- typeof resolvedExport.default === "function"
- ) {
- resolvedExport = resolvedExport.default;
- }
-
- // Check if it's a valid React component (function or forwardRef/memo)
- if (typeof resolvedExport === "function") {
- return resolvedExport as React.ComponentType>;
- }
-
- // Handle React.forwardRef/React.memo wrapped components
- if (
- resolvedExport &&
- typeof resolvedExport === "object" &&
- (resolvedExport.$$typeof || resolvedExport.render)
- ) {
- return resolvedExport as React.ComponentType>;
- }
-
- console.warn(`Icon "${iconName}" not found in library "${library}"`);
- return null;
-}
-
-export const IconRegistryProvider: React.FC = ({
- defaultSetId,
- rememberSelection = true,
- onSetChange,
- children,
-}) => {
- const [iconSets, setIconSets] = useState([]);
- const [currentSet, setCurrentSet] = useState(null);
- const [error, setError] = useState(null);
- const [isLoading, setIsLoading] = useState(true);
- const [iconsReady, setIconsReady] = useState(false);
-
- useEffect(() => {
- let cancelled = false;
-
- // Only load metadata for all sets, not the full icon maps
- const loadSetMetadatas = async () => {
- try {
- setIsLoading(true);
- setIconsReady(false);
- setError(null);
-
- const entries: IconRegistrySet[] = [];
-
- for (const [path] of Object.entries(iconModuleLoaders)) {
- try {
- // Load theme JSON for metadata without loading the full icon module
- const themeJson = await loadThemeJsonFromSourcePath(path);
- // Skip loading the full module at startup - only load metadata from themeJson
- const identity = deriveSetIdentity(path, undefined, themeJson);
- const iconMeta = themeJson?.icons || {};
- const fullMetadata: IconSetMetadata & {
- id: string;
- label: string;
- themeName: string;
- } = {
- id: identity.id,
- label: identity.label,
- themeName: identity.themeName,
- description: iconMeta.description,
- version: iconMeta.version,
- theme: identity.themeName,
- inheritsFrom: iconMeta.inheritsFrom,
- author: iconMeta.author ?? themeJson?.author,
- tags: iconMeta.tags,
- };
- // Only set icons to empty object until loaded
- const registrySet: IconRegistrySet = {
- id: identity.id,
- label: identity.label,
- themeName: identity.themeName,
- metadata: fullMetadata,
- icons: {},
- path,
- libraries: undefined,
- libraryConfig: undefined,
- };
- entries.push(registrySet);
- } catch (err) {
- console.error(
- `Failed to load icon registry module metadata at ${path}`,
- err,
- );
- }
- }
-
- if (!cancelled) {
- entries.sort((a, b) => a.label.localeCompare(b.label));
- setIconSets(entries);
-
- const storedId = rememberSelection
- ? typeof window !== "undefined"
- ? localStorage.getItem(LOCAL_STORAGE_KEY)
- : null
- : null;
-
- const preferredId = storedId ?? defaultSetId;
-
- const nextSet = preferredId
- ? entries.find(
- (entry) =>
- entry.id === preferredId || entry.themeName === preferredId,
- )
- : null;
-
- const fallbackSet =
- nextSet ??
- entries.find(
- (entry) => entry.metadata?.inheritsFrom === undefined,
- ) ??
- entries[0] ??
- null;
-
- // Only load icons for the current set, not all sets
- if (fallbackSet) {
- // Load icons for fallbackSet only
- const loader = iconModuleLoaders[fallbackSet.path];
- if (loader) {
- loader().then((module: any) => {
- const loadedSet = {
- ...fallbackSet,
- icons: module.default,
- libraries: module.libraries,
- libraryConfig: module.libraryConfig,
- };
- setIconSets((sets) =>
- sets.map((s) => (s.id === loadedSet.id ? loadedSet : s)),
- );
- setCurrentSet(loadedSet);
- setIconsReady(true);
- if (rememberSelection && typeof window !== "undefined") {
- localStorage.setItem(LOCAL_STORAGE_KEY, loadedSet.id);
- }
- });
- } else {
- setCurrentSet(fallbackSet);
- setIconsReady(true);
- if (rememberSelection && typeof window !== "undefined") {
- localStorage.setItem(LOCAL_STORAGE_KEY, fallbackSet.id);
- }
- }
- }
- }
- } catch (err) {
- if (!cancelled) {
- const message =
- err instanceof Error ? err.message : "Unable to load icon registry";
- setError(message);
- console.error("Icon registry loading error:", err);
- }
- } finally {
- if (!cancelled) {
- setIsLoading(false);
- }
- }
- };
-
- loadSetMetadatas();
-
- return () => {
- cancelled = true;
- };
- }, [defaultSetId, rememberSelection]);
-
- const iconSetMap = useMemo(() => {
- const map = new Map();
- for (const set of iconSets) {
- map.set(set.id, set);
- map.set(set.themeName.toLowerCase(), set);
- }
- return map;
- }, [iconSets]);
-
- const notifyChange = useRef(onSetChange);
- notifyChange.current = onSetChange;
-
- const setIconSet = useCallback(
- async (idOrName: string) => {
- const normalized = idOrName.toLowerCase();
- let next =
- iconSetMap.get(normalized) ??
- iconSets.find(
- (set) =>
- set.id === normalized || set.themeName.toLowerCase() === normalized,
- );
- if (!next) {
- console.warn(`Icon set "${idOrName}" not found`);
- return;
- }
-
- setIconsReady(false);
-
- // If icons not loaded, load them now
- if (!next.icons || Object.keys(next.icons).length === 0) {
- try {
- const loader = iconModuleLoaders[next.path];
- if (loader) {
- const module = (await loader()) as IconSetModule;
- next = {
- ...next,
- icons: module.default,
- libraries: module.libraries,
- libraryConfig: module.libraryConfig,
- };
- // Update iconSets and iconSetMap
- if (next) {
- setIconSets((sets) => {
- return sets.map((s) => {
- if (s.id === next!.id) {
- return next!;
- }
- return s;
- });
- });
- }
- }
- } catch (err) {
- console.error(`Failed to load icon set "${next.label}"`, err);
- }
- }
-
- setCurrentSet(next);
- setIconsReady(true);
- if (typeof window !== "undefined" && rememberSelection) {
- localStorage.setItem(LOCAL_STORAGE_KEY, next.id);
- }
-
- notifyChange.current?.(next);
- },
- [iconSetMap, iconSets, rememberSelection],
- );
-
- const resolveIconEntry = useCallback(
- (
- name: string,
- startSet: IconRegistrySet | null,
- visited: Set,
- ): IconDefinitionEntry | undefined => {
- if (!startSet || visited.has(startSet.id)) {
- return undefined;
- }
-
- visited.add(startSet.id);
-
- const definition = startSet.icons[name];
- if (definition) {
- return { definition, set: startSet };
- }
-
- const parentId = startSet.metadata?.inheritsFrom;
- if (parentId) {
- const parent =
- iconSetMap.get(parentId) ?? iconSetMap.get(parentId.toLowerCase());
- if (parent) {
- return resolveIconEntry(name, parent, visited);
- }
- }
-
- return undefined;
- },
- [iconSetMap],
- );
-
- const findIconEntry = useCallback(
- (
- name: string,
- options?: IconLookupOptions,
- ): IconDefinitionEntry | undefined => {
- if (!name) return undefined;
-
- const primary = options?.setId
- ? (iconSetMap.get(options.setId) ??
- iconSetMap.get(options.setId.toLowerCase()) ??
- null)
- : (currentSet ?? iconSets[0] ?? null);
-
- const primaryEntry = resolveIconEntry(name, primary, new Set());
- if (primaryEntry) {
- return primaryEntry;
- }
-
- if (options?.fallbackOrder && options.fallbackOrder.length > 0) {
- for (const fallback of options.fallbackOrder) {
- const fallbackSet =
- iconSetMap.get(fallback) ?? iconSetMap.get(fallback.toLowerCase());
- const entry = resolveIconEntry(
- name,
- fallbackSet ?? null,
- new Set(),
- );
- if (entry) {
- return entry;
- }
- }
- }
-
- return undefined;
- },
- [currentSet, iconSetMap, iconSets, resolveIconEntry],
- );
-
- const getIconDefinition = useCallback(
- (name: string, options?: IconLookupOptions) =>
- findIconEntry(name, options)?.definition,
- [findIconEntry],
- );
-
- // Use refs for values needed in loadIcon to keep the callback stable
- const currentSetRef = useRef(currentSet);
- const iconSetsRef = useRef(iconSets);
- const iconModuleLoadersRef = useRef(iconModuleLoaders);
-
- // Update refs when state changes
- useEffect(() => {
- currentSetRef.current = currentSet;
- }, [currentSet]);
-
- useEffect(() => {
- iconSetsRef.current = iconSets;
- }, [iconSets]);
-
- const loadIcon = useCallback(
- async (
- name: string,
- options?: IconLookupOptions,
- ): Promise => {
- if (!name) {
- return null;
- }
-
- // Use ref values to avoid triggering re-renders
- const localCurrentSet = currentSetRef.current;
-
- // Ensure currentSet icons are loaded (but don't update state from inside the callback)
- if (
- localCurrentSet &&
- (!localCurrentSet.icons ||
- Object.keys(localCurrentSet.icons).length === 0)
- ) {
- try {
- const loader = iconModuleLoadersRef.current[localCurrentSet.path];
- if (loader) {
- const module = (await loader()) as IconSetModule;
- // Update the set in iconSets without triggering re-renders in loadIcon
- const updatedSet = {
- ...localCurrentSet,
- icons: module.default,
- libraries: module.libraries,
- libraryConfig: module.libraryConfig,
- };
- // Update the ref immediately for the current request
- currentSetRef.current = updatedSet;
- // Schedule state update for the next render cycle
- queueMicrotask(() => {
- setIconSets((sets) =>
- sets.map((s) => (s.id === localCurrentSet.id ? updatedSet : s)),
- );
- });
- }
- } catch (err) {
- console.error(
- `Failed to load icon set "${localCurrentSet.label}"`,
- err,
- );
- }
- }
-
- const entry = findIconEntry(name, options);
- if (!entry) {
- return null;
- }
-
- const cacheKeyParts = [entry.set.id, name];
- if (options?.setId) {
- cacheKeyParts.push(`requested:${options.setId}`);
- }
- if (options?.fallbackOrder && options.fallbackOrder.length > 0) {
- cacheKeyParts.push(`fallback:${options.fallbackOrder.join("|")}`);
- }
- const cacheKey = cacheKeyParts.join("::");
-
- const cached = resolvedIconCache.get(cacheKey);
- if (cached) {
- return cached;
- }
-
- const { definition, set } = entry;
-
- switch (definition.type) {
- case "library": {
- const component = await loadLibraryIcon(
- definition.library,
- definition.icon,
- set,
- );
- if (!component) {
- console.warn(
- `Icon "${definition.icon}" from library "${definition.library}" not found.`,
- );
- return null;
- }
-
- // Extract prop transformer for this library
- const libraryConfig = set.libraryConfig?.[definition.library];
- let propTransformer: IconPropTransformer | undefined;
-
- if (
- libraryConfig &&
- typeof libraryConfig === "object" &&
- "propTransformer" in libraryConfig
- ) {
- const transformer = (libraryConfig as any).propTransformer;
- if (typeof transformer === "function") {
- propTransformer = transformer as IconPropTransformer;
- }
- }
-
- const resolved: ResolvedIcon = {
- type: "component",
- Component: component,
- defaultProps: {},
- propTransformer,
- title: definition.title,
- };
-
- resolvedIconCache.set(cacheKey, resolved);
- return resolved;
- }
- case "component": {
- const resolved: ResolvedIcon = {
- type: "component",
- Component: definition.component,
- defaultProps: definition.props,
- title: definition.title,
- };
- resolvedIconCache.set(cacheKey, resolved);
- return resolved;
- }
- case "image": {
- const resolved: ResolvedIcon = {
- type: "image",
- src: definition.src,
- alt: definition.alt,
- title: definition.title,
- };
- resolvedIconCache.set(cacheKey, resolved);
- return resolved;
- }
- case "svg-inline": {
- const resolved: ResolvedIcon = {
- type: "svg-inline",
- content: definition.content,
- viewBox: definition.viewBox,
- alt: definition.alt,
- title: definition.title,
- };
- resolvedIconCache.set(cacheKey, resolved);
- return resolved;
- }
- default: {
- console.warn(`Unsupported icon definition type for icon "${name}"`);
- return null;
- }
- }
- },
- [findIconEntry, setIconSets],
- );
-
- const contextValue = useMemo(
- () => ({
- iconSets,
- iconSetMap,
- currentSet,
- isLoading,
- iconsReady,
- error,
- setIconSet,
- getIconDefinition,
- loadIcon,
- }),
- [
- currentSet,
- error,
- getIconDefinition,
- iconSetMap,
- iconSets,
- isLoading,
- iconsReady,
- loadIcon,
- setIconSet,
- ],
- );
-
- useEffect(() => {
- if (typeof window !== "undefined") {
- (window as any).iconRegistry = {
- list: () => iconSets,
- current: () => currentSet,
- set: (id: string) => setIconSet(id),
- };
- }
- }, [iconSets, currentSet, setIconSet]);
-
- return (
-
- {children}
-
- );
-};
-
-export const useIconRegistry = () => {
- const context = useContext(IconRegistryContext);
- if (!context) {
- throw new Error(
- "useIconRegistry must be used within an IconRegistryProvider",
- );
- }
- return context;
-};
diff --git a/Build/src/helpers/importAudioFiles.tsx b/Build/src/helpers/importAudioFiles.tsx
index 45187e9..d53704e 100644
--- a/Build/src/helpers/importAudioFiles.tsx
+++ b/Build/src/helpers/importAudioFiles.tsx
@@ -1,11 +1,59 @@
import { toast } from "sonner";
-import { extractAudioMetadata, generateUniqueId } from "./filePickerHelper";
-import { musicIndexedDbHelper } from "./musicIndexedDbHelper";
-import { setAlbumArtInCache } from "../hooks/useAlbumArt";
+import {
+ createMetadataExtractor,
+ createFloMetadataExtractor,
+ compressAlbumArt,
+ generateUniqueId,
+} from "../platform/metadata";
+import { albumArtStorage } from "../platform/storage";
+import type { ExtractedMetadata } from "../platform/metadata";
+import type { Track } from "../core/engine/types";
+
+function getMetadataExtractor(file: File) {
+ const ext = file.name.split(".").pop()?.toLowerCase();
+ if (ext === "flo") {
+ return createFloMetadataExtractor();
+ }
+ return createMetadataExtractor();
+}
+
+async function extractAudioMetadata(
+ file: File,
+ t: any,
+): Promise<{
+ metadata: ExtractedMetadata;
+ albumArt: string | undefined;
+}> {
+ const extractor = getMetadataExtractor(file);
+ const metadata = await extractor.extractMetadata(file);
+
+ let albumArt = metadata.albumArt;
+ if (albumArt) {
+ try {
+ albumArt = await compressAlbumArt(albumArt);
+ } catch (e) {
+ console.warn("Failed to compress album art:", e);
+ }
+ }
+
+ const translated: ExtractedMetadata = {
+ ...metadata,
+ artist:
+ metadata.artist === "Unknown Artist"
+ ? t("common.unknownArtist")
+ : metadata.artist,
+ album:
+ metadata.album === "Unknown Album"
+ ? t("common.unknownAlbum")
+ : metadata.album,
+ };
+
+ return { metadata: translated, albumArt };
+}
export async function importAudioFiles(
audioFiles: Array<{ file: File } | File>,
- addSong: (song: Song, file: File) => Promise,
+ addSong: (song: Track, file: File) => Promise,
t: any,
) {
if (!audioFiles || audioFiles.length === 0) return;
@@ -24,7 +72,8 @@ export async function importAudioFiles(
for (const audioFile of batch) {
try {
const file: File = (audioFile as any).file || (audioFile as File);
- const metadata = await extractAudioMetadata(file);
+ const { metadata, albumArt: compressedArt } =
+ await extractAudioMetadata(file, t);
const songId = generateUniqueId();
// Pre-decode flo files for better performance
@@ -44,9 +93,11 @@ export async function importAudioFiles(
if (isSafari) {
// Safari: Pre-decode to WAV for compatibility
- const { decodeFloToWav } = await import("./refloWavHelper");
+ const { decodeFloToWav } =
+ await import("../platform/audio/floWavDecoder");
const wavBytes = await decodeFloToWav(arrayBuffer);
- const wavBlob = new Blob([wavBytes], { type: "audio/wav" });
+ const wavArray = new Uint8Array(wavBytes);
+ const wavBlob = new Blob([wavArray], { type: "audio/wav" });
processedFile = new File(
[wavBlob],
file.name.replace(/\.flo$/i, ".wav"),
@@ -56,7 +107,8 @@ export async function importAudioFiles(
console.log(`Pre-decoded flo to WAV for Safari: ${file.name}`);
} else {
// Non-Safari: Pre-decode to PCM for Web Audio API
- const { decodeFloToAudioBuffer } = await import("./floProcessor");
+ const { decodeFloToAudioBuffer } =
+ await import("../platform/audio/floDecoder");
const audioContext = new AudioContext();
const audioBuffer = await decodeFloToAudioBuffer(
arrayBuffer,
@@ -109,13 +161,12 @@ export async function importAudioFiles(
}
// Save album art separately if present
- const hasAlbumArt = !!metadata.albumArt;
- if (hasAlbumArt && metadata.albumArt) {
- await musicIndexedDbHelper.saveAlbumArt(songId, metadata.albumArt);
- setAlbumArtInCache(songId, metadata.albumArt);
+ const hasAlbumArt = !!compressedArt;
+ if (hasAlbumArt && compressedArt) {
+ await albumArtStorage.save(songId, compressedArt);
}
- const song: Song = {
+ const song: Track = {
id: songId,
title: metadata.title,
artist: metadata.artist,
@@ -124,7 +175,7 @@ export async function importAudioFiles(
t("songInfo.album", { title: t("common.unknownAlbum") }),
duration: metadata.duration,
url: "", // Will be set by addSong
- albumArt: metadata.albumArt, // Keep for immediate display
+ albumArt: compressedArt, // Keep for immediate display
hasAlbumArt,
embeddedLyrics: metadata.embeddedLyrics,
encoding: metadata.encoding,
diff --git a/Build/src/helpers/musicIndexedDbHelper.ts b/Build/src/helpers/musicIndexedDbHelper.ts
deleted file mode 100644
index eb6336c..0000000
--- a/Build/src/helpers/musicIndexedDbHelper.ts
+++ /dev/null
@@ -1,672 +0,0 @@
-// IndexedDB configuration
-import i18n from "i18next";
-
-const DB_NAME = "HTMLPlayerDB";
-const DB_VERSION = 2; // Bump version for album art store
-const STORES = {
- LIBRARY: "library",
- SETTINGS: "settings",
- AUDIO_DATA: "audioData", // Store for actual audio data
- ALBUM_ART: "albumArt", // New store for album art (lazy loaded)
-} as const;
-
-// In-memory cache for album art to avoid repeated IndexedDB reads
-const albumArtCache = new Map();
-const MAX_ALBUM_ART_CACHE = 50; // Only keep 50 album arts in memory
-
-// IndexedDB utilities
-const openDatabase = (): Promise => {
- return new Promise((resolve, reject) => {
- const request = indexedDB.open(DB_NAME, DB_VERSION);
-
- request.onerror = () => {
- console.error("Failed to open IndexedDB:", request.error);
- reject(request.error);
- };
-
- request.onsuccess = () => {
- resolve(request.result);
- };
-
- request.onupgradeneeded = (event) => {
- const db = (event.target as IDBOpenDBRequest).result;
- const oldVersion = event.oldVersion;
-
- // Create object stores if they don't exist
- if (!db.objectStoreNames.contains(STORES.LIBRARY)) {
- db.createObjectStore(STORES.LIBRARY, { keyPath: "id" });
- }
- if (!db.objectStoreNames.contains(STORES.SETTINGS)) {
- db.createObjectStore(STORES.SETTINGS, { keyPath: "id" });
- }
- if (!db.objectStoreNames.contains(STORES.AUDIO_DATA)) {
- const audioStore = db.createObjectStore(STORES.AUDIO_DATA, {
- keyPath: "songId",
- });
- audioStore.createIndex("lastAccessed", "lastAccessed", {
- unique: false,
- });
- }
- // Create album art store for lazy loading
- if (!db.objectStoreNames.contains(STORES.ALBUM_ART)) {
- db.createObjectStore(STORES.ALBUM_ART, { keyPath: "songId" });
- }
-
- // Migration: Move album art from library to separate store
- if (oldVersion < 2 && oldVersion > 0) {
- const transaction = (event.target as IDBOpenDBRequest).transaction;
- if (transaction) {
- const libraryStore = transaction.objectStore(STORES.LIBRARY);
- const albumArtStore = transaction.objectStore(STORES.ALBUM_ART);
-
- libraryStore.get("musicLibrary").onsuccess = function (e: any) {
- const library = e.target.result?.data;
- if (library?.songs) {
- library.songs.forEach((song: any) => {
- // Migrate album art to separate store
- if (song.albumArt) {
- albumArtStore.put({
- songId: song.id,
- albumArt: song.albumArt,
- });
- // Mark that album art exists but don't store it in library
- song.hasAlbumArt = true;
- delete song.albumArt;
- }
- // Also migrate audio data if present (from version 0)
- if (song.fileData && song.mimeType) {
- const audioStore = transaction.objectStore(STORES.AUDIO_DATA);
- audioStore.put({
- songId: song.id,
- fileData: song.fileData,
- mimeType: song.mimeType,
- lastAccessed: Date.now(),
- });
- delete song.fileData;
- delete song.mimeType;
- }
- });
- // Save cleaned up library
- libraryStore.put({ id: "musicLibrary", data: library });
- }
- };
- }
- }
- };
- });
-};
-
-const saveToIndexedDB = async (
- storeName: string,
- key: string,
- data: any,
-): Promise => {
- try {
- // Open database
- const db = await openDatabase();
-
- // For library data, we need to save album art separately
- if (key === "musicLibrary" && data?.songs) {
- // First pass: extract album art and save to separate store
- const albumArtsToSave: { songId: string; albumArt: string }[] = [];
-
- const BATCH_SIZE = 100;
- const processedSongs: any[] = [];
-
- // Process songs in batches to prevent RAM spikes
- for (let i = 0; i < data.songs.length; i += BATCH_SIZE) {
- const batch = data.songs.slice(i, i + BATCH_SIZE);
- const processedBatch = batch.map((song: any) => {
- // Extract album art for separate storage
- if (song.albumArt) {
- albumArtsToSave.push({ songId: song.id, albumArt: song.albumArt });
- }
-
- return {
- ...song,
- hasStoredAudio: song.hasStoredAudio || false,
- hasAlbumArt: !!song.albumArt || song.hasAlbumArt || false,
- url: "", // Clear URL - will be created on-demand
- albumArt: undefined, // Don't store album art in library - load lazily
- embeddedLyrics: song.embeddedLyrics, // Preserve embedded lyrics
- encoding: song.encoding, // Preserve encoding
- gapless: song.gapless, // Preserve gapless flag
- };
- });
- processedSongs.push(...processedBatch);
-
- // Yield to main thread between batches for large libraries
- if (
- i + BATCH_SIZE < data.songs.length &&
- data.songs.length > BATCH_SIZE
- ) {
- await new Promise((resolve) => setTimeout(resolve, 0));
- }
- }
-
- // Save album art separately in batches (don't block library save)
- if (albumArtsToSave.length > 0) {
- // Do this in background after library is saved
- setTimeout(async () => {
- try {
- const artDb = await openDatabase();
- const ART_BATCH_SIZE = 20; // Smaller batches for album art (they're big)
-
- for (let i = 0; i < albumArtsToSave.length; i += ART_BATCH_SIZE) {
- const artBatch = albumArtsToSave.slice(i, i + ART_BATCH_SIZE);
- const artTransaction = artDb.transaction(
- [STORES.ALBUM_ART],
- "readwrite",
- );
- const artStore = artTransaction.objectStore(STORES.ALBUM_ART);
-
- for (const art of artBatch) {
- artStore.put(art);
- }
-
- await new Promise((resolve, reject) => {
- artTransaction.oncomplete = () => resolve();
- artTransaction.onerror = () => reject(artTransaction.error);
- });
-
- // Yield between batches
- if (i + ART_BATCH_SIZE < albumArtsToSave.length) {
- await new Promise((resolve) => setTimeout(resolve, 10));
- }
- }
- artDb.close();
- console.log(
- `Saved ${albumArtsToSave.length} album arts to IndexedDB`,
- );
- } catch (error) {
- console.error("Failed to save album art:", error);
- }
- }, 100);
- }
-
- // Save library without album art data
- const transaction = db.transaction([storeName], "readwrite");
- const store = transaction.objectStore(storeName);
-
- const processedData = {
- ...data,
- songs: processedSongs,
- };
-
- const savePromise = new Promise((resolve, reject) => {
- transaction.oncomplete = () => resolve();
- transaction.onerror = () => reject(transaction.error);
- store.put({ id: key, data: processedData });
- });
-
- await savePromise;
- db.close();
- console.log(`Saved ${key} to IndexedDB`);
- return;
- }
-
- // Non-library data - save normally
- const transaction = db.transaction([storeName], "readwrite");
- const store = transaction.objectStore(storeName);
-
- // Create a promise that resolves when the transaction completes
- const savePromise = new Promise((resolve, reject) => {
- transaction.oncomplete = () => resolve();
- transaction.onerror = () => reject(transaction.error);
- store.put({ id: key, data });
- });
-
- // Wait for transaction to complete before closing
- await savePromise;
- db.close();
- console.log(`Saved ${key} to IndexedDB`);
- } catch (error) {
- console.error(`Failed to save ${key} to IndexedDB:`, error);
- throw error;
- }
-};
-
-const loadFromIndexedDB = async (
- storeName: string,
- key: string,
-): Promise => {
- try {
- const db = await openDatabase();
- const transaction = db.transaction([storeName], "readonly");
- const store = transaction.objectStore(storeName);
-
- const result = await new Promise((resolve, reject) => {
- const request = store.get(key);
- request.onsuccess = () => resolve(request.result?.data);
- request.onerror = () => reject(request.error);
- });
-
- db.close();
- console.log(`Loaded ${key} from IndexedDB`);
-
- // If loading library data, create placeholder URLs for display
- if (key === "musicLibrary" && result?.songs) {
- // Ensure we have a songs array even if empty
- const rawSongs = result.songs || [];
-
- // Process songs in batches to prevent RAM spikes on large libraries
- const BATCH_SIZE = 100;
- const songsWithoutAudio: any[] = [];
-
- for (let i = 0; i < rawSongs.length; i += BATCH_SIZE) {
- const batch = rawSongs.slice(i, i + BATCH_SIZE);
-
- // Transform this batch - don't include albumArt, it will be loaded lazily
- const transformedBatch = batch.map((song: any) => {
- // Always set up the indexeddb URL if the song has stored audio
- const placeholderUrl = song.hasStoredAudio
- ? `indexeddb://${song.id}` // Will be loaded from IndexedDB
- : song.url || ""; // Keep original URL if no stored data, or empty if none
-
- return {
- // Ensure all required fields exist first
- id: song.id || `song-${Date.now()}-${Math.random()}`,
- title: song.title || i18n.t("common.unknownTitle"),
- artist: song.artist || i18n.t("common.unknownArtist"),
- album: song.album || i18n.t("common.unknownAlbum"),
- duration: song.duration || 0,
- // Then add the library-specific fields
- url: placeholderUrl,
- hasStoredAudio: song.hasStoredAudio || false,
- // DON'T load albumArt here - it will be lazy loaded on-demand
- // This is the key memory optimization - album art is loaded only when visible
- hasAlbumArt: song.hasAlbumArt || !!song.albumArt || false,
- albumArt: undefined, // Will be loaded lazily via loadAlbumArt()
- embeddedLyrics: song.embeddedLyrics, // Restore embedded lyrics
- encoding: song.encoding, // Restore encoding
- gapless: song.gapless, // Restore gapless flag
- };
- });
-
- songsWithoutAudio.push(...transformedBatch);
-
- // Yield to main thread between batches for large libraries
- if (i + BATCH_SIZE < rawSongs.length && rawSongs.length > BATCH_SIZE) {
- await new Promise((resolve) => setTimeout(resolve, 0));
- }
- }
-
- return {
- songs: songsWithoutAudio,
- playlists: result.playlists || [],
- favorites: result.favorites || [],
- };
- }
-
- return result;
- } catch (error) {
- console.error(`Failed to load ${key} from IndexedDB:`, error);
- return null;
- }
-};
-
-// Add new type for song audio data
-interface SongAudioData {
- fileData: ArrayBuffer;
- mimeType: string;
-}
-
-export const musicIndexedDbHelper = {
- async loadLibrary(): Promise {
- try {
- const library = await loadFromIndexedDB(STORES.LIBRARY, "musicLibrary");
- console.log("Loaded library state:", {
- songCount: library?.songs?.length || 0,
- playlistCount: library?.playlists?.length || 0,
- favoriteCount: library?.favorites?.length || 0,
- });
- return library;
- } catch (error) {
- console.error("Failed to load library:", error);
- return {
- songs: [],
- playlists: [],
- favorites: [],
- };
- }
- },
-
- async saveLibrary(library: MusicLibrary): Promise {
- await saveToIndexedDB(STORES.LIBRARY, "musicLibrary", library);
- },
-
- async loadSettings(): Promise {
- return await loadFromIndexedDB(STORES.SETTINGS, "playerSettings");
- },
-
- async saveSettings(settings: PlayerSettings): Promise {
- await saveToIndexedDB(STORES.SETTINGS, "playerSettings", settings);
- },
-
- async loadSongAudio(songId: string): Promise {
- try {
- const db = await openDatabase();
- const transaction = db.transaction([STORES.AUDIO_DATA], "readwrite");
- const store = transaction.objectStore(STORES.AUDIO_DATA);
-
- const result = await new Promise((resolve, reject) => {
- const request = store.get(songId);
- request.onsuccess = () => resolve(request.result);
- request.onerror = () => reject(request.error);
- });
-
- if (result) {
- // Update last accessed time
- store.put({
- ...result,
- lastAccessed: Date.now(),
- });
-
- return {
- fileData: result.fileData,
- mimeType: result.mimeType,
- };
- }
-
- db.close();
- return null;
- } catch (error) {
- console.error(`Failed to load audio data for song ${songId}:`, error);
- return null;
- }
- },
-
- async saveSongAudio(songId: string, audioData: SongAudioData): Promise {
- try {
- const db = await openDatabase();
- const transaction = db.transaction(
- [STORES.AUDIO_DATA, STORES.LIBRARY],
- "readwrite",
- );
- const audioStore = transaction.objectStore(STORES.AUDIO_DATA);
- const libraryStore = transaction.objectStore(STORES.LIBRARY);
-
- // Save audio data
- await new Promise((resolve, reject) => {
- const request = audioStore.put({
- songId,
- fileData: audioData.fileData,
- mimeType: audioData.mimeType,
- lastAccessed: Date.now(),
- });
- request.onsuccess = () => resolve();
- request.onerror = () => reject(request.error);
- });
-
- // Update song metadata to indicate audio is available
- const libraryData = await new Promise((resolve, reject) => {
- const request = libraryStore.get("musicLibrary");
- request.onsuccess = () => resolve(request.result?.data);
- request.onerror = () => reject(request.error);
- });
-
- if (libraryData?.songs) {
- const updatedSongs = libraryData.songs.map((song: any) => {
- if (song.id === songId) {
- return {
- ...song,
- hasStoredAudio: true,
- };
- }
- return song;
- });
-
- await new Promise((resolve, reject) => {
- const request = libraryStore.put({
- id: "musicLibrary",
- data: {
- ...libraryData,
- songs: updatedSongs,
- },
- });
- request.onsuccess = () => resolve();
- request.onerror = () => reject(request.error);
- });
- }
-
- db.close();
- } catch (error) {
- console.error(`Failed to save audio data for song ${songId}:`, error);
- throw error;
- }
- },
-
- async removeSongAudio(songId: string): Promise {
- try {
- const db = await openDatabase();
- const transaction = db.transaction([STORES.AUDIO_DATA], "readwrite");
- const store = transaction.objectStore(STORES.AUDIO_DATA);
-
- await new Promise((resolve, reject) => {
- const request = store.delete(songId);
- request.onsuccess = () => resolve();
- request.onerror = () => reject(request.error);
- });
-
- db.close();
- } catch (error) {
- console.error(`Failed to remove audio data for song ${songId}:`, error);
- throw error;
- }
- },
-
- async shouldShowDialog(dialogKey: string): Promise {
- try {
- const db = await openDatabase();
- const transaction = db.transaction([STORES.SETTINGS], "readonly");
- const store = transaction.objectStore(STORES.SETTINGS);
-
- const result = await new Promise((resolve, reject) => {
- const request = store.get(`dialog-${dialogKey}`);
- request.onsuccess = () => resolve(request.result);
- request.onerror = () => reject(request.error);
- });
-
- db.close();
- // Return true if no preference is set (show by default), false if user chose not to show
- return result?.data?.dontShowAgain !== true;
- } catch (error) {
- console.error(
- `Failed to check dialog preference for ${dialogKey}:`,
- error,
- );
- return true; // Default to showing the dialog if there's an error
- }
- },
-
- async setDialogPreference(
- dialogKey: string,
- dontShowAgain: boolean,
- ): Promise {
- try {
- const db = await openDatabase();
- const transaction = db.transaction([STORES.SETTINGS], "readwrite");
- const store = transaction.objectStore(STORES.SETTINGS);
-
- await new Promise((resolve, reject) => {
- const request = store.put({
- id: `dialog-${dialogKey}`,
- data: { dontShowAgain, timestamp: Date.now() },
- });
- request.onsuccess = () => resolve();
- request.onerror = () => reject(request.error);
- });
-
- db.close();
- console.log(
- `Saved dialog preference for ${dialogKey}: dontShowAgain=${dontShowAgain}`,
- );
- } catch (error) {
- console.error(
- `Failed to save dialog preference for ${dialogKey}:`,
- error,
- );
- throw error;
- }
- },
-
- // Lazy load album art for a single song
- async loadAlbumArt(songId: string): Promise {
- // Check in-memory cache first
- if (albumArtCache.has(songId)) {
- return albumArtCache.get(songId)!;
- }
-
- try {
- const db = await openDatabase();
- const transaction = db.transaction([STORES.ALBUM_ART], "readonly");
- const store = transaction.objectStore(STORES.ALBUM_ART);
-
- const result = await new Promise<
- { songId: string; albumArt: string } | undefined
- >((resolve, reject) => {
- const request = store.get(songId);
- request.onsuccess = () => resolve(request.result);
- request.onerror = () => reject(request.error);
- });
-
- db.close();
-
- if (result?.albumArt) {
- // Cache in memory (with LRU eviction)
- if (albumArtCache.size >= MAX_ALBUM_ART_CACHE) {
- // Remove oldest entry (first key)
- const firstKey = albumArtCache.keys().next().value;
- if (firstKey) albumArtCache.delete(firstKey);
- }
- albumArtCache.set(songId, result.albumArt);
- return result.albumArt;
- }
-
- return null;
- } catch (error) {
- console.error(`Failed to load album art for ${songId}:`, error);
- return null;
- }
- },
-
- // Load album art for multiple songs at once (more efficient than one-by-one)
- async loadAlbumArtBatch(songIds: string[]): Promise> {
- const result = new Map();
- const toLoad: string[] = [];
-
- // Check cache first
- for (const songId of songIds) {
- if (albumArtCache.has(songId)) {
- result.set(songId, albumArtCache.get(songId)!);
- } else {
- toLoad.push(songId);
- }
- }
-
- if (toLoad.length === 0) {
- return result;
- }
-
- try {
- const db = await openDatabase();
- const transaction = db.transaction([STORES.ALBUM_ART], "readonly");
- const store = transaction.objectStore(STORES.ALBUM_ART);
-
- // Load all needed album arts in parallel
- const loadPromises = toLoad.map((songId) => {
- return new Promise<{ songId: string; albumArt: string } | null>(
- (resolve, reject) => {
- const request = store.get(songId);
- request.onsuccess = () => resolve(request.result || null);
- request.onerror = () => reject(request.error);
- },
- );
- });
-
- const loadedArts = await Promise.all(loadPromises);
- db.close();
-
- // Process results and cache
- for (const art of loadedArts) {
- if (art?.albumArt) {
- // Cache with LRU eviction
- if (albumArtCache.size >= MAX_ALBUM_ART_CACHE) {
- const firstKey = albumArtCache.keys().next().value;
- if (firstKey) albumArtCache.delete(firstKey);
- }
- albumArtCache.set(art.songId, art.albumArt);
- result.set(art.songId, art.albumArt);
- }
- }
-
- return result;
- } catch (error) {
- console.error("Failed to load album art batch:", error);
- return result;
- }
- },
-
- // Save album art for a single song (used when adding new songs)
- async saveAlbumArt(songId: string, albumArt: string): Promise {
- try {
- const db = await openDatabase();
- const transaction = db.transaction([STORES.ALBUM_ART], "readwrite");
- const store = transaction.objectStore(STORES.ALBUM_ART);
-
- await new Promise((resolve, reject) => {
- const request = store.put({ songId, albumArt });
- request.onsuccess = () => resolve();
- request.onerror = () => reject(request.error);
- });
-
- db.close();
-
- // Update cache
- if (albumArtCache.size >= MAX_ALBUM_ART_CACHE) {
- const firstKey = albumArtCache.keys().next().value;
- if (firstKey) albumArtCache.delete(firstKey);
- }
- albumArtCache.set(songId, albumArt);
- } catch (error) {
- console.error(`Failed to save album art for ${songId}:`, error);
- }
- },
-
- // Clear album art cache to free memory
- clearAlbumArtCache(): void {
- albumArtCache.clear();
- },
-};
-
-export default musicIndexedDbHelper;
-
-export async function resetAllDialogPreferences(): Promise {
- try {
- const db = await openDatabase();
- const transaction = db.transaction([STORES.SETTINGS], "readwrite");
- const store = transaction.objectStore(STORES.SETTINGS);
- // Get all keys
- const keys = await new Promise((resolve, reject) => {
- const request = store.getAllKeys();
- request.onsuccess = () => resolve(request.result as string[]);
- request.onerror = () => reject(request.error);
- });
- // Delete all dialog-* keys
- await Promise.all(
- keys
- .filter((key) => key.startsWith("dialog-"))
- .map((key) => {
- return new Promise((resolve, reject) => {
- const req = store.delete(key);
- req.onsuccess = () => resolve();
- req.onerror = () => reject(req.error);
- });
- }),
- );
- db.close();
- } catch (error) {
- console.error("Failed to reset dialog preferences:", error);
- throw error;
- }
-}
diff --git a/Build/src/helpers/musicPlayerUtils.ts b/Build/src/helpers/musicPlayerUtils.ts
deleted file mode 100644
index 0a5bebb..0000000
--- a/Build/src/helpers/musicPlayerUtils.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-// Debouncing utility for IndexedDB saves
-
-export const getValidTempo = (tempo: number | undefined) => {
- if (typeof tempo !== "number" || !Number.isFinite(tempo) || tempo <= 0) {
- return 1; // fallback to normal speed
- }
- return tempo;
-};
-
-/**
- * Calculate combined playback rate from tempo and pitch, clamped to browser limits (0.25-4.0)
- * Tempo and pitch are applied multiplicatively: rate = tempo × 2^(pitch/12)
- */
-export const getValidPlaybackRate = (
- tempo: number | undefined,
- pitch: number | undefined,
-): number => {
- const validTempo = getValidTempo(tempo);
- const validPitch = pitch ?? 0;
-
- // Convert pitch (semitones) to frequency multiplier
- const pitchMultiplier = Math.pow(2, validPitch / 12);
-
- // Combine tempo and pitch
- const combinedRate = validTempo * pitchMultiplier;
-
- // Clamp to browser's supported playback rate range
- return Math.max(0.25, Math.min(4.0, combinedRate));
-};
diff --git a/Build/src/helpers/pitchShiftHelper.ts b/Build/src/helpers/pitchShiftHelper.ts
deleted file mode 100644
index 4cdb05c..0000000
--- a/Build/src/helpers/pitchShiftHelper.ts
+++ /dev/null
@@ -1,81 +0,0 @@
-export interface PitchShiftProcessor {
- setPitch: (semitones: number) => void;
- getPitch: () => number;
- getPassThroughNode: () => GainNode;
- connectToAudioElement: (element: HTMLAudioElement) => void;
- destroy: () => void;
-}
-
-/**
- * Create a pitch shifter using playbackRate (affects both pitch and tempo)
- * Pitch is measured in semitones: -100 to +100
- * 0 means no pitch shift
- *
- * NOTE: This implementation uses HTMLAudioElement.playbackRate which changes
- * both pitch and tempo together (like playing a record at different speeds).
- * For true pitch shifting without tempo change, complex DSP would be required.
- */
-export function createPitchShifter(
- audioContext: AudioContext,
-): PitchShiftProcessor {
- let currentPitch = 0;
- let isDestroyed = false;
-
- // Create a gain node to maintain the audio chain
- const passThroughGain = audioContext.createGain();
- passThroughGain.gain.value = 1.0;
-
- const processor: PitchShiftProcessor = {
- setPitch(semitones: number) {
- if (isDestroyed) return;
-
- // Clamp to -48 to +48 semitones (4 octaves, staying within browser playback rate limits)
- currentPitch = Math.max(-48, Math.min(48, semitones));
- },
-
- getPitch() {
- return currentPitch;
- },
-
- getPassThroughNode() {
- return passThroughGain;
- },
-
- connectToAudioElement(_element: HTMLAudioElement) {
- // No-op: pitch control is handled elsewhere
- },
-
- destroy() {
- if (isDestroyed) return;
- isDestroyed = true;
-
- try {
- passThroughGain.disconnect();
- } catch (error) {
- console.error("Error destroying pitch shifter:", error);
- }
- },
- };
-
- return processor;
-}
-
-/**
- * Validate and clamp pitch value
- */
-export function getValidPitch(pitch: number | undefined): number {
- if (typeof pitch !== "number" || !Number.isFinite(pitch)) {
- return 0; // Default to no pitch shift
- }
- // Clamp to -48 to +48 semitones (4 octaves, staying within browser playback rate limits)
- return Math.max(-48, Math.min(48, pitch));
-}
-
-/**
- * Convert semitones to a human-readable string
- */
-export function formatPitchValue(semitones: number): string {
- if (semitones === 0) return "0";
- const sign = semitones > 0 ? "+" : "";
- return `${sign}${semitones}`;
-}
diff --git a/Build/src/helpers/platform.ts b/Build/src/helpers/platform.ts
deleted file mode 100644
index 9646562..0000000
--- a/Build/src/helpers/platform.ts
+++ /dev/null
@@ -1,323 +0,0 @@
-// Platform Detection Utilities
-// Use these helpers throughout the app to handle platform-specific behavior
-
-/**
- * Platform capabilities and feature detection
- */
-export const platform = {
- /**
- * Check if running in a web browser (not Tauri)
- */
- get isWeb(): boolean {
- return typeof window !== "undefined" && !("__TAURI__" in window);
- },
-
- /**
- * Check if running in Tauri desktop app
- */
- get isDesktop(): boolean {
- return typeof window !== "undefined" && "__TAURI__" in window;
- },
-
- /**
- * Check if PWA features are available
- */
- get isPWA(): boolean {
- return "serviceWorker" in navigator;
- },
-
- /**
- * Check if IndexedDB is available
- */
- get hasIndexedDB(): boolean {
- return typeof indexedDB !== "undefined";
- },
-
- /**
- * Check if native file system is available (Tauri)
- */
- get hasNativeFileSystem(): boolean {
- return this.isDesktop;
- },
-
- /**
- * Check if native dialogs are available (Tauri)
- */
- get hasNativeDialogs(): boolean {
- return this.isDesktop;
- },
-
- /**
- * Check if can install as PWA
- */
- get canInstallPWA(): boolean {
- return this.isWeb && "BeforeInstallPromptEvent" in window;
- },
-
- /**
- * Check if Web Audio API is available
- */
- get hasWebAudio(): boolean {
- return (
- typeof AudioContext !== "undefined" ||
- typeof (window as any).webkitAudioContext !== "undefined"
- );
- },
-
- /**
- * Detect Safari browser (for background playback workarounds)
- */
- get isSafari(): boolean {
- const ua = navigator.userAgent.toLowerCase();
- return (
- /^((?!chrome|android).)*safari/i.test(ua) || /iphone|ipad|ipod/i.test(ua)
- );
- },
-};
-
-/**
- * Audio file picker - unified interface for web and desktop
- * Uses Uppy Dashboard on web, native file picker on desktop
- */
-export async function pickAudioFiles(options?: {
- multiple?: boolean;
-}): Promise {
- if (platform.isDesktop) {
- // Use Tauri's native file picker
- const { open } = await import("@tauri-apps/plugin-dialog");
- const selected = await open({
- multiple: options?.multiple ?? true,
- filters: [
- {
- name: "Audio Files",
- extensions: [
- "mp3",
- "wav",
- "m4a",
- "flac",
- "aif",
- "aiff",
- "ogg",
- "opus",
- "webm",
- ],
- },
- ],
- });
-
- if (!selected) return [];
-
- // Convert Tauri paths to File objects
- const { readFile } = await import("@tauri-apps/plugin-fs");
- const paths = Array.isArray(selected) ? selected : [selected];
-
- const files = await Promise.all(
- paths.map(async (path) => {
- const contents = await readFile(path);
- const fileName = path.split("/").pop() ?? "unknown";
- const ext = fileName.split(".").pop()?.toLowerCase() ?? "mp3";
-
- // Determine MIME type from extension
- const mimeTypes: Record = {
- mp3: "audio/mpeg",
- wav: "audio/wav",
- m4a: "audio/mp4",
- flac: "audio/flac",
- aif: "audio/aiff",
- aiff: "audio/aiff",
- ogg: "audio/ogg",
- opus: "audio/opus",
- webm: "audio/webm",
- };
-
- return new File([contents], fileName, {
- type: mimeTypes[ext] || "audio/mpeg",
- });
- }),
- );
-
- return files;
- } else {
- // Web: Use existing Uppy implementation from filePickerHelper.tsx
- // This returns a promise that resolves when user completes selection
- const { pickAudioFiles: webPickAudioFiles } =
- await import("./filePickerHelper");
- const audioFiles = await webPickAudioFiles();
- return audioFiles.map((af) => af.file);
- }
-}
-
-/**
- * Export playlist file - unified interface for web and desktop
- */
-export async function exportPlaylistFile(
- content: string,
- fileName: string,
- fileType: "json" | "m3u",
-): Promise {
- const mimeType = fileType === "json" ? "application/json" : "audio/x-mpegurl";
- const blob = new Blob([content], { type: mimeType });
-
- if (platform.isDesktop) {
- // Use Tauri's native save dialog
- const { save } = await import("@tauri-apps/plugin-dialog");
- const { writeTextFile } = await import("@tauri-apps/plugin-fs");
-
- const filePath = await save({
- defaultPath: fileName,
- filters: [
- {
- name: fileType === "json" ? "JSON Files" : "M3U Playlist",
- extensions: [fileType],
- },
- ],
- });
-
- if (filePath) {
- await writeTextFile(filePath, content);
- }
- } else {
- // Web: Use download link
- const url = URL.createObjectURL(blob);
- const a = document.createElement("a");
- a.href = url;
- a.download = fileName;
- document.body.appendChild(a);
- a.click();
- document.body.removeChild(a);
- URL.revokeObjectURL(url);
- }
-}
-
-/**
- * Import playlist file - unified interface for web and desktop
- */
-export async function importPlaylistFile(): Promise {
- if (platform.isDesktop) {
- const { open } = await import("@tauri-apps/plugin-dialog");
- const { readTextFile } = await import("@tauri-apps/plugin-fs");
-
- const selected = await open({
- multiple: false,
- filters: [
- {
- name: "Playlist Files",
- extensions: ["json", "m3u", "m3u8"],
- },
- ],
- });
-
- if (!selected || Array.isArray(selected)) return null;
-
- const content = await readTextFile(selected);
- const fileName = selected.split("/").pop() ?? "playlist";
- const ext = fileName.split(".").pop()?.toLowerCase() ?? "json";
- const mimeType = ext === "json" ? "application/json" : "audio/x-mpegurl";
-
- return new File([content], fileName, { type: mimeType });
- } else {
- // Web: Use file input
- return new Promise((resolve) => {
- const input = document.createElement("input");
- input.type = "file";
- input.accept = ".json,.m3u,.m3u8";
- input.onchange = () => {
- resolve(input.files?.[0] || null);
- };
- input.click();
- });
- }
-}
-
-/**
- * Show native notification
- */
-export async function showNotification(
- title: string,
- body: string,
-): Promise {
- if (platform.isDesktop) {
- // Use Tauri's native notifications
- try {
- const { sendNotification } =
- await import("@tauri-apps/plugin-notification");
- await sendNotification({ title, body });
- } catch (error) {
- console.warn("Desktop notification failed:", error);
- }
- } else {
- // Use web Notification API
- if ("Notification" in window && Notification.permission === "granted") {
- new Notification(title, { body });
- } else if (
- "Notification" in window &&
- Notification.permission !== "denied"
- ) {
- const permission = await Notification.requestPermission();
- if (permission === "granted") {
- new Notification(title, { body });
- }
- }
- }
-}
-
-/**
- * Get app version
- */
-export async function getAppVersion(): Promise {
- if (platform.isDesktop) {
- try {
- const { getVersion } = await import("@tauri-apps/api/app");
- return await getVersion();
- } catch {
- return "2.0.0";
- }
- } else {
- // Return version from package.json
- return "2.0.0";
- }
-}
-
-/**
- * Open external URL in default browser
- */
-export async function openExternal(url: string): Promise {
- if (platform.isDesktop) {
- const { openUrl } = await import("@tauri-apps/plugin-opener");
- await openUrl(url);
- } else {
- window.open(url, "_blank", "noopener,noreferrer");
- }
-}
-
-/**
- * Check if a specific audio format is supported
- */
-export function isAudioFormatSupported(format: string): boolean {
- const audio = document.createElement("audio");
- const canPlay = audio.canPlayType(format);
- return canPlay === "probably" || canPlay === "maybe";
-}
-
-/**
- * Get persistent storage estimate (IndexedDB usage)
- */
-export async function getStorageEstimate(): Promise<{
- usage: number;
- quota: number;
- percentage: number;
-} | null> {
- if ("storage" in navigator && "estimate" in navigator.storage) {
- try {
- const estimate = await navigator.storage.estimate();
- const usage = estimate.usage || 0;
- const quota = estimate.quota || 0;
- const percentage = quota > 0 ? (usage / quota) * 100 : 0;
- return { usage, quota, percentage };
- } catch (error) {
- console.warn("Failed to get storage estimate:", error);
- return null;
- }
- }
- return null;
-}
diff --git a/Build/src/helpers/playlistImageHelper.ts b/Build/src/helpers/playlistImageHelper.ts
deleted file mode 100644
index 74cdb6d..0000000
--- a/Build/src/helpers/playlistImageHelper.ts
+++ /dev/null
@@ -1,85 +0,0 @@
-export const generatePlaylistImage = async (songs: Song[]): Promise => {
- // Create a canvas element
- const canvas = document.createElement("canvas");
- canvas.width = 80; // Same size as album art
- canvas.height = 80;
- const ctx = canvas.getContext("2d");
-
- if (!ctx) return "";
-
- // Get up to 4 unique album arts
- const uniqueAlbumArts = Array.from(
- new Set(songs.filter((song) => song.albumArt).map((song) => song.albumArt)),
- ).slice(0, 4);
-
- // If no album arts, return empty string
- if (uniqueAlbumArts.length === 0) return "";
-
- // Load all images first
- const loadImage = (src: string): Promise => {
- return new Promise((resolve, reject) => {
- const img = new Image();
- img.crossOrigin = "anonymous";
- img.onload = () => resolve(img);
- img.onerror = reject;
- img.src = src;
- });
- };
-
- try {
- const images = await Promise.all(
- uniqueAlbumArts.map((art) => loadImage(art!)),
- );
-
- // Clear the canvas
- ctx.fillStyle = "#1E3A8A"; // Default background
- ctx.fillRect(0, 0, canvas.width, canvas.height);
-
- // Draw images based on count
- switch (images.length) {
- case 1:
- // Single image takes up the whole space
- ctx.drawImage(images[0], 0, 0, 80, 80);
- break;
-
- case 2:
- // Two images side by side
- ctx.drawImage(images[0], 0, 0, 40, 80);
- ctx.drawImage(images[1], 40, 0, 40, 80);
- break;
-
- case 3:
- // One on top, two on bottom
- ctx.drawImage(images[0], 0, 0, 80, 40);
- ctx.drawImage(images[1], 0, 40, 40, 40);
- ctx.drawImage(images[2], 40, 40, 40, 40);
- break;
-
- case 4:
- // 2x2 grid
- ctx.drawImage(images[0], 0, 0, 40, 40);
- ctx.drawImage(images[1], 40, 0, 40, 40);
- ctx.drawImage(images[2], 0, 40, 40, 40);
- ctx.drawImage(images[3], 40, 40, 40, 40);
- break;
- }
-
- // Add a slight overlay to make it cohesive
- ctx.fillStyle = "rgba(0, 0, 0, 0.1)";
- ctx.fillRect(0, 0, 80, 80);
-
- const result = canvas.toDataURL("image/jpeg", 0.7); // Reduced from 0.8 to 0.7 for memory savings
-
- // Clean up canvas to free memory
- canvas.width = 0;
- canvas.height = 0;
-
- return result;
- } catch (error) {
- console.error("Failed to generate playlist image:", error);
- // Clean up canvas on error too
- canvas.width = 0;
- canvas.height = 0;
- return "";
- }
-};
diff --git a/Build/src/helpers/playlistManager.ts b/Build/src/helpers/playlistManager.ts
deleted file mode 100644
index 47ec998..0000000
--- a/Build/src/helpers/playlistManager.ts
+++ /dev/null
@@ -1,655 +0,0 @@
-import { toast } from "sonner";
-import i18n from "i18next";
-
-export const createPlaylistManager = (
- setLibrary: (updater: (prev: MusicLibrary) => MusicLibrary) => void,
- library: MusicLibrary,
- setSearchQuery: (query: string) => void,
- searchQuery: string,
- setPlayerState: (updater: (prev: any) => any) => void,
-) => {
- const prepareSongsForPlaylist = (
- songs: Song[],
- songCacheRef?: React.MutableRefObject>,
- ): Song[] => {
- return songs.map((song) => {
- if (song.hasStoredAudio) {
- // Always use indexeddb:// URL for stored songs
- return {
- ...song,
- url: `indexeddb://${song.id}`,
- };
- } else if (songCacheRef?.current.has(song.id)) {
- // If song is in cache, use its cached URL
- const cached = songCacheRef.current.get(song.id);
- return {
- ...song,
- url: cached?.url || song.url,
- };
- }
- return song;
- });
- };
-
- const uuid = () =>
- crypto.randomUUID
- ? crypto.randomUUID()
- : Math.random().toString(36).slice(2) + Date.now();
-
- const createPlaylist = (name: string, songs: Song[] = []) => {
- const newPlaylist: Playlist = {
- id: uuid(),
- name,
- songs: prepareSongsForPlaylist(songs),
- };
- setLibrary((prev) => ({
- ...prev,
- playlists: [...prev.playlists, newPlaylist],
- }));
- return newPlaylist;
- };
-
- const createFolder = (name: string) => {
- const newFolder: PlaylistFolder = {
- id: uuid(),
- name,
- children: [],
- };
- setLibrary((prev) => ({
- ...prev,
- playlists: [...prev.playlists, newFolder],
- }));
- return newFolder;
- };
-
- const removePlaylist = (playlistId: string) => {
- setLibrary((prev) => {
- // Recursive function to remove playlist from the tree
- const removeFrom = (
- items: (Playlist | PlaylistFolder)[],
- ): (Playlist | PlaylistFolder)[] => {
- return items
- .filter((p) => p.id !== playlistId)
- .map((p) => {
- if ("children" in p) {
- return { ...p, children: removeFrom(p.children) };
- }
- return p;
- });
- };
-
- return {
- ...prev,
- playlists: removeFrom(prev.playlists),
- };
- });
- };
-
- const addToFavorites = (songId: string) => {
- setLibrary((prev) => ({
- ...prev,
- favorites: prev.favorites.includes(songId)
- ? prev.favorites
- : [...prev.favorites, songId],
- }));
- };
-
- const removeFromFavorites = (songId: string) => {
- setLibrary((prev) => ({
- ...prev,
- favorites: prev.favorites.filter((id) => id !== songId),
- }));
- };
-
- const addToPlaylist = (playlistId: string, songId: string) => {
- setLibrary((prev) => {
- // Find the song
- const song = prev.songs.find((s) => s.id === songId);
- if (!song) return prev;
-
- // Recursive function to update playlists in the tree
- const updatePlaylists = (
- items: (Playlist | PlaylistFolder)[],
- ): (Playlist | PlaylistFolder)[] => {
- return items.map((p) => {
- if (p.id === playlistId && "songs" in p) {
- // Don't add if song is already in playlist
- if (p.songs.some((s) => s.id === songId)) return p;
- return {
- ...p,
- songs: [...p.songs, song],
- };
- }
- if ("children" in p) {
- return { ...p, children: updatePlaylists(p.children) };
- }
- return p;
- });
- };
-
- return {
- ...prev,
- playlists: updatePlaylists(prev.playlists),
- };
- });
- };
-
- const reorderPlaylistSongs = (
- playlistId: string | null,
- newSongs: Song[],
- ) => {
- setLibrary((prev) => {
- // If playlistId is undefined, update root songs (for All Songs)
- if (!playlistId) {
- return {
- ...prev,
- songs: newSongs,
- playlists: prev.playlists.map((p) =>
- p.id === "all-songs" ? { ...p, songs: newSongs } : p,
- ),
- };
- }
- // Otherwise, update the playlist in the tree
- const updatePlaylists = (
- items: (Playlist | PlaylistFolder)[],
- ): (Playlist | PlaylistFolder)[] => {
- return items.map((p) => {
- if (p.id === playlistId && "songs" in p) {
- return {
- ...p,
- songs: newSongs,
- };
- }
- if ("children" in p) {
- return { ...p, children: updatePlaylists(p.children) };
- }
- return p;
- });
- };
- return {
- ...prev,
- playlists: updatePlaylists(prev.playlists),
- };
- });
- };
-
- const moveSongToPlaylist = (
- songId: string,
- sourcePlaylistId: string | null,
- targetPlaylistId: string,
- ) => {
- setLibrary((prev) => {
- // Find the song first
- const song = prev.songs.find((s) => s.id === songId);
- if (!song) return prev;
-
- // Helper function to remove song from a playlist
- const removeSongFromPlaylist = (
- items: (Playlist | PlaylistFolder)[],
- playlistId: string | null,
- ): (Playlist | PlaylistFolder)[] => {
- if (playlistId === null || playlistId === "all-songs") {
- // Don't remove from "all-songs" or null (root songs)
- return items;
- }
-
- return items.map((p) => {
- if (p.id === playlistId && "songs" in p) {
- return {
- ...p,
- songs: p.songs.filter((s) => s.id !== songId),
- };
- }
- if ("children" in p) {
- return {
- ...p,
- children: removeSongFromPlaylist(p.children, playlistId),
- };
- }
- return p;
- });
- };
-
- // Helper function to add song to a playlist
- const addSongToPlaylist = (
- items: (Playlist | PlaylistFolder)[],
- playlistId: string,
- ): (Playlist | PlaylistFolder)[] => {
- return items.map((p) => {
- if (p.id === playlistId && "songs" in p) {
- // Don't add if song is already in playlist
- if (p.songs.some((s) => s.id === songId)) return p;
- return {
- ...p,
- songs: [...p.songs, song],
- };
- }
- if ("children" in p) {
- return {
- ...p,
- children: addSongToPlaylist(p.children, playlistId),
- };
- }
- return p;
- });
- };
-
- // Remove from source playlist (if specified and not "all-songs")
- let updatedPlaylists = prev.playlists;
- if (sourcePlaylistId && sourcePlaylistId !== "all-songs") {
- updatedPlaylists = removeSongFromPlaylist(
- updatedPlaylists,
- sourcePlaylistId,
- );
- }
-
- // Add to target playlist
- updatedPlaylists = addSongToPlaylist(updatedPlaylists, targetPlaylistId);
-
- return {
- ...prev,
- playlists: updatedPlaylists,
- };
- });
- };
-
- const moveToFolder = (
- itemId: string,
- folderId: string | null,
- beforeId?: string | null,
- ) => {
- setLibrary((prev) => {
- // Debug logs: log the intent of the move
- console.debug("[playlistManager] moveToFolder called with", {
- itemId,
- folderId,
- beforeId,
- });
- // Recursively find and remove the item from any depth
- let removedItem: Playlist | PlaylistFolder | null = null;
- const removeRecursive = (
- items: (Playlist | PlaylistFolder)[],
- ): (Playlist | PlaylistFolder)[] => {
- return items
- .filter((p) => {
- if (p.id === itemId) {
- removedItem = p;
- return false;
- }
- return true;
- })
- .map((p) => {
- if ("children" in p) {
- return { ...p, children: removeRecursive(p.children) };
- }
- return p;
- });
- };
-
- // Remove the item from the tree
- let newPlaylists = removeRecursive(prev.playlists);
- if (!removedItem) {
- // eslint-disable-next-line no-console
- console.warn("[playlistManager] moveToFolder: item not found", itemId);
- return prev;
- }
-
- // Prevent moving folder into itself or its descendants
- if (folderId && removedItem && "children" in removedItem) {
- const isDescendant = (
- items: (Playlist | PlaylistFolder)[],
- targetId: string,
- ): boolean => {
- for (const item of items) {
- if (item.id === targetId) return true;
- if ("children" in item && isDescendant(item.children, targetId))
- return true;
- }
- return false;
- };
- // Find the target folder
- const findFolder = (
- items: (Playlist | PlaylistFolder)[],
- id: string,
- ): PlaylistFolder | null => {
- for (const item of items) {
- if (item.id === id && "children" in item)
- return item as PlaylistFolder;
- if ("children" in item) {
- const found = findFolder(item.children, id);
- if (found) return found;
- }
- }
- return null;
- };
- const targetFolder = findFolder(newPlaylists, folderId);
- const removedFolder = removedItem as PlaylistFolder;
- if (targetFolder && isDescendant(removedFolder.children, folderId)) {
- return prev;
- }
- }
-
- // Recursively insert the item into the target folder or root
- const insertRecursive = (
- items: (Playlist | PlaylistFolder)[],
- parentId: string | null,
- newItem: Playlist | PlaylistFolder,
- beforeId: string | null,
- ): (Playlist | PlaylistFolder)[] => {
- if (parentId === null) {
- // Insert at root
- if (!beforeId) return [...items, newItem];
- const idx = items.findIndex((p) => p.id === beforeId);
- if (idx === -1) return [...items, newItem];
- return [...items.slice(0, idx), newItem, ...items.slice(idx)];
- }
- return items.map((p) => {
- if (p.id === parentId && "children" in p) {
- const children = p.children;
- if (!beforeId) {
- return { ...p, children: [...children, newItem] };
- }
- const idx = children.findIndex((c) => c.id === beforeId);
- if (idx === -1) {
- return { ...p, children: [...children, newItem] };
- }
- return {
- ...p,
- children: [
- ...children.slice(0, idx),
- newItem,
- ...children.slice(idx),
- ],
- };
- } else if ("children" in p) {
- return {
- ...p,
- children: insertRecursive(
- p.children,
- parentId,
- newItem,
- beforeId,
- ),
- };
- }
- return p;
- });
- };
-
- if (folderId) {
- // eslint-disable-next-line no-console
- console.debug(
- "[playlistManager] inserting into folder",
- folderId,
- "beforeId",
- beforeId,
- );
- newPlaylists = insertRecursive(
- newPlaylists,
- folderId,
- removedItem,
- beforeId || null,
- );
- } else {
- // eslint-disable-next-line no-console
- console.debug(
- "[playlistManager] inserting into root beforeId",
- beforeId,
- );
- newPlaylists = insertRecursive(
- newPlaylists,
- null,
- removedItem,
- beforeId || null,
- );
- }
-
- return { ...prev, playlists: newPlaylists };
- });
- };
-
- const toggleFavorite = (songId: string) => {
- const isFav = library.favorites.includes(songId);
- if (isFav) removeFromFavorites(songId);
- else addToFavorites(songId);
- return !isFav;
- };
-
- const isFavorited = (songId: string) => {
- return library.favorites.includes(songId);
- };
-
- const getFavoriteSongs = () => {
- return library.songs.filter((s) => library.favorites.includes(s.id));
- };
-
- const searchSongs = (query: string) => {
- setSearchQuery(query);
- if (!query.trim()) return library.songs;
- return library.songs.filter(
- (s) =>
- s.title.toLowerCase().includes(query.toLowerCase()) ||
- s.artist.toLowerCase().includes(query.toLowerCase()),
- );
- };
-
- const getSearchResults = () => {
- return searchSongs(searchQuery);
- };
-
- const navigateToArtist = (artist: string) => {
- setPlayerState((prev: any) => ({
- ...prev,
- view: "artist",
- currentArtist: artist,
- }));
- };
-
- const navigateToAlbum = (album: string) => {
- setPlayerState((prev: any) => ({
- ...prev,
- view: "album",
- currentAlbum: album,
- }));
- };
-
- const navigateToHome = () => {
- setPlayerState((prev: any) => ({
- ...prev,
- view: "home",
- currentArtist: undefined,
- currentAlbum: undefined,
- }));
- };
-
- const navigateToSongs = () => {
- setPlayerState((prev: any) => ({
- ...prev,
- view: "songs",
- currentArtist: undefined,
- currentAlbum: undefined,
- }));
- };
-
- // Export playlist to JSON or M3U format
- const exportPlaylist = (
- playlist: Playlist,
- format: "json" | "m3u" = "json",
- ) => {
- try {
- let content: string;
- let filename: string;
- let mimeType: string;
-
- if (format === "json") {
- // Export as JSON with full metadata
- const exportData = {
- name: playlist.name,
- created: new Date().toISOString(),
- songs: playlist.songs.map((song) => ({
- title: song.title,
- artist: song.artist,
- album: song.album,
- duration: song.duration,
- // Don't include URL or file data for privacy/size reasons
- })),
- };
- content = JSON.stringify(exportData, null, 2);
- filename = `${playlist.name.replace(/[^a-z0-9]/gi, "_")}.json`;
- mimeType = "application/json";
- } else {
- // Export as M3U playlist
- content = "#EXTM3U\n";
- playlist.songs.forEach((song) => {
- content += `#EXTINF:${Math.floor(song.duration)},${song.artist} - ${
- song.title
- }\n`;
- content += `# ${song.album}\n`;
- });
- filename = `${playlist.name.replace(/[^a-z0-9]/gi, "_")}.m3u`;
- mimeType = "audio/x-mpegurl";
- }
-
- // Create and download file
- const blob = new Blob([content], { type: mimeType });
- const url = URL.createObjectURL(blob);
- const a = document.createElement("a");
- a.href = url;
- a.download = filename;
- document.body.appendChild(a);
- a.click();
- document.body.removeChild(a);
- URL.revokeObjectURL(url);
-
- toast.success(
- i18n.t("playlist.exportedAs", {
- name: playlist.name,
- format: format.toUpperCase(),
- }),
- );
- } catch (error) {
- console.error("Export failed:", error);
- toast.error(
- i18n.t("playlist.exportFailed") +
- " " +
- (error instanceof Error
- ? error.message
- : i18n.t("common.unknownError")),
- );
- }
- };
-
- // Import playlist from JSON file
- const importPlaylist = (file: File) => {
- return new Promise((resolve, reject) => {
- const reader = new FileReader();
-
- reader.onload = (e) => {
- try {
- const content = e.target?.result as string;
-
- if (file.name.endsWith(".json")) {
- // Parse JSON playlist
- const playlistData = JSON.parse(content);
-
- if (!playlistData.name || !Array.isArray(playlistData.songs)) {
- throw new Error(i18n.t("playlist.invalidFormat"));
- }
-
- // Create new playlist with imported metadata (songs will need to be matched/re-added)
- const newPlaylist: Playlist = {
- id: Date.now().toString(),
- name: `${playlistData.name} (Imported)`,
- songs: [], // Empty for now, user will need to add songs manually
- };
-
- // Add the playlist
- createPlaylist(newPlaylist.name, newPlaylist.songs);
-
- toast.success(
- i18n.t("playlist.importedPlaylist", {
- name: playlistData.name,
- count: playlistData.songs.length,
- }),
- );
- toast.info(i18n.t("playlist.noteManualAdd"));
- resolve();
- } else if (
- file.name.endsWith(".m3u") ||
- file.name.endsWith(".m3u8")
- ) {
- // Parse M3U playlist
- const lines = content.split("\n").filter((line) => line.trim());
- const songs: Array<{ title: string; artist: string }> = [];
-
- for (let i = 0; i < lines.length; i++) {
- const line = lines[i].trim();
- if (line.startsWith("#EXTINF:")) {
- // Extract artist and title from M3U format
- const match = line.match(/#EXTINF:\d+,(.+?) - (.+)/);
- if (match) {
- songs.push({
- artist: match[1],
- title: match[2],
- });
- }
- }
- }
-
- // Create playlist
- const playlistName = file.name.replace(/\.(m3u|m3u8)$/i, "");
- createPlaylist(`${playlistName} (Imported)`, []);
-
- toast.success(
- i18n.t("playlist.importedM3u", { count: songs.length }),
- );
- toast.info(i18n.t("playlist.noteManualAdd"));
- resolve();
- } else {
- throw new Error(i18n.t("playlist.unsupportedFormat"));
- }
- } catch (error) {
- console.error("Import failed:", error);
- const message =
- error instanceof Error
- ? error.message
- : i18n.t("playlist.failedToParse");
- toast.error(i18n.t("playlist.importFailedWithMessage", { message }));
- reject(error);
- }
- };
-
- reader.onerror = () => {
- const error = new Error(i18n.t("playlist.failedToReadFile"));
- toast.error(i18n.t("playlist.failedToReadFile"));
- reject(error);
- };
-
- reader.readAsText(file);
- });
- };
-
- return {
- prepareSongsForPlaylist,
- createPlaylist,
- createFolder,
- removePlaylist,
- addToFavorites,
- removeFromFavorites,
- addToPlaylist,
- reorderPlaylistSongs,
- moveSongToPlaylist,
- moveToFolder,
- toggleFavorite,
- isFavorited,
- getFavoriteSongs,
- searchSongs,
- getSearchResults,
- navigateToHome,
- navigateToArtist,
- navigateToAlbum,
- navigateToSongs,
- exportPlaylist,
- importPlaylist,
- };
-};
diff --git a/Build/src/helpers/refloWavHelper.ts b/Build/src/helpers/refloWavHelper.ts
deleted file mode 100644
index 7c3a5e6..0000000
--- a/Build/src/helpers/refloWavHelper.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import initReflo, * as reflo from "@flo-audio/reflo/reflo.js";
-
-let refloInitialized = false;
-
-async function ensureRefloInitialized() {
- if (!refloInitialized) {
- await initReflo(); // Initialize WASM module
- refloInitialized = true;
- }
-}
-
-/**
- * Decode a .flo file to WAV format using @flo-audio/reflo
- * This is used for Safari which needs standard formats for background playback
- *
- * @param floData - ArrayBuffer containing flo audio data
- * @returns Uint8Array containing complete WAV file (headers + audio data)
- */
-export async function decodeFloToWav(
- floData: ArrayBuffer,
-): Promise {
- await ensureRefloInitialized();
-
- const uint8Flo = new Uint8Array(floData);
-
- // reflo.decode_flo_to_wav returns a complete WAV file
- const wavData = reflo.decode_flo_to_wav(uint8Flo);
-
- return wavData;
-}
-
-export { initReflo, ensureRefloInitialized };
diff --git a/Build/src/helpers/safariHelper.ts b/Build/src/helpers/safariHelper.ts
deleted file mode 100644
index 5ff9253..0000000
--- a/Build/src/helpers/safariHelper.ts
+++ /dev/null
@@ -1,233 +0,0 @@
-/**
- * Safari/WebKit background audio helper
- * Safari requires an actual element in the DOM to play audio in the background
- * AudioContext and new Audio() don't work in background on Safari
- */
-
-/**
- * Detect if the current browser is Safari or WebKit-based
- */
-export function isSafari(): boolean {
- const ua = navigator.userAgent.toLowerCase();
- const isSafari =
- ua.includes("safari") && !ua.includes("chrome") && !ua.includes("android");
- const isWebKit = ua.includes("applewebkit") && !ua.includes("chrome");
-
- return isSafari || isWebKit;
-}
-
-/**
- * Safari Audio Manager
- * Manages a element that stays in sync with the main audio
- * This allows background playback on Safari
- */
-export class SafariAudioManager {
- private audioElement: HTMLAudioElement | null = null;
- private isEnabled: boolean = false;
-
- constructor() {
- this.isEnabled = isSafari();
-
- if (this.isEnabled) {
- this.initializeAudioElement();
- }
- }
-
- /**
- * Create and configure the audio element
- */
- private initializeAudioElement(): void {
- // Create audio element
- this.audioElement = document.createElement("audio");
- this.audioElement.crossOrigin = "anonymous";
- this.audioElement.preload = "auto";
-
- // Start muted - will be unmuted if used as primary audio element
- this.audioElement.volume = 0;
- this.audioElement.muted = true;
-
- // Make it invisible but present in DOM
- this.audioElement.style.position = "fixed";
- this.audioElement.style.opacity = "0";
- this.audioElement.style.pointerEvents = "none";
- this.audioElement.style.width = "1px";
- this.audioElement.style.height = "1px";
- this.audioElement.style.bottom = "0";
- this.audioElement.style.left = "0";
-
- // Add to DOM - required for Safari background playback
- document.body.appendChild(this.audioElement);
-
- console.log(
- "[Safari Audio] Initialized audio element for background playback",
- );
- }
-
- /**
- * Check if Safari audio manager is enabled
- */
- public isActive(): boolean {
- return this.isEnabled && this.audioElement !== null;
- }
-
- /**
- * Set the audio source
- */
- public setSrc(src: string): void {
- if (!this.audioElement) return;
-
- try {
- // Only set src if it's a valid URL (not empty, not about:blank, and not indexeddb://)
- // IndexedDB URLs are internal references that need to be resolved to blob URLs first
- if (
- src &&
- !src.includes("about:blank") &&
- !src.startsWith("indexeddb://")
- ) {
- this.audioElement.src = src;
- console.log("[Safari Audio] Set source:", src.substring(0, 50) + "...");
- } else if (src.startsWith("indexeddb://")) {
- console.log(
- "[Safari Audio] Skipping IndexedDB URL - waiting for blob URL",
- );
- }
- } catch (error) {
- console.error("[Safari Audio] Failed to set src:", error);
- }
- }
-
- /**
- * Play the audio
- */
- public async play(): Promise {
- if (!this.audioElement) return;
-
- // Don't try to play if there's no valid source
- if (
- !this.audioElement.src ||
- this.audioElement.src.includes("about:blank")
- ) {
- console.warn("[Safari Audio] Cannot play - no valid source");
- return;
- }
-
- // Wait for the element to be ready if needed
- if (this.audioElement.readyState < 2) {
- console.log("[Safari Audio] Waiting for source to load...");
- const element = this.audioElement; // Capture for closure
- await new Promise((resolve, reject) => {
- const timeout = setTimeout(() => {
- console.warn("[Safari Audio] Timeout waiting for source to load");
- resolve(); // Resolve anyway to prevent hanging
- }, 2000);
-
- const onReady = () => {
- clearTimeout(timeout);
- element.removeEventListener("loadeddata", onReady);
- element.removeEventListener("canplay", onReady);
- element.removeEventListener("error", onError);
- resolve();
- };
-
- const onError = (e: Event) => {
- clearTimeout(timeout);
- element.removeEventListener("loadeddata", onReady);
- element.removeEventListener("canplay", onReady);
- element.removeEventListener("error", onError);
- console.error("[Safari Audio] Error loading source:", e);
- reject(e);
- };
-
- element.addEventListener("loadeddata", onReady);
- element.addEventListener("canplay", onReady);
- element.addEventListener("error", onError);
- });
- }
-
- try {
- await this.audioElement.play();
- console.log("[Safari Audio] Playing");
- } catch (error) {
- console.error("[Safari Audio] Failed to play:", error);
- }
- }
-
- /**
- * Pause the audio
- */
- public pause(): void {
- if (!this.audioElement) return;
-
- try {
- this.audioElement.pause();
- console.log("[Safari Audio] Paused");
- } catch (error) {
- console.error("[Safari Audio] Failed to pause:", error);
- }
- }
-
- /**
- * Set the volume
- */
- public setVolume(volume: number): void {
- if (!this.audioElement) return;
-
- try {
- this.audioElement.volume = Math.max(0, Math.min(1, volume));
- } catch (error) {
- console.error("[Safari Audio] Failed to set volume:", error);
- }
- }
-
- /**
- * Seek to a specific time
- */
- public seek(time: number): void {
- if (!this.audioElement) return;
-
- try {
- this.audioElement.currentTime = time;
- } catch (error) {
- console.error("[Safari Audio] Failed to seek:", error);
- }
- }
-
- /**
- * Set playback rate (for tempo/pitch)
- */
- public setPlaybackRate(rate: number): void {
- if (!this.audioElement) return;
-
- try {
- this.audioElement.playbackRate = rate;
- } catch (error) {
- console.error("[Safari Audio] Failed to set playback rate:", error);
- }
- }
-
- /**
- * Get the audio element (for advanced usage)
- */
- public getElement(): HTMLAudioElement | null {
- return this.audioElement;
- }
-
- /**
- * Clean up the audio element
- */
- public destroy(): void {
- if (!this.audioElement) return;
-
- try {
- this.audioElement.pause();
- this.audioElement.src = "";
- if (this.audioElement.parentNode) {
- this.audioElement.parentNode.removeChild(this.audioElement);
- }
- this.audioElement = null;
- console.log("[Safari Audio] Destroyed");
- } catch (error) {
- console.error("[Safari Audio] Failed to destroy:", error);
- }
- }
-}
diff --git a/Build/src/helpers/shuffleManager.ts b/Build/src/helpers/shuffleManager.ts
deleted file mode 100644
index f6748cc..0000000
--- a/Build/src/helpers/shuffleManager.ts
+++ /dev/null
@@ -1,205 +0,0 @@
-import { MutableRefObject } from "react";
-
-// Smart shuffle algorithm using Fisher-Yates shuffle with play history awareness
-// (this was fun to research and implement!)
-export const getSmartShuffledSong = (
- availableSongs: Song[],
- currentSongId: string,
- playHistory: Map,
-): Song | null => {
- if (availableSongs.length === 0) return null;
-
- const now = Date.now();
- const candidates = availableSongs.filter((song) => song.id !== currentSongId);
-
- if (candidates.length === 0) return null;
-
- // For very small playlists, ensure better variety by excluding recently played songs
- let filteredCandidates = candidates;
- if (availableSongs.length <= 3) {
- // Get recently played songs (within last 30 minutes for small playlists)
- const recentThreshold = now - 30 * 60 * 1000; // 30 minutes
- const recentlyPlayedIds = new Set();
-
- for (const [songId, history] of playHistory.entries()) {
- if (history.lastPlayed > recentThreshold) {
- recentlyPlayedIds.add(songId);
- }
- }
-
- // Filter out recently played songs, but keep at least one option
- filteredCandidates = candidates.filter(
- (song) => !recentlyPlayedIds.has(song.id),
- );
- if (filteredCandidates.length === 0) {
- // If all candidates were recently played, use the least recently played one
- filteredCandidates = candidates.sort((a, b) => {
- const aHistory = playHistory.get(a.id);
- const bHistory = playHistory.get(b.id);
- const aTime = aHistory?.lastPlayed || 0;
- const bTime = bHistory?.lastPlayed || 0;
- return aTime - bTime; // Oldest first
- });
- filteredCandidates = filteredCandidates.slice(0, 1); // Take only the least recent
- }
- }
-
- // Calculate weights based on recency and play frequency
- const songsWithWeights = filteredCandidates.map((song) => {
- const history = playHistory.get(song.id);
- let weight = 100; // Base weight
-
- if (history) {
- const timeSinceLastPlayed = now - history.lastPlayed;
- const hoursAgo = timeSinceLastPlayed / (1000 * 60 * 60);
-
- // Reduce weight based on recency (exponential decay)
- if (hoursAgo < 24) {
- weight *= Math.pow(0.5, Math.max(0, 4 - hoursAgo)); // Heavy penalty for recent plays
- }
-
- // Slightly reduce weight for frequently played songs
- weight *= Math.max(0.3, 1 - history.playCount * 0.1);
- }
-
- return { song, weight };
- });
-
- // If no candidates after filtering, fall back to original candidates
- if (songsWithWeights.length === 0) {
- const fallbackSong =
- candidates[Math.floor(Math.random() * candidates.length)];
- return fallbackSong;
- }
-
- // Weighted random selection using reservoir sampling
- const totalWeight = songsWithWeights.reduce(
- (sum, item) => sum + item.weight,
- 0,
- );
- let randomValue = Math.random() * totalWeight;
-
- for (const item of songsWithWeights) {
- randomValue -= item.weight;
- if (randomValue <= 0) {
- return item.song;
- }
- }
-
- // Fallback to first candidate
- return songsWithWeights[0].song;
-};
-
-// Next song cache manager
-export const createNextSongManager = (
- nextSongCacheRef: MutableRefObject,
- nextSongCacheValidRef: MutableRefObject,
-) => {
- let lastCacheInvalidation = 0;
- const CACHE_INVALIDATION_THROTTLE = 500; // Throttle invalidations to max once per 500ms
-
- // Function to determine and cache the next song
- const getAndCacheNextSong = (
- playerStateRef: MutableRefObject,
- settingsRef: MutableRefObject,
- playHistoryRef: MutableRefObject<
- Map
- >,
- ): Song | null => {
- if (
- !playerStateRef.current.currentPlaylist ||
- !playerStateRef.current.currentSong
- ) {
- return null;
- }
-
- // If we have a valid cached next song, return it
- if (nextSongCacheValidRef.current && nextSongCacheRef.current) {
- return nextSongCacheRef.current;
- }
-
- const songs = playerStateRef.current.currentPlaylist.songs;
- const currentIndex = songs.findIndex(
- (s: { id: any }) => s.id === playerStateRef.current.currentSong!.id,
- );
- let nextSong: Song | null = null;
-
- if (playerStateRef.current.shuffle) {
- const available = songs.filter(
- (s: { id: any }) => s.id !== playerStateRef.current.currentSong!.id,
- );
- if (available.length > 0) {
- if (settingsRef.current.smartShuffle) {
- // Use improved smart shuffle algorithm
- nextSong = getSmartShuffledSong(
- available,
- playerStateRef.current.currentSong!.id,
- playHistoryRef.current,
- );
- if (!nextSong) {
- nextSong = available[Math.floor(Math.random() * available.length)];
- }
- } else {
- // Use regular shuffle
- const randomIndex = Math.floor(Math.random() * available.length);
- nextSong = available[randomIndex];
- }
- }
- } else {
- if (currentIndex < songs.length - 1) {
- nextSong = songs[currentIndex + 1];
- } else if (playerStateRef.current.repeat === "all") {
- nextSong = songs[0];
- }
- }
-
- // Cache the result
- nextSongCacheRef.current = nextSong;
- nextSongCacheValidRef.current = true;
-
- return nextSong;
- };
-
- // Throttled function to invalidate the next song cache
- const invalidateNextSongCache = (force = false) => {
- const now = Date.now();
- if (force || now - lastCacheInvalidation > CACHE_INVALIDATION_THROTTLE) {
- nextSongCacheRef.current = null;
- nextSongCacheValidRef.current = false;
- lastCacheInvalidation = now;
- }
- };
-
- // Function to update play history
- const updatePlayHistory = (
- playHistoryRef: MutableRefObject<
- Map
- >,
- songId: string,
- ) => {
- const now = Date.now();
- const currentHistory = playHistoryRef.current.get(songId) || {
- lastPlayed: 0,
- playCount: 0,
- };
-
- playHistoryRef.current.set(songId, {
- lastPlayed: now,
- playCount: currentHistory.playCount + 1,
- });
-
- // Clean up old entries (older than 7 days)
- const weekAgo = now - 7 * 24 * 60 * 60 * 1000;
- for (const [id, history] of playHistoryRef.current.entries()) {
- if (history.lastPlayed < weekAgo) {
- playHistoryRef.current.delete(id);
- }
- }
- };
-
- return {
- getAndCacheNextSong,
- invalidateNextSongCache,
- updatePlayHistory,
- };
-};
diff --git a/Build/src/helpers/themeLoader.tsx b/Build/src/helpers/themeLoader.tsx
deleted file mode 100644
index a2a403a..0000000
--- a/Build/src/helpers/themeLoader.tsx
+++ /dev/null
@@ -1,356 +0,0 @@
-import React, {
- useState,
- useEffect,
- createContext,
- useContext,
- useCallback,
-} from "react";
-import { broadcastThemeCSS } from "../components/Miniplayer";
-import { getAllThemeJsonFiles } from "./themeMetadata";
-
-// ----------------------
-// Types
-// ----------------------
-export interface ThemeMetadata {
- name: string;
- author: string;
- description: string;
- version: string;
- cssFile: string;
-}
-
-interface ThemeContextProps {
- themes: ThemeMetadata[];
- currentTheme: ThemeMetadata | null;
- isLoading: boolean;
- error: string | null;
- setTheme: (themeName: string) => Promise;
-}
-
-const ThemeContext = createContext({
- themes: [],
- currentTheme: null,
- isLoading: false,
- error: null,
- setTheme: async () => {},
-});
-
-interface ThemeLoaderProps {
- defaultTheme: string;
- children: React.ReactNode;
- onThemeChange?: (theme: ThemeMetadata) => void;
-}
-
-// ----------------------
-// Global themes storage for console access
-// ----------------------
-let globalThemes: ThemeMetadata[] = [];
-
-// ----------------------
-// Import theme CSS and images
-// ----------------------
-const themeCssFiles = import.meta.glob("../themes/**/*.theme.css", {
- query: "?raw",
- import: "default",
- eager: false,
-});
-const themeImageFiles = import.meta.glob(
- "../themes/**/*.{jpg,jpeg,png,gif,webp,svg}",
- { eager: true },
-);
-
-// ----------------------
-// ThemeLoader Component
-// ----------------------
-export const ThemeLoader: React.FC = ({
- defaultTheme,
- children,
- onThemeChange,
-}) => {
- const [themes, setThemes] = useState([]);
- const [currentTheme, setCurrentTheme] = useState(null);
- const [isLoading, setIsLoading] = useState(true);
- const [error, setError] = useState(null);
-
- // ----------------------
- // Validate theme metadata
- // ----------------------
- const validateThemeMetadata = (
- meta: any,
- path: string,
- ): ThemeMetadata | null => {
- if (!meta || typeof meta !== "object") {
- console.warn(`Theme file ${path}: Invalid metadata format`);
- return null;
- }
-
- // Skip icon-only theme files (they only have 'icons' object, no cssFile)
- if (meta.icons && !meta.cssFile && !meta.name) {
- // This is an icon-only theme file, not a color theme
- return null;
- }
-
- // Skip wallpaper theme files (they only have 'wallpaper' object, no cssFile)
- if (meta.wallpaper && !meta.cssFile && !meta.name) {
- // This is a wallpaper theme file, not a color theme
- return null;
- }
-
- const required = ["name", "author", "description", "version", "cssFile"];
- for (const field of required) {
- if (!meta[field] || typeof meta[field] !== "string") {
- console.warn(`Theme file ${path}: Missing or invalid field "${field}"`);
- return null;
- }
- }
-
- return meta as ThemeMetadata;
- };
-
- // ----------------------
- // Load themes on mount
- // ----------------------
- useEffect(() => {
- const loadThemes = async () => {
- try {
- setIsLoading(true);
- setError(null);
-
- const loadedThemes: ThemeMetadata[] = [];
-
- // Get all theme JSON files using the unified loader
- const themeJsonMap = await getAllThemeJsonFiles();
-
- for (const [path, meta] of themeJsonMap.entries()) {
- const validatedTheme = validateThemeMetadata(meta, path);
- if (validatedTheme) {
- // Verify CSS file exists
- const cssExists = Object.keys(themeCssFiles).some((cssPath) =>
- cssPath.endsWith(validatedTheme.cssFile),
- );
-
- if (cssExists) {
- loadedThemes.push(validatedTheme);
- } else {
- console.warn(
- `Theme "${validatedTheme.name}": CSS file "${validatedTheme.cssFile}" not found`,
- );
- }
- }
- }
-
- if (loadedThemes.length === 0) {
- throw new Error("No valid themes found");
- }
-
- setThemes(loadedThemes);
- globalThemes = loadedThemes; // Update global variable for console access
-
- // Load initial theme
- const storedThemeName =
- localStorage.getItem("selected-color-theme") || defaultTheme;
- const initialTheme =
- loadedThemes.find((theme) => theme.name === storedThemeName) ||
- loadedThemes.find((theme) => theme.name === defaultTheme) ||
- loadedThemes[0]; // Fallback to first available
-
- if (initialTheme) {
- await applyTheme(initialTheme);
- // Broadcast theme immediately after loading
- setTimeout(() => {
- broadcastThemeCSS();
- }, 300);
- }
- } catch (err) {
- const errorMessage =
- err instanceof Error ? err.message : "Failed to load themes";
- setError(errorMessage);
- console.error("Theme loading error:", err);
- } finally {
- setIsLoading(false);
- }
- };
-
- loadThemes();
- }, [defaultTheme]);
-
- // ----------------------
- // Apply theme: dynamically import CSS and inject as style tag
- // ----------------------
- const applyTheme = useCallback(
- async (theme: ThemeMetadata): Promise => {
- try {
- // Find the matching CSS file
- const cssPath = Object.keys(themeCssFiles).find((path) =>
- path.endsWith(theme.cssFile),
- );
-
- if (!cssPath) {
- throw new Error(`CSS file not found: ${theme.cssFile}`);
- }
-
- // Remove ALL existing theme stylesheets
- const existingStyles = document.querySelectorAll(
- 'style[id^="theme-stylesheet"], link[id^="theme-stylesheet"]',
- );
- existingStyles.forEach((style) => style.remove());
-
- // Load the CSS module to get the CSS content
- const cssModule = await (
- themeCssFiles[cssPath] as () => Promise
- )();
-
- // Verify the content is a string
- if (!cssModule || typeof cssModule !== "string") {
- throw new Error(
- `Invalid CSS content for ${cssPath}: ${typeof cssModule}`,
- );
- }
-
- // Process CSS to replace image URLs with Vite asset URLs
- let processedCss = cssModule;
- const themeDir = cssPath.replace(/\/[^\/]+$/, ""); // Get directory containing the CSS file
-
- // Replace relative image URLs with imported asset URLs
- processedCss = processedCss.replace(
- /url\(['"]?([^'"\)]+)['"]?\)/g,
- (match, url) => {
- // Skip data URIs and absolute URLs
- if (
- url.startsWith("data:") ||
- url.startsWith("http") ||
- url.startsWith("/")
- ) {
- return match;
- }
-
- // Find the corresponding imported image
- const imagePath = `${themeDir}/${url}`;
- const imageModule = themeImageFiles[imagePath];
-
- if (imageModule) {
- return `url('${(imageModule as any).default}')`;
- }
-
- // If not found, return original (might be handled by other means)
- console.warn(`Image not found in imports: ${imagePath}`);
- return match;
- },
- );
-
- console.log("Theme loaded");
-
- // Create a style element and inject the CSS
- const styleElement = document.createElement("style");
- styleElement.id = `theme-stylesheet-${theme.name}`;
- styleElement.textContent = processedCss;
-
- // Use requestAnimationFrame to sync with browser rendering
- await new Promise((resolve) =>
- requestAnimationFrame(() => setTimeout(resolve, 50)),
- );
-
- // Append to head
- document.head.appendChild(styleElement);
-
- // Wait for styles to be applied
- await new Promise((resolve) => {
- requestAnimationFrame(() => {
- // Force a reflow to ensure styles are applied
- document.documentElement.offsetHeight;
- setTimeout(resolve, 100); // Additional delay for CSS variables to propagate
- });
- });
-
- // Update state after successful injection
- setCurrentTheme(theme);
- localStorage.setItem("selected-color-theme", theme.name);
-
- // Call optional callback
- onThemeChange?.(theme);
-
- setError(null);
-
- console.log(`Successfully applied theme: ${theme.name}`);
-
- // Update meta theme color
- const themeColor = getComputedStyle(document.documentElement)
- .getPropertyValue("--themecolor2")
- .trim();
-
- let meta = document.querySelector(
- 'meta[name="theme-color"]',
- ) as HTMLMetaElement | null;
- if (!meta) {
- meta = document.createElement("meta");
- meta.name = "theme-color";
- document.head.appendChild(meta);
- }
- meta.content = themeColor;
-
- // Wait a bit more and then broadcast theme CSS updates
- setTimeout(() => {
- broadcastThemeCSS();
- }, 200); // Additional delay to ensure all CSS is fully applied
- } catch (err) {
- const errorMessage =
- err instanceof Error ? err.message : "Failed to apply theme";
- setError(errorMessage);
- console.error("Theme application error:", err);
- throw err; // Re-throw for caller handling
- }
- },
- [onThemeChange],
- );
-
- // ----------------------
- // Set theme by name
- // ----------------------
- const setTheme = useCallback(
- async (themeName: string): Promise => {
- const theme = themes.find((t) => t.name === themeName);
- if (!theme) {
- throw new Error(`Theme "${themeName}" not found`);
- }
-
- await applyTheme(theme);
- },
- [themes, applyTheme],
- );
-
- const value: ThemeContextProps = {
- themes,
- currentTheme,
- isLoading,
- error,
- setTheme,
- };
-
- // ----------------------
- // Expose themes globally for console access
- // ----------------------
- useEffect(() => {
- if (typeof window !== "undefined") {
- (window as any).themeLoader = {
- getAllThemes: () => globalThemes,
- getCurrentTheme: () => currentTheme,
- setTheme: setTheme,
- };
- }
- }, [themes, currentTheme, setTheme]);
-
- return (
- {children}
- );
-};
-
-// ----------------------
-// Custom Hook
-// ----------------------
-export const useThemeLoader = () => {
- const context = useContext(ThemeContext);
- if (!context) {
- throw new Error("useThemeLoader must be used within a ThemeProvider");
- }
- return context;
-};
diff --git a/Build/src/helpers/themeMetadata.ts b/Build/src/helpers/themeMetadata.ts
deleted file mode 100644
index 10907a9..0000000
--- a/Build/src/helpers/themeMetadata.ts
+++ /dev/null
@@ -1,112 +0,0 @@
-/**
- * Unified theme metadata loader
- * Provides a single source of truth for loading theme JSON files
- */
-
-// Import all theme JSON files eagerly
-const themeJsonFiles = import.meta.glob("../themes/**/*.theme.json", {
- eager: true,
-});
-
-// Cache for parsed theme JSON to avoid re-parsing
-const themeJsonCache = new Map();
-
-/**
- * Load and parse a theme JSON file by path
- * @param themePath - The path to the theme JSON file (e.g., '../themes/Blue/Blue.theme.json')
- * @returns The parsed JSON object or null if not found/invalid
- */
-export async function loadThemeJson(themePath: string): Promise {
- // Normalize the path
- const normalizedPath = themePath.replace(/\\/g, "/");
-
- // Check cache first
- if (themeJsonCache.has(normalizedPath)) {
- return themeJsonCache.get(normalizedPath);
- }
-
- // Try to find the module
- const module = themeJsonFiles[normalizedPath];
-
- if (!module) {
- console.warn(`Theme JSON not found at ${normalizedPath}`);
- return null;
- }
-
- try {
- const json = (module as any).default || module;
- themeJsonCache.set(normalizedPath, json);
- return json;
- } catch (error) {
- console.warn(`Failed to parse theme JSON at ${normalizedPath}`, error);
- return null;
- }
-}
-
-/**
- * Load theme JSON by converting an icon/theme file path to its corresponding JSON path
- * @param sourcePath - Path to an icon or theme file (e.g., '../themes/Blue/Blue.icons.ts')
- * @returns The parsed JSON object or null if not found/invalid
- */
-export async function loadThemeJsonFromSourcePath(
- sourcePath: string,
-): Promise {
- // Convert icons/theme/wallpaper path to theme.json path
- // e.g., ../themes/Blue/Blue.icons.ts -> ../themes/Blue/Blue.theme.json
- // e.g., ../themes/Blue/Blue.theme.css -> ../themes/Blue/Blue.theme.json
- // e.g., ../themes/Wallpapers/Static/Static.wallpaper.tsx -> ../themes/Wallpapers/Static/Static.theme.json
- const themePath = sourcePath
- .replace(/\.icons\.(ts|tsx)$/, ".theme.json")
- .replace(/\.theme\.(css|scss|sass)$/, ".theme.json")
- .replace(/\.wallpaper\.(ts|tsx)$/, ".theme.json");
-
- return loadThemeJson(themePath);
-}
-
-/**
- * Get all available theme JSON files
- * @returns Map of paths to parsed JSON objects
- */
-export async function getAllThemeJsonFiles(): Promise> {
- const results = new Map();
-
- for (const [path, module] of Object.entries(themeJsonFiles)) {
- try {
- const json = (module as any).default || module;
- results.set(path, json);
- } catch (error) {
- console.warn(`Failed to parse theme JSON at ${path}`, error);
- }
- }
-
- return results;
-}
-
-/**
- * Find a theme JSON file by theme name
- * @param themeName - The name of the theme to find
- * @returns The parsed JSON object or null if not found
- */
-export async function findThemeJsonByName(
- themeName: string,
-): Promise<{ path: string; json: any } | null> {
- for (const [path, module] of Object.entries(themeJsonFiles)) {
- try {
- const json = (module as any).default || module;
- if (json.name === themeName) {
- return { path, json };
- }
- } catch (error) {
- console.warn(`Failed to parse theme JSON at ${path}`, error);
- }
- }
-
- return null;
-}
-
-/**
- * Clear the theme JSON cache
- */
-export function clearThemeJsonCache(): void {
- themeJsonCache.clear();
-}
diff --git a/Build/src/helpers/themeMode.ts b/Build/src/helpers/themeMode.ts
deleted file mode 100644
index b88af9b..0000000
--- a/Build/src/helpers/themeMode.ts
+++ /dev/null
@@ -1,210 +0,0 @@
-import { broadcastThemeCSS } from "../components/Miniplayer";
-
-export type ThemeMode = "light" | "dark" | "auto";
-
-export function updateMetaThemeColor(): void {
- // Delay to allow CSS changes to propagate
- requestAnimationFrame(() => {
- const themeColor = getComputedStyle(document.documentElement)
- .getPropertyValue("--themecolor2")
- .trim();
-
- let meta = document.querySelector(
- 'meta[name="theme-color"]',
- ) as HTMLMetaElement | null;
- if (!meta) {
- meta = document.createElement("meta");
- meta.name = "theme-color";
- document.head.appendChild(meta);
- }
- meta.content = themeColor;
-
- // Broadcast theme changes for PiP windows
- setTimeout(() => {
- broadcastThemeCSS();
- }, 100);
- });
-}
-
-/**
- * Switch to dark mode by adding the "dark" class to document.body.
- */
-export function switchToDarkMode(): void {
- // Clear any auto mode listener if present.
- if (currentMediaQuery) {
- currentMediaQuery.onchange = null;
- currentMediaQuery = null;
- }
- document.documentElement.classList.add("dark");
- updateMetaThemeColor();
-}
-
-/**
- * Switch to light mode by removing the "dark" class from document.body.
- */
-export function switchToLightMode(): void {
- // Clear any auto mode listener if present.
- if (currentMediaQuery) {
- currentMediaQuery.onchange = null;
- currentMediaQuery = null;
- }
- document.documentElement.classList.remove("dark");
- updateMetaThemeColor();
-}
-
-function updateTheme(darkPreferred: boolean): void {
- if (darkPreferred) {
- document.documentElement.classList.add("dark");
- } else {
- document.documentElement.classList.remove("dark");
- }
- updateMetaThemeColor();
-}
-
-let currentMediaQuery: MediaQueryList | null = null;
-
-/**
- * Switch to auto mode. This function immediately applies the user's color scheme preference
- * and listens for system preference changes to update the theme automatically.
- * It uses the onchange property instead of addEventListener to avoid TypeScript issues.
- */
-export function switchToAutoMode(): void {
- if (currentMediaQuery) {
- currentMediaQuery.onchange = null;
- }
- const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
- mediaQuery.onchange = (e: MediaQueryListEvent) => {
- updateTheme(e.matches);
- };
- currentMediaQuery = mediaQuery;
- updateTheme(mediaQuery.matches);
-}
-
-/**
- * Returns the current theme mode:
- * - "auto" if auto mode is enabled,
- * - "dark" if the document element has the "dark" class,
- * - "light" otherwise.
- */
-export function getCurrentThemeMode(): ThemeMode {
- if (currentMediaQuery) {
- return "auto";
- }
- return document.documentElement.classList.contains("dark") ? "dark" : "light";
-}
-
-/**
- * Retrieves all CSS variables for the current theme as a string.
- */
-export function getCurrentThemeCSS(): string {
- const styles = getComputedStyle(document.documentElement);
- const cssVariables: string[] = [];
-
- // Method 1: Use getComputedStyle iteration
- for (let i = 0; i < styles.length; i++) {
- const name = styles[i];
- if (name.startsWith("--")) {
- const value = styles.getPropertyValue(name).trim();
- if (value) {
- // Only include variables with values
- cssVariables.push(`${name}: ${value};`);
- }
- }
- }
-
- // Method 2: Fallback - Check specific theme variables that should exist
- const themeVariables = [
- "--themecolor",
- "--themecolor2",
- "--themecolor3",
- "--themecolor4",
- "--themegradient",
- "--themecolor-transparent",
- "--themecolor2-transparent",
- "--themecolor3-transparent",
- "--foreground",
- "--foreground-strong",
- "--foreground-stronger",
- "--foreground-muted",
- "--foreground-subtle",
- "--background",
- "--surface",
- "--surface-foreground",
- "--surface-transparent-05",
- "--surface-transparent-1",
- "--surface-transparent-2",
- "--primary",
- "--primary-foreground",
- "--primary-transparent",
- "--primary-border",
- "--primary-border-strong",
- "--secondary",
- "--secondary-foreground",
- "--menu-background",
- ];
-
- const fallbackVariables: string[] = [];
- themeVariables.forEach((varName) => {
- const value = styles.getPropertyValue(varName).trim();
- if (value && !cssVariables.some((v) => v.startsWith(varName))) {
- fallbackVariables.push(`${varName}: ${value};`);
- }
- });
-
- // Method 3: Check all style sheets for :root rules
- const stylesheetVariables: string[] = [];
- try {
- Array.from(document.styleSheets).forEach((sheet) => {
- try {
- Array.from(sheet.cssRules || []).forEach((rule) => {
- if (rule instanceof CSSStyleRule && rule.selectorText === ":root") {
- const style = rule.style;
- for (let i = 0; i < style.length; i++) {
- const prop = style[i];
- if (prop.startsWith("--")) {
- const value = style.getPropertyValue(prop).trim();
- if (
- value &&
- !cssVariables.some((v) => v.startsWith(prop)) &&
- !fallbackVariables.some((v) => v.startsWith(prop))
- ) {
- stylesheetVariables.push(`${prop}: ${value};`);
- }
- }
- }
- }
- });
- } catch (e) {
- // Skip inaccessible stylesheets (CORS)
- }
- });
- } catch (e) {
- console.warn("Could not access stylesheets:", e);
- }
-
- const allVariables = [
- ...cssVariables,
- ...fallbackVariables,
- ...stylesheetVariables,
- ];
-
- return `:root {\n ${allVariables.join("\n ")}\n}`;
-}
-
-/**
- * Logs all CSS variables defined on the :root element.
- */
-export function logAllCSSVariables() {
- const styles = getComputedStyle(document.documentElement);
- const cssVariables: string[] = [];
-
- for (let i = 0; i < styles.length; i++) {
- const name = styles[i];
- if (name.startsWith("--")) {
- const value = styles.getPropertyValue(name).trim();
- cssVariables.push(`${name}: ${value}`);
- }
- }
-
- console.log("All CSS Variables:", cssVariables.join("\n"));
-}
diff --git a/Build/src/helpers/wallpaperLoader.tsx b/Build/src/helpers/wallpaperLoader.tsx
deleted file mode 100644
index 4a59627..0000000
--- a/Build/src/helpers/wallpaperLoader.tsx
+++ /dev/null
@@ -1,282 +0,0 @@
-import React, {
- useState,
- useEffect,
- createContext,
- useContext,
- useCallback,
-} from "react";
-import { loadThemeJsonFromSourcePath } from "./themeMetadata";
-
-// ----------------------
-// Types
-// ----------------------
-export interface WallpaperMetadata {
- name: string;
- author: string;
- description: string;
- version: string;
- componentFile: string;
-}
-
-interface WallpaperContextProps {
- wallpapers: WallpaperMetadata[];
- currentWallpaper: WallpaperMetadata | null;
- currentWallpaperComponent: React.ComponentType | null;
- isLoading: boolean;
- error: string | null;
- setWallpaper: (wallpaperName: string) => Promise;
-}
-
-const WallpaperContext = createContext({
- wallpapers: [],
- currentWallpaper: null,
- currentWallpaperComponent: null,
- isLoading: false,
- error: null,
- setWallpaper: async () => {},
-});
-
-interface WallpaperLoaderProps {
- defaultWallpaper: string;
- children: React.ReactNode;
- onWallpaperChange?: (wallpaper: WallpaperMetadata) => void;
-}
-
-// ----------------------
-// Global wallpapers storage for console access
-// ----------------------
-let globalWallpapers: WallpaperMetadata[] = [];
-
-// ----------------------
-// Import wallpaper components
-// ----------------------
-const wallpaperComponentFiles = import.meta.glob(
- "../themes/Wallpapers/**/*.wallpaper.tsx",
- { eager: false },
-);
-
-// ----------------------
-// WallpaperLoader Component
-// ----------------------
-export const WallpaperLoader: React.FC = ({
- defaultWallpaper,
- children,
- onWallpaperChange,
-}) => {
- const [wallpapers, setWallpapers] = useState([]);
- const [currentWallpaper, setCurrentWallpaper] =
- useState(null);
- const [currentWallpaperComponent, setCurrentWallpaperComponent] =
- useState | null>(null);
- const [isLoading, setIsLoading] = useState(true);
- const [error, setError] = useState(null);
-
- // ----------------------
- // Load wallpapers on mount
- // ----------------------
- useEffect(() => {
- const loadWallpapers = async () => {
- try {
- setIsLoading(true);
- setError(null);
-
- const loadedWallpapers: WallpaperMetadata[] = [];
-
- // Load wallpapers from JSON metadata
- for (const path of Object.keys(wallpaperComponentFiles)) {
- try {
- const themeJson = await loadThemeJsonFromSourcePath(path);
- const wallpaperMeta = themeJson?.wallpaper;
-
- if (!wallpaperMeta) {
- console.warn(
- `Wallpaper file ${path}: No wallpaper metadata in theme.json`,
- );
- continue;
- }
-
- // TODO: i18n-ize
- const metadata: WallpaperMetadata = {
- name:
- wallpaperMeta.label ||
- wallpaperMeta.name ||
- "Unnamed Wallpaper",
- author: wallpaperMeta.author || "Unknown",
- description: wallpaperMeta.description || "",
- version: wallpaperMeta.version || "1.0.0",
- componentFile:
- wallpaperMeta.componentFile || path.split("/").pop() || "",
- };
-
- // Verify component file exists
- const componentExists = Object.keys(wallpaperComponentFiles).some(
- (componentPath) => componentPath.endsWith(metadata.componentFile),
- );
-
- if (componentExists) {
- loadedWallpapers.push(metadata);
- } else {
- console.warn(
- `Wallpaper "${metadata.name}": Component file "${metadata.componentFile}" not found`,
- );
- }
- } catch (err) {
- console.warn(`Failed to load wallpaper metadata for ${path}`, err);
- }
- }
-
- if (loadedWallpapers.length === 0) {
- throw new Error("No valid wallpapers found");
- }
-
- setWallpapers(loadedWallpapers);
- globalWallpapers = loadedWallpapers; // Update global variable for console access
-
- // Load initial wallpaper
- const storedWallpaperName =
- localStorage.getItem("selected-wallpaper") || defaultWallpaper;
-
- if (storedWallpaperName === "None") {
- // Special case for "None" - no wallpaper
- setCurrentWallpaper(null);
- setCurrentWallpaperComponent(null);
- setError(null);
- } else {
- const initialWallpaper =
- loadedWallpapers.find(
- (wallpaper) => wallpaper.name === storedWallpaperName,
- ) ||
- loadedWallpapers.find(
- (wallpaper) => wallpaper.name === defaultWallpaper,
- ) ||
- loadedWallpapers[0]; // Fallback to first available
-
- if (initialWallpaper) {
- await applyWallpaper(initialWallpaper);
- }
- }
- } catch (err) {
- const errorMessage =
- err instanceof Error ? err.message : "Failed to load wallpapers";
- setError(errorMessage);
- console.error("Wallpaper loading error:", err);
- } finally {
- setIsLoading(false);
- }
- };
-
- loadWallpapers();
- }, [defaultWallpaper]);
-
- // ----------------------
- // Apply wallpaper: dynamically import and render component
- // ----------------------
- const applyWallpaper = useCallback(
- async (wallpaper: WallpaperMetadata): Promise => {
- try {
- // Find the matching component file
- const componentPath = Object.keys(wallpaperComponentFiles).find(
- (path) => path.endsWith(wallpaper.componentFile),
- );
-
- if (!componentPath) {
- throw new Error(
- `Component file not found: ${wallpaper.componentFile}`,
- );
- }
-
- // Load the component module
- const componentModule = await wallpaperComponentFiles[componentPath]();
- const WallpaperComponent = (componentModule as any).default;
-
- if (!WallpaperComponent || typeof WallpaperComponent !== "function") {
- throw new Error(`Invalid component for ${componentPath}`);
- }
-
- // Update state
- setCurrentWallpaper(wallpaper);
- setCurrentWallpaperComponent(() => WallpaperComponent);
- localStorage.setItem("selected-wallpaper", wallpaper.name);
-
- // Call optional callback
- onWallpaperChange?.(wallpaper);
-
- setError(null);
-
- console.log(`Successfully applied wallpaper: ${wallpaper.name}`);
- } catch (err) {
- const errorMessage =
- err instanceof Error ? err.message : "Failed to apply wallpaper";
- setError(errorMessage);
- console.error("Wallpaper application error:", err);
- throw err;
- }
- },
- [onWallpaperChange],
- );
-
- // ----------------------
- // Set wallpaper by name
- // ----------------------
- const setWallpaper = useCallback(
- async (wallpaperName: string): Promise => {
- if (wallpaperName === "None") {
- // Special case for "None" - disable wallpaper
- setCurrentWallpaper(null);
- setCurrentWallpaperComponent(null);
- localStorage.setItem("selected-wallpaper", "None");
- setError(null);
- return;
- }
-
- const wallpaper = wallpapers.find((w) => w.name === wallpaperName);
- if (!wallpaper) {
- throw new Error(`Wallpaper "${wallpaperName}" not found`);
- }
-
- await applyWallpaper(wallpaper);
- },
- [wallpapers, applyWallpaper],
- );
-
- const value: WallpaperContextProps = {
- wallpapers,
- currentWallpaper,
- currentWallpaperComponent,
- isLoading,
- error,
- setWallpaper,
- };
-
- // ----------------------
- // Expose wallpapers globally for console access
- // ----------------------
- useEffect(() => {
- if (typeof window !== "undefined") {
- (window as any).wallpaperLoader = {
- getAllWallpapers: () => globalWallpapers,
- getCurrentWallpaper: () => currentWallpaper,
- setWallpaper: setWallpaper,
- };
- }
- }, [wallpapers, currentWallpaper, setWallpaper]);
-
- return (
-
- {children}
-
- );
-};
-
-// ----------------------
-// Custom Hook
-// ----------------------
-export const useWallpaperLoader = () => {
- const context = useContext(WallpaperContext);
- if (!context) {
- throw new Error(
- "useWallpaperLoader must be used within a WallpaperProvider",
- );
- }
- return context;
-};
diff --git a/Build/src/hooks/musicPlayerHook.tsx b/Build/src/hooks/musicPlayerHook.tsx
deleted file mode 100644
index 9489e7b..0000000
--- a/Build/src/hooks/musicPlayerHook.tsx
+++ /dev/null
@@ -1,1979 +0,0 @@
-import { useState, useRef, useEffect, useCallback } from "react";
-import { toast } from "sonner";
-import { musicIndexedDbHelper } from "../helpers/musicIndexedDbHelper";
-import { toggleMiniplayer } from "../components/Miniplayer";
-import { CrossfadeManager, AudioSource } from "../helpers/crossfadeHelper";
-import DiscordService from "../helpers/discordService";
-import { getValidPlaybackRate } from "../helpers/musicPlayerUtils";
-import { createCacheManager } from "../helpers/cacheManager";
-import {
- getSmartShuffledSong,
- createNextSongManager,
-} from "../helpers/shuffleManager";
-import { createCrossfadeManager } from "../helpers/crossfadeUtils";
-import { calculateGaplessOffsets } from "../helpers/gaplessHelper";
-import { createPlaylistManager } from "../helpers/playlistManager";
-import { debounce } from "lodash";
-import { useTranslation } from "react-i18next";
-import { getSafariAudioManager } from "../contexts/audioStore";
-import { isSafari } from "../helpers/safariHelper";
-
-export const useMusicPlayer = () => {
- const { t } = useTranslation();
- const audioRef = useRef(null);
- const audioContextRef = useRef(null);
- const songCacheRef = useRef>(new Map());
-
- // Safari audio manager for background playback support
- const safariAudioRef = useRef(getSafariAudioManager());
-
- // --- AudioBufferSourceNode for flo (non-Safari) ---
- const floBufferSourceRef = useRef(null);
- const floAudioBufferRef = useRef(null);
- const floStartTimeRef = useRef(0);
- const floPausedAtRef = useRef(0);
- const floIsPlayingRef = useRef(false);
- const floGainNodeRef = useRef(null);
-
- // Simplified crossfade-related refs
- const nextAudioRef = useRef(null);
- const crossfadeManagerRef = useRef(null);
- const currentAudioSourceRef = useRef(null);
- const nextAudioSourceRef = useRef(null);
- const preloadTimeoutRef = useRef(null);
- const crossfadeTimeoutRef = useRef(null);
- const gaplessAdvanceTriggeredRef = useRef(false);
- const gaplessStartAppliedRef = useRef(false);
-
- // Guard to prevent multiple crossfade triggers from timeupdate events
- const crossfadeInitiatedRef = useRef(false);
-
- // Cache the next song decision
- const nextSongCacheRef = useRef(null);
- const nextSongCacheValidRef = useRef(false);
- const isPreloadingRef = useRef(false);
-
- const [isInitialized, setIsInitialized] = useState(false);
- const playNextRef = useRef<(() => void) | null>(null);
-
- const [playerState, setPlayerState] = useState({
- currentSong: null,
- currentPlaylist: null,
- isPlaying: false,
- volume: 0.75,
- currentTime: 0,
- duration: 0,
- shuffle: false,
- repeat: "off",
- analyserNode: null,
- view: "home",
- });
-
- const [settings, setSettings] = useState({
- volume: 0.75,
- crossfade: 3,
- colorTheme: "Blue",
- wallpaper: "None",
- defaultShuffle: false,
- defaultRepeat: "off",
- autoPlayNext: true,
- themeMode: "auto",
- compactMode: false,
- showAlbumArt: true,
- showLyrics: false,
- sessionRestore: true,
- lastPlayedSongId: "none",
- lastPlayedPlaylistId: "none",
- language: "English",
- tempo: 1,
- pitch: 0,
- gaplessPlayback: false,
- smartShuffle: true,
- discordEnabled: false,
- discordUserId: undefined,
- erudaEnabled: false,
- });
-
- const [library, setLibrary] = useState(() => ({
- songs: [],
- playlists: [],
- favorites: [],
- }));
-
- const [searchQuery, setSearchQuery] = useState("");
-
- // Create refs for settings and state
- const playHistoryRef = useRef<
- Map
- >(new Map());
- const settingsRef = useRef(settings);
- const playerStateRef = useRef(playerState);
-
- // Create debounced save functions
- const debouncedSaveLibrary = useCallback(
- debounce(async (library: MusicLibrary) => {
- try {
- await musicIndexedDbHelper.saveLibrary(library);
- console.log("Saved musicLibrary to IndexedDB");
- } catch (error) {
- console.error("Failed to persist library data:", error);
- }
- }, 500),
- [],
- );
-
- const debouncedSaveSettings = useCallback(
- debounce(
- async (
- settings: PlayerSettings,
- playHistory: Map,
- ) => {
- try {
- const playHistoryArray = Array.from(playHistory.entries());
- const settingsWithPlayHistory = {
- ...settings,
- playHistory: playHistoryArray,
- };
- await musicIndexedDbHelper.saveSettings(settingsWithPlayHistory);
- console.log("Saved playerSettings to IndexedDB");
- } catch (error) {
- console.error("Failed to persist settings:", error);
- }
- },
- 300,
- ),
- [],
- );
-
- // Initialize the managers
- const cacheManager = createCacheManager(songCacheRef);
- const nextSongManager = createNextSongManager(
- nextSongCacheRef,
- nextSongCacheValidRef,
- );
- const crossfadeManager = createCrossfadeManager(
- audioRef,
- nextAudioRef,
- crossfadeManagerRef,
- currentAudioSourceRef,
- nextAudioSourceRef,
- gaplessAdvanceTriggeredRef,
- gaplessStartAppliedRef,
- );
- const playlistManager = createPlaylistManager(
- setLibrary,
- library,
- setSearchQuery,
- searchQuery,
- setPlayerState,
- );
-
- // Extract manager functions
- const {
- cacheSong,
- getCachedSong,
- prepareSongsForPlaylist,
- updateSongCache,
- clearAllCache,
- } = cacheManager;
-
- const { getAndCacheNextSong, invalidateNextSongCache, updatePlayHistory } =
- nextSongManager;
-
- const {
- setupCrossfadeManager,
- prepareNextSongForCrossfade,
- preloadNextSong,
- startCrossfadeTransition,
- cleanupCrossfadeManager,
- } = crossfadeManager;
-
- const {
- createPlaylist,
- createFolder,
- removePlaylist,
- addToFavorites,
- removeFromFavorites,
- addToPlaylist,
- reorderPlaylistSongs,
- moveSongToPlaylist,
- moveToFolder,
- toggleFavorite,
- isFavorited,
- getFavoriteSongs,
- searchSongs,
- getSearchResults,
- navigateToHome,
- navigateToArtist,
- navigateToAlbum,
- navigateToSongs,
- exportPlaylist,
- importPlaylist,
- } = playlistManager;
-
- const setupAudioContext = useCallback(() => {
- // Skip Web Audio API setup on Safari for non-flo playback (crossfade/gapless)
- // But allow for flo playback
- const isSafari = safariAudioRef.current.isActive();
- const currentSong = playerStateRef.current.currentSong;
- const isFlo =
- currentSong?.url?.toLowerCase().endsWith(".flo") ||
- currentSong?.mimeType === "audio/x-flo";
- if (isSafari && !isFlo) {
- console.log(
- "[Safari] Skipping Web Audio API setup for non-flo playback compatibility",
- );
- return;
- }
-
- if (!audioContextRef.current && audioRef.current) {
- const context = new (
- window.AudioContext || (window as any).webkitAudioContext
- )();
-
- audioContextRef.current = context;
-
- // Setup crossfade manager with the new audio context (only if not Safari or if flo)
- if (!isSafari || isFlo) {
- const manager = setupCrossfadeManager(context);
- if (manager) {
- const analyserNode = manager.getAnalyzerNode();
- setPlayerState((prev) => ({ ...prev, analyserNode }));
- }
- }
-
- console.log("[Audio Context] Created and initialized");
- }
- }, [setupCrossfadeManager]);
-
- // Keep AudioContext alive for background playback (non-Safari browsers)
- useEffect(() => {
- const handleVisibilityChange = () => {
- // Resume AudioContext if suspended
- if (
- audioContextRef.current &&
- audioContextRef.current.state === "suspended"
- ) {
- console.log("[Audio Context] Resuming suspended context");
- audioContextRef.current.resume();
- }
- };
-
- const handleFocus = () => {
- if (
- audioContextRef.current &&
- audioContextRef.current.state === "suspended"
- ) {
- console.log("[Audio Context] Resuming on focus");
- audioContextRef.current.resume();
- }
- };
-
- document.addEventListener("visibilitychange", handleVisibilityChange);
- window.addEventListener("focus", handleFocus);
-
- return () => {
- document.removeEventListener("visibilitychange", handleVisibilityChange);
- window.removeEventListener("focus", handleFocus);
- };
- }, []);
-
- // Update currentTime for flo playback
- useEffect(() => {
- let animationFrame: number;
- const updateTime = () => {
- if (floIsPlayingRef.current && audioContextRef.current) {
- const currentTime = Math.max(
- 0,
- audioContextRef.current.currentTime - floStartTimeRef.current,
- );
- setPlayerState((prev) => {
- // Only update if time changed significantly to avoid excessive re-renders
- if (Math.abs(prev.currentTime - currentTime) > 0.1) {
- return { ...prev, currentTime };
- }
- return prev;
- });
- }
- animationFrame = requestAnimationFrame(updateTime);
- };
- updateTime(); // Start immediately
- return () => {
- if (animationFrame) {
- cancelAnimationFrame(animationFrame);
- }
- };
- }, []); // Empty deps, runs once
-
- // Clear timeouts on unmount
- useEffect(() => {
- return () => {
- cleanupCrossfadeManager();
-
- if (preloadTimeoutRef.current) {
- clearTimeout(preloadTimeoutRef.current);
- }
-
- clearAllCache();
- };
- }, []);
-
- // Initialize data loading with batched processing to prevent RAM spikes
- useEffect(() => {
- const BATCH_SIZE = 100; // Process songs in batches of 100
- const BATCH_DELAY = 10; // ms delay between batches to let GC run
-
- // Helper to process songs in batches to prevent RAM spikes
- const processSongsInBatches = async (songs: Song[]): Promise => {
- if (songs.length <= BATCH_SIZE) {
- // Small library, process all at once
- return songs.filter((song: Song) => song.url && song.url !== "");
- }
-
- const validSongs: Song[] = [];
-
- for (let i = 0; i < songs.length; i += BATCH_SIZE) {
- const batch = songs.slice(i, i + BATCH_SIZE);
- const validBatch = batch.filter(
- (song: Song) => song.url && song.url !== "",
- );
- validSongs.push(...validBatch);
-
- // Yield to main thread between batches
- if (i + BATCH_SIZE < songs.length) {
- await new Promise((resolve) => setTimeout(resolve, BATCH_DELAY));
- }
- }
-
- return validSongs;
- };
-
- // Helper to prepare songs in batches
- const prepareSongsInBatches = async (songs: Song[]): Promise => {
- if (songs.length <= BATCH_SIZE) {
- return prepareSongsForPlaylist(songs);
- }
-
- const preparedSongs: Song[] = [];
-
- for (let i = 0; i < songs.length; i += BATCH_SIZE) {
- const batch = songs.slice(i, i + BATCH_SIZE);
- const preparedBatch = prepareSongsForPlaylist(batch);
- preparedSongs.push(...preparedBatch);
-
- // Yield to main thread between batches
- if (i + BATCH_SIZE < songs.length) {
- await new Promise((resolve) => setTimeout(resolve, BATCH_DELAY));
- }
- }
-
- return preparedSongs;
- };
-
- const loadPersistedData = async () => {
- try {
- const persistedLibrary = await musicIndexedDbHelper.loadLibrary();
- const persistedSettings = await musicIndexedDbHelper.loadSettings();
-
- if (persistedLibrary) {
- // Process songs in batches to prevent RAM spike
- const validSongs = await processSongsInBatches(
- persistedLibrary.songs,
- );
-
- const validLibrary = {
- ...persistedLibrary,
- songs: validSongs,
- };
-
- // Prepare songs for playlist in batches
- const preparedSongs = await prepareSongsInBatches(validLibrary.songs);
-
- const allSongsPlaylist = {
- id: "all-songs",
- name: t("allSongs"),
- songs: preparedSongs,
- };
-
- const updatedLibrary = {
- ...validLibrary,
- playlists: validLibrary.playlists.some(
- (p: any) => p.id === "all-songs",
- )
- ? validLibrary.playlists.map((p: any) =>
- p.id === "all-songs"
- ? {
- ...p,
- songs: preparedSongs, // Reuse already prepared songs
- }
- : p,
- )
- : [allSongsPlaylist, ...validLibrary.playlists],
- };
-
- setLibrary(updatedLibrary);
-
- let songToPlay: Song | null = null;
- let playlistToSet: Playlist | null = null;
-
- if (persistedSettings?.sessionRestore !== false) {
- if (persistedSettings?.lastPlayedSongId) {
- songToPlay =
- updatedLibrary.songs.find(
- (s: Song) => s.id === persistedSettings.lastPlayedSongId,
- ) || null;
- }
- if (persistedSettings?.lastPlayedPlaylistId) {
- playlistToSet =
- updatedLibrary.playlists.find(
- (p: Playlist) =>
- p.id === persistedSettings.lastPlayedPlaylistId,
- ) || null;
- }
- }
-
- if (
- !playlistToSet ||
- !playlistToSet.songs ||
- playlistToSet.songs.length === 0
- ) {
- playlistToSet = allSongsPlaylist;
- }
-
- if (
- !songToPlay &&
- playlistToSet.songs.length > 0 &&
- persistedSettings?.sessionRestore !== false
- ) {
- songToPlay = playlistToSet.songs[0];
- }
-
- setPlayerState((prev) => ({
- ...prev,
- currentSong: songToPlay,
- currentPlaylist: playlistToSet,
- isPlaying: false,
- currentTime: 0,
- duration: songToPlay?.duration || 0,
- }));
-
- if (persistedSettings) {
- // On Safari, force disable gapless playback and crossfade
- // since Web Audio API is not used for background compatibility
- const isSafari = safariAudioRef.current.isActive();
- if (isSafari) {
- persistedSettings.gaplessPlayback = false;
- persistedSettings.crossfade = 0;
- }
-
- // Ensure pitch has a valid default value to prevent NaN errors
- if (
- persistedSettings.pitch === undefined ||
- persistedSettings.pitch === null ||
- isNaN(persistedSettings.pitch)
- ) {
- persistedSettings.pitch = 0;
- }
-
- setSettings(persistedSettings);
- if (persistedSettings.playHistory) {
- playHistoryRef.current = new Map(persistedSettings.playHistory);
- console.log(
- "Restored play history with",
- persistedSettings.playHistory.length,
- "entries",
- );
- }
- }
- }
- } catch (error) {
- console.error("Failed to load persisted data:", error);
- } finally {
- setIsInitialized(true);
- }
- };
- loadPersistedData();
- }, [prepareSongsForPlaylist]);
-
- // Save data when changed (same as before)
- useEffect(() => {
- if (!isInitialized) return;
- debouncedSaveLibrary(library);
- }, [library, isInitialized, debouncedSaveLibrary]);
-
- useEffect(() => {
- if (!isInitialized) return;
- debouncedSaveSettings(settings, playHistoryRef.current);
- }, [settings, isInitialized, debouncedSaveSettings]);
-
- // Update refs when state changes
- useEffect(() => {
- const previousSettings = settingsRef.current;
- settingsRef.current = settings;
-
- if (previousSettings.smartShuffle !== settings.smartShuffle) {
- console.log("Smart shuffle setting changed, invalidating cache");
- invalidateNextSongCache(true);
- }
- }, [settings, invalidateNextSongCache]);
-
- useEffect(() => {
- const previousState = playerStateRef.current;
- playerStateRef.current = playerState;
-
- const shouldInvalidate =
- previousState.currentPlaylist?.id !== playerState.currentPlaylist?.id ||
- (previousState.shuffle !== playerState.shuffle && playerState.shuffle) ||
- previousState.repeat !== playerState.repeat;
-
- if (shouldInvalidate) {
- console.log("Player state changed significantly, invalidating cache");
- invalidateNextSongCache(true);
- }
- }, [playerState, invalidateNextSongCache]);
-
- // Update playlist when library changes
- useEffect(() => {
- if (playerState.currentPlaylist) {
- // Recursive function to find playlist in the tree
- const findPlaylist = (
- items: (Playlist | PlaylistFolder)[],
- ): Playlist | null => {
- for (const item of items) {
- if ("songs" in item && item.id === playerState.currentPlaylist?.id) {
- return item;
- }
- if ("children" in item) {
- const found = findPlaylist(item.children);
- if (found) return found;
- }
- }
- return null;
- };
- const updatedPlaylist = findPlaylist(library.playlists);
- if (
- updatedPlaylist &&
- updatedPlaylist.songs !== playerState.currentPlaylist.songs
- ) {
- setPlayerState((prev) => ({
- ...prev,
- currentPlaylist: updatedPlaylist,
- }));
- }
- }
- }, [library.playlists, playerState.currentPlaylist?.id]);
-
- // Update master volume through crossfade manager
- useEffect(() => {
- if (crossfadeManagerRef.current) {
- crossfadeManagerRef.current.setMasterVolume(settings.volume);
- } else if (audioRef.current) {
- audioRef.current.volume = settings.volume;
- }
- }, [settings.volume]);
-
- // Update player state when settings change
- useEffect(() => {
- setPlayerState((prev) => ({
- ...prev,
- volume: settings.volume,
- shuffle: settings.defaultShuffle,
- repeat: settings.defaultRepeat,
- }));
- }, [settings.volume, settings.defaultShuffle, settings.defaultRepeat]);
-
- // Media session and last played updates (same as before)
- useEffect(() => {
- if (!isInitialized) return;
-
- if (settings.sessionRestore) {
- setSettings((prev) => ({
- ...prev,
- lastPlayedSongId: playerState.currentSong?.id ?? prev.lastPlayedSongId,
- lastPlayedPlaylistId:
- playerState.currentPlaylist?.id ?? prev.lastPlayedPlaylistId,
- }));
- }
-
- if ("mediaSession" in navigator && playerState.currentSong) {
- navigator.mediaSession.metadata = new MediaMetadata({
- title: playerState.currentSong.title,
- artist: playerState.currentSong.artist,
- album: playerState.currentSong.album,
- artwork: playerState.currentSong.albumArt
- ? [{ src: playerState.currentSong.albumArt }]
- : [],
- });
-
- navigator.mediaSession.setActionHandler("previoustrack", () => {
- playPrevious();
- });
-
- navigator.mediaSession.setActionHandler("nexttrack", () => {
- playNext();
- });
-
- // Seek handlers for system controls
- navigator.mediaSession.setActionHandler("seekto", (details) => {
- if (details.seekTime !== undefined) {
- seekTo(details.seekTime);
- }
- });
-
- navigator.mediaSession.setActionHandler("seekforward", (details) => {
- const skipTime = details.seekOffset || 10; // Default 10 seconds
- const currentTime = playerState.currentTime;
- const duration = playerState.duration || 0;
- const newTime = Math.min(currentTime + skipTime, duration);
- seekTo(newTime);
- });
-
- navigator.mediaSession.setActionHandler("seekbackward", (details) => {
- const skipTime = details.seekOffset || 10; // Default 10 seconds
- const currentTime = playerState.currentTime;
- const newTime = Math.max(currentTime - skipTime, 0);
- seekTo(newTime);
- });
-
- // Only set enterpictureinpicture handler if supported
- try {
- navigator.mediaSession.setActionHandler(
- "enterpictureinpicture" as any,
- () => {
- toggleMiniplayer({
- playerState: {
- currentSong: playerState.currentSong,
- isPlaying: playerState.isPlaying,
- },
- togglePlayPause,
- playNext,
- playPrevious,
- });
- },
- );
- } catch (error) {
- // Browser doesn't support enterpictureinpicture action
- console.log("enterpictureinpicture action not supported");
- }
-
- return () => {
- if ("mediaSession" in navigator) {
- navigator.mediaSession.setActionHandler("previoustrack", null);
- navigator.mediaSession.setActionHandler("nexttrack", null);
- navigator.mediaSession.setActionHandler("seekto", null);
- navigator.mediaSession.setActionHandler("seekforward", null);
- navigator.mediaSession.setActionHandler("seekbackward", null);
- try {
- navigator.mediaSession.setActionHandler(
- "enterpictureinpicture" as any,
- null,
- );
- } catch (error) {
- // Browser doesn't support enterpictureinpicture action
- }
- }
- };
- }
- }, [playerState.currentSong, playerState.currentPlaylist, isInitialized]);
-
- // Update tempo and pitch when settings change (combined playbackRate)
- useEffect(() => {
- const combinedRate = getValidPlaybackRate(settings.tempo, settings.pitch);
-
- if (audioRef.current) {
- audioRef.current.playbackRate = combinedRate;
- }
- if (nextAudioRef.current) {
- nextAudioRef.current.playbackRate = combinedRate;
- }
-
- // No need to sync - on Safari, audioRef.current IS the Safari element
- }, [settings.tempo, settings.pitch]);
-
- // Discord presence update function
- const updateDiscordPresence = useCallback(
- async (song: Song | null, isPlaying: boolean) => {
- if (!settings.discordEnabled) return;
-
- // Prefer Tauri RPC (desktop) if available
- const isTauri = (await import("@tauri-apps/api/core")).isTauri();
-
- try {
- if (song && isPlaying) {
- if (isTauri) {
- const { invoke } = await import("@tauri-apps/api/core");
- await invoke("set_discord_presence", {
- details: song.title,
- state: song.artist,
- });
- } else if (settings.discordUserId) {
- const discordService = DiscordService.getInstance();
- await discordService.updatePresence({
- userId: settings.discordUserId,
- details: song.title,
- state: song.artist,
- });
- }
- } else {
- if (isTauri) {
- const { invoke } = await import("@tauri-apps/api/core");
- await invoke("clear_discord_presence");
- } else if (settings.discordUserId) {
- const discordService = DiscordService.getInstance();
- await discordService.clearPresence(settings.discordUserId);
- }
- }
- } catch (error) {
- console.error("Failed to update Discord presence:", error);
- }
- },
- [settings.discordEnabled, settings.discordUserId],
- );
-
- // Improved preload function
- const smartPreloadNextSong = useCallback(async () => {
- if (
- isPreloadingRef.current ||
- !playerState.currentSong ||
- !playerState.currentPlaylist
- ) {
- return;
- }
-
- if (playerState.repeat === "one") {
- return;
- }
-
- isPreloadingRef.current = true;
-
- try {
- const nextSong = getAndCacheNextSong(
- playerStateRef,
- settingsRef,
- playHistoryRef,
- );
-
- if (nextSong) {
- nextSongCacheRef.current = nextSong;
- nextSongCacheValidRef.current = true;
-
- if (settings.crossfade > 0 && nextAudioRef.current) {
- const isFlo =
- nextSong.url?.toLowerCase().endsWith(".flo") ||
- nextSong.mimeType === "audio/x-flo";
- if (!isFlo) {
- await preloadNextSong(
- () => nextSong,
- cacheSong,
- getCachedSong,
- settingsRef,
- );
- }
- }
- }
- } catch (error) {
- console.error("Failed to preload next song:", error);
- } finally {
- isPreloadingRef.current = false;
- }
- }, [
- playerState,
- settings,
- preloadNextSong,
- cacheSong,
- getCachedSong,
- getAndCacheNextSong,
- ]);
-
- const playSong = useCallback(
- async (song: Song, playlist?: Playlist) => {
- // Even if URL is empty, we might have it in IndexedDB
- if (!song.url && !song.hasStoredAudio) {
- console.error("No URL or stored audio available for song:", song);
- toast.error(`Cannot play "${song.title}" - No audio source available`);
- return;
- }
-
- if (!audioContextRef.current) setupAudioContext();
- if (audioContextRef.current?.state === "suspended") {
- audioContextRef.current.resume();
- }
-
- // Clear any pending timeouts
- if (crossfadeTimeoutRef.current) {
- clearTimeout(crossfadeTimeoutRef.current);
- crossfadeTimeoutRef.current = null;
- }
- if (preloadTimeoutRef.current) {
- clearTimeout(preloadTimeoutRef.current);
- preloadTimeoutRef.current = null;
- }
-
- // Prepare song for playing
- const songToPlay = song.hasStoredAudio
- ? { ...song, url: `indexeddb://${song.id}` }
- : song;
-
- // Cache song
- await cacheSong(songToPlay);
- const cachedSong = getCachedSong(song.id);
- if (!cachedSong) {
- console.error("Failed to play song: could not cache");
- return;
- }
-
- // Load album art for current song if it exists
- let songWithArt = song;
- if (song.hasAlbumArt && !song.albumArt) {
- try {
- const albumArt = await musicIndexedDbHelper.loadAlbumArt(song.id);
- if (albumArt) {
- songWithArt = { ...song, albumArt };
- }
- } catch (error) {
- console.warn("Failed to load album art for current song:", error);
- }
- }
-
- // Prepare playlist
- const preparedPlaylist =
- playlist && "songs" in playlist
- ? { ...playlist, songs: prepareSongsForPlaylist(playlist.songs) }
- : playerStateRef.current.currentPlaylist;
-
- setPlayerState((prev) => ({
- ...prev,
- currentSong: songWithArt,
- currentPlaylist: preparedPlaylist,
- isPlaying: true,
- currentTime: 0,
- }));
-
- // Track play history
- if (
- playerStateRef.current.currentSong &&
- playerStateRef.current.currentSong.id !== song.id
- ) {
- updatePlayHistory(
- playHistoryRef,
- playerStateRef.current.currentSong.id,
- );
- }
-
- // Check if this is a pre-decoded WAV (Safari path)
- const isFloWav =
- song.mimeType === "audio/wav" && song.encoding?.codec === "flo";
-
- // Check if this is pre-decoded PCM (non-Safari path)
- const isFloPcm =
- song.mimeType === "audio/pcm" || song.encoding?.codec === "pcm-float32";
-
- // Check if this is original flo
- const isFloOriginal =
- song.mimeType === "audio/x-flo" ||
- song.url?.toLowerCase().endsWith(".flo");
-
- if (isFloWav) {
- // Play pre-decoded WAV (Safari)
- try {
- let wavBuffer: ArrayBuffer | undefined;
-
- if (song.hasStoredAudio && song.url.startsWith("indexeddb://")) {
- const audioData = await musicIndexedDbHelper.loadSongAudio(song.id);
- wavBuffer = audioData?.fileData;
- } else if (song.url && song.url.startsWith("blob:")) {
- const res = await fetch(song.url);
- wavBuffer = await res.arrayBuffer();
- }
-
- if (!wavBuffer) {
- throw new Error("Could not load WAV data for playback");
- }
-
- const wavBlob = new Blob([wavBuffer], { type: "audio/wav" });
- const wavUrl = URL.createObjectURL(wavBlob);
-
- if (audioRef.current) {
- audioRef.current.src = wavUrl;
- audioRef.current.playbackRate = getValidPlaybackRate(
- settingsRef.current.tempo,
- settingsRef.current.pitch,
- );
- await audioRef.current.play();
- } else {
- throw new Error("Audio element not available");
- }
- } catch (error: any) {
- console.error("Failed to play pre-decoded flo (WAV):", error);
- toast.error(`Failed to play "${song.title}" (flo)`, {
- description: error.message || "Unknown error occurred",
- });
- setPlayerState((prev) => ({ ...prev, isPlaying: false }));
- return;
- }
- } else if (isFloPcm) {
- // Play pre-decoded PCM using AudioBufferSourceNode
- try {
- let pcmBuffer: ArrayBuffer | undefined;
-
- if (song.hasStoredAudio && song.url.startsWith("indexeddb://")) {
- const audioData = await musicIndexedDbHelper.loadSongAudio(song.id);
- pcmBuffer = audioData?.fileData;
- } else if (song.url && song.url.startsWith("blob:")) {
- const res = await fetch(song.url);
- pcmBuffer = await res.arrayBuffer();
- }
-
- if (!pcmBuffer) {
- throw new Error("Could not load PCM data for playback");
- }
-
- if (!audioContextRef.current) setupAudioContext();
- const ctx = audioContextRef.current;
- if (!ctx) throw new Error("AudioContext not available");
-
- // Stop any previous buffer source
- if (floBufferSourceRef.current) {
- try {
- floBufferSourceRef.current.stop();
- } catch {}
- floBufferSourceRef.current.disconnect();
- floBufferSourceRef.current = null;
- }
-
- // Reconstruct AudioBuffer from interleaved PCM data
- const sampleRate = song.encoding?.sampleRate || 44100;
- const channels = song.encoding?.channels || 2;
- const pcmData = new Float32Array(pcmBuffer);
- const frameCount = pcmData.length / channels;
-
- const audioBuffer = ctx.createBuffer(
- channels,
- frameCount,
- sampleRate,
- );
-
- // Deinterleave
- for (let ch = 0; ch < channels; ch++) {
- const channelData = audioBuffer.getChannelData(ch);
- for (let i = 0; i < frameCount; i++) {
- channelData[i] = pcmData[i * channels + ch];
- }
- }
-
- floAudioBufferRef.current = audioBuffer;
-
- // Create source node
- const source = ctx.createBufferSource();
- source.buffer = audioBuffer;
-
- // Connect through gain node for volume control
- if (!floGainNodeRef.current) {
- floGainNodeRef.current = ctx.createGain();
- floGainNodeRef.current.connect(ctx.destination);
- }
- source.connect(floGainNodeRef.current);
- floGainNodeRef.current.gain.value = settingsRef.current.volume;
-
- source.onended = () => {
- floIsPlayingRef.current = false;
- setPlayerState((prev) => ({
- ...prev,
- isPlaying: false,
- currentTime: audioBuffer.duration,
- }));
- };
-
- floBufferSourceRef.current = source;
- floStartTimeRef.current = ctx.currentTime;
- floPausedAtRef.current = 0;
- floIsPlayingRef.current = true;
-
- setPlayerState((prev) => ({
- ...prev,
- isPlaying: true,
- currentTime: 0,
- duration: audioBuffer.duration,
- }));
-
- source.start();
- } catch (error: any) {
- console.error("Failed to play pre-decoded flo (PCM):", error);
- toast.error(`Failed to play "${song.title}" (flo)`, {
- description: error.message || "Unknown error occurred",
- });
- setPlayerState((prev) => ({ ...prev, isPlaying: false }));
- return;
- }
- } else if (isFloOriginal) {
- // Decode flo on-demand and play
- try {
- let floBuffer: ArrayBuffer | undefined;
-
- if (song.hasStoredAudio && song.url.startsWith("indexeddb://")) {
- const audioData = await musicIndexedDbHelper.loadSongAudio(song.id);
- floBuffer = audioData?.fileData;
- } else if (song.url && song.url.startsWith("blob:")) {
- const res = await fetch(song.url);
- floBuffer = await res.arrayBuffer();
- }
-
- if (!floBuffer) {
- throw new Error("Could not load flo data for playback");
- }
-
- // Decode flo to AudioBuffer
- const { decodeFloToAudioBuffer } =
- await import("../helpers/floProcessor");
- if (!audioContextRef.current) setupAudioContext();
- const ctx = audioContextRef.current;
- if (!ctx) throw new Error("AudioContext not available");
-
- const audioBuffer = await decodeFloToAudioBuffer(floBuffer, ctx);
-
- // Stop any previous buffer source
- if (floBufferSourceRef.current) {
- try {
- floBufferSourceRef.current.stop();
- } catch {}
- floBufferSourceRef.current.disconnect();
- floBufferSourceRef.current = null;
- }
-
- floAudioBufferRef.current = audioBuffer;
-
- // Create and play
- const source = ctx.createBufferSource();
- source.buffer = audioBuffer;
-
- if (!floGainNodeRef.current) {
- floGainNodeRef.current = ctx.createGain();
- floGainNodeRef.current.connect(ctx.destination);
- }
- source.connect(floGainNodeRef.current);
- floGainNodeRef.current.gain.value = settingsRef.current.volume;
-
- source.onended = () => {
- floIsPlayingRef.current = false;
- setPlayerState((prev) => ({
- ...prev,
- isPlaying: false,
- currentTime: audioBuffer.duration,
- }));
- };
-
- floBufferSourceRef.current = source;
- floStartTimeRef.current = ctx.currentTime;
- floPausedAtRef.current = 0;
- floIsPlayingRef.current = true;
-
- setPlayerState((prev) => ({
- ...prev,
- isPlaying: true,
- currentTime: 0,
- duration: audioBuffer.duration,
- }));
-
- source.start();
- } catch (error: any) {
- console.error("Failed to decode and play flo:", error);
- toast.error(`Failed to play "${song.title}" (flo)`, {
- description: error.message || "Unknown error occurred",
- });
- setPlayerState((prev) => ({ ...prev, isPlaying: false }));
- return;
- }
- } else {
- if (audioRef.current) {
- // Cancel any ongoing crossfade
- if (crossfadeManagerRef.current?.isCrossfading()) {
- crossfadeManagerRef.current.cancelCrossfade();
- }
-
- gaplessAdvanceTriggeredRef.current = false;
- gaplessStartAppliedRef.current = false;
- crossfadeInitiatedRef.current = false;
-
- audioRef.current.src = cachedSong.url;
- const combinedRate = getValidPlaybackRate(
- settingsRef.current.tempo,
- settingsRef.current.pitch,
- );
- audioRef.current.playbackRate = combinedRate;
-
- if (!audioContextRef.current) setupAudioContext();
- if (audioContextRef.current && !crossfadeManagerRef.current) {
- setupCrossfadeManager(audioContextRef.current);
- }
- if (crossfadeManagerRef.current) {
- if (
- !currentAudioSourceRef.current ||
- currentAudioSourceRef.current.element !== audioRef.current
- ) {
- currentAudioSourceRef.current =
- crossfadeManagerRef.current.createAudioSource(audioRef.current);
- }
- crossfadeManagerRef.current.setCurrentSource(
- currentAudioSourceRef.current,
- );
- }
-
- try {
- await audioRef.current.play();
- } catch (error: any) {
- const isInterruptedError =
- error.name === "AbortError" ||
- error.message?.includes("interrupted");
-
- if (isInterruptedError) {
- console.debug("Play interrupted, this is expected");
- setPlayerState((prev) => ({ ...prev, isPlaying: false }));
- return;
- }
-
- console.error("Failed to play song:", error);
- toast.error(`Failed to play "${song.title}"`, {
- description: error.message || "Unknown error occurred",
- });
- setPlayerState((prev) => ({ ...prev, isPlaying: false }));
- return;
- }
-
- if (playlist) {
- updateSongCache(
- song,
- playlist,
- playerStateRef,
- settingsRef,
- playHistoryRef,
- getSmartShuffledSong,
- );
- }
-
- updateDiscordPresence(song, true);
- invalidateNextSongCache();
-
- preloadTimeoutRef.current = window.setTimeout(() => {
- smartPreloadNextSong();
- }, 2000);
- }
- }
- },
- [
- setupAudioContext,
- cacheSong,
- getCachedSong,
- updateSongCache,
- prepareSongsForPlaylist,
- updateDiscordPresence,
- invalidateNextSongCache,
- smartPreloadNextSong,
- ],
- );
-
- // Audio event handling setup
- useEffect(() => {
- // Initialize primary audio element
- // On Safari, use the Safari audio element as the primary element (it's in the DOM)
- // This allows background playback while still using Web Audio API for processing
- const safariElement = safariAudioRef.current.getElement();
- if (safariElement) {
- console.log("[Music Player] Using Safari audio element as primary audio");
- audioRef.current = safariElement;
- // Unmute it since it's now the primary audio source
- safariElement.muted = false;
- safariElement.volume = settingsRef.current.volume;
- } else {
- audioRef.current = new Audio();
- audioRef.current.crossOrigin = "anonymous";
- }
- // Initial playback rate will be set by the tempo/pitch effect
-
- // Initialize secondary audio element for crossfading
- nextAudioRef.current = new Audio();
- nextAudioRef.current.crossOrigin = "anonymous";
- // Initial playback rate will be set by the tempo/pitch effect
-
- const audio = audioRef.current;
-
- const handleTimeUpdate = (event: Event) => {
- const target = event.target as HTMLAudioElement;
- const currentAudio = audioRef.current;
- const nextAudio = nextAudioRef.current;
-
- let shouldUpdateFrom = currentAudio;
-
- // During crossfade, use the next audio element since that's the song becoming current
- // But only if the crossfade is actually in progress and hasn't failed
- if (
- crossfadeManagerRef.current?.isCrossfading() &&
- nextAudio &&
- nextAudio.src &&
- !nextAudio.src.includes("about:blank")
- ) {
- shouldUpdateFrom = nextAudio;
- }
-
- // Only update if this event is from the element that should control progress
- if (target !== shouldUpdateFrom) return;
-
- setPlayerState((prev) => {
- return {
- ...prev,
- currentTime: target.currentTime,
- };
- });
-
- // Update Media Session position state for system controls
- if (
- "mediaSession" in navigator &&
- "setPositionState" in navigator.mediaSession
- ) {
- try {
- navigator.mediaSession.setPositionState({
- duration: target.duration || 0,
- playbackRate: target.playbackRate || 1,
- position: target.currentTime || 0,
- });
- } catch (error) {
- // Ignore errors (some browsers may not support all parameters)
- }
- }
-
- // Handle crossfade and gapless timing
- const crossfadeEnabled = settingsRef.current.crossfade > 0;
- const gaplessEnabled = settingsRef.current.gaplessPlayback;
- const autoPlayNext = settingsRef.current.autoPlayNext;
- const playNextAvailable = !!playNextRef.current;
- const notRepeatOne = playerStateRef.current.repeat !== "one";
- const hasDuration = currentAudio && currentAudio.duration > 0;
- const notCrossfading = !crossfadeManagerRef.current?.isCrossfading();
-
- if (
- autoPlayNext &&
- playNextAvailable &&
- notRepeatOne &&
- hasDuration &&
- notCrossfading &&
- currentAudio
- ) {
- const offsets = gaplessEnabled
- ? calculateGaplessOffsets(playerStateRef.current.currentSong)
- : { start: 0, end: 0 };
-
- const trimmedDuration =
- currentAudio.duration - offsets.start - offsets.end;
- const effectiveDuration =
- Number.isFinite(trimmedDuration) && trimmedDuration > 0.1
- ? trimmedDuration
- : currentAudio.duration;
- const elapsedInContent = Math.max(
- 0,
- currentAudio.currentTime - offsets.start,
- );
- const timeRemaining = Math.max(0, effectiveDuration - elapsedInContent);
- const hasMeaningfulGaplessOffsets =
- gaplessEnabled && (offsets.start > 0 || offsets.end > 0);
-
- if (crossfadeEnabled) {
- const crossfadeDuration = settingsRef.current.crossfade;
- const preloadTime = Math.max(crossfadeDuration + 5, 10);
-
- // Preload next song early
- if (timeRemaining <= preloadTime && timeRemaining > preloadTime - 1) {
- if (!isPreloadingRef.current) {
- smartPreloadNextSong();
- }
- }
-
- // Start crossfade
- if (
- timeRemaining <= crossfadeDuration &&
- !crossfadeInitiatedRef.current
- ) {
- // Set guard immediately to prevent re-triggering
- crossfadeInitiatedRef.current = true;
- console.log(
- "Triggering crossfade at",
- timeRemaining.toFixed(1),
- "seconds remaining",
- );
- startCrossfadeTransition(
- playNextRef,
- () =>
- nextSongCacheRef.current ||
- getAndCacheNextSong(
- playerStateRef,
- settingsRef,
- playHistoryRef,
- ),
- (nextSong: Song) =>
- prepareNextSongForCrossfade(
- nextSong,
- cacheSong,
- getCachedSong,
- settingsRef,
- ),
- playerStateRef,
- playHistoryRef,
- updatePlayHistory,
- setPlayerState,
- settingsRef,
- audioContextRef,
- invalidateNextSongCache,
- gaplessAdvanceTriggeredRef,
- gaplessStartAppliedRef,
- ).catch((error: any) => {
- console.error("Crossfade transition failed:", error);
- // Reset guard on failure so it can be retried
- crossfadeInitiatedRef.current = false;
- });
- }
- } else if (gaplessEnabled) {
- // For gapless playback, prepare next song earlier
- if (timeRemaining <= 3 && timeRemaining > 2.5) {
- if (!isPreloadingRef.current) {
- smartPreloadNextSong();
- }
- }
-
- if (
- hasMeaningfulGaplessOffsets &&
- timeRemaining <= 0.15 &&
- !gaplessAdvanceTriggeredRef.current
- ) {
- gaplessAdvanceTriggeredRef.current = true;
-
- // Schedule the advance with precise timing to minimize gap
- const delayMs = Math.max(0, (timeRemaining - 0.02) * 1000);
-
- if (autoPlayNext && playNextRef.current) {
- if (delayMs > 0) {
- setTimeout(() => playNextRef.current?.(), delayMs);
- } else {
- playNextRef.current();
- }
- } else if (!autoPlayNext) {
- if (delayMs > 0) {
- setTimeout(() => {
- currentAudio.pause();
- setPlayerState((prev) => ({ ...prev, isPlaying: false }));
- }, delayMs);
- } else {
- currentAudio.pause();
- setPlayerState((prev) => ({ ...prev, isPlaying: false }));
- }
- }
- }
- }
- }
- };
-
- const handleLoadedMetadata = () => {
- const currentAudio = audioRef.current;
- if (!currentAudio) return;
-
- let effectiveDuration = currentAudio.duration;
-
- if (settingsRef.current.gaplessPlayback) {
- const offsets = calculateGaplessOffsets(
- playerStateRef.current.currentSong,
- );
-
- if (
- !gaplessStartAppliedRef.current &&
- offsets.start > 0 &&
- offsets.start < currentAudio.duration
- ) {
- try {
- currentAudio.currentTime = offsets.start;
- gaplessStartAppliedRef.current = true;
- } catch (error) {
- console.warn("Failed to apply gapless start offset:", error);
- }
- }
-
- const trimmedDuration =
- currentAudio.duration - offsets.start - offsets.end;
- if (Number.isFinite(trimmedDuration) && trimmedDuration > 0.1) {
- effectiveDuration = trimmedDuration;
- }
- }
-
- setPlayerState((prev) => ({
- ...prev,
- duration: effectiveDuration,
- }));
- };
-
- const handleEnded = (event: Event) => {
- const target = event.target as HTMLAudioElement;
-
- // Determine which element should be considered "current"
- // Use crossfade manager's active element if available, otherwise audioRef
- const activeElement =
- crossfadeManagerRef.current?.getActiveElement() || audioRef.current;
-
- // Only respond to ended events from the active element
- if (target !== activeElement) {
- return;
- }
-
- // If crossfade is in progress and current (outgoing) song ends,
- // the crossfade manager handles this via its own 'ended' listener
- // So we should not trigger playNext here
- if (crossfadeManagerRef.current?.isCrossfading()) {
- console.log(
- "Current song ended during crossfade - letting crossfade manager handle it",
- );
- // Reset the crossfade initiated flag since crossfade is completing
- crossfadeInitiatedRef.current = false;
- return;
- }
-
- if (settingsRef.current.autoPlayNext) {
- if (playerStateRef.current.repeat === "one") {
- if (audioRef.current) {
- audioRef.current.currentTime = 0;
- audioRef.current.play();
- }
- } else if (playNextRef.current) {
- // Handle different transition modes based on settings
- if (settingsRef.current.crossfade === 0) {
- // No crossfade - use gapless or with delay
- if (settingsRef.current.gaplessPlayback) {
- playNextRef.current();
- } else {
- setTimeout(() => playNextRef.current?.(), 400);
- }
- } else {
- // Crossfade is enabled - check if transition already happened or needs to happen now
- if (crossfadeManagerRef.current?.isCrossfading()) {
- // Crossfade is already in progress, let it complete naturally
- console.log("Crossfade transition already in progress");
- } else {
- // Crossfade didn't start in time (maybe song too short), do immediate transition
- console.log(
- "Starting immediate crossfade transition on song end",
- );
-
- // Clear any existing crossfade timeout to prevent conflicts
- if (crossfadeTimeoutRef.current) {
- clearTimeout(crossfadeTimeoutRef.current);
- crossfadeTimeoutRef.current = null;
- }
-
- // Start immediate crossfade with proper error handling
- startCrossfadeTransition(
- playNextRef,
- () =>
- nextSongCacheRef.current ||
- getAndCacheNextSong(
- playerStateRef,
- settingsRef,
- playHistoryRef,
- ),
- (nextSong: Song) =>
- prepareNextSongForCrossfade(
- nextSong,
- cacheSong,
- getCachedSong,
- settingsRef,
- ),
- playerStateRef,
- playHistoryRef,
- updatePlayHistory,
- setPlayerState,
- settingsRef,
- audioContextRef,
- invalidateNextSongCache,
- gaplessAdvanceTriggeredRef,
- gaplessStartAppliedRef,
- ).catch((error: any) => {
- console.error("Immediate crossfade failed:", error);
- // Fallback to regular playNext if crossfade fails
- if (playNextRef.current) {
- console.log("Falling back to regular playNext");
- playNextRef.current();
- }
- });
- }
- }
- }
- }
- };
-
- audio.addEventListener("timeupdate", handleTimeUpdate);
- audio.addEventListener("loadedmetadata", handleLoadedMetadata);
- audio.addEventListener("ended", handleEnded);
-
- // Attach timeupdate and loadedmetadata to secondary audio element for crossfading
- const nextAudio = nextAudioRef.current;
- nextAudio.addEventListener("timeupdate", handleTimeUpdate);
- nextAudio.addEventListener("loadedmetadata", handleLoadedMetadata);
-
- return () => {
- audio.removeEventListener("timeupdate", handleTimeUpdate);
- audio.removeEventListener("loadedmetadata", handleLoadedMetadata);
- audio.removeEventListener("ended", handleEnded);
-
- nextAudio.removeEventListener("timeupdate", handleTimeUpdate);
- nextAudio.removeEventListener("loadedmetadata", handleLoadedMetadata);
-
- audio.pause();
- nextAudio.pause();
- };
- }, []);
-
- const togglePlayPause = useCallback(async () => {
- const isFlo =
- playerState.currentSong?.url?.toLowerCase().endsWith(".flo") ||
- playerState.currentSong?.mimeType === "audio/x-flo" ||
- playerState.currentSong?.mimeType === "audio/wav" ||
- playerState.currentSong?.mimeType === "audio/pcm" ||
- playerState.currentSong?.encoding?.codec === "flo";
- if (isFlo && !isSafari()) {
- // AudioBufferSourceNode path
- const ctx = audioContextRef.current;
- if (!ctx || !floAudioBufferRef.current) return;
- if (floIsPlayingRef.current) {
- // Pause: stop source, record pausedAt
- try {
- floBufferSourceRef.current?.stop();
- } catch {}
- floPausedAtRef.current = ctx.currentTime - floStartTimeRef.current;
- floIsPlayingRef.current = false;
- setPlayerState((prev) => ({ ...prev, isPlaying: false }));
- } else {
- // Resume: create new source, start at pausedAt
- const source = ctx.createBufferSource();
- source.buffer = floAudioBufferRef.current;
- if (floGainNodeRef.current) {
- source.connect(floGainNodeRef.current);
- } else {
- source.connect(ctx.destination);
- }
- source.onended = () => {
- floIsPlayingRef.current = false;
- setPlayerState((prev) => ({
- ...prev,
- isPlaying: false,
- currentTime: floAudioBufferRef.current?.duration || 0,
- }));
- };
- floBufferSourceRef.current = source;
- floStartTimeRef.current = ctx.currentTime - floPausedAtRef.current;
- floIsPlayingRef.current = true;
- setPlayerState((prev) => ({ ...prev, isPlaying: true }));
- source.start(0, floPausedAtRef.current);
- }
- return;
- }
- // Default path
- if (!audioRef.current || !playerState.currentSong) return;
- if (audioContextRef.current?.state === "suspended") {
- audioContextRef.current.resume();
- }
- if (playerState.isPlaying) {
- audioRef.current.pause();
- setPlayerState((prev) => ({ ...prev, isPlaying: false }));
- updateDiscordPresence(playerState.currentSong, false);
- } else {
- if (
- !audioRef.current.src ||
- audioRef.current.src.includes("about:blank")
- ) {
- await playSong(
- playerState.currentSong,
- playerState.currentPlaylist || undefined,
- );
- return;
- }
- try {
- await audioRef.current.play();
- setPlayerState((prev) => ({ ...prev, isPlaying: true }));
- updateDiscordPresence(playerState.currentSong, true);
- } catch (error) {
- setPlayerState((prev) => ({ ...prev, isPlaying: false }));
- }
- }
- }, [
- playerState.isPlaying,
- playerState.currentSong,
- playerState.currentPlaylist,
- playSong,
- updateDiscordPresence,
- ]);
-
- const playNext = useCallback(() => {
- if (!playerState.currentPlaylist || !playerState.currentSong) return;
-
- // Cancel any ongoing crossfade when user manually skips
- if (crossfadeManagerRef.current?.isCrossfading()) {
- crossfadeManagerRef.current.cancelCrossfade();
- }
-
- // Clear any pending timeouts
- if (crossfadeTimeoutRef.current) {
- clearTimeout(crossfadeTimeoutRef.current);
- crossfadeTimeoutRef.current = null;
- }
- if (preloadTimeoutRef.current) {
- clearTimeout(preloadTimeoutRef.current);
- preloadTimeoutRef.current = null;
- }
-
- // Use cached next song if available, otherwise get it using the same logic as crossfade
- let nextSong: Song | null = null;
-
- if (nextSongCacheRef.current && nextSongCacheValidRef.current) {
- nextSong = nextSongCacheRef.current;
- // Clear the cache since we're using it
- nextSongCacheRef.current = null;
- nextSongCacheValidRef.current = false;
- } else {
- // Get next song using the same logic as crossfade
- nextSong = getAndCacheNextSong(
- playerStateRef,
- settingsRef,
- playHistoryRef,
- );
- }
-
- if (nextSong) {
- // Update play history for shuffle mode
- if (playerState.shuffle) {
- updatePlayHistory(playHistoryRef, playerState.currentSong.id);
- }
-
- playSong(nextSong, playerState.currentPlaylist);
- }
- }, [
- playerState,
- settings.smartShuffle,
- updatePlayHistory,
- playSong,
- getAndCacheNextSong,
- ]);
-
- useEffect(() => {
- playNextRef.current = playNext;
- }, [playNext]);
-
- const playPrevious = useCallback(() => {
- if (!playerState.currentPlaylist || !playerState.currentSong) return;
-
- // Cancel any ongoing crossfade when user manually skips
- if (crossfadeManagerRef.current?.isCrossfading()) {
- crossfadeManagerRef.current.cancelCrossfade();
- }
-
- // Clear any pending timeouts
- if (crossfadeTimeoutRef.current) {
- clearTimeout(crossfadeTimeoutRef.current);
- crossfadeTimeoutRef.current = null;
- }
- if (preloadTimeoutRef.current) {
- clearTimeout(preloadTimeoutRef.current);
- preloadTimeoutRef.current = null;
- }
-
- const songs = playerState.currentPlaylist.songs;
- const currentIndex = songs.findIndex(
- (s) => s.id === playerState.currentSong!.id,
- );
-
- let previousSong: Song | null = null;
-
- if (playerState.shuffle) {
- // In shuffle mode, "previous" just picks another random song using the same logic
- previousSong = getAndCacheNextSong(
- playerStateRef,
- settingsRef,
- playHistoryRef,
- );
- } else {
- // Sequential play - go to previous song
- if (currentIndex > 0) {
- previousSong = songs[currentIndex - 1];
- } else if (playerState.repeat === "all") {
- previousSong = songs[songs.length - 1];
- }
- }
-
- if (previousSong) {
- // Update play history for shuffle mode
- if (playerState.shuffle) {
- updatePlayHistory(playHistoryRef, playerState.currentSong.id);
- }
-
- playSong(previousSong, playerState.currentPlaylist);
- }
- }, [
- playerState,
- settings.smartShuffle,
- updatePlayHistory,
- playSong,
- getAndCacheNextSong,
- ]);
-
- const setVolume = useCallback((volume: number) => {
- const clamped = Math.max(0, Math.min(1, volume));
- setSettings((prev) => ({ ...prev, volume: clamped }));
-
- // Set volume for flo playback
- if (floGainNodeRef.current) {
- floGainNodeRef.current.gain.value = clamped;
- }
-
- // Safari uses native playback without Web Audio API
- const isSafari = safariAudioRef.current.isActive();
- if (isSafari) {
- if (audioRef.current) {
- audioRef.current.volume = clamped;
- }
- return;
- }
-
- // Use crossfade manager for volume control if available
- if (crossfadeManagerRef.current) {
- crossfadeManagerRef.current.setMasterVolume(clamped);
- } else if (audioRef.current) {
- audioRef.current.volume = clamped;
- }
- }, []);
-
- const toggleShuffle = useCallback(() => {
- setPlayerState((prev) => ({ ...prev, shuffle: !prev.shuffle }));
- // Invalidate next song cache when shuffle mode changes
- invalidateNextSongCache(true);
- }, [invalidateNextSongCache]);
-
- const toggleRepeat = useCallback(() => {
- setPlayerState((prev) => ({
- ...prev,
- repeat:
- prev.repeat === "off" ? "all" : prev.repeat === "all" ? "one" : "off",
- }));
- }, []);
-
- const updateSettings = useCallback((newSettings: Partial) => {
- setSettings((prev) => ({ ...prev, ...newSettings }));
- }, []);
-
- const seekTo = useCallback((time: number) => {
- // Handle flo seek
- if (
- floIsPlayingRef.current &&
- floAudioBufferRef.current &&
- audioContextRef.current
- ) {
- const ctx = audioContextRef.current;
- // Stop current source
- if (floBufferSourceRef.current) {
- try {
- floBufferSourceRef.current.stop();
- } catch {}
- floBufferSourceRef.current.disconnect();
- }
- // Create new source
- const source = ctx.createBufferSource();
- source.buffer = floAudioBufferRef.current;
- if (floGainNodeRef.current) {
- source.connect(floGainNodeRef.current);
- } else {
- source.connect(ctx.destination);
- }
- source.onended = () => {
- floIsPlayingRef.current = false;
- setPlayerState((prev) => ({
- ...prev,
- isPlaying: false,
- currentTime: floAudioBufferRef.current!.duration,
- }));
- };
- floBufferSourceRef.current = source;
- floStartTimeRef.current = ctx.currentTime - time;
- floPausedAtRef.current = 0;
- source.start(0, time);
- setPlayerState((prev) => ({ ...prev, currentTime: time }));
- return;
- }
-
- if (audioRef.current) {
- const beforeSeek = audioRef.current.currentTime;
- console.log(
- "Seeking to:",
- time,
- "from:",
- beforeSeek,
- "readyState:",
- audioRef.current.readyState,
- );
- audioRef.current.currentTime = time;
-
- // No need to sync - on Safari, audioRef.current IS the Safari element
-
- // Check if seek actually worked
- setTimeout(() => {
- const afterSeek = audioRef.current?.currentTime;
- console.log("After seek - requested:", time, "actual:", afterSeek);
- if (Math.abs((afterSeek || 0) - time) > 0.1) {
- console.warn("Seek failed or was overridden!");
- }
- }, 100);
-
- setPlayerState((prev) => ({ ...prev, currentTime: time }));
- }
- }, []);
-
- const addSong = useCallback(
- async (song: Song, file?: File) => {
- // First, update library synchronously to show song in UI immediately
- setLibrary((prev) => {
- const newSongs = [...prev.songs, song];
- const allSongsPlaylistExists = prev.playlists.some(
- (p) => p.id === "all-songs",
- );
-
- let newPlaylists = prev.playlists.map((p) =>
- p.id === "all-songs"
- ? { ...p, songs: prepareSongsForPlaylist(newSongs) }
- : p,
- );
-
- if (!allSongsPlaylistExists) {
- newPlaylists = [
- {
- id: "all-songs",
- name: t("allSongs"),
- songs: prepareSongsForPlaylist(newSongs),
- },
- ...newPlaylists,
- ];
- }
- return {
- ...prev,
- songs: newSongs,
- playlists: newPlaylists,
- };
- });
-
- // If we have the file, process and store audio in background
- if (file) {
- try {
- // Convert file directly to ArrayBuffer
- const arrayBuffer = await file.arrayBuffer();
-
- // Save to IndexedDB
- const mimeType = song.mimeType || file.type;
- await musicIndexedDbHelper.saveSongAudio(song.id, {
- fileData: arrayBuffer,
- mimeType,
- });
-
- // Update song to mark it as stored
- setLibrary((prev) => {
- const newSongs = prev.songs.map((s) =>
- s.id === song.id
- ? {
- ...s,
- hasStoredAudio: true,
- url: `indexeddb://${song.id}`,
- mimeType,
- }
- : s,
- );
- return {
- ...prev,
- songs: newSongs,
- playlists: prev.playlists.map((p) =>
- p.id === "all-songs"
- ? { ...p, songs: prepareSongsForPlaylist(newSongs) }
- : p,
- ),
- };
- });
-
- console.log(`Successfully stored audio for: ${song.title}`);
- } catch (error) {
- console.error("Failed to process song audio:", error);
- // TODO: i18n-ize
- toast.error(`Failed to process "${song.title}"`, {
- description: (error as Error).message || "Unknown error occurred",
- });
- }
- }
- },
- [prepareSongsForPlaylist, t],
- );
-
- const removeSong = useCallback(async (songId: string) => {
- // First, update library synchronously
- setLibrary((prev) => {
- const newSongs = prev.songs.filter((s) => s.id !== songId);
- const newPlaylists = prev.playlists.map((p) => {
- if ("songs" in p) {
- return {
- ...p,
- songs: p.songs.filter((s: Song) => s.id !== songId),
- };
- }
- return p;
- });
- return {
- ...prev,
- songs: newSongs,
- playlists: newPlaylists,
- favorites: prev.favorites.filter((id) => id !== songId),
- };
- });
-
- // Then, remove the audio data from IndexedDB asynchronously
- try {
- await musicIndexedDbHelper.removeSongAudio(songId);
- } catch (error) {
- console.error("Failed to remove song audio from IndexedDB:", error);
- }
- }, []);
-
- return {
- playerState,
- library,
- settings,
- searchQuery,
- isInitialized,
- playSong,
- togglePlayPause,
- playNext,
- playPrevious,
- setVolume,
- seekTo,
- toggleShuffle,
- toggleRepeat,
- updateSettings,
- addSong,
- removeSong,
- createPlaylist,
- createFolder,
- removePlaylist,
- addToPlaylist,
- reorderPlaylistSongs,
- moveSongToPlaylist,
- moveToFolder,
- addToFavorites,
- removeFromFavorites,
- toggleFavorite,
- isFavorited,
- getFavoriteSongs,
- searchSongs,
- getSearchResults,
- setSearchQuery,
- navigateToHome,
- navigateToArtist,
- navigateToAlbum,
- navigateToSongs,
- exportPlaylist,
- importPlaylist,
- };
-};
diff --git a/Build/src/hooks/useAlbumArt.tsx b/Build/src/hooks/useAlbumArt.tsx
index 1159279..1fe7e6d 100644
--- a/Build/src/hooks/useAlbumArt.tsx
+++ b/Build/src/hooks/useAlbumArt.tsx
@@ -1,26 +1,15 @@
import { useState, useEffect, useRef } from "react";
-import { musicIndexedDbHelper } from "../helpers/musicIndexedDbHelper";
+import { albumArtStorage } from "../platform/storage";
-// Cache to store loaded album arts in memory
-const loadedAlbumArts = new Map();
-// Pending load requests to avoid duplicate fetches
const pendingLoads = new Map>();
-/**
- * Hook to lazily load album art for a single song
- * Only fetches from IndexedDB when needed, uses in-memory cache
- */
export function useAlbumArt(
songId: string | undefined,
hasAlbumArt: boolean = false,
): string | undefined {
- const [albumArt, setAlbumArt] = useState(() => {
- // Check cache immediately for initial render
- if (songId && loadedAlbumArts.has(songId)) {
- return loadedAlbumArts.get(songId);
- }
- return undefined;
- });
+ const [albumArt, setAlbumArt] = useState(() =>
+ songId ? albumArtStorage.get(songId) : undefined,
+ );
useEffect(() => {
if (!songId || !hasAlbumArt) {
@@ -28,13 +17,12 @@ export function useAlbumArt(
return;
}
- // Check memory cache first
- if (loadedAlbumArts.has(songId)) {
- setAlbumArt(loadedAlbumArts.get(songId));
+ const cached = albumArtStorage.get(songId);
+ if (cached) {
+ setAlbumArt(cached);
return;
}
- // Check if already loading
if (pendingLoads.has(songId)) {
pendingLoads.get(songId)!.then((art) => {
if (art) setAlbumArt(art);
@@ -42,16 +30,12 @@ export function useAlbumArt(
return;
}
- // Start loading
- const loadPromise = musicIndexedDbHelper.loadAlbumArt(songId);
+ const loadPromise = albumArtStorage.load(songId);
pendingLoads.set(songId, loadPromise);
loadPromise
.then((art) => {
- if (art) {
- loadedAlbumArts.set(songId, art);
- setAlbumArt(art);
- }
+ if (art) setAlbumArt(art);
})
.finally(() => {
pendingLoads.delete(songId);
@@ -61,10 +45,6 @@ export function useAlbumArt(
return albumArt;
}
-/**
- * Hook to batch load album art for visible songs
- * More efficient for lists - loads multiple arts in one IndexedDB transaction
- */
export function useAlbumArtBatch(
songs: Array<{ id: string; hasAlbumArt?: boolean }>,
): Map {
@@ -74,87 +54,33 @@ export function useAlbumArtBatch(
useEffect(() => {
if (songs.length === 0) return;
- // Find songs that need loading
const toLoad = songs.filter(
(song) =>
song.hasAlbumArt &&
- !loadedAlbumArts.has(song.id) &&
+ !albumArtStorage.has(song.id) &&
!loadedRef.current.has(song.id),
);
if (toLoad.length === 0) {
- // All already cached, update state if needed
const cached = new Map();
for (const song of songs) {
- if (loadedAlbumArts.has(song.id)) {
- cached.set(song.id, loadedAlbumArts.get(song.id)!);
- }
- }
- if (cached.size > 0) {
- setAlbumArts(cached);
+ const art = albumArtStorage.get(song.id);
+ if (art) cached.set(song.id, art);
}
+ if (cached.size > 0) setAlbumArts(cached);
return;
}
- // Mark as loading to prevent duplicate requests
toLoad.forEach((song) => loadedRef.current.add(song.id));
-
- // Batch load
- musicIndexedDbHelper
- .loadAlbumArtBatch(toLoad.map((s) => s.id))
- .then((loaded) => {
- // Update memory cache
- loaded.forEach((art, songId) => {
- loadedAlbumArts.set(songId, art);
- });
-
- // Update state with all cached arts
- const allArts = new Map