From f5315aacb88ba52f5ca0c1ad83af87b51745724b Mon Sep 17 00:00:00 2001 From: vorotamoroz Date: Wed, 22 Oct 2025 13:56:15 +0100 Subject: [PATCH] v0.25.23.beta1 ### Fixed (This should be backported to 0.25.22 if the beta phase is prolonged) - No longer larger files will not create a chunks during preparing `Reset Synchronisation on This Device`. ### Behaviour changes - Setup wizard is now more `goal-oriented`. Brand-new screens are introduced. - `Fetch everything` and `Rebuild everything` is now `Reset Synchronisation on This Device` and `Overwrite Server Data with This Device's Files`. - Remote configuration and E2EE settings are now separated to each modal dialogue. - Peer-to-Peer settings is also separated into its own modal dialogue. - Setup-URI, and Report for the Issue are now not copied to clipboard automatically. Instead, there are copy dialogue and buttons to copy them explicitly. - No longer optional features are introduced during the setup or `Reset Synchronisation on This Device`, `Overwrite Server Data with This Device's Files`. - We cannot preform `Fetch everything` and `Rebuild everything` (Removed, so the old name) without restarting Obsidian now. ### Miscellaneous - Setup QR Code generation is separated into a src/lib/src/API/processSetting.ts file. Please use it as a subrepository if you want to generate QR codes in your own application. - Setup-URI is also separated into a src/lib/src/API/processSetting.ts - Some direct access to web-APIs are now wrapped into the services layer. ### Dependency updates - Many dependencies are updated. Please see `package.json`. - As upgrading TypeScript, Fixed many UInt8Array and Uint8Array type mismatches. --- manifest-beta.json | 2 +- manifest.json | 2 +- package-lock.json | 3552 ++++++++++++----- package.json | 31 +- src/features/P2PSync/CmdP2PReplicator.ts | 12 +- .../P2PReplicator/P2PReplicatorPane.svelte | 5 +- src/lib | 2 +- src/main.ts | 12 +- src/modules/core/ModuleFileHandler.ts | 4 + src/modules/core/ModuleRebuilder.ts | 18 +- src/modules/coreFeatures/ModuleRedFlag.ts | 440 +- src/modules/essential/ModuleMigration.ts | 13 +- .../essentialObsidian/ModuleObsidianAPI.ts | 2 +- src/modules/features/ModuleSetupObsidian.ts | 762 ++-- .../features/SettingDialogue/InfoPanel.svelte | 80 + .../features/SettingDialogue/PaneHatch.ts | 12 +- .../SettingDialogue/PaneMaintenance.ts | 93 +- .../SettingDialogue/PaneRemoteConfig.ts | 1031 ++--- .../features/SettingDialogue/PaneSetup.ts | 11 +- .../features/SettingDialogue/SveltePanel.ts | 54 + .../features/SettingDialogue/settingUtils.ts | 78 + .../SettingDialogue/utilFixCouchDBSetting.ts | 274 ++ .../SetupWizard/ObsidianSvelteDialog.ts | 141 + .../dialogs/FetchEverything.svelte | 154 + .../features/SetupWizard/dialogs/Intro.svelte | 55 + .../dialogs/OutroAskUserMode.svelte | 75 + .../dialogs/OutroExistingUser.svelte | 37 + .../SetupWizard/dialogs/OutroNewUser.svelte | 38 + .../dialogs/PanelCouchDBCheck.svelte | 141 + .../dialogs/RebuildEverything.svelte | 126 + .../SetupWizard/dialogs/ScanQRCode.svelte | 28 + .../dialogs/SelectMethodExisting.svelte | 62 + .../dialogs/SelectMethodNewUser.svelte | 57 + .../SetupWizard/dialogs/SetupRemote.svelte | 56 + .../dialogs/SetupRemoteBucket.svelte | 241 ++ .../dialogs/SetupRemoteCouchDB.svelte | 284 ++ .../dialogs/SetupRemoteE2EE.svelte | 123 + .../SetupWizard/dialogs/SetupRemoteP2P.svelte | 255 ++ .../SetupWizard/dialogs/UseSetupURI.svelte | 96 + .../SetupWizard/dialogs/utilCheckCouchDB.ts | 293 ++ src/modules/services/ObsidianServices.ts | 15 + src/modules/services/ObsidianUIService.ts | 40 + 42 files changed, 6546 insertions(+), 2261 deletions(-) create mode 100644 src/modules/features/SettingDialogue/InfoPanel.svelte create mode 100644 src/modules/features/SettingDialogue/SveltePanel.ts create mode 100644 src/modules/features/SettingDialogue/settingUtils.ts create mode 100644 src/modules/features/SettingDialogue/utilFixCouchDBSetting.ts create mode 100644 src/modules/features/SetupWizard/ObsidianSvelteDialog.ts create mode 100644 src/modules/features/SetupWizard/dialogs/FetchEverything.svelte create mode 100644 src/modules/features/SetupWizard/dialogs/Intro.svelte create mode 100644 src/modules/features/SetupWizard/dialogs/OutroAskUserMode.svelte create mode 100644 src/modules/features/SetupWizard/dialogs/OutroExistingUser.svelte create mode 100644 src/modules/features/SetupWizard/dialogs/OutroNewUser.svelte create mode 100644 src/modules/features/SetupWizard/dialogs/PanelCouchDBCheck.svelte create mode 100644 src/modules/features/SetupWizard/dialogs/RebuildEverything.svelte create mode 100644 src/modules/features/SetupWizard/dialogs/ScanQRCode.svelte create mode 100644 src/modules/features/SetupWizard/dialogs/SelectMethodExisting.svelte create mode 100644 src/modules/features/SetupWizard/dialogs/SelectMethodNewUser.svelte create mode 100644 src/modules/features/SetupWizard/dialogs/SetupRemote.svelte create mode 100644 src/modules/features/SetupWizard/dialogs/SetupRemoteBucket.svelte create mode 100644 src/modules/features/SetupWizard/dialogs/SetupRemoteCouchDB.svelte create mode 100644 src/modules/features/SetupWizard/dialogs/SetupRemoteE2EE.svelte create mode 100644 src/modules/features/SetupWizard/dialogs/SetupRemoteP2P.svelte create mode 100644 src/modules/features/SetupWizard/dialogs/UseSetupURI.svelte create mode 100644 src/modules/features/SetupWizard/dialogs/utilCheckCouchDB.ts create mode 100644 src/modules/services/ObsidianUIService.ts diff --git a/manifest-beta.json b/manifest-beta.json index 7885ae5..04f26f6 100644 --- a/manifest-beta.json +++ b/manifest-beta.json @@ -1,7 +1,7 @@ { "id": "obsidian-livesync", "name": "Self-hosted LiveSync", - "version": "0.25.21.beta2", + "version": "0.25.23.beta1", "minAppVersion": "0.9.12", "description": "Community implementation of self-hosted livesync. Reflect your vault changes to some other devices immediately. Please make sure to disable other synchronize solutions to avoid content corruption or duplication.", "author": "vorotamoroz", diff --git a/manifest.json b/manifest.json index 311f8a7..04f26f6 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "obsidian-livesync", "name": "Self-hosted LiveSync", - "version": "0.25.22", + "version": "0.25.23.beta1", "minAppVersion": "0.9.12", "description": "Community implementation of self-hosted livesync. Reflect your vault changes to some other devices immediately. Please make sure to disable other synchronize solutions to avoid content corruption or duplication.", "author": "vorotamoroz", diff --git a/package-lock.json b/package-lock.json index 3df7526..ec1f56e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "obsidian-livesync", - "version": "0.25.22", + "version": "0.25.23.beta1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "obsidian-livesync", - "version": "0.25.22", + "version": "0.25.23.beta1", "license": "MIT", "dependencies": { "@aws-sdk/client-s3": "^3.808.0", @@ -29,7 +29,8 @@ "@eslint/compat": "^1.2.7", "@eslint/eslintrc": "^3.3.0", "@eslint/js": "^9.21.0", - "@tsconfig/svelte": "^5.0.4", + "@sveltejs/vite-plugin-svelte": "^6.2.1", + "@tsconfig/svelte": "^5.0.5", "@types/deno": "^2.3.0", "@types/diff-match-patch": "^1.0.36", "@types/node": "^22.13.8", @@ -41,15 +42,15 @@ "@types/pouchdb-mapreduce": "^6.1.10", "@types/pouchdb-replication": "^6.4.7", "@types/transform-pouch": "^1.0.6", - "@typescript-eslint/eslint-plugin": "8.25.0", - "@typescript-eslint/parser": "8.25.0", + "@typescript-eslint/eslint-plugin": "8.46.2", + "@typescript-eslint/parser": "8.46.2", "builtin-modules": "5.0.0", "esbuild": "0.25.0", "esbuild-plugin-inline-worker": "^0.1.1", - "esbuild-svelte": "^0.9.0", - "eslint": "^9.21.0", - "eslint-plugin-import": "^2.31.0", - "eslint-plugin-svelte": "^3.0.2", + "esbuild-svelte": "^0.9.3", + "eslint": "^9.38.0", + "eslint-plugin-import": "^2.32.0", + "eslint-plugin-svelte": "^3.12.4", "events": "^3.3.0", "glob": "^11.0.3", "obsidian": "^1.8.7", @@ -67,14 +68,14 @@ "pouchdb-replication": "^9.0.0", "pouchdb-utils": "^9.0.0", "prettier": "3.5.2", - "svelte": "5.28.6", - "svelte-check": "^4.1.7", + "svelte": "5.41.1", + "svelte-check": "^4.3.3", "svelte-preprocess": "^6.0.3", "terser": "^5.39.0", "transform-pouch": "^2.0.0", "tslib": "^2.8.1", - "tsx": "^4.19.4", - "typescript": "5.7.3", + "tsx": "^4.20.6", + "typescript": "5.9.3", "yaml": "^2.8.0" } }, @@ -87,20 +88,6 @@ "node": ">=0.10.0" } }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@aws-crypto/crc32": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", @@ -1514,9 +1501,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", - "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", "dev": true, "license": "MIT", "dependencies": { @@ -1561,13 +1548,13 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", - "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.6", + "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.2" }, @@ -1575,17 +1562,6 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@eslint/config-array/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/@eslint/config-array/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -1600,19 +1576,22 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.0.tgz", - "integrity": "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.1.tgz", + "integrity": "sha512-csZAzkNhsgwb0I/UAV6/RGFTbiakPCf0ZrGmrIxQpYvGZ00PhTkSnyKNolphgIvmnJeGw6rcGVEXfTzUnFuEvw==", "dev": true, "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.16.0" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/core": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz", - "integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==", + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.16.0.tgz", + "integrity": "sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1646,17 +1625,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@eslint/eslintrc/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/@eslint/eslintrc/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -1671,9 +1639,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.31.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.31.0.tgz", - "integrity": "sha512-LOm5OVt7D4qiKCqoiPbA7LWmI+tbw1VbTUowBcUMgQSuM6poJufkFkYDcQpo5KfgD39TnNySV26QjOh7VFpSyw==", + "version": "9.38.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.38.0.tgz", + "integrity": "sha512-UZ1VpFvXf9J06YG9xQBdnzU+kthors6KjhMAl6f4gH4usHyh31rUf2DLGInT8RFYIReYXNSydgPY0V2LuWgl7A==", "dev": true, "license": "MIT", "engines": { @@ -1684,9 +1652,9 @@ } }, "node_modules/@eslint/object-schema": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", - "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1694,13 +1662,13 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.4.tgz", - "integrity": "sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.0.tgz", + "integrity": "sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.15.1", + "@eslint/core": "^0.16.0", "levn": "^0.4.1" }, "engines": { @@ -2623,6 +2591,17 @@ "node": ">=6.0.0" } }, + "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.0", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", @@ -3208,6 +3187,336 @@ "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", "license": "BSD-3-Clause" }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.5.tgz", + "integrity": "sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "peer": true + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.5.tgz", + "integrity": "sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "peer": true + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.5.tgz", + "integrity": "sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.5.tgz", + "integrity": "sha512-W901Pla8Ya95WpxDn//VF9K9u2JbocwV/v75TE0YIHNTbhqUTv9w4VuQ9MaWlNOkkEfFwkdNhXgcLqPSmHy0fA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.5.tgz", + "integrity": "sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "peer": true + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.5.tgz", + "integrity": "sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.5.tgz", + "integrity": "sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.5.tgz", + "integrity": "sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.5.tgz", + "integrity": "sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.5.tgz", + "integrity": "sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.5.tgz", + "integrity": "sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.5.tgz", + "integrity": "sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.5.tgz", + "integrity": "sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.5.tgz", + "integrity": "sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.5.tgz", + "integrity": "sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.5.tgz", + "integrity": "sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.5.tgz", + "integrity": "sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.5.tgz", + "integrity": "sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "peer": true + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.5.tgz", + "integrity": "sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.5.tgz", + "integrity": "sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.5.tgz", + "integrity": "sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.5.tgz", + "integrity": "sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true + }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -4057,11 +4366,51 @@ "acorn": "^8.9.0" } }, + "node_modules/@sveltejs/vite-plugin-svelte": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-6.2.1.tgz", + "integrity": "sha512-YZs/OSKOQAQCnJvM/P+F1URotNnYNeU3P2s4oIpzm1uFaqUEqRxUB0g5ejMjEb5Gjb9/PiBI5Ktrq4rUUF8UVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sveltejs/vite-plugin-svelte-inspector": "^5.0.0", + "debug": "^4.4.1", + "deepmerge": "^4.3.1", + "magic-string": "^0.30.17", + "vitefu": "^1.1.1" + }, + "engines": { + "node": "^20.19 || ^22.12 || >=24" + }, + "peerDependencies": { + "svelte": "^5.0.0", + "vite": "^6.3.0 || ^7.0.0" + } + }, + "node_modules/@sveltejs/vite-plugin-svelte-inspector": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-5.0.1.tgz", + "integrity": "sha512-ubWshlMk4bc8mkwWbg6vNvCeT7lGQojE3ijDh3QTR6Zr/R+GXxsGbyH4PExEPpiFmqPhYiVSVmHBjUcVc1JIrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.1" + }, + "engines": { + "node": "^20.19 || ^22.12 || >=24" + }, + "peerDependencies": { + "@sveltejs/vite-plugin-svelte": "^6.0.0-next.0", + "svelte": "^5.0.0", + "vite": "^6.3.0 || ^7.0.0" + } + }, "node_modules/@tsconfig/svelte": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/svelte/-/svelte-5.0.4.tgz", - "integrity": "sha512-BV9NplVgLmSi4mwKzD8BD/NQ8erOY/nUE/GpgWe2ckx+wIQF5RyRirn/QsSSCPeulVpc3RA/iJt6DpfTIZps0Q==", - "dev": true + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@tsconfig/svelte/-/svelte-5.0.5.tgz", + "integrity": "sha512-48fAnUjKye38FvMiNOj0J9I/4XlQQiZlpe9xaNPfe8vy2Y1hFBt8g1yqf2EGjVvHavo4jf2lC+TQyENCr4BJBQ==", + "dev": true, + "license": "MIT" }, "node_modules/@types/codemirror": { "version": "5.60.8", @@ -4104,9 +4453,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "dev": true, "license": "MIT" }, @@ -4368,21 +4717,21 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.25.0.tgz", - "integrity": "sha512-VM7bpzAe7JO/BFf40pIT1lJqS/z1F8OaSsUB3rpFJucQA4cOSuH2RVVVkFULN+En0Djgr29/jb4EQnedUo95KA==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.2.tgz", + "integrity": "sha512-ZGBMToy857/NIPaaCucIUQgqueOiq7HeAKkhlvqVV4lm089zUFW6ikRySx2v+cAhKeUCPuWVHeimyk6Dw1iY3w==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.25.0", - "@typescript-eslint/type-utils": "8.25.0", - "@typescript-eslint/utils": "8.25.0", - "@typescript-eslint/visitor-keys": "8.25.0", + "@typescript-eslint/scope-manager": "8.46.2", + "@typescript-eslint/type-utils": "8.46.2", + "@typescript-eslint/utils": "8.46.2", + "@typescript-eslint/visitor-keys": "8.46.2", "graphemer": "^1.4.0", - "ignore": "^5.3.1", + "ignore": "^7.0.0", "natural-compare": "^1.4.0", - "ts-api-utils": "^2.0.1" + "ts-api-utils": "^2.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4392,22 +4741,32 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "@typescript-eslint/parser": "^8.46.2", "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/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/@typescript-eslint/parser": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.25.0.tgz", - "integrity": "sha512-4gbs64bnbSzu4FpgMiQ1A+D+urxkoJk/kqlDJ2W//5SygaEiAP2B4GoS7TEdxgwol2el03gckFV9lJ4QOMiiHg==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.2.tgz", + "integrity": "sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.25.0", - "@typescript-eslint/types": "8.25.0", - "@typescript-eslint/typescript-estree": "8.25.0", - "@typescript-eslint/visitor-keys": "8.25.0", + "@typescript-eslint/scope-manager": "8.46.2", + "@typescript-eslint/types": "8.46.2", + "@typescript-eslint/typescript-estree": "8.46.2", + "@typescript-eslint/visitor-keys": "8.46.2", "debug": "^4.3.4" }, "engines": { @@ -4419,18 +4778,40 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.25.0.tgz", - "integrity": "sha512-6PPeiKIGbgStEyt4NNXa2ru5pMzQ8OYKO1hX1z53HMomrmiSB+R5FmChgQAP1ro8jMtNawz+TRQo/cSXrauTpg==", + "node_modules/@typescript-eslint/project-service": { + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.2.tgz", + "integrity": "sha512-PULOLZ9iqwI7hXcmL4fVfIsBi6AN9YxRc0frbvmg8f+4hQAjQ5GYNKK0DIArNo+rOKmR/iBYwkpBmnIwin4wBg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.25.0", - "@typescript-eslint/visitor-keys": "8.25.0" + "@typescript-eslint/tsconfig-utils": "^8.46.2", + "@typescript-eslint/types": "^8.46.2", + "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": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.2.tgz", + "integrity": "sha512-LF4b/NmGvdWEHD2H4MsHD8ny6JpiVNDzrSZr3CsckEgCbAGZbYM4Cqxvi9L+WqDMT+51Ozy7lt2M+d0JLEuBqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.46.2", + "@typescript-eslint/visitor-keys": "8.46.2" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4440,17 +4821,35 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.2.tgz", + "integrity": "sha512-a7QH6fw4S57+F5y2FIxxSDyi5M4UfGF+Jl1bCGd7+L4KsaUY80GsiF/t0UoRFDHAguKlBaACWJRmdrc6Xfkkag==", + "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.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.25.0.tgz", - "integrity": "sha512-d77dHgHWnxmXOPJuDWO4FDWADmGQkN5+tt6SFRZz/RtCWl4pHgFl3+WdYCn16+3teG09DY6XtEpf3gGD0a186g==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.2.tgz", + "integrity": "sha512-HbPM4LbaAAt/DjxXaG9yiS9brOOz6fabal4uvUmaUYe6l3K1phQDMQKBRUrr06BQkxkvIZVVHttqiybM9nJsLA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.25.0", - "@typescript-eslint/utils": "8.25.0", + "@typescript-eslint/types": "8.46.2", + "@typescript-eslint/typescript-estree": "8.46.2", + "@typescript-eslint/utils": "8.46.2", "debug": "^4.3.4", - "ts-api-utils": "^2.0.1" + "ts-api-utils": "^2.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4461,13 +4860,13 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.25.0.tgz", - "integrity": "sha512-+vUe0Zb4tkNgznQwicsvLUJgZIRs6ITeWSCclX1q85pR1iOiaj+4uZJIUp//Z27QWu5Cseiw3O3AR8hVpax7Aw==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.2.tgz", + "integrity": "sha512-lNCWCbq7rpg7qDsQrd3D6NyWYu+gkTENkG5IKYhUIcxSb59SQC/hEQ+MrG4sTgBVghTonNWq42bA/d4yYumldQ==", "dev": true, "license": "MIT", "engines": { @@ -4479,20 +4878,22 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.25.0.tgz", - "integrity": "sha512-ZPaiAKEZ6Blt/TPAx5Ot0EIB/yGtLI2EsGoY6F7XKklfMxYQyvtL+gT/UCqkMzO0BVFHLDlzvFqQzurYahxv9Q==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.2.tgz", + "integrity": "sha512-f7rW7LJ2b7Uh2EiQ+7sza6RDZnajbNbemn54Ob6fRwQbgcIn+GWfyuHDHRYgRoZu1P4AayVScrRW+YfbTvPQoQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.25.0", - "@typescript-eslint/visitor-keys": "8.25.0", + "@typescript-eslint/project-service": "8.46.2", + "@typescript-eslint/tsconfig-utils": "8.46.2", + "@typescript-eslint/types": "8.46.2", + "@typescript-eslint/visitor-keys": "8.46.2", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", - "ts-api-utils": "^2.0.1" + "ts-api-utils": "^2.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4502,7 +4903,17 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <5.8.0" + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/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/@typescript-eslint/typescript-estree/node_modules/minimatch": { @@ -4522,16 +4933,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.25.0.tgz", - "integrity": "sha512-syqRbrEv0J1wywiLsK60XzHnQe/kRViI3zwFALrNEgnntn1l24Ra2KvOAWwWbWZ1lBZxZljPDGOq967dsl6fkA==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.2.tgz", + "integrity": "sha512-sExxzucx0Tud5tE0XqR0lT0psBQvEpnpiul9XbGUB1QwpWJJAps1O/Z7hJxLGiZLBKMCutjTzDgmd1muEhBnVg==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.25.0", - "@typescript-eslint/types": "8.25.0", - "@typescript-eslint/typescript-estree": "8.25.0" + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.46.2", + "@typescript-eslint/types": "8.46.2", + "@typescript-eslint/typescript-estree": "8.46.2" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4542,18 +4953,18 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.25.0.tgz", - "integrity": "sha512-kCYXKAum9CecGVHGij7muybDfTS2sD3t0L4bJsEZLkyrXUImiCTq1M3LG2SRtOhiHFwMR9wAFplpT6XHYjTkwQ==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.2.tgz", + "integrity": "sha512-tUFMXI4gxzzMXt4xpGJEsBsTox0XbNQ1y94EwlD/CuZwFcQP79xfQqMhau9HsRc/J0cAPA/HZt1dZPtGn9V/7w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.25.0", - "eslint-visitor-keys": "^4.2.0" + "@typescript-eslint/types": "8.46.2", + "eslint-visitor-keys": "^4.2.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4985,13 +5396,14 @@ } }, "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "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-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" }, "engines": { "node": ">= 0.4" @@ -5001,18 +5413,20 @@ } }, "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "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.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "is-string": "^1.0.7" + "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" @@ -5022,18 +5436,19 @@ } }, "node_modules/array.prototype.findlastindex": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", - "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", + "es-abstract": "^1.23.9", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -5043,15 +5458,16 @@ } }, "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "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.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "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" @@ -5061,15 +5477,16 @@ } }, "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "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.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "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" @@ -5079,19 +5496,19 @@ } }, "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "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.5", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" + "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" @@ -5109,11 +5526,22 @@ "node": "*" } }, + "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/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" }, @@ -5179,13 +5607,14 @@ "license": "MIT" }, "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==", + "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" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, "node_modules/braces": { @@ -5244,16 +5673,16 @@ } }, "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "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", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "set-function-length": "^1.2.2" }, "engines": { "node": ">= 0.4" @@ -5493,15 +5922,15 @@ } }, "node_modules/data-view-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", - "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "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-bind": "^1.0.6", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "is-data-view": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -5511,31 +5940,31 @@ } }, "node_modules/data-view-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", - "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "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-bind": "^1.0.7", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "is-data-view": "^1.0.2" }, "engines": { "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/inspect-js" } }, "node_modules/data-view-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", - "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "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-bind": "^1.0.6", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" }, @@ -5599,6 +6028,16 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "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/deferred-leveldown": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-5.3.0.tgz", @@ -5792,58 +6231,66 @@ } }, "node_modules/es-abstract": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", - "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "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.1", - "arraybuffer.prototype.slice": "^1.0.3", + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "data-view-buffer": "^1.0.1", - "data-view-byte-length": "^1.0.1", - "data-view-byte-offset": "^1.0.0", - "es-define-property": "^1.0.0", + "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.0.0", - "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", - "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", + "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.0.3", - "has-symbols": "^1.0.3", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", "hasown": "^2.0.2", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", - "is-data-view": "^1.0.1", + "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", + "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.5", - "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.2", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.9", - "string.prototype.trimend": "^1.0.8", + "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.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.6", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.15" + "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" @@ -5885,37 +6332,44 @@ } }, "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "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": { - "get-intrinsic": "^1.2.4", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" + "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" } }, "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "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.0" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "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.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" }, "engines": { "node": ">= 0.4" @@ -5976,9 +6430,9 @@ } }, "node_modules/esbuild-svelte": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/esbuild-svelte/-/esbuild-svelte-0.9.2.tgz", - "integrity": "sha512-8Jq6+rh+g1E2mkBOZKdYZ8JtlbtDq2Fydwvn+/cBvUX9S0cdKv6AISZcEbErKQ0TpLC/Cv04l1vKaqXOBO8+VQ==", + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/esbuild-svelte/-/esbuild-svelte-0.9.3.tgz", + "integrity": "sha512-CgEcGY1r/d16+aggec3czoFBEBaYIrFOnMxpsO6fWNaNEqHregPN5DLAPZDqrL7rXDNplW+WMu8s3GMq9FqgJA==", "dev": true, "license": "MIT", "dependencies": { @@ -6014,25 +6468,24 @@ } }, "node_modules/eslint": { - "version": "9.31.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.31.0.tgz", - "integrity": "sha512-QldCVh/ztyKJJZLr4jXNUByx3gR+TDYZCRXEktiZoUR3PGy4qCmSbkxcIle8GEwGpb5JBZazlaJ/CxLidXdEbQ==", + "version": "9.38.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.38.0.tgz", + "integrity": "sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.0", - "@eslint/config-helpers": "^0.3.0", - "@eslint/core": "^0.15.0", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.1", + "@eslint/core": "^0.16.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.31.0", - "@eslint/plugin-kit": "^0.3.1", + "@eslint/js": "9.38.0", + "@eslint/plugin-kit": "^0.4.0", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", @@ -6095,9 +6548,9 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", - "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", "dev": true, "license": "MIT", "dependencies": { @@ -6123,30 +6576,30 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.31.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", - "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", "dependencies": { "@rtsao/scc": "^1.1.0", - "array-includes": "^3.1.8", - "array.prototype.findlastindex": "^1.2.5", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.12.0", + "eslint-module-utils": "^2.12.1", "hasown": "^2.0.2", - "is-core-module": "^2.15.1", + "is-core-module": "^2.16.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "object.groupby": "^1.0.3", - "object.values": "^1.2.0", + "object.values": "^1.2.1", "semver": "^6.3.1", - "string.prototype.trimend": "^1.0.8", + "string.prototype.trimend": "^1.0.9", "tsconfig-paths": "^3.15.0" }, "engines": { @@ -6156,17 +6609,6 @@ "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, - "node_modules/eslint-plugin-import/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/eslint-plugin-import/node_modules/debug": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", @@ -6210,21 +6652,22 @@ } }, "node_modules/eslint-plugin-svelte": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-3.6.0.tgz", - "integrity": "sha512-IIf6Cj6yQuCwL7Qd8bX13BZspz+DQsOkClozMF9EkW20FSxI75Ndd5ZzbviCn32DdXRo9FUWXn+YMIL46qPOOg==", + "version": "3.12.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-3.12.5.tgz", + "integrity": "sha512-4KRG84eAHQfYd9OjZ1K7sCHy0nox+9KwT+s5WCCku3jTim5RV4tVENob274nCwIaApXsYPKAUAZFBxKZ3Wyfjw==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.1", + "@eslint-community/eslint-utils": "^4.6.1", "@jridgewell/sourcemap-codec": "^1.5.0", "esutils": "^2.0.3", - "known-css-properties": "^0.36.0", + "globals": "^16.0.0", + "known-css-properties": "^0.37.0", "postcss": "^8.4.49", "postcss-load-config": "^3.1.4", "postcss-safe-parser": "^7.0.0", "semver": "^7.6.3", - "svelte-eslint-parser": "^1.1.1" + "svelte-eslint-parser": "^1.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6242,6 +6685,19 @@ } } }, + "node_modules/eslint-plugin-svelte/node_modules/globals": { + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz", + "integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/eslint-plugin-svelte/node_modules/lilconfig": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", @@ -6321,17 +6777,6 @@ "url": "https://opencollective.com/eslint" } }, - "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, - "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", @@ -6408,9 +6853,9 @@ } }, "node_modules/esrap": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/esrap/-/esrap-1.4.6.tgz", - "integrity": "sha512-F/D2mADJ9SHY3IwksD4DAXjTt7qt7GWUf3/8RhCNWmC/67tyb55dpimHmy7EplakFaflV0R/PC+fdSPqrRHAQw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.1.0.tgz", + "integrity": "sha512-yzmPNpl7TBbMRC5Lj2JlJZNPml0tzqoqP5B1JXycNUwtqma9AKCO0M2wHrdgsHcy1WRW7S9rJknAMtByg3usgA==", "dev": true, "license": "MIT", "dependencies": { @@ -6716,12 +7161,19 @@ "license": "ISC" }, "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", "dev": true, + "license": "MIT", "dependencies": { - "is-callable": "^1.1.3" + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/foreground-child": { @@ -6766,15 +7218,18 @@ } }, "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "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": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" + "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" @@ -6795,10 +7250,21 @@ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "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", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -6863,14 +7329,15 @@ } }, "node_modules/get-symbol-description": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "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": { - "call-bind": "^1.0.5", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -6942,12 +7409,14 @@ } }, "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "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": { - "define-properties": "^1.1.3" + "define-properties": "^1.2.1", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -6976,10 +7445,14 @@ "dev": true }, "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "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", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -7006,10 +7479,14 @@ } }, "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "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": { + "dunder-proto": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -7035,6 +7512,7 @@ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, + "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" }, @@ -7108,10 +7586,11 @@ "license": "BSD-3-Clause" }, "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } @@ -7171,14 +7650,15 @@ "license": "Apache-2.0 OR MIT" }, "node_modules/internal-slot": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "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.0", - "side-channel": "^1.0.4" + "hasown": "^2.0.2", + "side-channel": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -7198,13 +7678,35 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "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.2", - "get-intrinsic": "^1.2.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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", + "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" @@ -7214,25 +7716,30 @@ } }, "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "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", "dependencies": { - "has-bigints": "^1.0.1" + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "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": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -7246,6 +7753,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": ">= 0.4" }, @@ -7254,9 +7762,9 @@ } }, "node_modules/is-core-module": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", - "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "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": { @@ -7270,12 +7778,14 @@ } }, "node_modules/is-data-view": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", - "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "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": "MIT", "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" }, "engines": { @@ -7286,12 +7796,14 @@ } }, "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "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": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -7315,6 +7827,22 @@ "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-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "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", @@ -7324,6 +7852,26 @@ "node": ">=8" } }, + "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-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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -7342,6 +7890,19 @@ "integrity": "sha512-26POf2KRCno/KTNL5Q0b/9TYnL00xEsSaLfiFRmjM7m7Lw7ZMmFybzzuX4CcsLAluZGd+niLUiMRxEooVE3aqg==", "license": "MIT" }, + "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", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-negative-zero": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", @@ -7377,12 +7938,14 @@ } }, "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "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": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -7414,13 +7977,16 @@ } }, "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "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": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -7429,13 +7995,27 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "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", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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": "MIT", "dependencies": { - "call-bind": "^1.0.7" + "call-bound": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -7445,12 +8025,14 @@ } }, "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "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": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -7460,12 +8042,15 @@ } }, "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "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, + "license": "MIT", "dependencies": { - "has-symbols": "^1.0.2" + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -7475,12 +8060,13 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "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.14" + "which-typed-array": "^1.1.16" }, "engines": { "node": ">= 0.4" @@ -7489,13 +8075,47 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "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", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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": { - "call-bind": "^1.0.2" + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7505,7 +8125,8 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/isexe": { "version": "2.0.0", @@ -7890,9 +8511,9 @@ } }, "node_modules/known-css-properties": { - "version": "0.36.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.36.0.tgz", - "integrity": "sha512-A+9jP+IUmuQsNdsLdcg6Yt7voiMF/D4K83ew0OpJtpu+l34ef7LaohWV0Rc6KNvzw6ZDizkqfyB5JznZnzuKQA==", + "version": "0.37.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.37.0.tgz", + "integrity": "sha512-JCDrsP4Z1Sb9JwG0aJ8Eo2r7k4Ou5MwmThS/6lcIe1ICyb7UBJKGRIUUdqc2ASdE/42lgz6zFUnzAIhtXnBVrQ==", "dev": true, "license": "MIT" }, @@ -8435,9 +9056,9 @@ "license": "Apache-2.0 OR MIT" }, "node_modules/nanoid": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", - "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "dev": true, "funding": [ { @@ -8445,6 +9066,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -8520,14 +9142,17 @@ } }, "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", "object-keys": "^1.1.1" }, "engines": { @@ -8572,13 +9197,14 @@ } }, "node_modules/object.values": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", - "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" }, @@ -8630,6 +9256,24 @@ "node": ">= 0.8.0" } }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/p-defer": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-4.0.1.tgz", @@ -8907,18 +9551,19 @@ } }, "node_modules/possible-typed-array-names": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/postcss": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "dev": true, "funding": [ { @@ -8936,7 +9581,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.8", + "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -9519,16 +10164,42 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", - "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", - "set-function-name": "^2.0.1" + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -9615,6 +10286,49 @@ "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "license": "MIT" }, + "node_modules/rollup": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.5.tgz", + "integrity": "sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.52.5", + "@rollup/rollup-android-arm64": "4.52.5", + "@rollup/rollup-darwin-arm64": "4.52.5", + "@rollup/rollup-darwin-x64": "4.52.5", + "@rollup/rollup-freebsd-arm64": "4.52.5", + "@rollup/rollup-freebsd-x64": "4.52.5", + "@rollup/rollup-linux-arm-gnueabihf": "4.52.5", + "@rollup/rollup-linux-arm-musleabihf": "4.52.5", + "@rollup/rollup-linux-arm64-gnu": "4.52.5", + "@rollup/rollup-linux-arm64-musl": "4.52.5", + "@rollup/rollup-linux-loong64-gnu": "4.52.5", + "@rollup/rollup-linux-ppc64-gnu": "4.52.5", + "@rollup/rollup-linux-riscv64-gnu": "4.52.5", + "@rollup/rollup-linux-riscv64-musl": "4.52.5", + "@rollup/rollup-linux-s390x-gnu": "4.52.5", + "@rollup/rollup-linux-x64-gnu": "4.52.5", + "@rollup/rollup-linux-x64-musl": "4.52.5", + "@rollup/rollup-openharmony-arm64": "4.52.5", + "@rollup/rollup-win32-arm64-msvc": "4.52.5", + "@rollup/rollup-win32-ia32-msvc": "4.52.5", + "@rollup/rollup-win32-x64-gnu": "4.52.5", + "@rollup/rollup-win32-x64-msvc": "4.52.5", + "fsevents": "~2.3.2" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -9652,14 +10366,16 @@ } }, "node_modules/safe-array-concat": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", - "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4", - "has-symbols": "^1.0.3", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", "isarray": "^2.0.5" }, "engines": { @@ -9689,15 +10405,33 @@ ], "license": "MIT" }, - "node_modules/safe-regex-test": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", "es-errors": "^1.3.0", - "is-regex": "^1.1.4" + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -9747,6 +10481,7 @@ "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, + "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -9757,6 +10492,21 @@ "node": ">= 0.4" } }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -9943,6 +10693,20 @@ "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", "license": "BSD-3-Clause" }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -9983,16 +10747,19 @@ } }, "node_modules/string.prototype.trim": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", - "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", - "es-object-atoms": "^1.0.0" + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -10002,16 +10769,20 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", - "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -10165,13 +10936,13 @@ } }, "node_modules/svelte": { - "version": "5.28.6", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.28.6.tgz", - "integrity": "sha512-9qqr7mw8YR9PAnxGFfzCK6PUlNGtns7wVavrhnxyf3fpB1mP/Ol55Z2UnIapsSzNNl3k9qw7cZ22PdE8+xT/jQ==", + "version": "5.41.1", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.41.1.tgz", + "integrity": "sha512-0a/huwc8e2es+7KFi70esqsReRfRbrT8h1cJSY/+z1lF0yKM6TT+//HYu28Yxstr50H7ifaqZRDGd0KuKDxP7w==", "dev": true, "license": "MIT", "dependencies": { - "@ampproject/remapping": "^2.3.0", + "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/estree": "^1.0.5", @@ -10180,7 +10951,7 @@ "axobject-query": "^4.1.0", "clsx": "^2.1.1", "esm-env": "^1.2.1", - "esrap": "^1.4.6", + "esrap": "^2.1.0", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", @@ -10191,9 +10962,9 @@ } }, "node_modules/svelte-check": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-4.1.7.tgz", - "integrity": "sha512-1jX4BzXrQJhC/Jt3SqYf6Ntu//vmfc6VWp07JkRfK2nn+22yIblspVUo96gzMkg0Zov8lQicxhxsMzOctwcMQQ==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-4.3.3.tgz", + "integrity": "sha512-RYP0bEwenDXzfv0P1sKAwjZSlaRyqBn0Fz1TVni58lqyEiqgwztTpmodJrGzP6ZT2aHl4MbTvWP6gbmQ3FOnBg==", "dev": true, "license": "MIT", "dependencies": { @@ -10244,9 +11015,9 @@ } }, "node_modules/svelte-eslint-parser": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-1.1.3.tgz", - "integrity": "sha512-DUc/z/vk+AFVoxGv54+BOBFqUrmUgNg2gSO2YqrE3OL6ro19/0azPmQj/4wN3s9RxuF5l7G0162q/Ddk4LJhZA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-1.4.0.tgz", + "integrity": "sha512-fjPzOfipR5S7gQ/JvI9r2H8y9gMGXO3JtmrylHLLyahEMquXI0lrebcjT+9/hNgDej0H7abTyox5HpHmW1PSWA==", "dev": true, "license": "MIT", "dependencies": { @@ -10258,7 +11029,8 @@ "postcss-selector-parser": "^7.0.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0", + "pnpm": "10.18.3" }, "funding": { "url": "https://github.com/sponsors/ota-meshi" @@ -10386,6 +11158,57 @@ "node": ">= 6" } }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -10453,9 +11276,9 @@ } }, "node_modules/ts-api-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz", - "integrity": "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", "dev": true, "license": "MIT", "engines": { @@ -10484,9 +11307,9 @@ "license": "0BSD" }, "node_modules/tsx": { - "version": "4.19.4", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.4.tgz", - "integrity": "sha512-gK5GVzDkJK1SI1zwHf32Mqxf2tSJkNx+eYcNly5+nHvWqXUJYUkWBQtKauoESz3ymezAI++ZwT855x5p5eop+Q==", + "version": "4.20.6", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.6.tgz", + "integrity": "sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==", "dev": true, "license": "MIT", "dependencies": { @@ -10525,30 +11348,32 @@ } }, "node_modules/typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" + "is-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" } }, "node_modules/typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -10558,17 +11383,19 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", - "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", "dev": true, + "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" }, "engines": { "node": ">= 0.4" @@ -10578,18 +11405,18 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", - "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "dev": true, "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-proto": "^1.0.3", "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0" + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" }, "engines": { "node": ">= 0.4" @@ -10605,9 +11432,9 @@ "license": "MIT" }, "node_modules/typescript": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", - "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -10647,15 +11474,19 @@ } }, "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", + "call-bound": "^1.0.3", "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -10711,6 +11542,135 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/vite": { + "version": "7.1.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.11.tgz", + "integrity": "sha512-uzcxnSDVjAopEUjljkWh8EIrg6tlzrjFUfMcR1EVsRDGwf/ccef0qQPRyOrROwhrTDaApueq+ja+KLPlzR/zdg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vitefu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.1.tgz", + "integrity": "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==", + "dev": true, + "license": "MIT", + "workspaces": [ + "tests/deps/*", + "tests/projects/*", + "tests/projects/workspace/packages/*" + ], + "peerDependencies": { + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" + }, + "peerDependenciesMeta": { + "vite": { + "optional": true + } + } + }, "node_modules/vuvuzela": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/vuvuzela/-/vuvuzela-1.0.3.tgz", @@ -10828,31 +11788,85 @@ } }, "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", "dev": true, + "license": "MIT", "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/which-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", - "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", "dev": true, + "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" }, "engines": { @@ -11058,16 +12072,6 @@ "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", "dev": true }, - "@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, "@aws-crypto/crc32": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", @@ -12040,9 +13044,9 @@ "optional": true }, "@eslint-community/eslint-utils": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", - "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", "dev": true, "requires": { "eslint-visitor-keys": "^3.4.3" @@ -12062,26 +13066,16 @@ "requires": {} }, "@eslint/config-array": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", - "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", "dev": true, "requires": { - "@eslint/object-schema": "^2.1.6", + "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.2" }, "dependencies": { - "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, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -12094,15 +13088,18 @@ } }, "@eslint/config-helpers": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.0.tgz", - "integrity": "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==", - "dev": true + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.1.tgz", + "integrity": "sha512-csZAzkNhsgwb0I/UAV6/RGFTbiakPCf0ZrGmrIxQpYvGZ00PhTkSnyKNolphgIvmnJeGw6rcGVEXfTzUnFuEvw==", + "dev": true, + "requires": { + "@eslint/core": "^0.16.0" + } }, "@eslint/core": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz", - "integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==", + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.16.0.tgz", + "integrity": "sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==", "dev": true, "requires": { "@types/json-schema": "^7.0.15" @@ -12125,16 +13122,6 @@ "strip-json-comments": "^3.1.1" }, "dependencies": { - "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, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -12147,24 +13134,24 @@ } }, "@eslint/js": { - "version": "9.31.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.31.0.tgz", - "integrity": "sha512-LOm5OVt7D4qiKCqoiPbA7LWmI+tbw1VbTUowBcUMgQSuM6poJufkFkYDcQpo5KfgD39TnNySV26QjOh7VFpSyw==", + "version": "9.38.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.38.0.tgz", + "integrity": "sha512-UZ1VpFvXf9J06YG9xQBdnzU+kthors6KjhMAl6f4gH4usHyh31rUf2DLGInT8RFYIReYXNSydgPY0V2LuWgl7A==", "dev": true }, "@eslint/object-schema": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", - "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", "dev": true }, "@eslint/plugin-kit": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.4.tgz", - "integrity": "sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.0.tgz", + "integrity": "sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A==", "dev": true, "requires": { - "@eslint/core": "^0.15.1", + "@eslint/core": "^0.16.0", "levn": "^0.4.1" } }, @@ -12781,6 +13768,16 @@ "@jridgewell/trace-mapping": "^0.3.24" } }, + "@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, + "requires": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, "@jridgewell/resolve-uri": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", @@ -13280,6 +14277,182 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, + "@rollup/rollup-android-arm-eabi": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.5.tgz", + "integrity": "sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ==", + "dev": true, + "optional": true, + "peer": true + }, + "@rollup/rollup-android-arm64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.5.tgz", + "integrity": "sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA==", + "dev": true, + "optional": true, + "peer": true + }, + "@rollup/rollup-darwin-arm64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.5.tgz", + "integrity": "sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA==", + "dev": true, + "optional": true, + "peer": true + }, + "@rollup/rollup-darwin-x64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.5.tgz", + "integrity": "sha512-W901Pla8Ya95WpxDn//VF9K9u2JbocwV/v75TE0YIHNTbhqUTv9w4VuQ9MaWlNOkkEfFwkdNhXgcLqPSmHy0fA==", + "dev": true, + "optional": true, + "peer": true + }, + "@rollup/rollup-freebsd-arm64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.5.tgz", + "integrity": "sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA==", + "dev": true, + "optional": true, + "peer": true + }, + "@rollup/rollup-freebsd-x64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.5.tgz", + "integrity": "sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ==", + "dev": true, + "optional": true, + "peer": true + }, + "@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.5.tgz", + "integrity": "sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ==", + "dev": true, + "optional": true, + "peer": true + }, + "@rollup/rollup-linux-arm-musleabihf": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.5.tgz", + "integrity": "sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ==", + "dev": true, + "optional": true, + "peer": true + }, + "@rollup/rollup-linux-arm64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.5.tgz", + "integrity": "sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg==", + "dev": true, + "optional": true, + "peer": true + }, + "@rollup/rollup-linux-arm64-musl": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.5.tgz", + "integrity": "sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q==", + "dev": true, + "optional": true, + "peer": true + }, + "@rollup/rollup-linux-loong64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.5.tgz", + "integrity": "sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA==", + "dev": true, + "optional": true, + "peer": true + }, + "@rollup/rollup-linux-ppc64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.5.tgz", + "integrity": "sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw==", + "dev": true, + "optional": true, + "peer": true + }, + "@rollup/rollup-linux-riscv64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.5.tgz", + "integrity": "sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw==", + "dev": true, + "optional": true, + "peer": true + }, + "@rollup/rollup-linux-riscv64-musl": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.5.tgz", + "integrity": "sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg==", + "dev": true, + "optional": true, + "peer": true + }, + "@rollup/rollup-linux-s390x-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.5.tgz", + "integrity": "sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ==", + "dev": true, + "optional": true, + "peer": true + }, + "@rollup/rollup-linux-x64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.5.tgz", + "integrity": "sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q==", + "dev": true, + "optional": true, + "peer": true + }, + "@rollup/rollup-linux-x64-musl": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.5.tgz", + "integrity": "sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg==", + "dev": true, + "optional": true, + "peer": true + }, + "@rollup/rollup-openharmony-arm64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.5.tgz", + "integrity": "sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw==", + "dev": true, + "optional": true, + "peer": true + }, + "@rollup/rollup-win32-arm64-msvc": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.5.tgz", + "integrity": "sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w==", + "dev": true, + "optional": true, + "peer": true + }, + "@rollup/rollup-win32-ia32-msvc": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.5.tgz", + "integrity": "sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg==", + "dev": true, + "optional": true, + "peer": true + }, + "@rollup/rollup-win32-x64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.5.tgz", + "integrity": "sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ==", + "dev": true, + "optional": true, + "peer": true + }, + "@rollup/rollup-win32-x64-msvc": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.5.tgz", + "integrity": "sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg==", + "dev": true, + "optional": true, + "peer": true + }, "@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -13898,10 +15071,32 @@ "dev": true, "requires": {} }, + "@sveltejs/vite-plugin-svelte": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-6.2.1.tgz", + "integrity": "sha512-YZs/OSKOQAQCnJvM/P+F1URotNnYNeU3P2s4oIpzm1uFaqUEqRxUB0g5ejMjEb5Gjb9/PiBI5Ktrq4rUUF8UVQ==", + "dev": true, + "requires": { + "@sveltejs/vite-plugin-svelte-inspector": "^5.0.0", + "debug": "^4.4.1", + "deepmerge": "^4.3.1", + "magic-string": "^0.30.17", + "vitefu": "^1.1.1" + } + }, + "@sveltejs/vite-plugin-svelte-inspector": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-5.0.1.tgz", + "integrity": "sha512-ubWshlMk4bc8mkwWbg6vNvCeT7lGQojE3ijDh3QTR6Zr/R+GXxsGbyH4PExEPpiFmqPhYiVSVmHBjUcVc1JIrA==", + "dev": true, + "requires": { + "debug": "^4.4.1" + } + }, "@tsconfig/svelte": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/svelte/-/svelte-5.0.4.tgz", - "integrity": "sha512-BV9NplVgLmSi4mwKzD8BD/NQ8erOY/nUE/GpgWe2ckx+wIQF5RyRirn/QsSSCPeulVpc3RA/iJt6DpfTIZps0Q==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@tsconfig/svelte/-/svelte-5.0.5.tgz", + "integrity": "sha512-48fAnUjKye38FvMiNOj0J9I/4XlQQiZlpe9xaNPfe8vy2Y1hFBt8g1yqf2EGjVvHavo4jf2lC+TQyENCr4BJBQ==", "dev": true }, "@types/codemirror": { @@ -13943,9 +15138,9 @@ } }, "@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "dev": true }, "@types/json-schema": { @@ -14199,79 +15394,117 @@ } }, "@typescript-eslint/eslint-plugin": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.25.0.tgz", - "integrity": "sha512-VM7bpzAe7JO/BFf40pIT1lJqS/z1F8OaSsUB3rpFJucQA4cOSuH2RVVVkFULN+En0Djgr29/jb4EQnedUo95KA==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.2.tgz", + "integrity": "sha512-ZGBMToy857/NIPaaCucIUQgqueOiq7HeAKkhlvqVV4lm089zUFW6ikRySx2v+cAhKeUCPuWVHeimyk6Dw1iY3w==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.25.0", - "@typescript-eslint/type-utils": "8.25.0", - "@typescript-eslint/utils": "8.25.0", - "@typescript-eslint/visitor-keys": "8.25.0", + "@typescript-eslint/scope-manager": "8.46.2", + "@typescript-eslint/type-utils": "8.46.2", + "@typescript-eslint/utils": "8.46.2", + "@typescript-eslint/visitor-keys": "8.46.2", "graphemer": "^1.4.0", - "ignore": "^5.3.1", + "ignore": "^7.0.0", "natural-compare": "^1.4.0", - "ts-api-utils": "^2.0.1" + "ts-api-utils": "^2.1.0" + }, + "dependencies": { + "ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true + } } }, "@typescript-eslint/parser": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.25.0.tgz", - "integrity": "sha512-4gbs64bnbSzu4FpgMiQ1A+D+urxkoJk/kqlDJ2W//5SygaEiAP2B4GoS7TEdxgwol2el03gckFV9lJ4QOMiiHg==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.2.tgz", + "integrity": "sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "8.25.0", - "@typescript-eslint/types": "8.25.0", - "@typescript-eslint/typescript-estree": "8.25.0", - "@typescript-eslint/visitor-keys": "8.25.0", + "@typescript-eslint/scope-manager": "8.46.2", + "@typescript-eslint/types": "8.46.2", + "@typescript-eslint/typescript-estree": "8.46.2", + "@typescript-eslint/visitor-keys": "8.46.2", + "debug": "^4.3.4" + } + }, + "@typescript-eslint/project-service": { + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.2.tgz", + "integrity": "sha512-PULOLZ9iqwI7hXcmL4fVfIsBi6AN9YxRc0frbvmg8f+4hQAjQ5GYNKK0DIArNo+rOKmR/iBYwkpBmnIwin4wBg==", + "dev": true, + "requires": { + "@typescript-eslint/tsconfig-utils": "^8.46.2", + "@typescript-eslint/types": "^8.46.2", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.25.0.tgz", - "integrity": "sha512-6PPeiKIGbgStEyt4NNXa2ru5pMzQ8OYKO1hX1z53HMomrmiSB+R5FmChgQAP1ro8jMtNawz+TRQo/cSXrauTpg==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.2.tgz", + "integrity": "sha512-LF4b/NmGvdWEHD2H4MsHD8ny6JpiVNDzrSZr3CsckEgCbAGZbYM4Cqxvi9L+WqDMT+51Ozy7lt2M+d0JLEuBqA==", "dev": true, "requires": { - "@typescript-eslint/types": "8.25.0", - "@typescript-eslint/visitor-keys": "8.25.0" + "@typescript-eslint/types": "8.46.2", + "@typescript-eslint/visitor-keys": "8.46.2" } }, + "@typescript-eslint/tsconfig-utils": { + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.2.tgz", + "integrity": "sha512-a7QH6fw4S57+F5y2FIxxSDyi5M4UfGF+Jl1bCGd7+L4KsaUY80GsiF/t0UoRFDHAguKlBaACWJRmdrc6Xfkkag==", + "dev": true, + "requires": {} + }, "@typescript-eslint/type-utils": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.25.0.tgz", - "integrity": "sha512-d77dHgHWnxmXOPJuDWO4FDWADmGQkN5+tt6SFRZz/RtCWl4pHgFl3+WdYCn16+3teG09DY6XtEpf3gGD0a186g==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.2.tgz", + "integrity": "sha512-HbPM4LbaAAt/DjxXaG9yiS9brOOz6fabal4uvUmaUYe6l3K1phQDMQKBRUrr06BQkxkvIZVVHttqiybM9nJsLA==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "8.25.0", - "@typescript-eslint/utils": "8.25.0", + "@typescript-eslint/types": "8.46.2", + "@typescript-eslint/typescript-estree": "8.46.2", + "@typescript-eslint/utils": "8.46.2", "debug": "^4.3.4", - "ts-api-utils": "^2.0.1" + "ts-api-utils": "^2.1.0" } }, "@typescript-eslint/types": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.25.0.tgz", - "integrity": "sha512-+vUe0Zb4tkNgznQwicsvLUJgZIRs6ITeWSCclX1q85pR1iOiaj+4uZJIUp//Z27QWu5Cseiw3O3AR8hVpax7Aw==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.2.tgz", + "integrity": "sha512-lNCWCbq7rpg7qDsQrd3D6NyWYu+gkTENkG5IKYhUIcxSb59SQC/hEQ+MrG4sTgBVghTonNWq42bA/d4yYumldQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.25.0.tgz", - "integrity": "sha512-ZPaiAKEZ6Blt/TPAx5Ot0EIB/yGtLI2EsGoY6F7XKklfMxYQyvtL+gT/UCqkMzO0BVFHLDlzvFqQzurYahxv9Q==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.2.tgz", + "integrity": "sha512-f7rW7LJ2b7Uh2EiQ+7sza6RDZnajbNbemn54Ob6fRwQbgcIn+GWfyuHDHRYgRoZu1P4AayVScrRW+YfbTvPQoQ==", "dev": true, "requires": { - "@typescript-eslint/types": "8.25.0", - "@typescript-eslint/visitor-keys": "8.25.0", + "@typescript-eslint/project-service": "8.46.2", + "@typescript-eslint/tsconfig-utils": "8.46.2", + "@typescript-eslint/types": "8.46.2", + "@typescript-eslint/visitor-keys": "8.46.2", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", - "ts-api-utils": "^2.0.1" + "ts-api-utils": "^2.1.0" }, "dependencies": { + "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, + "requires": { + "balanced-match": "^1.0.0" + } + }, "minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -14284,25 +15517,25 @@ } }, "@typescript-eslint/utils": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.25.0.tgz", - "integrity": "sha512-syqRbrEv0J1wywiLsK60XzHnQe/kRViI3zwFALrNEgnntn1l24Ra2KvOAWwWbWZ1lBZxZljPDGOq967dsl6fkA==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.2.tgz", + "integrity": "sha512-sExxzucx0Tud5tE0XqR0lT0psBQvEpnpiul9XbGUB1QwpWJJAps1O/Z7hJxLGiZLBKMCutjTzDgmd1muEhBnVg==", "dev": true, "requires": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.25.0", - "@typescript-eslint/types": "8.25.0", - "@typescript-eslint/typescript-estree": "8.25.0" + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.46.2", + "@typescript-eslint/types": "8.46.2", + "@typescript-eslint/typescript-estree": "8.46.2" } }, "@typescript-eslint/visitor-keys": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.25.0.tgz", - "integrity": "sha512-kCYXKAum9CecGVHGij7muybDfTS2sD3t0L4bJsEZLkyrXUImiCTq1M3LG2SRtOhiHFwMR9wAFplpT6XHYjTkwQ==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.2.tgz", + "integrity": "sha512-tUFMXI4gxzzMXt4xpGJEsBsTox0XbNQ1y94EwlD/CuZwFcQP79xfQqMhau9HsRc/J0cAPA/HZt1dZPtGn9V/7w==", "dev": true, "requires": { - "@typescript-eslint/types": "8.25.0", - "eslint-visitor-keys": "^4.2.0" + "@typescript-eslint/types": "8.46.2", + "eslint-visitor-keys": "^4.2.1" }, "dependencies": { "eslint-visitor-keys": { @@ -14598,81 +15831,83 @@ "dev": true }, "array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "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, "requires": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" } }, "array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", "dev": true, "requires": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "is-string": "^1.0.7" + "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" } }, "array.prototype.findlastindex": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", - "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", "dev": true, "requires": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", + "es-abstract": "^1.23.9", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" } }, "array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "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, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" } }, "array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "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, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" } }, "arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "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, "requires": { "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" } }, "assertion-error": { @@ -14680,6 +15915,12 @@ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" }, + "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 + }, "available-typed-arrays": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", @@ -14723,12 +15964,13 @@ "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==" }, "brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "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, "requires": { - "balanced-match": "^1.0.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, "braces": { @@ -14761,16 +16003,15 @@ "dev": true }, "call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", "dev": true, "requires": { + "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "set-function-length": "^1.2.2" } }, "call-bind-apply-helpers": { @@ -14939,34 +16180,34 @@ "dev": true }, "data-view-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", - "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "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, "requires": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "is-data-view": "^1.0.2" } }, "data-view-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", - "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "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, "requires": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "is-data-view": "^1.0.2" } }, "data-view-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", - "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "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, "requires": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" } @@ -15010,6 +16251,12 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "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 + }, "deferred-leveldown": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-5.3.0.tgz", @@ -15138,57 +16385,65 @@ } }, "es-abstract": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", - "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", + "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", "dev": true, "requires": { - "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.3", + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "data-view-buffer": "^1.0.1", - "data-view-byte-length": "^1.0.1", - "data-view-byte-offset": "^1.0.0", - "es-define-property": "^1.0.0", + "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.0.0", - "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", - "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", + "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.0.3", - "has-symbols": "^1.0.3", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", "hasown": "^2.0.2", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", - "is-data-view": "^1.0.1", + "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", + "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.5", - "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.2", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.9", - "string.prototype.trimend": "^1.0.8", + "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.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.6", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.15" + "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" } }, "es-define-property": { @@ -15213,34 +16468,35 @@ } }, "es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "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, "requires": { - "get-intrinsic": "^1.2.4", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" + "hasown": "^2.0.2" } }, "es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "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, "requires": { - "hasown": "^2.0.0" + "hasown": "^2.0.2" } }, "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "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, "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" } }, "esbuild": { @@ -15287,9 +16543,9 @@ } }, "esbuild-svelte": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/esbuild-svelte/-/esbuild-svelte-0.9.2.tgz", - "integrity": "sha512-8Jq6+rh+g1E2mkBOZKdYZ8JtlbtDq2Fydwvn+/cBvUX9S0cdKv6AISZcEbErKQ0TpLC/Cv04l1vKaqXOBO8+VQ==", + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/esbuild-svelte/-/esbuild-svelte-0.9.3.tgz", + "integrity": "sha512-CgEcGY1r/d16+aggec3czoFBEBaYIrFOnMxpsO6fWNaNEqHregPN5DLAPZDqrL7rXDNplW+WMu8s3GMq9FqgJA==", "dev": true, "requires": { "@jridgewell/trace-mapping": "^0.3.19" @@ -15307,24 +16563,23 @@ "dev": true }, "eslint": { - "version": "9.31.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.31.0.tgz", - "integrity": "sha512-QldCVh/ztyKJJZLr4jXNUByx3gR+TDYZCRXEktiZoUR3PGy4qCmSbkxcIle8GEwGpb5JBZazlaJ/CxLidXdEbQ==", + "version": "9.38.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.38.0.tgz", + "integrity": "sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==", "dev": true, "requires": { - "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.0", - "@eslint/config-helpers": "^0.3.0", - "@eslint/core": "^0.15.0", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.1", + "@eslint/core": "^0.16.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.31.0", - "@eslint/plugin-kit": "^0.3.1", + "@eslint/js": "9.38.0", + "@eslint/plugin-kit": "^0.4.0", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", @@ -15349,16 +16604,6 @@ "optionator": "^0.9.3" }, "dependencies": { - "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, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "eslint-visitor-keys": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", @@ -15399,9 +16644,9 @@ } }, "eslint-module-utils": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", - "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", "dev": true, "requires": { "debug": "^3.2.7" @@ -15419,42 +16664,32 @@ } }, "eslint-plugin-import": { - "version": "2.31.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", - "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "requires": { "@rtsao/scc": "^1.1.0", - "array-includes": "^3.1.8", - "array.prototype.findlastindex": "^1.2.5", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.12.0", + "eslint-module-utils": "^2.12.1", "hasown": "^2.0.2", - "is-core-module": "^2.15.1", + "is-core-module": "^2.16.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "object.groupby": "^1.0.3", - "object.values": "^1.2.0", + "object.values": "^1.2.1", "semver": "^6.3.1", - "string.prototype.trimend": "^1.0.8", + "string.prototype.trimend": "^1.0.9", "tsconfig-paths": "^3.15.0" }, "dependencies": { - "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, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "debug": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", @@ -15491,22 +16726,29 @@ } }, "eslint-plugin-svelte": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-3.6.0.tgz", - "integrity": "sha512-IIf6Cj6yQuCwL7Qd8bX13BZspz+DQsOkClozMF9EkW20FSxI75Ndd5ZzbviCn32DdXRo9FUWXn+YMIL46qPOOg==", + "version": "3.12.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-3.12.5.tgz", + "integrity": "sha512-4KRG84eAHQfYd9OjZ1K7sCHy0nox+9KwT+s5WCCku3jTim5RV4tVENob274nCwIaApXsYPKAUAZFBxKZ3Wyfjw==", "dev": true, "requires": { - "@eslint-community/eslint-utils": "^4.4.1", + "@eslint-community/eslint-utils": "^4.6.1", "@jridgewell/sourcemap-codec": "^1.5.0", "esutils": "^2.0.3", - "known-css-properties": "^0.36.0", + "globals": "^16.0.0", + "known-css-properties": "^0.37.0", "postcss": "^8.4.49", "postcss-load-config": "^3.1.4", "postcss-safe-parser": "^7.0.0", "semver": "^7.6.3", - "svelte-eslint-parser": "^1.1.1" + "svelte-eslint-parser": "^1.4.0" }, "dependencies": { + "globals": { + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz", + "integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==", + "dev": true + }, "lilconfig": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", @@ -15582,9 +16824,9 @@ } }, "esrap": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/esrap/-/esrap-1.4.6.tgz", - "integrity": "sha512-F/D2mADJ9SHY3IwksD4DAXjTt7qt7GWUf3/8RhCNWmC/67tyb55dpimHmy7EplakFaflV0R/PC+fdSPqrRHAQw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.1.0.tgz", + "integrity": "sha512-yzmPNpl7TBbMRC5Lj2JlJZNPml0tzqoqP5B1JXycNUwtqma9AKCO0M2wHrdgsHcy1WRW7S9rJknAMtByg3usgA==", "dev": true, "requires": { "@jridgewell/sourcemap-codec": "^1.4.15" @@ -15813,12 +17055,12 @@ "dev": true }, "for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", "dev": true, "requires": { - "is-callable": "^1.1.3" + "is-callable": "^1.2.7" } }, "foreground-child": { @@ -15845,15 +17087,17 @@ "dev": true }, "function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "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, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" + "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" } }, "functional-red-black-tree": { @@ -15868,6 +17112,12 @@ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true }, + "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 + }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -15912,14 +17162,14 @@ } }, "get-symbol-description": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "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, "requires": { - "call-bind": "^1.0.5", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" + "get-intrinsic": "^1.2.6" } }, "get-tsconfig": { @@ -15961,12 +17211,13 @@ "dev": true }, "globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "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, "requires": { - "define-properties": "^1.1.3" + "define-properties": "^1.2.1", + "gopd": "^1.0.1" } }, "gopd": { @@ -15982,9 +17233,9 @@ "dev": true }, "has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", "dev": true }, "has-flag": { @@ -16003,10 +17254,13 @@ } }, "has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "dev": true + "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, + "requires": { + "dunder-proto": "^1.0.0" + } }, "has-symbols": { "version": "1.1.0", @@ -16063,9 +17317,9 @@ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true }, "immediate": { @@ -16110,14 +17364,14 @@ "integrity": "sha512-+WvfEZnFUhRwFxgz+QCQi7UC6o9AM0EHM9bpIe2Nhqb100NHCsTvNAn4eJgvgV2/tmLo1MP9nGxQKEcZTAueLA==" }, "internal-slot": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", "dev": true, "requires": { "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" + "hasown": "^2.0.2", + "side-channel": "^1.1.0" } }, "ip-address": { @@ -16130,32 +17384,46 @@ } }, "is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "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, "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + } + }, + "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, + "requires": { + "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" } }, "is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", "dev": true, "requires": { - "has-bigints": "^1.0.1" + "has-bigints": "^1.0.2" } }, "is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "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, "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" } }, "is-callable": { @@ -16165,30 +17433,33 @@ "dev": true }, "is-core-module": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", - "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "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, "requires": { "hasown": "^2.0.2" } }, "is-data-view": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", - "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "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, "requires": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" } }, "is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "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, "requires": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" } }, "is-electron": { @@ -16202,11 +17473,33 @@ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, + "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, + "requires": { + "call-bound": "^1.0.3" + } + }, "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==" }, + "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, + "requires": { + "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" + } + }, "is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -16221,6 +17514,12 @@ "resolved": "https://registry.npmjs.org/is-loopback-addr/-/is-loopback-addr-2.0.2.tgz", "integrity": "sha512-26POf2KRCno/KTNL5Q0b/9TYnL00xEsSaLfiFRmjM7m7Lw7ZMmFybzzuX4CcsLAluZGd+niLUiMRxEooVE3aqg==" }, + "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 + }, "is-negative-zero": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", @@ -16239,12 +17538,13 @@ "dev": true }, "is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "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, "requires": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" } }, "is-plain-obj": { @@ -16262,58 +17562,85 @@ } }, "is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "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, "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" } }, + "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 + }, "is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "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, "requires": { - "call-bind": "^1.0.7" + "call-bound": "^1.0.3" } }, "is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", "dev": true, "requires": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" } }, "is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "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, "requires": { - "has-symbols": "^1.0.2" + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" } }, "is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "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, "requires": { - "which-typed-array": "^1.1.14" + "which-typed-array": "^1.1.16" } }, + "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 + }, "is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", "dev": true, "requires": { - "call-bind": "^1.0.2" + "call-bound": "^1.0.3" + } + }, + "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, + "requires": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" } }, "isarray": { @@ -16637,9 +17964,9 @@ } }, "known-css-properties": { - "version": "0.36.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.36.0.tgz", - "integrity": "sha512-A+9jP+IUmuQsNdsLdcg6Yt7voiMF/D4K83ew0OpJtpu+l34ef7LaohWV0Rc6KNvzw6ZDizkqfyB5JznZnzuKQA==", + "version": "0.37.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.37.0.tgz", + "integrity": "sha512-JCDrsP4Z1Sb9JwG0aJ8Eo2r7k4Ou5MwmThS/6lcIe1ICyb7UBJKGRIUUdqc2ASdE/42lgz6zFUnzAIhtXnBVrQ==", "dev": true }, "level-codec": { @@ -17045,9 +18372,9 @@ "integrity": "sha512-yakbt9cPYj8d3vi/8o/XWm61MrOILo7fsTL0qxNx6zS0Nso6K5JqqS2WV7vK/KSuDBvrW3KfCwAdAgarAgOmww==" }, "nanoid": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", - "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "dev": true }, "natural-compare": { @@ -17092,14 +18419,16 @@ "dev": true }, "object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "dev": true, "requires": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", "object-keys": "^1.1.1" } }, @@ -17127,12 +18456,13 @@ } }, "object.values": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", - "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", "dev": true, "requires": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } @@ -17169,6 +18499,17 @@ "type-check": "^0.4.0" } }, + "own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "requires": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + } + }, "p-defer": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-4.0.1.tgz", @@ -17347,18 +18688,18 @@ } }, "possible-typed-array-names": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", "dev": true }, "postcss": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "dev": true, "requires": { - "nanoid": "^3.3.8", + "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } @@ -17793,16 +19134,34 @@ "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", "dev": true }, - "regexp.prototype.flags": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", - "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", "dev": true, "requires": { - "call-bind": "^1.0.6", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + } + }, + "regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "requires": { + "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", - "set-function-name": "^2.0.1" + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" } }, "require-directory": { @@ -17855,6 +19214,39 @@ "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==" }, + "rollup": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.5.tgz", + "integrity": "sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw==", + "dev": true, + "peer": true, + "requires": { + "@rollup/rollup-android-arm-eabi": "4.52.5", + "@rollup/rollup-android-arm64": "4.52.5", + "@rollup/rollup-darwin-arm64": "4.52.5", + "@rollup/rollup-darwin-x64": "4.52.5", + "@rollup/rollup-freebsd-arm64": "4.52.5", + "@rollup/rollup-freebsd-x64": "4.52.5", + "@rollup/rollup-linux-arm-gnueabihf": "4.52.5", + "@rollup/rollup-linux-arm-musleabihf": "4.52.5", + "@rollup/rollup-linux-arm64-gnu": "4.52.5", + "@rollup/rollup-linux-arm64-musl": "4.52.5", + "@rollup/rollup-linux-loong64-gnu": "4.52.5", + "@rollup/rollup-linux-ppc64-gnu": "4.52.5", + "@rollup/rollup-linux-riscv64-gnu": "4.52.5", + "@rollup/rollup-linux-riscv64-musl": "4.52.5", + "@rollup/rollup-linux-s390x-gnu": "4.52.5", + "@rollup/rollup-linux-x64-gnu": "4.52.5", + "@rollup/rollup-linux-x64-musl": "4.52.5", + "@rollup/rollup-openharmony-arm64": "4.52.5", + "@rollup/rollup-win32-arm64-msvc": "4.52.5", + "@rollup/rollup-win32-ia32-msvc": "4.52.5", + "@rollup/rollup-win32-x64-gnu": "4.52.5", + "@rollup/rollup-win32-x64-msvc": "4.52.5", + "@types/estree": "1.0.8", + "fsevents": "~2.3.2" + } + }, "run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -17874,14 +19266,15 @@ } }, "safe-array-concat": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", - "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", "dev": true, "requires": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4", - "has-symbols": "^1.0.3", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", "isarray": "^2.0.5" } }, @@ -17890,15 +19283,25 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, - "safe-regex-test": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", "dev": true, "requires": { - "call-bind": "^1.0.6", "es-errors": "^1.3.0", - "is-regex": "^1.1.4" + "isarray": "^2.0.5" + } + }, + "safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "requires": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" } }, "semver": { @@ -17939,6 +19342,17 @@ "has-property-descriptors": "^1.0.2" } }, + "set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "requires": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + } + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -18060,6 +19474,16 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" }, + "stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + } + }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -18090,24 +19514,28 @@ } }, "string.prototype.trim": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", - "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", "dev": true, "requires": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", - "es-object-atoms": "^1.0.0" + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" } }, "string.prototype.trimend": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", - "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", "dev": true, "requires": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } @@ -18217,12 +19645,12 @@ "dev": true }, "svelte": { - "version": "5.28.6", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.28.6.tgz", - "integrity": "sha512-9qqr7mw8YR9PAnxGFfzCK6PUlNGtns7wVavrhnxyf3fpB1mP/Ol55Z2UnIapsSzNNl3k9qw7cZ22PdE8+xT/jQ==", + "version": "5.41.1", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.41.1.tgz", + "integrity": "sha512-0a/huwc8e2es+7KFi70esqsReRfRbrT8h1cJSY/+z1lF0yKM6TT+//HYu28Yxstr50H7ifaqZRDGd0KuKDxP7w==", "dev": true, "requires": { - "@ampproject/remapping": "^2.3.0", + "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/estree": "^1.0.5", @@ -18231,7 +19659,7 @@ "axobject-query": "^4.1.0", "clsx": "^2.1.1", "esm-env": "^1.2.1", - "esrap": "^1.4.6", + "esrap": "^2.1.0", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", @@ -18239,9 +19667,9 @@ } }, "svelte-check": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-4.1.7.tgz", - "integrity": "sha512-1jX4BzXrQJhC/Jt3SqYf6Ntu//vmfc6VWp07JkRfK2nn+22yIblspVUo96gzMkg0Zov8lQicxhxsMzOctwcMQQ==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-4.3.3.tgz", + "integrity": "sha512-RYP0bEwenDXzfv0P1sKAwjZSlaRyqBn0Fz1TVni58lqyEiqgwztTpmodJrGzP6ZT2aHl4MbTvWP6gbmQ3FOnBg==", "dev": true, "requires": { "@jridgewell/trace-mapping": "^0.3.25", @@ -18269,9 +19697,9 @@ } }, "svelte-eslint-parser": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-1.1.3.tgz", - "integrity": "sha512-DUc/z/vk+AFVoxGv54+BOBFqUrmUgNg2gSO2YqrE3OL6ro19/0azPmQj/4wN3s9RxuF5l7G0162q/Ddk4LJhZA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-1.4.0.tgz", + "integrity": "sha512-fjPzOfipR5S7gQ/JvI9r2H8y9gMGXO3JtmrylHLLyahEMquXI0lrebcjT+9/hNgDej0H7abTyox5HpHmW1PSWA==", "dev": true, "requires": { "eslint-scope": "^8.2.0", @@ -18332,6 +19760,34 @@ } } }, + "tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "peer": true, + "requires": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "dependencies": { + "fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "peer": true, + "requires": {} + }, + "picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "peer": true + } + } + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -18389,9 +19845,9 @@ } }, "ts-api-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz", - "integrity": "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", "dev": true, "requires": {} }, @@ -18413,9 +19869,9 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "tsx": { - "version": "4.19.4", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.4.tgz", - "integrity": "sha512-gK5GVzDkJK1SI1zwHf32Mqxf2tSJkNx+eYcNly5+nHvWqXUJYUkWBQtKauoESz3ymezAI++ZwT855x5p5eop+Q==", + "version": "4.20.6", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.6.tgz", + "integrity": "sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==", "dev": true, "requires": { "esbuild": "~0.25.0", @@ -18438,55 +19894,56 @@ "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==" }, "typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "dev": true, "requires": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" + "is-typed-array": "^1.1.14" } }, "typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", "dev": true, "requires": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" } }, "typed-array-byte-offset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", - "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", "dev": true, "requires": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" } }, "typed-array-length": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", - "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "dev": true, "requires": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-proto": "^1.0.3", "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0" + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" } }, "typedarray": { @@ -18495,9 +19952,9 @@ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" }, "typescript": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", - "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true }, "uint8-varint": { @@ -18526,15 +19983,15 @@ } }, "unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, "requires": { - "call-bind": "^1.0.2", + "call-bound": "^1.0.3", "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" } }, "undici-types": { @@ -18578,6 +20035,46 @@ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true }, + "vite": { + "version": "7.1.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.11.tgz", + "integrity": "sha512-uzcxnSDVjAopEUjljkWh8EIrg6tlzrjFUfMcR1EVsRDGwf/ccef0qQPRyOrROwhrTDaApueq+ja+KLPlzR/zdg==", + "dev": true, + "peer": true, + "requires": { + "esbuild": "^0.25.0", + "fdir": "^6.5.0", + "fsevents": "~2.3.3", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "dependencies": { + "fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "peer": true, + "requires": {} + }, + "picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "peer": true + } + } + }, + "vitefu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.1.tgz", + "integrity": "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==", + "dev": true, + "requires": {} + }, "vuvuzela": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/vuvuzela/-/vuvuzela-1.0.3.tgz", @@ -18664,28 +20161,63 @@ } }, "which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", "dev": true, "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + } + }, + "which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "requires": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + } + }, + "which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "requires": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" } }, "which-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", - "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", "dev": true, "requires": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, diff --git a/package.json b/package.json index 9a77f0d..91cc4a4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "obsidian-livesync", - "version": "0.25.22", + "version": "0.25.23.beta1", "description": "Reflect your vault changes to some other devices immediately. Please make sure to disable other synchronize solutions to avoid content corruption or duplication.", "main": "main.js", "type": "module", @@ -23,7 +23,7 @@ "pretty": "npm run prettyNoWrite -- --write --log-level error", "prettyCheck": "npm run prettyNoWrite -- --check", "prettyNoWrite": "prettier --config ./.prettierrc \"**/*.js\" \"**/*.ts\" \"**/*.json\" ", - "check": "npm run lint && npm run svelte-check && npm run tsc-check", + "check": "npm run lint && npm run svelte-check", "unittest": "deno test -A --no-check --coverage=cov_profile --v8-flags=--expose-gc --trace-leaks ./src/" }, "keywords": [], @@ -34,7 +34,9 @@ "@eslint/compat": "^1.2.7", "@eslint/eslintrc": "^3.3.0", "@eslint/js": "^9.21.0", - "@tsconfig/svelte": "^5.0.4", + "@sveltejs/vite-plugin-svelte": "^6.2.1", + "@tsconfig/svelte": "^5.0.5", + "@types/deno": "^2.3.0", "@types/diff-match-patch": "^1.0.36", "@types/node": "^22.13.8", "@types/pouchdb": "^6.4.2", @@ -45,15 +47,15 @@ "@types/pouchdb-mapreduce": "^6.1.10", "@types/pouchdb-replication": "^6.4.7", "@types/transform-pouch": "^1.0.6", - "@typescript-eslint/eslint-plugin": "8.25.0", - "@typescript-eslint/parser": "8.25.0", + "@typescript-eslint/eslint-plugin": "8.46.2", + "@typescript-eslint/parser": "8.46.2", "builtin-modules": "5.0.0", "esbuild": "0.25.0", "esbuild-plugin-inline-worker": "^0.1.1", - "esbuild-svelte": "^0.9.0", - "eslint": "^9.21.0", - "eslint-plugin-import": "^2.31.0", - "eslint-plugin-svelte": "^3.0.2", + "esbuild-svelte": "^0.9.3", + "eslint": "^9.38.0", + "eslint-plugin-import": "^2.32.0", + "eslint-plugin-svelte": "^3.12.4", "events": "^3.3.0", "glob": "^11.0.3", "obsidian": "^1.8.7", @@ -71,16 +73,15 @@ "pouchdb-replication": "^9.0.0", "pouchdb-utils": "^9.0.0", "prettier": "3.5.2", - "svelte": "5.28.6", - "svelte-check": "^4.1.7", + "svelte": "5.41.1", + "svelte-check": "^4.3.3", "svelte-preprocess": "^6.0.3", "terser": "^5.39.0", "transform-pouch": "^2.0.0", "tslib": "^2.8.1", - "tsx": "^4.19.4", - "typescript": "5.7.3", - "yaml": "^2.8.0", - "@types/deno": "^2.3.0" + "tsx": "^4.20.6", + "typescript": "5.9.3", + "yaml": "^2.8.0" }, "dependencies": { "@aws-sdk/client-s3": "^3.808.0", diff --git a/src/features/P2PSync/CmdP2PReplicator.ts b/src/features/P2PSync/CmdP2PReplicator.ts index 16c6298..865df50 100644 --- a/src/features/P2PSync/CmdP2PReplicator.ts +++ b/src/features/P2PSync/CmdP2PReplicator.ts @@ -32,6 +32,7 @@ import type { SimpleStore } from "octagonal-wheels/databases/SimpleStoreBase"; import { getPlatformName } from "../../lib/src/PlatformAPIs/obsidian/Environment.ts"; import type { LiveSyncCore } from "../../main.ts"; import { TrysteroReplicator } from "../../lib/src/replication/trystero/TrysteroReplicator.ts"; +import { SETTING_KEY_P2P_DEVICE_NAME } from "../../lib/src/common/types.ts"; export class P2PReplicator extends LiveSyncCommands implements P2PReplicatorBase, CommandShim { storeP2PStatusLine = reactiveSource(""); @@ -93,14 +94,10 @@ export class P2PReplicator extends LiveSyncCommands implements P2PReplicatorBase } getConfig(key: string) { - const vaultName = this.services.vault.getVaultName(); - const dbKey = `${vaultName}-${key}`; - return localStorage.getItem(dbKey); + return this.services.config.getSmallConfig(key); } setConfig(key: string, value: string) { - const vaultName = this.services.vault.getVaultName(); - const dbKey = `${vaultName}-${key}`; - localStorage.setItem(dbKey, value); + return this.services.config.setSmallConfig(key, value); } enableBroadcastCastings() { return this?._replicatorInstance?.enableBroadcastChanges(); @@ -125,7 +122,8 @@ export class P2PReplicator extends LiveSyncCommands implements P2PReplicatorBase if (!this.settings.P2P_AppID) { this.settings.P2P_AppID = P2P_DEFAULT_SETTINGS.P2P_AppID; } - const getInitialDeviceName = () => this.getConfig("p2p_device_name") || this.services.vault.getVaultName(); + const getInitialDeviceName = () => + this.getConfig(SETTING_KEY_P2P_DEVICE_NAME) || this.services.vault.getVaultName(); const getSettings = () => this.settings; const store = () => this.simpleStore(); diff --git a/src/features/P2PSync/P2PReplicator/P2PReplicatorPane.svelte b/src/features/P2PSync/P2PReplicator/P2PReplicatorPane.svelte index 344b1b5..06fa93d 100644 --- a/src/features/P2PSync/P2PReplicator/P2PReplicatorPane.svelte +++ b/src/features/P2PSync/P2PReplicator/P2PReplicatorPane.svelte @@ -19,6 +19,7 @@ } from "../../../lib/src/replication/trystero/TrysteroReplicatorP2PServer"; import { type P2PReplicatorStatus } from "../../../lib/src/replication/trystero/TrysteroReplicator"; import { $msg as _msg } from "../../../lib/src/common/i18n"; + import { SETTING_KEY_P2P_DEVICE_NAME } from "../../../lib/src/common/types"; interface Props { plugin: PluginShim; @@ -35,7 +36,7 @@ // const vaultName = service.vault.getVaultName(); // const dbKey = `${vaultName}-p2p-device-name`; - const initialDeviceName = cmdSync.getConfig("p2p_device_name") ?? plugin.services.vault.getVaultName(); + const initialDeviceName = cmdSync.getConfig(SETTING_KEY_P2P_DEVICE_NAME) ?? plugin.services.vault.getVaultName(); let deviceName = $state(initialDeviceName); let eP2PEnabled = $state(initialSettings.P2P_Enabled); @@ -84,7 +85,7 @@ P2P_AutoBroadcast: eAutoBroadcast, }; plugin.settings = newSettings; - cmdSync.setConfig("p2p_device_name", eDeviceName); + cmdSync.setConfig(SETTING_KEY_P2P_DEVICE_NAME, eDeviceName); deviceName = eDeviceName; await plugin.saveSettings(); } diff --git a/src/lib b/src/lib index 422194f..82c6843 160000 --- a/src/lib +++ b/src/lib @@ -1 +1 @@ -Subproject commit 422194fb1b38e10234c942e5037e859c245ec4a5 +Subproject commit 82c68435a1e26d969c2a18be2a0523ea2ca83633 diff --git a/src/main.ts b/src/main.ts index d0e37b7..b0a730c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -33,7 +33,7 @@ import { ModuleLog } from "./modules/features/ModuleLog.ts"; import { ModuleObsidianSettings } from "./modules/features/ModuleObsidianSetting.ts"; import { ModuleRedFlag } from "./modules/coreFeatures/ModuleRedFlag.ts"; import { ModuleObsidianMenu } from "./modules/essentialObsidian/ModuleObsidianMenu.ts"; -import { ModuleSetupObsidian } from "./modules/features/ModuleSetupObsidian.ts"; +import { ModuleSetupObsidian, SetupManager } from "./modules/features/ModuleSetupObsidian.ts"; import type { StorageAccess } from "./modules/interfaces/StorageAccess.ts"; import type { Confirm } from "./lib/src/interfaces/Confirm.ts"; import type { Rebuilder } from "./modules/interfaces/DatabaseRebuilder.ts"; @@ -107,7 +107,7 @@ export default class ObsidianLiveSyncPlugin /** * The service hub for managing all services. */ - _services: InjectableServiceHub = new ObsidianServiceHub(); + _services: InjectableServiceHub = new ObsidianServiceHub(this); get services() { return this._services; } @@ -176,7 +176,15 @@ export default class ObsidianLiveSyncPlugin new ModuleDev(this, this), new ModuleReplicateTest(this, this), new ModuleIntegratedTest(this, this), + new SetupManager(this, this), ] as (IObsidianModule | AbstractModule)[]; + + getModule(constructor: new (...args: any[]) => T): T { + for (const module of this.modules) { + if (module.constructor === constructor) return module as T; + } + throw new Error(`Module ${constructor} not found or not loaded.`); + } // injected = injectModules(this, [...this.modules, ...this.addOns] as ICoreModule[]); // <-- Module System diff --git a/src/modules/core/ModuleFileHandler.ts b/src/modules/core/ModuleFileHandler.ts index 909b670..29155f6 100644 --- a/src/modules/core/ModuleFileHandler.ts +++ b/src/modules/core/ModuleFileHandler.ts @@ -399,6 +399,10 @@ export class ModuleFileHandler extends AbstractModule { incProcessed(); return true; } + if (this.services.vault.isFileSizeTooLarge(file.stat.size)) { + incProcessed(); + return true; + } if (shouldBeIgnored(file.path)) { incProcessed(); return true; diff --git a/src/modules/core/ModuleRebuilder.ts b/src/modules/core/ModuleRebuilder.ts index 4cefcfd..5e59694 100644 --- a/src/modules/core/ModuleRebuilder.ts +++ b/src/modules/core/ModuleRebuilder.ts @@ -36,6 +36,14 @@ export class ModuleRebuilder extends AbstractModule implements Rebuilder { } } + async informOptionalFeatures() { + await this.core.services.UI.showMarkdownDialog( + "All optional features are disabled", + `Customisation Sync and Hidden File Sync will all be disabled. +Please enable them from the settings screen after setup is complete.`, + ["OK"] + ); + } async askUsingOptionalFeature(opt: { enableFetch?: boolean; enableOverwrite?: boolean }) { if ( (await this.core.confirm.askYesNoDialog( @@ -56,11 +64,12 @@ export class ModuleRebuilder extends AbstractModule implements Rebuilder { await this.services.remote.tryResetDatabase(); await this.services.remote.markLocked(); await delay(500); - await this.askUsingOptionalFeature({ enableOverwrite: true }); + // await this.askUsingOptionalFeature({ enableOverwrite: true }); await delay(1000); await this.services.remote.replicateAllToRemote(true); await delay(1000); await this.services.remote.replicateAllToRemote(true, true); + await this.informOptionalFeatures(); } $rebuildRemote(): Promise { return this.rebuildRemote(); @@ -79,11 +88,12 @@ export class ModuleRebuilder extends AbstractModule implements Rebuilder { await this.services.remote.markLocked(); await delay(500); // We do not have any other devices' data, so we do not need to ask for overwriting. - await this.askUsingOptionalFeature({ enableOverwrite: false }); + // await this.askUsingOptionalFeature({ enableOverwrite: false }); await delay(1000); await this.services.remote.replicateAllToRemote(true); await delay(1000); await this.services.remote.replicateAllToRemote(true, true); + await this.informOptionalFeatures(); } $rebuildEverything(): Promise { @@ -200,7 +210,9 @@ export class ModuleRebuilder extends AbstractModule implements Rebuilder { await delay(1000); await this.services.remote.replicateAllFromRemote(true); await this.resumeReflectingDatabase(); - await this.askUsingOptionalFeature({ enableFetch: true }); + await this.informOptionalFeatures(); + // No longer enable + // await this.askUsingOptionalFeature({ enableFetch: true }); } async fetchLocalWithRebuild() { return await this.fetchLocal(true); diff --git a/src/modules/coreFeatures/ModuleRedFlag.ts b/src/modules/coreFeatures/ModuleRedFlag.ts index 31e0b53..3262412 100644 --- a/src/modules/coreFeatures/ModuleRedFlag.ts +++ b/src/modules/coreFeatures/ModuleRedFlag.ts @@ -1,16 +1,17 @@ -import { LOG_LEVEL_NOTICE, LOG_LEVEL_VERBOSE } from "octagonal-wheels/common/logger"; +import { LOG_LEVEL_INFO, LOG_LEVEL_NOTICE, LOG_LEVEL_VERBOSE } from "octagonal-wheels/common/logger"; import { normalizePath } from "../../deps.ts"; import { - FLAGMD_REDFLAG, - FLAGMD_REDFLAG2, - FLAGMD_REDFLAG2_HR, - FLAGMD_REDFLAG3, - FLAGMD_REDFLAG3_HR, + FlagFilesHumanReadable, + FlagFilesOriginal, + TweakValuesShouldMatchedTemplate, type ObsidianLiveSyncSettings, } from "../../lib/src/common/types.ts"; import { AbstractModule } from "../AbstractModule.ts"; -import { $msg } from "../../lib/src/common/i18n.ts"; import type { LiveSyncCore } from "../../main.ts"; +import { SvelteDialogManager } from "../features/SetupWizard/ObsidianSvelteDialog.ts"; +import FetchEverything from "../features/SetupWizard/dialogs/FetchEverything.svelte"; +import RebuildEverything from "../features/SetupWizard/dialogs/RebuildEverything.svelte"; +import { extractObject } from "octagonal-wheels/object"; export class ModuleRedFlag extends AbstractModule { async isFlagFileExist(path: string) { @@ -33,165 +34,284 @@ export class ModuleRedFlag extends AbstractModule { } } - isRedFlagRaised = async () => await this.isFlagFileExist(FLAGMD_REDFLAG); - isRedFlag2Raised = async () => - (await this.isFlagFileExist(FLAGMD_REDFLAG2)) || (await this.isFlagFileExist(FLAGMD_REDFLAG2_HR)); - isRedFlag3Raised = async () => - (await this.isFlagFileExist(FLAGMD_REDFLAG3)) || (await this.isFlagFileExist(FLAGMD_REDFLAG3_HR)); + isSuspendFlagActive = async () => await this.isFlagFileExist(FlagFilesOriginal.SUSPEND_ALL); + isRebuildFlagActive = async () => + (await this.isFlagFileExist(FlagFilesOriginal.REBUILD_ALL)) || + (await this.isFlagFileExist(FlagFilesHumanReadable.REBUILD_ALL)); + isFetchAllFlagActive = async () => + (await this.isFlagFileExist(FlagFilesOriginal.FETCH_ALL)) || + (await this.isFlagFileExist(FlagFilesHumanReadable.FETCH_ALL)); - async deleteRedFlag2() { - await this.deleteFlagFile(FLAGMD_REDFLAG2); - await this.deleteFlagFile(FLAGMD_REDFLAG2_HR); + async cleanupRebuildFlag() { + await this.deleteFlagFile(FlagFilesOriginal.REBUILD_ALL); + await this.deleteFlagFile(FlagFilesHumanReadable.REBUILD_ALL); } - async deleteRedFlag3() { - await this.deleteFlagFile(FLAGMD_REDFLAG3); - await this.deleteFlagFile(FLAGMD_REDFLAG3_HR); + async cleanupFetchAllFlag() { + await this.deleteFlagFile(FlagFilesOriginal.FETCH_ALL); + await this.deleteFlagFile(FlagFilesHumanReadable.FETCH_ALL); } + dialogManager = new SvelteDialogManager(this.core); + + /** + * Adjust setting to remote if needed. + * @param extra result of dialogues that may contain preventFetchingConfig flag (e.g, from FetchEverything or RebuildEverything) + * @param config current configuration to retrieve remote preferred config + */ + async adjustSettingToRemoteIfNeeded(extra: { preventFetchingConfig: boolean }, config: ObsidianLiveSyncSettings) { + if (extra && extra.preventFetchingConfig) { + return; + } + + // Remote configuration fetched and applied. + if (await this.adjustSettingToRemote(config)) { + config = this.core.settings; + } else { + this._log("Remote configuration not applied.", LOG_LEVEL_NOTICE); + } + console.debug(config); + } + + /** + * Adjust setting to remote configuration. + * @param config current configuration to retrieve remote preferred config + * @returns updated configuration if applied, otherwise null. + */ + async adjustSettingToRemote(config: ObsidianLiveSyncSettings) { + // Fetch remote configuration unless prevented. + const SKIP_FETCH = "Skip and proceed"; + const RETRY_FETCH = "Retry (recommended)"; + let canProceed = false; + do { + const remoteTweaks = await this.services.tweakValue.fetchRemotePreferred(config); + if (!remoteTweaks) { + const choice = await this.core.confirm.askSelectStringDialogue( + "Could not fetch remote configuration. What do you want to do?", + [SKIP_FETCH, RETRY_FETCH] as const, + { + defaultAction: RETRY_FETCH, + timeout: 0, + title: "Fetch Remote Configuration Failed", + } + ); + if (choice === SKIP_FETCH) { + canProceed = true; + } + } else { + const necessary = extractObject(TweakValuesShouldMatchedTemplate, remoteTweaks); + // Check if any necessary tweak value is different from current config. + const differentItems = Object.entries(necessary).filter(([key, value]) => { + return (config as any)[key] !== value; + }); + if (differentItems.length === 0) { + this._log( + "Remote configuration matches local configuration. No changes applied.", + LOG_LEVEL_NOTICE + ); + } else { + await this.core.confirm.askSelectStringDialogue( + "Your settings differed slightly from the server's. The plug-in has supplemented the incompatible parts with the server settings!", + ["OK"] as const, + { + defaultAction: "OK", + timeout: 0, + } + ); + } + + config = { + ...config, + ...Object.fromEntries(differentItems), + } satisfies ObsidianLiveSyncSettings; + this.core.settings = config; + await this.core.services.setting.saveSettingData(); + this._log("Remote configuration applied.", LOG_LEVEL_NOTICE); + canProceed = true; + return this.core.settings; + } + } while (!canProceed); + } + + /** + * Process vault initialisation with suspending file watching and sync. + * @param proc process to be executed during initialisation, should return true if can be continued, false if app is unable to continue the process. + * @param keepSuspending whether to keep suspending file watching after the process. + * @returns result of the process, or false if error occurs. + */ + async processVaultInitialisation(proc: () => Promise, keepSuspending = false) { + try { + // Disable batch saving and file watching during initialisation. + this.settings.batchSave = false; + await this.services.setting.suspendAllSync(); + await this.services.setting.suspendExtraSync(); + this.settings.suspendFileWatching = true; + await this.saveSettings(); + try { + const result = await proc(); + return result; + } catch (ex) { + this._log("Error during vault initialisation process.", LOG_LEVEL_NOTICE); + this._log(ex, LOG_LEVEL_VERBOSE); + return false; + } + } catch (ex) { + this._log("Error during vault initialisation.", LOG_LEVEL_NOTICE); + this._log(ex, LOG_LEVEL_VERBOSE); + return false; + } finally { + if (!keepSuspending) { + // Re-enable file watching after initialisation. + this.settings.suspendFileWatching = false; + await this.saveSettings(); + } + } + } + + /** + * Handle the rebuild everything scheduled operation. + * @returns true if can be continued, false if app restart is needed. + */ + async onRebuildEverythingScheduled() { + const method = await this.dialogManager.openWithExplicitCancel(RebuildEverything); + if (method === "cancelled") { + // Clean up the flag file and restart the app. + this._log("Rebuild everything cancelled by user.", LOG_LEVEL_NOTICE); + await this.cleanupRebuildFlag(); + this.services.appLifecycle.performRestart(); + return false; + } + const { extra } = method; + await this.adjustSettingToRemoteIfNeeded(extra, this.settings); + return await this.processVaultInitialisation(async () => { + await this.core.rebuilder.$rebuildEverything(); + await this.cleanupRebuildFlag(); + this._log("Rebuild everything operation completed.", LOG_LEVEL_NOTICE); + return true; + }); + } + /** + * Handle the fetch all scheduled operation. + * @returns true if can be continued, false if app restart is needed. + */ + async onFetchAllScheduled() { + const method = await this.dialogManager.openWithExplicitCancel(FetchEverything); + if (method === "cancelled") { + this._log("Fetch everything cancelled by user.", LOG_LEVEL_NOTICE); + // Clean up the flag file and restart the app. + await this.cleanupFetchAllFlag(); + this.services.appLifecycle.performRestart(); + return false; + } + const { vault, extra } = method; + + const mapVaultStateToAction = { + identical: { + // If both are identical, no need to make local files/chunks before sync, + // Just for the efficiency, chunks should be made before sync. + makeLocalChunkBeforeSync: true, + makeLocalFilesBeforeSync: false, + }, + independent: { + // If both are independent, nothing needs to be made before sync. + // Respect the remote state. + makeLocalChunkBeforeSync: false, + makeLocalFilesBeforeSync: false, + }, + unbalanced: { + // If both are unbalanced, local files should be made before sync to avoid data loss. + // Then, chunks should be made before sync for the efficiency, but also the metadata made and should be detected as conflicting. + makeLocalChunkBeforeSync: false, + makeLocalFilesBeforeSync: true, + }, + cancelled: { + // Cancelled case, not actually used. + makeLocalChunkBeforeSync: false, + makeLocalFilesBeforeSync: false, + }, + } as const; + + return await this.processVaultInitialisation(async () => { + await this.adjustSettingToRemoteIfNeeded(extra, this.settings); + // Okay, proceed to fetch everything. + const { makeLocalChunkBeforeSync, makeLocalFilesBeforeSync } = mapVaultStateToAction[vault]; + this._log( + `Fetching everything with settings: makeLocalChunkBeforeSync=${makeLocalChunkBeforeSync}, makeLocalFilesBeforeSync=${makeLocalFilesBeforeSync}`, + LOG_LEVEL_INFO + ); + await this.core.rebuilder.$fetchLocal(makeLocalChunkBeforeSync, !makeLocalFilesBeforeSync); + await this.cleanupFetchAllFlag(); + this._log("Fetch everything operation completed. Vault files will be gradually synced.", LOG_LEVEL_NOTICE); + return true; + }); + } + + async onSuspendAllScheduled() { + this._log("SCRAM is detected. All operations are suspended.", LOG_LEVEL_NOTICE); + return await this.processVaultInitialisation(async () => { + this._log( + "All operations are suspended as per SCRAM.\nLogs will be written to the file. This might be a performance impact.", + LOG_LEVEL_NOTICE + ); + this.settings.writeLogToTheFile = true; + await this.core.services.setting.saveSettingData(); + return Promise.resolve(false); + }, true); + } + + async verifyAndUnlockSuspension() { + if (!this.settings.suspendFileWatching) { + return true; + } + if ( + (await this.core.confirm.askYesNoDialog( + "Do you want to resume file and database processing, and restart obsidian now?", + { defaultOption: "Yes", timeout: 15 } + )) != "yes" + ) { + // TODO: Confirm actually proceed to next process. + return true; + } + this.settings.suspendFileWatching = false; + await this.saveSettings(); + this.services.appLifecycle.performRestart(); + return false; + } + + private async processFlagFilesOnStartup(): Promise { + const isFlagSuspensionActive = await this.isSuspendFlagActive(); + const isFlagRebuildActive = await this.isRebuildFlagActive(); + const isFlagFetchAllActive = await this.isFetchAllFlagActive(); + // TODO: Address the case when both flags are active (very unlikely though). + // if(isFlagFetchAllActive && isFlagRebuildActive) { + // const message = "Rebuild everything and Fetch everything flags are both detected."; + // await this.core.confirm.askSelectStringDialogue( + // "Both Rebuild Everything and Fetch Everything flags are detected. Please remove one of them and restart the app.", + // ["OK"] as const,) + if (isFlagFetchAllActive) { + const res = await this.onFetchAllScheduled(); + if (res) { + return await this.verifyAndUnlockSuspension(); + } + return false; + } + if (isFlagRebuildActive) { + const res = await this.onRebuildEverythingScheduled(); + if (res) { + return await this.verifyAndUnlockSuspension(); + } + return false; + } + if (isFlagSuspensionActive) { + const res = await this.onSuspendAllScheduled(); + return res; + } + return true; + } + async _everyOnLayoutReady(): Promise { try { - const isRedFlagRaised = await this.isRedFlagRaised(); - const isRedFlag2Raised = await this.isRedFlag2Raised(); - const isRedFlag3Raised = await this.isRedFlag3Raised(); - - if (isRedFlagRaised || isRedFlag2Raised || isRedFlag3Raised) { - if (isRedFlag2Raised) { - if ( - (await this.core.confirm.askYesNoDialog( - "Rebuild everything has been scheduled! Are you sure to rebuild everything?", - { defaultOption: "Yes", timeout: 0 } - )) !== "yes" - ) { - await this.deleteRedFlag2(); - this.services.appLifecycle.performRestart(); - return false; - } - } - if (isRedFlag3Raised) { - if ( - (await this.core.confirm.askYesNoDialog("Fetch again has been scheduled! Are you sure?", { - defaultOption: "Yes", - timeout: 0, - })) !== "yes" - ) { - await this.deleteRedFlag3(); - this.services.appLifecycle.performRestart(); - return false; - } - } - this.settings.batchSave = false; - await this.services.setting.suspendAllSync(); - await this.services.setting.suspendExtraSync(); - this.settings.suspendFileWatching = true; - await this.saveSettings(); - if (isRedFlag2Raised) { - this._log( - `${FLAGMD_REDFLAG2} or ${FLAGMD_REDFLAG2_HR} has been detected! Self-hosted LiveSync suspends all sync and rebuild everything.`, - LOG_LEVEL_NOTICE - ); - await this.core.rebuilder.$rebuildEverything(); - await this.deleteRedFlag2(); - if ( - (await this.core.confirm.askYesNoDialog( - "Do you want to resume file and database processing, and restart obsidian now?", - { defaultOption: "Yes", timeout: 15 } - )) == "yes" - ) { - this.settings.suspendFileWatching = false; - await this.saveSettings(); - this.services.appLifecycle.performRestart(); - return false; - } - } else if (isRedFlag3Raised) { - this._log( - `${FLAGMD_REDFLAG3} or ${FLAGMD_REDFLAG3_HR} has been detected! Self-hosted LiveSync will discard the local database and fetch everything from the remote once again.`, - LOG_LEVEL_NOTICE - ); - const method1 = $msg("RedFlag.Fetch.Method.FetchSafer"); - const method2 = $msg("RedFlag.Fetch.Method.FetchSmoother"); - const method3 = $msg("RedFlag.Fetch.Method.FetchTraditional"); - - const methods = [method1, method2, method3] as const; - const chunkMode = await this.core.confirm.askSelectStringDialogue( - $msg("RedFlag.Fetch.Method.Desc"), - methods, - { - defaultAction: method1, - timeout: 0, - title: $msg("RedFlag.Fetch.Method.Title"), - } - ); - let makeLocalChunkBeforeSync = false; - let makeLocalFilesBeforeSync = false; - if (chunkMode === method1) { - makeLocalFilesBeforeSync = true; - } else if (chunkMode === method2) { - makeLocalChunkBeforeSync = true; - } else if (chunkMode === method3) { - // Do nothing. - } else { - this._log("Cancelled the fetch operation", LOG_LEVEL_NOTICE); - return false; - } - - const optionFetchRemoteConf = $msg("RedFlag.FetchRemoteConfig.Buttons.Fetch"); - const optionCancel = $msg("RedFlag.FetchRemoteConfig.Buttons.Cancel"); - const fetchRemote = await this.core.confirm.askSelectStringDialogue( - $msg("RedFlag.FetchRemoteConfig.Message"), - [optionFetchRemoteConf, optionCancel], - { - defaultAction: optionFetchRemoteConf, - timeout: 0, - title: $msg("RedFlag.FetchRemoteConfig.Title"), - } - ); - if (fetchRemote === optionFetchRemoteConf) { - this._log("Fetching remote configuration", LOG_LEVEL_NOTICE); - const newSettings = JSON.parse(JSON.stringify(this.core.settings)) as ObsidianLiveSyncSettings; - const remoteConfig = await this.services.tweakValue.fetchRemotePreferred(newSettings); - if (remoteConfig) { - this._log("Remote configuration found.", LOG_LEVEL_NOTICE); - const mergedSettings = { - ...this.core.settings, - ...remoteConfig, - } satisfies ObsidianLiveSyncSettings; - this._log("Remote configuration applied.", LOG_LEVEL_NOTICE); - this.core.settings = mergedSettings; - } else { - this._log("Remote configuration not applied.", LOG_LEVEL_NOTICE); - } - } - - await this.core.rebuilder.$fetchLocal(makeLocalChunkBeforeSync, !makeLocalFilesBeforeSync); - - await this.deleteRedFlag3(); - if (this.settings.suspendFileWatching) { - if ( - (await this.core.confirm.askYesNoDialog( - "Do you want to resume file and database processing, and restart obsidian now?", - { defaultOption: "Yes", timeout: 15 } - )) == "yes" - ) { - this.settings.suspendFileWatching = false; - await this.saveSettings(); - this.services.appLifecycle.performRestart(); - return false; - } - } else { - this._log( - "Your content of files will be synchronised gradually. Please wait for the completion.", - LOG_LEVEL_NOTICE - ); - } - } else { - // Case of FLAGMD_REDFLAG. - this.settings.writeLogToTheFile = true; - // await this.plugin.openDatabase(); - const warningMessage = - "The red flag is raised! The whole initialize steps are skipped, and any file changes are not captured."; - this._log(warningMessage, LOG_LEVEL_NOTICE); - } - } + const flagProcessResult = await this.processFlagFilesOnStartup(); + return flagProcessResult; } catch (ex) { this._log("Something went wrong on FlagFile Handling", LOG_LEVEL_NOTICE); this._log(ex, LOG_LEVEL_VERBOSE); diff --git a/src/modules/essential/ModuleMigration.ts b/src/modules/essential/ModuleMigration.ts index b2bb1ca..49dbbcc 100644 --- a/src/modules/essential/ModuleMigration.ts +++ b/src/modules/essential/ModuleMigration.ts @@ -3,7 +3,6 @@ import { EVENT_REQUEST_OPEN_P2P, EVENT_REQUEST_OPEN_SETTING_WIZARD, EVENT_REQUEST_OPEN_SETTINGS, - EVENT_REQUEST_OPEN_SETUP_URI, EVENT_REQUEST_RUN_DOCTOR, EVENT_REQUEST_RUN_FIX_INCOMPLETE, eventHub, @@ -16,6 +15,7 @@ import { isMetaEntry } from "../../lib/src/common/types.ts"; import { isDeletedEntry, isDocContentSame, isLoadedEntry, readAsBlob } from "../../lib/src/common/utils.ts"; import { countCompromisedChunks } from "../../lib/src/pouchdb/negotiation.ts"; import type { LiveSyncCore } from "../../main.ts"; +import { SetupManager } from "../features/ModuleSetupObsidian.ts"; type ErrorInfo = { path: string; @@ -66,6 +66,9 @@ export class ModuleMigration extends AbstractModule { } async initialMessage() { + const manager = this.core.getModule(SetupManager); + return await manager.startOnBoarding(); + /* const message = $msg("moduleMigration.msgInitialSetup", { URI_DOC: $msg("moduleMigration.docUri"), }); @@ -83,6 +86,7 @@ export class ModuleMigration extends AbstractModule { return true; } return false; + */ } async askAgainForSetupURI() { @@ -326,8 +330,11 @@ export class ModuleMigration extends AbstractModule { await this.migrateDisableBulkSend(); } if (!this.settings.isConfigured) { - // Case sensitivity - if (!(await this.initialMessage()) || !(await this.askAgainForSetupURI())) { + // if (!(await this.initialMessage()) || !(await this.askAgainForSetupURI())) { + // this._log($msg("moduleMigration.logSetupCancelled"), LOG_LEVEL_NOTICE); + // return false; + // } + if (!(await this.initialMessage())) { this._log($msg("moduleMigration.logSetupCancelled"), LOG_LEVEL_NOTICE); return false; } diff --git a/src/modules/essentialObsidian/ModuleObsidianAPI.ts b/src/modules/essentialObsidian/ModuleObsidianAPI.ts index ac015b8..981b321 100644 --- a/src/modules/essentialObsidian/ModuleObsidianAPI.ts +++ b/src/modules/essentialObsidian/ModuleObsidianAPI.ts @@ -102,7 +102,7 @@ export class ModuleObsidianAPI extends AbstractObsidianModule { compression: boolean, customHeaders: Record, useRequestAPI: boolean, - getPBKDF2Salt: () => Promise + getPBKDF2Salt: () => Promise> ): Promise; info: PouchDB.Core.DatabaseInfo }> { if (!isValidRemoteCouchDBURI(uri)) return "Remote URI is not valid"; if (uri.toLowerCase() != uri) return "Remote URI and database name could not contain capital letters."; diff --git a/src/modules/features/ModuleSetupObsidian.ts b/src/modules/features/ModuleSetupObsidian.ts index 4d7489c..f806dd9 100644 --- a/src/modules/features/ModuleSetupObsidian.ts +++ b/src/modules/features/ModuleSetupObsidian.ts @@ -1,13 +1,16 @@ import { type ObsidianLiveSyncSettings, DEFAULT_SETTINGS, - KeyIndexOfSettings, LOG_LEVEL_NOTICE, LOG_LEVEL_VERBOSE, + REMOTE_COUCHDB, + REMOTE_MINIO, + REMOTE_P2P, } from "../../lib/src/common/types.ts"; -import { configURIBase, configURIBaseQR } from "../../common/types.ts"; +import { SETTING_KEY_P2P_DEVICE_NAME } from "../../lib/src/common/types.ts"; +import { configURIBase } from "../../common/types.ts"; // import { PouchDB } from "../../lib/src/pouchdb/pouchdb-browser.js"; -import { fireAndForget } from "../../lib/src/common/utils.ts"; +import { fireAndForget, generatePatchObj, isObjectDifferent } from "../../lib/src/common/utils.ts"; import { EVENT_REQUEST_COPY_SETUP_URI, EVENT_REQUEST_OPEN_SETUP_URI, @@ -15,20 +18,284 @@ import { eventHub, } from "../../common/events.ts"; import { AbstractObsidianModule } from "../AbstractObsidianModule.ts"; -import { decodeAnyArray, encodeAnyArray } from "../../common/utils.ts"; -import qrcode from "qrcode-generator"; import { $msg } from "../../lib/src/common/i18n.ts"; -import { performDoctorConsultation, RebuildOptions } from "@/lib/src/common/configForDoc.ts"; -import { encryptString, decryptString } from "@/lib/src/encryption/stringEncryption.ts"; +// import { performDoctorConsultation, RebuildOptions } from "@/lib/src/common/configForDoc.ts"; import type { LiveSyncCore } from "../../main.ts"; +import { SvelteDialogManager } from "./SetupWizard/ObsidianSvelteDialog.ts"; +import Intro from "./SetupWizard/dialogs/Intro.svelte"; +import SelectMethodNewUser from "./SetupWizard/dialogs/SelectMethodNewUser.svelte"; +import SelectMethodExisting from "./SetupWizard/dialogs/SelectMethodExisting.svelte"; +import ScanQRCode from "./SetupWizard/dialogs/ScanQRCode.svelte"; +import UseSetupURI from "./SetupWizard/dialogs/UseSetupURI.svelte"; +import OutroNewUser from "./SetupWizard/dialogs/OutroNewUser.svelte"; +import OutroExistingUser from "./SetupWizard/dialogs/OutroExistingUser.svelte"; +import OutroAskUserMode from "./SetupWizard/dialogs/OutroAskUserMode.svelte"; +import SetupRemote from "./SetupWizard/dialogs/SetupRemote.svelte"; +import SetupRemoteCouchDB from "./SetupWizard/dialogs/SetupRemoteCouchDB.svelte"; +import SetupRemoteBucket from "./SetupWizard/dialogs/SetupRemoteBucket.svelte"; +import SetupRemoteP2P from "./SetupWizard/dialogs/SetupRemoteP2P.svelte"; +import SetupRemoteE2EE from "./SetupWizard/dialogs/SetupRemoteE2EE.svelte"; +import { + decodeSettingsFromQRCodeData, + encodeQR, + encodeSettingsToQRCodeData, + encodeSettingsToSetupURI, + OutputFormat, +} from "../../lib/src/API/processSetting.ts"; +// import type ObsidianLiveSyncPlugin from "../../main.ts"; +export const enum UserMode { + NewUser = "new-user", + ExistingUser = "existing-user", + Unknown = "unknown", + // eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values + Update = "unknown", // Alias for Unknown for better readability +} + +export class SetupManager extends AbstractObsidianModule { + private dialogManager: SvelteDialogManager = new SvelteDialogManager(this.plugin); + + async startOnBoarding(): Promise { + const isUserNewOrExisting = await this.dialogManager.openWithExplicitCancel(Intro); + if (isUserNewOrExisting === "new-user") { + await this.onBoard(UserMode.NewUser); + } else if (isUserNewOrExisting === "existing-user") { + await this.onBoard(UserMode.ExistingUser); + } else if (isUserNewOrExisting === "cancelled") { + this._log("Onboarding cancelled by user.", LOG_LEVEL_NOTICE); + return false; + } + return false; + } + + async onBoard(userMode: UserMode): Promise { + const originalSetting = userMode === UserMode.NewUser ? DEFAULT_SETTINGS : this.core.settings; + if (userMode === UserMode.NewUser) { + //Ask how to apply initial setup + const method = await this.dialogManager.openWithExplicitCancel(SelectMethodNewUser); + if (method === "use-setup-uri") { + await this.onUseSetupURI(userMode); + } else if (method === "configure-manually") { + await this.onConfigureManually(originalSetting, userMode); + } else if (method === "cancelled") { + this._log("Onboarding cancelled by user.", LOG_LEVEL_NOTICE); + return false; + } + } else if (userMode === UserMode.ExistingUser) { + const method = await this.dialogManager.openWithExplicitCancel(SelectMethodExisting); + if (method === "use-setup-uri") { + await this.onUseSetupURI(userMode); + } else if (method === "configure-manually") { + await this.onConfigureManually(originalSetting, userMode); + } else if (method === "scan-qr-code") { + await this.onPromptQRCodeInstruction(); + } else if (method === "cancelled") { + this._log("Onboarding cancelled by user.", LOG_LEVEL_NOTICE); + return false; + } + } + return false; + } + + async onUseSetupURI(userMode: UserMode, setupURI: string = ""): Promise { + const newSetting = await this.dialogManager.openWithExplicitCancel(UseSetupURI, setupURI); + if (newSetting === "cancelled") { + this._log("Setup URI dialog cancelled.", LOG_LEVEL_NOTICE); + return false; + } + this._log("Setup URI dialog closed.", LOG_LEVEL_VERBOSE); + return await this.confirmApplySettingsFromWizard(newSetting, userMode); + } + async onCouchDBManualSetup( + userMode: UserMode, + currentSetting: ObsidianLiveSyncSettings, + activate = true + ): Promise { + const originalSetting = JSON.parse(JSON.stringify(currentSetting)) as ObsidianLiveSyncSettings; + const baseSetting = JSON.parse(JSON.stringify(originalSetting)) as ObsidianLiveSyncSettings; + const couchConf = await this.dialogManager.openWithExplicitCancel(SetupRemoteCouchDB, originalSetting); + if (couchConf === "cancelled") { + this._log("Manual configuration cancelled.", LOG_LEVEL_NOTICE); + return await this.onBoard(userMode); + } + const newSetting = { ...baseSetting, ...couchConf } as ObsidianLiveSyncSettings; + if (activate) { + newSetting.remoteType = REMOTE_COUCHDB; + } + return await this.confirmApplySettingsFromWizard(newSetting, userMode, activate); + } + + async onBucketManualSetup( + userMode: UserMode, + currentSetting: ObsidianLiveSyncSettings, + activate = true + ): Promise { + const bucketConf = await this.dialogManager.openWithExplicitCancel(SetupRemoteBucket, currentSetting); + if (bucketConf === "cancelled") { + this._log("Manual configuration cancelled.", LOG_LEVEL_NOTICE); + return await this.onBoard(userMode); + } + const newSetting = { ...currentSetting, ...bucketConf } as ObsidianLiveSyncSettings; + if (activate) { + newSetting.remoteType = REMOTE_MINIO; + } + return await this.confirmApplySettingsFromWizard(newSetting, userMode, activate); + } + async onP2PManualSetup( + userMode: UserMode, + currentSetting: ObsidianLiveSyncSettings, + activate = true + ): Promise { + const p2pConf = await this.dialogManager.openWithExplicitCancel(SetupRemoteP2P, currentSetting); + if (p2pConf === "cancelled") { + this._log("Manual configuration cancelled.", LOG_LEVEL_NOTICE); + return await this.onBoard(userMode); + } + const newSetting = { ...currentSetting, ...p2pConf.info } as ObsidianLiveSyncSettings; + if (activate) { + newSetting.remoteType = REMOTE_P2P; + } + return await this.confirmApplySettingsFromWizard(newSetting, userMode, activate, () => { + this.services.config.setSmallConfig(SETTING_KEY_P2P_DEVICE_NAME, p2pConf.devicePeerId); + }); + } + async onlyE2EEConfiguration(userMode: UserMode, currentSetting: ObsidianLiveSyncSettings): Promise { + const e2eeConf = await this.dialogManager.openWithExplicitCancel(SetupRemoteE2EE, currentSetting); + if (e2eeConf === "cancelled") { + this._log("E2EE configuration cancelled.", LOG_LEVEL_NOTICE); + return await false; + } + const newSetting = { + ...currentSetting, + ...e2eeConf, + } as ObsidianLiveSyncSettings; + return await this.confirmApplySettingsFromWizard(newSetting, userMode); + } + async onConfigureManually(originalSetting: ObsidianLiveSyncSettings, userMode: UserMode): Promise { + const e2eeConf = await this.dialogManager.openWithExplicitCancel(SetupRemoteE2EE, originalSetting); + if (e2eeConf === "cancelled") { + this._log("Manual configuration cancelled.", LOG_LEVEL_NOTICE); + return await this.onBoard(userMode); + } + const currentSetting = { + ...originalSetting, + ...e2eeConf, + } as ObsidianLiveSyncSettings; + return await this.selectServer(currentSetting, userMode); + } + + async selectServer(currentSetting: ObsidianLiveSyncSettings, userMode: UserMode): Promise { + const method = await this.dialogManager.openWithExplicitCancel(SetupRemote); + if (method === "couchdb") { + return await this.onCouchDBManualSetup(userMode, currentSetting, true); + } else if (method === "bucket") { + return await this.onBucketManualSetup(userMode, currentSetting, true); + } else if (method === "p2p") { + return await this.onP2PManualSetup(userMode, currentSetting, true); + } else if (method === "cancelled") { + this._log("Manual configuration cancelled.", LOG_LEVEL_NOTICE); + if (userMode !== UserMode.Unknown) { + return await this.onBoard(userMode); + } + } + // Should not reach here. + return false; + } + async confirmApplySettingsFromWizard( + newConf: ObsidianLiveSyncSettings, + _userMode: UserMode, + activate: boolean = true, + extra: () => void = () => {} + ): Promise { + let userMode = _userMode; + // let rebuildRequired = true; + if (userMode === UserMode.Unknown) { + if (isObjectDifferent(this.settings, newConf, true) === false) { + this._log("No changes in settings detected. Skipping applying settings from wizard.", LOG_LEVEL_NOTICE); + return true; + } + const patch = generatePatchObj(this.settings, newConf); + console.log(`Changes:`); + console.dir(patch); + if (!activate) { + extra(); + await this.applySetting(newConf, UserMode.ExistingUser); + this._log("Setting Applied", LOG_LEVEL_NOTICE); + return true; + } + const userModeResult = await this.dialogManager.openWithExplicitCancel(OutroAskUserMode); + if (userModeResult === "new-user") { + userMode = UserMode.NewUser; + } else if (userModeResult === "existing-user") { + userMode = UserMode.ExistingUser; + } else if (userModeResult === "compatible-existing-user") { + extra(); + await this.applySetting(newConf, UserMode.ExistingUser); + this._log("Settings from wizard applied.", LOG_LEVEL_NOTICE); + return true; + } else if (userModeResult === "cancelled") { + this._log("User cancelled applying settings from wizard.", LOG_LEVEL_NOTICE); + return false; + } + } + const component = userMode === UserMode.NewUser ? OutroNewUser : OutroExistingUser; + const confirm = await this.dialogManager.openWithExplicitCancel(component); + if (confirm === "cancelled") { + this._log("User cancelled applying settings from wizard..", LOG_LEVEL_NOTICE); + return false; + } + if (confirm) { + extra(); + await this.applySetting(newConf, userMode); + if (userMode === UserMode.NewUser) { + // For new users, schedule a rebuild everything. + await this.core.rebuilder.scheduleRebuild(); + } else { + // For existing users, schedule a fetch. + await this.core.rebuilder.scheduleFetch(); + } + } + // Settings applied, but may require rebuild to take effect. + return false; + } + + async onPromptQRCodeInstruction(): Promise { + const qrResult = await this.dialogManager.open(ScanQRCode); + this._log("QR Code dialog closed.", LOG_LEVEL_VERBOSE); + // Result is not used, but log it for debugging. + this._log(`QR Code result: ${qrResult}`, LOG_LEVEL_VERBOSE); + // QR Code instruction dialog never yields settings directly. + return false; + } + + async decodeQR(qr: string) { + const newSettings = decodeSettingsFromQRCodeData(qr); + return await this.confirmApplySettingsFromWizard(newSettings, UserMode.Unknown); + } + + async applySetting(newConf: ObsidianLiveSyncSettings, userMode: UserMode) { + const newSetting = { + ...this.core.settings, + ...newConf, + }; + this.core.settings = newSetting; + this.services.setting.clearUsedPassphrase(); + await this.services.setting.saveSettingData(); + return true; + } +} export class ModuleSetupObsidian extends AbstractObsidianModule { + private _setupManager!: SetupManager; private _everyOnload(): Promise { + this._setupManager = this.plugin.getModule(SetupManager); this.registerObsidianProtocolHandler("setuplivesync", async (conf: any) => { if (conf.settings) { - await this.setupWizard(conf.settings); + await this._setupManager.onUseSetupURI( + UserMode.Unknown, + `${configURIBase}${encodeURIComponent(conf.settings)}` + ); } else if (conf.settingsQR) { - await this.decodeQR(conf.settingsQR); + await this._setupManager.decodeQR(conf.settingsQR); } }); this.addCommand({ @@ -59,293 +326,246 @@ export class ModuleSetupObsidian extends AbstractObsidianModule { name: "Use the copied setup URI (Formerly Open setup URI)", callback: () => fireAndForget(this.command_openSetupURI()), }); + eventHub.onEvent(EVENT_REQUEST_OPEN_SETUP_URI, () => fireAndForget(() => this.command_openSetupURI())); eventHub.onEvent(EVENT_REQUEST_COPY_SETUP_URI, () => fireAndForget(() => this.command_copySetupURI())); eventHub.onEvent(EVENT_REQUEST_SHOW_SETUP_QR, () => fireAndForget(() => this.encodeQR())); return Promise.resolve(true); } async encodeQR() { - const settingArr = []; - const fullIndexes = Object.entries(KeyIndexOfSettings) as [keyof ObsidianLiveSyncSettings, number][]; - for (const [settingKey, index] of fullIndexes) { - const settingValue = this.settings[settingKey]; - if (index < 0) { - // This setting should be ignored. - continue; - } - settingArr[index] = settingValue; - } - const w = encodeAnyArray(settingArr); - const qr = qrcode(0, "L"); - const uri = `${configURIBaseQR}${encodeURIComponent(w)}`; - qr.addData(uri); - qr.make(); - const img = qr.createSvgTag(3); - const msg = $msg("Setup.QRCode", { qr_image: img }); + const settingString = encodeSettingsToQRCodeData(this.settings); + const codeSVG = encodeQR(settingString, OutputFormat.SVG); + const msg = $msg("Setup.QRCode", { qr_image: codeSVG }); await this.core.confirm.confirmWithMessage("Settings QR Code", msg, ["OK"], "OK"); - return await Promise.resolve(w); + return await Promise.resolve(codeSVG); } - async decodeQR(qr: string) { - const settingArr = decodeAnyArray(qr); - // console.warn(settingArr); - const fullIndexes = Object.entries(KeyIndexOfSettings) as [keyof ObsidianLiveSyncSettings, number][]; - const newSettings = { ...DEFAULT_SETTINGS } as ObsidianLiveSyncSettings; - for (const [settingKey, index] of fullIndexes) { - if (index < 0) { - // This setting should be ignored. - continue; - } - if (index >= settingArr.length) { - // Possibly a new setting added. - continue; - } - const settingValue = settingArr[index]; - //@ts-ignore - newSettings[settingKey] = settingValue; - } - await this.applySettingWizard(this.settings, newSettings, "QR Code"); + + async askEncryptingPassphrase(): Promise { + const encryptingPassphrase = await this.core.confirm.askString( + "Encrypt your settings", + "The passphrase to encrypt the setup URI", + "", + true + ); + return encryptingPassphrase; } + async command_copySetupURI(stripExtra = true) { - const encryptingPassphrase = await this.core.confirm.askString( - "Encrypt your settings", - "The passphrase to encrypt the setup URI", - "", + const encryptingPassphrase = await this.askEncryptingPassphrase(); + if (encryptingPassphrase === false) return; + const encryptedURI = await encodeSettingsToSetupURI( + this.settings, + encryptingPassphrase, + [...((stripExtra ? ["pluginSyncExtendedSetting"] : []) as (keyof ObsidianLiveSyncSettings)[])], true ); - if (encryptingPassphrase === false) return; - const setting = { - ...this.settings, - configPassphraseStore: "", - encryptedCouchDBConnection: "", - encryptedPassphrase: "", - } as Partial; - if (stripExtra) { - delete setting.pluginSyncExtendedSetting; + if (await this.services.UI.promptCopyToClipboard("Setup URI", encryptedURI)) { + this._log("Setup URI copied to clipboard", LOG_LEVEL_NOTICE); } - const keys = Object.keys(setting) as (keyof ObsidianLiveSyncSettings)[]; - for (const k of keys) { - if ( - JSON.stringify(k in setting ? setting[k] : "") == - JSON.stringify(k in DEFAULT_SETTINGS ? DEFAULT_SETTINGS[k] : "*") - ) { - delete setting[k]; - } - } - const encryptedSetting = encodeURIComponent(await encryptString(JSON.stringify(setting), encryptingPassphrase)); - const uri = `${configURIBase}${encryptedSetting} `; - await navigator.clipboard.writeText(uri); - this._log("Setup URI copied to clipboard", LOG_LEVEL_NOTICE); + // await navigator.clipboard.writeText(encryptedURI); } + async command_copySetupURIFull() { - const encryptingPassphrase = await this.core.confirm.askString( - "Encrypt your settings", - "The passphrase to encrypt the setup URI", - "", - true - ); + const encryptingPassphrase = await this.askEncryptingPassphrase(); if (encryptingPassphrase === false) return; - const setting = { - ...this.settings, - configPassphraseStore: "", - encryptedCouchDBConnection: "", - encryptedPassphrase: "", - }; - const encryptedSetting = encodeURIComponent(await encryptString(JSON.stringify(setting), encryptingPassphrase)); - const uri = `${configURIBase}${encryptedSetting} `; - await navigator.clipboard.writeText(uri); + const encryptedURI = await encodeSettingsToSetupURI(this.settings, encryptingPassphrase, [], false); + await navigator.clipboard.writeText(encryptedURI); this._log("Setup URI copied to clipboard", LOG_LEVEL_NOTICE); } + async command_copySetupURIWithSync() { await this.command_copySetupURI(false); } async command_openSetupURI() { - const setupURI = await this.core.confirm.askString("Easy setup", "Set up URI", `${configURIBase} aaaaa`); - if (setupURI === false) return; - if (!setupURI.startsWith(`${configURIBase}`)) { - this._log("Set up URI looks wrong.", LOG_LEVEL_NOTICE); - return; - } - const config = decodeURIComponent(setupURI.substring(configURIBase.length)); - await this.setupWizard(config); - } - async askSyncWithRemoteConfig(tryingSettings: ObsidianLiveSyncSettings): Promise { - const buttons = { - fetch: $msg("Setup.FetchRemoteConf.Buttons.Fetch"), - no: $msg("Setup.FetchRemoteConf.Buttons.Skip"), - } as const; - const fetchRemoteConf = await this.core.confirm.askSelectStringDialogue( - $msg("Setup.FetchRemoteConf.Message"), - Object.values(buttons), - { defaultAction: buttons.fetch, timeout: 0, title: $msg("Setup.FetchRemoteConf.Title") } - ); - if (fetchRemoteConf == buttons.no) { - return tryingSettings; - } - - const newSettings = JSON.parse(JSON.stringify(tryingSettings)) as ObsidianLiveSyncSettings; - const remoteConfig = await this.services.tweakValue.fetchRemotePreferred(newSettings); - if (remoteConfig) { - this._log("Remote configuration found.", LOG_LEVEL_NOTICE); - const resultSettings = { - ...DEFAULT_SETTINGS, - ...tryingSettings, - ...remoteConfig, - } satisfies ObsidianLiveSyncSettings; - return resultSettings; - } else { - this._log("Remote configuration not applied.", LOG_LEVEL_NOTICE); - return { - ...DEFAULT_SETTINGS, - ...tryingSettings, - } satisfies ObsidianLiveSyncSettings; - } - } - async askPerformDoctor( - tryingSettings: ObsidianLiveSyncSettings - ): Promise<{ settings: ObsidianLiveSyncSettings; shouldRebuild: boolean; isModified: boolean }> { - const buttons = { - yes: $msg("Setup.Doctor.Buttons.Yes"), - no: $msg("Setup.Doctor.Buttons.No"), - } as const; - const performDoctor = await this.core.confirm.askSelectStringDialogue( - $msg("Setup.Doctor.Message"), - Object.values(buttons), - { defaultAction: buttons.yes, timeout: 0, title: $msg("Setup.Doctor.Title") } - ); - if (performDoctor == buttons.no) { - return { settings: tryingSettings, shouldRebuild: false, isModified: false }; - } - - const newSettings = JSON.parse(JSON.stringify(tryingSettings)) as ObsidianLiveSyncSettings; - const { settings, shouldRebuild, isModified } = await performDoctorConsultation(this.core, newSettings, { - localRebuild: RebuildOptions.AutomaticAcceptable, // Because we are in the setup wizard, we can skip the confirmation. - remoteRebuild: RebuildOptions.SkipEvenIfRequired, - activateReason: "New settings from URI", - }); - if (isModified) { - this._log("Doctor has fixed some issues!", LOG_LEVEL_NOTICE); - return { - settings, - shouldRebuild, - isModified, - }; - } else { - this._log("Doctor detected no issues!", LOG_LEVEL_NOTICE); - return { settings: tryingSettings, shouldRebuild: false, isModified: false }; - } + await this._setupManager.onUseSetupURI(UserMode.Unknown); } - async applySettingWizard( - oldConf: ObsidianLiveSyncSettings, - newConf: ObsidianLiveSyncSettings, - method = "Setup URI" - ) { - const result = await this.core.confirm.askYesNoDialog( - "Importing Configuration from the " + method + ". Are you sure to proceed ? ", - {} - ); - if (result == "yes") { - let newSettingW = Object.assign({}, DEFAULT_SETTINGS, newConf) as ObsidianLiveSyncSettings; - this.core.replicator.closeReplication(); - this.settings.suspendFileWatching = true; - newSettingW = await this.askSyncWithRemoteConfig(newSettingW); - const { settings, shouldRebuild, isModified } = await this.askPerformDoctor(newSettingW); - if (isModified) { - newSettingW = settings; - } - // Back into the default method once. - newSettingW.configPassphraseStore = ""; - newSettingW.encryptedPassphrase = ""; - newSettingW.encryptedCouchDBConnection = ""; - newSettingW.additionalSuffixOfDatabaseName = `${"appId" in this.app ? this.app.appId : ""} `; - const setupJustImport = $msg("Setup.Apply.Buttons.OnlyApply"); - const setupAsNew = $msg("Setup.Apply.Buttons.ApplyAndFetch"); - const setupAsMerge = $msg("Setup.Apply.Buttons.ApplyAndMerge"); - const setupAgain = $msg("Setup.Apply.Buttons.ApplyAndRebuild"); - const setupCancel = $msg("Setup.Apply.Buttons.Cancel"); - newSettingW.syncInternalFiles = false; - newSettingW.usePluginSync = false; - newSettingW.isConfigured = true; - // Migrate completely obsoleted configuration. - if (!newSettingW.useIndexedDBAdapter) { - newSettingW.useIndexedDBAdapter = true; - } - const warn = shouldRebuild ? $msg("Setup.Apply.WarningRebuildRecommended") : ""; - const message = $msg("Setup.Apply.Message", { - method, - warn, - }); + // async askSyncWithRemoteConfig(tryingSettings: ObsidianLiveSyncSettings): Promise { + // const buttons = { + // fetch: $msg("Setup.FetchRemoteConf.Buttons.Fetch"), + // no: $msg("Setup.FetchRemoteConf.Buttons.Skip"), + // } as const; + // const fetchRemoteConf = await this.core.confirm.askSelectStringDialogue( + // $msg("Setup.FetchRemoteConf.Message"), + // Object.values(buttons), + // { defaultAction: buttons.fetch, timeout: 0, title: $msg("Setup.FetchRemoteConf.Title") } + // ); + // if (fetchRemoteConf == buttons.no) { + // return tryingSettings; + // } + + // const newSettings = JSON.parse(JSON.stringify(tryingSettings)) as ObsidianLiveSyncSettings; + // const remoteConfig = await this.services.tweakValue.fetchRemotePreferred(newSettings); + // if (remoteConfig) { + // this._log("Remote configuration found.", LOG_LEVEL_NOTICE); + // const resultSettings = { + // ...DEFAULT_SETTINGS, + // ...tryingSettings, + // ...remoteConfig, + // } satisfies ObsidianLiveSyncSettings; + // return resultSettings; + // } else { + // this._log("Remote configuration not applied.", LOG_LEVEL_NOTICE); + // return { + // ...DEFAULT_SETTINGS, + // ...tryingSettings, + // } satisfies ObsidianLiveSyncSettings; + // } + // } + // async askPerformDoctor( + // tryingSettings: ObsidianLiveSyncSettings + // ): Promise<{ settings: ObsidianLiveSyncSettings; shouldRebuild: boolean; isModified: boolean }> { + // const buttons = { + // yes: $msg("Setup.Doctor.Buttons.Yes"), + // no: $msg("Setup.Doctor.Buttons.No"), + // } as const; + // const performDoctor = await this.core.confirm.askSelectStringDialogue( + // $msg("Setup.Doctor.Message"), + // Object.values(buttons), + // { defaultAction: buttons.yes, timeout: 0, title: $msg("Setup.Doctor.Title") } + // ); + // if (performDoctor == buttons.no) { + // return { settings: tryingSettings, shouldRebuild: false, isModified: false }; + // } + + // const newSettings = JSON.parse(JSON.stringify(tryingSettings)) as ObsidianLiveSyncSettings; + // const { settings, shouldRebuild, isModified } = await performDoctorConsultation(this.core, newSettings, { + // localRebuild: RebuildOptions.AutomaticAcceptable, // Because we are in the setup wizard, we can skip the confirmation. + // remoteRebuild: RebuildOptions.SkipEvenIfRequired, + // activateReason: "New settings from URI", + // }); + // if (isModified) { + // this._log("Doctor has fixed some issues!", LOG_LEVEL_NOTICE); + // return { + // settings, + // shouldRebuild, + // isModified, + // }; + // } else { + // this._log("Doctor detected no issues!", LOG_LEVEL_NOTICE); + // return { settings: tryingSettings, shouldRebuild: false, isModified: false }; + // } + // } + + // async applySettingWizard( + // oldConf: ObsidianLiveSyncSettings, + // newConf: ObsidianLiveSyncSettings, + // method = "Setup URI" + // ) { + // const result = await this.core.confirm.askYesNoDialog( + // "Importing Configuration from the " + method + ". Are you sure to proceed ? ", + // {} + // ); + // if (result == "yes") { + // let newSettingW = Object.assign({}, DEFAULT_SETTINGS, newConf) as ObsidianLiveSyncSettings; + // this.core.replicator.closeReplication(); + // this.settings.suspendFileWatching = true; + // newSettingW = await this.askSyncWithRemoteConfig(newSettingW); + // const { settings, shouldRebuild, isModified } = await this.askPerformDoctor(newSettingW); + // if (isModified) { + // newSettingW = settings; + // } + // // Back into the default method once. + // newSettingW.configPassphraseStore = ""; + // newSettingW.encryptedPassphrase = ""; + // newSettingW.encryptedCouchDBConnection = ""; + // newSettingW.additionalSuffixOfDatabaseName = `${"appId" in this.app ? this.app.appId : ""} `; + // const setupJustImport = $msg("Setup.Apply.Buttons.OnlyApply"); + // const setupAsNew = $msg("Setup.Apply.Buttons.ApplyAndFetch"); + // const setupAsMerge = $msg("Setup.Apply.Buttons.ApplyAndMerge"); + // const setupAgain = $msg("Setup.Apply.Buttons.ApplyAndRebuild"); + // const setupCancel = $msg("Setup.Apply.Buttons.Cancel"); + // newSettingW.syncInternalFiles = false; + // newSettingW.usePluginSync = false; + // newSettingW.isConfigured = true; + // // Migrate completely obsoleted configuration. + // if (!newSettingW.useIndexedDBAdapter) { + // newSettingW.useIndexedDBAdapter = true; + // } + // const warn = shouldRebuild ? $msg("Setup.Apply.WarningRebuildRecommended") : ""; + // const message = $msg("Setup.Apply.Message", { + // method, + // warn, + // }); + + // const setupType = await this.core.confirm.askSelectStringDialogue( + // message, + // [setupAsNew, setupAsMerge, setupAgain, setupJustImport, setupCancel], + // { defaultAction: setupAsNew, title: $msg("Setup.Apply.Title", { method }), timeout: 0 } + // ); + // if (setupType == setupJustImport) { + // this.core.settings = newSettingW; + // this.services.setting.clearUsedPassphrase(); + // await this.core.saveSettings(); + // } else if (setupType == setupAsNew) { + // this.core.settings = newSettingW; + // this.services.setting.clearUsedPassphrase(); + // await this.core.saveSettings(); + // await this.core.rebuilder.$fetchLocal(); + // } else if (setupType == setupAsMerge) { + // this.core.settings = newSettingW; + // this.services.setting.clearUsedPassphrase(); + // await this.core.saveSettings(); + // await this.core.rebuilder.$fetchLocal(true); + // } else if (setupType == setupAgain) { + // const confirm = + // "This operation will rebuild all databases with files on this device. Any files on the remote database not synced here will be lost."; + // if ( + // (await this.core.confirm.askSelectStringDialogue( + // "Are you sure you want to do this?", + // ["Cancel", confirm], + // { defaultAction: "Cancel" } + // )) != confirm + // ) { + // return; + // } + // this.core.settings = newSettingW; + // await this.core.saveSettings(); + // this.services.setting.clearUsedPassphrase(); + // await this.core.rebuilder.$rebuildEverything(); + // } else { + // // Explicitly cancel the operation or the dialog was closed. + // this._log("Cancelled", LOG_LEVEL_NOTICE); + // this.core.settings = oldConf; + // return; + // } + // this._log("Configuration loaded.", LOG_LEVEL_NOTICE); + // } else { + // this._log("Cancelled", LOG_LEVEL_NOTICE); + // this.core.settings = oldConf; + // return; + // } + // } + // async setupWizard(confString: string) { + // try { + // const oldConf = JSON.parse(JSON.stringify(this.settings)); + // const encryptingPassphrase = await this.core.confirm.askString( + // "Passphrase", + // "The passphrase to decrypt your setup URI", + // "", + // true + // ); + // if (encryptingPassphrase === false) return; + // const newConf = await JSON.parse(await decryptString(confString, encryptingPassphrase)); + // if (newConf) { + // await this.applySettingWizard(oldConf, newConf); + // this._log("Configuration loaded.", LOG_LEVEL_NOTICE); + // } else { + // this._log("Cancelled.", LOG_LEVEL_NOTICE); + // } + // } catch (ex) { + // this._log("Couldn't parse or decrypt configuration uri.", LOG_LEVEL_NOTICE); + // this._log(ex, LOG_LEVEL_VERBOSE); + // } + // } + + // async askHowToApplySetupURI() { + // const method = await this.dialogManager.openWithExplicitCancel(OutroAskUserMode); + // if( method === "new-user") { + // return UserMode.NewUser; + // } + // } - const setupType = await this.core.confirm.askSelectStringDialogue( - message, - [setupAsNew, setupAsMerge, setupAgain, setupJustImport, setupCancel], - { defaultAction: setupAsNew, title: $msg("Setup.Apply.Title", { method }), timeout: 0 } - ); - if (setupType == setupJustImport) { - this.core.settings = newSettingW; - this.services.setting.clearUsedPassphrase(); - await this.core.saveSettings(); - } else if (setupType == setupAsNew) { - this.core.settings = newSettingW; - this.services.setting.clearUsedPassphrase(); - await this.core.saveSettings(); - await this.core.rebuilder.$fetchLocal(); - } else if (setupType == setupAsMerge) { - this.core.settings = newSettingW; - this.services.setting.clearUsedPassphrase(); - await this.core.saveSettings(); - await this.core.rebuilder.$fetchLocal(true); - } else if (setupType == setupAgain) { - const confirm = - "This operation will rebuild all databases with files on this device. Any files on the remote database not synced here will be lost."; - if ( - (await this.core.confirm.askSelectStringDialogue( - "Are you sure you want to do this?", - ["Cancel", confirm], - { defaultAction: "Cancel" } - )) != confirm - ) { - return; - } - this.core.settings = newSettingW; - await this.core.saveSettings(); - this.services.setting.clearUsedPassphrase(); - await this.core.rebuilder.$rebuildEverything(); - } else { - // Explicitly cancel the operation or the dialog was closed. - this._log("Cancelled", LOG_LEVEL_NOTICE); - this.core.settings = oldConf; - return; - } - this._log("Configuration loaded.", LOG_LEVEL_NOTICE); - } else { - this._log("Cancelled", LOG_LEVEL_NOTICE); - this.core.settings = oldConf; - return; - } - } - async setupWizard(confString: string) { - try { - const oldConf = JSON.parse(JSON.stringify(this.settings)); - const encryptingPassphrase = await this.core.confirm.askString( - "Passphrase", - "The passphrase to decrypt your setup URI", - "", - true - ); - if (encryptingPassphrase === false) return; - const newConf = await JSON.parse(await decryptString(confString, encryptingPassphrase)); - if (newConf) { - await this.applySettingWizard(oldConf, newConf); - this._log("Configuration loaded.", LOG_LEVEL_NOTICE); - } else { - this._log("Cancelled.", LOG_LEVEL_NOTICE); - } - } catch (ex) { - this._log("Couldn't parse or decrypt configuration uri.", LOG_LEVEL_NOTICE); - this._log(ex, LOG_LEVEL_VERBOSE); - } - } onBindFunction(core: LiveSyncCore, services: typeof core.services): void { services.appLifecycle.handleOnLoaded(this._everyOnload.bind(this)); } diff --git a/src/modules/features/SettingDialogue/InfoPanel.svelte b/src/modules/features/SettingDialogue/InfoPanel.svelte new file mode 100644 index 0000000..e5f2696 --- /dev/null +++ b/src/modules/features/SettingDialogue/InfoPanel.svelte @@ -0,0 +1,80 @@ + + +
+
+ {#each infoEntries as [key, value]} +
+
{key}
+
+
+
{value}
+
+ {/each} +
+
+ + diff --git a/src/modules/features/SettingDialogue/PaneHatch.ts b/src/modules/features/SettingDialogue/PaneHatch.ts index cfc6a01..9923e45 100644 --- a/src/modules/features/SettingDialogue/PaneHatch.ts +++ b/src/modules/features/SettingDialogue/PaneHatch.ts @@ -170,11 +170,13 @@ ${stringifyYaml({ ...pluginConfig, })}`; console.log(msgConfig); - await navigator.clipboard.writeText(msgConfig); - Logger( - `Generated report has been copied to clipboard. Please report the issue with this! Thank you for your cooperation!`, - LOG_LEVEL_NOTICE - ); + if ((await this.services.UI.promptCopyToClipboard("Generated report", msgConfig)) == true) { + // await navigator.clipboard.writeText(msgConfig); + // Logger( + // `Generated report has been copied to clipboard. Please report the issue with this! Thank you for your cooperation!`, + // LOG_LEVEL_NOTICE + // ); + } }) ); new Setting(paneEl).autoWireToggle("writeLogToTheFile"); diff --git a/src/modules/features/SettingDialogue/PaneMaintenance.ts b/src/modules/features/SettingDialogue/PaneMaintenance.ts index 9afa213..5747209 100644 --- a/src/modules/features/SettingDialogue/PaneMaintenance.ts +++ b/src/modules/features/SettingDialogue/PaneMaintenance.ts @@ -1,6 +1,6 @@ import { LocalDatabaseMaintenance } from "../../../features/LocalDatabaseMainte/CmdLocalDatabaseMainte.ts"; import { LOG_LEVEL_NOTICE, Logger } from "../../../lib/src/common/logger.ts"; -import { FLAGMD_REDFLAG, FLAGMD_REDFLAG2_HR, FLAGMD_REDFLAG3_HR } from "../../../lib/src/common/types.ts"; +import { FlagFilesHumanReadable, FLAGMD_REDFLAG } from "../../../lib/src/common/types.ts"; import { fireAndForget } from "../../../lib/src/common/utils.ts"; import { LiveSyncCouchDBReplicator } from "../../../lib/src/replication/couchdb/LiveSyncReplicator.ts"; import { LiveSyncSetting as Setting } from "./LiveSyncSetting.ts"; @@ -98,6 +98,35 @@ export function paneMaintenance( ); }); + void addPanel(paneEl, "Reset Synchronisation information").then((paneEl) => { + new Setting(paneEl) + .setName("Reset Synchronisation on This Device") + .setDesc("Restore or reconstruct local database from remote.") + .addButton((button) => + button + .setButtonText("Schedule and Restart") + .setCta() + .setDisabled(false) + .onClick(async () => { + await this.plugin.storageAccess.writeFileAuto(FlagFilesHumanReadable.FETCH_ALL, ""); + this.services.appLifecycle.performRestart(); + }) + ); + new Setting(paneEl) + .setName("Overwrite Server Data with This Device's Files") + .setDesc("Rebuild local and remote database with local files.") + .addButton((button) => + button + .setButtonText("Schedule and Restart") + .setCta() + .setDisabled(false) + .onClick(async () => { + await this.plugin.storageAccess.writeFileAuto(FlagFilesHumanReadable.REBUILD_ALL, ""); + this.services.appLifecycle.performRestart(); + }) + ); + }); + void addPanel(paneEl, "Syncing", () => {}, this.onlyOnCouchDBOrMinIO).then((paneEl) => { new Setting(paneEl) .setName("Resend") @@ -244,69 +273,7 @@ export function paneMaintenance( ); } ); - void addPanel(paneEl, "Rebuilding Operations (Local)").then((paneEl) => { - new Setting(paneEl) - .setName("Fetch from remote") - .setDesc("Restore or reconstruct local database from remote.") - .addButton((button) => - button - .setButtonText("Fetch") - .setWarning() - .setDisabled(false) - .onClick(async () => { - await this.plugin.storageAccess.writeFileAuto(FLAGMD_REDFLAG3_HR, ""); - this.services.appLifecycle.performRestart(); - }) - ) - .addButton((button) => - button - .setButtonText("Fetch w/o restarting") - .setWarning() - .setDisabled(false) - .onClick(async () => { - await this.rebuildDB("localOnly"); - }) - ); - new Setting(paneEl) - .setName("Fetch rebuilt DB (Save local documents before)") - .setDesc("Restore or reconstruct local database from remote database but use local chunks.") - .addButton((button) => - button - .setButtonText("Save and Fetch") - .setWarning() - .setDisabled(false) - .onClick(async () => { - await this.rebuildDB("localOnlyWithChunks"); - }) - ) - .addOnUpdate(this.onlyOnCouchDB); - }); - - void addPanel(paneEl, "Total Overhaul", () => {}, this.onlyOnCouchDBOrMinIO).then((paneEl) => { - new Setting(paneEl) - .setName("Rebuild everything") - .setDesc("Rebuild local and remote database with local files.") - .addButton((button) => - button - .setButtonText("Rebuild") - .setWarning() - .setDisabled(false) - .onClick(async () => { - await this.plugin.storageAccess.writeFileAuto(FLAGMD_REDFLAG2_HR, ""); - this.services.appLifecycle.performRestart(); - }) - ) - .addButton((button) => - button - .setButtonText("Rebuild w/o restarting") - .setWarning() - .setDisabled(false) - .onClick(async () => { - await this.rebuildDB("rebuildBothByThisDevice"); - }) - ); - }); void addPanel(paneEl, "Rebuilding Operations (Remote Only)", () => {}, this.onlyOnCouchDBOrMinIO).then((paneEl) => { new Setting(paneEl) .setName("Perform cleanup") diff --git a/src/modules/features/SettingDialogue/PaneRemoteConfig.ts b/src/modules/features/SettingDialogue/PaneRemoteConfig.ts index d8228eb..0d8a578 100644 --- a/src/modules/features/SettingDialogue/PaneRemoteConfig.ts +++ b/src/modules/features/SettingDialogue/PaneRemoteConfig.ts @@ -1,307 +1,213 @@ -import { MarkdownRenderer } from "../../../deps.ts"; import { - LOG_LEVEL_NOTICE, - LOG_LEVEL_VERBOSE, - PREFERRED_JOURNAL_SYNC, - PREFERRED_SETTING_CLOUDANT, - PREFERRED_SETTING_SELF_HOSTED, REMOTE_COUCHDB, REMOTE_MINIO, REMOTE_P2P, + type ObsidianLiveSyncSettings, } from "../../../lib/src/common/types.ts"; -import { parseHeaderValues } from "../../../lib/src/common/utils.ts"; -import { LOG_LEVEL_INFO, Logger } from "../../../lib/src/common/logger.ts"; -import { isCloudantURI } from "../../../lib/src/pouchdb/utils_couchdb.ts"; -import { requestToCouchDBWithCredentials } from "../../../common/utils.ts"; import { $msg } from "../../../lib/src/common/i18n.ts"; import { LiveSyncSetting as Setting } from "./LiveSyncSetting.ts"; -import { fireAndForget } from "octagonal-wheels/promises"; -import { generateCredentialObject } from "../../../lib/src/replication/httplib.ts"; import type { ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts"; import type { PageFunctions } from "./SettingPane.ts"; -import { combineOnUpdate, visibleOnly } from "./SettingPane.ts"; -import { getWebCrypto } from "../../../lib/src/mods.ts"; -import { arrayBufferToBase64Single } from "../../../lib/src/string_and_binary/convert.ts"; +import { visibleOnly } from "./SettingPane.ts"; +import InfoPanel from "./InfoPanel.svelte"; +import { writable } from "svelte/store"; +import { SveltePanel } from "./SveltePanel.ts"; +import { + getBucketConfigSummary, + getP2PConfigSummary, + getCouchDBConfigSummary, + getE2EEConfigSummary, +} from "./settingUtils.ts"; +import { SETTING_KEY_P2P_DEVICE_NAME } from "../../../lib/src/common/types.ts"; +import { SetupManager, UserMode } from "../ModuleSetupObsidian.ts"; +import { OnDialogSettingsDefault, type AllSettings } from "./settingConstants.ts"; + +function getSettingsFromEditingSettings(editingSettings: AllSettings): ObsidianLiveSyncSettings { + const workObj = { ...editingSettings } as ObsidianLiveSyncSettings; + const keys = Object.keys(OnDialogSettingsDefault); + for (const k of keys) { + delete (workObj as any)[k]; + } + return workObj; +} + export function paneRemoteConfig( this: ObsidianLiveSyncSettingTab, paneEl: HTMLElement, { addPanel, addPane }: PageFunctions ): void { - let checkResultDiv: HTMLDivElement; - const checkConfig = async (checkResultDiv: HTMLDivElement | undefined) => { - Logger($msg("obsidianLiveSyncSettingTab.logCheckingDbConfig"), LOG_LEVEL_INFO); - let isSuccessful = true; - const emptyDiv = createDiv(); - emptyDiv.innerHTML = ""; - checkResultDiv?.replaceChildren(...[emptyDiv]); - const addResult = (msg: string, classes?: string[]) => { - const tmpDiv = createDiv(); - tmpDiv.addClass("ob-btn-config-fix"); - if (classes) { - tmpDiv.addClasses(classes); - } - tmpDiv.innerHTML = `${msg}`; - checkResultDiv?.appendChild(tmpDiv); + const remoteNameMap = { + [REMOTE_COUCHDB]: $msg("obsidianLiveSyncSettingTab.optionCouchDB"), + [REMOTE_MINIO]: $msg("obsidianLiveSyncSettingTab.optionMinioS3R2"), + [REMOTE_P2P]: "Only Peer-to-Peer", + } as const; + + { + /* E2EE */ + const E2EEInitialProps = { + info: getE2EEConfigSummary({ ...this.editingSettings }), }; - try { - if (isCloudantURI(this.editingSettings.couchDB_URI)) { - Logger($msg("obsidianLiveSyncSettingTab.logCannotUseCloudant"), LOG_LEVEL_NOTICE); - return; - } - // Tip: Add log for cloudant as Logger($msg("obsidianLiveSyncSettingTab.logServerConfigurationCheck")); - const customHeaders = parseHeaderValues(this.editingSettings.couchDB_CustomHeaders); - const credential = generateCredentialObject(this.editingSettings); - const r = await requestToCouchDBWithCredentials( - this.editingSettings.couchDB_URI, - credential, - window.origin, - undefined, - undefined, - undefined, - customHeaders - ); - const responseConfig = r.json; - - const addConfigFixButton = (title: string, key: string, value: string) => { - if (!checkResultDiv) return; - const tmpDiv = createDiv(); - tmpDiv.addClass("ob-btn-config-fix"); - tmpDiv.innerHTML = ``; - const x = checkResultDiv.appendChild(tmpDiv); - x.querySelector("button")?.addEventListener("click", () => { - fireAndForget(async () => { - Logger($msg("obsidianLiveSyncSettingTab.logCouchDbConfigSet", { title, key, value })); - const res = await requestToCouchDBWithCredentials( - this.editingSettings.couchDB_URI, - credential, - undefined, - key, - value, - undefined, - customHeaders - ); - if (res.status == 200) { - Logger( - $msg("obsidianLiveSyncSettingTab.logCouchDbConfigUpdated", { title }), - LOG_LEVEL_NOTICE - ); - checkResultDiv.removeChild(x); - await checkConfig(checkResultDiv); - } else { - Logger( - $msg("obsidianLiveSyncSettingTab.logCouchDbConfigFail", { title }), - LOG_LEVEL_NOTICE - ); - Logger(res.text, LOG_LEVEL_VERBOSE); - } - }); - }); - }; - addResult($msg("obsidianLiveSyncSettingTab.msgNotice"), ["ob-btn-config-head"]); - addResult($msg("obsidianLiveSyncSettingTab.msgIfConfigNotPersistent"), ["ob-btn-config-info"]); - addResult($msg("obsidianLiveSyncSettingTab.msgConfigCheck"), ["ob-btn-config-head"]); - - const serverBanner = r.headers["server"] ?? r.headers["Server"] ?? "unknown"; - addResult($msg("obsidianLiveSyncSettingTab.serverVersion", { info: serverBanner })); - const versionMatch = serverBanner.match(/CouchDB(\/([0-9.]+))?/); - const versionStr = versionMatch ? versionMatch[2] : "0.0.0"; - const versionParts = `${versionStr}.0.0.0`.split("."); - // Compare version string with the target version. - // version must be a string like "3.2.1" or "3.10.2", and must be two or three parts. - function isGreaterThanOrEqual(version: string) { - const targetParts = version.split("."); - for (let i = 0; i < targetParts.length; i++) { - // compare as number if possible (so 3.10 > 3.2, 3.10.1b > 3.10.1a) - const result = versionParts[i].localeCompare(targetParts[i], undefined, { numeric: true }); - if (result > 0) return true; - if (result < 0) return false; - } - return true; - } - // Admin check - // for database creation and deletion - if (!(this.editingSettings.couchDB_USER in responseConfig.admins)) { - addResult($msg("obsidianLiveSyncSettingTab.warnNoAdmin")); - } else { - addResult($msg("obsidianLiveSyncSettingTab.okAdminPrivileges")); - } - if (isGreaterThanOrEqual("3.2.0")) { - // HTTP user-authorization check - if (responseConfig?.chttpd?.require_valid_user != "true") { - isSuccessful = false; - addResult($msg("obsidianLiveSyncSettingTab.errRequireValidUser")); - addConfigFixButton( - $msg("obsidianLiveSyncSettingTab.msgSetRequireValidUser"), - "chttpd/require_valid_user", - "true" - ); - } else { - addResult($msg("obsidianLiveSyncSettingTab.okRequireValidUser")); - } - } else { - if (responseConfig?.chttpd_auth?.require_valid_user != "true") { - isSuccessful = false; - addResult($msg("obsidianLiveSyncSettingTab.errRequireValidUserAuth")); - addConfigFixButton( - $msg("obsidianLiveSyncSettingTab.msgSetRequireValidUserAuth"), - "chttpd_auth/require_valid_user", - "true" - ); - } else { - addResult($msg("obsidianLiveSyncSettingTab.okRequireValidUserAuth")); - } - } - // HTTPD check - // Check Authentication header - if (!responseConfig?.httpd["WWW-Authenticate"]) { - isSuccessful = false; - addResult($msg("obsidianLiveSyncSettingTab.errMissingWwwAuth")); - addConfigFixButton( - $msg("obsidianLiveSyncSettingTab.msgSetWwwAuth"), - "httpd/WWW-Authenticate", - 'Basic realm="couchdb"' - ); - } else { - addResult($msg("obsidianLiveSyncSettingTab.okWwwAuth")); - } - if (isGreaterThanOrEqual("3.2.0")) { - if (responseConfig?.chttpd?.enable_cors != "true") { - isSuccessful = false; - addResult($msg("obsidianLiveSyncSettingTab.errEnableCorsChttpd")); - addConfigFixButton( - $msg("obsidianLiveSyncSettingTab.msgEnableCorsChttpd"), - "chttpd/enable_cors", - "true" - ); - } else { - addResult($msg("obsidianLiveSyncSettingTab.okEnableCorsChttpd")); - } - } else { - if (responseConfig?.httpd?.enable_cors != "true") { - isSuccessful = false; - addResult($msg("obsidianLiveSyncSettingTab.errEnableCors")); - addConfigFixButton($msg("obsidianLiveSyncSettingTab.msgEnableCors"), "httpd/enable_cors", "true"); - } else { - addResult($msg("obsidianLiveSyncSettingTab.okEnableCors")); - } - } - // If the server is not cloudant, configure request size - if (!isCloudantURI(this.editingSettings.couchDB_URI)) { - // REQUEST SIZE - if (Number(responseConfig?.chttpd?.max_http_request_size ?? 0) < 4294967296) { - isSuccessful = false; - addResult($msg("obsidianLiveSyncSettingTab.errMaxRequestSize")); - addConfigFixButton( - $msg("obsidianLiveSyncSettingTab.msgSetMaxRequestSize"), - "chttpd/max_http_request_size", - "4294967296" - ); - } else { - addResult($msg("obsidianLiveSyncSettingTab.okMaxRequestSize")); - } - if (Number(responseConfig?.couchdb?.max_document_size ?? 0) < 50000000) { - isSuccessful = false; - addResult($msg("obsidianLiveSyncSettingTab.errMaxDocumentSize")); - addConfigFixButton( - $msg("obsidianLiveSyncSettingTab.msgSetMaxDocSize"), - "couchdb/max_document_size", - "50000000" - ); - } else { - addResult($msg("obsidianLiveSyncSettingTab.okMaxDocumentSize")); - } - } - // CORS check - // checking connectivity for mobile - if (responseConfig?.cors?.credentials != "true") { - isSuccessful = false; - addResult($msg("obsidianLiveSyncSettingTab.errCorsCredentials")); - addConfigFixButton( - $msg("obsidianLiveSyncSettingTab.msgSetCorsCredentials"), - "cors/credentials", - "true" - ); - } else { - addResult($msg("obsidianLiveSyncSettingTab.okCorsCredentials")); - } - const ConfiguredOrigins = ((responseConfig?.cors?.origins ?? "") + "").split(","); - if ( - responseConfig?.cors?.origins == "*" || - (ConfiguredOrigins.indexOf("app://obsidian.md") !== -1 && - ConfiguredOrigins.indexOf("capacitor://localhost") !== -1 && - ConfiguredOrigins.indexOf("http://localhost") !== -1) - ) { - addResult($msg("obsidianLiveSyncSettingTab.okCorsOrigins")); - } else { - const fixedValue = [ - ...new Set([ - ...ConfiguredOrigins.map((e) => e.trim()), - "app://obsidian.md", - "capacitor://localhost", - "http://localhost", - ]), - ].join(","); - addResult($msg("obsidianLiveSyncSettingTab.errCorsOrigins")); - addConfigFixButton($msg("obsidianLiveSyncSettingTab.msgSetCorsOrigins"), "cors/origins", fixedValue); - isSuccessful = false; - } - addResult($msg("obsidianLiveSyncSettingTab.msgConnectionCheck"), ["ob-btn-config-head"]); - addResult($msg("obsidianLiveSyncSettingTab.msgCurrentOrigin", { origin: window.location.origin })); - - // Request header check - const origins = ["app://obsidian.md", "capacitor://localhost", "http://localhost"]; - for (const org of origins) { - const rr = await requestToCouchDBWithCredentials( - this.editingSettings.couchDB_URI, - credential, - org, - undefined, - undefined, - undefined, - customHeaders - ); - const responseHeaders = Object.fromEntries( - Object.entries(rr.headers).map((e) => { - e[0] = `${e[0]}`.toLowerCase(); - return e; + const E2EESummaryWritable = writable(E2EEInitialProps); + const updateE2EESummary = () => { + E2EESummaryWritable.set({ + info: getE2EEConfigSummary(this.editingSettings), + }); + }; + void addPanel(paneEl, "E2EE Configuration", () => {}).then((paneEl) => { + new SveltePanel(InfoPanel, paneEl, E2EESummaryWritable); + const setupButton = new Setting(paneEl).setName("Configure E2EE"); + setupButton.addButton((button) => + button + .onClick(async () => { + const setupManager = this.plugin.getModule(SetupManager); + const originalSettings = getSettingsFromEditingSettings(this.editingSettings); + await setupManager.onlyE2EEConfiguration(UserMode.Update, originalSettings); + updateE2EESummary(); }) - ); - addResult($msg("obsidianLiveSyncSettingTab.msgOriginCheck", { org })); - if (responseHeaders["access-control-allow-credentials"] != "true") { - addResult($msg("obsidianLiveSyncSettingTab.errCorsNotAllowingCredentials")); - isSuccessful = false; - } else { - addResult($msg("obsidianLiveSyncSettingTab.okCorsCredentialsForOrigin")); - } - if (responseHeaders["access-control-allow-origin"] != org) { - addResult( - $msg("obsidianLiveSyncSettingTab.warnCorsOriginUnmatched", { - from: origin, - to: responseHeaders["access-control-allow-origin"], - }) - ); - } else { - addResult($msg("obsidianLiveSyncSettingTab.okCorsOriginMatched")); - } - } - addResult($msg("obsidianLiveSyncSettingTab.msgDone"), ["ob-btn-config-head"]); - addResult($msg("obsidianLiveSyncSettingTab.msgConnectionProxyNote"), ["ob-btn-config-info"]); - Logger($msg("obsidianLiveSyncSettingTab.logCheckingConfigDone"), LOG_LEVEL_INFO); - } catch (ex: any) { - if (ex?.status == 401) { - isSuccessful = false; - addResult($msg("obsidianLiveSyncSettingTab.errAccessForbidden")); - addResult($msg("obsidianLiveSyncSettingTab.errCannotContinueTest")); - Logger($msg("obsidianLiveSyncSettingTab.logCheckingConfigDone"), LOG_LEVEL_INFO); - } else { - Logger($msg("obsidianLiveSyncSettingTab.logCheckingConfigFailed"), LOG_LEVEL_NOTICE); - Logger(ex); - isSuccessful = false; - } - } - return isSuccessful; - }; - void addPanel(paneEl, $msg("obsidianLiveSyncSettingTab.titleRemoteServer")).then((paneEl) => { + .setButtonText("Configure") + .setWarning() + ); + updateE2EESummary(); + }); + } + { + void addPanel( + paneEl, + $msg("obsidianLiveSyncSettingTab.titleRemoteServer"), + () => {}, + () => ({ classes: this.editingSettings.remoteType === REMOTE_COUCHDB ? ["active-sync"] : [] }) + ).then((paneEl) => { + const nSetting = new Setting(paneEl).setName("Active Remote Configuration"); + + const el = nSetting.controlEl.createDiv({}); + el.setText(`${remoteNameMap[this.editingSettings.remoteType] || " - "}`); + nSetting.addButton((button) => + button + .setButtonText("Change Remote and Setup") + .setCta() + .onClick(async () => { + const setupManager = this.plugin.getModule(SetupManager); + const originalSettings = getSettingsFromEditingSettings(this.editingSettings); + await setupManager.selectServer(originalSettings, UserMode.Update); + }) + ); + }); + } + { + const initialProps = { + info: getCouchDBConfigSummary(this.editingSettings), + }; + const summaryWritable = writable(initialProps); + const updateSummary = () => { + summaryWritable.set({ + info: getCouchDBConfigSummary(this.editingSettings), + }); + }; + void addPanel( + paneEl, + $msg("obsidianLiveSyncSettingTab.titleCouchDB"), + () => {}, + () => ({ classes: this.editingSettings.remoteType === REMOTE_COUCHDB ? ["active-sync"] : [] }) + ).then((paneEl) => { + new SveltePanel(InfoPanel, paneEl, summaryWritable); + const setupButton = new Setting(paneEl).setName("Configure Remote"); + setupButton.addButton((button) => + button + .setButtonText("Configure") + .setCta() + .onClick(async () => { + const setupManager = this.plugin.getModule(SetupManager); + const originalSettings = getSettingsFromEditingSettings(this.editingSettings); + await setupManager.onCouchDBManualSetup( + UserMode.Update, + originalSettings, + this.editingSettings.remoteType === REMOTE_COUCHDB + ); + + updateSummary(); + }) + ); + }); + } + { + const initialProps = { + info: getBucketConfigSummary(this.editingSettings), + }; + const summaryWritable = writable(initialProps); + const updateSummary = () => { + summaryWritable.set({ + info: getBucketConfigSummary(this.editingSettings), + }); + }; + void addPanel( + paneEl, + $msg("obsidianLiveSyncSettingTab.titleMinioS3R2"), + () => {}, + () => ({ classes: this.editingSettings.remoteType === REMOTE_MINIO ? ["active-sync"] : [] }) + ).then((paneEl) => { + new SveltePanel(InfoPanel, paneEl, summaryWritable); + const setupButton = new Setting(paneEl).setName("Configure Remote"); + setupButton.addButton((button) => + button + .setButtonText("Configure") + .setCta() + .onClick(async () => { + const setupManager = this.plugin.getModule(SetupManager); + const originalSettings = getSettingsFromEditingSettings(this.editingSettings); + await setupManager.onBucketManualSetup( + UserMode.Update, + originalSettings, + this.editingSettings.remoteType === REMOTE_MINIO + ); + //TODO + updateSummary(); + }) + ); + }); + } + { + const getDevicePeerId = () => this.services.config.getSmallConfig(SETTING_KEY_P2P_DEVICE_NAME) || ""; + const initialProps = { + info: getP2PConfigSummary(this.editingSettings, { + "Device Peer ID": getDevicePeerId(), + }), + }; + const summaryWritable = writable(initialProps); + const updateSummary = () => { + summaryWritable.set({ + info: getP2PConfigSummary(this.editingSettings, { + "Device Peer ID": getDevicePeerId(), + }), + }); + }; + void addPanel( + paneEl, + "Peer-to-Peer Synchronisation", + () => {}, + () => ({ classes: this.editingSettings.remoteType === REMOTE_P2P ? ["active-sync"] : [] }) + ).then((paneEl) => { + new SveltePanel(InfoPanel, paneEl, summaryWritable); + const setupButton = new Setting(paneEl).setName("Configure Remote"); + setupButton.addButton((button) => + button + .setButtonText("Configure") + .setCta() + .onClick(async () => { + const setupManager = this.plugin.getModule(SetupManager); + const originalSettings = getSettingsFromEditingSettings(this.editingSettings); + await setupManager.onP2PManualSetup( + UserMode.Update, + originalSettings, + this.editingSettings.remoteType === REMOTE_P2P + ); + //TODO + updateSummary(); + }) + ); + }); + } + + void addPanel(paneEl, $msg("obsidianLiveSyncSettingTab.titleActiveRemoteServer")).then((paneEl) => { // const containerRemoteDatabaseEl = containerEl.createDiv(); this.createEl( paneEl, @@ -312,431 +218,132 @@ export function paneRemoteConfig( undefined, visibleOnly(() => this.isAnySyncEnabled()) ).addClass("op-warn-info"); - new Setting(paneEl).autoWireDropDown("remoteType", { - holdValue: true, - options: { - [REMOTE_COUCHDB]: $msg("obsidianLiveSyncSettingTab.optionCouchDB"), - [REMOTE_MINIO]: $msg("obsidianLiveSyncSettingTab.optionMinioS3R2"), - [REMOTE_P2P]: "Only Peer-to-Peer", - }, - onUpdate: this.enableOnlySyncDisabled, - }); - }); - void addPanel(paneEl, "Peer-to-Peer", undefined, this.onlyOnOnlyP2P).then((paneEl) => { - const syncWarnP2P = this.createEl(paneEl, "div", { - text: "", - }); - const p2pMessage = `This feature is a Work In Progress, and configurable on \`P2P Replicator\` Pane. -The pane also can be launched by \`P2P Replicator\` command from the Command Palette. -`; - - void MarkdownRenderer.render(this.plugin.app, p2pMessage, syncWarnP2P, "/", this.plugin); - syncWarnP2P.addClass("op-warn-info"); - new Setting(paneEl).setName("Apply Settings").setClass("wizardHidden").addApplyButton(["remoteType"]); - // .addOnUpdate(onlyOnMinIO); - // new Setting(paneEl).addButton((button) => - // button - // .setButtonText("Open P2P Replicator") - // .onClick(() => { - // const addOn = this.plugin.getAddOn(P2PReplicator.name); - // void addOn?.openPane(); - // this.closeSetting(); - // }) - // ); - }); - void addPanel(paneEl, $msg("obsidianLiveSyncSettingTab.titleMinioS3R2"), undefined, this.onlyOnMinIO).then( - (paneEl) => { - const syncWarnMinio = this.createEl(paneEl, "div", { - text: "", - }); - const ObjectStorageMessage = $msg("obsidianLiveSyncSettingTab.msgObjectStorageWarning"); - - void MarkdownRenderer.render(this.plugin.app, ObjectStorageMessage, syncWarnMinio, "/", this.plugin); - syncWarnMinio.addClass("op-warn-info"); - - new Setting(paneEl).autoWireText("endpoint", { holdValue: true }); - new Setting(paneEl).autoWireToggle("forcePathStyle", { holdValue: true }); - new Setting(paneEl).autoWireText("accessKey", { holdValue: true }); - - new Setting(paneEl).autoWireText("secretKey", { - holdValue: true, - isPassword: true, - }); - - new Setting(paneEl).autoWireText("region", { holdValue: true }); - - new Setting(paneEl).autoWireText("bucket", { holdValue: true }); - new Setting(paneEl).autoWireText("bucketPrefix", { - holdValue: true, - placeHolder: "vaultname/", - }); - - new Setting(paneEl).autoWireToggle("useCustomRequestHandler", { holdValue: true }); - new Setting(paneEl).autoWireTextArea("bucketCustomHeaders", { - holdValue: true, - placeHolder: "x-custom-header: value\n x-custom-header2: value2", - }); - new Setting(paneEl).setName($msg("obsidianLiveSyncSettingTab.nameTestConnection")).addButton((button) => - button - .setButtonText($msg("obsidianLiveSyncSettingTab.btnTest")) - .setDisabled(false) - .onClick(async () => { - await this.testConnection(this.editingSettings); - }) - ); - new Setting(paneEl) - .setName($msg("obsidianLiveSyncSettingTab.nameApplySettings")) - .setClass("wizardHidden") - .addApplyButton([ - "remoteType", - "endpoint", - "region", - "accessKey", - "secretKey", - "bucket", - "useCustomRequestHandler", - "bucketCustomHeaders", - "bucketPrefix", - ]) - .addOnUpdate(this.onlyOnMinIO); - } - ); - - void addPanel(paneEl, $msg("obsidianLiveSyncSettingTab.titleCouchDB"), undefined, this.onlyOnCouchDB).then( - (paneEl) => { - if (this.services.API.isMobile()) { - this.createEl( - paneEl, - "div", - { - text: $msg("obsidianLiveSyncSettingTab.msgNonHTTPSWarning"), - }, - undefined, - visibleOnly(() => !this.editingSettings.couchDB_URI.startsWith("https://")) - ).addClass("op-warn"); - } else { - this.createEl( - paneEl, - "div", - { - text: $msg("obsidianLiveSyncSettingTab.msgNonHTTPSInfo"), - }, - undefined, - visibleOnly(() => !this.editingSettings.couchDB_URI.startsWith("https://")) - ).addClass("op-warn-info"); - } - - new Setting(paneEl).autoWireText("couchDB_URI", { - holdValue: true, - onUpdate: this.enableOnlySyncDisabled, - }); - new Setting(paneEl).autoWireToggle("useJWT", { - holdValue: true, - onUpdate: this.enableOnlySyncDisabled, - }); - new Setting(paneEl).autoWireText("couchDB_USER", { - holdValue: true, - onUpdate: combineOnUpdate( - this.enableOnlySyncDisabled, - visibleOnly(() => !this.editingSettings.useJWT) - ), - }); - new Setting(paneEl).autoWireText("couchDB_PASSWORD", { - holdValue: true, - isPassword: true, - onUpdate: combineOnUpdate( - this.enableOnlySyncDisabled, - visibleOnly(() => !this.editingSettings.useJWT) - ), - }); - const algorithms = { - ["HS256"]: "HS256", - ["HS512"]: "HS512", - ["ES256"]: "ES256", - ["ES512"]: "ES512", - } as const; - new Setting(paneEl).autoWireDropDown("jwtAlgorithm", { - options: algorithms, - onUpdate: combineOnUpdate( - this.enableOnlySyncDisabled, - visibleOnly(() => this.editingSettings.useJWT) - ), - }); - new Setting(paneEl).autoWireTextArea("jwtKey", { - holdValue: true, - onUpdate: combineOnUpdate( - this.enableOnlySyncDisabled, - visibleOnly(() => this.editingSettings.useJWT) - ), - }); - // eslint-disable-next-line prefer-const - let generatedKeyDivEl: HTMLDivElement; - new Setting(paneEl) - .setDesc("Generate ES256 Keypair for testing") - .addButton((button) => - button.setButtonText("Generate").onClick(async () => { - const crypto = await getWebCrypto(); - const keyPair = await crypto.subtle.generateKey({ name: "ECDSA", namedCurve: "P-256" }, true, [ - "sign", - "verify", - ]); - const pubKey = await crypto.subtle.exportKey("spki", keyPair.publicKey); - const privateKey = await crypto.subtle.exportKey("pkcs8", keyPair.privateKey); - const encodedPublicKey = await arrayBufferToBase64Single(pubKey); - const encodedPrivateKey = await arrayBufferToBase64Single(privateKey); - - const privateKeyPem = `> -----BEGIN PRIVATE KEY-----\n> ${encodedPrivateKey}\n> -----END PRIVATE KEY-----`; - const publicKeyPem = `> -----BEGIN PUBLIC KEY-----\\n${encodedPublicKey}\\n-----END PUBLIC KEY-----`; - - const title = $msg("Setting.GenerateKeyPair.Title"); - const msg = $msg("Setting.GenerateKeyPair.Desc", { - public_key: publicKeyPem, - private_key: privateKeyPem, - }); - await MarkdownRenderer.render( - this.plugin.app, - "## " + title + "\n\n" + msg, - generatedKeyDivEl, - "/", - this.plugin - ); - }) - ) - .addOnUpdate( - combineOnUpdate( - this.enableOnlySyncDisabled, - visibleOnly(() => this.editingSettings.useJWT) - ) - ); - generatedKeyDivEl = this.createEl( - paneEl, - "div", - { text: "" }, - (el) => {}, - visibleOnly(() => this.editingSettings.useJWT) - ); - - new Setting(paneEl).autoWireText("jwtKid", { - holdValue: true, - onUpdate: combineOnUpdate( - this.enableOnlySyncDisabled, - visibleOnly(() => this.editingSettings.useJWT) - ), - }); - new Setting(paneEl).autoWireText("jwtSub", { - holdValue: true, - onUpdate: combineOnUpdate( - this.enableOnlySyncDisabled, - visibleOnly(() => this.editingSettings.useJWT) - ), - }); - new Setting(paneEl).autoWireNumeric("jwtExpDuration", { - holdValue: true, - onUpdate: combineOnUpdate( - this.enableOnlySyncDisabled, - visibleOnly(() => this.editingSettings.useJWT) - ), - }); - new Setting(paneEl).autoWireText("couchDB_DBNAME", { - holdValue: true, - onUpdate: this.enableOnlySyncDisabled, - }); - new Setting(paneEl).autoWireTextArea("couchDB_CustomHeaders", { holdValue: true }); - new Setting(paneEl).autoWireToggle("useRequestAPI", { - holdValue: true, - onUpdate: this.enableOnlySyncDisabled, - }); - new Setting(paneEl) - .setName($msg("obsidianLiveSyncSettingTab.nameTestDatabaseConnection")) - .setClass("wizardHidden") - .setDesc($msg("obsidianLiveSyncSettingTab.descTestDatabaseConnection")) - .addButton((button) => - button - .setButtonText($msg("obsidianLiveSyncSettingTab.btnTest")) - .setDisabled(false) - .onClick(async () => { - await this.testConnection(); - }) - ); - - new Setting(paneEl) - .setName($msg("obsidianLiveSyncSettingTab.nameValidateDatabaseConfig")) - .setDesc($msg("obsidianLiveSyncSettingTab.descValidateDatabaseConfig")) - .addButton((button) => - button - .setButtonText($msg("obsidianLiveSyncSettingTab.btnCheck")) - .setDisabled(false) - .onClick(async () => { - await checkConfig(checkResultDiv); - }) - ); - checkResultDiv = this.createEl(paneEl, "div", { - text: "", - }); - - new Setting(paneEl) - .setName($msg("obsidianLiveSyncSettingTab.nameApplySettings")) - .setClass("wizardHidden") - .addApplyButton([ - "remoteType", - "couchDB_URI", - "couchDB_USER", - "couchDB_PASSWORD", - "couchDB_DBNAME", - "jwtAlgorithm", - "jwtExpDuration", - "jwtKey", - "jwtSub", - "jwtKid", - "useJWT", - "couchDB_CustomHeaders", - "useRequestAPI", - ]) - .addOnUpdate(this.onlyOnCouchDB); - } - ); - void addPanel(paneEl, $msg("obsidianLiveSyncSettingTab.titleNotification"), () => {}, this.onlyOnCouchDB).then( - (paneEl) => { - paneEl.addClass("wizardHidden"); - new Setting(paneEl).autoWireNumeric("notifyThresholdOfRemoteStorageSize", {}).setClass("wizardHidden"); - } - ); - - void addPanel(paneEl, $msg("obsidianLiveSyncSettingTab.panelPrivacyEncryption")).then((paneEl) => { - new Setting(paneEl).autoWireToggle("encrypt", { holdValue: true }); - - const isEncryptEnabled = visibleOnly(() => this.isConfiguredAs("encrypt", true)); - - new Setting(paneEl).autoWireText("passphrase", { - holdValue: true, - isPassword: true, - onUpdate: isEncryptEnabled, - }); - - new Setting(paneEl).autoWireToggle("usePathObfuscation", { - holdValue: true, - onUpdate: isEncryptEnabled, - }); - }); - - void addPanel(paneEl, $msg("obsidianLiveSyncSettingTab.titleFetchSettings")).then((paneEl) => { new Setting(paneEl) - .setName($msg("obsidianLiveSyncSettingTab.titleFetchConfigFromRemote")) - .setDesc($msg("obsidianLiveSyncSettingTab.descFetchConfigFromRemote")) - .addButton((button) => - button - .setButtonText($msg("obsidianLiveSyncSettingTab.buttonFetch")) - .setDisabled(false) - .onClick(async () => { - const trialSetting = { ...this.initialSettings, ...this.editingSettings }; - const newTweaks = - await this.services.tweakValue.checkAndAskUseRemoteConfiguration(trialSetting); - if (newTweaks.result !== false) { - if (this.inWizard) { - this.editingSettings = { ...this.editingSettings, ...newTweaks.result }; - this.requestUpdate(); - return; - } else { - this.closeSetting(); - this.plugin.settings = { ...this.plugin.settings, ...newTweaks.result }; - if (newTweaks.requireFetch) { - if ( - (await this.plugin.confirm.askYesNoDialog( - $msg("SettingTab.Message.AskRebuild"), - { - defaultOption: "Yes", - } - )) == "no" - ) { - await this.services.setting.saveSettingData(); - return; - } - await this.services.setting.saveSettingData(); - await this.plugin.rebuilder.scheduleFetch(); - this.services.appLifecycle.scheduleRestart(); - return; - } else { - await this.services.setting.saveSettingData(); - } - } - } - }) - ); - }); - new Setting(paneEl).setClass("wizardOnly").addButton((button) => - button - .setButtonText($msg("obsidianLiveSyncSettingTab.buttonNext")) - .setCta() - .setDisabled(false) - .onClick(async () => { - if (!(await checkConfig(checkResultDiv))) { - if ( - (await this.plugin.confirm.askYesNoDialog( - $msg("obsidianLiveSyncSettingTab.msgConfigCheckFailed"), - { - defaultOption: "No", - title: $msg("obsidianLiveSyncSettingTab.titleRemoteConfigCheckFailed"), - } - )) == "no" - ) { - return; - } - } - const isEncryptionFullyEnabled = - !this.editingSettings.encrypt || !this.editingSettings.usePathObfuscation; - if (isEncryptionFullyEnabled) { - if ( - (await this.plugin.confirm.askYesNoDialog( - $msg("obsidianLiveSyncSettingTab.msgEnableEncryptionRecommendation"), - { - defaultOption: "No", - title: $msg("obsidianLiveSyncSettingTab.titleEncryptionNotEnabled"), - } - )) == "no" - ) { - return; - } - } - if (!this.editingSettings.encrypt) { - this.editingSettings.passphrase = ""; - } - if (!(await this.isPassphraseValid())) { - if ( - (await this.plugin.confirm.askYesNoDialog( - $msg("obsidianLiveSyncSettingTab.msgInvalidPassphrase"), - { - defaultOption: "No", - title: $msg("obsidianLiveSyncSettingTab.titleEncryptionPassphraseInvalid"), - } - )) == "no" - ) { - return; - } - } - if (isCloudantURI(this.editingSettings.couchDB_URI)) { - this.editingSettings = { ...this.editingSettings, ...PREFERRED_SETTING_CLOUDANT }; - } else if (this.editingSettings.remoteType == REMOTE_MINIO) { - this.editingSettings = { ...this.editingSettings, ...PREFERRED_JOURNAL_SYNC }; - } else { - this.editingSettings = { ...this.editingSettings, ...PREFERRED_SETTING_SELF_HOSTED }; - } - if ( - (await this.plugin.confirm.askYesNoDialog( - $msg("obsidianLiveSyncSettingTab.msgFetchConfigFromRemote"), - { defaultOption: "Yes", title: $msg("obsidianLiveSyncSettingTab.titleFetchConfig") } - )) == "yes" - ) { - const trialSetting = { ...this.initialSettings, ...this.editingSettings }; - const newTweaks = await this.services.tweakValue.checkAndAskUseRemoteConfiguration(trialSetting); - if (newTweaks.result !== false) { - this.editingSettings = { ...this.editingSettings, ...newTweaks.result }; - this.requestUpdate(); - } else { - // Messages should be already shown. - } - } - this.changeDisplay("30"); + .autoWireDropDown("remoteType", { + holdValue: true, + options: remoteNameMap, + onUpdate: this.enableOnlySyncDisabled, }) - ); + .addApplyButton(["remoteType"]); + }); + + // new Setting(paneEl) + // .setDesc("Generate ES256 Keypair for testing") + // .addButton((button) => + // button.setButtonText("Generate").onClick(async () => { + // const crypto = await getWebCrypto(); + // const keyPair = await crypto.subtle.generateKey({ name: "ECDSA", namedCurve: "P-256" }, true, [ + // "sign", + // "verify", + // ]); + // const pubKey = await crypto.subtle.exportKey("spki", keyPair.publicKey); + // const privateKey = await crypto.subtle.exportKey("pkcs8", keyPair.privateKey); + // const encodedPublicKey = await arrayBufferToBase64Single(pubKey); + // const encodedPrivateKey = await arrayBufferToBase64Single(privateKey); + + // const privateKeyPem = `> -----BEGIN PRIVATE KEY-----\n> ${encodedPrivateKey}\n> -----END PRIVATE KEY-----`; + // const publicKeyPem = `> -----BEGIN PUBLIC KEY-----\\n${encodedPublicKey}\\n-----END PUBLIC KEY-----`; + + // const title = $msg("Setting.GenerateKeyPair.Title"); + // const msg = $msg("Setting.GenerateKeyPair.Desc", { + // public_key: publicKeyPem, + // private_key: privateKeyPem, + // }); + // await MarkdownRenderer.render( + // this.plugin.app, + // "## " + title + "\n\n" + msg, + // generatedKeyDivEl, + // "/", + // this.plugin + // ); + // }) + // ) + // .addOnUpdate( + // combineOnUpdate( + // this.enableOnlySyncDisabled, + // visibleOnly(() => this.editingSettings.useJWT) + // ) + // ); + + void addPanel(paneEl, $msg("obsidianLiveSyncSettingTab.titleNotification"), () => {}).then((paneEl) => { + paneEl.addClass("wizardHidden"); + new Setting(paneEl).autoWireNumeric("notifyThresholdOfRemoteStorageSize", {}).setClass("wizardHidden"); + }); + + // new Setting(paneEl).setClass("wizardOnly").addButton((button) => + // button + // .setButtonText($msg("obsidianLiveSyncSettingTab.buttonNext")) + // .setCta() + // .setDisabled(false) + // .onClick(async () => { + // if (!(await checkConfig(checkResultDiv))) { + // if ( + // (await this.plugin.confirm.askYesNoDialog( + // $msg("obsidianLiveSyncSettingTab.msgConfigCheckFailed"), + // { + // defaultOption: "No", + // title: $msg("obsidianLiveSyncSettingTab.titleRemoteConfigCheckFailed"), + // } + // )) == "no" + // ) { + // return; + // } + // } + // const isEncryptionFullyEnabled = + // !this.editingSettings.encrypt || !this.editingSettings.usePathObfuscation; + // if (isEncryptionFullyEnabled) { + // if ( + // (await this.plugin.confirm.askYesNoDialog( + // $msg("obsidianLiveSyncSettingTab.msgEnableEncryptionRecommendation"), + // { + // defaultOption: "No", + // title: $msg("obsidianLiveSyncSettingTab.titleEncryptionNotEnabled"), + // } + // )) == "no" + // ) { + // return; + // } + // } + // if (!this.editingSettings.encrypt) { + // this.editingSettings.passphrase = ""; + // } + // if (!(await this.isPassphraseValid())) { + // if ( + // (await this.plugin.confirm.askYesNoDialog( + // $msg("obsidianLiveSyncSettingTab.msgInvalidPassphrase"), + // { + // defaultOption: "No", + // title: $msg("obsidianLiveSyncSettingTab.titleEncryptionPassphraseInvalid"), + // } + // )) == "no" + // ) { + // return; + // } + // } + // if (isCloudantURI(this.editingSettings.couchDB_URI)) { + // this.editingSettings = { ...this.editingSettings, ...PREFERRED_SETTING_CLOUDANT }; + // } else if (this.editingSettings.remoteType == REMOTE_MINIO) { + // this.editingSettings = { ...this.editingSettings, ...PREFERRED_JOURNAL_SYNC }; + // } else { + // this.editingSettings = { ...this.editingSettings, ...PREFERRED_SETTING_SELF_HOSTED }; + // } + // if ( + // (await this.plugin.confirm.askYesNoDialog( + // $msg("obsidianLiveSyncSettingTab.msgFetchConfigFromRemote"), + // { defaultOption: "Yes", title: $msg("obsidianLiveSyncSettingTab.titleFetchConfig") } + // )) == "yes" + // ) { + // const trialSetting = { ...this.initialSettings, ...this.editingSettings }; + // const newTweaks = await this.services.tweakValue.checkAndAskUseRemoteConfiguration(trialSetting); + // if (newTweaks.result !== false) { + // this.editingSettings = { ...this.editingSettings, ...newTweaks.result }; + // this.requestUpdate(); + // } else { + // // Messages should be already shown. + // } + // } + // this.changeDisplay("30"); + // }) + // ); } diff --git a/src/modules/features/SettingDialogue/PaneSetup.ts b/src/modules/features/SettingDialogue/PaneSetup.ts index eade8c6..ade3937 100644 --- a/src/modules/features/SettingDialogue/PaneSetup.ts +++ b/src/modules/features/SettingDialogue/PaneSetup.ts @@ -13,6 +13,7 @@ import type { PageFunctions } from "./SettingPane.ts"; import { visibleOnly } from "./SettingPane.ts"; import { DEFAULT_SETTINGS } from "../../../lib/src/common/types.ts"; import { request } from "obsidian"; +import { SetupManager, UserMode } from "../ModuleSetupObsidian.ts"; export function paneSetup( this: ObsidianLiveSyncSettingTab, paneEl: HTMLElement, @@ -30,11 +31,13 @@ export function paneSetup( }); new Setting(paneEl) - .setName($msg("obsidianLiveSyncSettingTab.nameManualSetup")) - .setDesc($msg("obsidianLiveSyncSettingTab.descManualSetup")) + .setName("Rerun Onboarding Wizard") + .setDesc("Rerun the onboarding wizard to set up Self-hosted LiveSync again.") .addButton((text) => { - text.setButtonText($msg("obsidianLiveSyncSettingTab.btnStart")).onClick(async () => { - await this.enableMinimalSetup(); + text.setButtonText("Rerun Wizard").onClick(async () => { + const setupManager = this.plugin.getModule(SetupManager); + await setupManager.onBoard(UserMode.ExistingUser); + // await this.plugin.moduleSetupObsidian.onBoardingWizard(true); }); }); diff --git a/src/modules/features/SettingDialogue/SveltePanel.ts b/src/modules/features/SettingDialogue/SveltePanel.ts new file mode 100644 index 0000000..9dc13a1 --- /dev/null +++ b/src/modules/features/SettingDialogue/SveltePanel.ts @@ -0,0 +1,54 @@ +import { mount, type Component, unmount } from "svelte"; +import { type Writable, writable, get } from "svelte/store"; + +/** + * Props passed to Svelte panels, containing a writable port + * to communicate with the panel + */ +export type SveltePanelProps = { + port: Writable; +}; + +/** + * A class to manage a Svelte panel within Obsidian + * Especially useful for settings panels + */ +export class SveltePanel { + private _mountedComponent: ReturnType; + private _componentValue = writable(undefined); + /** + * Creates a Svelte panel instance + * @param component Component to mount + * @param mountTo HTMLElement to mount the component to + * @param valueStore Optional writable store to bind to the component's port, if not provided a new one will be created + * @returns The SveltePanel instance + */ + constructor(component: Component>, mountTo: HTMLElement, valueStore?: Writable) { + this._componentValue = valueStore ?? writable(undefined); + this._mountedComponent = mount(component, { + target: mountTo, + props: { + port: this._componentValue, + }, + }); + return this; + } + /** + * Destroys the Svelte panel instance by unmounting the component + */ + destroy() { + if (this._mountedComponent) { + void unmount(this._mountedComponent); + } + } + + /** + * Gets or sets the current value of the component's port + */ + get componentValue() { + return get(this._componentValue); + } + set componentValue(value: T | undefined) { + this._componentValue.set(value); + } +} diff --git a/src/modules/features/SettingDialogue/settingUtils.ts b/src/modules/features/SettingDialogue/settingUtils.ts new file mode 100644 index 0000000..99afea5 --- /dev/null +++ b/src/modules/features/SettingDialogue/settingUtils.ts @@ -0,0 +1,78 @@ +import { escapeStringToHTML } from "octagonal-wheels/string"; +import { E2EEAlgorithmNames, type ObsidianLiveSyncSettings } from "../../../lib/src/common/types"; +import { + pickCouchDBSyncSettings, + pickBucketSyncSettings, + pickP2PSyncSettings, + pickEncryptionSettings, +} from "../../../lib/src/common/utils"; +import { getConfig, type AllSettingItemKey } from "./settingConstants"; + +/** + * Generates a summary of P2P configuration settings + * @param setting Settings object + * @param additional Additional summary information to include + * @param showAdvanced Whether to include advanced settings + * @returns Summary object + */ +export function getP2PConfigSummary( + setting: ObsidianLiveSyncSettings, + additional: Record = {}, + showAdvanced = false +) { + const settingTable: Partial = pickP2PSyncSettings(setting); + return { ...getSummaryFromPartialSettings({ ...settingTable }, showAdvanced), ...additional }; +} +/** + * Generates a summary of Object Storage configuration settings + * @param setting Settings object + * @param showAdvanced Whether to include advanced settings + * @returns Summary object + */ +export function getBucketConfigSummary(setting: ObsidianLiveSyncSettings, showAdvanced = false) { + const settingTable: Partial = pickBucketSyncSettings(setting); + return getSummaryFromPartialSettings(settingTable, showAdvanced); +} +/** + * Generates a summary of CouchDB configuration settings + * @param setting Settings object + * @param showAdvanced Whether to include advanced settings + * @returns Summary object + */ +export function getCouchDBConfigSummary(setting: ObsidianLiveSyncSettings, showAdvanced = false) { + const settingTable: Partial = pickCouchDBSyncSettings(setting); + return getSummaryFromPartialSettings(settingTable, showAdvanced); +} + +/** + * Generates a summary of E2EE configuration settings + * @param setting Settings object + * @param showAdvanced Whether to include advanced settings + * @returns Summary object + */ +export function getE2EEConfigSummary(setting: ObsidianLiveSyncSettings, showAdvanced = false) { + const settingTable: Partial = pickEncryptionSettings(setting); + return getSummaryFromPartialSettings(settingTable, showAdvanced); +} + +/** + * Converts partial settings into a summary object + * @param setting Partial settings object + * @param showAdvanced Whether to include advanced settings + * @returns Summary object + */ +export function getSummaryFromPartialSettings(setting: Partial, showAdvanced = false) { + const outputSummary: Record = {}; + for (const key of Object.keys(setting) as (keyof ObsidianLiveSyncSettings)[]) { + const config = getConfig(key as AllSettingItemKey); + if (!config) continue; + if (config.isAdvanced && !showAdvanced) continue; + const value = + key != "E2EEAlgorithm" + ? `${setting[key]}` + : E2EEAlgorithmNames[`${setting[key]}` as keyof typeof E2EEAlgorithmNames]; + const displayValue = config.isHidden ? "•".repeat(value.length) : escapeStringToHTML(value); + outputSummary[config.name] = displayValue; + } + return outputSummary; +} diff --git a/src/modules/features/SettingDialogue/utilFixCouchDBSetting.ts b/src/modules/features/SettingDialogue/utilFixCouchDBSetting.ts new file mode 100644 index 0000000..041c923 --- /dev/null +++ b/src/modules/features/SettingDialogue/utilFixCouchDBSetting.ts @@ -0,0 +1,274 @@ +import { requestToCouchDBWithCredentials } from "../../../common/utils"; +import { $msg } from "../../../lib/src/common/i18n"; +import { LOG_LEVEL_INFO, LOG_LEVEL_NOTICE, LOG_LEVEL_VERBOSE, Logger } from "../../../lib/src/common/logger"; +import type { ObsidianLiveSyncSettings } from "../../../lib/src/common/types"; +import { fireAndForget, parseHeaderValues } from "../../../lib/src/common/utils"; +import { isCloudantURI } from "../../../lib/src/pouchdb/utils_couchdb"; +import { generateCredentialObject } from "../../../lib/src/replication/httplib"; + +export const checkConfig = async ( + checkResultDiv: HTMLDivElement | undefined, + editingSettings: ObsidianLiveSyncSettings +) => { + Logger($msg("obsidianLiveSyncSettingTab.logCheckingDbConfig"), LOG_LEVEL_INFO); + let isSuccessful = true; + const emptyDiv = createDiv(); + emptyDiv.innerHTML = ""; + checkResultDiv?.replaceChildren(...[emptyDiv]); + const addResult = (msg: string, classes?: string[]) => { + const tmpDiv = createDiv(); + tmpDiv.addClass("ob-btn-config-fix"); + if (classes) { + tmpDiv.addClasses(classes); + } + tmpDiv.innerHTML = `${msg}`; + checkResultDiv?.appendChild(tmpDiv); + }; + try { + if (isCloudantURI(editingSettings.couchDB_URI)) { + Logger($msg("obsidianLiveSyncSettingTab.logCannotUseCloudant"), LOG_LEVEL_NOTICE); + return; + } + // Tip: Add log for cloudant as Logger($msg("obsidianLiveSyncSettingTab.logServerConfigurationCheck")); + const customHeaders = parseHeaderValues(editingSettings.couchDB_CustomHeaders); + const credential = generateCredentialObject(editingSettings); + const r = await requestToCouchDBWithCredentials( + editingSettings.couchDB_URI, + credential, + window.origin, + undefined, + undefined, + undefined, + customHeaders + ); + const responseConfig = r.json; + + const addConfigFixButton = (title: string, key: string, value: string) => { + if (!checkResultDiv) return; + const tmpDiv = createDiv(); + tmpDiv.addClass("ob-btn-config-fix"); + tmpDiv.innerHTML = ``; + const x = checkResultDiv.appendChild(tmpDiv); + x.querySelector("button")?.addEventListener("click", () => { + fireAndForget(async () => { + Logger($msg("obsidianLiveSyncSettingTab.logCouchDbConfigSet", { title, key, value })); + const res = await requestToCouchDBWithCredentials( + editingSettings.couchDB_URI, + credential, + undefined, + key, + value, + undefined, + customHeaders + ); + if (res.status == 200) { + Logger($msg("obsidianLiveSyncSettingTab.logCouchDbConfigUpdated", { title }), LOG_LEVEL_NOTICE); + checkResultDiv.removeChild(x); + await checkConfig(checkResultDiv, editingSettings); + } else { + Logger($msg("obsidianLiveSyncSettingTab.logCouchDbConfigFail", { title }), LOG_LEVEL_NOTICE); + Logger(res.text, LOG_LEVEL_VERBOSE); + } + }); + }); + }; + addResult($msg("obsidianLiveSyncSettingTab.msgNotice"), ["ob-btn-config-head"]); + addResult($msg("obsidianLiveSyncSettingTab.msgIfConfigNotPersistent"), ["ob-btn-config-info"]); + addResult($msg("obsidianLiveSyncSettingTab.msgConfigCheck"), ["ob-btn-config-head"]); + + const serverBanner = r.headers["server"] ?? r.headers["Server"] ?? "unknown"; + addResult($msg("obsidianLiveSyncSettingTab.serverVersion", { info: serverBanner })); + const versionMatch = serverBanner.match(/CouchDB(\/([0-9.]+))?/); + const versionStr = versionMatch ? versionMatch[2] : "0.0.0"; + const versionParts = `${versionStr}.0.0.0`.split("."); + // Compare version string with the target version. + // version must be a string like "3.2.1" or "3.10.2", and must be two or three parts. + function isGreaterThanOrEqual(version: string) { + const targetParts = version.split("."); + for (let i = 0; i < targetParts.length; i++) { + // compare as number if possible (so 3.10 > 3.2, 3.10.1b > 3.10.1a) + const result = versionParts[i].localeCompare(targetParts[i], undefined, { numeric: true }); + if (result > 0) return true; + if (result < 0) return false; + } + return true; + } + // Admin check + // for database creation and deletion + if (!(editingSettings.couchDB_USER in responseConfig.admins)) { + addResult($msg("obsidianLiveSyncSettingTab.warnNoAdmin")); + } else { + addResult($msg("obsidianLiveSyncSettingTab.okAdminPrivileges")); + } + if (isGreaterThanOrEqual("3.2.0")) { + // HTTP user-authorization check + if (responseConfig?.chttpd?.require_valid_user != "true") { + isSuccessful = false; + addResult($msg("obsidianLiveSyncSettingTab.errRequireValidUser")); + addConfigFixButton( + $msg("obsidianLiveSyncSettingTab.msgSetRequireValidUser"), + "chttpd/require_valid_user", + "true" + ); + } else { + addResult($msg("obsidianLiveSyncSettingTab.okRequireValidUser")); + } + } else { + if (responseConfig?.chttpd_auth?.require_valid_user != "true") { + isSuccessful = false; + addResult($msg("obsidianLiveSyncSettingTab.errRequireValidUserAuth")); + addConfigFixButton( + $msg("obsidianLiveSyncSettingTab.msgSetRequireValidUserAuth"), + "chttpd_auth/require_valid_user", + "true" + ); + } else { + addResult($msg("obsidianLiveSyncSettingTab.okRequireValidUserAuth")); + } + } + // HTTPD check + // Check Authentication header + if (!responseConfig?.httpd["WWW-Authenticate"]) { + isSuccessful = false; + addResult($msg("obsidianLiveSyncSettingTab.errMissingWwwAuth")); + addConfigFixButton( + $msg("obsidianLiveSyncSettingTab.msgSetWwwAuth"), + "httpd/WWW-Authenticate", + 'Basic realm="couchdb"' + ); + } else { + addResult($msg("obsidianLiveSyncSettingTab.okWwwAuth")); + } + if (isGreaterThanOrEqual("3.2.0")) { + if (responseConfig?.chttpd?.enable_cors != "true") { + isSuccessful = false; + addResult($msg("obsidianLiveSyncSettingTab.errEnableCorsChttpd")); + addConfigFixButton( + $msg("obsidianLiveSyncSettingTab.msgEnableCorsChttpd"), + "chttpd/enable_cors", + "true" + ); + } else { + addResult($msg("obsidianLiveSyncSettingTab.okEnableCorsChttpd")); + } + } else { + if (responseConfig?.httpd?.enable_cors != "true") { + isSuccessful = false; + addResult($msg("obsidianLiveSyncSettingTab.errEnableCors")); + addConfigFixButton($msg("obsidianLiveSyncSettingTab.msgEnableCors"), "httpd/enable_cors", "true"); + } else { + addResult($msg("obsidianLiveSyncSettingTab.okEnableCors")); + } + } + // If the server is not cloudant, configure request size + if (!isCloudantURI(editingSettings.couchDB_URI)) { + // REQUEST SIZE + if (Number(responseConfig?.chttpd?.max_http_request_size ?? 0) < 4294967296) { + isSuccessful = false; + addResult($msg("obsidianLiveSyncSettingTab.errMaxRequestSize")); + addConfigFixButton( + $msg("obsidianLiveSyncSettingTab.msgSetMaxRequestSize"), + "chttpd/max_http_request_size", + "4294967296" + ); + } else { + addResult($msg("obsidianLiveSyncSettingTab.okMaxRequestSize")); + } + if (Number(responseConfig?.couchdb?.max_document_size ?? 0) < 50000000) { + isSuccessful = false; + addResult($msg("obsidianLiveSyncSettingTab.errMaxDocumentSize")); + addConfigFixButton( + $msg("obsidianLiveSyncSettingTab.msgSetMaxDocSize"), + "couchdb/max_document_size", + "50000000" + ); + } else { + addResult($msg("obsidianLiveSyncSettingTab.okMaxDocumentSize")); + } + } + // CORS check + // checking connectivity for mobile + if (responseConfig?.cors?.credentials != "true") { + isSuccessful = false; + addResult($msg("obsidianLiveSyncSettingTab.errCorsCredentials")); + addConfigFixButton($msg("obsidianLiveSyncSettingTab.msgSetCorsCredentials"), "cors/credentials", "true"); + } else { + addResult($msg("obsidianLiveSyncSettingTab.okCorsCredentials")); + } + const ConfiguredOrigins = ((responseConfig?.cors?.origins ?? "") + "").split(","); + if ( + responseConfig?.cors?.origins == "*" || + (ConfiguredOrigins.indexOf("app://obsidian.md") !== -1 && + ConfiguredOrigins.indexOf("capacitor://localhost") !== -1 && + ConfiguredOrigins.indexOf("http://localhost") !== -1) + ) { + addResult($msg("obsidianLiveSyncSettingTab.okCorsOrigins")); + } else { + const fixedValue = [ + ...new Set([ + ...ConfiguredOrigins.map((e) => e.trim()), + "app://obsidian.md", + "capacitor://localhost", + "http://localhost", + ]), + ].join(","); + addResult($msg("obsidianLiveSyncSettingTab.errCorsOrigins")); + addConfigFixButton($msg("obsidianLiveSyncSettingTab.msgSetCorsOrigins"), "cors/origins", fixedValue); + isSuccessful = false; + } + addResult($msg("obsidianLiveSyncSettingTab.msgConnectionCheck"), ["ob-btn-config-head"]); + addResult($msg("obsidianLiveSyncSettingTab.msgCurrentOrigin", { origin: window.location.origin })); + + // Request header check + const origins = ["app://obsidian.md", "capacitor://localhost", "http://localhost"]; + for (const org of origins) { + const rr = await requestToCouchDBWithCredentials( + editingSettings.couchDB_URI, + credential, + org, + undefined, + undefined, + undefined, + customHeaders + ); + const responseHeaders = Object.fromEntries( + Object.entries(rr.headers).map((e) => { + e[0] = `${e[0]}`.toLowerCase(); + return e; + }) + ); + addResult($msg("obsidianLiveSyncSettingTab.msgOriginCheck", { org })); + if (responseHeaders["access-control-allow-credentials"] != "true") { + addResult($msg("obsidianLiveSyncSettingTab.errCorsNotAllowingCredentials")); + isSuccessful = false; + } else { + addResult($msg("obsidianLiveSyncSettingTab.okCorsCredentialsForOrigin")); + } + if (responseHeaders["access-control-allow-origin"] != org) { + addResult( + $msg("obsidianLiveSyncSettingTab.warnCorsOriginUnmatched", { + from: origin, + to: responseHeaders["access-control-allow-origin"], + }) + ); + } else { + addResult($msg("obsidianLiveSyncSettingTab.okCorsOriginMatched")); + } + } + addResult($msg("obsidianLiveSyncSettingTab.msgDone"), ["ob-btn-config-head"]); + addResult($msg("obsidianLiveSyncSettingTab.msgConnectionProxyNote"), ["ob-btn-config-info"]); + Logger($msg("obsidianLiveSyncSettingTab.logCheckingConfigDone"), LOG_LEVEL_INFO); + } catch (ex: any) { + if (ex?.status == 401) { + isSuccessful = false; + addResult($msg("obsidianLiveSyncSettingTab.errAccessForbidden")); + addResult($msg("obsidianLiveSyncSettingTab.errCannotContinueTest")); + Logger($msg("obsidianLiveSyncSettingTab.logCheckingConfigDone"), LOG_LEVEL_INFO); + } else { + Logger($msg("obsidianLiveSyncSettingTab.logCheckingConfigFailed"), LOG_LEVEL_NOTICE); + Logger(ex); + isSuccessful = false; + } + } + return isSuccessful; +}; diff --git a/src/modules/features/SetupWizard/ObsidianSvelteDialog.ts b/src/modules/features/SetupWizard/ObsidianSvelteDialog.ts new file mode 100644 index 0000000..51e57ad --- /dev/null +++ b/src/modules/features/SetupWizard/ObsidianSvelteDialog.ts @@ -0,0 +1,141 @@ +import { eventHub, EVENT_PLUGIN_UNLOADED } from "@/common/events"; +import { Modal } from "@/deps"; +import type ObsidianLiveSyncPlugin from "@/main"; +import { mount, unmount } from "svelte"; +import DialogHost from "@lib/UI/DialogHost.svelte"; +import { fireAndForget, promiseWithResolvers, type PromiseWithResolvers } from "octagonal-wheels/promises"; +import { LOG_LEVEL_NOTICE, Logger } from "octagonal-wheels/common/logger"; +import { + type DialogControlBase, + type DialogSvelteComponentBaseProps, + type ComponentHasResult, + setupDialogContext, + getDialogContext, + type SvelteDialogManagerBase, +} from "@/lib/src/UI/svelteDialog.ts"; + +export type DialogSvelteComponentProps = DialogSvelteComponentBaseProps & { + plugin: ObsidianLiveSyncPlugin; + services: ObsidianLiveSyncPlugin["services"]; +}; + +export type DialogControls = DialogControlBase & { + plugin: ObsidianLiveSyncPlugin; + services: ObsidianLiveSyncPlugin["services"]; +}; + +export type DialogMessageProps = Record; +// type DialogSvelteComponent = Component,any>; + +export class SvelteDialog extends Modal { + plugin: ObsidianLiveSyncPlugin; + mountedComponent?: ReturnType; + component: ComponentHasResult; + result?: T; + initialData?: U; + title: string = "Obsidian LiveSync - Setup Wizard"; + constructor(plugin: ObsidianLiveSyncPlugin, component: ComponentHasResult, initialData?: U) { + super(plugin.app); + this.plugin = plugin; + this.component = component; + this.initialData = initialData; + } + resolveResult() { + this.resultPromiseWithResolvers?.resolve(this.result); + this.resultPromiseWithResolvers = undefined; + } + resultPromiseWithResolvers?: PromiseWithResolvers; + onOpen() { + const { contentEl } = this; + contentEl.empty(); + // eslint-disable-next-line @typescript-eslint/no-this-alias + const dialog = this; + + if (this.resultPromiseWithResolvers) { + this.resultPromiseWithResolvers.reject("Dialog opened again"); + } + const pr = promiseWithResolvers(); + eventHub.once(EVENT_PLUGIN_UNLOADED, () => { + if (this.resultPromiseWithResolvers === pr) { + pr.reject("Plugin unloaded"); + this.close(); + } + }); + this.resultPromiseWithResolvers = pr; + this.mountedComponent = mount(DialogHost, { + target: contentEl, + props: { + onSetupContext: (props: DialogSvelteComponentBaseProps) => { + setupDialogContext({ + ...props, + plugin: this.plugin, + services: this.plugin.services, + }); + }, + setTitle: (title: string) => { + dialog.setTitle(title); + }, + closeDialog: () => { + dialog.close(); + }, + setResult: (result: T) => { + this.result = result; + }, + getInitialData: () => this.initialData, + mountComponent: this.component, + }, + }); + } + waitForClose(): Promise { + if (!this.resultPromiseWithResolvers) { + throw new Error("Dialog not opened yet"); + } + return this.resultPromiseWithResolvers.promise; + } + onClose() { + this.resolveResult(); + fireAndForget(async () => { + if (this.mountedComponent) { + await unmount(this.mountedComponent); + } + }); + } +} + +export async function openSvelteDialog( + plugin: ObsidianLiveSyncPlugin, + component: ComponentHasResult, + initialData?: U +): Promise { + const dialog = new SvelteDialog(plugin, component, initialData); + dialog.open(); + + return await dialog.waitForClose(); +} + +export class SvelteDialogManager implements SvelteDialogManagerBase { + plugin: ObsidianLiveSyncPlugin; + constructor(plugin: ObsidianLiveSyncPlugin) { + this.plugin = plugin; + } + async open(component: ComponentHasResult, initialData?: U): Promise { + return await openSvelteDialog(this.plugin, component, initialData); + } + async openWithExplicitCancel(component: ComponentHasResult, initialData?: U): Promise { + for (let i = 0; i < 10; i++) { + const ret = await openSvelteDialog(this.plugin, component, initialData); + if (ret !== undefined) { + return ret; + } + if (this.plugin.services.appLifecycle.hasUnloaded()) { + throw new Error("Operation cancelled due to app shutdown."); + } + Logger("Please select 'Cancel' explicitly to cancel this operation.", LOG_LEVEL_NOTICE); + } + throw new Error("Operation Forcibly cancelled by user."); + } +} + +export function getObsidianDialogContext(): DialogControls { + return getDialogContext() as DialogControls; +} diff --git a/src/modules/features/SetupWizard/dialogs/FetchEverything.svelte b/src/modules/features/SetupWizard/dialogs/FetchEverything.svelte new file mode 100644 index 0000000..e704782 --- /dev/null +++ b/src/modules/features/SetupWizard/dialogs/FetchEverything.svelte @@ -0,0 +1,154 @@ + + + +This will rebuild the local database on this device using the most recent data from the server. This action is + designed to resolve synchronisation inconsistencies and restore correct functionality. + + If you have unsynchronised changes in your Vault on this device, they will likely diverge from the server's + versions after the reset. This may result in a large number of file conflicts.
+ Furthermore, if conflicts are already present in the server data, they will be synchronised to this device as they are, + and you will need to resolve them locally. +
+
+ + To minimise the creation of new conflicts, please select the option that best describes the + current state of your Vault. The application will then check your files in the most appropriate way based on + your selection. + + + + + + +
+ + Have you created a backup before proceeding? + + We recommend that you copy your Vault folder to a safe location. This will provide a safeguard in case a large + number of conflicts arise, or if you accidentally synchronise with an incorrect destination. + + + + + + + + + + + + commit()} /> + setResult(TYPE_CANCEL)} /> + diff --git a/src/modules/features/SetupWizard/dialogs/Intro.svelte b/src/modules/features/SetupWizard/dialogs/Intro.svelte new file mode 100644 index 0000000..a1f90de --- /dev/null +++ b/src/modules/features/SetupWizard/dialogs/Intro.svelte @@ -0,0 +1,55 @@ + + + +We will now guide you through a few questions to simplify the synchronisation setup. + + First, please select the option that best describes your current situation. + + + + + + + setResult(userType)} /> + setResult(TYPE_CANCELLED)} /> + diff --git a/src/modules/features/SetupWizard/dialogs/OutroAskUserMode.svelte b/src/modules/features/SetupWizard/dialogs/OutroAskUserMode.svelte new file mode 100644 index 0000000..217e142 --- /dev/null +++ b/src/modules/features/SetupWizard/dialogs/OutroAskUserMode.svelte @@ -0,0 +1,75 @@ + + + + + The connection to the server has been configured successfully. As the next step, the local database, that is to say the synchronisation information, must be reconstituted. + + + Please select your situation. + + + + + + setResult(userType)} /> + setResult(TYPE_CANCELLED)} /> + diff --git a/src/modules/features/SetupWizard/dialogs/OutroExistingUser.svelte b/src/modules/features/SetupWizard/dialogs/OutroExistingUser.svelte new file mode 100644 index 0000000..ef9f5ac --- /dev/null +++ b/src/modules/features/SetupWizard/dialogs/OutroExistingUser.svelte @@ -0,0 +1,37 @@ + + + + +

+ The connection to the server has been configured successfully. As the next step, the latest synchronisation data will be downloaded from the server to this device. +

+

+ PLEASE NOTE +
+ After restarting, the database on this device will be rebuilt using data from the server. If there are any unsynchronised + files in this vault, conflicts may occur with the server data. +

+
+ + Please select the button below to restart and proceed to the data fetching confirmation. + + + setResult(TYPE_APPLY)} /> + setResult(TYPE_CANCELLED)} /> + diff --git a/src/modules/features/SetupWizard/dialogs/OutroNewUser.svelte b/src/modules/features/SetupWizard/dialogs/OutroNewUser.svelte new file mode 100644 index 0000000..ff39c62 --- /dev/null +++ b/src/modules/features/SetupWizard/dialogs/OutroNewUser.svelte @@ -0,0 +1,38 @@ + + + + +

+ The connection to the server has been configured successfully. As the next step, the synchronisation data on the server will be built based on the current data on this device. +

+

+ IMPORTANT +
+ After restarting, the data on this device will be uploaded to the server as the 'master copy'. Please be aware that + any unintended data currently on the server will be completely overwritten. +

+
+ + Please select the button below to restart and proceed to the final confirmation. + + + setResult(TYPE_APPLY)} /> + setResult(TYPE_CANCELLED)} /> + diff --git a/src/modules/features/SetupWizard/dialogs/PanelCouchDBCheck.svelte b/src/modules/features/SetupWizard/dialogs/PanelCouchDBCheck.svelte new file mode 100644 index 0000000..d2cef32 --- /dev/null +++ b/src/modules/features/SetupWizard/dialogs/PanelCouchDBCheck.svelte @@ -0,0 +1,141 @@ + + +{#snippet result(issue: ConfigCheckResult)} +
+
+ {issue.message} +
+ {#if isFixableError(issue)} +
+ +
+ {/if} +
+{/snippet} + + + +
+
+ + {#if detectedIssues.length === 0} + No checks have been performed yet. + {:else if isAllSuccess} + All checks passed successfully! + {:else} + {errorIssueCount} issue(s) detected! + {/if} + + {#if detectedIssues.length > 0} +

Issue detection log:

+ {#each detectedIssues as issue} + {@render result(issue)} + {/each} + {/if} +
+
+ + diff --git a/src/modules/features/SetupWizard/dialogs/RebuildEverything.svelte b/src/modules/features/SetupWizard/dialogs/RebuildEverything.svelte new file mode 100644 index 0000000..93aa834 --- /dev/null +++ b/src/modules/features/SetupWizard/dialogs/RebuildEverything.svelte @@ -0,0 +1,126 @@ + + + +This procedure will first delete all existing synchronisation data from the server. Following this, the server data + will be completely rebuilt, using the current state of your Vault on this device (including its local database) as + the single, authoritative master copy. + + You should perform this operation only in exceptional circumstances, such as when the server data is completely + corrupted, when changes on all other devices are no longer needed, or when the database size has become unusually + large in comparison to the Vault size. + + + + There is a way to resolve this on other devices. + Of course, we can back up the data before proceeding. + + + by resetting the remote, you will be informed on other devices. + + + +
+ + Have you created a backup before proceeding? + + This is an extremely powerful operation. We strongly recommend that you copy your Vault folder to a safe + location. + + + + + + + + + + + + commit()} /> + setResult(TYPE_CANCEL)} /> + diff --git a/src/modules/features/SetupWizard/dialogs/ScanQRCode.svelte b/src/modules/features/SetupWizard/dialogs/ScanQRCode.svelte new file mode 100644 index 0000000..58ad125 --- /dev/null +++ b/src/modules/features/SetupWizard/dialogs/ScanQRCode.svelte @@ -0,0 +1,28 @@ + + + +Please follow the steps below to import settings from your existing device. + + +
    +
  1. On this device, please keep this Vault open.
  2. +
  3. On the source device, open Obsidian.
  4. +
  5. On the source device, from the command palette, run the 'Show settings as a QR code' command.
  6. +
  7. On this device, switch to the camera app or use a QR code scanner to scan the displayed QR code.
  8. +
+
+ + setResult(TYPE_CLOSE)} /> + diff --git a/src/modules/features/SetupWizard/dialogs/SelectMethodExisting.svelte b/src/modules/features/SetupWizard/dialogs/SelectMethodExisting.svelte new file mode 100644 index 0000000..b339d3e --- /dev/null +++ b/src/modules/features/SetupWizard/dialogs/SelectMethodExisting.svelte @@ -0,0 +1,62 @@ + + + +You are adding this device to an existing synchronisation setup. + + Please select a method to import the settings from another device. + + + + + + + + setResult(userType)} /> + setResult(TYPE_CANCELLED)} /> + diff --git a/src/modules/features/SetupWizard/dialogs/SelectMethodNewUser.svelte b/src/modules/features/SetupWizard/dialogs/SelectMethodNewUser.svelte new file mode 100644 index 0000000..2478521 --- /dev/null +++ b/src/modules/features/SetupWizard/dialogs/SelectMethodNewUser.svelte @@ -0,0 +1,57 @@ + + + +We will now proceed with the server configuration. + + How would you like to configure the connection to your server? + + + + + + + setResult(userType)} /> + setResult(TYPE_CANCELLED)} /> + diff --git a/src/modules/features/SetupWizard/dialogs/SetupRemote.svelte b/src/modules/features/SetupWizard/dialogs/SetupRemote.svelte new file mode 100644 index 0000000..74b809b --- /dev/null +++ b/src/modules/features/SetupWizard/dialogs/SetupRemote.svelte @@ -0,0 +1,56 @@ + + + + + Please select the type of server to which you are connecting. + + + + + + + + setResult(userType)} /> + setResult(TYPE_CANCELLED)} /> + diff --git a/src/modules/features/SetupWizard/dialogs/SetupRemoteBucket.svelte b/src/modules/features/SetupWizard/dialogs/SetupRemoteBucket.svelte new file mode 100644 index 0000000..d4f905b --- /dev/null +++ b/src/modules/features/SetupWizard/dialogs/SetupRemoteBucket.svelte @@ -0,0 +1,241 @@ + + + +Please enter the details required to connect to your S3/MinIO/R2 compatible object storage service. + + + +We can use only Secure (HTTPS) connections on Obsidian Mobile. + + + + + + + + + + + + + + + + + + + + + + If you want to store the data in a specific folder within the bucket, you can specify a folder prefix here. + Otherwise, leave it blank to store data at the root of the bucket. + + + + + + If you cannot avoid CORS issues, you might want to try this option. It uses Obsidian's internal API to communicate + with the S3 server. Not compliant with web standards, but works. Note that this might break in future Obsidian + versions. + + + + + + + + + + {error} + + +{#if processing} + Checking connection... Please wait. +{:else} + + checkAndCommit()} /> + commit()} /> + cancel()} /> + +{/if} diff --git a/src/modules/features/SetupWizard/dialogs/SetupRemoteCouchDB.svelte b/src/modules/features/SetupWizard/dialogs/SetupRemoteCouchDB.svelte new file mode 100644 index 0000000..0710214 --- /dev/null +++ b/src/modules/features/SetupWizard/dialogs/SetupRemoteCouchDB.svelte @@ -0,0 +1,284 @@ + + + +Please enter the CouchDB server information below. + + + +We can use only Secure (HTTPS) connections on Obsidian Mobile. + + + + + + + + + + + + You cannot use capital letters, spaces, or special characters in the database name. And not allowed to start with an + underscore (_). + + + + + + If you cannot avoid CORS issues, you might want to try this option. It uses Obsidian's internal API to communicate + with the CouchDB server. Not compliant with web standards, but works. Note that this might break in future Obsidian + versions. + + + + + + + + + + + + + + + + `${syncSetting.jwtExpDuration}`, (v) => (syncSetting.jwtExpDuration = parseInt(v) || 0)} + disabled={!isUseJWT} + /> + + + + + + + + + + + + JWT (JSON Web Token) authentication allows you to securely authenticate with the CouchDB server using tokens. + Ensure that your CouchDB server is configured to accept JWTs and that the provided key and settings match the + server's configuration. Incidentally, I have not verified it very thoroughly. + + + + +
+ + + {error} + + +{#if processing} + Checking connection... Please wait. +{:else} + + checkAndCommit()} /> + commit()} /> + cancel()} /> + +{/if} diff --git a/src/modules/features/SetupWizard/dialogs/SetupRemoteE2EE.svelte b/src/modules/features/SetupWizard/dialogs/SetupRemoteE2EE.svelte new file mode 100644 index 0000000..052e97d --- /dev/null +++ b/src/modules/features/SetupWizard/dialogs/SetupRemoteE2EE.svelte @@ -0,0 +1,123 @@ + + + +Please configure your end-to-end encryption settings. + + + + + + Enabling end-to-end encryption ensures that your data is encrypted on your device before being sent to the remote + server. This means that even if someone gains access to the server, they won't be able to read your data without the + passphrase. Make sure to remember your passphrase, as it will be required to decrypt your data on other devices. +
+ Also, please note that if you are using Peer-to-Peer synchronization, this configuration will be used when you switch + to other methods and connect to a remote server in the future. +
+ + This setting must be the same even when connecting to multiple synchronisation destinations. + + + + + + + Obfuscating properties (e.g., path of file, size, creation and modification dates) adds an additional layer of + security by making it harder to identify the structure and names of your files and folders on the remote server. + This helps protect your privacy and makes it more difficult for unauthorized users to infer information about your + data. + + + + + + + + In most cases, you should stick with the default algorithm ({E2EEAlgorithmNames[ + DEFAULT_SETTINGS.E2EEAlgorithm + ]}), This setting is only required if you have an existing Vault encrypted in a different format. + + + Changing the encryption algorithm will prevent access to any data previously encrypted with a different + algorithm. Ensure that all your devices are configured to use the same algorithm to maintain access to your + data. + + + + +

+ Please be aware that the End-to-End Encryption passphrase is not validated until the synchronisation process + actually commences. This is a security measure designed to protect your data. +

+

+ Therefore, we ask that you exercise extreme caution when configuring server information manually. If an + incorrect passphrase is entered, the data on the server will become corrupted.

+ Please understand that this is intended behaviour. +

+
+ + + commit()} /> + setResult(TYPE_CANCELLED)} /> + diff --git a/src/modules/features/SetupWizard/dialogs/SetupRemoteP2P.svelte b/src/modules/features/SetupWizard/dialogs/SetupRemoteP2P.svelte new file mode 100644 index 0000000..0467488 --- /dev/null +++ b/src/modules/features/SetupWizard/dialogs/SetupRemoteP2P.svelte @@ -0,0 +1,255 @@ + + + +Please enter the Peer-to-Peer Synchronisation information below. + + + + + + + + + + + + + The Group ID and passphrase are used to identify your group of devices. Make sure to use the same Group ID and + passphrase on all devices you want to synchronise.
+ Note that the Group ID is not limited to the generated format; you can use any string as the Group ID. +
+ + + + + + {error} + +{#if processing} + Checking connection... Please wait. +{:else} + + checkAndCommit()} /> + commit()} /> + cancel()} /> + +{/if} diff --git a/src/modules/features/SetupWizard/dialogs/UseSetupURI.svelte b/src/modules/features/SetupWizard/dialogs/UseSetupURI.svelte new file mode 100644 index 0000000..d6152b7 --- /dev/null +++ b/src/modules/features/SetupWizard/dialogs/UseSetupURI.svelte @@ -0,0 +1,96 @@ + + + +Please enter the Setup URI that was generated during server installation or on another device, along with the vault + passphrase.
+ Note that you can generate a new Setup URI by running the "Copy settings as a new Setup URI" command in the command palette.
+ + + + +The Setup-URI is valid and ready to use. + + The Setup-URI does not appear to be valid. Please check that you have copied it correctly. + + + + + + {error} + + + + processSetupURI()} + /> + setResult(TYPE_CANCELLED)} /> + diff --git a/src/modules/features/SetupWizard/dialogs/utilCheckCouchDB.ts b/src/modules/features/SetupWizard/dialogs/utilCheckCouchDB.ts new file mode 100644 index 0000000..62699bc --- /dev/null +++ b/src/modules/features/SetupWizard/dialogs/utilCheckCouchDB.ts @@ -0,0 +1,293 @@ +import { requestToCouchDBWithCredentials } from "../../../../common/utils"; +import { $msg } from "../../../../lib/src/common/i18n"; +import { Logger } from "../../../../lib/src/common/logger"; +import type { ObsidianLiveSyncSettings } from "../../../../lib/src/common/types"; +import { parseHeaderValues } from "../../../../lib/src/common/utils"; +import { isCloudantURI } from "../../../../lib/src/pouchdb/utils_couchdb"; +import { generateCredentialObject } from "../../../../lib/src/replication/httplib"; +export type ResultMessage = { message: string; classes: string[] }; +export type ResultErrorMessage = { message: string; result: "error"; classes: string[] }; +export type ResultOk = { message: string; result: "ok"; value?: any }; +export type ResultError = { message: string; result: "error"; value: any; fixMessage: string; fix(): Promise }; +export type ConfigCheckResult = ResultOk | ResultError | ResultMessage | ResultErrorMessage; +/** + * Compares two version strings to determine if the baseVersion is greater than or equal to the version. + * @param baseVersion a.b.c format + * @param version a.b.c format + * @returns true if baseVersion is greater than or equal to version, false otherwise + */ +function isGreaterThanOrEqual(baseVersion: string, version: string) { + const versionParts = `${baseVersion}.0.0.0`.split("."); + const targetParts = version.split("."); + for (let i = 0; i < targetParts.length; i++) { + // compare as number if possible (so 3.10 > 3.2, 3.10.1b > 3.10.1a) + const result = versionParts[i].localeCompare(targetParts[i], undefined, { numeric: true }); + if (result > 0) return true; + if (result < 0) return false; + } + return true; +} + +/** + * Updates the remote CouchDB setting with the given key and value. + * @param setting Connection settings + * @param key setting key to update + * @param value setting value to update + * @returns true if the update was successful, false otherwise + */ +async function updateRemoteSetting(setting: ObsidianLiveSyncSettings, key: string, value: any) { + const customHeaders = parseHeaderValues(setting.couchDB_CustomHeaders); + const credential = generateCredentialObject(setting); + const res = await requestToCouchDBWithCredentials( + setting.couchDB_URI, + credential, + undefined, + key, + value, + undefined, + customHeaders + ); + if (res.status == 200) { + return true; + } else { + return res.text || "Unknown error"; + } +} + +/** + * Checks the CouchDB configuration and returns the results. + * @param editingSettings + * @returns Array of ConfigCheckResult + */ +export const checkConfig = async (editingSettings: ObsidianLiveSyncSettings) => { + const result = [] as ConfigCheckResult[]; + const addMessage = (msg: string, classes: string[] = []) => { + result.push({ message: msg, classes }); + }; + const addSuccess = (msg: string, value?: any) => { + result.push({ message: msg, result: "ok", value }); + }; + const _addError = (message: string, fixMessage: string, fix: () => Promise, value?: any) => { + result.push({ message, result: "error", fixMessage, fix, value }); + }; + const addErrorMessage = (msg: string, classes: string[] = []) => { + result.push({ message: msg, result: "error", classes }); + }; + + const addError = (message: string, fixMessage: string, key: string, expected: any) => { + _addError(message, fixMessage, async () => { + await updateRemoteSetting(editingSettings, key, expected); + }); + }; + + addMessage($msg("obsidianLiveSyncSettingTab.logCheckingDbConfig")); + + try { + if (isCloudantURI(editingSettings.couchDB_URI)) { + addMessage($msg("obsidianLiveSyncSettingTab.logCannotUseCloudant")); + return result; + } + // Tip: Add log for cloudant as Logger($msg("obsidianLiveSyncSettingTab.logServerConfigurationCheck")); + const customHeaders = parseHeaderValues(editingSettings.couchDB_CustomHeaders); + const credential = generateCredentialObject(editingSettings); + const r = await requestToCouchDBWithCredentials( + editingSettings.couchDB_URI, + credential, + window.origin, + undefined, + undefined, + undefined, + customHeaders + ); + const responseConfig = r.json; + addMessage($msg("obsidianLiveSyncSettingTab.msgNotice"), ["ob-btn-config-head"]); + addMessage($msg("obsidianLiveSyncSettingTab.msgIfConfigNotPersistent"), ["ob-btn-config-info"]); + addMessage($msg("obsidianLiveSyncSettingTab.msgConfigCheck"), ["ob-btn-config-head"]); + + const serverBanner = r.headers["server"] ?? r.headers["Server"] ?? "unknown"; + addMessage($msg("obsidianLiveSyncSettingTab.serverVersion", { info: serverBanner })); + const versionMatch = serverBanner.match(/CouchDB(\/([0-9.]+))?/); + const versionStr = versionMatch ? versionMatch[2] : "0.0.0"; + + // Compare version string with the target version. + // version must be a string like "3.2.1" or "3.10.2", and must be two or three parts. + + // Admin check + // for database creation and deletion + if (!(editingSettings.couchDB_USER in responseConfig.admins)) { + addSuccess($msg("obsidianLiveSyncSettingTab.warnNoAdmin")); + } else { + addSuccess($msg("obsidianLiveSyncSettingTab.okAdminPrivileges")); + } + if (isGreaterThanOrEqual(versionStr, "3.2.0")) { + // HTTP user-authorization check + if (responseConfig?.chttpd?.require_valid_user != "true") { + addError( + $msg("obsidianLiveSyncSettingTab.errRequireValidUser"), + $msg("obsidianLiveSyncSettingTab.msgSetRequireValidUser"), + "chttpd/require_valid_user", + "true" + ); + } else { + addSuccess($msg("obsidianLiveSyncSettingTab.okRequireValidUser")); + } + } else { + if (responseConfig?.chttpd_auth?.require_valid_user != "true") { + addError( + $msg("obsidianLiveSyncSettingTab.errRequireValidUserAuth"), + $msg("obsidianLiveSyncSettingTab.msgSetRequireValidUserAuth"), + "chttpd_auth/require_valid_user", + "true" + ); + } else { + addSuccess($msg("obsidianLiveSyncSettingTab.okRequireValidUserAuth")); + } + } + // HTTPD check + // Check Authentication header + if (!responseConfig?.httpd["WWW-Authenticate"]) { + addError( + $msg("obsidianLiveSyncSettingTab.errMissingWwwAuth"), + $msg("obsidianLiveSyncSettingTab.msgSetWwwAuth"), + "httpd/WWW-Authenticate", + 'Basic realm="couchdb"' + ); + } else { + addSuccess($msg("obsidianLiveSyncSettingTab.okWwwAuth")); + } + if (isGreaterThanOrEqual(versionStr, "3.2.0")) { + if (responseConfig?.chttpd?.enable_cors != "true") { + addError( + $msg("obsidianLiveSyncSettingTab.errEnableCorsChttpd"), + $msg("obsidianLiveSyncSettingTab.msgEnableCorsChttpd"), + "chttpd/enable_cors", + "true" + ); + } else { + addSuccess($msg("obsidianLiveSyncSettingTab.okEnableCorsChttpd")); + } + } else { + if (responseConfig?.httpd?.enable_cors != "true") { + addError( + $msg("obsidianLiveSyncSettingTab.errEnableCors"), + $msg("obsidianLiveSyncSettingTab.msgEnableCors"), + "httpd/enable_cors", + "true" + ); + } else { + addSuccess($msg("obsidianLiveSyncSettingTab.okEnableCors")); + } + } + // If the server is not cloudant, configure request size + if (!isCloudantURI(editingSettings.couchDB_URI)) { + // REQUEST SIZE + if (Number(responseConfig?.chttpd?.max_http_request_size ?? 0) < 4294967296) { + addError( + $msg("obsidianLiveSyncSettingTab.errMaxRequestSize"), + $msg("obsidianLiveSyncSettingTab.msgSetMaxRequestSize"), + "chttpd/max_http_request_size", + "4294967296" + ); + } else { + addSuccess($msg("obsidianLiveSyncSettingTab.okMaxRequestSize")); + } + if (Number(responseConfig?.couchdb?.max_document_size ?? 0) < 50000000) { + addError( + $msg("obsidianLiveSyncSettingTab.errMaxDocumentSize"), + $msg("obsidianLiveSyncSettingTab.msgSetMaxDocSize"), + "couchdb/max_document_size", + "50000000" + ); + } else { + addSuccess($msg("obsidianLiveSyncSettingTab.okMaxDocumentSize")); + } + } + // CORS check + // checking connectivity for mobile + if (responseConfig?.cors?.credentials != "true") { + addError( + $msg("obsidianLiveSyncSettingTab.errCorsCredentials"), + $msg("obsidianLiveSyncSettingTab.msgSetCorsCredentials"), + "cors/credentials", + "true" + ); + } else { + addSuccess($msg("obsidianLiveSyncSettingTab.okCorsCredentials")); + } + const ConfiguredOrigins = ((responseConfig?.cors?.origins ?? "") + "").split(","); + if ( + responseConfig?.cors?.origins == "*" || + (ConfiguredOrigins.indexOf("app://obsidian.md") !== -1 && + ConfiguredOrigins.indexOf("capacitor://localhost") !== -1 && + ConfiguredOrigins.indexOf("http://localhost") !== -1) + ) { + addSuccess($msg("obsidianLiveSyncSettingTab.okCorsOrigins")); + } else { + const fixedValue = [ + ...new Set([ + ...ConfiguredOrigins.map((e) => e.trim()), + "app://obsidian.md", + "capacitor://localhost", + "http://localhost", + ]), + ].join(","); + addError( + $msg("obsidianLiveSyncSettingTab.errCorsOrigins"), + $msg("obsidianLiveSyncSettingTab.msgSetCorsOrigins"), + "cors/origins", + fixedValue + ); + } + addMessage($msg("obsidianLiveSyncSettingTab.msgConnectionCheck"), ["ob-btn-config-head"]); + addMessage($msg("obsidianLiveSyncSettingTab.msgCurrentOrigin", { origin: window.location.origin })); + + // Request header check + const origins = ["app://obsidian.md", "capacitor://localhost", "http://localhost"]; + for (const org of origins) { + const rr = await requestToCouchDBWithCredentials( + editingSettings.couchDB_URI, + credential, + org, + undefined, + undefined, + undefined, + customHeaders + ); + const responseHeaders = Object.fromEntries( + Object.entries(rr.headers).map((e) => { + e[0] = `${e[0]}`.toLowerCase(); + return e; + }) + ); + addMessage($msg("obsidianLiveSyncSettingTab.msgOriginCheck", { org })); + if (responseHeaders["access-control-allow-credentials"] != "true") { + addErrorMessage($msg("obsidianLiveSyncSettingTab.errCorsNotAllowingCredentials")); + } else { + addSuccess($msg("obsidianLiveSyncSettingTab.okCorsCredentialsForOrigin")); + } + if (responseHeaders["access-control-allow-origin"] != org) { + addErrorMessage( + $msg("obsidianLiveSyncSettingTab.warnCorsOriginUnmatched", { + from: origin, + to: responseHeaders["access-control-allow-origin"], + }) + ); + } else { + addSuccess($msg("obsidianLiveSyncSettingTab.okCorsOriginMatched")); + } + } + addMessage($msg("obsidianLiveSyncSettingTab.msgDone"), ["ob-btn-config-head"]); + addMessage($msg("obsidianLiveSyncSettingTab.msgConnectionProxyNote"), ["ob-btn-config-info"]); + addMessage($msg("obsidianLiveSyncSettingTab.logCheckingConfigDone")); + } catch (ex: any) { + if (ex?.status == 401) { + addErrorMessage($msg("obsidianLiveSyncSettingTab.errAccessForbidden")); + addErrorMessage($msg("obsidianLiveSyncSettingTab.errCannotContinueTest")); + addMessage($msg("obsidianLiveSyncSettingTab.logCheckingConfigDone")); + } else { + addErrorMessage($msg("obsidianLiveSyncSettingTab.logCheckingConfigFailed")); + Logger(ex); + } + } + return result; +}; diff --git a/src/modules/services/ObsidianServices.ts b/src/modules/services/ObsidianServices.ts index 3972752..0f98428 100644 --- a/src/modules/services/ObsidianServices.ts +++ b/src/modules/services/ObsidianServices.ts @@ -14,6 +14,9 @@ import { InjectableVaultService, } from "../../lib/src/services/InjectableServices.ts"; import { InjectableServiceHub } from "../../lib/src/services/InjectableServices.ts"; +import { ConfigServiceBrowserCompat } from "../../lib/src/services/Services.ts"; +import type ObsidianLiveSyncPlugin from "../../main.ts"; +import { ObsidianUIService } from "./ObsidianUIService.ts"; // All Services will be migrated to be based on Plain Services, not Injectable Services. // This is a migration step. @@ -42,6 +45,8 @@ export class ObsidianVaultService extends InjectableVaultService {} // InjectableTestService export class ObsidianTestService extends InjectableTestService {} +export class ObsidianConfigService extends ConfigServiceBrowserCompat {} + // InjectableServiceHub export class ObsidianServiceHub extends InjectableServiceHub { @@ -73,4 +78,14 @@ export class ObsidianServiceHub extends InjectableServiceHub { ); protected _vault: ObsidianVaultService = new ObsidianVaultService(this._serviceBackend, this._throughHole); protected _test: ObsidianTestService = new ObsidianTestService(this._serviceBackend, this._throughHole); + + private _plugin: ObsidianLiveSyncPlugin; + constructor(plugin: ObsidianLiveSyncPlugin) { + const config = new ObsidianConfigService(); + super({ + ui: new ObsidianUIService(plugin), + config: config, + }); + this._plugin = plugin; + } } diff --git a/src/modules/services/ObsidianUIService.ts b/src/modules/services/ObsidianUIService.ts new file mode 100644 index 0000000..1c8c522 --- /dev/null +++ b/src/modules/services/ObsidianUIService.ts @@ -0,0 +1,40 @@ +import { UIService } from "../../lib/src/services/Services"; +import type ObsidianLiveSyncPlugin from "../../main"; +import { SvelteDialogManager } from "../features/SetupWizard/ObsidianSvelteDialog"; +import DialogueToCopy from "../../lib/src/UI/dialogues/DialogueToCopy.svelte"; + +export class ObsidianUIService extends UIService { + private _dialogManager: SvelteDialogManager; + private _plugin: ObsidianLiveSyncPlugin; + get dialogManager() { + return this._dialogManager; + } + constructor(plugin: ObsidianLiveSyncPlugin) { + super(); + this._dialogManager = new SvelteDialogManager(plugin); + this._plugin = plugin; + } + async promptCopyToClipboard(title: string, value: string): Promise { + const param = { + title: title, + dataToCopy: value, + }; + const result = await this._dialogManager.open(DialogueToCopy, param); + if (result !== "ok") { + return false; + } + return true; + } + showMarkdownDialog( + title: string, + contentMD: string, + buttons: T, + defaultAction?: (typeof buttons)[number] + ): Promise<(typeof buttons)[number] | false> { + return this._plugin.confirm.askSelectStringDialogue(contentMD, buttons, { + title, + defaultAction: defaultAction ?? buttons[0], + timeout: 0, + }); + } +}