handy online tools for AT Protocol boat.kelinci.net
atproto bluesky atcute typescript solidjs

Compare changes

Choose any two refs to compare.

+3
.gitignore
··· 1 1 node_modules/ 2 2 dist/ 3 3 4 + /.wrangler/ 5 + /.research/ 6 + 4 7 *.local 5 8 *.local.ts 6 9
-2
.npmrc
··· 1 1 auto-install-peers=false 2 2 public-hoist-pattern[]=workbox-window 3 - 4 - @jsr:registry=https://npm.jsr.io
+1 -1
.vscode/settings.json
··· 1 1 { 2 - "editor.defaultFormatter": "esbenp.prettier-vscode", 2 + "editor.defaultFormatter": "prettier.prettier-vscode", 3 3 "typescript.tsdk": "node_modules/typescript/lib", 4 4 "tailwindCSS.experimental.classRegex": ["tw`([^`]*)"] 5 5 }
+14
LICENSE
··· 1 + BSD Zero Clause License 2 + 3 + Copyright (c) 2025 Mary 4 + 5 + Permission to use, copy, modify, and/or distribute this software for any 6 + purpose with or without fee is hereby granted. 7 + 8 + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 9 + REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10 + AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 11 + INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 + LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 13 + OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 + PERFORMANCE OF THIS SOFTWARE.
+32 -31
package.json
··· 4 4 "dev": "vite", 5 5 "build": "tsc -b && vite build", 6 6 "preview": "vite preview", 7 - "fmt": "prettier --cache --write ." 7 + "fmt": "PRETTIER_EXPERIMENTAL_CLI=1 prettier --cache --write ." 8 8 }, 9 9 "dependencies": { 10 - "@atcute/atproto": "^3.0.2", 11 - "@atcute/bluesky": "^3.0.2", 12 - "@atcute/car": "^3.1.1", 13 - "@atcute/cbor": "^2.2.4", 14 - "@atcute/cid": "^2.2.3", 15 - "@atcute/client": "^4.0.3", 16 - "@atcute/crypto": "^2.2.2", 17 - "@atcute/did-plc": "^0.1.5", 18 - "@atcute/identity": "^1.0.2", 19 - "@atcute/identity-resolver": "^1.1.0", 20 - "@atcute/lexicons": "^1.0.3", 21 - "@atcute/multibase": "^1.1.4", 22 - "@atcute/tid": "^1.0.2", 23 - "@badrap/valita": "^0.4.5", 24 - "@mary/array-fns": "npm:@jsr/mary__array-fns@^0.1.4", 25 - "@mary/ds-queue": "npm:@jsr/mary__ds-queue@^0.1.2", 26 - "@mary/events": "npm:@jsr/mary__events@^0.2.0", 10 + "@atcute/atproto": "^3.1.9", 11 + "@atcute/bluesky": "^3.2.13", 12 + "@atcute/car": "^5.0.0", 13 + "@atcute/cbor": "^2.2.8", 14 + "@atcute/cid": "^2.2.6", 15 + "@atcute/client": "^4.1.1", 16 + "@atcute/crypto": "^2.3.0", 17 + "@atcute/did-plc": "^0.2.0", 18 + "@atcute/identity": "^1.1.3", 19 + "@atcute/identity-resolver": "^1.2.0", 20 + "@atcute/lexicons": "^1.2.5", 21 + "@atcute/multibase": "^1.1.6", 22 + "@atcute/repo": "^0.1.0", 23 + "@atcute/tid": "^1.0.3", 24 + "@badrap/valita": "^0.4.6", 25 + "@mary/array-fns": "jsr:^0.1.5", 26 + "@mary/ds-queue": "jsr:^0.1.3", 27 + "@mary/events": "jsr:^0.2.0", 27 28 "@mary/solid-freeze": "npm:@externdefs/solid-freeze@^0.1.1", 28 - "@mary/tar": "npm:@jsr/mary__tar@^0.2.4", 29 - "nanoid": "^5.1.5", 29 + "@mary/tar": "jsr:^0.3.1", 30 + "nanoid": "^5.1.6", 30 31 "native-file-system-adapter": "^3.0.1", 31 - "solid-js": "^1.9.7" 32 + "solid-js": "^1.9.10" 32 33 }, 33 34 "devDependencies": { 34 35 "@tailwindcss/forms": "^0.5.10", 35 - "@types/node": "^22.15.21", 36 - "autoprefixer": "^10.4.21", 37 - "prettier": "^3.5.3", 38 - "prettier-plugin-tailwindcss": "^0.6.11", 39 - "tailwindcss": "^3.4.17", 40 - "terser": "^5.39.2", 41 - "typescript": "~5.8.3", 42 - "vite": "^6.3.5", 43 - "vite-plugin-solid": "^2.11.6", 44 - "wrangler": "^4.16.1" 36 + "@types/node": "^22.19.2", 37 + "autoprefixer": "^10.4.22", 38 + "prettier": "^3.7.4", 39 + "prettier-plugin-tailwindcss": "^0.6.14", 40 + "tailwindcss": "^3.4.18", 41 + "terser": "^5.44.1", 42 + "typescript": "~5.9.3", 43 + "vite": "^7.2.7", 44 + "vite-plugin-solid": "^2.11.10", 45 + "wrangler": "^4.53.0" 45 46 } 46 47 }
+957 -1151
pnpm-lock.yaml
··· 9 9 .: 10 10 dependencies: 11 11 '@atcute/atproto': 12 - specifier: ^3.0.2 13 - version: 3.0.2 12 + specifier: ^3.1.9 13 + version: 3.1.9 14 14 '@atcute/bluesky': 15 - specifier: ^3.0.2 16 - version: 3.0.2 15 + specifier: ^3.2.13 16 + version: 3.2.13 17 17 '@atcute/car': 18 - specifier: ^3.1.1 19 - version: 3.1.1 18 + specifier: ^5.0.0 19 + version: 5.0.0 20 20 '@atcute/cbor': 21 - specifier: ^2.2.4 22 - version: 2.2.4 21 + specifier: ^2.2.8 22 + version: 2.2.8 23 23 '@atcute/cid': 24 - specifier: ^2.2.3 25 - version: 2.2.3 24 + specifier: ^2.2.6 25 + version: 2.2.6 26 26 '@atcute/client': 27 - specifier: ^4.0.3 28 - version: 4.0.3 27 + specifier: ^4.1.1 28 + version: 4.1.1 29 29 '@atcute/crypto': 30 - specifier: ^2.2.2 31 - version: 2.2.2 30 + specifier: ^2.3.0 31 + version: 2.3.0 32 32 '@atcute/did-plc': 33 - specifier: ^0.1.5 34 - version: 0.1.5 33 + specifier: ^0.2.0 34 + version: 0.2.0 35 35 '@atcute/identity': 36 - specifier: ^1.0.2 37 - version: 1.0.2 36 + specifier: ^1.1.3 37 + version: 1.1.3 38 38 '@atcute/identity-resolver': 39 - specifier: ^1.1.0 40 - version: 1.1.0(@atcute/identity@1.0.2) 39 + specifier: ^1.2.0 40 + version: 1.2.0(@atcute/identity@1.1.3) 41 41 '@atcute/lexicons': 42 + specifier: ^1.2.5 43 + version: 1.2.5 44 + '@atcute/multibase': 45 + specifier: ^1.1.6 46 + version: 1.1.6 47 + '@atcute/repo': 48 + specifier: ^0.1.0 49 + version: 0.1.0 50 + '@atcute/tid': 42 51 specifier: ^1.0.3 43 52 version: 1.0.3 44 - '@atcute/multibase': 45 - specifier: ^1.1.4 46 - version: 1.1.4 47 - '@atcute/tid': 48 - specifier: ^1.0.2 49 - version: 1.0.2 50 53 '@badrap/valita': 51 - specifier: ^0.4.5 52 - version: 0.4.5 54 + specifier: ^0.4.6 55 + version: 0.4.6 53 56 '@mary/array-fns': 54 - specifier: npm:@jsr/mary__array-fns@^0.1.4 55 - version: '@jsr/mary__array-fns@0.1.4' 57 + specifier: jsr:^0.1.5 58 + version: '@jsr/mary__array-fns@0.1.5' 56 59 '@mary/ds-queue': 57 - specifier: npm:@jsr/mary__ds-queue@^0.1.2 58 - version: '@jsr/mary__ds-queue@0.1.2' 60 + specifier: jsr:^0.1.3 61 + version: '@jsr/mary__ds-queue@0.1.3' 59 62 '@mary/events': 60 - specifier: npm:@jsr/mary__events@^0.2.0 63 + specifier: jsr:^0.2.0 61 64 version: '@jsr/mary__events@0.2.0' 62 65 '@mary/solid-freeze': 63 66 specifier: npm:@externdefs/solid-freeze@^0.1.1 64 - version: '@externdefs/solid-freeze@0.1.1(solid-js@1.9.7)' 67 + version: '@externdefs/solid-freeze@0.1.1(solid-js@1.9.10)' 65 68 '@mary/tar': 66 - specifier: npm:@jsr/mary__tar@^0.2.4 67 - version: '@jsr/mary__tar@0.2.4' 69 + specifier: jsr:^0.3.1 70 + version: '@jsr/mary__tar@0.3.1' 68 71 nanoid: 69 - specifier: ^5.1.5 70 - version: 5.1.5 72 + specifier: ^5.1.6 73 + version: 5.1.6 71 74 native-file-system-adapter: 72 75 specifier: ^3.0.1 73 76 version: 3.0.1 74 77 solid-js: 75 - specifier: ^1.9.7 76 - version: 1.9.7 78 + specifier: ^1.9.10 79 + version: 1.9.10 77 80 devDependencies: 78 81 '@tailwindcss/forms': 79 82 specifier: ^0.5.10 80 - version: 0.5.10(tailwindcss@3.4.17) 83 + version: 0.5.10(tailwindcss@3.4.18) 81 84 '@types/node': 82 - specifier: ^22.15.21 83 - version: 22.15.21 85 + specifier: ^22.19.2 86 + version: 22.19.2 84 87 autoprefixer: 85 - specifier: ^10.4.21 86 - version: 10.4.21(postcss@8.5.3) 88 + specifier: ^10.4.22 89 + version: 10.4.22(postcss@8.5.6) 87 90 prettier: 88 - specifier: ^3.5.3 89 - version: 3.5.3 91 + specifier: ^3.7.4 92 + version: 3.7.4 90 93 prettier-plugin-tailwindcss: 91 - specifier: ^0.6.11 92 - version: 0.6.11(prettier@3.5.3) 94 + specifier: ^0.6.14 95 + version: 0.6.14(prettier@3.7.4) 93 96 tailwindcss: 94 - specifier: ^3.4.17 95 - version: 3.4.17 97 + specifier: ^3.4.18 98 + version: 3.4.18 96 99 terser: 97 - specifier: ^5.39.2 98 - version: 5.39.2 100 + specifier: ^5.44.1 101 + version: 5.44.1 99 102 typescript: 100 - specifier: ~5.8.3 101 - version: 5.8.3 103 + specifier: ~5.9.3 104 + version: 5.9.3 102 105 vite: 103 - specifier: ^6.3.5 104 - version: 6.3.5(@types/node@22.15.21)(jiti@1.21.7)(terser@5.39.2)(yaml@2.8.0) 106 + specifier: ^7.2.7 107 + version: 7.2.7(@types/node@22.19.2)(jiti@1.21.7)(terser@5.44.1) 105 108 vite-plugin-solid: 106 - specifier: ^2.11.6 107 - version: 2.11.6(solid-js@1.9.7)(vite@6.3.5(@types/node@22.15.21)(jiti@1.21.7)(terser@5.39.2)(yaml@2.8.0)) 109 + specifier: ^2.11.10 110 + version: 2.11.10(solid-js@1.9.10)(vite@7.2.7(@types/node@22.19.2)(jiti@1.21.7)(terser@5.44.1)) 108 111 wrangler: 109 - specifier: ^4.16.1 110 - version: 4.16.1 112 + specifier: ^4.53.0 113 + version: 4.53.0 111 114 112 115 packages: 113 116 ··· 115 118 resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} 116 119 engines: {node: '>=10'} 117 120 118 - '@ampproject/remapping@2.3.0': 119 - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} 120 - engines: {node: '>=6.0.0'} 121 - 122 - '@atcute/atproto@3.0.2': 123 - resolution: {integrity: sha512-p37GqTmrxc1XaxtX8JsePEuomL+PtDeGdy0lcBm+HisD03ZZTia7MouxUpnYezX0l926fFaDc9tllIBtX9iSsQ==} 121 + '@atcute/atproto@3.1.9': 122 + resolution: {integrity: sha512-DyWwHCTdR4hY2BPNbLXgVmm7lI+fceOwWbE4LXbGvbvVtSn+ejSVFaAv01Ra3kWDha0whsOmbJL8JP0QPpf1+w==} 124 123 125 - '@atcute/bluesky@3.0.2': 126 - resolution: {integrity: sha512-xDRu/8Rlu3uTG/Mf625vUvKiFvy3hdCE371pXSJpHofivNZxi+MburdmYgOsBWZstNMo4vTBUviWaLJpL23rFg==} 124 + '@atcute/bluesky@3.2.13': 125 + resolution: {integrity: sha512-ZG/mqsCjVU6zvH6XsRw+oQglrsdu5R7mnncMO+Ux0KWbX2xJw4ZMFHfs7ZTC69dVPK9r/yle7YbpygZTOWDM9A==} 127 126 128 - '@atcute/car@3.1.1': 129 - resolution: {integrity: sha512-yhez/LqIl0zHubG6z/G/gqWYHmg7wJ5L4jNkbXj5FvZ4eOvmzsw8+ojbdq6wfMU4p5NhP0pUJNLkTZHbYSPmLg==} 127 + '@atcute/car@5.0.0': 128 + resolution: {integrity: sha512-OIY2xTXv8lSpZsDSn/UYQtJSMvDw5Hi4Q+uyvmiqSM+fht08QRAEq/nxa5YFciPZ3nfDFnZ3//EgJw7QhkSXLQ==} 130 129 131 - '@atcute/cbor@2.2.4': 132 - resolution: {integrity: sha512-8Y/OTM8zs5VInOCjfx4f9Idiiz7ygM/FkfWv/HW3/ZUsXczn1xk7GzTBbm4P5crn4C5luwDGpO7FwClMOERrow==} 130 + '@atcute/cbor@2.2.8': 131 + resolution: {integrity: sha512-UzOAN9BuN6JCXgn0ryV8qZuRJUDrNqrbLd6EFM8jc6RYssjRyGRxNy6RZ1NU/07Hd8Tq/0pz8+nQiMu5Zai5uw==} 133 132 134 - '@atcute/cid@2.2.3': 135 - resolution: {integrity: sha512-WEzNSL1EuCVtCQDFYEBIm4dEP6PcMEwi8IYUVIWvT77eO5EjY58F63z5T4qMABxSBM0+L4kqMxypdL1Fzf6LZw==} 133 + '@atcute/cid@2.2.6': 134 + resolution: {integrity: sha512-bTAHHbJ24p+E//V4KCS4xdmd39o211jJswvqQOevj7vk+5IYcgDLx1ryZWZ1sEPOo9x875li/kj5gpKL14RDwQ==} 136 135 137 - '@atcute/client@4.0.3': 138 - resolution: {integrity: sha512-RIOZWFVLca/HiPAAUDqQPOdOreCxTbL5cb+WUf5yqQOKIu5yEAP3eksinmlLmgIrlr5qVOE7brazUUzaskFCfw==} 136 + '@atcute/client@4.1.1': 137 + resolution: {integrity: sha512-FROCbTTCeL5u4tO/n72jDEKyKqjdlXMB56Ehve3W/gnnLGCYWvN42sS7tvL1Mgu6sbO3yZwsXKDrmM2No4XpjA==} 139 138 140 - '@atcute/crypto@2.2.2': 141 - resolution: {integrity: sha512-zpJjB6m0+Wy4YrgBJTSps4wbi3Xv1z/yZO/m/3sUYl1bIqUdHhH3vmDJtiXkRONgKNhiaQdukyt0omd9n4vDUA==} 139 + '@atcute/crypto@2.3.0': 140 + resolution: {integrity: sha512-w5pkJKCjbNMQu+F4JRHbR3ROQyhi1wbn+GSC6WDQamcYHkZmEZk1/eoI354bIQOOfkEM6aFLv718iskrkon4GQ==} 142 141 143 - '@atcute/did-plc@0.1.5': 144 - resolution: {integrity: sha512-f0UTge7i1MgHNk73SKN2FE/nt/FzRyEypIbc85hL32sig0kCs87yZ2W+1okBkaBoQ6Fis2ILwwAA5VAUJE3Yng==} 142 + '@atcute/did-plc@0.2.0': 143 + resolution: {integrity: sha512-1sGek8GRM/Ph7nLVRREm8FqM7g4shGckItvdVwJcRbUa8Rh0zOsXQa0QyYWAC0k40BhkqO9FwKXhJEaXCmF5oQ==} 145 144 146 - '@atcute/identity-resolver@1.1.0': 147 - resolution: {integrity: sha512-Ak41aYsQwW1xPan7BXM6TfQ18AkQg8RVH2s7Ppcg3b7YJUo8v24KJXaYoha3t+Tcr0T1xx56j/vZPIfwUG+b4g==} 145 + '@atcute/identity-resolver@1.2.0': 146 + resolution: {integrity: sha512-5UbSJfdV3JIkF8ksXz7g4nKBWasf2wROvzM66cfvTIWydWFO6/oS1KZd+zo9Eokje5Scf5+jsY9ZfgVARLepXg==} 148 147 peerDependencies: 149 148 '@atcute/identity': ^1.0.0 150 149 151 - '@atcute/identity@1.0.2': 152 - resolution: {integrity: sha512-SrDPHuEarEHj9bx7NfYn7DYG6kIgJIMRU581iOCIaVaiZ1WhE9D8QxTxeYG/rbGNSa85E891ECp1sQcKiBN0kg==} 150 + '@atcute/identity@1.1.3': 151 + resolution: {integrity: sha512-oIqPoI8TwWeQxvcLmFEZLdN2XdWcaLVtlm8pNk0E72As9HNzzD9pwKPrLr3rmTLRIoULPPFmq9iFNsTeCIU9ng==} 152 + 153 + '@atcute/lexicons@1.2.5': 154 + resolution: {integrity: sha512-9yO9WdgxW8jZ7SbzUycH710z+JmsQ9W9n5S6i6eghYju32kkluFmgBeS47r8e8p2+Dv4DemS7o/3SUGsX9FR5Q==} 153 155 154 - '@atcute/lexicons@1.0.3': 155 - resolution: {integrity: sha512-R4xa3AMD+uMNn67/Nly0ohieT+vuN2qeV8Oq/mkpb0O3pFTuG7IkhXEGIXVnFY6I/NEQGhWB1FjHYpgRyL35Pw==} 156 + '@atcute/mst@0.1.0': 157 + resolution: {integrity: sha512-h+iDToKEnBpigk2DOHjSqY63vJtjYKUIztqu1CZ0P+I54wV2SrgoqAXAT1xrW6A1Iup8cjTv+U2H5WVG4KxPLw==} 156 158 157 - '@atcute/multibase@1.1.4': 158 - resolution: {integrity: sha512-NUf5AeeSOmuZHGU+4GAaMtISJoG+ZHtW/vUVA4lK/YDt/7LODAW0Fd0NNIIUPVUoW0xJS6zSEIWvwLLuxmEHhA==} 159 + '@atcute/multibase@1.1.6': 160 + resolution: {integrity: sha512-HBxuCgYLKPPxETV0Rot4VP9e24vKl8JdzGCZOVsDaOXJgbRZoRIF67Lp0H/OgnJeH/Xpva8Z5ReoTNJE5dn3kg==} 159 161 160 - '@atcute/tid@1.0.2': 161 - resolution: {integrity: sha512-ahmjroNyeDPJhtuf3+HTJropaH04HmJ8fhntDu73Gpz/RkAF7+nkz6kcP2QTgfvMCgMPAJUdskAAP82GPDTY9w==} 162 + '@atcute/repo@0.1.0': 163 + resolution: {integrity: sha512-INiYAuma8dydBu7cqd2WVpcXh3mzhIepYBUqFWAK5MqMulPRLTRCc/9GW3G9pxYrOdlvLCVamG2Jf8XK0nuFEw==} 162 164 163 - '@atcute/uint8array@1.0.2': 164 - resolution: {integrity: sha512-JvD61GCKLknPFmusf34LVOPRb2rzl7BaJWt2ejxDz+/UzKCsHBYjhbeQgZg7w4hCXu1GVBAaKJMlXv+jRHW5IQ==} 165 + '@atcute/tid@1.0.3': 166 + resolution: {integrity: sha512-wfMJx1IMdnu0CZgWl0uR4JO2s6PGT1YPhpytD4ZHzEYKKQVuqV6Eb/7vieaVo1eYNMp2FrY67FZObeR7utRl2w==} 165 167 166 - '@atcute/util-fetch@1.0.1': 167 - resolution: {integrity: sha512-Clc0E/5ufyGBVfYBUwWNlHONlZCoblSr4Ho50l1LhmRPGB1Wu/AQ9Sz+rsBg7fdaW/auve8ulmwhRhnX2cGRow==} 168 + '@atcute/uint8array@1.0.6': 169 + resolution: {integrity: sha512-ucfRBQc7BFT8n9eCyGOzDHEMKF/nZwhS2pPao4Xtab1ML3HdFYcX2DM1tadCzas85QTGxHe5urnUAAcNKGRi9A==} 168 170 169 - '@atcute/varint@1.0.2': 170 - resolution: {integrity: sha512-0O31hePzzr4O3NGWHUKKOyta6CGSL+AtN8iir8grGxu9jXyI7DBARlw6PbgKA6uTAvsXdpmRmF8MX+p0TsLnNg==} 171 + '@atcute/util-fetch@1.0.4': 172 + resolution: {integrity: sha512-sIU9Qk0dE8PLEXSfhy+gIJV+HpiiknMytCI2SqLlqd0vgZUtEKI/EQfP+23LHWvP+CLCzVDOa6cpH045OlmNBg==} 173 + 174 + '@atcute/varint@1.0.3': 175 + resolution: {integrity: sha512-fdvMPyBB+McDT+Ai5e9RwEbwYV4yjZ60S2Dn5PTjGqUyxvoCH1z42viuheDZRUDkmfQehXJTZ5az7dSozVNtog==} 171 176 172 177 '@babel/code-frame@7.27.1': 173 178 resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} 174 179 engines: {node: '>=6.9.0'} 175 180 176 - '@babel/compat-data@7.27.2': 177 - resolution: {integrity: sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==} 181 + '@babel/compat-data@7.28.5': 182 + resolution: {integrity: sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==} 178 183 engines: {node: '>=6.9.0'} 179 184 180 - '@babel/core@7.27.1': 181 - resolution: {integrity: sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==} 185 + '@babel/core@7.28.5': 186 + resolution: {integrity: sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==} 182 187 engines: {node: '>=6.9.0'} 183 188 184 - '@babel/generator@7.27.1': 185 - resolution: {integrity: sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==} 189 + '@babel/generator@7.28.5': 190 + resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==} 186 191 engines: {node: '>=6.9.0'} 187 192 188 193 '@babel/helper-compilation-targets@7.27.2': 189 194 resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} 195 + engines: {node: '>=6.9.0'} 196 + 197 + '@babel/helper-globals@7.28.0': 198 + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} 190 199 engines: {node: '>=6.9.0'} 191 200 192 201 '@babel/helper-module-imports@7.18.6': ··· 197 206 resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} 198 207 engines: {node: '>=6.9.0'} 199 208 200 - '@babel/helper-module-transforms@7.27.1': 201 - resolution: {integrity: sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g==} 209 + '@babel/helper-module-transforms@7.28.3': 210 + resolution: {integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==} 202 211 engines: {node: '>=6.9.0'} 203 212 peerDependencies: 204 213 '@babel/core': ^7.0.0 ··· 211 220 resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} 212 221 engines: {node: '>=6.9.0'} 213 222 214 - '@babel/helper-validator-identifier@7.27.1': 215 - resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} 223 + '@babel/helper-validator-identifier@7.28.5': 224 + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} 216 225 engines: {node: '>=6.9.0'} 217 226 218 227 '@babel/helper-validator-option@7.27.1': 219 228 resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} 220 229 engines: {node: '>=6.9.0'} 221 230 222 - '@babel/helpers@7.27.1': 223 - resolution: {integrity: sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==} 231 + '@babel/helpers@7.28.4': 232 + resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==} 224 233 engines: {node: '>=6.9.0'} 225 234 226 - '@babel/parser@7.27.2': 227 - resolution: {integrity: sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==} 235 + '@babel/parser@7.28.5': 236 + resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} 228 237 engines: {node: '>=6.0.0'} 229 238 hasBin: true 230 239 ··· 238 247 resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} 239 248 engines: {node: '>=6.9.0'} 240 249 241 - '@babel/traverse@7.27.1': 242 - resolution: {integrity: sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==} 250 + '@babel/traverse@7.28.5': 251 + resolution: {integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==} 243 252 engines: {node: '>=6.9.0'} 244 253 245 - '@babel/types@7.27.1': 246 - resolution: {integrity: sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==} 254 + '@babel/types@7.28.5': 255 + resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} 247 256 engines: {node: '>=6.9.0'} 248 257 249 - '@badrap/valita@0.4.5': 250 - resolution: {integrity: sha512-4QwGbuhh/JesHRQj79mO/l37PvJj4l/tlAu7+S1n4h47qwaNpZ0WDvIwUGLYUsdi9uQ5UPpiG9wb1Wm3XUFBUQ==} 258 + '@badrap/valita@0.4.6': 259 + resolution: {integrity: sha512-4kdqcjyxo/8RQ8ayjms47HCWZIF5981oE5nIenbfThKDxWXtEHKipAOWlflpPJzZx9y/JWYQkp18Awr7VuepFg==} 251 260 engines: {node: '>= 18'} 252 261 253 - '@cloudflare/kv-asset-handler@0.4.0': 254 - resolution: {integrity: sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA==} 262 + '@cloudflare/kv-asset-handler@0.4.1': 263 + resolution: {integrity: sha512-Nu8ahitGFFJztxUml9oD/DLb7Z28C8cd8F46IVQ7y5Btz575pvMY8AqZsXkX7Gds29eCKdMgIHjIvzskHgPSFg==} 255 264 engines: {node: '>=18.0.0'} 256 265 257 - '@cloudflare/unenv-preset@2.3.2': 258 - resolution: {integrity: sha512-MtUgNl+QkQyhQvv5bbWP+BpBC1N0me4CHHuP2H4ktmOMKdB/6kkz/lo+zqiA4mEazb4y+1cwyNjVrQ2DWeE4mg==} 266 + '@cloudflare/unenv-preset@2.7.13': 267 + resolution: {integrity: sha512-NulO1H8R/DzsJguLC0ndMuk4Ufv0KSlN+E54ay9rn9ZCQo0kpAPwwh3LhgpZ96a3Dr6L9LqW57M4CqC34iLOvw==} 259 268 peerDependencies: 260 - unenv: 2.0.0-rc.17 261 - workerd: ^1.20250508.0 269 + unenv: 2.0.0-rc.24 270 + workerd: ^1.20251202.0 262 271 peerDependenciesMeta: 263 272 workerd: 264 273 optional: true 265 274 266 - '@cloudflare/workerd-darwin-64@1.20250508.0': 267 - resolution: {integrity: sha512-9x09MrA9Y5RQs3zqWvWns8xHgM2pVNXWpeJ+3hQYu4PrwPFZXtTD6b/iMmOnlYKzINlREq1RGeEybMFyWEUlUg==} 275 + '@cloudflare/workerd-darwin-64@1.20251202.0': 276 + resolution: {integrity: sha512-/uvEAWEukTWb1geHhbjGUeZqcSSSyYzp0mvoPUBl+l0ont4NVGao3fgwM0q8wtKvgoKCHSG6zcG23wj9Opj3Nw==} 268 277 engines: {node: '>=16'} 269 278 cpu: [x64] 270 279 os: [darwin] 271 280 272 - '@cloudflare/workerd-darwin-arm64@1.20250508.0': 273 - resolution: {integrity: sha512-0Ili+nE2LLRzYue/yPc1pepSyNNg6LxR3/ng/rlQzVQUxPXIXldHFkJ/ynsYwQnAcf6OxasSi/kbTm6yvDoSAQ==} 281 + '@cloudflare/workerd-darwin-arm64@1.20251202.0': 282 + resolution: {integrity: sha512-f52xRvcI9cWRd6400EZStRtXiRC5XKEud7K5aFIbbUv0VeINltujFQQ9nHWtsF6g1quIXWkjhh5u01gPAYNNXA==} 274 283 engines: {node: '>=16'} 275 284 cpu: [arm64] 276 285 os: [darwin] 277 286 278 - '@cloudflare/workerd-linux-64@1.20250508.0': 279 - resolution: {integrity: sha512-5saVrZ3uVwYxvBa7BaonXjeqB6X0YF3ak05qvBaWcmZ3FNmnarMm2W8842cnbhnckDVBpB/iDo51Sy6Y7y1jcw==} 287 + '@cloudflare/workerd-linux-64@1.20251202.0': 288 + resolution: {integrity: sha512-HYXinF5RBH7oXbsFUMmwKCj+WltpYbf5mRKUBG5v3EuPhUjSIFB84U+58pDyfBJjcynHdy3EtvTWcvh/+lcgow==} 280 289 engines: {node: '>=16'} 281 290 cpu: [x64] 282 291 os: [linux] 283 292 284 - '@cloudflare/workerd-linux-arm64@1.20250508.0': 285 - resolution: {integrity: sha512-muQe1pkxRi3eaq1Q417xvfGd2SlktbLTzNhT5Yftsx8OecWrYuB8i4ttR6Nr5ER06bfEj0FqQjqJJhcp6wLLUQ==} 293 + '@cloudflare/workerd-linux-arm64@1.20251202.0': 294 + resolution: {integrity: sha512-++L02Jdoxz7hEA9qDaQjbVU1RzQS+S+eqIi22DkPe2Tgiq2M3UfNpeu+75k5L9DGRIkZPYvwMBMbcmKvQqdIIg==} 286 295 engines: {node: '>=16'} 287 296 cpu: [arm64] 288 297 os: [linux] 289 298 290 - '@cloudflare/workerd-windows-64@1.20250508.0': 291 - resolution: {integrity: sha512-EJj8iTWFMqjgvZUxxNvzK7frA1JMFi3y/9eDIdZPL/OaQh3cmk5Lai5DCXsKYUxfooMBZWYTp53zOLrvuJI8VQ==} 299 + '@cloudflare/workerd-windows-64@1.20251202.0': 300 + resolution: {integrity: sha512-gzeU6eDydTi7ib+Q9DD/c0hpXtqPucnHk2tfGU03mljPObYxzMkkPGgB5qxpksFvub3y4K0ChjqYxGJB4F+j3g==} 292 301 engines: {node: '>=16'} 293 302 cpu: [x64] 294 303 os: [win32] ··· 297 306 resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} 298 307 engines: {node: '>=12'} 299 308 300 - '@emnapi/runtime@1.4.3': 301 - resolution: {integrity: sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==} 309 + '@emnapi/runtime@1.7.1': 310 + resolution: {integrity: sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==} 302 311 303 - '@esbuild/aix-ppc64@0.25.4': 304 - resolution: {integrity: sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==} 312 + '@esbuild/aix-ppc64@0.25.12': 313 + resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} 305 314 engines: {node: '>=18'} 306 315 cpu: [ppc64] 307 316 os: [aix] 308 317 309 - '@esbuild/aix-ppc64@0.25.5': 310 - resolution: {integrity: sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==} 318 + '@esbuild/aix-ppc64@0.27.0': 319 + resolution: {integrity: sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A==} 311 320 engines: {node: '>=18'} 312 321 cpu: [ppc64] 313 322 os: [aix] 314 323 315 - '@esbuild/android-arm64@0.25.4': 316 - resolution: {integrity: sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==} 324 + '@esbuild/android-arm64@0.25.12': 325 + resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} 317 326 engines: {node: '>=18'} 318 327 cpu: [arm64] 319 328 os: [android] 320 329 321 - '@esbuild/android-arm64@0.25.5': 322 - resolution: {integrity: sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==} 330 + '@esbuild/android-arm64@0.27.0': 331 + resolution: {integrity: sha512-CC3vt4+1xZrs97/PKDkl0yN7w8edvU2vZvAFGD16n9F0Cvniy5qvzRXjfO1l94efczkkQE6g1x0i73Qf5uthOQ==} 323 332 engines: {node: '>=18'} 324 333 cpu: [arm64] 325 334 os: [android] 326 335 327 - '@esbuild/android-arm@0.25.4': 328 - resolution: {integrity: sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==} 336 + '@esbuild/android-arm@0.25.12': 337 + resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} 329 338 engines: {node: '>=18'} 330 339 cpu: [arm] 331 340 os: [android] 332 341 333 - '@esbuild/android-arm@0.25.5': 334 - resolution: {integrity: sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==} 342 + '@esbuild/android-arm@0.27.0': 343 + resolution: {integrity: sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ==} 335 344 engines: {node: '>=18'} 336 345 cpu: [arm] 337 346 os: [android] 338 347 339 - '@esbuild/android-x64@0.25.4': 340 - resolution: {integrity: sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==} 348 + '@esbuild/android-x64@0.25.12': 349 + resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} 341 350 engines: {node: '>=18'} 342 351 cpu: [x64] 343 352 os: [android] 344 353 345 - '@esbuild/android-x64@0.25.5': 346 - resolution: {integrity: sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==} 354 + '@esbuild/android-x64@0.27.0': 355 + resolution: {integrity: sha512-wurMkF1nmQajBO1+0CJmcN17U4BP6GqNSROP8t0X/Jiw2ltYGLHpEksp9MpoBqkrFR3kv2/te6Sha26k3+yZ9Q==} 347 356 engines: {node: '>=18'} 348 357 cpu: [x64] 349 358 os: [android] 350 359 351 - '@esbuild/darwin-arm64@0.25.4': 352 - resolution: {integrity: sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==} 360 + '@esbuild/darwin-arm64@0.25.12': 361 + resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} 353 362 engines: {node: '>=18'} 354 363 cpu: [arm64] 355 364 os: [darwin] 356 365 357 - '@esbuild/darwin-arm64@0.25.5': 358 - resolution: {integrity: sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==} 366 + '@esbuild/darwin-arm64@0.27.0': 367 + resolution: {integrity: sha512-uJOQKYCcHhg07DL7i8MzjvS2LaP7W7Pn/7uA0B5S1EnqAirJtbyw4yC5jQ5qcFjHK9l6o/MX9QisBg12kNkdHg==} 359 368 engines: {node: '>=18'} 360 369 cpu: [arm64] 361 370 os: [darwin] 362 371 363 - '@esbuild/darwin-x64@0.25.4': 364 - resolution: {integrity: sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==} 372 + '@esbuild/darwin-x64@0.25.12': 373 + resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} 365 374 engines: {node: '>=18'} 366 375 cpu: [x64] 367 376 os: [darwin] 368 377 369 - '@esbuild/darwin-x64@0.25.5': 370 - resolution: {integrity: sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==} 378 + '@esbuild/darwin-x64@0.27.0': 379 + resolution: {integrity: sha512-8mG6arH3yB/4ZXiEnXof5MK72dE6zM9cDvUcPtxhUZsDjESl9JipZYW60C3JGreKCEP+p8P/72r69m4AZGJd5g==} 371 380 engines: {node: '>=18'} 372 381 cpu: [x64] 373 382 os: [darwin] 374 383 375 - '@esbuild/freebsd-arm64@0.25.4': 376 - resolution: {integrity: sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==} 384 + '@esbuild/freebsd-arm64@0.25.12': 385 + resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} 377 386 engines: {node: '>=18'} 378 387 cpu: [arm64] 379 388 os: [freebsd] 380 389 381 - '@esbuild/freebsd-arm64@0.25.5': 382 - resolution: {integrity: sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==} 390 + '@esbuild/freebsd-arm64@0.27.0': 391 + resolution: {integrity: sha512-9FHtyO988CwNMMOE3YIeci+UV+x5Zy8fI2qHNpsEtSF83YPBmE8UWmfYAQg6Ux7Gsmd4FejZqnEUZCMGaNQHQw==} 383 392 engines: {node: '>=18'} 384 393 cpu: [arm64] 385 394 os: [freebsd] 386 395 387 - '@esbuild/freebsd-x64@0.25.4': 388 - resolution: {integrity: sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==} 396 + '@esbuild/freebsd-x64@0.25.12': 397 + resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} 389 398 engines: {node: '>=18'} 390 399 cpu: [x64] 391 400 os: [freebsd] 392 401 393 - '@esbuild/freebsd-x64@0.25.5': 394 - resolution: {integrity: sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==} 402 + '@esbuild/freebsd-x64@0.27.0': 403 + resolution: {integrity: sha512-zCMeMXI4HS/tXvJz8vWGexpZj2YVtRAihHLk1imZj4efx1BQzN76YFeKqlDr3bUWI26wHwLWPd3rwh6pe4EV7g==} 395 404 engines: {node: '>=18'} 396 405 cpu: [x64] 397 406 os: [freebsd] 398 407 399 - '@esbuild/linux-arm64@0.25.4': 400 - resolution: {integrity: sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==} 408 + '@esbuild/linux-arm64@0.25.12': 409 + resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} 401 410 engines: {node: '>=18'} 402 411 cpu: [arm64] 403 412 os: [linux] 404 413 405 - '@esbuild/linux-arm64@0.25.5': 406 - resolution: {integrity: sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==} 414 + '@esbuild/linux-arm64@0.27.0': 415 + resolution: {integrity: sha512-AS18v0V+vZiLJyi/4LphvBE+OIX682Pu7ZYNsdUHyUKSoRwdnOsMf6FDekwoAFKej14WAkOef3zAORJgAtXnlQ==} 407 416 engines: {node: '>=18'} 408 417 cpu: [arm64] 409 418 os: [linux] 410 419 411 - '@esbuild/linux-arm@0.25.4': 412 - resolution: {integrity: sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==} 420 + '@esbuild/linux-arm@0.25.12': 421 + resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} 413 422 engines: {node: '>=18'} 414 423 cpu: [arm] 415 424 os: [linux] 416 425 417 - '@esbuild/linux-arm@0.25.5': 418 - resolution: {integrity: sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==} 426 + '@esbuild/linux-arm@0.27.0': 427 + resolution: {integrity: sha512-t76XLQDpxgmq2cNXKTVEB7O7YMb42atj2Re2Haf45HkaUpjM2J0UuJZDuaGbPbamzZ7bawyGFUkodL+zcE+jvQ==} 419 428 engines: {node: '>=18'} 420 429 cpu: [arm] 421 430 os: [linux] 422 431 423 - '@esbuild/linux-ia32@0.25.4': 424 - resolution: {integrity: sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==} 432 + '@esbuild/linux-ia32@0.25.12': 433 + resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} 425 434 engines: {node: '>=18'} 426 435 cpu: [ia32] 427 436 os: [linux] 428 437 429 - '@esbuild/linux-ia32@0.25.5': 430 - resolution: {integrity: sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==} 438 + '@esbuild/linux-ia32@0.27.0': 439 + resolution: {integrity: sha512-Mz1jxqm/kfgKkc/KLHC5qIujMvnnarD9ra1cEcrs7qshTUSksPihGrWHVG5+osAIQ68577Zpww7SGapmzSt4Nw==} 431 440 engines: {node: '>=18'} 432 441 cpu: [ia32] 433 442 os: [linux] 434 443 435 - '@esbuild/linux-loong64@0.25.4': 436 - resolution: {integrity: sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==} 444 + '@esbuild/linux-loong64@0.25.12': 445 + resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} 437 446 engines: {node: '>=18'} 438 447 cpu: [loong64] 439 448 os: [linux] 440 449 441 - '@esbuild/linux-loong64@0.25.5': 442 - resolution: {integrity: sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==} 450 + '@esbuild/linux-loong64@0.27.0': 451 + resolution: {integrity: sha512-QbEREjdJeIreIAbdG2hLU1yXm1uu+LTdzoq1KCo4G4pFOLlvIspBm36QrQOar9LFduavoWX2msNFAAAY9j4BDg==} 443 452 engines: {node: '>=18'} 444 453 cpu: [loong64] 445 454 os: [linux] 446 455 447 - '@esbuild/linux-mips64el@0.25.4': 448 - resolution: {integrity: sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==} 456 + '@esbuild/linux-mips64el@0.25.12': 457 + resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} 449 458 engines: {node: '>=18'} 450 459 cpu: [mips64el] 451 460 os: [linux] 452 461 453 - '@esbuild/linux-mips64el@0.25.5': 454 - resolution: {integrity: sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==} 462 + '@esbuild/linux-mips64el@0.27.0': 463 + resolution: {integrity: sha512-sJz3zRNe4tO2wxvDpH/HYJilb6+2YJxo/ZNbVdtFiKDufzWq4JmKAiHy9iGoLjAV7r/W32VgaHGkk35cUXlNOg==} 455 464 engines: {node: '>=18'} 456 465 cpu: [mips64el] 457 466 os: [linux] 458 467 459 - '@esbuild/linux-ppc64@0.25.4': 460 - resolution: {integrity: sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==} 468 + '@esbuild/linux-ppc64@0.25.12': 469 + resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} 461 470 engines: {node: '>=18'} 462 471 cpu: [ppc64] 463 472 os: [linux] 464 473 465 - '@esbuild/linux-ppc64@0.25.5': 466 - resolution: {integrity: sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==} 474 + '@esbuild/linux-ppc64@0.27.0': 475 + resolution: {integrity: sha512-z9N10FBD0DCS2dmSABDBb5TLAyF1/ydVb+N4pi88T45efQ/w4ohr/F/QYCkxDPnkhkp6AIpIcQKQ8F0ANoA2JA==} 467 476 engines: {node: '>=18'} 468 477 cpu: [ppc64] 469 478 os: [linux] 470 479 471 - '@esbuild/linux-riscv64@0.25.4': 472 - resolution: {integrity: sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==} 480 + '@esbuild/linux-riscv64@0.25.12': 481 + resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} 473 482 engines: {node: '>=18'} 474 483 cpu: [riscv64] 475 484 os: [linux] 476 485 477 - '@esbuild/linux-riscv64@0.25.5': 478 - resolution: {integrity: sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==} 486 + '@esbuild/linux-riscv64@0.27.0': 487 + resolution: {integrity: sha512-pQdyAIZ0BWIC5GyvVFn5awDiO14TkT/19FTmFcPdDec94KJ1uZcmFs21Fo8auMXzD4Tt+diXu1LW1gHus9fhFQ==} 479 488 engines: {node: '>=18'} 480 489 cpu: [riscv64] 481 490 os: [linux] 482 491 483 - '@esbuild/linux-s390x@0.25.4': 484 - resolution: {integrity: sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==} 492 + '@esbuild/linux-s390x@0.25.12': 493 + resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} 485 494 engines: {node: '>=18'} 486 495 cpu: [s390x] 487 496 os: [linux] 488 497 489 - '@esbuild/linux-s390x@0.25.5': 490 - resolution: {integrity: sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==} 498 + '@esbuild/linux-s390x@0.27.0': 499 + resolution: {integrity: sha512-hPlRWR4eIDDEci953RI1BLZitgi5uqcsjKMxwYfmi4LcwyWo2IcRP+lThVnKjNtk90pLS8nKdroXYOqW+QQH+w==} 491 500 engines: {node: '>=18'} 492 501 cpu: [s390x] 493 502 os: [linux] 494 503 495 - '@esbuild/linux-x64@0.25.4': 496 - resolution: {integrity: sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==} 504 + '@esbuild/linux-x64@0.25.12': 505 + resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} 497 506 engines: {node: '>=18'} 498 507 cpu: [x64] 499 508 os: [linux] 500 509 501 - '@esbuild/linux-x64@0.25.5': 502 - resolution: {integrity: sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==} 510 + '@esbuild/linux-x64@0.27.0': 511 + resolution: {integrity: sha512-1hBWx4OUJE2cab++aVZ7pObD6s+DK4mPGpemtnAORBvb5l/g5xFGk0vc0PjSkrDs0XaXj9yyob3d14XqvnQ4gw==} 503 512 engines: {node: '>=18'} 504 513 cpu: [x64] 505 514 os: [linux] 506 515 507 - '@esbuild/netbsd-arm64@0.25.4': 508 - resolution: {integrity: sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==} 516 + '@esbuild/netbsd-arm64@0.25.12': 517 + resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} 509 518 engines: {node: '>=18'} 510 519 cpu: [arm64] 511 520 os: [netbsd] 512 521 513 - '@esbuild/netbsd-arm64@0.25.5': 514 - resolution: {integrity: sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==} 522 + '@esbuild/netbsd-arm64@0.27.0': 523 + resolution: {integrity: sha512-6m0sfQfxfQfy1qRuecMkJlf1cIzTOgyaeXaiVaaki8/v+WB+U4hc6ik15ZW6TAllRlg/WuQXxWj1jx6C+dfy3w==} 515 524 engines: {node: '>=18'} 516 525 cpu: [arm64] 517 526 os: [netbsd] 518 527 519 - '@esbuild/netbsd-x64@0.25.4': 520 - resolution: {integrity: sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==} 528 + '@esbuild/netbsd-x64@0.25.12': 529 + resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} 521 530 engines: {node: '>=18'} 522 531 cpu: [x64] 523 532 os: [netbsd] 524 533 525 - '@esbuild/netbsd-x64@0.25.5': 526 - resolution: {integrity: sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==} 534 + '@esbuild/netbsd-x64@0.27.0': 535 + resolution: {integrity: sha512-xbbOdfn06FtcJ9d0ShxxvSn2iUsGd/lgPIO2V3VZIPDbEaIj1/3nBBe1AwuEZKXVXkMmpr6LUAgMkLD/4D2PPA==} 527 536 engines: {node: '>=18'} 528 537 cpu: [x64] 529 538 os: [netbsd] 530 539 531 - '@esbuild/openbsd-arm64@0.25.4': 532 - resolution: {integrity: sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==} 540 + '@esbuild/openbsd-arm64@0.25.12': 541 + resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} 533 542 engines: {node: '>=18'} 534 543 cpu: [arm64] 535 544 os: [openbsd] 536 545 537 - '@esbuild/openbsd-arm64@0.25.5': 538 - resolution: {integrity: sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==} 546 + '@esbuild/openbsd-arm64@0.27.0': 547 + resolution: {integrity: sha512-fWgqR8uNbCQ/GGv0yhzttj6sU/9Z5/Sv/VGU3F5OuXK6J6SlriONKrQ7tNlwBrJZXRYk5jUhuWvF7GYzGguBZQ==} 539 548 engines: {node: '>=18'} 540 549 cpu: [arm64] 541 550 os: [openbsd] 542 551 543 - '@esbuild/openbsd-x64@0.25.4': 544 - resolution: {integrity: sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==} 552 + '@esbuild/openbsd-x64@0.25.12': 553 + resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} 545 554 engines: {node: '>=18'} 546 555 cpu: [x64] 547 556 os: [openbsd] 548 557 549 - '@esbuild/openbsd-x64@0.25.5': 550 - resolution: {integrity: sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==} 558 + '@esbuild/openbsd-x64@0.27.0': 559 + resolution: {integrity: sha512-aCwlRdSNMNxkGGqQajMUza6uXzR/U0dIl1QmLjPtRbLOx3Gy3otfFu/VjATy4yQzo9yFDGTxYDo1FfAD9oRD2A==} 551 560 engines: {node: '>=18'} 552 561 cpu: [x64] 553 562 os: [openbsd] 554 563 555 - '@esbuild/sunos-x64@0.25.4': 556 - resolution: {integrity: sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==} 564 + '@esbuild/openharmony-arm64@0.25.12': 565 + resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} 566 + engines: {node: '>=18'} 567 + cpu: [arm64] 568 + os: [openharmony] 569 + 570 + '@esbuild/openharmony-arm64@0.27.0': 571 + resolution: {integrity: sha512-nyvsBccxNAsNYz2jVFYwEGuRRomqZ149A39SHWk4hV0jWxKM0hjBPm3AmdxcbHiFLbBSwG6SbpIcUbXjgyECfA==} 572 + engines: {node: '>=18'} 573 + cpu: [arm64] 574 + os: [openharmony] 575 + 576 + '@esbuild/sunos-x64@0.25.12': 577 + resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} 557 578 engines: {node: '>=18'} 558 579 cpu: [x64] 559 580 os: [sunos] 560 581 561 - '@esbuild/sunos-x64@0.25.5': 562 - resolution: {integrity: sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==} 582 + '@esbuild/sunos-x64@0.27.0': 583 + resolution: {integrity: sha512-Q1KY1iJafM+UX6CFEL+F4HRTgygmEW568YMqDA5UV97AuZSm21b7SXIrRJDwXWPzr8MGr75fUZPV67FdtMHlHA==} 563 584 engines: {node: '>=18'} 564 585 cpu: [x64] 565 586 os: [sunos] 566 587 567 - '@esbuild/win32-arm64@0.25.4': 568 - resolution: {integrity: sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==} 588 + '@esbuild/win32-arm64@0.25.12': 589 + resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} 569 590 engines: {node: '>=18'} 570 591 cpu: [arm64] 571 592 os: [win32] 572 593 573 - '@esbuild/win32-arm64@0.25.5': 574 - resolution: {integrity: sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==} 594 + '@esbuild/win32-arm64@0.27.0': 595 + resolution: {integrity: sha512-W1eyGNi6d+8kOmZIwi/EDjrL9nxQIQ0MiGqe/AWc6+IaHloxHSGoeRgDRKHFISThLmsewZ5nHFvGFWdBYlgKPg==} 575 596 engines: {node: '>=18'} 576 597 cpu: [arm64] 577 598 os: [win32] 578 599 579 - '@esbuild/win32-ia32@0.25.4': 580 - resolution: {integrity: sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==} 600 + '@esbuild/win32-ia32@0.25.12': 601 + resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} 581 602 engines: {node: '>=18'} 582 603 cpu: [ia32] 583 604 os: [win32] 584 605 585 - '@esbuild/win32-ia32@0.25.5': 586 - resolution: {integrity: sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==} 606 + '@esbuild/win32-ia32@0.27.0': 607 + resolution: {integrity: sha512-30z1aKL9h22kQhilnYkORFYt+3wp7yZsHWus+wSKAJR8JtdfI76LJ4SBdMsCopTR3z/ORqVu5L1vtnHZWVj4cQ==} 587 608 engines: {node: '>=18'} 588 609 cpu: [ia32] 589 610 os: [win32] 590 611 591 - '@esbuild/win32-x64@0.25.4': 592 - resolution: {integrity: sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==} 612 + '@esbuild/win32-x64@0.25.12': 613 + resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} 593 614 engines: {node: '>=18'} 594 615 cpu: [x64] 595 616 os: [win32] 596 617 597 - '@esbuild/win32-x64@0.25.5': 598 - resolution: {integrity: sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==} 618 + '@esbuild/win32-x64@0.27.0': 619 + resolution: {integrity: sha512-aIitBcjQeyOhMTImhLZmtxfdOcuNRpwlPNmlFKPcHQYPhEssw75Cl1TSXJXpMkzaua9FUetx/4OQKq7eJul5Cg==} 599 620 engines: {node: '>=18'} 600 621 cpu: [x64] 601 622 os: [win32] ··· 604 625 resolution: {integrity: sha512-duvZBfJB9oOLphx04ckKF534hP186xIBFaw4GHJ5fGeZY5syZs59UeumV5NC6aiEU9hVhAFMOnDDGkQrFqHrnQ==} 605 626 peerDependencies: 606 627 solid-js: ^1.8.5 607 - 608 - '@fastify/busboy@2.1.1': 609 - resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} 610 - engines: {node: '>=14'} 611 628 612 629 '@img/sharp-darwin-arm64@0.33.5': 613 630 resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==} ··· 714 731 cpu: [x64] 715 732 os: [win32] 716 733 717 - '@isaacs/cliui@8.0.2': 718 - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} 719 - engines: {node: '>=12'} 734 + '@jridgewell/gen-mapping@0.3.13': 735 + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} 720 736 721 - '@jridgewell/gen-mapping@0.3.8': 722 - resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} 723 - engines: {node: '>=6.0.0'} 737 + '@jridgewell/remapping@2.3.5': 738 + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} 724 739 725 740 '@jridgewell/resolve-uri@3.1.2': 726 741 resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} 727 742 engines: {node: '>=6.0.0'} 728 743 729 - '@jridgewell/set-array@1.2.1': 730 - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} 731 - engines: {node: '>=6.0.0'} 732 - 733 - '@jridgewell/source-map@0.3.6': 734 - resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==} 744 + '@jridgewell/source-map@0.3.11': 745 + resolution: {integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==} 735 746 736 - '@jridgewell/sourcemap-codec@1.5.0': 737 - resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} 747 + '@jridgewell/sourcemap-codec@1.5.5': 748 + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} 738 749 739 - '@jridgewell/trace-mapping@0.3.25': 740 - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} 750 + '@jridgewell/trace-mapping@0.3.31': 751 + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} 741 752 742 753 '@jridgewell/trace-mapping@0.3.9': 743 754 resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} 744 755 745 - '@jsr/mary__array-fns@0.1.4': 746 - resolution: {integrity: sha512-+HbGYR9Ll5blEmAvVAoPejyGj01YeBbVmJ59qxaMDKt5i3F90ohYLA5a78y6AULDlet1IxYB+a/cMN+A0vGnDg==, tarball: https://npm.jsr.io/~/11/@jsr/mary__array-fns/0.1.4.tgz} 756 + '@jsr/mary__array-fns@0.1.5': 757 + resolution: {integrity: sha512-gI4scq/Hh9GtFUJfS8cvZf5nr+cs7udvrEpMv75grws5/0LIwBycKeeJcNi4+xNl6x4CGW6Fp46puhtJiQOpMg==, tarball: https://npm.jsr.io/~/11/@jsr/mary__array-fns/0.1.5.tgz} 747 758 748 - '@jsr/mary__ds-queue@0.1.2': 749 - resolution: {integrity: sha512-AOZ/FXYHVWI05bNHgi/Ln0RCiWvOQuZ/fZ1AxkT27Ytbon8VNtLAYs7uOgVITJcbMrsdE6zJXh/bP9LF16sk/A==, tarball: https://npm.jsr.io/~/11/@jsr/mary__ds-queue/0.1.2.tgz} 759 + '@jsr/mary__ds-queue@0.1.3': 760 + resolution: {integrity: sha512-gGqIHXiAmhUUtonNI6YVvL7VlXjEHUpGdc7RGU8BLP4XnFvqovDTH5y9VlBZmvozTWgTIMoZF6/1//sMrvYKtQ==, tarball: https://npm.jsr.io/~/11/@jsr/mary__ds-queue/0.1.3.tgz} 750 761 751 762 '@jsr/mary__events@0.2.0': 752 763 resolution: {integrity: sha512-WcBRbtuTno3zcfXKd7SEeKr1lAJF+CQ8BCv+PEEMmNKNqFurkEksGxRB3UDPZxIxjJ7sAqMVTL26wRuMpAcIeA==, tarball: https://npm.jsr.io/~/11/@jsr/mary__events/0.2.0.tgz} 753 764 754 - '@jsr/mary__tar@0.2.4': 755 - resolution: {integrity: sha512-jFjPcZj8DRSukPLZOt6+h74cVFdfdTMG9gzbW67YByCJTD52PEpe2sNcfCSw4mQ8hZBNgwiufCPyYL8hR9yicA==, tarball: https://npm.jsr.io/~/11/@jsr/mary__tar/0.2.4.tgz} 765 + '@jsr/mary__tar@0.3.1': 766 + resolution: {integrity: sha512-T803kucwCLVOXFJGzVbpkT5vRK6fARy5HL6xMiLK5hJFck72bsAeluENlRnvD0kFPSlFNp/5EJWfTHnpDK0qYA==, tarball: https://npm.jsr.io/~/11/@jsr/mary__tar/0.3.1.tgz} 756 767 757 - '@noble/secp256k1@2.2.3': 758 - resolution: {integrity: sha512-l7r5oEQym9Us7EAigzg30/PQAvynhMt2uoYtT3t26eGDVm9Yii5mZ5jWSWmZ/oSIR2Et0xfc6DXrG0bZ787V3w==} 768 + '@noble/secp256k1@3.0.0': 769 + resolution: {integrity: sha512-NJBaR352KyIvj3t6sgT/+7xrNyF9Xk9QlLSIqUGVUYlsnDTAUqY8LOmwpcgEx4AMJXRITQ5XEVHD+mMaPfr3mg==} 759 770 760 771 '@nodelib/fs.scandir@2.1.5': 761 772 resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} ··· 769 780 resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 770 781 engines: {node: '>= 8'} 771 782 772 - '@pkgjs/parseargs@0.11.0': 773 - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} 774 - engines: {node: '>=14'} 783 + '@poppinss/colors@4.1.5': 784 + resolution: {integrity: sha512-FvdDqtcRCtz6hThExcFOgW0cWX+xwSMWcRuQe5ZEb2m7cVQOAVZOIMt+/v9RxGiD9/OY16qJBXK4CVKWAPalBw==} 785 + 786 + '@poppinss/dumper@0.6.5': 787 + resolution: {integrity: sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw==} 788 + 789 + '@poppinss/exception@1.2.2': 790 + resolution: {integrity: sha512-m7bpKCD4QMlFCjA/nKTs23fuvoVFoA83brRKmObCUNmi/9tVu8Ve3w4YQAnJu4q3Tjf5fr685HYIC/IA2zHRSg==} 775 791 776 - '@rollup/rollup-android-arm-eabi@4.41.1': 777 - resolution: {integrity: sha512-NELNvyEWZ6R9QMkiytB4/L4zSEaBC03KIXEghptLGLZWJ6VPrL63ooZQCOnlx36aQPGhzuOMwDerC1Eb2VmrLw==} 792 + '@rollup/rollup-android-arm-eabi@4.53.3': 793 + resolution: {integrity: sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==} 778 794 cpu: [arm] 779 795 os: [android] 780 796 781 - '@rollup/rollup-android-arm64@4.41.1': 782 - resolution: {integrity: sha512-DXdQe1BJ6TK47ukAoZLehRHhfKnKg9BjnQYUu9gzhI8Mwa1d2fzxA1aw2JixHVl403bwp1+/o/NhhHtxWJBgEA==} 797 + '@rollup/rollup-android-arm64@4.53.3': 798 + resolution: {integrity: sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==} 783 799 cpu: [arm64] 784 800 os: [android] 785 801 786 - '@rollup/rollup-darwin-arm64@4.41.1': 787 - resolution: {integrity: sha512-5afxvwszzdulsU2w8JKWwY8/sJOLPzf0e1bFuvcW5h9zsEg+RQAojdW0ux2zyYAz7R8HvvzKCjLNJhVq965U7w==} 802 + '@rollup/rollup-darwin-arm64@4.53.3': 803 + resolution: {integrity: sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==} 788 804 cpu: [arm64] 789 805 os: [darwin] 790 806 791 - '@rollup/rollup-darwin-x64@4.41.1': 792 - resolution: {integrity: sha512-egpJACny8QOdHNNMZKf8xY0Is6gIMz+tuqXlusxquWu3F833DcMwmGM7WlvCO9sB3OsPjdC4U0wHw5FabzCGZg==} 807 + '@rollup/rollup-darwin-x64@4.53.3': 808 + resolution: {integrity: sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==} 793 809 cpu: [x64] 794 810 os: [darwin] 795 811 796 - '@rollup/rollup-freebsd-arm64@4.41.1': 797 - resolution: {integrity: sha512-DBVMZH5vbjgRk3r0OzgjS38z+atlupJ7xfKIDJdZZL6sM6wjfDNo64aowcLPKIx7LMQi8vybB56uh1Ftck/Atg==} 812 + '@rollup/rollup-freebsd-arm64@4.53.3': 813 + resolution: {integrity: sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==} 798 814 cpu: [arm64] 799 815 os: [freebsd] 800 816 801 - '@rollup/rollup-freebsd-x64@4.41.1': 802 - resolution: {integrity: sha512-3FkydeohozEskBxNWEIbPfOE0aqQgB6ttTkJ159uWOFn42VLyfAiyD9UK5mhu+ItWzft60DycIN1Xdgiy8o/SA==} 817 + '@rollup/rollup-freebsd-x64@4.53.3': 818 + resolution: {integrity: sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==} 803 819 cpu: [x64] 804 820 os: [freebsd] 805 821 806 - '@rollup/rollup-linux-arm-gnueabihf@4.41.1': 807 - resolution: {integrity: sha512-wC53ZNDgt0pqx5xCAgNunkTzFE8GTgdZ9EwYGVcg+jEjJdZGtq9xPjDnFgfFozQI/Xm1mh+D9YlYtl+ueswNEg==} 822 + '@rollup/rollup-linux-arm-gnueabihf@4.53.3': 823 + resolution: {integrity: sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==} 808 824 cpu: [arm] 809 825 os: [linux] 810 826 811 - '@rollup/rollup-linux-arm-musleabihf@4.41.1': 812 - resolution: {integrity: sha512-jwKCca1gbZkZLhLRtsrka5N8sFAaxrGz/7wRJ8Wwvq3jug7toO21vWlViihG85ei7uJTpzbXZRcORotE+xyrLA==} 827 + '@rollup/rollup-linux-arm-musleabihf@4.53.3': 828 + resolution: {integrity: sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==} 813 829 cpu: [arm] 814 830 os: [linux] 815 831 816 - '@rollup/rollup-linux-arm64-gnu@4.41.1': 817 - resolution: {integrity: sha512-g0UBcNknsmmNQ8V2d/zD2P7WWfJKU0F1nu0k5pW4rvdb+BIqMm8ToluW/eeRmxCared5dD76lS04uL4UaNgpNA==} 832 + '@rollup/rollup-linux-arm64-gnu@4.53.3': 833 + resolution: {integrity: sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==} 818 834 cpu: [arm64] 819 835 os: [linux] 820 836 821 - '@rollup/rollup-linux-arm64-musl@4.41.1': 822 - resolution: {integrity: sha512-XZpeGB5TKEZWzIrj7sXr+BEaSgo/ma/kCgrZgL0oo5qdB1JlTzIYQKel/RmhT6vMAvOdM2teYlAaOGJpJ9lahg==} 837 + '@rollup/rollup-linux-arm64-musl@4.53.3': 838 + resolution: {integrity: sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==} 823 839 cpu: [arm64] 824 840 os: [linux] 825 841 826 - '@rollup/rollup-linux-loongarch64-gnu@4.41.1': 827 - resolution: {integrity: sha512-bkCfDJ4qzWfFRCNt5RVV4DOw6KEgFTUZi2r2RuYhGWC8WhCA8lCAJhDeAmrM/fdiAH54m0mA0Vk2FGRPyzI+tw==} 842 + '@rollup/rollup-linux-loong64-gnu@4.53.3': 843 + resolution: {integrity: sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==} 828 844 cpu: [loong64] 829 845 os: [linux] 830 846 831 - '@rollup/rollup-linux-powerpc64le-gnu@4.41.1': 832 - resolution: {integrity: sha512-3mr3Xm+gvMX+/8EKogIZSIEF0WUu0HL9di+YWlJpO8CQBnoLAEL/roTCxuLncEdgcfJcvA4UMOf+2dnjl4Ut1A==} 847 + '@rollup/rollup-linux-ppc64-gnu@4.53.3': 848 + resolution: {integrity: sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==} 833 849 cpu: [ppc64] 834 850 os: [linux] 835 851 836 - '@rollup/rollup-linux-riscv64-gnu@4.41.1': 837 - resolution: {integrity: sha512-3rwCIh6MQ1LGrvKJitQjZFuQnT2wxfU+ivhNBzmxXTXPllewOF7JR1s2vMX/tWtUYFgphygxjqMl76q4aMotGw==} 852 + '@rollup/rollup-linux-riscv64-gnu@4.53.3': 853 + resolution: {integrity: sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==} 838 854 cpu: [riscv64] 839 855 os: [linux] 840 856 841 - '@rollup/rollup-linux-riscv64-musl@4.41.1': 842 - resolution: {integrity: sha512-LdIUOb3gvfmpkgFZuccNa2uYiqtgZAz3PTzjuM5bH3nvuy9ty6RGc/Q0+HDFrHrizJGVpjnTZ1yS5TNNjFlklw==} 857 + '@rollup/rollup-linux-riscv64-musl@4.53.3': 858 + resolution: {integrity: sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==} 843 859 cpu: [riscv64] 844 860 os: [linux] 845 861 846 - '@rollup/rollup-linux-s390x-gnu@4.41.1': 847 - resolution: {integrity: sha512-oIE6M8WC9ma6xYqjvPhzZYk6NbobIURvP/lEbh7FWplcMO6gn7MM2yHKA1eC/GvYwzNKK/1LYgqzdkZ8YFxR8g==} 862 + '@rollup/rollup-linux-s390x-gnu@4.53.3': 863 + resolution: {integrity: sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==} 848 864 cpu: [s390x] 849 865 os: [linux] 850 866 851 - '@rollup/rollup-linux-x64-gnu@4.41.1': 852 - resolution: {integrity: sha512-cWBOvayNvA+SyeQMp79BHPK8ws6sHSsYnK5zDcsC3Hsxr1dgTABKjMnMslPq1DvZIp6uO7kIWhiGwaTdR4Og9A==} 867 + '@rollup/rollup-linux-x64-gnu@4.53.3': 868 + resolution: {integrity: sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==} 853 869 cpu: [x64] 854 870 os: [linux] 855 871 856 - '@rollup/rollup-linux-x64-musl@4.41.1': 857 - resolution: {integrity: sha512-y5CbN44M+pUCdGDlZFzGGBSKCA4A/J2ZH4edTYSSxFg7ce1Xt3GtydbVKWLlzL+INfFIZAEg1ZV6hh9+QQf9YQ==} 872 + '@rollup/rollup-linux-x64-musl@4.53.3': 873 + resolution: {integrity: sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==} 858 874 cpu: [x64] 859 875 os: [linux] 860 876 861 - '@rollup/rollup-win32-arm64-msvc@4.41.1': 862 - resolution: {integrity: sha512-lZkCxIrjlJlMt1dLO/FbpZbzt6J/A8p4DnqzSa4PWqPEUUUnzXLeki/iyPLfV0BmHItlYgHUqJe+3KiyydmiNQ==} 877 + '@rollup/rollup-openharmony-arm64@4.53.3': 878 + resolution: {integrity: sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==} 879 + cpu: [arm64] 880 + os: [openharmony] 881 + 882 + '@rollup/rollup-win32-arm64-msvc@4.53.3': 883 + resolution: {integrity: sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==} 863 884 cpu: [arm64] 864 885 os: [win32] 865 886 866 - '@rollup/rollup-win32-ia32-msvc@4.41.1': 867 - resolution: {integrity: sha512-+psFT9+pIh2iuGsxFYYa/LhS5MFKmuivRsx9iPJWNSGbh2XVEjk90fmpUEjCnILPEPJnikAU6SFDiEUyOv90Pg==} 887 + '@rollup/rollup-win32-ia32-msvc@4.53.3': 888 + resolution: {integrity: sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==} 868 889 cpu: [ia32] 869 890 os: [win32] 870 891 871 - '@rollup/rollup-win32-x64-msvc@4.41.1': 872 - resolution: {integrity: sha512-Wq2zpapRYLfi4aKxf2Xff0tN+7slj2d4R87WEzqw7ZLsVvO5zwYCIuEGSZYiK41+GlwUo1HiR+GdkLEJnCKTCw==} 892 + '@rollup/rollup-win32-x64-gnu@4.53.3': 893 + resolution: {integrity: sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==} 894 + cpu: [x64] 895 + os: [win32] 896 + 897 + '@rollup/rollup-win32-x64-msvc@4.53.3': 898 + resolution: {integrity: sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==} 873 899 cpu: [x64] 874 900 os: [win32] 875 901 902 + '@sindresorhus/is@7.1.1': 903 + resolution: {integrity: sha512-rO92VvpgMc3kfiTjGT52LEtJ8Yc5kCWhZjLQ3LwlA4pSgPpQO7bVpYXParOD8Jwf+cVQECJo3yP/4I8aZtUQTQ==} 904 + engines: {node: '>=18'} 905 + 906 + '@speed-highlight/core@1.2.12': 907 + resolution: {integrity: sha512-uilwrK0Ygyri5dToHYdZSjcvpS2ZwX0w5aSt3GCEN9hrjxWCoeV4Z2DTXuxjwbntaLQIEEAlCeNQss5SoHvAEA==} 908 + 909 + '@standard-schema/spec@1.0.0': 910 + resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==} 911 + 876 912 '@tailwindcss/forms@0.5.10': 877 913 resolution: {integrity: sha512-utI1ONF6uf/pPNO68kmN1b8rEwNXv3czukalo8VtJH8ksIkZXr3Q3VYudZLkCsDd4Wku120uF02hYK25XGPorw==} 878 914 peerDependencies: ··· 887 923 '@types/babel__template@7.4.4': 888 924 resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} 889 925 890 - '@types/babel__traverse@7.20.7': 891 - resolution: {integrity: sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==} 926 + '@types/babel__traverse@7.28.0': 927 + resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} 892 928 893 - '@types/estree@1.0.7': 894 - resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} 929 + '@types/estree@1.0.8': 930 + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} 895 931 896 - '@types/node@22.15.21': 897 - resolution: {integrity: sha512-EV/37Td6c+MgKAbkcLG6vqZ2zEYHD7bvSrzqqs2RIhbA6w3x+Dqz8MZM3sP6kGTeLrdoOgKZe+Xja7tUB2DNkQ==} 932 + '@types/node@22.19.2': 933 + resolution: {integrity: sha512-LPM2G3Syo1GLzXLGJAKdqoU35XvrWzGJ21/7sgZTUpbkBaOasTj8tjwn6w+hCkqaa1TfJ/w67rJSwYItlJ2mYw==} 898 934 899 935 acorn-walk@8.3.2: 900 936 resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} ··· 905 941 engines: {node: '>=0.4.0'} 906 942 hasBin: true 907 943 908 - acorn@8.14.1: 909 - resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} 944 + acorn@8.15.0: 945 + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} 910 946 engines: {node: '>=0.4.0'} 911 947 hasBin: true 912 948 913 - ansi-regex@5.0.1: 914 - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 915 - engines: {node: '>=8'} 916 - 917 - ansi-regex@6.1.0: 918 - resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} 919 - engines: {node: '>=12'} 920 - 921 - ansi-styles@4.3.0: 922 - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 923 - engines: {node: '>=8'} 924 - 925 - ansi-styles@6.2.1: 926 - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} 927 - engines: {node: '>=12'} 928 - 929 949 any-promise@1.3.0: 930 950 resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} 931 951 ··· 936 956 arg@5.0.2: 937 957 resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} 938 958 939 - as-table@1.0.55: 940 - resolution: {integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==} 941 - 942 - autoprefixer@10.4.21: 943 - resolution: {integrity: sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==} 959 + autoprefixer@10.4.22: 960 + resolution: {integrity: sha512-ARe0v/t9gO28Bznv6GgqARmVqcWOV3mfgUPn9becPHMiD3o9BwlRgaeccZnwTpZ7Zwqrm+c1sUSsMxIzQzc8Xg==} 944 961 engines: {node: ^10 || ^12 || >=14} 945 962 hasBin: true 946 963 peerDependencies: 947 964 postcss: ^8.1.0 948 965 949 - babel-plugin-jsx-dom-expressions@0.39.8: 950 - resolution: {integrity: sha512-/MVOIIjonylDXnrWmG23ZX82m9mtKATsVHB7zYlPfDR9Vdd/NBE48if+wv27bSkBtyO7EPMUlcUc4J63QwuACQ==} 966 + babel-plugin-jsx-dom-expressions@0.40.3: 967 + resolution: {integrity: sha512-5HOwwt0BYiv/zxl7j8Pf2bGL6rDXfV6nUhLs8ygBX+EFJXzBPHM/euj9j/6deMZ6wa52Wb2PBaAV5U/jKwIY1w==} 951 968 peerDependencies: 952 969 '@babel/core': ^7.20.12 953 970 954 - babel-preset-solid@1.9.6: 955 - resolution: {integrity: sha512-HXTK9f93QxoH8dYn1M2mJdOlWgMsR88Lg/ul6QCZGkNTktjTE5HAf93YxQumHoCudLEtZrU1cFCMFOVho6GqFg==} 971 + babel-preset-solid@1.9.10: 972 + resolution: {integrity: sha512-HCelrgua/Y+kqO8RyL04JBWS/cVdrtUv/h45GntgQY+cJl4eBcKkCDV3TdMjtKx1nXwRaR9QXslM/Npm1dxdZQ==} 956 973 peerDependencies: 957 974 '@babel/core': ^7.0.0 975 + solid-js: ^1.9.10 976 + peerDependenciesMeta: 977 + solid-js: 978 + optional: true 958 979 959 - balanced-match@1.0.2: 960 - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 980 + baseline-browser-mapping@2.9.5: 981 + resolution: {integrity: sha512-D5vIoztZOq1XM54LUdttJVc96ggEsIfju2JBvht06pSzpckp3C7HReun67Bghzrtdsq9XdMGbSSB3v3GhMNmAA==} 982 + hasBin: true 961 983 962 984 binary-extensions@2.3.0: 963 985 resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} ··· 966 988 blake3-wasm@2.1.5: 967 989 resolution: {integrity: sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==} 968 990 969 - brace-expansion@2.0.1: 970 - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} 971 - 972 991 braces@3.0.3: 973 992 resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} 974 993 engines: {node: '>=8'} 975 994 976 - browserslist@4.24.5: 977 - resolution: {integrity: sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==} 995 + browserslist@4.28.1: 996 + resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} 978 997 engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} 979 998 hasBin: true 980 999 ··· 985 1004 resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} 986 1005 engines: {node: '>= 6'} 987 1006 988 - caniuse-lite@1.0.30001718: 989 - resolution: {integrity: sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==} 1007 + caniuse-lite@1.0.30001760: 1008 + resolution: {integrity: sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw==} 990 1009 991 1010 chokidar@3.6.0: 992 1011 resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} ··· 1016 1035 convert-source-map@2.0.0: 1017 1036 resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} 1018 1037 1019 - cookie@0.7.2: 1020 - resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} 1021 - engines: {node: '>= 0.6'} 1022 - 1023 - cross-spawn@7.0.6: 1024 - resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} 1025 - engines: {node: '>= 8'} 1038 + cookie@1.1.1: 1039 + resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} 1040 + engines: {node: '>=18'} 1026 1041 1027 1042 cssesc@3.0.0: 1028 1043 resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} 1029 1044 engines: {node: '>=4'} 1030 1045 hasBin: true 1031 1046 1032 - csstype@3.1.3: 1033 - resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} 1047 + csstype@3.2.3: 1048 + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} 1034 1049 1035 - data-uri-to-buffer@2.0.2: 1036 - resolution: {integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==} 1037 - 1038 - debug@4.4.1: 1039 - resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} 1050 + debug@4.4.3: 1051 + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} 1040 1052 engines: {node: '>=6.0'} 1041 1053 peerDependencies: 1042 1054 supports-color: '*' ··· 1044 1056 supports-color: 1045 1057 optional: true 1046 1058 1047 - defu@6.1.4: 1048 - resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} 1049 - 1050 - detect-libc@2.0.4: 1051 - resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==} 1059 + detect-libc@2.1.2: 1060 + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} 1052 1061 engines: {node: '>=8'} 1053 1062 1054 1063 didyoumean@1.2.2: ··· 1057 1066 dlv@1.1.3: 1058 1067 resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} 1059 1068 1060 - eastasianwidth@0.2.0: 1061 - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} 1062 - 1063 - electron-to-chromium@1.5.158: 1064 - resolution: {integrity: sha512-9vcp2xHhkvraY6AHw2WMi+GDSLPX42qe2xjYaVoZqFRJiOcilVQFq9mZmpuHEQpzlgGDelKlV7ZiGcmMsc8WxQ==} 1065 - 1066 - emoji-regex@8.0.0: 1067 - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} 1068 - 1069 - emoji-regex@9.2.2: 1070 - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} 1069 + electron-to-chromium@1.5.267: 1070 + resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==} 1071 1071 1072 - entities@6.0.0: 1073 - resolution: {integrity: sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==} 1072 + entities@6.0.1: 1073 + resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} 1074 1074 engines: {node: '>=0.12'} 1075 1075 1076 - esbuild@0.25.4: 1077 - resolution: {integrity: sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==} 1076 + error-stack-parser-es@1.0.5: 1077 + resolution: {integrity: sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==} 1078 + 1079 + esbuild@0.25.12: 1080 + resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} 1078 1081 engines: {node: '>=18'} 1079 1082 hasBin: true 1080 1083 1081 - esbuild@0.25.5: 1082 - resolution: {integrity: sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==} 1084 + esbuild@0.27.0: 1085 + resolution: {integrity: sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA==} 1083 1086 engines: {node: '>=18'} 1084 1087 hasBin: true 1085 1088 ··· 1094 1097 resolution: {integrity: sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==} 1095 1098 engines: {node: '>=6'} 1096 1099 1097 - exsolve@1.0.5: 1098 - resolution: {integrity: sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg==} 1099 - 1100 1100 fast-glob@3.3.3: 1101 1101 resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} 1102 1102 engines: {node: '>=8.6.0'} ··· 1104 1104 fastq@1.19.1: 1105 1105 resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} 1106 1106 1107 - fdir@6.4.4: 1108 - resolution: {integrity: sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==} 1107 + fdir@6.5.0: 1108 + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} 1109 + engines: {node: '>=12.0.0'} 1109 1110 peerDependencies: 1110 1111 picomatch: ^3 || ^4 1111 1112 peerDependenciesMeta: ··· 1120 1121 resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} 1121 1122 engines: {node: '>=8'} 1122 1123 1123 - foreground-child@3.3.1: 1124 - resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} 1125 - engines: {node: '>=14'} 1126 - 1127 - fraction.js@4.3.7: 1128 - resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} 1124 + fraction.js@5.3.4: 1125 + resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==} 1129 1126 1130 1127 fsevents@2.3.3: 1131 1128 resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} ··· 1139 1136 resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} 1140 1137 engines: {node: '>=6.9.0'} 1141 1138 1142 - get-source@2.0.12: 1143 - resolution: {integrity: sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==} 1144 - 1145 1139 glob-parent@5.1.2: 1146 1140 resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 1147 1141 engines: {node: '>= 6'} ··· 1153 1147 glob-to-regexp@0.4.1: 1154 1148 resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} 1155 1149 1156 - glob@10.4.5: 1157 - resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} 1158 - hasBin: true 1159 - 1160 - globals@11.12.0: 1161 - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} 1162 - engines: {node: '>=4'} 1163 - 1164 1150 hasown@2.0.2: 1165 1151 resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} 1166 1152 engines: {node: '>= 0.4'} ··· 1168 1154 html-entities@2.3.3: 1169 1155 resolution: {integrity: sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==} 1170 1156 1171 - is-arrayish@0.3.2: 1172 - resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} 1157 + is-arrayish@0.3.4: 1158 + resolution: {integrity: sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==} 1173 1159 1174 1160 is-binary-path@2.1.0: 1175 1161 resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} ··· 1183 1169 resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 1184 1170 engines: {node: '>=0.10.0'} 1185 1171 1186 - is-fullwidth-code-point@3.0.0: 1187 - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} 1188 - engines: {node: '>=8'} 1189 - 1190 1172 is-glob@4.0.3: 1191 1173 resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 1192 1174 engines: {node: '>=0.10.0'} ··· 1199 1181 resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} 1200 1182 engines: {node: '>=12.13'} 1201 1183 1202 - isexe@2.0.0: 1203 - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 1204 - 1205 - jackspeak@3.4.3: 1206 - resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} 1207 - 1208 1184 jiti@1.21.7: 1209 1185 resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==} 1210 1186 hasBin: true ··· 1221 1197 resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} 1222 1198 engines: {node: '>=6'} 1223 1199 hasBin: true 1200 + 1201 + kleur@4.1.5: 1202 + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} 1203 + engines: {node: '>=6'} 1224 1204 1225 1205 lilconfig@3.1.3: 1226 1206 resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} ··· 1229 1209 lines-and-columns@1.2.4: 1230 1210 resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} 1231 1211 1232 - lru-cache@10.4.3: 1233 - resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} 1234 - 1235 1212 lru-cache@5.1.1: 1236 1213 resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} 1237 1214 ··· 1256 1233 resolution: {integrity: sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==} 1257 1234 hasBin: true 1258 1235 1259 - miniflare@4.20250508.3: 1260 - resolution: {integrity: sha512-43oTmZ0CCmUcieetI5YDDyX0IiwhOcVIWzdBBCqWXK3F1XgQwg4d3fTqRyJnCmHIoaYx9CE1kTEKZC1UahPQhA==} 1236 + miniflare@4.20251202.1: 1237 + resolution: {integrity: sha512-cRp2QNgnt9wpLMoNs4MOzzomyfe9UTS9sPRxIpUvxMl+mweCZ0FHpWWQvCnU7wWlfAP8VGZrHwqSsV5ERA6ahQ==} 1261 1238 engines: {node: '>=18.0.0'} 1262 1239 hasBin: true 1263 1240 1264 - minimatch@9.0.5: 1265 - resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} 1266 - engines: {node: '>=16 || 14 >=14.17'} 1267 - 1268 - minipass@7.1.2: 1269 - resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} 1270 - engines: {node: '>=16 || 14 >=14.17'} 1271 - 1272 1241 ms@2.1.3: 1273 1242 resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} 1274 1243 1275 - mustache@4.2.0: 1276 - resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==} 1277 - hasBin: true 1278 - 1279 1244 mz@2.7.0: 1280 1245 resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} 1281 1246 ··· 1284 1249 engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 1285 1250 hasBin: true 1286 1251 1287 - nanoid@5.1.5: 1288 - resolution: {integrity: sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==} 1252 + nanoid@5.1.6: 1253 + resolution: {integrity: sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==} 1289 1254 engines: {node: ^18 || >=20} 1290 1255 hasBin: true 1291 1256 ··· 1298 1263 engines: {node: '>=10.5.0'} 1299 1264 deprecated: Use your platform's native DOMException instead 1300 1265 1301 - node-releases@2.0.19: 1302 - resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} 1266 + node-releases@2.0.27: 1267 + resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} 1303 1268 1304 1269 normalize-path@3.0.0: 1305 1270 resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} ··· 1316 1281 object-hash@3.0.0: 1317 1282 resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} 1318 1283 engines: {node: '>= 6'} 1319 - 1320 - ohash@2.0.11: 1321 - resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==} 1322 - 1323 - package-json-from-dist@1.0.1: 1324 - resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} 1325 1284 1326 1285 parse5@7.3.0: 1327 1286 resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} 1328 1287 1329 - path-key@3.1.1: 1330 - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 1331 - engines: {node: '>=8'} 1332 - 1333 1288 path-parse@1.0.7: 1334 1289 resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} 1335 - 1336 - path-scurry@1.11.1: 1337 - resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} 1338 - engines: {node: '>=16 || 14 >=14.18'} 1339 1290 1340 1291 path-to-regexp@6.3.0: 1341 1292 resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==} ··· 1350 1301 resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 1351 1302 engines: {node: '>=8.6'} 1352 1303 1353 - picomatch@4.0.2: 1354 - resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} 1304 + picomatch@4.0.3: 1305 + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} 1355 1306 engines: {node: '>=12'} 1356 1307 1357 1308 pify@2.3.0: ··· 1368 1319 peerDependencies: 1369 1320 postcss: ^8.0.0 1370 1321 1371 - postcss-js@4.0.1: 1372 - resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} 1322 + postcss-js@4.1.0: 1323 + resolution: {integrity: sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==} 1373 1324 engines: {node: ^12 || ^14 || >= 16} 1374 1325 peerDependencies: 1375 1326 postcss: ^8.4.21 1376 1327 1377 - postcss-load-config@4.0.2: 1378 - resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} 1379 - engines: {node: '>= 14'} 1328 + postcss-load-config@6.0.1: 1329 + resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} 1330 + engines: {node: '>= 18'} 1380 1331 peerDependencies: 1332 + jiti: '>=1.21.0' 1381 1333 postcss: '>=8.0.9' 1382 - ts-node: '>=9.0.0' 1334 + tsx: ^4.8.1 1335 + yaml: ^2.4.2 1383 1336 peerDependenciesMeta: 1337 + jiti: 1338 + optional: true 1384 1339 postcss: 1385 1340 optional: true 1386 - ts-node: 1341 + tsx: 1342 + optional: true 1343 + yaml: 1387 1344 optional: true 1388 1345 1389 1346 postcss-nested@6.2.0: ··· 1399 1356 postcss-value-parser@4.2.0: 1400 1357 resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} 1401 1358 1402 - postcss@8.5.3: 1403 - resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} 1359 + postcss@8.5.6: 1360 + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} 1404 1361 engines: {node: ^10 || ^12 || >=14} 1405 1362 1406 - prettier-plugin-tailwindcss@0.6.11: 1407 - resolution: {integrity: sha512-YxaYSIvZPAqhrrEpRtonnrXdghZg1irNg4qrjboCXrpybLWVs55cW2N3juhspVJiO0JBvYJT8SYsJpc8OQSnsA==} 1363 + prettier-plugin-tailwindcss@0.6.14: 1364 + resolution: {integrity: sha512-pi2e/+ZygeIqntN+vC573BcW5Cve8zUB0SSAGxqpB4f96boZF4M3phPVoOFCeypwkpRYdi7+jQ5YJJUwrkGUAg==} 1408 1365 engines: {node: '>=14.21.3'} 1409 1366 peerDependencies: 1410 1367 '@ianvs/prettier-plugin-sort-imports': '*' 1368 + '@prettier/plugin-hermes': '*' 1369 + '@prettier/plugin-oxc': '*' 1411 1370 '@prettier/plugin-pug': '*' 1412 1371 '@shopify/prettier-plugin-liquid': '*' 1413 1372 '@trivago/prettier-plugin-sort-imports': '*' ··· 1426 1385 prettier-plugin-svelte: '*' 1427 1386 peerDependenciesMeta: 1428 1387 '@ianvs/prettier-plugin-sort-imports': 1388 + optional: true 1389 + '@prettier/plugin-hermes': 1390 + optional: true 1391 + '@prettier/plugin-oxc': 1429 1392 optional: true 1430 1393 '@prettier/plugin-pug': 1431 1394 optional: true ··· 1458 1421 prettier-plugin-svelte: 1459 1422 optional: true 1460 1423 1461 - prettier@3.5.3: 1462 - resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==} 1424 + prettier@3.7.4: 1425 + resolution: {integrity: sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==} 1463 1426 engines: {node: '>=14'} 1464 1427 hasBin: true 1465 1428 1466 - printable-characters@1.0.42: 1467 - resolution: {integrity: sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==} 1468 - 1469 1429 queue-microtask@1.2.3: 1470 1430 resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 1471 1431 ··· 1476 1436 resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} 1477 1437 engines: {node: '>=8.10.0'} 1478 1438 1479 - resolve@1.22.10: 1480 - resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} 1439 + resolve@1.22.11: 1440 + resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} 1481 1441 engines: {node: '>= 0.4'} 1482 1442 hasBin: true 1483 1443 ··· 1485 1445 resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} 1486 1446 engines: {iojs: '>=1.0.0', node: '>=0.10.0'} 1487 1447 1488 - rollup@4.41.1: 1489 - resolution: {integrity: sha512-cPmwD3FnFv8rKMBc1MxWCwVQFxwf1JEmSX3iQXrRVVG15zerAIXRjMFVWnd5Q5QvgKF7Aj+5ykXFhUl+QGnyOw==} 1448 + rollup@4.53.3: 1449 + resolution: {integrity: sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==} 1490 1450 engines: {node: '>=18.0.0', npm: '>=8.0.0'} 1491 1451 hasBin: true 1492 1452 ··· 1497 1457 resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} 1498 1458 hasBin: true 1499 1459 1500 - semver@7.7.2: 1501 - resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} 1460 + semver@7.7.3: 1461 + resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} 1502 1462 engines: {node: '>=10'} 1503 1463 hasBin: true 1504 1464 1505 - seroval-plugins@1.3.2: 1506 - resolution: {integrity: sha512-0QvCV2lM3aj/U3YozDiVwx9zpH0q8A60CTWIv4Jszj/givcudPb48B+rkU5D51NJ0pTpweGMttHjboPa9/zoIQ==} 1465 + seroval-plugins@1.3.3: 1466 + resolution: {integrity: sha512-16OL3NnUBw8JG1jBLUoZJsLnQq0n5Ua6aHalhJK4fMQkz1lqR7Osz1sA30trBtd9VUDc2NgkuRCn8+/pBwqZ+w==} 1507 1467 engines: {node: '>=10'} 1508 1468 peerDependencies: 1509 1469 seroval: ^1.0 ··· 1516 1476 resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==} 1517 1477 engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 1518 1478 1519 - shebang-command@2.0.0: 1520 - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 1521 - engines: {node: '>=8'} 1479 + simple-swizzle@0.2.4: 1480 + resolution: {integrity: sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==} 1522 1481 1523 - shebang-regex@3.0.0: 1524 - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 1525 - engines: {node: '>=8'} 1526 - 1527 - signal-exit@4.1.0: 1528 - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} 1529 - engines: {node: '>=14'} 1530 - 1531 - simple-swizzle@0.2.2: 1532 - resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} 1533 - 1534 - solid-js@1.9.7: 1535 - resolution: {integrity: sha512-/saTKi8iWEM233n5OSi1YHCCuh66ZIQ7aK2hsToPe4tqGm7qAejU1SwNuTPivbWAYq7SjuHVVYxxuZQNRbICiw==} 1482 + solid-js@1.9.10: 1483 + resolution: {integrity: sha512-Coz956cos/EPDlhs6+jsdTxKuJDPT7B5SVIWgABwROyxjY7Xbr8wkzD68Et+NxnV7DLJ3nJdAC2r9InuV/4Jew==} 1536 1484 1537 1485 solid-refresh@0.6.3: 1538 1486 resolution: {integrity: sha512-F3aPsX6hVw9ttm5LYlth8Q15x6MlI/J3Dn+o3EQyRTtTxidepSTwAYdozt01/YA+7ObcciagGEyXIopGZzQtbA==} ··· 1550 1498 resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} 1551 1499 engines: {node: '>=0.10.0'} 1552 1500 1553 - stacktracey@2.1.8: 1554 - resolution: {integrity: sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==} 1555 - 1556 1501 stoppable@1.1.0: 1557 1502 resolution: {integrity: sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==} 1558 1503 engines: {node: '>=4', npm: '>=6'} 1559 1504 1560 - string-width@4.2.3: 1561 - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} 1562 - engines: {node: '>=8'} 1563 - 1564 - string-width@5.1.2: 1565 - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} 1566 - engines: {node: '>=12'} 1567 - 1568 - strip-ansi@6.0.1: 1569 - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 1570 - engines: {node: '>=8'} 1571 - 1572 - strip-ansi@7.1.0: 1573 - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} 1574 - engines: {node: '>=12'} 1575 - 1576 - sucrase@3.35.0: 1577 - resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} 1505 + sucrase@3.35.1: 1506 + resolution: {integrity: sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==} 1578 1507 engines: {node: '>=16 || 14 >=14.17'} 1579 1508 hasBin: true 1509 + 1510 + supports-color@10.2.2: 1511 + resolution: {integrity: sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==} 1512 + engines: {node: '>=18'} 1580 1513 1581 1514 supports-preserve-symlinks-flag@1.0.0: 1582 1515 resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} 1583 1516 engines: {node: '>= 0.4'} 1584 1517 1585 - tailwindcss@3.4.17: 1586 - resolution: {integrity: sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==} 1518 + tailwindcss@3.4.18: 1519 + resolution: {integrity: sha512-6A2rnmW5xZMdw11LYjhcI5846rt9pbLSabY5XPxo+XWdxwZaFEn47Go4NzFiHu9sNNmr/kXivP1vStfvMaK1GQ==} 1587 1520 engines: {node: '>=14.0.0'} 1588 1521 hasBin: true 1589 1522 1590 - terser@5.39.2: 1591 - resolution: {integrity: sha512-yEPUmWve+VA78bI71BW70Dh0TuV4HHd+I5SHOAfS1+QBOmvmCiiffgjR8ryyEd3KIfvPGFqoADt8LdQ6XpXIvg==} 1523 + terser@5.44.1: 1524 + resolution: {integrity: sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==} 1592 1525 engines: {node: '>=10'} 1593 1526 hasBin: true 1594 1527 ··· 1599 1532 thenify@3.3.1: 1600 1533 resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} 1601 1534 1602 - tinyglobby@0.2.14: 1603 - resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} 1535 + tinyglobby@0.2.15: 1536 + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} 1604 1537 engines: {node: '>=12.0.0'} 1605 1538 1606 1539 to-regex-range@5.0.1: ··· 1613 1546 tslib@2.8.1: 1614 1547 resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} 1615 1548 1616 - typescript@5.8.3: 1617 - resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} 1549 + typescript@5.9.3: 1550 + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} 1618 1551 engines: {node: '>=14.17'} 1619 1552 hasBin: true 1620 1553 1621 - ufo@1.6.1: 1622 - resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==} 1623 - 1624 1554 undici-types@6.21.0: 1625 1555 resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} 1626 1556 1627 - undici@5.29.0: 1628 - resolution: {integrity: sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==} 1629 - engines: {node: '>=14.0'} 1557 + undici@7.14.0: 1558 + resolution: {integrity: sha512-Vqs8HTzjpQXZeXdpsfChQTlafcMQaaIwnGwLam1wudSSjlJeQ3bw1j+TLPePgrCnCpUXx7Ba5Pdpf5OBih62NQ==} 1559 + engines: {node: '>=20.18.1'} 1630 1560 1631 - unenv@2.0.0-rc.17: 1632 - resolution: {integrity: sha512-B06u0wXkEd+o5gOCMl/ZHl5cfpYbDZKAT+HWTL+Hws6jWu7dCiqBBXXXzMFcFVJb8D4ytAnYmxJA83uwOQRSsg==} 1561 + unenv@2.0.0-rc.24: 1562 + resolution: {integrity: sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==} 1633 1563 1634 - update-browserslist-db@1.1.3: 1635 - resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} 1564 + update-browserslist-db@1.2.2: 1565 + resolution: {integrity: sha512-E85pfNzMQ9jpKkA7+TJAi4TJN+tBCuWh5rUcS/sv6cFi+1q9LYDwDI5dpUL0u/73EElyQ8d3TEaeW4sPedBqYA==} 1636 1566 hasBin: true 1637 1567 peerDependencies: 1638 1568 browserslist: '>= 4.21.0' ··· 1640 1570 util-deprecate@1.0.2: 1641 1571 resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} 1642 1572 1643 - validate-html-nesting@1.2.2: 1644 - resolution: {integrity: sha512-hGdgQozCsQJMyfK5urgFcWEqsSSrK63Awe0t/IMR0bZ0QMtnuaiHzThW81guu3qx9abLi99NEuiaN6P9gVYsNg==} 1645 - 1646 - vite-plugin-solid@2.11.6: 1647 - resolution: {integrity: sha512-Sl5CTqJTGyEeOsmdH6BOgalIZlwH3t4/y0RQuFLMGnvWMBvxb4+lq7x3BSiAw6etf0QexfNJW7HSOO/Qf7pigg==} 1573 + vite-plugin-solid@2.11.10: 1574 + resolution: {integrity: sha512-Yr1dQybmtDtDAHkii6hXuc1oVH9CPcS/Zb2jN/P36qqcrkNnVPsMTzQ06jyzFPFjj3U1IYKMVt/9ZqcwGCEbjw==} 1648 1575 peerDependencies: 1649 1576 '@testing-library/jest-dom': ^5.16.6 || ^5.17.0 || ^6.* 1650 1577 solid-js: ^1.7.2 1651 - vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 1578 + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 1652 1579 peerDependenciesMeta: 1653 1580 '@testing-library/jest-dom': 1654 1581 optional: true 1655 1582 1656 - vite@6.3.5: 1657 - resolution: {integrity: sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==} 1658 - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} 1583 + vite@7.2.7: 1584 + resolution: {integrity: sha512-ITcnkFeR3+fI8P1wMgItjGrR10170d8auB4EpMLPqmx6uxElH3a/hHGQabSHKdqd4FXWO1nFIp9rRn7JQ34ACQ==} 1585 + engines: {node: ^20.19.0 || >=22.12.0} 1659 1586 hasBin: true 1660 1587 peerDependencies: 1661 - '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 1588 + '@types/node': ^20.19.0 || >=22.12.0 1662 1589 jiti: '>=1.21.0' 1663 - less: '*' 1590 + less: ^4.0.0 1664 1591 lightningcss: ^1.21.0 1665 - sass: '*' 1666 - sass-embedded: '*' 1667 - stylus: '*' 1668 - sugarss: '*' 1592 + sass: ^1.70.0 1593 + sass-embedded: ^1.70.0 1594 + stylus: '>=0.54.8' 1595 + sugarss: ^5.0.0 1669 1596 terser: ^5.16.0 1670 1597 tsx: ^4.8.1 1671 1598 yaml: ^2.4.2 ··· 1693 1620 yaml: 1694 1621 optional: true 1695 1622 1696 - vitefu@1.0.6: 1697 - resolution: {integrity: sha512-+Rex1GlappUyNN6UfwbVZne/9cYC4+R2XDk9xkNXBKMw6HQagdX9PgZ8V2v1WUSK1wfBLp7qbI1+XSNIlB1xmA==} 1623 + vitefu@1.1.1: 1624 + resolution: {integrity: sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==} 1698 1625 peerDependencies: 1699 - vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 1626 + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0 1700 1627 peerDependenciesMeta: 1701 1628 vite: 1702 1629 optional: true ··· 1705 1632 resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} 1706 1633 engines: {node: '>= 8'} 1707 1634 1708 - which@2.0.2: 1709 - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} 1710 - engines: {node: '>= 8'} 1711 - hasBin: true 1712 - 1713 - workerd@1.20250508.0: 1714 - resolution: {integrity: sha512-ffLxe7dXSuGoA6jb3Qx2SClIV1aLHfJQ6RhGhzYHjQgv7dL6fdUOSIIGgzmu2mRKs+WFSujp6c8WgKquco6w3w==} 1635 + workerd@1.20251202.0: 1636 + resolution: {integrity: sha512-p08YfrUMHkjCECNdT36r+6DpJIZX4kixbZ4n6GMUcLR5Gh18fakSCsiQrh72iOm4M9QHv/rM7P8YvCrUPWT5sg==} 1715 1637 engines: {node: '>=16'} 1716 1638 hasBin: true 1717 1639 1718 - wrangler@4.16.1: 1719 - resolution: {integrity: sha512-YiLdWXcaQva2K/bqokpsZbySPmoT8TJFyJPsQPZumnkgimM9+/g/yoXArByA+pf+xU8jhw7ybQ8X1yBGXv731g==} 1720 - engines: {node: '>=18.0.0'} 1640 + wrangler@4.53.0: 1641 + resolution: {integrity: sha512-/wvnHlRnlHsqaeIgGbmcEJE5NFYdTUWHCKow+U5Tv2XwQXI9vXUqBwCLAGy/BwqyS5nnycRt2kppqCzgHgyb7Q==} 1642 + engines: {node: '>=20.0.0'} 1721 1643 hasBin: true 1722 1644 peerDependencies: 1723 - '@cloudflare/workers-types': ^4.20250508.0 1645 + '@cloudflare/workers-types': ^4.20251202.0 1724 1646 peerDependenciesMeta: 1725 1647 '@cloudflare/workers-types': 1726 1648 optional: true 1727 1649 1728 - wrap-ansi@7.0.0: 1729 - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} 1730 - engines: {node: '>=10'} 1731 - 1732 - wrap-ansi@8.1.0: 1733 - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} 1734 - engines: {node: '>=12'} 1735 - 1736 1650 ws@8.18.0: 1737 1651 resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} 1738 1652 engines: {node: '>=10.0.0'} ··· 1748 1662 yallist@3.1.1: 1749 1663 resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} 1750 1664 1751 - yaml@2.8.0: 1752 - resolution: {integrity: sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==} 1753 - engines: {node: '>= 14.6'} 1754 - hasBin: true 1665 + youch-core@0.3.3: 1666 + resolution: {integrity: sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA==} 1755 1667 1756 - yocto-queue@1.2.1: 1757 - resolution: {integrity: sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==} 1758 - engines: {node: '>=12.20'} 1759 - 1760 - youch@3.3.4: 1761 - resolution: {integrity: sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg==} 1668 + youch@4.1.0-beta.10: 1669 + resolution: {integrity: sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ==} 1762 1670 1763 1671 zod@3.22.3: 1764 1672 resolution: {integrity: sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug==} ··· 1767 1675 1768 1676 '@alloc/quick-lru@5.2.0': {} 1769 1677 1770 - '@ampproject/remapping@2.3.0': 1678 + '@atcute/atproto@3.1.9': 1771 1679 dependencies: 1772 - '@jridgewell/gen-mapping': 0.3.8 1773 - '@jridgewell/trace-mapping': 0.3.25 1680 + '@atcute/lexicons': 1.2.5 1774 1681 1775 - '@atcute/atproto@3.0.2': 1682 + '@atcute/bluesky@3.2.13': 1776 1683 dependencies: 1777 - '@atcute/lexicons': 1.0.3 1684 + '@atcute/atproto': 3.1.9 1685 + '@atcute/lexicons': 1.2.5 1778 1686 1779 - '@atcute/bluesky@3.0.2': 1687 + '@atcute/car@5.0.0': 1780 1688 dependencies: 1781 - '@atcute/atproto': 3.0.2 1782 - '@atcute/lexicons': 1.0.3 1689 + '@atcute/cbor': 2.2.8 1690 + '@atcute/cid': 2.2.6 1691 + '@atcute/uint8array': 1.0.6 1692 + '@atcute/varint': 1.0.3 1783 1693 1784 - '@atcute/car@3.1.1': 1694 + '@atcute/cbor@2.2.8': 1785 1695 dependencies: 1786 - '@atcute/cbor': 2.2.4 1787 - '@atcute/cid': 2.2.3 1788 - '@atcute/uint8array': 1.0.2 1789 - '@atcute/varint': 1.0.2 1790 - yocto-queue: 1.2.1 1696 + '@atcute/cid': 2.2.6 1697 + '@atcute/multibase': 1.1.6 1698 + '@atcute/uint8array': 1.0.6 1791 1699 1792 - '@atcute/cbor@2.2.4': 1700 + '@atcute/cid@2.2.6': 1793 1701 dependencies: 1794 - '@atcute/cid': 2.2.3 1795 - '@atcute/multibase': 1.1.4 1796 - '@atcute/uint8array': 1.0.2 1702 + '@atcute/multibase': 1.1.6 1703 + '@atcute/uint8array': 1.0.6 1797 1704 1798 - '@atcute/cid@2.2.3': 1705 + '@atcute/client@4.1.1': 1799 1706 dependencies: 1800 - '@atcute/multibase': 1.1.4 1801 - '@atcute/uint8array': 1.0.2 1707 + '@atcute/identity': 1.1.3 1708 + '@atcute/lexicons': 1.2.5 1802 1709 1803 - '@atcute/client@4.0.3': 1710 + '@atcute/crypto@2.3.0': 1804 1711 dependencies: 1805 - '@atcute/identity': 1.0.2 1806 - '@atcute/lexicons': 1.0.3 1712 + '@atcute/multibase': 1.1.6 1713 + '@atcute/uint8array': 1.0.6 1714 + '@noble/secp256k1': 3.0.0 1807 1715 1808 - '@atcute/crypto@2.2.2': 1716 + '@atcute/did-plc@0.2.0': 1809 1717 dependencies: 1810 - '@atcute/multibase': 1.1.4 1811 - '@atcute/uint8array': 1.0.2 1812 - '@noble/secp256k1': 2.2.3 1718 + '@atcute/cbor': 2.2.8 1719 + '@atcute/cid': 2.2.6 1720 + '@atcute/crypto': 2.3.0 1721 + '@atcute/identity': 1.1.3 1722 + '@atcute/lexicons': 1.2.5 1723 + '@atcute/multibase': 1.1.6 1724 + '@atcute/uint8array': 1.0.6 1725 + '@badrap/valita': 0.4.6 1813 1726 1814 - '@atcute/did-plc@0.1.5': 1727 + '@atcute/identity-resolver@1.2.0(@atcute/identity@1.1.3)': 1815 1728 dependencies: 1816 - '@atcute/cbor': 2.2.4 1817 - '@atcute/cid': 2.2.3 1818 - '@atcute/crypto': 2.2.2 1819 - '@atcute/multibase': 1.1.4 1820 - '@atcute/uint8array': 1.0.2 1821 - '@badrap/valita': 0.4.5 1729 + '@atcute/identity': 1.1.3 1730 + '@atcute/lexicons': 1.2.5 1731 + '@atcute/util-fetch': 1.0.4 1732 + '@badrap/valita': 0.4.6 1822 1733 1823 - '@atcute/identity-resolver@1.1.0(@atcute/identity@1.0.2)': 1734 + '@atcute/identity@1.1.3': 1824 1735 dependencies: 1825 - '@atcute/identity': 1.0.2 1826 - '@atcute/lexicons': 1.0.3 1827 - '@atcute/util-fetch': 1.0.1 1828 - '@badrap/valita': 0.4.5 1736 + '@atcute/lexicons': 1.2.5 1737 + '@badrap/valita': 0.4.6 1829 1738 1830 - '@atcute/identity@1.0.2': 1739 + '@atcute/lexicons@1.2.5': 1831 1740 dependencies: 1832 - '@atcute/lexicons': 1.0.3 1833 - '@badrap/valita': 0.4.5 1741 + '@standard-schema/spec': 1.0.0 1742 + esm-env: 1.2.2 1743 + 1744 + '@atcute/mst@0.1.0': 1745 + dependencies: 1746 + '@atcute/cbor': 2.2.8 1747 + '@atcute/cid': 2.2.6 1748 + '@atcute/uint8array': 1.0.6 1834 1749 1835 - '@atcute/lexicons@1.0.3': 1750 + '@atcute/multibase@1.1.6': 1836 1751 dependencies: 1837 - esm-env: 1.2.2 1752 + '@atcute/uint8array': 1.0.6 1838 1753 1839 - '@atcute/multibase@1.1.4': 1754 + '@atcute/repo@0.1.0': 1840 1755 dependencies: 1841 - '@atcute/uint8array': 1.0.2 1756 + '@atcute/car': 5.0.0 1757 + '@atcute/cbor': 2.2.8 1758 + '@atcute/cid': 2.2.6 1759 + '@atcute/crypto': 2.3.0 1760 + '@atcute/lexicons': 1.2.5 1761 + '@atcute/mst': 0.1.0 1762 + '@atcute/uint8array': 1.0.6 1842 1763 1843 - '@atcute/tid@1.0.2': {} 1764 + '@atcute/tid@1.0.3': {} 1844 1765 1845 - '@atcute/uint8array@1.0.2': {} 1766 + '@atcute/uint8array@1.0.6': {} 1846 1767 1847 - '@atcute/util-fetch@1.0.1': 1768 + '@atcute/util-fetch@1.0.4': 1848 1769 dependencies: 1849 - '@badrap/valita': 0.4.5 1770 + '@badrap/valita': 0.4.6 1850 1771 1851 - '@atcute/varint@1.0.2': {} 1772 + '@atcute/varint@1.0.3': {} 1852 1773 1853 1774 '@babel/code-frame@7.27.1': 1854 1775 dependencies: 1855 - '@babel/helper-validator-identifier': 7.27.1 1776 + '@babel/helper-validator-identifier': 7.28.5 1856 1777 js-tokens: 4.0.0 1857 1778 picocolors: 1.1.1 1858 1779 1859 - '@babel/compat-data@7.27.2': {} 1780 + '@babel/compat-data@7.28.5': {} 1860 1781 1861 - '@babel/core@7.27.1': 1782 + '@babel/core@7.28.5': 1862 1783 dependencies: 1863 - '@ampproject/remapping': 2.3.0 1864 1784 '@babel/code-frame': 7.27.1 1865 - '@babel/generator': 7.27.1 1785 + '@babel/generator': 7.28.5 1866 1786 '@babel/helper-compilation-targets': 7.27.2 1867 - '@babel/helper-module-transforms': 7.27.1(@babel/core@7.27.1) 1868 - '@babel/helpers': 7.27.1 1869 - '@babel/parser': 7.27.2 1787 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) 1788 + '@babel/helpers': 7.28.4 1789 + '@babel/parser': 7.28.5 1870 1790 '@babel/template': 7.27.2 1871 - '@babel/traverse': 7.27.1 1872 - '@babel/types': 7.27.1 1791 + '@babel/traverse': 7.28.5 1792 + '@babel/types': 7.28.5 1793 + '@jridgewell/remapping': 2.3.5 1873 1794 convert-source-map: 2.0.0 1874 - debug: 4.4.1 1795 + debug: 4.4.3 1875 1796 gensync: 1.0.0-beta.2 1876 1797 json5: 2.2.3 1877 1798 semver: 6.3.1 1878 1799 transitivePeerDependencies: 1879 1800 - supports-color 1880 1801 1881 - '@babel/generator@7.27.1': 1802 + '@babel/generator@7.28.5': 1882 1803 dependencies: 1883 - '@babel/parser': 7.27.2 1884 - '@babel/types': 7.27.1 1885 - '@jridgewell/gen-mapping': 0.3.8 1886 - '@jridgewell/trace-mapping': 0.3.25 1804 + '@babel/parser': 7.28.5 1805 + '@babel/types': 7.28.5 1806 + '@jridgewell/gen-mapping': 0.3.13 1807 + '@jridgewell/trace-mapping': 0.3.31 1887 1808 jsesc: 3.1.0 1888 1809 1889 1810 '@babel/helper-compilation-targets@7.27.2': 1890 1811 dependencies: 1891 - '@babel/compat-data': 7.27.2 1812 + '@babel/compat-data': 7.28.5 1892 1813 '@babel/helper-validator-option': 7.27.1 1893 - browserslist: 4.24.5 1814 + browserslist: 4.28.1 1894 1815 lru-cache: 5.1.1 1895 1816 semver: 6.3.1 1896 1817 1818 + '@babel/helper-globals@7.28.0': {} 1819 + 1897 1820 '@babel/helper-module-imports@7.18.6': 1898 1821 dependencies: 1899 - '@babel/types': 7.27.1 1822 + '@babel/types': 7.28.5 1900 1823 1901 1824 '@babel/helper-module-imports@7.27.1': 1902 1825 dependencies: 1903 - '@babel/traverse': 7.27.1 1904 - '@babel/types': 7.27.1 1826 + '@babel/traverse': 7.28.5 1827 + '@babel/types': 7.28.5 1905 1828 transitivePeerDependencies: 1906 1829 - supports-color 1907 1830 1908 - '@babel/helper-module-transforms@7.27.1(@babel/core@7.27.1)': 1831 + '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.5)': 1909 1832 dependencies: 1910 - '@babel/core': 7.27.1 1833 + '@babel/core': 7.28.5 1911 1834 '@babel/helper-module-imports': 7.27.1 1912 - '@babel/helper-validator-identifier': 7.27.1 1913 - '@babel/traverse': 7.27.1 1835 + '@babel/helper-validator-identifier': 7.28.5 1836 + '@babel/traverse': 7.28.5 1914 1837 transitivePeerDependencies: 1915 1838 - supports-color 1916 1839 ··· 1918 1841 1919 1842 '@babel/helper-string-parser@7.27.1': {} 1920 1843 1921 - '@babel/helper-validator-identifier@7.27.1': {} 1844 + '@babel/helper-validator-identifier@7.28.5': {} 1922 1845 1923 1846 '@babel/helper-validator-option@7.27.1': {} 1924 1847 1925 - '@babel/helpers@7.27.1': 1848 + '@babel/helpers@7.28.4': 1926 1849 dependencies: 1927 1850 '@babel/template': 7.27.2 1928 - '@babel/types': 7.27.1 1851 + '@babel/types': 7.28.5 1929 1852 1930 - '@babel/parser@7.27.2': 1853 + '@babel/parser@7.28.5': 1931 1854 dependencies: 1932 - '@babel/types': 7.27.1 1855 + '@babel/types': 7.28.5 1933 1856 1934 - '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.27.1)': 1857 + '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.5)': 1935 1858 dependencies: 1936 - '@babel/core': 7.27.1 1859 + '@babel/core': 7.28.5 1937 1860 '@babel/helper-plugin-utils': 7.27.1 1938 1861 1939 1862 '@babel/template@7.27.2': 1940 1863 dependencies: 1941 1864 '@babel/code-frame': 7.27.1 1942 - '@babel/parser': 7.27.2 1943 - '@babel/types': 7.27.1 1865 + '@babel/parser': 7.28.5 1866 + '@babel/types': 7.28.5 1944 1867 1945 - '@babel/traverse@7.27.1': 1868 + '@babel/traverse@7.28.5': 1946 1869 dependencies: 1947 1870 '@babel/code-frame': 7.27.1 1948 - '@babel/generator': 7.27.1 1949 - '@babel/parser': 7.27.2 1871 + '@babel/generator': 7.28.5 1872 + '@babel/helper-globals': 7.28.0 1873 + '@babel/parser': 7.28.5 1950 1874 '@babel/template': 7.27.2 1951 - '@babel/types': 7.27.1 1952 - debug: 4.4.1 1953 - globals: 11.12.0 1875 + '@babel/types': 7.28.5 1876 + debug: 4.4.3 1954 1877 transitivePeerDependencies: 1955 1878 - supports-color 1956 1879 1957 - '@babel/types@7.27.1': 1880 + '@babel/types@7.28.5': 1958 1881 dependencies: 1959 1882 '@babel/helper-string-parser': 7.27.1 1960 - '@babel/helper-validator-identifier': 7.27.1 1883 + '@babel/helper-validator-identifier': 7.28.5 1961 1884 1962 - '@badrap/valita@0.4.5': {} 1885 + '@badrap/valita@0.4.6': {} 1963 1886 1964 - '@cloudflare/kv-asset-handler@0.4.0': 1887 + '@cloudflare/kv-asset-handler@0.4.1': 1965 1888 dependencies: 1966 1889 mime: 3.0.0 1967 1890 1968 - '@cloudflare/unenv-preset@2.3.2(unenv@2.0.0-rc.17)(workerd@1.20250508.0)': 1891 + '@cloudflare/unenv-preset@2.7.13(unenv@2.0.0-rc.24)(workerd@1.20251202.0)': 1969 1892 dependencies: 1970 - unenv: 2.0.0-rc.17 1893 + unenv: 2.0.0-rc.24 1971 1894 optionalDependencies: 1972 - workerd: 1.20250508.0 1895 + workerd: 1.20251202.0 1973 1896 1974 - '@cloudflare/workerd-darwin-64@1.20250508.0': 1897 + '@cloudflare/workerd-darwin-64@1.20251202.0': 1975 1898 optional: true 1976 1899 1977 - '@cloudflare/workerd-darwin-arm64@1.20250508.0': 1900 + '@cloudflare/workerd-darwin-arm64@1.20251202.0': 1978 1901 optional: true 1979 1902 1980 - '@cloudflare/workerd-linux-64@1.20250508.0': 1903 + '@cloudflare/workerd-linux-64@1.20251202.0': 1981 1904 optional: true 1982 1905 1983 - '@cloudflare/workerd-linux-arm64@1.20250508.0': 1906 + '@cloudflare/workerd-linux-arm64@1.20251202.0': 1984 1907 optional: true 1985 1908 1986 - '@cloudflare/workerd-windows-64@1.20250508.0': 1909 + '@cloudflare/workerd-windows-64@1.20251202.0': 1987 1910 optional: true 1988 1911 1989 1912 '@cspotcode/source-map-support@0.8.1': 1990 1913 dependencies: 1991 1914 '@jridgewell/trace-mapping': 0.3.9 1992 1915 1993 - '@emnapi/runtime@1.4.3': 1916 + '@emnapi/runtime@1.7.1': 1994 1917 dependencies: 1995 1918 tslib: 2.8.1 1996 1919 optional: true 1997 1920 1998 - '@esbuild/aix-ppc64@0.25.4': 1921 + '@esbuild/aix-ppc64@0.25.12': 1922 + optional: true 1923 + 1924 + '@esbuild/aix-ppc64@0.27.0': 1925 + optional: true 1926 + 1927 + '@esbuild/android-arm64@0.25.12': 1999 1928 optional: true 2000 1929 2001 - '@esbuild/aix-ppc64@0.25.5': 1930 + '@esbuild/android-arm64@0.27.0': 2002 1931 optional: true 2003 1932 2004 - '@esbuild/android-arm64@0.25.4': 1933 + '@esbuild/android-arm@0.25.12': 2005 1934 optional: true 2006 1935 2007 - '@esbuild/android-arm64@0.25.5': 1936 + '@esbuild/android-arm@0.27.0': 2008 1937 optional: true 2009 1938 2010 - '@esbuild/android-arm@0.25.4': 1939 + '@esbuild/android-x64@0.25.12': 2011 1940 optional: true 2012 1941 2013 - '@esbuild/android-arm@0.25.5': 1942 + '@esbuild/android-x64@0.27.0': 2014 1943 optional: true 2015 1944 2016 - '@esbuild/android-x64@0.25.4': 1945 + '@esbuild/darwin-arm64@0.25.12': 2017 1946 optional: true 2018 1947 2019 - '@esbuild/android-x64@0.25.5': 1948 + '@esbuild/darwin-arm64@0.27.0': 2020 1949 optional: true 2021 1950 2022 - '@esbuild/darwin-arm64@0.25.4': 1951 + '@esbuild/darwin-x64@0.25.12': 2023 1952 optional: true 2024 1953 2025 - '@esbuild/darwin-arm64@0.25.5': 1954 + '@esbuild/darwin-x64@0.27.0': 2026 1955 optional: true 2027 1956 2028 - '@esbuild/darwin-x64@0.25.4': 1957 + '@esbuild/freebsd-arm64@0.25.12': 2029 1958 optional: true 2030 1959 2031 - '@esbuild/darwin-x64@0.25.5': 1960 + '@esbuild/freebsd-arm64@0.27.0': 2032 1961 optional: true 2033 1962 2034 - '@esbuild/freebsd-arm64@0.25.4': 1963 + '@esbuild/freebsd-x64@0.25.12': 2035 1964 optional: true 2036 1965 2037 - '@esbuild/freebsd-arm64@0.25.5': 1966 + '@esbuild/freebsd-x64@0.27.0': 2038 1967 optional: true 2039 1968 2040 - '@esbuild/freebsd-x64@0.25.4': 1969 + '@esbuild/linux-arm64@0.25.12': 2041 1970 optional: true 2042 1971 2043 - '@esbuild/freebsd-x64@0.25.5': 1972 + '@esbuild/linux-arm64@0.27.0': 2044 1973 optional: true 2045 1974 2046 - '@esbuild/linux-arm64@0.25.4': 1975 + '@esbuild/linux-arm@0.25.12': 2047 1976 optional: true 2048 1977 2049 - '@esbuild/linux-arm64@0.25.5': 1978 + '@esbuild/linux-arm@0.27.0': 2050 1979 optional: true 2051 1980 2052 - '@esbuild/linux-arm@0.25.4': 1981 + '@esbuild/linux-ia32@0.25.12': 2053 1982 optional: true 2054 1983 2055 - '@esbuild/linux-arm@0.25.5': 1984 + '@esbuild/linux-ia32@0.27.0': 2056 1985 optional: true 2057 1986 2058 - '@esbuild/linux-ia32@0.25.4': 1987 + '@esbuild/linux-loong64@0.25.12': 2059 1988 optional: true 2060 1989 2061 - '@esbuild/linux-ia32@0.25.5': 1990 + '@esbuild/linux-loong64@0.27.0': 2062 1991 optional: true 2063 1992 2064 - '@esbuild/linux-loong64@0.25.4': 1993 + '@esbuild/linux-mips64el@0.25.12': 2065 1994 optional: true 2066 1995 2067 - '@esbuild/linux-loong64@0.25.5': 1996 + '@esbuild/linux-mips64el@0.27.0': 2068 1997 optional: true 2069 1998 2070 - '@esbuild/linux-mips64el@0.25.4': 1999 + '@esbuild/linux-ppc64@0.25.12': 2071 2000 optional: true 2072 2001 2073 - '@esbuild/linux-mips64el@0.25.5': 2002 + '@esbuild/linux-ppc64@0.27.0': 2074 2003 optional: true 2075 2004 2076 - '@esbuild/linux-ppc64@0.25.4': 2005 + '@esbuild/linux-riscv64@0.25.12': 2077 2006 optional: true 2078 2007 2079 - '@esbuild/linux-ppc64@0.25.5': 2008 + '@esbuild/linux-riscv64@0.27.0': 2080 2009 optional: true 2081 2010 2082 - '@esbuild/linux-riscv64@0.25.4': 2011 + '@esbuild/linux-s390x@0.25.12': 2083 2012 optional: true 2084 2013 2085 - '@esbuild/linux-riscv64@0.25.5': 2014 + '@esbuild/linux-s390x@0.27.0': 2086 2015 optional: true 2087 2016 2088 - '@esbuild/linux-s390x@0.25.4': 2017 + '@esbuild/linux-x64@0.25.12': 2089 2018 optional: true 2090 2019 2091 - '@esbuild/linux-s390x@0.25.5': 2020 + '@esbuild/linux-x64@0.27.0': 2092 2021 optional: true 2093 2022 2094 - '@esbuild/linux-x64@0.25.4': 2023 + '@esbuild/netbsd-arm64@0.25.12': 2095 2024 optional: true 2096 2025 2097 - '@esbuild/linux-x64@0.25.5': 2026 + '@esbuild/netbsd-arm64@0.27.0': 2098 2027 optional: true 2099 2028 2100 - '@esbuild/netbsd-arm64@0.25.4': 2029 + '@esbuild/netbsd-x64@0.25.12': 2101 2030 optional: true 2102 2031 2103 - '@esbuild/netbsd-arm64@0.25.5': 2032 + '@esbuild/netbsd-x64@0.27.0': 2104 2033 optional: true 2105 2034 2106 - '@esbuild/netbsd-x64@0.25.4': 2035 + '@esbuild/openbsd-arm64@0.25.12': 2107 2036 optional: true 2108 2037 2109 - '@esbuild/netbsd-x64@0.25.5': 2038 + '@esbuild/openbsd-arm64@0.27.0': 2110 2039 optional: true 2111 2040 2112 - '@esbuild/openbsd-arm64@0.25.4': 2041 + '@esbuild/openbsd-x64@0.25.12': 2113 2042 optional: true 2114 2043 2115 - '@esbuild/openbsd-arm64@0.25.5': 2044 + '@esbuild/openbsd-x64@0.27.0': 2116 2045 optional: true 2117 2046 2118 - '@esbuild/openbsd-x64@0.25.4': 2047 + '@esbuild/openharmony-arm64@0.25.12': 2119 2048 optional: true 2120 2049 2121 - '@esbuild/openbsd-x64@0.25.5': 2050 + '@esbuild/openharmony-arm64@0.27.0': 2122 2051 optional: true 2123 2052 2124 - '@esbuild/sunos-x64@0.25.4': 2053 + '@esbuild/sunos-x64@0.25.12': 2125 2054 optional: true 2126 2055 2127 - '@esbuild/sunos-x64@0.25.5': 2056 + '@esbuild/sunos-x64@0.27.0': 2128 2057 optional: true 2129 2058 2130 - '@esbuild/win32-arm64@0.25.4': 2059 + '@esbuild/win32-arm64@0.25.12': 2131 2060 optional: true 2132 2061 2133 - '@esbuild/win32-arm64@0.25.5': 2062 + '@esbuild/win32-arm64@0.27.0': 2134 2063 optional: true 2135 2064 2136 - '@esbuild/win32-ia32@0.25.4': 2065 + '@esbuild/win32-ia32@0.25.12': 2137 2066 optional: true 2138 2067 2139 - '@esbuild/win32-ia32@0.25.5': 2068 + '@esbuild/win32-ia32@0.27.0': 2140 2069 optional: true 2141 2070 2142 - '@esbuild/win32-x64@0.25.4': 2071 + '@esbuild/win32-x64@0.25.12': 2143 2072 optional: true 2144 2073 2145 - '@esbuild/win32-x64@0.25.5': 2074 + '@esbuild/win32-x64@0.27.0': 2146 2075 optional: true 2147 2076 2148 - '@externdefs/solid-freeze@0.1.1(solid-js@1.9.7)': 2077 + '@externdefs/solid-freeze@0.1.1(solid-js@1.9.10)': 2149 2078 dependencies: 2150 - solid-js: 1.9.7 2151 - 2152 - '@fastify/busboy@2.1.1': {} 2079 + solid-js: 1.9.10 2153 2080 2154 2081 '@img/sharp-darwin-arm64@0.33.5': 2155 2082 optionalDependencies: ··· 2217 2144 2218 2145 '@img/sharp-wasm32@0.33.5': 2219 2146 dependencies: 2220 - '@emnapi/runtime': 1.4.3 2147 + '@emnapi/runtime': 1.7.1 2221 2148 optional: true 2222 2149 2223 2150 '@img/sharp-win32-ia32@0.33.5': ··· 2226 2153 '@img/sharp-win32-x64@0.33.5': 2227 2154 optional: true 2228 2155 2229 - '@isaacs/cliui@8.0.2': 2156 + '@jridgewell/gen-mapping@0.3.13': 2230 2157 dependencies: 2231 - string-width: 5.1.2 2232 - string-width-cjs: string-width@4.2.3 2233 - strip-ansi: 7.1.0 2234 - strip-ansi-cjs: strip-ansi@6.0.1 2235 - wrap-ansi: 8.1.0 2236 - wrap-ansi-cjs: wrap-ansi@7.0.0 2158 + '@jridgewell/sourcemap-codec': 1.5.5 2159 + '@jridgewell/trace-mapping': 0.3.31 2237 2160 2238 - '@jridgewell/gen-mapping@0.3.8': 2161 + '@jridgewell/remapping@2.3.5': 2239 2162 dependencies: 2240 - '@jridgewell/set-array': 1.2.1 2241 - '@jridgewell/sourcemap-codec': 1.5.0 2242 - '@jridgewell/trace-mapping': 0.3.25 2163 + '@jridgewell/gen-mapping': 0.3.13 2164 + '@jridgewell/trace-mapping': 0.3.31 2243 2165 2244 2166 '@jridgewell/resolve-uri@3.1.2': {} 2245 2167 2246 - '@jridgewell/set-array@1.2.1': {} 2247 - 2248 - '@jridgewell/source-map@0.3.6': 2168 + '@jridgewell/source-map@0.3.11': 2249 2169 dependencies: 2250 - '@jridgewell/gen-mapping': 0.3.8 2251 - '@jridgewell/trace-mapping': 0.3.25 2170 + '@jridgewell/gen-mapping': 0.3.13 2171 + '@jridgewell/trace-mapping': 0.3.31 2252 2172 2253 - '@jridgewell/sourcemap-codec@1.5.0': {} 2173 + '@jridgewell/sourcemap-codec@1.5.5': {} 2254 2174 2255 - '@jridgewell/trace-mapping@0.3.25': 2175 + '@jridgewell/trace-mapping@0.3.31': 2256 2176 dependencies: 2257 2177 '@jridgewell/resolve-uri': 3.1.2 2258 - '@jridgewell/sourcemap-codec': 1.5.0 2178 + '@jridgewell/sourcemap-codec': 1.5.5 2259 2179 2260 2180 '@jridgewell/trace-mapping@0.3.9': 2261 2181 dependencies: 2262 2182 '@jridgewell/resolve-uri': 3.1.2 2263 - '@jridgewell/sourcemap-codec': 1.5.0 2183 + '@jridgewell/sourcemap-codec': 1.5.5 2264 2184 2265 - '@jsr/mary__array-fns@0.1.4': {} 2185 + '@jsr/mary__array-fns@0.1.5': {} 2266 2186 2267 - '@jsr/mary__ds-queue@0.1.2': {} 2187 + '@jsr/mary__ds-queue@0.1.3': {} 2268 2188 2269 2189 '@jsr/mary__events@0.2.0': {} 2270 2190 2271 - '@jsr/mary__tar@0.2.4': {} 2191 + '@jsr/mary__tar@0.3.1': {} 2272 2192 2273 - '@noble/secp256k1@2.2.3': {} 2193 + '@noble/secp256k1@3.0.0': {} 2274 2194 2275 2195 '@nodelib/fs.scandir@2.1.5': 2276 2196 dependencies: ··· 2284 2204 '@nodelib/fs.scandir': 2.1.5 2285 2205 fastq: 1.19.1 2286 2206 2287 - '@pkgjs/parseargs@0.11.0': 2207 + '@poppinss/colors@4.1.5': 2208 + dependencies: 2209 + kleur: 4.1.5 2210 + 2211 + '@poppinss/dumper@0.6.5': 2212 + dependencies: 2213 + '@poppinss/colors': 4.1.5 2214 + '@sindresorhus/is': 7.1.1 2215 + supports-color: 10.2.2 2216 + 2217 + '@poppinss/exception@1.2.2': {} 2218 + 2219 + '@rollup/rollup-android-arm-eabi@4.53.3': 2288 2220 optional: true 2289 2221 2290 - '@rollup/rollup-android-arm-eabi@4.41.1': 2222 + '@rollup/rollup-android-arm64@4.53.3': 2291 2223 optional: true 2292 2224 2293 - '@rollup/rollup-android-arm64@4.41.1': 2225 + '@rollup/rollup-darwin-arm64@4.53.3': 2294 2226 optional: true 2295 2227 2296 - '@rollup/rollup-darwin-arm64@4.41.1': 2228 + '@rollup/rollup-darwin-x64@4.53.3': 2297 2229 optional: true 2298 2230 2299 - '@rollup/rollup-darwin-x64@4.41.1': 2231 + '@rollup/rollup-freebsd-arm64@4.53.3': 2300 2232 optional: true 2301 2233 2302 - '@rollup/rollup-freebsd-arm64@4.41.1': 2234 + '@rollup/rollup-freebsd-x64@4.53.3': 2303 2235 optional: true 2304 2236 2305 - '@rollup/rollup-freebsd-x64@4.41.1': 2237 + '@rollup/rollup-linux-arm-gnueabihf@4.53.3': 2306 2238 optional: true 2307 2239 2308 - '@rollup/rollup-linux-arm-gnueabihf@4.41.1': 2240 + '@rollup/rollup-linux-arm-musleabihf@4.53.3': 2309 2241 optional: true 2310 2242 2311 - '@rollup/rollup-linux-arm-musleabihf@4.41.1': 2243 + '@rollup/rollup-linux-arm64-gnu@4.53.3': 2312 2244 optional: true 2313 2245 2314 - '@rollup/rollup-linux-arm64-gnu@4.41.1': 2246 + '@rollup/rollup-linux-arm64-musl@4.53.3': 2315 2247 optional: true 2316 2248 2317 - '@rollup/rollup-linux-arm64-musl@4.41.1': 2249 + '@rollup/rollup-linux-loong64-gnu@4.53.3': 2318 2250 optional: true 2319 2251 2320 - '@rollup/rollup-linux-loongarch64-gnu@4.41.1': 2252 + '@rollup/rollup-linux-ppc64-gnu@4.53.3': 2253 + optional: true 2254 + 2255 + '@rollup/rollup-linux-riscv64-gnu@4.53.3': 2321 2256 optional: true 2322 2257 2323 - '@rollup/rollup-linux-powerpc64le-gnu@4.41.1': 2258 + '@rollup/rollup-linux-riscv64-musl@4.53.3': 2324 2259 optional: true 2325 2260 2326 - '@rollup/rollup-linux-riscv64-gnu@4.41.1': 2261 + '@rollup/rollup-linux-s390x-gnu@4.53.3': 2327 2262 optional: true 2328 2263 2329 - '@rollup/rollup-linux-riscv64-musl@4.41.1': 2264 + '@rollup/rollup-linux-x64-gnu@4.53.3': 2330 2265 optional: true 2331 2266 2332 - '@rollup/rollup-linux-s390x-gnu@4.41.1': 2267 + '@rollup/rollup-linux-x64-musl@4.53.3': 2333 2268 optional: true 2334 2269 2335 - '@rollup/rollup-linux-x64-gnu@4.41.1': 2270 + '@rollup/rollup-openharmony-arm64@4.53.3': 2336 2271 optional: true 2337 2272 2338 - '@rollup/rollup-linux-x64-musl@4.41.1': 2273 + '@rollup/rollup-win32-arm64-msvc@4.53.3': 2339 2274 optional: true 2340 2275 2341 - '@rollup/rollup-win32-arm64-msvc@4.41.1': 2276 + '@rollup/rollup-win32-ia32-msvc@4.53.3': 2342 2277 optional: true 2343 2278 2344 - '@rollup/rollup-win32-ia32-msvc@4.41.1': 2279 + '@rollup/rollup-win32-x64-gnu@4.53.3': 2345 2280 optional: true 2346 2281 2347 - '@rollup/rollup-win32-x64-msvc@4.41.1': 2282 + '@rollup/rollup-win32-x64-msvc@4.53.3': 2348 2283 optional: true 2349 2284 2350 - '@tailwindcss/forms@0.5.10(tailwindcss@3.4.17)': 2285 + '@sindresorhus/is@7.1.1': {} 2286 + 2287 + '@speed-highlight/core@1.2.12': {} 2288 + 2289 + '@standard-schema/spec@1.0.0': {} 2290 + 2291 + '@tailwindcss/forms@0.5.10(tailwindcss@3.4.18)': 2351 2292 dependencies: 2352 2293 mini-svg-data-uri: 1.4.4 2353 - tailwindcss: 3.4.17 2294 + tailwindcss: 3.4.18 2354 2295 2355 2296 '@types/babel__core@7.20.5': 2356 2297 dependencies: 2357 - '@babel/parser': 7.27.2 2358 - '@babel/types': 7.27.1 2298 + '@babel/parser': 7.28.5 2299 + '@babel/types': 7.28.5 2359 2300 '@types/babel__generator': 7.27.0 2360 2301 '@types/babel__template': 7.4.4 2361 - '@types/babel__traverse': 7.20.7 2302 + '@types/babel__traverse': 7.28.0 2362 2303 2363 2304 '@types/babel__generator@7.27.0': 2364 2305 dependencies: 2365 - '@babel/types': 7.27.1 2306 + '@babel/types': 7.28.5 2366 2307 2367 2308 '@types/babel__template@7.4.4': 2368 2309 dependencies: 2369 - '@babel/parser': 7.27.2 2370 - '@babel/types': 7.27.1 2310 + '@babel/parser': 7.28.5 2311 + '@babel/types': 7.28.5 2371 2312 2372 - '@types/babel__traverse@7.20.7': 2313 + '@types/babel__traverse@7.28.0': 2373 2314 dependencies: 2374 - '@babel/types': 7.27.1 2315 + '@babel/types': 7.28.5 2375 2316 2376 - '@types/estree@1.0.7': {} 2317 + '@types/estree@1.0.8': {} 2377 2318 2378 - '@types/node@22.15.21': 2319 + '@types/node@22.19.2': 2379 2320 dependencies: 2380 2321 undici-types: 6.21.0 2381 2322 ··· 2383 2324 2384 2325 acorn@8.14.0: {} 2385 2326 2386 - acorn@8.14.1: {} 2387 - 2388 - ansi-regex@5.0.1: {} 2389 - 2390 - ansi-regex@6.1.0: {} 2391 - 2392 - ansi-styles@4.3.0: 2393 - dependencies: 2394 - color-convert: 2.0.1 2395 - 2396 - ansi-styles@6.2.1: {} 2327 + acorn@8.15.0: {} 2397 2328 2398 2329 any-promise@1.3.0: {} 2399 2330 ··· 2404 2335 2405 2336 arg@5.0.2: {} 2406 2337 2407 - as-table@1.0.55: 2408 - dependencies: 2409 - printable-characters: 1.0.42 2410 - 2411 - autoprefixer@10.4.21(postcss@8.5.3): 2338 + autoprefixer@10.4.22(postcss@8.5.6): 2412 2339 dependencies: 2413 - browserslist: 4.24.5 2414 - caniuse-lite: 1.0.30001718 2415 - fraction.js: 4.3.7 2340 + browserslist: 4.28.1 2341 + caniuse-lite: 1.0.30001760 2342 + fraction.js: 5.3.4 2416 2343 normalize-range: 0.1.2 2417 2344 picocolors: 1.1.1 2418 - postcss: 8.5.3 2345 + postcss: 8.5.6 2419 2346 postcss-value-parser: 4.2.0 2420 2347 2421 - babel-plugin-jsx-dom-expressions@0.39.8(@babel/core@7.27.1): 2348 + babel-plugin-jsx-dom-expressions@0.40.3(@babel/core@7.28.5): 2422 2349 dependencies: 2423 - '@babel/core': 7.27.1 2350 + '@babel/core': 7.28.5 2424 2351 '@babel/helper-module-imports': 7.18.6 2425 - '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.27.1) 2426 - '@babel/types': 7.27.1 2352 + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.5) 2353 + '@babel/types': 7.28.5 2427 2354 html-entities: 2.3.3 2428 2355 parse5: 7.3.0 2429 - validate-html-nesting: 1.2.2 2430 2356 2431 - babel-preset-solid@1.9.6(@babel/core@7.27.1): 2357 + babel-preset-solid@1.9.10(@babel/core@7.28.5)(solid-js@1.9.10): 2432 2358 dependencies: 2433 - '@babel/core': 7.27.1 2434 - babel-plugin-jsx-dom-expressions: 0.39.8(@babel/core@7.27.1) 2359 + '@babel/core': 7.28.5 2360 + babel-plugin-jsx-dom-expressions: 0.40.3(@babel/core@7.28.5) 2361 + optionalDependencies: 2362 + solid-js: 1.9.10 2435 2363 2436 - balanced-match@1.0.2: {} 2364 + baseline-browser-mapping@2.9.5: {} 2437 2365 2438 2366 binary-extensions@2.3.0: {} 2439 2367 2440 2368 blake3-wasm@2.1.5: {} 2441 - 2442 - brace-expansion@2.0.1: 2443 - dependencies: 2444 - balanced-match: 1.0.2 2445 2369 2446 2370 braces@3.0.3: 2447 2371 dependencies: 2448 2372 fill-range: 7.1.1 2449 2373 2450 - browserslist@4.24.5: 2374 + browserslist@4.28.1: 2451 2375 dependencies: 2452 - caniuse-lite: 1.0.30001718 2453 - electron-to-chromium: 1.5.158 2454 - node-releases: 2.0.19 2455 - update-browserslist-db: 1.1.3(browserslist@4.24.5) 2376 + baseline-browser-mapping: 2.9.5 2377 + caniuse-lite: 1.0.30001760 2378 + electron-to-chromium: 1.5.267 2379 + node-releases: 2.0.27 2380 + update-browserslist-db: 1.2.2(browserslist@4.28.1) 2456 2381 2457 2382 buffer-from@1.1.2: {} 2458 2383 2459 2384 camelcase-css@2.0.1: {} 2460 2385 2461 - caniuse-lite@1.0.30001718: {} 2386 + caniuse-lite@1.0.30001760: {} 2462 2387 2463 2388 chokidar@3.6.0: 2464 2389 dependencies: ··· 2481 2406 color-string@1.9.1: 2482 2407 dependencies: 2483 2408 color-name: 1.1.4 2484 - simple-swizzle: 0.2.2 2409 + simple-swizzle: 0.2.4 2485 2410 2486 2411 color@4.2.3: 2487 2412 dependencies: ··· 2494 2419 2495 2420 convert-source-map@2.0.0: {} 2496 2421 2497 - cookie@0.7.2: {} 2498 - 2499 - cross-spawn@7.0.6: 2500 - dependencies: 2501 - path-key: 3.1.1 2502 - shebang-command: 2.0.0 2503 - which: 2.0.2 2422 + cookie@1.1.1: {} 2504 2423 2505 2424 cssesc@3.0.0: {} 2506 2425 2507 - csstype@3.1.3: {} 2508 - 2509 - data-uri-to-buffer@2.0.2: {} 2426 + csstype@3.2.3: {} 2510 2427 2511 - debug@4.4.1: 2428 + debug@4.4.3: 2512 2429 dependencies: 2513 2430 ms: 2.1.3 2514 2431 2515 - defu@6.1.4: {} 2516 - 2517 - detect-libc@2.0.4: {} 2432 + detect-libc@2.1.2: {} 2518 2433 2519 2434 didyoumean@1.2.2: {} 2520 2435 2521 2436 dlv@1.1.3: {} 2522 2437 2523 - eastasianwidth@0.2.0: {} 2438 + electron-to-chromium@1.5.267: {} 2524 2439 2525 - electron-to-chromium@1.5.158: {} 2440 + entities@6.0.1: {} 2526 2441 2527 - emoji-regex@8.0.0: {} 2528 - 2529 - emoji-regex@9.2.2: {} 2530 - 2531 - entities@6.0.0: {} 2442 + error-stack-parser-es@1.0.5: {} 2532 2443 2533 - esbuild@0.25.4: 2444 + esbuild@0.25.12: 2534 2445 optionalDependencies: 2535 - '@esbuild/aix-ppc64': 0.25.4 2536 - '@esbuild/android-arm': 0.25.4 2537 - '@esbuild/android-arm64': 0.25.4 2538 - '@esbuild/android-x64': 0.25.4 2539 - '@esbuild/darwin-arm64': 0.25.4 2540 - '@esbuild/darwin-x64': 0.25.4 2541 - '@esbuild/freebsd-arm64': 0.25.4 2542 - '@esbuild/freebsd-x64': 0.25.4 2543 - '@esbuild/linux-arm': 0.25.4 2544 - '@esbuild/linux-arm64': 0.25.4 2545 - '@esbuild/linux-ia32': 0.25.4 2546 - '@esbuild/linux-loong64': 0.25.4 2547 - '@esbuild/linux-mips64el': 0.25.4 2548 - '@esbuild/linux-ppc64': 0.25.4 2549 - '@esbuild/linux-riscv64': 0.25.4 2550 - '@esbuild/linux-s390x': 0.25.4 2551 - '@esbuild/linux-x64': 0.25.4 2552 - '@esbuild/netbsd-arm64': 0.25.4 2553 - '@esbuild/netbsd-x64': 0.25.4 2554 - '@esbuild/openbsd-arm64': 0.25.4 2555 - '@esbuild/openbsd-x64': 0.25.4 2556 - '@esbuild/sunos-x64': 0.25.4 2557 - '@esbuild/win32-arm64': 0.25.4 2558 - '@esbuild/win32-ia32': 0.25.4 2559 - '@esbuild/win32-x64': 0.25.4 2446 + '@esbuild/aix-ppc64': 0.25.12 2447 + '@esbuild/android-arm': 0.25.12 2448 + '@esbuild/android-arm64': 0.25.12 2449 + '@esbuild/android-x64': 0.25.12 2450 + '@esbuild/darwin-arm64': 0.25.12 2451 + '@esbuild/darwin-x64': 0.25.12 2452 + '@esbuild/freebsd-arm64': 0.25.12 2453 + '@esbuild/freebsd-x64': 0.25.12 2454 + '@esbuild/linux-arm': 0.25.12 2455 + '@esbuild/linux-arm64': 0.25.12 2456 + '@esbuild/linux-ia32': 0.25.12 2457 + '@esbuild/linux-loong64': 0.25.12 2458 + '@esbuild/linux-mips64el': 0.25.12 2459 + '@esbuild/linux-ppc64': 0.25.12 2460 + '@esbuild/linux-riscv64': 0.25.12 2461 + '@esbuild/linux-s390x': 0.25.12 2462 + '@esbuild/linux-x64': 0.25.12 2463 + '@esbuild/netbsd-arm64': 0.25.12 2464 + '@esbuild/netbsd-x64': 0.25.12 2465 + '@esbuild/openbsd-arm64': 0.25.12 2466 + '@esbuild/openbsd-x64': 0.25.12 2467 + '@esbuild/openharmony-arm64': 0.25.12 2468 + '@esbuild/sunos-x64': 0.25.12 2469 + '@esbuild/win32-arm64': 0.25.12 2470 + '@esbuild/win32-ia32': 0.25.12 2471 + '@esbuild/win32-x64': 0.25.12 2560 2472 2561 - esbuild@0.25.5: 2473 + esbuild@0.27.0: 2562 2474 optionalDependencies: 2563 - '@esbuild/aix-ppc64': 0.25.5 2564 - '@esbuild/android-arm': 0.25.5 2565 - '@esbuild/android-arm64': 0.25.5 2566 - '@esbuild/android-x64': 0.25.5 2567 - '@esbuild/darwin-arm64': 0.25.5 2568 - '@esbuild/darwin-x64': 0.25.5 2569 - '@esbuild/freebsd-arm64': 0.25.5 2570 - '@esbuild/freebsd-x64': 0.25.5 2571 - '@esbuild/linux-arm': 0.25.5 2572 - '@esbuild/linux-arm64': 0.25.5 2573 - '@esbuild/linux-ia32': 0.25.5 2574 - '@esbuild/linux-loong64': 0.25.5 2575 - '@esbuild/linux-mips64el': 0.25.5 2576 - '@esbuild/linux-ppc64': 0.25.5 2577 - '@esbuild/linux-riscv64': 0.25.5 2578 - '@esbuild/linux-s390x': 0.25.5 2579 - '@esbuild/linux-x64': 0.25.5 2580 - '@esbuild/netbsd-arm64': 0.25.5 2581 - '@esbuild/netbsd-x64': 0.25.5 2582 - '@esbuild/openbsd-arm64': 0.25.5 2583 - '@esbuild/openbsd-x64': 0.25.5 2584 - '@esbuild/sunos-x64': 0.25.5 2585 - '@esbuild/win32-arm64': 0.25.5 2586 - '@esbuild/win32-ia32': 0.25.5 2587 - '@esbuild/win32-x64': 0.25.5 2475 + '@esbuild/aix-ppc64': 0.27.0 2476 + '@esbuild/android-arm': 0.27.0 2477 + '@esbuild/android-arm64': 0.27.0 2478 + '@esbuild/android-x64': 0.27.0 2479 + '@esbuild/darwin-arm64': 0.27.0 2480 + '@esbuild/darwin-x64': 0.27.0 2481 + '@esbuild/freebsd-arm64': 0.27.0 2482 + '@esbuild/freebsd-x64': 0.27.0 2483 + '@esbuild/linux-arm': 0.27.0 2484 + '@esbuild/linux-arm64': 0.27.0 2485 + '@esbuild/linux-ia32': 0.27.0 2486 + '@esbuild/linux-loong64': 0.27.0 2487 + '@esbuild/linux-mips64el': 0.27.0 2488 + '@esbuild/linux-ppc64': 0.27.0 2489 + '@esbuild/linux-riscv64': 0.27.0 2490 + '@esbuild/linux-s390x': 0.27.0 2491 + '@esbuild/linux-x64': 0.27.0 2492 + '@esbuild/netbsd-arm64': 0.27.0 2493 + '@esbuild/netbsd-x64': 0.27.0 2494 + '@esbuild/openbsd-arm64': 0.27.0 2495 + '@esbuild/openbsd-x64': 0.27.0 2496 + '@esbuild/openharmony-arm64': 0.27.0 2497 + '@esbuild/sunos-x64': 0.27.0 2498 + '@esbuild/win32-arm64': 0.27.0 2499 + '@esbuild/win32-ia32': 0.27.0 2500 + '@esbuild/win32-x64': 0.27.0 2588 2501 2589 2502 escalade@3.2.0: {} 2590 2503 2591 2504 esm-env@1.2.2: {} 2592 2505 2593 2506 exit-hook@2.2.1: {} 2594 - 2595 - exsolve@1.0.5: {} 2596 2507 2597 2508 fast-glob@3.3.3: 2598 2509 dependencies: ··· 2606 2517 dependencies: 2607 2518 reusify: 1.1.0 2608 2519 2609 - fdir@6.4.4(picomatch@4.0.2): 2520 + fdir@6.5.0(picomatch@4.0.3): 2610 2521 optionalDependencies: 2611 - picomatch: 4.0.2 2522 + picomatch: 4.0.3 2612 2523 2613 2524 fetch-blob@3.2.0: 2614 2525 dependencies: ··· 2620 2531 dependencies: 2621 2532 to-regex-range: 5.0.1 2622 2533 2623 - foreground-child@3.3.1: 2624 - dependencies: 2625 - cross-spawn: 7.0.6 2626 - signal-exit: 4.1.0 2627 - 2628 - fraction.js@4.3.7: {} 2534 + fraction.js@5.3.4: {} 2629 2535 2630 2536 fsevents@2.3.3: 2631 2537 optional: true ··· 2634 2540 2635 2541 gensync@1.0.0-beta.2: {} 2636 2542 2637 - get-source@2.0.12: 2638 - dependencies: 2639 - data-uri-to-buffer: 2.0.2 2640 - source-map: 0.6.1 2641 - 2642 2543 glob-parent@5.1.2: 2643 2544 dependencies: 2644 2545 is-glob: 4.0.3 ··· 2649 2550 2650 2551 glob-to-regexp@0.4.1: {} 2651 2552 2652 - glob@10.4.5: 2653 - dependencies: 2654 - foreground-child: 3.3.1 2655 - jackspeak: 3.4.3 2656 - minimatch: 9.0.5 2657 - minipass: 7.1.2 2658 - package-json-from-dist: 1.0.1 2659 - path-scurry: 1.11.1 2660 - 2661 - globals@11.12.0: {} 2662 - 2663 2553 hasown@2.0.2: 2664 2554 dependencies: 2665 2555 function-bind: 1.1.2 2666 2556 2667 2557 html-entities@2.3.3: {} 2668 2558 2669 - is-arrayish@0.3.2: {} 2559 + is-arrayish@0.3.4: {} 2670 2560 2671 2561 is-binary-path@2.1.0: 2672 2562 dependencies: ··· 2678 2568 2679 2569 is-extglob@2.1.1: {} 2680 2570 2681 - is-fullwidth-code-point@3.0.0: {} 2682 - 2683 2571 is-glob@4.0.3: 2684 2572 dependencies: 2685 2573 is-extglob: 2.1.1 ··· 2688 2576 2689 2577 is-what@4.1.16: {} 2690 2578 2691 - isexe@2.0.0: {} 2692 - 2693 - jackspeak@3.4.3: 2694 - dependencies: 2695 - '@isaacs/cliui': 8.0.2 2696 - optionalDependencies: 2697 - '@pkgjs/parseargs': 0.11.0 2698 - 2699 2579 jiti@1.21.7: {} 2700 2580 2701 2581 js-tokens@4.0.0: {} ··· 2704 2584 2705 2585 json5@2.2.3: {} 2706 2586 2587 + kleur@4.1.5: {} 2588 + 2707 2589 lilconfig@3.1.3: {} 2708 2590 2709 2591 lines-and-columns@1.2.4: {} 2710 2592 2711 - lru-cache@10.4.3: {} 2712 - 2713 2593 lru-cache@5.1.1: 2714 2594 dependencies: 2715 2595 yallist: 3.1.1 ··· 2729 2609 2730 2610 mini-svg-data-uri@1.4.4: {} 2731 2611 2732 - miniflare@4.20250508.3: 2612 + miniflare@4.20251202.1: 2733 2613 dependencies: 2734 2614 '@cspotcode/source-map-support': 0.8.1 2735 2615 acorn: 8.14.0 ··· 2738 2618 glob-to-regexp: 0.4.1 2739 2619 sharp: 0.33.5 2740 2620 stoppable: 1.1.0 2741 - undici: 5.29.0 2742 - workerd: 1.20250508.0 2621 + undici: 7.14.0 2622 + workerd: 1.20251202.0 2743 2623 ws: 8.18.0 2744 - youch: 3.3.4 2624 + youch: 4.1.0-beta.10 2745 2625 zod: 3.22.3 2746 2626 transitivePeerDependencies: 2747 2627 - bufferutil 2748 2628 - utf-8-validate 2749 2629 2750 - minimatch@9.0.5: 2751 - dependencies: 2752 - brace-expansion: 2.0.1 2753 - 2754 - minipass@7.1.2: {} 2755 - 2756 2630 ms@2.1.3: {} 2757 - 2758 - mustache@4.2.0: {} 2759 2631 2760 2632 mz@2.7.0: 2761 2633 dependencies: ··· 2765 2637 2766 2638 nanoid@3.3.11: {} 2767 2639 2768 - nanoid@5.1.5: {} 2640 + nanoid@5.1.6: {} 2769 2641 2770 2642 native-file-system-adapter@3.0.1: 2771 2643 optionalDependencies: ··· 2774 2646 node-domexception@1.0.0: 2775 2647 optional: true 2776 2648 2777 - node-releases@2.0.19: {} 2649 + node-releases@2.0.27: {} 2778 2650 2779 2651 normalize-path@3.0.0: {} 2780 2652 ··· 2783 2655 object-assign@4.1.1: {} 2784 2656 2785 2657 object-hash@3.0.0: {} 2786 - 2787 - ohash@2.0.11: {} 2788 - 2789 - package-json-from-dist@1.0.1: {} 2790 2658 2791 2659 parse5@7.3.0: 2792 2660 dependencies: 2793 - entities: 6.0.0 2794 - 2795 - path-key@3.1.1: {} 2661 + entities: 6.0.1 2796 2662 2797 2663 path-parse@1.0.7: {} 2798 2664 2799 - path-scurry@1.11.1: 2800 - dependencies: 2801 - lru-cache: 10.4.3 2802 - minipass: 7.1.2 2803 - 2804 2665 path-to-regexp@6.3.0: {} 2805 2666 2806 2667 pathe@2.0.3: {} ··· 2809 2670 2810 2671 picomatch@2.3.1: {} 2811 2672 2812 - picomatch@4.0.2: {} 2673 + picomatch@4.0.3: {} 2813 2674 2814 2675 pify@2.3.0: {} 2815 2676 2816 2677 pirates@4.0.7: {} 2817 2678 2818 - postcss-import@15.1.0(postcss@8.5.3): 2679 + postcss-import@15.1.0(postcss@8.5.6): 2819 2680 dependencies: 2820 - postcss: 8.5.3 2681 + postcss: 8.5.6 2821 2682 postcss-value-parser: 4.2.0 2822 2683 read-cache: 1.0.0 2823 - resolve: 1.22.10 2684 + resolve: 1.22.11 2824 2685 2825 - postcss-js@4.0.1(postcss@8.5.3): 2686 + postcss-js@4.1.0(postcss@8.5.6): 2826 2687 dependencies: 2827 2688 camelcase-css: 2.0.1 2828 - postcss: 8.5.3 2689 + postcss: 8.5.6 2829 2690 2830 - postcss-load-config@4.0.2(postcss@8.5.3): 2691 + postcss-load-config@6.0.1(jiti@1.21.7)(postcss@8.5.6): 2831 2692 dependencies: 2832 2693 lilconfig: 3.1.3 2833 - yaml: 2.8.0 2834 2694 optionalDependencies: 2835 - postcss: 8.5.3 2695 + jiti: 1.21.7 2696 + postcss: 8.5.6 2836 2697 2837 - postcss-nested@6.2.0(postcss@8.5.3): 2698 + postcss-nested@6.2.0(postcss@8.5.6): 2838 2699 dependencies: 2839 - postcss: 8.5.3 2700 + postcss: 8.5.6 2840 2701 postcss-selector-parser: 6.1.2 2841 2702 2842 2703 postcss-selector-parser@6.1.2: ··· 2846 2707 2847 2708 postcss-value-parser@4.2.0: {} 2848 2709 2849 - postcss@8.5.3: 2710 + postcss@8.5.6: 2850 2711 dependencies: 2851 2712 nanoid: 3.3.11 2852 2713 picocolors: 1.1.1 2853 2714 source-map-js: 1.2.1 2854 2715 2855 - prettier-plugin-tailwindcss@0.6.11(prettier@3.5.3): 2716 + prettier-plugin-tailwindcss@0.6.14(prettier@3.7.4): 2856 2717 dependencies: 2857 - prettier: 3.5.3 2858 - 2859 - prettier@3.5.3: {} 2718 + prettier: 3.7.4 2860 2719 2861 - printable-characters@1.0.42: {} 2720 + prettier@3.7.4: {} 2862 2721 2863 2722 queue-microtask@1.2.3: {} 2864 2723 ··· 2870 2729 dependencies: 2871 2730 picomatch: 2.3.1 2872 2731 2873 - resolve@1.22.10: 2732 + resolve@1.22.11: 2874 2733 dependencies: 2875 2734 is-core-module: 2.16.1 2876 2735 path-parse: 1.0.7 ··· 2878 2737 2879 2738 reusify@1.1.0: {} 2880 2739 2881 - rollup@4.41.1: 2740 + rollup@4.53.3: 2882 2741 dependencies: 2883 - '@types/estree': 1.0.7 2742 + '@types/estree': 1.0.8 2884 2743 optionalDependencies: 2885 - '@rollup/rollup-android-arm-eabi': 4.41.1 2886 - '@rollup/rollup-android-arm64': 4.41.1 2887 - '@rollup/rollup-darwin-arm64': 4.41.1 2888 - '@rollup/rollup-darwin-x64': 4.41.1 2889 - '@rollup/rollup-freebsd-arm64': 4.41.1 2890 - '@rollup/rollup-freebsd-x64': 4.41.1 2891 - '@rollup/rollup-linux-arm-gnueabihf': 4.41.1 2892 - '@rollup/rollup-linux-arm-musleabihf': 4.41.1 2893 - '@rollup/rollup-linux-arm64-gnu': 4.41.1 2894 - '@rollup/rollup-linux-arm64-musl': 4.41.1 2895 - '@rollup/rollup-linux-loongarch64-gnu': 4.41.1 2896 - '@rollup/rollup-linux-powerpc64le-gnu': 4.41.1 2897 - '@rollup/rollup-linux-riscv64-gnu': 4.41.1 2898 - '@rollup/rollup-linux-riscv64-musl': 4.41.1 2899 - '@rollup/rollup-linux-s390x-gnu': 4.41.1 2900 - '@rollup/rollup-linux-x64-gnu': 4.41.1 2901 - '@rollup/rollup-linux-x64-musl': 4.41.1 2902 - '@rollup/rollup-win32-arm64-msvc': 4.41.1 2903 - '@rollup/rollup-win32-ia32-msvc': 4.41.1 2904 - '@rollup/rollup-win32-x64-msvc': 4.41.1 2744 + '@rollup/rollup-android-arm-eabi': 4.53.3 2745 + '@rollup/rollup-android-arm64': 4.53.3 2746 + '@rollup/rollup-darwin-arm64': 4.53.3 2747 + '@rollup/rollup-darwin-x64': 4.53.3 2748 + '@rollup/rollup-freebsd-arm64': 4.53.3 2749 + '@rollup/rollup-freebsd-x64': 4.53.3 2750 + '@rollup/rollup-linux-arm-gnueabihf': 4.53.3 2751 + '@rollup/rollup-linux-arm-musleabihf': 4.53.3 2752 + '@rollup/rollup-linux-arm64-gnu': 4.53.3 2753 + '@rollup/rollup-linux-arm64-musl': 4.53.3 2754 + '@rollup/rollup-linux-loong64-gnu': 4.53.3 2755 + '@rollup/rollup-linux-ppc64-gnu': 4.53.3 2756 + '@rollup/rollup-linux-riscv64-gnu': 4.53.3 2757 + '@rollup/rollup-linux-riscv64-musl': 4.53.3 2758 + '@rollup/rollup-linux-s390x-gnu': 4.53.3 2759 + '@rollup/rollup-linux-x64-gnu': 4.53.3 2760 + '@rollup/rollup-linux-x64-musl': 4.53.3 2761 + '@rollup/rollup-openharmony-arm64': 4.53.3 2762 + '@rollup/rollup-win32-arm64-msvc': 4.53.3 2763 + '@rollup/rollup-win32-ia32-msvc': 4.53.3 2764 + '@rollup/rollup-win32-x64-gnu': 4.53.3 2765 + '@rollup/rollup-win32-x64-msvc': 4.53.3 2905 2766 fsevents: 2.3.3 2906 2767 2907 2768 run-parallel@1.2.0: ··· 2910 2771 2911 2772 semver@6.3.1: {} 2912 2773 2913 - semver@7.7.2: {} 2774 + semver@7.7.3: {} 2914 2775 2915 - seroval-plugins@1.3.2(seroval@1.3.2): 2776 + seroval-plugins@1.3.3(seroval@1.3.2): 2916 2777 dependencies: 2917 2778 seroval: 1.3.2 2918 2779 ··· 2921 2782 sharp@0.33.5: 2922 2783 dependencies: 2923 2784 color: 4.2.3 2924 - detect-libc: 2.0.4 2925 - semver: 7.7.2 2785 + detect-libc: 2.1.2 2786 + semver: 7.7.3 2926 2787 optionalDependencies: 2927 2788 '@img/sharp-darwin-arm64': 0.33.5 2928 2789 '@img/sharp-darwin-x64': 0.33.5 ··· 2944 2805 '@img/sharp-win32-ia32': 0.33.5 2945 2806 '@img/sharp-win32-x64': 0.33.5 2946 2807 2947 - shebang-command@2.0.0: 2948 - dependencies: 2949 - shebang-regex: 3.0.0 2950 - 2951 - shebang-regex@3.0.0: {} 2952 - 2953 - signal-exit@4.1.0: {} 2954 - 2955 - simple-swizzle@0.2.2: 2808 + simple-swizzle@0.2.4: 2956 2809 dependencies: 2957 - is-arrayish: 0.3.2 2810 + is-arrayish: 0.3.4 2958 2811 2959 - solid-js@1.9.7: 2812 + solid-js@1.9.10: 2960 2813 dependencies: 2961 - csstype: 3.1.3 2814 + csstype: 3.2.3 2962 2815 seroval: 1.3.2 2963 - seroval-plugins: 1.3.2(seroval@1.3.2) 2816 + seroval-plugins: 1.3.3(seroval@1.3.2) 2964 2817 2965 - solid-refresh@0.6.3(solid-js@1.9.7): 2818 + solid-refresh@0.6.3(solid-js@1.9.10): 2966 2819 dependencies: 2967 - '@babel/generator': 7.27.1 2820 + '@babel/generator': 7.28.5 2968 2821 '@babel/helper-module-imports': 7.27.1 2969 - '@babel/types': 7.27.1 2970 - solid-js: 1.9.7 2822 + '@babel/types': 7.28.5 2823 + solid-js: 1.9.10 2971 2824 transitivePeerDependencies: 2972 2825 - supports-color 2973 2826 ··· 2980 2833 2981 2834 source-map@0.6.1: {} 2982 2835 2983 - stacktracey@2.1.8: 2984 - dependencies: 2985 - as-table: 1.0.55 2986 - get-source: 2.0.12 2987 - 2988 2836 stoppable@1.1.0: {} 2989 2837 2990 - string-width@4.2.3: 2991 - dependencies: 2992 - emoji-regex: 8.0.0 2993 - is-fullwidth-code-point: 3.0.0 2994 - strip-ansi: 6.0.1 2995 - 2996 - string-width@5.1.2: 2997 - dependencies: 2998 - eastasianwidth: 0.2.0 2999 - emoji-regex: 9.2.2 3000 - strip-ansi: 7.1.0 3001 - 3002 - strip-ansi@6.0.1: 2838 + sucrase@3.35.1: 3003 2839 dependencies: 3004 - ansi-regex: 5.0.1 3005 - 3006 - strip-ansi@7.1.0: 3007 - dependencies: 3008 - ansi-regex: 6.1.0 3009 - 3010 - sucrase@3.35.0: 3011 - dependencies: 3012 - '@jridgewell/gen-mapping': 0.3.8 2840 + '@jridgewell/gen-mapping': 0.3.13 3013 2841 commander: 4.1.1 3014 - glob: 10.4.5 3015 2842 lines-and-columns: 1.2.4 3016 2843 mz: 2.7.0 3017 2844 pirates: 4.0.7 2845 + tinyglobby: 0.2.15 3018 2846 ts-interface-checker: 0.1.13 3019 2847 2848 + supports-color@10.2.2: {} 2849 + 3020 2850 supports-preserve-symlinks-flag@1.0.0: {} 3021 2851 3022 - tailwindcss@3.4.17: 2852 + tailwindcss@3.4.18: 3023 2853 dependencies: 3024 2854 '@alloc/quick-lru': 5.2.0 3025 2855 arg: 5.0.2 ··· 3035 2865 normalize-path: 3.0.0 3036 2866 object-hash: 3.0.0 3037 2867 picocolors: 1.1.1 3038 - postcss: 8.5.3 3039 - postcss-import: 15.1.0(postcss@8.5.3) 3040 - postcss-js: 4.0.1(postcss@8.5.3) 3041 - postcss-load-config: 4.0.2(postcss@8.5.3) 3042 - postcss-nested: 6.2.0(postcss@8.5.3) 2868 + postcss: 8.5.6 2869 + postcss-import: 15.1.0(postcss@8.5.6) 2870 + postcss-js: 4.1.0(postcss@8.5.6) 2871 + postcss-load-config: 6.0.1(jiti@1.21.7)(postcss@8.5.6) 2872 + postcss-nested: 6.2.0(postcss@8.5.6) 3043 2873 postcss-selector-parser: 6.1.2 3044 - resolve: 1.22.10 3045 - sucrase: 3.35.0 2874 + resolve: 1.22.11 2875 + sucrase: 3.35.1 3046 2876 transitivePeerDependencies: 3047 - - ts-node 2877 + - tsx 2878 + - yaml 3048 2879 3049 - terser@5.39.2: 2880 + terser@5.44.1: 3050 2881 dependencies: 3051 - '@jridgewell/source-map': 0.3.6 3052 - acorn: 8.14.1 2882 + '@jridgewell/source-map': 0.3.11 2883 + acorn: 8.15.0 3053 2884 commander: 2.20.3 3054 2885 source-map-support: 0.5.21 3055 2886 ··· 3061 2892 dependencies: 3062 2893 any-promise: 1.3.0 3063 2894 3064 - tinyglobby@0.2.14: 2895 + tinyglobby@0.2.15: 3065 2896 dependencies: 3066 - fdir: 6.4.4(picomatch@4.0.2) 3067 - picomatch: 4.0.2 2897 + fdir: 6.5.0(picomatch@4.0.3) 2898 + picomatch: 4.0.3 3068 2899 3069 2900 to-regex-range@5.0.1: 3070 2901 dependencies: ··· 3075 2906 tslib@2.8.1: 3076 2907 optional: true 3077 2908 3078 - typescript@5.8.3: {} 3079 - 3080 - ufo@1.6.1: {} 2909 + typescript@5.9.3: {} 3081 2910 3082 2911 undici-types@6.21.0: {} 3083 2912 3084 - undici@5.29.0: 3085 - dependencies: 3086 - '@fastify/busboy': 2.1.1 2913 + undici@7.14.0: {} 3087 2914 3088 - unenv@2.0.0-rc.17: 2915 + unenv@2.0.0-rc.24: 3089 2916 dependencies: 3090 - defu: 6.1.4 3091 - exsolve: 1.0.5 3092 - ohash: 2.0.11 3093 2917 pathe: 2.0.3 3094 - ufo: 1.6.1 3095 2918 3096 - update-browserslist-db@1.1.3(browserslist@4.24.5): 2919 + update-browserslist-db@1.2.2(browserslist@4.28.1): 3097 2920 dependencies: 3098 - browserslist: 4.24.5 2921 + browserslist: 4.28.1 3099 2922 escalade: 3.2.0 3100 2923 picocolors: 1.1.1 3101 2924 3102 2925 util-deprecate@1.0.2: {} 3103 2926 3104 - validate-html-nesting@1.2.2: {} 3105 - 3106 - vite-plugin-solid@2.11.6(solid-js@1.9.7)(vite@6.3.5(@types/node@22.15.21)(jiti@1.21.7)(terser@5.39.2)(yaml@2.8.0)): 2927 + vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.2.7(@types/node@22.19.2)(jiti@1.21.7)(terser@5.44.1)): 3107 2928 dependencies: 3108 - '@babel/core': 7.27.1 2929 + '@babel/core': 7.28.5 3109 2930 '@types/babel__core': 7.20.5 3110 - babel-preset-solid: 1.9.6(@babel/core@7.27.1) 2931 + babel-preset-solid: 1.9.10(@babel/core@7.28.5)(solid-js@1.9.10) 3111 2932 merge-anything: 5.1.7 3112 - solid-js: 1.9.7 3113 - solid-refresh: 0.6.3(solid-js@1.9.7) 3114 - vite: 6.3.5(@types/node@22.15.21)(jiti@1.21.7)(terser@5.39.2)(yaml@2.8.0) 3115 - vitefu: 1.0.6(vite@6.3.5(@types/node@22.15.21)(jiti@1.21.7)(terser@5.39.2)(yaml@2.8.0)) 2933 + solid-js: 1.9.10 2934 + solid-refresh: 0.6.3(solid-js@1.9.10) 2935 + vite: 7.2.7(@types/node@22.19.2)(jiti@1.21.7)(terser@5.44.1) 2936 + vitefu: 1.1.1(vite@7.2.7(@types/node@22.19.2)(jiti@1.21.7)(terser@5.44.1)) 3116 2937 transitivePeerDependencies: 3117 2938 - supports-color 3118 2939 3119 - vite@6.3.5(@types/node@22.15.21)(jiti@1.21.7)(terser@5.39.2)(yaml@2.8.0): 2940 + vite@7.2.7(@types/node@22.19.2)(jiti@1.21.7)(terser@5.44.1): 3120 2941 dependencies: 3121 - esbuild: 0.25.5 3122 - fdir: 6.4.4(picomatch@4.0.2) 3123 - picomatch: 4.0.2 3124 - postcss: 8.5.3 3125 - rollup: 4.41.1 3126 - tinyglobby: 0.2.14 2942 + esbuild: 0.25.12 2943 + fdir: 6.5.0(picomatch@4.0.3) 2944 + picomatch: 4.0.3 2945 + postcss: 8.5.6 2946 + rollup: 4.53.3 2947 + tinyglobby: 0.2.15 3127 2948 optionalDependencies: 3128 - '@types/node': 22.15.21 2949 + '@types/node': 22.19.2 3129 2950 fsevents: 2.3.3 3130 2951 jiti: 1.21.7 3131 - terser: 5.39.2 3132 - yaml: 2.8.0 2952 + terser: 5.44.1 3133 2953 3134 - vitefu@1.0.6(vite@6.3.5(@types/node@22.15.21)(jiti@1.21.7)(terser@5.39.2)(yaml@2.8.0)): 2954 + vitefu@1.1.1(vite@7.2.7(@types/node@22.19.2)(jiti@1.21.7)(terser@5.44.1)): 3135 2955 optionalDependencies: 3136 - vite: 6.3.5(@types/node@22.15.21)(jiti@1.21.7)(terser@5.39.2)(yaml@2.8.0) 2956 + vite: 7.2.7(@types/node@22.19.2)(jiti@1.21.7)(terser@5.44.1) 3137 2957 3138 2958 web-streams-polyfill@3.3.3: 3139 2959 optional: true 3140 2960 3141 - which@2.0.2: 3142 - dependencies: 3143 - isexe: 2.0.0 3144 - 3145 - workerd@1.20250508.0: 2961 + workerd@1.20251202.0: 3146 2962 optionalDependencies: 3147 - '@cloudflare/workerd-darwin-64': 1.20250508.0 3148 - '@cloudflare/workerd-darwin-arm64': 1.20250508.0 3149 - '@cloudflare/workerd-linux-64': 1.20250508.0 3150 - '@cloudflare/workerd-linux-arm64': 1.20250508.0 3151 - '@cloudflare/workerd-windows-64': 1.20250508.0 2963 + '@cloudflare/workerd-darwin-64': 1.20251202.0 2964 + '@cloudflare/workerd-darwin-arm64': 1.20251202.0 2965 + '@cloudflare/workerd-linux-64': 1.20251202.0 2966 + '@cloudflare/workerd-linux-arm64': 1.20251202.0 2967 + '@cloudflare/workerd-windows-64': 1.20251202.0 3152 2968 3153 - wrangler@4.16.1: 2969 + wrangler@4.53.0: 3154 2970 dependencies: 3155 - '@cloudflare/kv-asset-handler': 0.4.0 3156 - '@cloudflare/unenv-preset': 2.3.2(unenv@2.0.0-rc.17)(workerd@1.20250508.0) 2971 + '@cloudflare/kv-asset-handler': 0.4.1 2972 + '@cloudflare/unenv-preset': 2.7.13(unenv@2.0.0-rc.24)(workerd@1.20251202.0) 3157 2973 blake3-wasm: 2.1.5 3158 - esbuild: 0.25.4 3159 - miniflare: 4.20250508.3 2974 + esbuild: 0.27.0 2975 + miniflare: 4.20251202.1 3160 2976 path-to-regexp: 6.3.0 3161 - unenv: 2.0.0-rc.17 3162 - workerd: 1.20250508.0 2977 + unenv: 2.0.0-rc.24 2978 + workerd: 1.20251202.0 3163 2979 optionalDependencies: 3164 2980 fsevents: 2.3.3 3165 - sharp: 0.33.5 3166 2981 transitivePeerDependencies: 3167 2982 - bufferutil 3168 2983 - utf-8-validate 3169 2984 3170 - wrap-ansi@7.0.0: 3171 - dependencies: 3172 - ansi-styles: 4.3.0 3173 - string-width: 4.2.3 3174 - strip-ansi: 6.0.1 3175 - 3176 - wrap-ansi@8.1.0: 3177 - dependencies: 3178 - ansi-styles: 6.2.1 3179 - string-width: 5.1.2 3180 - strip-ansi: 7.1.0 3181 - 3182 2985 ws@8.18.0: {} 3183 2986 3184 2987 yallist@3.1.1: {} 3185 2988 3186 - yaml@2.8.0: {} 3187 - 3188 - yocto-queue@1.2.1: {} 2989 + youch-core@0.3.3: 2990 + dependencies: 2991 + '@poppinss/exception': 1.2.2 2992 + error-stack-parser-es: 1.0.5 3189 2993 3190 - youch@3.3.4: 2994 + youch@4.1.0-beta.10: 3191 2995 dependencies: 3192 - cookie: 0.7.2 3193 - mustache: 4.2.0 3194 - stacktracey: 2.1.8 2996 + '@poppinss/colors': 4.1.5 2997 + '@poppinss/dumper': 0.6.5 2998 + '@speed-highlight/core': 1.2.12 2999 + cookie: 1.1.1 3000 + youch-core: 0.3.3 3195 3001 3196 3002 zod@3.22.3: {}
+2
pnpm-workspace.yaml
··· 1 + onlyBuiltDependencies: 2 + - esbuild
+1 -1
src/api/queries/plc.ts
··· 1 1 import { defs } from '@atcute/did-plc'; 2 - import { Did } from '@atcute/lexicons/syntax'; 2 + import type { Did } from '@atcute/lexicons/syntax'; 3 3 4 4 export const getPlcAuditLogs = async ({ did, signal }: { did: Did<'plc'>; signal?: AbortSignal }) => { 5 5 const origin = import.meta.env.VITE_PLC_DIRECTORY_URL;
+2 -2
src/api/types/plc.ts
··· 1 1 import * as v from '@badrap/valita'; 2 2 3 - import { defs, UnsignedOperation } from '@atcute/did-plc'; 3 + import { defs, type UnsignedOperation } from '@atcute/did-plc'; 4 4 5 - import { ToValidator } from '../utils/valita'; 5 + import type { ToValidator } from '../utils/valita'; 6 6 import { serviceUrlString } from './strings'; 7 7 8 8 const _unsignedOperation = defs.unsignedOperation as ToValidator<UnsignedOperation>;
+72
src/components/accordion.tsx
··· 1 + import { createSignal, type JSX, Show } from 'solid-js'; 2 + 3 + import ChevronRightIcon from '~/components/ic-icons/baseline-chevron-right'; 4 + 5 + export interface AccordionProps { 6 + title: string; 7 + children: JSX.Element; 8 + defaultOpen?: boolean; 9 + } 10 + 11 + export const Accordion = (props: AccordionProps) => { 12 + const [isOpen, setIsOpen] = createSignal(props.defaultOpen ?? false); 13 + 14 + return ( 15 + <div class="border-b border-gray-200"> 16 + <button 17 + type="button" 18 + onClick={() => setIsOpen(!isOpen())} 19 + class="flex w-full items-center gap-3 px-4 py-3 text-left hover:bg-gray-50" 20 + > 21 + <ChevronRightIcon 22 + class={`h-5 w-5 text-gray-500 transition-transform` + (isOpen() ? ` rotate-90` : ``)} 23 + /> 24 + <span class="font-semibold">{props.title}</span> 25 + </button> 26 + 27 + <Show when={isOpen()}> 28 + <div class="pb-4 pl-12 pr-4">{props.children}</div> 29 + </Show> 30 + </div> 31 + ); 32 + }; 33 + 34 + export interface SubsectionProps { 35 + title: string; 36 + children: JSX.Element; 37 + } 38 + 39 + export const Subsection = (props: SubsectionProps) => { 40 + return ( 41 + <div class="mb-4 last:mb-0"> 42 + <h4 class="mb-3 text-sm font-semibold text-gray-600">{props.title}</h4> 43 + <div class="flex flex-col gap-3">{props.children}</div> 44 + </div> 45 + ); 46 + }; 47 + 48 + export interface StatusBadgeProps { 49 + variant: 'idle' | 'pending' | 'success' | 'error'; 50 + children: JSX.Element; 51 + } 52 + 53 + export const StatusBadge = (props: StatusBadgeProps) => { 54 + const variantStyles = () => { 55 + switch (props.variant) { 56 + case 'idle': 57 + return 'bg-gray-100 text-gray-600'; 58 + case 'pending': 59 + return 'bg-yellow-100 text-yellow-800'; 60 + case 'success': 61 + return 'bg-green-100 text-green-800'; 62 + case 'error': 63 + return 'bg-red-100 text-red-800'; 64 + } 65 + }; 66 + 67 + return ( 68 + <span class={`inline-flex items-center rounded px-2 py-0.5 text-xs font-medium ${variantStyles()}`}> 69 + {props.children} 70 + </span> 71 + ); 72 + };
+65
src/components/file-drop-zone.tsx
··· 1 + import type { JSX } from 'solid-js'; 2 + 3 + import { createDropZone, type CreateDropZoneOptions } from '~/lib/hooks/dropzone'; 4 + 5 + import Button from './inputs/button'; 6 + 7 + interface FileDropZoneProps { 8 + accept?: string; 9 + disabled?: boolean; 10 + onFiles: (files: File[]) => void; 11 + dataTypes?: CreateDropZoneOptions['dataTypes']; 12 + multiple?: boolean; 13 + children?: JSX.Element; 14 + } 15 + 16 + const FileDropZone = (props: FileDropZoneProps) => { 17 + const { ref: dropRef, isDropping } = createDropZone({ 18 + dataTypes: props.dataTypes, 19 + multiple: props.multiple ?? false, 20 + onDrop(files) { 21 + if (files) { 22 + props.onFiles(files); 23 + } 24 + }, 25 + }); 26 + 27 + const handleBrowse = () => { 28 + const input = document.createElement('input'); 29 + input.type = 'file'; 30 + if (props.accept) { 31 + input.accept = props.accept; 32 + } 33 + if (props.multiple) { 34 + input.multiple = true; 35 + } 36 + input.oninput = () => { 37 + const files = Array.from(input.files!); 38 + if (files.length > 0) { 39 + props.onFiles(files); 40 + } 41 + }; 42 + input.click(); 43 + }; 44 + 45 + return ( 46 + <fieldset 47 + ref={dropRef} 48 + disabled={props.disabled} 49 + class={ 50 + `relative grid place-items-center rounded border border-gray-300 px-6 py-12 disabled:opacity-50` + 51 + (props.disabled || !isDropping() ? ` bg-gray-100` : ` bg-green-100`) 52 + } 53 + > 54 + <div class="flex flex-col items-center gap-4"> 55 + <Button variant="outline" onClick={handleBrowse}> 56 + Browse files 57 + </Button> 58 + <p class="select-none font-medium text-gray-600">or drop your file here</p> 59 + </div> 60 + {props.children} 61 + </fieldset> 62 + ); 63 + }; 64 + 65 + export default FileDropZone;
+27 -12
src/components/inputs/button.tsx
··· 1 - import { JSX } from 'solid-js'; 1 + import { createMemo, type JSX } from 'solid-js'; 2 2 3 3 interface ButtonProps { 4 4 children?: JSX.Element; 5 5 disabled?: boolean; 6 - variant?: 'primary' | 'secondary'; 6 + variant?: 'primary' | 'secondary' | 'outline'; 7 7 type?: 'button' | 'submit'; 8 + href?: string; 8 9 onClick?: JSX.EventHandlerUnion<HTMLButtonElement, MouseEvent>; 9 10 } 10 11 ··· 15 16 cn += ` bg-purple-800 text-white hover:bg-purple-700 active:bg-purple-700`; 16 17 } else if (variant === 'secondary') { 17 18 cn += ` bg-gray-200 text-black hover:bg-gray-300 active:bg-gray-300`; 19 + } else if (variant === 'outline') { 20 + cn += ` border border-gray-300 text-gray-800 hover:bg-gray-100 active:bg-gray-100`; 18 21 } 19 22 20 23 if (disabled) { ··· 25 28 }; 26 29 27 30 const Button = (props: ButtonProps) => { 28 - return ( 29 - <button 30 - type={props.type ?? 'button'} 31 - disabled={props.disabled} 32 - class={buttonStyles(props)} 33 - onClick={props.onClick} 34 - > 35 - {props.children} 36 - </button> 37 - ); 31 + const hasLink = createMemo(() => props.href !== undefined); 32 + 33 + return (() => { 34 + if (hasLink()) { 35 + return ( 36 + <a href={!props.disabled ? props.href : undefined} class={buttonStyles(props)}> 37 + {props.children} 38 + </a> 39 + ); 40 + } 41 + 42 + return ( 43 + <button 44 + type={props.type ?? 'button'} 45 + disabled={props.disabled} 46 + class={buttonStyles(props)} 47 + onClick={props.onClick} 48 + > 49 + {props.children} 50 + </button> 51 + ); 52 + }) as unknown as JSX.Element; 38 53 }; 39 54 40 55 export default Button;
+2 -2
src/components/inputs/multiline-input.tsx
··· 1 - import { createEffect, JSX } from 'solid-js'; 1 + import { createEffect, type JSX } from 'solid-js'; 2 2 3 3 import { createId } from '~/lib/hooks/id'; 4 4 5 - import { BoundInputEvent } from './_types'; 5 + import type { BoundInputEvent } from './_types'; 6 6 7 7 interface MultilineInputProps { 8 8 label: JSX.Element;
+2 -2
src/components/inputs/radio-input.tsx
··· 1 - import { JSX } from 'solid-js'; 1 + import type { JSX } from 'solid-js'; 2 2 3 3 import { createId } from '~/lib/hooks/id'; 4 4 5 - import { BoundInputEvent } from './_types'; 5 + import type { BoundInputEvent } from './_types'; 6 6 7 7 interface RadioInputProps<T extends string> { 8 8 label: JSX.Element;
+2 -2
src/components/inputs/select-input.tsx
··· 1 - import { createEffect, JSX } from 'solid-js'; 1 + import { createEffect, type JSX } from 'solid-js'; 2 2 3 3 import { createId } from '~/lib/hooks/id'; 4 4 5 - import { BoundInputEvent } from './_types'; 5 + import type { BoundInputEvent } from './_types'; 6 6 7 7 interface SelectInputProps<T extends string> { 8 8 label: JSX.Element;
+5 -3
src/components/inputs/text-input.tsx
··· 1 - import { createEffect, JSX } from 'solid-js'; 1 + import { createEffect, type JSX } from 'solid-js'; 2 2 3 3 import { createId } from '~/lib/hooks/id'; 4 4 5 - import { BoundInputEvent } from './_types'; 5 + import type { BoundInputEvent } from './_types'; 6 6 7 - interface TextInputProps { 7 + export interface TextInputProps { 8 8 label: JSX.Element; 9 9 blurb?: JSX.Element; 10 10 monospace?: boolean; 11 11 type?: 'text' | 'password' | 'url' | 'email'; 12 12 name?: string; 13 13 required?: boolean; 14 + disabled?: boolean; 14 15 autocomplete?: 'off' | 'on' | 'one-time-code' | 'username'; 15 16 autocorrect?: 'off' | 'on'; 16 17 pattern?: string; ··· 55 56 id={fieldId} 56 57 name={props.name} 57 58 required={props.required} 59 + disabled={props.disabled} 58 60 autocomplete={props.autocomplete} 59 61 pattern={props.pattern} 60 62 placeholder={props.placeholder}
+1 -1
src/components/inputs/toggle-input.tsx
··· 2 2 3 3 import { createId } from '~/lib/hooks/id'; 4 4 5 - import { BoundInputEvent } from './_types'; 5 + import type { BoundInputEvent } from './_types'; 6 6 7 7 export interface ToggleInputProps { 8 8 label: string;
+22
src/components/page-header.tsx
··· 1 + import type { JSX } from 'solid-js'; 2 + 3 + interface PageHeaderProps { 4 + title: string; 5 + subtitle?: string; 6 + children?: JSX.Element; 7 + } 8 + 9 + const PageHeader = (props: PageHeaderProps) => { 10 + return ( 11 + <> 12 + <div class="p-4"> 13 + <h1 class="text-lg font-bold text-purple-800">{props.title}</h1> 14 + {props.subtitle && <p class="text-gray-600">{props.subtitle}</p>} 15 + {props.children} 16 + </div> 17 + <hr class="mx-4 border-gray-300" /> 18 + </> 19 + ); 20 + }; 21 + 22 + export default PageHeader;
+1 -1
src/components/wizard.tsx
··· 1 - import { Component, createMemo, createSignal, For, JSX } from 'solid-js'; 1 + import { type Component, createMemo, createSignal, For, type JSX } from 'solid-js'; 2 2 3 3 type EmptyObjectKeys<T> = { 4 4 [K in keyof T]: T[K] extends Record<string, never> ? K : never;
+104 -4
src/lib/utils/confirmation-code.ts
··· 1 - import { customAlphabet } from 'nanoid'; 1 + import { sample } from '@mary/array-fns'; 2 2 3 - const generateCode = customAlphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', 10); 3 + const words = [ 4 + 'abroad', 5 + 'acorn', 6 + 'anaconda', 7 + 'anchovy', 8 + 'aorta', 9 + 'argue', 10 + 'ashy', 11 + 'astound', 12 + 'attest', 13 + 'babied', 14 + 'bobcat', 15 + 'bondless', 16 + 'bullion', 17 + 'bunny', 18 + 'celtic', 19 + 'chivalry', 20 + 'circling', 21 + 'civic', 22 + 'clobber', 23 + 'conform', 24 + 'cosmic', 25 + 'crier', 26 + 'curtly', 27 + 'depose', 28 + 'diagnosis', 29 + 'disfigure', 30 + 'drank', 31 + 'ducktail', 32 + 'eel', 33 + 'effort', 34 + 'equipment', 35 + 'eternal', 36 + 'exemplify', 37 + 'filtrate', 38 + 'fit', 39 + 'flaccid', 40 + 'fool', 41 + 'germinate', 42 + 'glade', 43 + 'graveness', 44 + 'gray', 45 + 'hydrant', 46 + 'italicize', 47 + 'landowner', 48 + 'lavender', 49 + 'mandatory', 50 + 'molecule', 51 + 'multitude', 52 + 'music', 53 + 'national', 54 + 'neatly', 55 + 'omnivore', 56 + 'other', 57 + 'overdrive', 58 + 'overhang', 59 + 'overlying', 60 + 'padded', 61 + 'pang', 62 + 'paralyses', 63 + 'partner', 64 + 'pedometer', 65 + 'plaything', 66 + 'pointy', 67 + 'prescribe', 68 + 'pueblo', 69 + 'pursuant', 70 + 'reprise', 71 + 'resilient', 72 + 'reusable', 73 + 'roster', 74 + 'scenic', 75 + 'selected', 76 + 'singer', 77 + 'slacker', 78 + 'smirk', 79 + 'smoked', 80 + 'smugly', 81 + 'startle', 82 + 'sternum', 83 + 'strut', 84 + 'subsystem', 85 + 'supper', 86 + 'swifter', 87 + 'tacking', 88 + 'traffic', 89 + 'tragedy', 90 + 'trapper', 91 + 'tummy', 92 + 'twiddle', 93 + 'unglazed', 94 + 'ungloved', 95 + 'unicorn', 96 + 'unissued', 97 + 'unmovable', 98 + 'unwary', 99 + 'uselessly', 100 + 'venus', 101 + 'vertebrae', 102 + 'wildly', 103 + 'wrecker', 104 + ]; 4 105 5 106 export const generateConfirmationCode = () => { 6 - const code = generateCode(); 7 - return `${code.slice(0, 5)}-${code.slice(5, 10)}`; 107 + return sample(words, 3).join(' '); 8 108 };
+1 -1
src/lib/utils/search-params.ts
··· 2 2 3 3 import { isDid, isHandle } from '@atcute/lexicons/syntax'; 4 4 5 - import { UnwrapArray } from '~/api/utils/types'; 5 + import type { UnwrapArray } from '~/api/utils/types'; 6 6 7 7 export interface ParamParser<T> { 8 8 parse: (value: string | string[] | null) => T | null;
+17
src/lib/utils/stream.ts
··· 1 + export async function* iterateStream<T>(stream: ReadableStream<T>) { 2 + const reader = stream.getReader(); 3 + 4 + try { 5 + while (true) { 6 + const { done, value } = await reader.read(); 7 + 8 + if (done) { 9 + return; 10 + } 11 + 12 + yield value; 13 + } 14 + } finally { 15 + reader.releaseLock(); 16 + } 17 + }
+9
src/routes.ts
··· 22 22 path: '/crypto-generate', 23 23 component: lazy(() => import('./views/crypto/crypto-generate')), 24 24 }, 25 + { 26 + path: '/crypto-info', 27 + component: lazy(() => import('./views/crypto/crypto-info')), 28 + }, 25 29 26 30 { 27 31 path: '/did-lookup', ··· 47 51 { 48 52 path: '/repo-archive-explore', 49 53 component: lazy(() => import('./views/repository/repo-archive-explore/page')), 54 + }, 55 + 56 + { 57 + path: '/account-migrate', 58 + component: lazy(() => import('./views/account/account-migrate/page')), 50 59 }, 51 60 52 61 {
+49
src/views/account/account-migrate/context.tsx
··· 1 + import { createContext, createSignal, useContext, type JSX } from 'solid-js'; 2 + 3 + import type { CredentialManager } from '@atcute/client'; 4 + import type { DidDocument } from '@atcute/identity'; 5 + import type { AtprotoDid, Did } from '@atcute/lexicons/syntax'; 6 + 7 + export interface SourceAccount { 8 + did: AtprotoDid; 9 + didDoc: DidDocument; 10 + pdsUrl: string; 11 + manager: CredentialManager | null; 12 + } 13 + 14 + export interface DestinationAccount { 15 + pdsUrl: string; 16 + serviceDid: Did; 17 + manager: CredentialManager | null; 18 + } 19 + 20 + export interface MigrationContextValue { 21 + source: () => SourceAccount | null; 22 + setSource: (account: SourceAccount | null) => void; 23 + destination: () => DestinationAccount | null; 24 + setDestination: (account: DestinationAccount | null) => void; 25 + } 26 + 27 + const MigrationContext = createContext<MigrationContextValue>(); 28 + 29 + export const MigrationProvider = (props: { children: JSX.Element }) => { 30 + const [source, setSource] = createSignal<SourceAccount | null>(null); 31 + const [destination, setDestination] = createSignal<DestinationAccount | null>(null); 32 + 33 + const value: MigrationContextValue = { 34 + source, 35 + setSource, 36 + destination, 37 + setDestination, 38 + }; 39 + 40 + return <MigrationContext.Provider value={value}>{props.children}</MigrationContext.Provider>; 41 + }; 42 + 43 + export const useMigration = (): MigrationContextValue => { 44 + const context = useContext(MigrationContext); 45 + if (!context) { 46 + throw new Error('useMigration must be used within a MigrationProvider'); 47 + } 48 + return context; 49 + };
+54
src/views/account/account-migrate/page.tsx
··· 1 + import { createEffect, createSignal, onCleanup } from 'solid-js'; 2 + 3 + import { history } from '~/globals/navigation'; 4 + 5 + import { useTitle } from '~/lib/navigation/router'; 6 + 7 + import PageHeader from '~/components/page-header'; 8 + 9 + import { MigrationProvider } from './context'; 10 + 11 + import SourceAccountSection from './sections/source-account'; 12 + import DestinationAccountSection from './sections/destination-account'; 13 + import RepositorySection from './sections/repository'; 14 + import BlobsSection from './sections/blobs'; 15 + import PreferencesSection from './sections/preferences'; 16 + import IdentitySection from './sections/identity'; 17 + import AccountStatusSection from './sections/account-status'; 18 + 19 + const AccountMigratePage = () => { 20 + const [hasStarted, setHasStarted] = createSignal(false); 21 + 22 + createEffect(() => { 23 + if (hasStarted()) { 24 + const cleanup = history.block((tx) => { 25 + if (window.confirm(`You have a migration in progress. Leave this page?`)) { 26 + cleanup(); 27 + tx.retry(); 28 + } 29 + }); 30 + 31 + onCleanup(cleanup); 32 + } 33 + }); 34 + 35 + useTitle(() => `Migrate account โ€” boat`); 36 + 37 + return ( 38 + <MigrationProvider> 39 + <PageHeader title="Migrate account" subtitle="Move your account data to another server" /> 40 + 41 + <div class="flex flex-col"> 42 + <SourceAccountSection onStarted={() => setHasStarted(true)} /> 43 + <DestinationAccountSection /> 44 + <RepositorySection /> 45 + <BlobsSection /> 46 + <PreferencesSection /> 47 + <IdentitySection /> 48 + <AccountStatusSection /> 49 + </div> 50 + </MigrationProvider> 51 + ); 52 + }; 53 + 54 + export default AccountMigratePage;
+207
src/views/account/account-migrate/sections/account-status.tsx
··· 1 + import { Show } from 'solid-js'; 2 + 3 + import { Client, type CredentialManager, ok } from '@atcute/client'; 4 + 5 + import { createMutation } from '~/lib/utils/mutation'; 6 + 7 + import { Accordion, StatusBadge, Subsection } from '~/components/accordion'; 8 + import Button from '~/components/inputs/button'; 9 + 10 + import { useMigration } from '../context'; 11 + 12 + interface AccountStatus { 13 + activated: boolean; 14 + validDid: boolean; 15 + repoCommit: string; 16 + repoRev: string; 17 + repoBlocks: number; 18 + indexedRecords: number; 19 + privateStateValues: number; 20 + expectedBlobs: number; 21 + importedBlobs: number; 22 + } 23 + 24 + const AccountStatusSection = () => { 25 + const { source, destination } = useMigration(); 26 + 27 + const checkSourceMutation = createMutation({ 28 + async mutationFn({ manager }: { manager: CredentialManager }) { 29 + const sourceClient = new Client({ handler: manager }); 30 + return await ok(sourceClient.get('com.atproto.server.checkAccountStatus')) as AccountStatus; 31 + }, 32 + onError(err) { 33 + console.error(err); 34 + }, 35 + }); 36 + 37 + const checkDestMutation = createMutation({ 38 + async mutationFn({ manager }: { manager: CredentialManager }) { 39 + const destClient = new Client({ handler: manager }); 40 + return await ok(destClient.get('com.atproto.server.checkAccountStatus')) as AccountStatus; 41 + }, 42 + onError(err) { 43 + console.error(err); 44 + }, 45 + }); 46 + 47 + const activateMutation = createMutation({ 48 + async mutationFn({ manager }: { manager: CredentialManager }) { 49 + const destClient = new Client({ handler: manager }); 50 + await ok(destClient.post('com.atproto.server.activateAccount', { as: null })); 51 + }, 52 + onSuccess() { 53 + const dest = destination(); 54 + if (dest?.manager) { 55 + checkDestMutation.mutate({ manager: dest.manager }); 56 + } 57 + }, 58 + onError(err) { 59 + console.error(err); 60 + }, 61 + }); 62 + 63 + const deactivateMutation = createMutation({ 64 + async mutationFn({ manager }: { manager: CredentialManager }) { 65 + if (!confirm('Are you sure you want to deactivate your source account? This will prevent the old PDS from serving your data.')) { 66 + throw new Error('Cancelled'); 67 + } 68 + const sourceClient = new Client({ handler: manager }); 69 + await ok(sourceClient.post('com.atproto.server.deactivateAccount', { as: null, input: {} })); 70 + }, 71 + onSuccess() { 72 + const src = source(); 73 + if (src?.manager) { 74 + checkSourceMutation.mutate({ manager: src.manager }); 75 + } 76 + }, 77 + onError(err) { 78 + if (err instanceof Error && err.message === 'Cancelled') return; 79 + console.error(err); 80 + }, 81 + }); 82 + 83 + const renderStatus = (status: AccountStatus) => ( 84 + <div class="space-y-1 text-sm"> 85 + <p> 86 + <span class="text-gray-500">Status:</span>{' '} 87 + <StatusBadge variant={status.activated ? 'success' : 'idle'}> 88 + {status.activated ? 'Active' : 'Deactivated'} 89 + </StatusBadge> 90 + </p> 91 + <p> 92 + <span class="text-gray-500">Records:</span>{' '} 93 + <span class="font-mono">{status.indexedRecords}</span> 94 + </p> 95 + <p> 96 + <span class="text-gray-500">Blobs:</span>{' '} 97 + <span class="font-mono">{status.importedBlobs}/{status.expectedBlobs}</span> 98 + </p> 99 + <p> 100 + <span class="text-gray-500">Repo blocks:</span>{' '} 101 + <span class="font-mono">{status.repoBlocks}</span> 102 + </p> 103 + </div> 104 + ); 105 + 106 + return ( 107 + <Accordion title="Account Status"> 108 + <Subsection title="Source account"> 109 + <Show 110 + when={source()?.manager} 111 + fallback={<p class="text-sm text-gray-500">Sign in to source account first.</p>} 112 + > 113 + {(manager) => ( 114 + <> 115 + <div class="flex items-center gap-3"> 116 + <Button 117 + variant="outline" 118 + onClick={() => checkSourceMutation.mutate({ manager: manager() })} 119 + disabled={checkSourceMutation.isPending} 120 + > 121 + {checkSourceMutation.isPending ? 'Checking...' : 'Check status'} 122 + </Button> 123 + </div> 124 + 125 + <Show when={checkSourceMutation.isError}> 126 + <p class="text-sm text-red-600">{`${checkSourceMutation.error}`}</p> 127 + </Show> 128 + 129 + <Show when={checkSourceMutation.data}> 130 + {(status) => ( 131 + <> 132 + {renderStatus(status())} 133 + 134 + <Show when={status().activated}> 135 + <div class="mt-3"> 136 + <Button 137 + variant="secondary" 138 + onClick={() => deactivateMutation.mutate({ manager: manager() })} 139 + disabled={deactivateMutation.isPending} 140 + > 141 + {deactivateMutation.isPending ? 'Deactivating...' : 'Deactivate source account'} 142 + </Button> 143 + </div> 144 + </Show> 145 + </> 146 + )} 147 + </Show> 148 + </> 149 + )} 150 + </Show> 151 + </Subsection> 152 + 153 + <Subsection title="Destination account"> 154 + <Show 155 + when={destination()?.manager} 156 + fallback={<p class="text-sm text-gray-500">Sign in to destination account first.</p>} 157 + > 158 + {(manager) => ( 159 + <> 160 + <div class="flex items-center gap-3"> 161 + <Button 162 + variant="outline" 163 + onClick={() => checkDestMutation.mutate({ manager: manager() })} 164 + disabled={checkDestMutation.isPending} 165 + > 166 + {checkDestMutation.isPending ? 'Checking...' : 'Check status'} 167 + </Button> 168 + </div> 169 + 170 + <Show when={checkDestMutation.isError}> 171 + <p class="text-sm text-red-600">{`${checkDestMutation.error}`}</p> 172 + </Show> 173 + 174 + <Show when={checkDestMutation.data}> 175 + {(status) => ( 176 + <> 177 + {renderStatus(status())} 178 + 179 + <Show when={!status().activated}> 180 + <div class="mt-3"> 181 + <Button 182 + onClick={() => activateMutation.mutate({ manager: manager() })} 183 + disabled={activateMutation.isPending} 184 + > 185 + {activateMutation.isPending ? 'Activating...' : 'Activate destination account'} 186 + </Button> 187 + </div> 188 + </Show> 189 + </> 190 + )} 191 + </Show> 192 + </> 193 + )} 194 + </Show> 195 + </Subsection> 196 + 197 + <Show when={activateMutation.isError || deactivateMutation.isError}> 198 + <p class="text-sm text-red-600"> 199 + {activateMutation.isError ? `Failed to activate: ${activateMutation.error}` : ''} 200 + {deactivateMutation.isError ? `Failed to deactivate: ${deactivateMutation.error}` : ''} 201 + </p> 202 + </Show> 203 + </Accordion> 204 + ); 205 + }; 206 + 207 + export default AccountStatusSection;
+455
src/views/account/account-migrate/sections/blobs.tsx
··· 1 + import { showOpenFilePicker, showSaveFilePicker } from 'native-file-system-adapter'; 2 + import { createSignal, For, Show } from 'solid-js'; 3 + 4 + import { Client, ClientResponseError, type CredentialManager, ok, simpleFetchHandler } from '@atcute/client'; 5 + import { untar, writeTarEntry } from '@mary/tar'; 6 + 7 + import { createMutation } from '~/lib/utils/mutation'; 8 + 9 + import { Accordion, StatusBadge, Subsection } from '~/components/accordion'; 10 + import Button from '~/components/inputs/button'; 11 + 12 + import { useMigration, type SourceAccount } from '../context'; 13 + 14 + const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); 15 + 16 + const BlobsSection = () => { 17 + const { source, destination } = useMigration(); 18 + 19 + // Progress state (kept separate since mutations don't handle incremental updates) 20 + const [exportProgress, setExportProgress] = createSignal<string>(); 21 + const [importProgress, setImportProgress] = createSignal<string>(); 22 + 23 + const exportMutation = createMutation({ 24 + async mutationFn({ source }: { source: SourceAccount }) { 25 + const sourceClient = new Client({ handler: simpleFetchHandler({ service: source.pdsUrl }) }); 26 + 27 + setExportProgress('Retrieving list of blobs...'); 28 + 29 + // Get list of all blobs 30 + let blobs: string[] = []; 31 + let cursor: string | undefined; 32 + do { 33 + const data = await ok( 34 + sourceClient.get('com.atproto.sync.listBlobs', { 35 + params: { did: source.did, cursor, limit: 1_000 }, 36 + }), 37 + ); 38 + cursor = data.cursor; 39 + blobs = blobs.concat(data.cids); 40 + setExportProgress(`Retrieving list of blobs (found ${blobs.length})`); 41 + } while (cursor !== undefined); 42 + 43 + if (blobs.length === 0) { 44 + return { count: 0, cancelled: false }; 45 + } 46 + 47 + setExportProgress('Waiting for file picker...'); 48 + 49 + const fd = await showSaveFilePicker({ 50 + suggestedName: `blobs-${source.did}-${new Date().toISOString()}.tar`, 51 + // @ts-expect-error: ponyfill doesn't have the full typings 52 + id: 'blob-export', 53 + startIn: 'downloads', 54 + types: [ 55 + { 56 + description: 'Tarball archive', 57 + accept: { 'application/tar': ['.tar'] }, 58 + }, 59 + ], 60 + }).catch((err) => { 61 + if (err instanceof DOMException && err.name === 'AbortError') { 62 + return undefined; 63 + } 64 + throw err; 65 + }); 66 + 67 + if (!fd) { 68 + return { count: 0, cancelled: true }; 69 + } 70 + 71 + const writable = await fd.createWritable(); 72 + 73 + let downloaded = 0; 74 + for (const cid of blobs) { 75 + setExportProgress(`Downloading blobs (${downloaded}/${blobs.length})`); 76 + 77 + const downloadBlob = async (): Promise<Uint8Array | undefined> => { 78 + let attempts = 0; 79 + while (true) { 80 + if (attempts > 0) await sleep(2_000); 81 + attempts++; 82 + 83 + try { 84 + const response = await sourceClient.get('com.atproto.sync.getBlob', { 85 + as: 'bytes', 86 + params: { did: source.did, cid }, 87 + }); 88 + 89 + if (response.ok) { 90 + return response.data; 91 + } 92 + 93 + if (response.status === 400 && response.data.message === 'Blob not found') { 94 + return undefined; 95 + } 96 + 97 + if (response.status === 429) { 98 + await sleep(10_000); 99 + } 100 + 101 + if (attempts < 3) continue; 102 + throw new ClientResponseError(response); 103 + } catch (err) { 104 + if (attempts < 3) continue; 105 + throw err; 106 + } 107 + } 108 + }; 109 + 110 + const data = await downloadBlob(); 111 + if (data !== undefined) { 112 + const entry = writeTarEntry({ filename: `blobs/${cid}`, data }); 113 + await writable.write(entry); 114 + } 115 + 116 + downloaded++; 117 + } 118 + 119 + await writable.close(); 120 + return { count: blobs.length, cancelled: false }; 121 + }, 122 + onError(err) { 123 + console.error(err); 124 + }, 125 + onSettled() { 126 + setExportProgress(); 127 + }, 128 + }); 129 + 130 + const importFromFileMutation = createMutation({ 131 + async mutationFn({ destManager }: { destManager: CredentialManager }) { 132 + setImportProgress('Waiting for file picker...'); 133 + 134 + const [fd] = await showOpenFilePicker({ 135 + // @ts-expect-error: ponyfill doesn't have the full typings 136 + id: 'blob-import', 137 + types: [ 138 + { 139 + description: 'Tarball archive', 140 + accept: { 'application/tar': ['.tar'] }, 141 + }, 142 + ], 143 + }).catch((err) => { 144 + if (err instanceof DOMException && err.name === 'AbortError') { 145 + return [undefined]; 146 + } 147 + throw err; 148 + }); 149 + 150 + if (!fd) { 151 + return { uploaded: 0, failed: 0, cancelled: true }; 152 + } 153 + 154 + setImportProgress('Reading archive...'); 155 + const file = await fd.getFile(); 156 + 157 + const destClient = new Client({ handler: destManager }); 158 + 159 + let uploaded = 0; 160 + let failed = 0; 161 + 162 + for await (const entry of untar(file.stream())) { 163 + if (entry.type !== 'file') continue; 164 + 165 + const filename = entry.name; 166 + // Extract CID from path like "blobs/bafk..." 167 + const cid = filename.split('/').pop(); 168 + if (!cid) continue; 169 + 170 + setImportProgress(`Uploading blobs (${uploaded} uploaded, ${failed} failed)`); 171 + 172 + try { 173 + const data = await entry.bytes(); 174 + await destClient.post('com.atproto.repo.uploadBlob', { 175 + input: data, 176 + headers: { 177 + 'content-type': 'application/octet-stream', 178 + }, 179 + }); 180 + uploaded++; 181 + } catch (err) { 182 + console.error(`Failed to upload blob ${cid}:`, err); 183 + failed++; 184 + } 185 + } 186 + 187 + return { uploaded, failed, cancelled: false }; 188 + }, 189 + onError(err) { 190 + console.error(err); 191 + }, 192 + onSettled() { 193 + setImportProgress(); 194 + }, 195 + }); 196 + 197 + const importFromSourceMutation = createMutation({ 198 + async mutationFn({ source, destManager }: { source: SourceAccount; destManager: CredentialManager }) { 199 + setImportProgress('Checking for missing blobs...'); 200 + 201 + const sourceClient = new Client({ handler: simpleFetchHandler({ service: source.pdsUrl }) }); 202 + const destClient = new Client({ handler: destManager }); 203 + 204 + let uploaded = 0; 205 + let failed = 0; 206 + let cursor: string | undefined; 207 + 208 + do { 209 + const data = await ok( 210 + destClient.get('com.atproto.repo.listMissingBlobs', { 211 + params: { cursor, limit: 100 }, 212 + }), 213 + ); 214 + cursor = data.cursor; 215 + 216 + for (const blob of data.blobs) { 217 + setImportProgress(`Uploading missing blobs (${uploaded} uploaded, ${failed} failed)`); 218 + 219 + try { 220 + const response = await sourceClient.get('com.atproto.sync.getBlob', { 221 + as: 'stream', 222 + params: { did: source.did, cid: blob.cid }, 223 + }); 224 + 225 + if (!response.ok) { 226 + failed++; 227 + continue; 228 + } 229 + 230 + const contentType = response.headers.get('content-type') || 'application/octet-stream'; 231 + 232 + await destClient.post('com.atproto.repo.uploadBlob', { 233 + input: response.data, 234 + headers: { 235 + 'content-type': contentType, 236 + }, 237 + }); 238 + 239 + uploaded++; 240 + } catch (err) { 241 + console.error(`Failed to transfer blob ${blob.cid}:`, err); 242 + failed++; 243 + } 244 + } 245 + } while (cursor !== undefined); 246 + 247 + return { uploaded, failed }; 248 + }, 249 + onError(err) { 250 + console.error(err); 251 + }, 252 + onSettled() { 253 + setImportProgress(); 254 + }, 255 + }); 256 + 257 + const checkStatusMutation = createMutation({ 258 + async mutationFn({ destManager }: { destManager: CredentialManager }) { 259 + const destClient = new Client({ handler: destManager }); 260 + const status = await ok(destClient.get('com.atproto.server.checkAccountStatus')); 261 + 262 + let missingBlobs: string[] = []; 263 + 264 + // Get list of missing blobs if any 265 + if (status.expectedBlobs > status.importedBlobs) { 266 + let cursor: string | undefined; 267 + do { 268 + const data = await ok( 269 + destClient.get('com.atproto.repo.listMissingBlobs', { 270 + params: { cursor, limit: 100 }, 271 + }), 272 + ); 273 + cursor = data.cursor; 274 + missingBlobs.push(...data.blobs.map((b) => b.cid)); 275 + } while (cursor !== undefined); 276 + } 277 + 278 + return { 279 + expected: status.expectedBlobs, 280 + imported: status.importedBlobs, 281 + missingBlobs, 282 + }; 283 + }, 284 + onError(err) { 285 + console.error(err); 286 + }, 287 + }); 288 + 289 + const isImporting = () => importFromFileMutation.isPending || importFromSourceMutation.isPending; 290 + 291 + const getExportStatusText = () => { 292 + const data = exportMutation.data; 293 + if (data?.cancelled) return undefined; 294 + if (data?.count === 0) return 'No blobs to export'; 295 + if (data) return `Exported ${data.count} blobs`; 296 + return exportProgress(); 297 + }; 298 + 299 + const getImportStatusText = () => { 300 + const fileData = importFromFileMutation.data; 301 + const sourceData = importFromSourceMutation.data; 302 + 303 + if (fileData && !fileData.cancelled) { 304 + return ( 305 + `Uploaded ${fileData.uploaded} blobs` + (fileData.failed > 0 ? ` (${fileData.failed} failed)` : '') 306 + ); 307 + } 308 + if (sourceData) { 309 + if (sourceData.uploaded === 0 && sourceData.failed === 0) return 'No missing blobs'; 310 + return ( 311 + `Uploaded ${sourceData.uploaded} blobs` + 312 + (sourceData.failed > 0 ? ` (${sourceData.failed} failed)` : '') 313 + ); 314 + } 315 + return importProgress(); 316 + }; 317 + 318 + const getImportError = () => importFromFileMutation.error || importFromSourceMutation.error; 319 + 320 + return ( 321 + <Accordion title="Blobs"> 322 + <Subsection title="Export from source"> 323 + <p class="text-sm text-gray-600">Download all blobs as a tarball for backup or manual import.</p> 324 + 325 + <Show when={source()} fallback={<p class="text-sm text-gray-500">Resolve source account first.</p>}> 326 + {(src) => ( 327 + <> 328 + <div class="flex items-center gap-3"> 329 + <Button 330 + onClick={() => exportMutation.mutate({ source: src() })} 331 + disabled={exportMutation.isPending} 332 + > 333 + {exportMutation.isPending ? 'Exporting...' : 'Export to file'} 334 + </Button> 335 + <Show when={getExportStatusText()}> 336 + {(text) => <span class="text-sm text-gray-600">{text()}</span>} 337 + </Show> 338 + </div> 339 + 340 + <Show when={exportMutation.error}> 341 + {(err) => <p class="text-sm text-red-600">{`${err()}`}</p>} 342 + </Show> 343 + </> 344 + )} 345 + </Show> 346 + </Subsection> 347 + 348 + <Subsection title="Import to destination"> 349 + <p class="text-sm text-gray-600">Upload blobs from a tarball or transfer directly from source.</p> 350 + 351 + <Show 352 + when={destination()?.manager} 353 + fallback={<p class="text-sm text-gray-500">Sign in to destination account first.</p>} 354 + > 355 + {(destManager) => ( 356 + <> 357 + <div class="flex flex-wrap items-center gap-3"> 358 + <Button 359 + onClick={() => importFromFileMutation.mutate({ destManager: destManager() })} 360 + disabled={isImporting()} 361 + > 362 + {isImporting() ? 'Importing...' : 'Import from file'} 363 + </Button> 364 + 365 + <Show when={source()}> 366 + {(src) => ( 367 + <Button 368 + variant="secondary" 369 + onClick={() => 370 + importFromSourceMutation.mutate({ source: src(), destManager: destManager() }) 371 + } 372 + disabled={isImporting()} 373 + > 374 + Transfer from source 375 + </Button> 376 + )} 377 + </Show> 378 + </div> 379 + 380 + <Show when={getImportStatusText()}> 381 + {(text) => <span class="text-sm text-gray-600">{text()}</span>} 382 + </Show> 383 + 384 + <Show when={getImportError()}>{(err) => <p class="text-sm text-red-600">{`${err()}`}</p>}</Show> 385 + </> 386 + )} 387 + </Show> 388 + </Subsection> 389 + 390 + <Subsection title="Status"> 391 + <Show 392 + when={destination()?.manager} 393 + fallback={<p class="text-sm text-gray-500">Sign in to destination account first.</p>} 394 + > 395 + {(destManager) => ( 396 + <> 397 + <div class="flex items-center gap-3"> 398 + <Button 399 + variant="outline" 400 + onClick={() => checkStatusMutation.mutate({ destManager: destManager() })} 401 + disabled={checkStatusMutation.isPending} 402 + > 403 + {checkStatusMutation.isPending ? 'Checking...' : 'Check status'} 404 + </Button> 405 + 406 + <Show when={checkStatusMutation.data}> 407 + {(status) => ( 408 + <span class="text-sm"> 409 + <StatusBadge variant={status().imported === status().expected ? 'success' : 'pending'}> 410 + {status().imported}/{status().expected} blobs 411 + </StatusBadge> 412 + </span> 413 + )} 414 + </Show> 415 + </div> 416 + 417 + <Show when={checkStatusMutation.data?.missingBlobs.length}> 418 + {(count) => ( 419 + <div class="mt-2 rounded border border-yellow-300 bg-yellow-50 p-3"> 420 + <p class="mb-2 text-sm font-medium text-yellow-800">{count()} missing blobs</p> 421 + 422 + <Show when={source()}> 423 + {(src) => ( 424 + <Button 425 + variant="secondary" 426 + onClick={() => 427 + importFromSourceMutation.mutate({ source: src(), destManager: destManager() }) 428 + } 429 + disabled={isImporting()} 430 + > 431 + Transfer missing from source 432 + </Button> 433 + )} 434 + </Show> 435 + 436 + <details class="mt-2"> 437 + <summary class="cursor-pointer text-sm text-yellow-700">Show CIDs</summary> 438 + <div class="mt-1 max-h-32 overflow-auto font-mono text-xs"> 439 + <For each={checkStatusMutation.data?.missingBlobs}> 440 + {(cid) => <div class="truncate">{cid}</div>} 441 + </For> 442 + </div> 443 + </details> 444 + </div> 445 + )} 446 + </Show> 447 + </> 448 + )} 449 + </Show> 450 + </Subsection> 451 + </Accordion> 452 + ); 453 + }; 454 + 455 + export default BlobsSection;
+437
src/views/account/account-migrate/sections/destination-account.tsx
··· 1 + import { createSignal, Show } from 'solid-js'; 2 + 3 + import { 4 + type AtpAccessJwt, 5 + Client, 6 + ClientResponseError, 7 + CredentialManager, 8 + ok, 9 + simpleFetchHandler, 10 + } from '@atcute/client'; 11 + import type { Did, Handle } from '@atcute/lexicons/syntax'; 12 + 13 + import { formatTotpCode, TOTP_RE } from '~/api/utils/auth'; 14 + import { decodeJwt } from '~/api/utils/jwt'; 15 + import { isServiceUrlString } from '~/api/types/strings'; 16 + 17 + import { createMutation } from '~/lib/utils/mutation'; 18 + 19 + import { Accordion, StatusBadge, Subsection } from '~/components/accordion'; 20 + import Button from '~/components/inputs/button'; 21 + import TextInput from '~/components/inputs/text-input'; 22 + 23 + import { useMigration } from '../context'; 24 + 25 + class InsufficientLoginError extends Error {} 26 + 27 + const DestinationAccountSection = () => { 28 + const { source, destination, setDestination } = useMigration(); 29 + 30 + // Connect state 31 + const [pdsUrl, setPdsUrl] = createSignal(''); 32 + const [connectError, setConnectError] = createSignal<string>(); 33 + 34 + // Create account state 35 + const [newHandle, setNewHandle] = createSignal(''); 36 + const [newEmail, setNewEmail] = createSignal(''); 37 + const [newPassword, setNewPassword] = createSignal(''); 38 + const [inviteCode, setInviteCode] = createSignal(''); 39 + const [createError, setCreateError] = createSignal<string>(); 40 + 41 + // Login state 42 + const [loginPassword, setLoginPassword] = createSignal(''); 43 + const [loginOtp, setLoginOtp] = createSignal(''); 44 + const [isLoginTotpRequired, setIsLoginTotpRequired] = createSignal(false); 45 + const [loginError, setLoginError] = createSignal<string>(); 46 + 47 + const connectMutation = createMutation({ 48 + async mutationFn({ pdsUrl }: { pdsUrl: string }) { 49 + const destClient = new Client({ handler: simpleFetchHandler({ service: pdsUrl }) }); 50 + const desc = await ok(destClient.get('com.atproto.server.describeServer')); 51 + 52 + return { serviceDid: desc.did }; 53 + }, 54 + onMutate() { 55 + setConnectError(); 56 + }, 57 + onSuccess({ serviceDid }) { 58 + setDestination({ pdsUrl: pdsUrl(), serviceDid, manager: null }); 59 + }, 60 + onError(err) { 61 + console.error(err); 62 + setConnectError(`Failed to connect: ${err}`); 63 + }, 64 + }); 65 + 66 + const createAccountMutation = createMutation({ 67 + async mutationFn({ 68 + sourceDid, 69 + sourceManager, 70 + destPdsUrl, 71 + destServiceDid, 72 + handle, 73 + email, 74 + password, 75 + inviteCode, 76 + }: { 77 + sourceDid: Did; 78 + sourceManager: CredentialManager; 79 + destPdsUrl: string; 80 + destServiceDid: string; 81 + handle: Handle; 82 + email: string; 83 + password: string; 84 + inviteCode: string; 85 + }) { 86 + // Get service auth token from old PDS 87 + const sourceClient = new Client({ handler: sourceManager }); 88 + const authResp = await ok( 89 + sourceClient.get('com.atproto.server.getServiceAuth', { 90 + params: { 91 + aud: destServiceDid as Did, 92 + lxm: 'com.atproto.server.createAccount', 93 + }, 94 + }), 95 + ); 96 + const serviceJwt = authResp.token; 97 + 98 + // Create account on new PDS with service auth 99 + const destClient = new Client({ handler: simpleFetchHandler({ service: destPdsUrl }) }); 100 + const createResp = await destClient.post('com.atproto.server.createAccount', { 101 + headers: { Authorization: `Bearer ${serviceJwt}` }, 102 + input: { 103 + did: sourceDid, 104 + handle: handle, 105 + email: email, 106 + password: password, 107 + inviteCode: inviteCode || undefined, 108 + }, 109 + }); 110 + 111 + if (!createResp.ok) { 112 + throw new ClientResponseError(createResp); 113 + } 114 + 115 + if (createResp.data.did !== sourceDid) { 116 + throw new Error(`Created account has different DID: ${createResp.data.did}`); 117 + } 118 + 119 + // Login to the new account 120 + const manager = new CredentialManager({ service: destPdsUrl }); 121 + await manager.login({ 122 + identifier: sourceDid, 123 + password: password, 124 + }); 125 + 126 + return manager; 127 + }, 128 + onMutate() { 129 + setCreateError(); 130 + }, 131 + onSuccess(manager) { 132 + setDestination({ ...destination()!, manager }); 133 + setNewPassword(''); 134 + }, 135 + onError(err) { 136 + if (err instanceof ClientResponseError) { 137 + if (err.error === 'InvalidInviteCode') { 138 + setCreateError(`Invalid invite code`); 139 + return; 140 + } 141 + if (err.error === 'HandleNotAvailable') { 142 + setCreateError(`Handle is not available`); 143 + return; 144 + } 145 + if (err.description) { 146 + setCreateError(err.description); 147 + return; 148 + } 149 + } 150 + console.error(err); 151 + setCreateError(`${err}`); 152 + }, 153 + }); 154 + 155 + const loginMutation = createMutation({ 156 + async mutationFn({ 157 + pdsUrl, 158 + did, 159 + password, 160 + otp, 161 + }: { 162 + pdsUrl: string; 163 + did: string; 164 + password: string; 165 + otp: string; 166 + }) { 167 + const manager = new CredentialManager({ service: pdsUrl }); 168 + const session = await manager.login({ 169 + identifier: did, 170 + password: password, 171 + code: formatTotpCode(otp), 172 + }); 173 + 174 + const decoded = decodeJwt(session.accessJwt) as AtpAccessJwt; 175 + if (decoded.scope !== 'com.atproto.access') { 176 + throw new InsufficientLoginError(`You need to sign in with a main password, not an app password`); 177 + } 178 + 179 + return manager; 180 + }, 181 + onMutate() { 182 + setLoginError(); 183 + }, 184 + onSuccess(manager) { 185 + setDestination({ ...destination()!, manager }); 186 + setLoginPassword(''); 187 + setLoginOtp(''); 188 + setIsLoginTotpRequired(false); 189 + }, 190 + onError(err) { 191 + if (err instanceof ClientResponseError) { 192 + if (err.error === 'AuthFactorTokenRequired') { 193 + setLoginOtp(''); 194 + setIsLoginTotpRequired(true); 195 + return; 196 + } 197 + if (err.error === 'AuthenticationRequired') { 198 + setLoginError(`Invalid identifier or password`); 199 + return; 200 + } 201 + if (err.description?.includes('Token is invalid')) { 202 + setLoginError(`Invalid one-time confirmation code`); 203 + setIsLoginTotpRequired(true); 204 + return; 205 + } 206 + } 207 + if (err instanceof InsufficientLoginError) { 208 + setLoginError(err.message); 209 + return; 210 + } 211 + console.error(err); 212 + setLoginError(`${err}`); 213 + }, 214 + }); 215 + 216 + const isConnected = () => destination() !== null; 217 + const isAuthenticated = () => destination()?.manager != null; 218 + const canCreateAccount = () => source()?.manager != null; 219 + 220 + return ( 221 + <Accordion title="Destination Account"> 222 + <Subsection title="Connect to PDS"> 223 + <Show when={!isConnected()}> 224 + <form 225 + onSubmit={(ev) => { 226 + ev.preventDefault(); 227 + connectMutation.mutate({ pdsUrl: pdsUrl() }); 228 + }} 229 + class="flex flex-col gap-3" 230 + > 231 + <TextInput 232 + label="PDS URL" 233 + type="url" 234 + placeholder="https://pds.example.com" 235 + value={pdsUrl()} 236 + required 237 + onChange={(text, event) => { 238 + setPdsUrl(text); 239 + const input = event.currentTarget; 240 + if (text !== '' && !isServiceUrlString(text)) { 241 + input.setCustomValidity('Must be a valid URL'); 242 + } else { 243 + input.setCustomValidity(''); 244 + } 245 + }} 246 + /> 247 + 248 + <Show when={connectError()}> 249 + <p class="text-sm text-red-600">{connectError()}</p> 250 + </Show> 251 + 252 + <div> 253 + <Button type="submit" disabled={connectMutation.isPending}> 254 + {connectMutation.isPending ? 'Connecting...' : 'Connect'} 255 + </Button> 256 + </div> 257 + </form> 258 + </Show> 259 + 260 + <Show when={isConnected()}> 261 + <div class="flex flex-col gap-2 text-sm"> 262 + <p> 263 + <span class="text-gray-500">URL:</span>{' '} 264 + <span class="font-mono">{destination()!.pdsUrl}</span> 265 + </p> 266 + <p> 267 + <span class="text-gray-500">Service DID:</span>{' '} 268 + <span class="font-mono">{destination()!.serviceDid}</span> 269 + </p> 270 + <div class="mt-1"> 271 + <button 272 + type="button" 273 + onClick={() => setDestination(null)} 274 + class="text-sm text-purple-800 hover:underline" 275 + > 276 + Change PDS 277 + </button> 278 + </div> 279 + </div> 280 + </Show> 281 + </Subsection> 282 + 283 + <Show when={isConnected() && !isAuthenticated()}> 284 + <Subsection title="Create new account"> 285 + <Show when={!canCreateAccount()}> 286 + <p class="text-sm text-gray-600"> 287 + You need to authenticate to your source account first to create an account on the 288 + destination PDS. 289 + </p> 290 + </Show> 291 + 292 + <Show when={canCreateAccount()}> 293 + <form 294 + onSubmit={(ev) => { 295 + ev.preventDefault(); 296 + const src = source()!; 297 + const dest = destination()!; 298 + createAccountMutation.mutate({ 299 + sourceDid: src.did, 300 + sourceManager: src.manager!, 301 + destPdsUrl: dest.pdsUrl, 302 + destServiceDid: dest.serviceDid, 303 + handle: newHandle() as Handle, 304 + email: newEmail(), 305 + password: newPassword(), 306 + inviteCode: inviteCode(), 307 + }); 308 + }} 309 + class="flex flex-col gap-3" 310 + > 311 + <TextInput 312 + label="Handle" 313 + placeholder="alice.pds.example.com" 314 + value={newHandle()} 315 + required 316 + onChange={setNewHandle} 317 + /> 318 + 319 + <TextInput 320 + label="Email" 321 + type="email" 322 + placeholder="alice@example.com" 323 + value={newEmail()} 324 + required 325 + onChange={setNewEmail} 326 + /> 327 + 328 + <TextInput 329 + label="Password" 330 + type="password" 331 + value={newPassword()} 332 + required 333 + onChange={setNewPassword} 334 + /> 335 + 336 + <TextInput 337 + label="Invite code (if required)" 338 + placeholder="pds-example-com-xxxxx" 339 + value={inviteCode()} 340 + onChange={setInviteCode} 341 + /> 342 + 343 + <Show when={createError()}> 344 + <p class="text-sm text-red-600">{createError()}</p> 345 + </Show> 346 + 347 + <div> 348 + <Button type="submit" disabled={createAccountMutation.isPending}> 349 + {createAccountMutation.isPending ? 'Creating...' : 'Create account'} 350 + </Button> 351 + </div> 352 + </form> 353 + </Show> 354 + </Subsection> 355 + 356 + <Subsection title="Or login to existing account"> 357 + <p class="mb-2 text-sm text-gray-600"> 358 + If you already have a deactivated account on the destination PDS. 359 + </p> 360 + 361 + <Show when={!source()}> 362 + <p class="text-sm text-gray-600"> 363 + Resolve your source account first so we know which DID to use. 364 + </p> 365 + </Show> 366 + 367 + <Show when={source()}> 368 + <form 369 + onSubmit={(ev) => { 370 + ev.preventDefault(); 371 + const src = source()!; 372 + const dest = destination()!; 373 + loginMutation.mutate({ 374 + pdsUrl: dest.pdsUrl, 375 + did: src.did, 376 + password: loginPassword(), 377 + otp: loginOtp(), 378 + }); 379 + }} 380 + class="flex flex-col gap-3" 381 + > 382 + <TextInput 383 + label="Password" 384 + type="password" 385 + value={loginPassword()} 386 + required 387 + onChange={setLoginPassword} 388 + /> 389 + 390 + <Show when={isLoginTotpRequired()}> 391 + <TextInput 392 + label="One-time confirmation code" 393 + blurb="A code has been sent to your email address." 394 + type="text" 395 + autocomplete="one-time-code" 396 + pattern={TOTP_RE.source} 397 + placeholder="AAAAA-BBBBB" 398 + value={loginOtp()} 399 + required 400 + onChange={setLoginOtp} 401 + monospace 402 + /> 403 + </Show> 404 + 405 + <Show when={loginError()}> 406 + <p class="text-sm text-red-600">{loginError()}</p> 407 + </Show> 408 + 409 + <div> 410 + <Button type="submit" disabled={loginMutation.isPending}> 411 + {loginMutation.isPending ? 'Signing in...' : 'Sign in'} 412 + </Button> 413 + </div> 414 + </form> 415 + </Show> 416 + </Subsection> 417 + </Show> 418 + 419 + <Show when={isAuthenticated()}> 420 + <Subsection title="Account status"> 421 + <div class="flex items-center gap-2"> 422 + <StatusBadge variant="success">Signed in</StatusBadge> 423 + <button 424 + type="button" 425 + onClick={() => setDestination({ ...destination()!, manager: null })} 426 + class="text-sm text-purple-800 hover:underline" 427 + > 428 + Sign out 429 + </button> 430 + </div> 431 + </Subsection> 432 + </Show> 433 + </Accordion> 434 + ); 435 + }; 436 + 437 + export default DestinationAccountSection;
+545
src/views/account/account-migrate/sections/identity.tsx
··· 1 + import { createSignal, For, Index, Show } from 'solid-js'; 2 + 3 + import { Client, ClientResponseError, type CredentialManager, ok } from '@atcute/client'; 4 + import { type DidKeyString, Secp256k1PrivateKeyExportable } from '@atcute/crypto'; 5 + import type { Did } from '@atcute/lexicons/syntax'; 6 + 7 + import { getPlcAuditLogs } from '~/api/queries/plc'; 8 + import { formatTotpCode, TOTP_RE } from '~/api/utils/auth'; 9 + 10 + import { createMutation } from '~/lib/utils/mutation'; 11 + 12 + import { Accordion, StatusBadge, Subsection } from '~/components/accordion'; 13 + import Button from '~/components/inputs/button'; 14 + import TextInput from '~/components/inputs/text-input'; 15 + import ToggleInput from '~/components/inputs/toggle-input'; 16 + 17 + import { getPlcPayload } from '~/views/identity/plc-applicator/plc-utils'; 18 + 19 + import { useMigration } from '../context'; 20 + 21 + interface RecommendedCredentials { 22 + alsoKnownAs?: string[]; 23 + rotationKeys?: string[]; 24 + verificationMethods?: Record<string, unknown>; 25 + services?: Record<string, unknown>; 26 + } 27 + 28 + interface GeneratedKeypair { 29 + publicDidKey: DidKeyString; 30 + privateHex: string; 31 + privateMultikey: string; 32 + } 33 + 34 + const IdentitySection = () => { 35 + const { source, destination } = useMigration(); 36 + 37 + // Rotation key state 38 + const [useGeneratedKey, setUseGeneratedKey] = createSignal(false); 39 + const [customKeys, setCustomKeys] = createSignal<string[]>([]); 40 + const [plcToken, setPlcToken] = createSignal(''); 41 + 42 + const requestTokenMutation = createMutation({ 43 + async mutationFn({ manager }: { manager: CredentialManager }) { 44 + const client = new Client({ handler: manager }); 45 + await ok(client.post('com.atproto.identity.requestPlcOperationSignature', { as: null })); 46 + }, 47 + onError(err) { 48 + console.error(err); 49 + }, 50 + }); 51 + 52 + const loadCredentialsMutation = createMutation({ 53 + async mutationFn({ manager }: { manager: CredentialManager }) { 54 + const client = new Client({ handler: manager }); 55 + return (await ok( 56 + client.get('com.atproto.identity.getRecommendedDidCredentials', {}), 57 + )) as RecommendedCredentials; 58 + }, 59 + onError(err) { 60 + console.error(err); 61 + }, 62 + }); 63 + 64 + // Analyze current rotation keys to find user-controlled keys that should be preserved 65 + const analyzeRotationKeysMutation = createMutation({ 66 + async mutationFn({ did, sourceManager }: { did: Did<'plc'>; sourceManager: CredentialManager }, signal) { 67 + // Get current rotation keys from PLC audit log 68 + const auditLogs = await getPlcAuditLogs({ did, signal }); 69 + const latestEntry = auditLogs[auditLogs.length - 1]; 70 + const currentPayload = getPlcPayload(latestEntry); 71 + const currentRotationKeys = currentPayload.rotationKeys ?? []; 72 + 73 + // Get source PDS's recommended credentials to identify PDS-controlled keys 74 + const sourceClient = new Client({ handler: sourceManager }); 75 + const sourcePdsCredentials = (await ok( 76 + sourceClient.get('com.atproto.identity.getRecommendedDidCredentials', {}), 77 + )) as RecommendedCredentials; 78 + const sourcePdsKeys = new Set(sourcePdsCredentials.rotationKeys ?? []); 79 + 80 + // Keys in current doc that aren't from source PDS are user-controlled 81 + const userControlledKeys = currentRotationKeys.filter((key) => !sourcePdsKeys.has(key)); 82 + 83 + return { 84 + currentRotationKeys, 85 + sourcePdsKeys: sourcePdsCredentials.rotationKeys ?? [], 86 + userControlledKeys, 87 + }; 88 + }, 89 + onSuccess(data) { 90 + // Pre-populate custom keys with user-controlled keys 91 + if (data.userControlledKeys.length > 0) { 92 + setCustomKeys(data.userControlledKeys); 93 + } 94 + }, 95 + onError(err) { 96 + console.error(err); 97 + }, 98 + }); 99 + 100 + const generateKeyMutation = createMutation({ 101 + async mutationFn() { 102 + const keypair = await Secp256k1PrivateKeyExportable.createKeypair(); 103 + const [publicDidKey, privateHex, privateMultikey] = await Promise.all([ 104 + keypair.exportPublicKey('did'), 105 + keypair.exportPrivateKey('rawHex'), 106 + keypair.exportPrivateKey('multikey'), 107 + ]); 108 + return { publicDidKey, privateHex, privateMultikey } as GeneratedKeypair; 109 + }, 110 + onError(err) { 111 + console.error(err); 112 + }, 113 + }); 114 + 115 + const signAndSubmitMutation = createMutation({ 116 + async mutationFn({ 117 + sourceManager, 118 + destManager, 119 + token, 120 + credentials, 121 + generatedKey, 122 + customKeys, 123 + }: { 124 + sourceManager: CredentialManager; 125 + destManager: CredentialManager; 126 + token: string; 127 + credentials: RecommendedCredentials; 128 + generatedKey?: GeneratedKeypair; 129 + customKeys: string[]; 130 + }) { 131 + const sourceClient = new Client({ handler: sourceManager }); 132 + const destClient = new Client({ handler: destManager }); 133 + 134 + // Prepend user keys to PDS-provided keys (so user keys appear first for recovery) 135 + const pdsRotationKeys = credentials.rotationKeys ?? []; 136 + const userKeys: string[] = []; 137 + if (generatedKey) { 138 + userKeys.push(generatedKey.publicDidKey); 139 + } 140 + userKeys.push(...customKeys.filter((k) => k.trim())); 141 + const rotationKeys = [...userKeys, ...pdsRotationKeys]; 142 + 143 + // Sign the PLC operation on the source PDS 144 + const signage = await ok( 145 + sourceClient.post('com.atproto.identity.signPlcOperation', { 146 + input: { 147 + token: formatTotpCode(token), 148 + alsoKnownAs: credentials.alsoKnownAs, 149 + rotationKeys: rotationKeys, 150 + services: credentials.services, 151 + verificationMethods: credentials.verificationMethods, 152 + }, 153 + }), 154 + ); 155 + 156 + // Submit via the destination PDS 157 + await ok( 158 + destClient.post('com.atproto.identity.submitPlcOperation', { 159 + as: null, 160 + input: { 161 + operation: signage.operation, 162 + }, 163 + }), 164 + ); 165 + }, 166 + onSuccess() { 167 + setPlcToken(''); 168 + }, 169 + onError(err) { 170 + console.error(err); 171 + }, 172 + }); 173 + 174 + // Calculate rotation key counts 175 + const pdsKeyCount = () => loadCredentialsMutation.data?.rotationKeys?.length ?? 0; 176 + const totalKeyCount = () => { 177 + const custom = customKeys().filter((k) => k.trim()).length; 178 + const generated = useGeneratedKey() && generateKeyMutation.data ? 1 : 0; 179 + return pdsKeyCount() + custom + generated; 180 + }; 181 + const canAddCustomKey = () => totalKeyCount() < 5; 182 + const isOverLimit = () => totalKeyCount() > 5; 183 + 184 + const addCustomKey = () => { 185 + if (canAddCustomKey()) { 186 + setCustomKeys([...customKeys(), '']); 187 + } 188 + }; 189 + 190 + const removeCustomKey = (index: number) => { 191 + setCustomKeys(customKeys().filter((_, i) => i !== index)); 192 + }; 193 + 194 + const updateCustomKey = (index: number, value: string) => { 195 + setCustomKeys(customKeys().map((k, i) => (i === index ? value : k))); 196 + }; 197 + 198 + const canSignAndSubmit = () => { 199 + const src = source(); 200 + const dest = destination(); 201 + const creds = loadCredentialsMutation.data; 202 + const token = plcToken().trim(); 203 + 204 + return !!(src?.manager && dest?.manager && creds && token && !isOverLimit()); 205 + }; 206 + 207 + const handleSignAndSubmit = () => { 208 + const src = source(); 209 + const dest = destination(); 210 + const creds = loadCredentialsMutation.data; 211 + const token = plcToken().trim(); 212 + 213 + if (!src?.manager || !dest?.manager || !creds || !token || isOverLimit()) return; 214 + 215 + signAndSubmitMutation.mutate({ 216 + sourceManager: src.manager, 217 + destManager: dest.manager, 218 + token, 219 + credentials: creds, 220 + generatedKey: useGeneratedKey() ? generateKeyMutation.data : undefined, 221 + customKeys: customKeys(), 222 + }); 223 + }; 224 + 225 + const getSubmitErrorMessage = () => { 226 + const err = signAndSubmitMutation.error; 227 + if (err instanceof ClientResponseError) { 228 + if (err.error === 'InvalidToken' || err.error === 'ExpiredToken') { 229 + return 'Confirmation code has expired or is invalid'; 230 + } 231 + } 232 + return `${err}`; 233 + }; 234 + 235 + return ( 236 + <Accordion title="Identity (PLC)"> 237 + <div class="mb-4 rounded border border-yellow-300 bg-yellow-50 p-3"> 238 + <p class="text-sm font-medium text-yellow-800"> 239 + This updates your DID document to point to the new PDS. This is the critical step that makes the 240 + migration official. 241 + </p> 242 + </div> 243 + 244 + <Subsection title="1. Preview new credentials"> 245 + <p class="text-sm text-gray-600">View what your DID document will look like after the migration.</p> 246 + 247 + <Show 248 + when={destination()?.manager} 249 + fallback={<p class="text-sm text-gray-500">Sign in to destination account first.</p>} 250 + > 251 + {(manager) => ( 252 + <> 253 + <div class="flex items-center gap-3"> 254 + <Button 255 + variant="outline" 256 + onClick={() => loadCredentialsMutation.mutate({ manager: manager() })} 257 + disabled={loadCredentialsMutation.isPending} 258 + > 259 + {loadCredentialsMutation.isPending ? 'Loading...' : 'Load credentials'} 260 + </Button> 261 + 262 + <Show when={loadCredentialsMutation.isSuccess}> 263 + <StatusBadge variant="success">Loaded</StatusBadge> 264 + </Show> 265 + </div> 266 + 267 + <Show when={loadCredentialsMutation.isError}> 268 + <p class="text-sm text-red-600">{`${loadCredentialsMutation.error}`}</p> 269 + </Show> 270 + 271 + <Show when={loadCredentialsMutation.data}> 272 + {(creds) => ( 273 + <> 274 + <div class="mt-2 text-sm"> 275 + <p class="text-gray-500"> 276 + Destination PDS rotation keys ({creds().rotationKeys?.length ?? 0}/5): 277 + </p> 278 + <div class="mt-1 flex flex-col gap-1"> 279 + <For each={creds().rotationKeys ?? []}> 280 + {(key) => <code class="block truncate text-xs text-gray-700">{key}</code>} 281 + </For> 282 + </div> 283 + </div> 284 + 285 + <Show when={source()?.manager && source()}> 286 + {(src) => ( 287 + <div class="mt-3 rounded border border-blue-200 bg-blue-50 p-3"> 288 + <div class="flex items-center justify-between"> 289 + <p class="text-sm font-medium text-blue-800">Analyze existing rotation keys</p> 290 + <Button 291 + variant="outline" 292 + onClick={() => 293 + analyzeRotationKeysMutation.mutate({ 294 + did: src().did as Did<'plc'>, 295 + sourceManager: src().manager!, 296 + }) 297 + } 298 + disabled={analyzeRotationKeysMutation.isPending} 299 + > 300 + {analyzeRotationKeysMutation.isPending ? 'Analyzing...' : 'Analyze'} 301 + </Button> 302 + </div> 303 + <p class="mt-1 text-xs text-blue-600"> 304 + Check if you have any user-controlled rotation keys that should be preserved 305 + during migration. 306 + </p> 307 + 308 + <Show when={analyzeRotationKeysMutation.error}> 309 + <p class="mt-2 text-sm text-red-600">{`${analyzeRotationKeysMutation.error}`}</p> 310 + </Show> 311 + 312 + <Show when={analyzeRotationKeysMutation.data}> 313 + {(analysis) => ( 314 + <div class="mt-2 text-sm"> 315 + <Show 316 + when={analysis().userControlledKeys.length > 0} 317 + fallback={ 318 + <p class="text-blue-700"> 319 + No user-controlled rotation keys found. Your current keys are all 320 + managed by your source PDS. 321 + </p> 322 + } 323 + > 324 + <p class="font-medium text-blue-800"> 325 + Found {analysis().userControlledKeys.length} user-controlled key(s) to 326 + preserve: 327 + </p> 328 + <div class="mt-1 flex flex-col gap-1"> 329 + <For each={analysis().userControlledKeys}> 330 + {(key) => ( 331 + <code class="block truncate text-xs text-blue-700">{key}</code> 332 + )} 333 + </For> 334 + </div> 335 + <p class="mt-2 text-xs text-blue-600"> 336 + These keys have been added to the custom keys section below. 337 + </p> 338 + </Show> 339 + </div> 340 + )} 341 + </Show> 342 + </div> 343 + )} 344 + </Show> 345 + 346 + <details class="mt-2"> 347 + <summary class="cursor-pointer text-sm text-gray-600">View full credentials</summary> 348 + <pre class="mt-2 max-h-48 overflow-auto rounded border border-gray-200 bg-gray-50 p-2 font-mono text-xs"> 349 + {JSON.stringify(creds(), null, 2)} 350 + </pre> 351 + </details> 352 + </> 353 + )} 354 + </Show> 355 + </> 356 + )} 357 + </Show> 358 + </Subsection> 359 + 360 + <Subsection title="2. Rotation keys (optional)"> 361 + <p class="text-sm text-gray-600"> 362 + Add a rotation key to recover your account if your new PDS goes rogue. This will be prepended to the 363 + PDS rotation keys shown above. 364 + </p> 365 + 366 + <ToggleInput 367 + label="Generate a new rotation key" 368 + checked={useGeneratedKey()} 369 + onChange={(checked) => { 370 + setUseGeneratedKey(checked); 371 + // Auto-generate if checked and no key exists yet 372 + if (checked && !generateKeyMutation.data && !generateKeyMutation.isPending) { 373 + generateKeyMutation.mutate(); 374 + } 375 + }} 376 + /> 377 + 378 + <Show when={useGeneratedKey() && generateKeyMutation.isPending}> 379 + <p class="mt-2 text-sm text-gray-500">Generating key...</p> 380 + </Show> 381 + 382 + <Show when={useGeneratedKey() && generateKeyMutation.isError}> 383 + <p class="mt-2 text-sm text-red-600">{`${generateKeyMutation.error}`}</p> 384 + </Show> 385 + 386 + <Show when={useGeneratedKey() && generateKeyMutation.data}> 387 + {(keypair) => ( 388 + <div class="rounded border border-green-300 bg-green-50 p-3"> 389 + <p class="mb-2 text-sm font-semibold text-green-800">Save your rotation key private key!</p> 390 + <p class="mb-3 text-xs text-green-700"> 391 + Store this securely. You'll need it to recover your account if your PDS becomes unavailable or 392 + malicious. 393 + </p> 394 + 395 + <div class="flex flex-col gap-2 text-sm"> 396 + <div> 397 + <p class="font-medium text-gray-600">Public key (did:key)</p> 398 + <p class="break-all font-mono text-xs">{keypair().publicDidKey}</p> 399 + </div> 400 + <div> 401 + <p class="font-medium text-gray-600">Private key (hex)</p> 402 + <p class="break-all font-mono text-xs">{keypair().privateHex}</p> 403 + </div> 404 + <div> 405 + <p class="font-medium text-gray-600">Private key (multikey)</p> 406 + <p class="break-all font-mono text-xs">{keypair().privateMultikey}</p> 407 + </div> 408 + </div> 409 + </div> 410 + )} 411 + </Show> 412 + 413 + <div class="rounded border border-gray-200 bg-gray-50 p-3"> 414 + <p class="mb-2 text-sm font-medium text-gray-700">Custom rotation keys</p> 415 + <p class="mb-3 text-xs text-gray-500"> 416 + Add existing rotation keys (did:key format) you already control. 417 + </p> 418 + 419 + <Index each={customKeys()}> 420 + {(key, index) => ( 421 + <div class="mb-2 flex items-center gap-2"> 422 + <TextInput 423 + label="" 424 + placeholder="did:key:z..." 425 + monospace 426 + autocomplete="off" 427 + value={key()} 428 + onChange={(value) => updateCustomKey(index, value)} 429 + /> 430 + <button 431 + type="button" 432 + class="shrink-0 rounded px-2 py-1 text-sm text-red-600 hover:bg-red-50" 433 + onClick={() => removeCustomKey(index)} 434 + > 435 + Remove 436 + </button> 437 + </div> 438 + )} 439 + </Index> 440 + 441 + <Button variant="outline" onClick={addCustomKey} disabled={!canAddCustomKey()}> 442 + Add rotation key 443 + </Button> 444 + 445 + <Show when={isOverLimit()}> 446 + <p class="mt-2 text-sm text-red-600"> 447 + Too many rotation keys. PLC documents can only have up to 5 rotation keys total. 448 + </p> 449 + </Show> 450 + 451 + <p class="mt-2 text-xs text-gray-500"> 452 + Total keys: {totalKeyCount()}/5 (PDS: {pdsKeyCount()} 453 + {useGeneratedKey() && generateKeyMutation.data ? ', generated: 1' : ''} 454 + {customKeys().filter((k) => k.trim()).length > 0 455 + ? `, custom: ${customKeys().filter((k) => k.trim()).length}` 456 + : ''} 457 + ) 458 + </p> 459 + </div> 460 + </Subsection> 461 + 462 + <Subsection title="3. Request operation signature"> 463 + <p class="text-sm text-gray-600">Request a confirmation token via email from your source PDS.</p> 464 + 465 + <Show 466 + when={source()?.manager} 467 + fallback={<p class="text-sm text-gray-500">Sign in to source account first.</p>} 468 + > 469 + {(manager) => ( 470 + <> 471 + <div class="flex items-center gap-3"> 472 + <Button 473 + onClick={() => requestTokenMutation.mutate({ manager: manager() })} 474 + disabled={requestTokenMutation.isPending} 475 + > 476 + {requestTokenMutation.isPending ? 'Requesting...' : 'Request token'} 477 + </Button> 478 + 479 + <Show when={requestTokenMutation.isSuccess}> 480 + <StatusBadge variant="success">Email sent</StatusBadge> 481 + </Show> 482 + </div> 483 + 484 + <Show when={requestTokenMutation.isError}> 485 + <p class="text-sm text-red-600">{`${requestTokenMutation.error}`}</p> 486 + </Show> 487 + 488 + <Show when={requestTokenMutation.isSuccess}> 489 + <p class="text-sm text-gray-600">Check your email inbox for the confirmation code.</p> 490 + </Show> 491 + </> 492 + )} 493 + </Show> 494 + </Subsection> 495 + 496 + <Subsection title="4. Sign and submit"> 497 + <p class="text-sm text-gray-600">Enter the confirmation code and submit the PLC operation.</p> 498 + 499 + <Show when={!source()?.manager || !destination()?.manager}> 500 + <p class="text-sm text-gray-500">Sign in to both source and destination accounts first.</p> 501 + </Show> 502 + 503 + <Show when={!loadCredentialsMutation.data}> 504 + <p class="text-sm text-gray-500">Load credentials first.</p> 505 + </Show> 506 + 507 + <Show when={useGeneratedKey() && !generateKeyMutation.data}> 508 + <p class="text-sm text-gray-500">Generate your rotation key first.</p> 509 + </Show> 510 + 511 + <Show when={source()?.manager && destination()?.manager && loadCredentialsMutation.data}> 512 + <TextInput 513 + label="Confirmation code from email" 514 + type="text" 515 + autocomplete="one-time-code" 516 + pattern={TOTP_RE.source} 517 + placeholder="AAAAA-BBBBB" 518 + value={plcToken()} 519 + onChange={setPlcToken} 520 + monospace 521 + /> 522 + 523 + <div class="flex items-center gap-3"> 524 + <Button 525 + onClick={handleSignAndSubmit} 526 + disabled={signAndSubmitMutation.isPending || !canSignAndSubmit()} 527 + > 528 + {signAndSubmitMutation.isPending ? 'Submitting...' : 'Sign and submit'} 529 + </Button> 530 + 531 + <Show when={signAndSubmitMutation.isSuccess}> 532 + <StatusBadge variant="success">Identity updated successfully</StatusBadge> 533 + </Show> 534 + </div> 535 + 536 + <Show when={signAndSubmitMutation.isError}> 537 + <p class="text-sm text-red-600">{getSubmitErrorMessage()}</p> 538 + </Show> 539 + </Show> 540 + </Subsection> 541 + </Accordion> 542 + ); 543 + }; 544 + 545 + export default IdentitySection;
+180
src/views/account/account-migrate/sections/preferences.tsx
··· 1 + import { showSaveFilePicker } from 'native-file-system-adapter'; 2 + import { createSignal, Show } from 'solid-js'; 3 + 4 + import { Client, type CredentialManager, ok } from '@atcute/client'; 5 + 6 + import { createMutation } from '~/lib/utils/mutation'; 7 + 8 + import { Accordion, StatusBadge, Subsection } from '~/components/accordion'; 9 + import Button from '~/components/inputs/button'; 10 + import MultilineInput from '~/components/inputs/multiline-input'; 11 + 12 + import { useMigration } from '../context'; 13 + 14 + const PreferencesSection = () => { 15 + const { source, destination } = useMigration(); 16 + 17 + const [prefsInput, setPrefsInput] = createSignal(''); 18 + 19 + const exportMutation = createMutation({ 20 + async mutationFn({ sourceManager }: { sourceManager: CredentialManager }) { 21 + const sourceClient = new Client({ handler: sourceManager }); 22 + const prefs = await ok(sourceClient.get('app.bsky.actor.getPreferences', { params: {} })); 23 + return JSON.stringify(prefs, null, 2); 24 + }, 25 + onSuccess(json) { 26 + setPrefsInput(json); 27 + }, 28 + onError(err) { 29 + console.error(err); 30 + }, 31 + }); 32 + 33 + const downloadPrefs = async () => { 34 + const prefs = exportMutation.data; 35 + if (!prefs) return; 36 + 37 + try { 38 + const fd = await showSaveFilePicker({ 39 + suggestedName: `preferences-${source()?.did}-${new Date().toISOString()}.json`, 40 + // @ts-expect-error: ponyfill doesn't have the full typings 41 + id: 'prefs-export', 42 + startIn: 'downloads', 43 + types: [ 44 + { 45 + description: 'JSON file', 46 + accept: { 'application/json': ['.json'] }, 47 + }, 48 + ], 49 + }).catch((err) => { 50 + if (err instanceof DOMException && err.name === 'AbortError') { 51 + return undefined; 52 + } 53 + throw err; 54 + }); 55 + 56 + if (!fd) return; 57 + 58 + const writable = await fd.createWritable(); 59 + await writable.write(prefs); 60 + await writable.close(); 61 + } catch (err) { 62 + console.error(err); 63 + } 64 + }; 65 + 66 + const importMutation = createMutation({ 67 + async mutationFn({ destManager, input }: { destManager: CredentialManager; input: string }) { 68 + const prefs = JSON.parse(input); 69 + 70 + // Validate that it has a preferences array 71 + if (!prefs.preferences || !Array.isArray(prefs.preferences)) { 72 + throw new Error('Invalid preferences format: missing preferences array'); 73 + } 74 + 75 + const destClient = new Client({ handler: destManager }); 76 + await destClient.post('app.bsky.actor.putPreferences', { 77 + as: null, 78 + input: prefs, 79 + }); 80 + }, 81 + onError(err) { 82 + console.error(err); 83 + }, 84 + }); 85 + 86 + const getImportErrorMessage = () => { 87 + const err = importMutation.error; 88 + if (err instanceof SyntaxError) { 89 + return 'Invalid JSON format'; 90 + } 91 + return `${err}`; 92 + }; 93 + 94 + return ( 95 + <Accordion title="Preferences"> 96 + <Subsection title="Export from source"> 97 + <p class="text-sm text-gray-600"> 98 + Export your Bluesky preferences (muted words, content filters, saved feeds, etc). 99 + </p> 100 + 101 + <Show 102 + when={source()?.manager} 103 + fallback={<p class="text-sm text-gray-500">Sign in to source account first.</p>} 104 + > 105 + {(sourceManager) => ( 106 + <> 107 + <div class="flex items-center gap-3"> 108 + <Button 109 + onClick={() => exportMutation.mutate({ sourceManager: sourceManager() })} 110 + disabled={exportMutation.isPending} 111 + > 112 + {exportMutation.isPending ? 'Exporting...' : 'Export preferences'} 113 + </Button> 114 + 115 + <Show when={exportMutation.data}> 116 + <Button variant="secondary" onClick={downloadPrefs}> 117 + Download as file 118 + </Button> 119 + </Show> 120 + </div> 121 + 122 + <Show when={exportMutation.error}> 123 + {(err) => <p class="text-sm text-red-600">{`${err()}`}</p>} 124 + </Show> 125 + 126 + <Show when={exportMutation.data}> 127 + {(prefs) => ( 128 + <details class="mt-2"> 129 + <summary class="cursor-pointer text-sm text-gray-600"> 130 + View exported preferences 131 + </summary> 132 + <pre class="mt-2 max-h-48 overflow-auto rounded border border-gray-200 bg-gray-50 p-2 font-mono text-xs"> 133 + {prefs()} 134 + </pre> 135 + </details> 136 + )} 137 + </Show> 138 + </> 139 + )} 140 + </Show> 141 + </Subsection> 142 + 143 + <Subsection title="Import to destination"> 144 + <p class="text-sm text-gray-600">Paste preferences JSON or use the exported data above.</p> 145 + 146 + <Show 147 + when={destination()?.manager} 148 + fallback={<p class="text-sm text-gray-500">Sign in to destination account first.</p>} 149 + > 150 + {(destManager) => ( 151 + <> 152 + <MultilineInput label="Preferences JSON" value={prefsInput()} onChange={setPrefsInput} /> 153 + 154 + <div class="flex items-center gap-3"> 155 + <Button 156 + onClick={() => 157 + importMutation.mutate({ destManager: destManager(), input: prefsInput().trim() }) 158 + } 159 + disabled={importMutation.isPending || !prefsInput().trim()} 160 + > 161 + {importMutation.isPending ? 'Importing...' : 'Import preferences'} 162 + </Button> 163 + 164 + <Show when={importMutation.isSuccess}> 165 + <StatusBadge variant="success">Preferences imported successfully</StatusBadge> 166 + </Show> 167 + </div> 168 + 169 + <Show when={importMutation.error}> 170 + <p class="text-sm text-red-600">{getImportErrorMessage()}</p> 171 + </Show> 172 + </> 173 + )} 174 + </Show> 175 + </Subsection> 176 + </Accordion> 177 + ); 178 + }; 179 + 180 + export default PreferencesSection;
+291
src/views/account/account-migrate/sections/repository.tsx
··· 1 + import { showOpenFilePicker, showSaveFilePicker } from 'native-file-system-adapter'; 2 + import { createSignal, Show } from 'solid-js'; 3 + 4 + import { Client, type CredentialManager, ok, simpleFetchHandler } from '@atcute/client'; 5 + import type { Did } from '@atcute/lexicons/syntax'; 6 + 7 + import { formatBytes } from '~/lib/utils/intl/bytes'; 8 + import { createMutation } from '~/lib/utils/mutation'; 9 + import { iterateStream } from '~/lib/utils/stream'; 10 + 11 + import { Accordion, StatusBadge, Subsection } from '~/components/accordion'; 12 + import Button from '~/components/inputs/button'; 13 + 14 + import { useMigration } from '../context'; 15 + 16 + const RepositorySection = () => { 17 + const { source, destination } = useMigration(); 18 + 19 + // Export state 20 + const [exportStatus, setExportStatus] = createSignal<string>(); 21 + 22 + // Import state 23 + const [importStatus, setImportStatus] = createSignal<string>(); 24 + const [importedRecords, setImportedRecords] = createSignal<number>(); 25 + 26 + const exportMutation = createMutation({ 27 + async mutationFn({ pdsUrl, did }: { pdsUrl: string; did: Did }) { 28 + setExportStatus('Waiting for file picker...'); 29 + 30 + const fd = await showSaveFilePicker({ 31 + suggestedName: `repo-${did}-${new Date().toISOString()}.car`, 32 + // @ts-expect-error: ponyfill doesn't have the full typings 33 + id: 'repo-export', 34 + startIn: 'downloads', 35 + types: [ 36 + { 37 + description: 'CAR archive file', 38 + accept: { 'application/vnd.ipld.car': ['.car'] }, 39 + }, 40 + ], 41 + }).catch((err) => { 42 + if (err instanceof DOMException && err.name === 'AbortError') { 43 + return undefined; 44 + } 45 + throw err; 46 + }); 47 + 48 + if (!fd) { 49 + setExportStatus(); 50 + return null; 51 + } 52 + 53 + const writable = await fd.createWritable(); 54 + 55 + setExportStatus('Downloading repository...'); 56 + 57 + const sourceClient = new Client({ handler: simpleFetchHandler({ service: pdsUrl }) }); 58 + const response = await sourceClient.get('com.atproto.sync.getRepo', { 59 + as: 'stream', 60 + params: { did }, 61 + }); 62 + 63 + if (!response.ok) { 64 + throw new Error(`Failed to download repository: ${response.status}`); 65 + } 66 + 67 + let size = 0; 68 + for await (const chunk of iterateStream(response.data)) { 69 + size += chunk.length; 70 + await writable.write(chunk); 71 + setExportStatus(`Downloading repository... (${formatBytes(size)})`); 72 + } 73 + 74 + await writable.close(); 75 + setExportStatus(`Exported ${formatBytes(size)}`); 76 + return size; 77 + }, 78 + onMutate() { 79 + setExportStatus(); 80 + }, 81 + onError(err) { 82 + console.error(err); 83 + setExportStatus(); 84 + }, 85 + }); 86 + 87 + const importFromFileMutation = createMutation({ 88 + async mutationFn({ manager }: { manager: CredentialManager }) { 89 + setImportStatus('Waiting for file picker...'); 90 + 91 + const [fd] = await showOpenFilePicker({ 92 + // @ts-expect-error: ponyfill doesn't have the full typings 93 + id: 'repo-import', 94 + types: [ 95 + { 96 + description: 'CAR archive file', 97 + accept: { 'application/vnd.ipld.car': ['.car'] }, 98 + }, 99 + ], 100 + }).catch((err) => { 101 + if (err instanceof DOMException && err.name === 'AbortError') { 102 + return [undefined]; 103 + } 104 + throw err; 105 + }); 106 + 107 + if (!fd) { 108 + setImportStatus(); 109 + return null; 110 + } 111 + 112 + const file = await fd.getFile(); 113 + 114 + setImportStatus(`Uploading repository (${formatBytes(file.size)})...`); 115 + 116 + const destClient = new Client({ handler: manager }); 117 + const importResp = await destClient.post('com.atproto.repo.importRepo', { 118 + as: null, 119 + input: file, 120 + headers: { 121 + 'content-type': 'application/vnd.ipld.car', 122 + }, 123 + }); 124 + 125 + if (!importResp.ok) { 126 + throw new Error(`Failed to import repository: ${importResp.status}`); 127 + } 128 + 129 + // Check account status to get record count 130 + const status = await ok(destClient.get('com.atproto.server.checkAccountStatus', {})); 131 + setImportedRecords(status.indexedRecords); 132 + 133 + setImportStatus(`Imported successfully`); 134 + return status.indexedRecords; 135 + }, 136 + onMutate() { 137 + setImportStatus(); 138 + setImportedRecords(); 139 + }, 140 + onError(err) { 141 + console.error(err); 142 + setImportStatus(); 143 + }, 144 + }); 145 + 146 + const importFromSourceMutation = createMutation({ 147 + async mutationFn({ 148 + sourcePdsUrl, 149 + sourceDid, 150 + destManager, 151 + }: { 152 + sourcePdsUrl: string; 153 + sourceDid: Did; 154 + destManager: CredentialManager; 155 + }) { 156 + setImportStatus('Downloading from source PDS...'); 157 + 158 + const sourceClient = new Client({ handler: simpleFetchHandler({ service: sourcePdsUrl }) }); 159 + const response = await sourceClient.get('com.atproto.sync.getRepo', { 160 + as: 'bytes', 161 + params: { did: sourceDid }, 162 + }); 163 + 164 + if (!response.ok) { 165 + throw new Error(`Failed to download repository: ${response.status}`); 166 + } 167 + 168 + setImportStatus(`Uploading to destination (${formatBytes(response.data.length)})...`); 169 + 170 + const destClient = new Client({ handler: destManager }); 171 + const importResp = await destClient.post('com.atproto.repo.importRepo', { 172 + as: null, 173 + input: response.data, 174 + headers: { 175 + 'content-type': 'application/vnd.ipld.car', 176 + }, 177 + }); 178 + 179 + if (!importResp.ok) { 180 + throw new Error(`Failed to import repository: ${importResp.status}`); 181 + } 182 + 183 + // Check account status to get record count 184 + const status = await ok(destClient.get('com.atproto.server.checkAccountStatus', {})); 185 + setImportedRecords(status.indexedRecords); 186 + 187 + setImportStatus(`Imported successfully`); 188 + return status.indexedRecords; 189 + }, 190 + onMutate() { 191 + setImportStatus(); 192 + setImportedRecords(); 193 + }, 194 + onError(err) { 195 + console.error(err); 196 + setImportStatus(); 197 + }, 198 + }); 199 + 200 + const isExporting = () => exportMutation.isPending; 201 + const isImporting = () => importFromFileMutation.isPending || importFromSourceMutation.isPending; 202 + 203 + return ( 204 + <Accordion title="Repository"> 205 + <Subsection title="Export from source"> 206 + <p class="text-sm text-gray-600"> 207 + Download the repository as a CAR file for backup or manual import. 208 + </p> 209 + 210 + <Show when={source()} fallback={<p class="text-sm text-gray-500">Resolve source account first.</p>}> 211 + {(src) => ( 212 + <> 213 + <div class="flex items-center gap-3"> 214 + <Button 215 + onClick={() => exportMutation.mutate({ pdsUrl: src().pdsUrl, did: src().did })} 216 + disabled={isExporting()} 217 + > 218 + {isExporting() ? 'Exporting...' : 'Export to file'} 219 + </Button> 220 + <Show when={exportStatus()}> 221 + <span class="text-sm text-gray-600">{exportStatus()}</span> 222 + </Show> 223 + </div> 224 + 225 + <Show when={exportMutation.isError}> 226 + <p class="text-sm text-red-600">{`${exportMutation.error}`}</p> 227 + </Show> 228 + </> 229 + )} 230 + </Show> 231 + </Subsection> 232 + 233 + <Subsection title="Import to destination"> 234 + <p class="text-sm text-gray-600">Upload a repository CAR file or transfer directly from source.</p> 235 + 236 + <Show 237 + when={destination()?.manager} 238 + fallback={<p class="text-sm text-gray-500">Sign in to destination account first.</p>} 239 + > 240 + {(manager) => ( 241 + <> 242 + <div class="flex flex-wrap items-center gap-3"> 243 + <Button 244 + onClick={() => importFromFileMutation.mutate({ manager: manager() })} 245 + disabled={isImporting()} 246 + > 247 + {isImporting() ? 'Importing...' : 'Import from file'} 248 + </Button> 249 + 250 + <Show when={source()}> 251 + {(src) => ( 252 + <Button 253 + variant="secondary" 254 + onClick={() => 255 + importFromSourceMutation.mutate({ 256 + sourcePdsUrl: src().pdsUrl, 257 + sourceDid: src().did, 258 + destManager: manager(), 259 + }) 260 + } 261 + disabled={isImporting()} 262 + > 263 + Transfer from source 264 + </Button> 265 + )} 266 + </Show> 267 + </div> 268 + 269 + <Show when={importStatus()}> 270 + <div class="flex items-center gap-2"> 271 + <span class="text-sm text-gray-600">{importStatus()}</span> 272 + <Show when={importedRecords() !== undefined}> 273 + <StatusBadge variant="success">{importedRecords()} records</StatusBadge> 274 + </Show> 275 + </div> 276 + </Show> 277 + 278 + <Show when={importFromFileMutation.isError || importFromSourceMutation.isError}> 279 + <p class="text-sm text-red-600"> 280 + {`${importFromFileMutation.error || importFromSourceMutation.error}`} 281 + </p> 282 + </Show> 283 + </> 284 + )} 285 + </Show> 286 + </Subsection> 287 + </Accordion> 288 + ); 289 + }; 290 + 291 + export default RepositorySection;
+265
src/views/account/account-migrate/sections/source-account.tsx
··· 1 + import { createSignal, Show } from 'solid-js'; 2 + 3 + import { type AtpAccessJwt, ClientResponseError, CredentialManager } from '@atcute/client'; 4 + import { getPdsEndpoint, isAtprotoDid } from '@atcute/identity'; 5 + import { isHandle, type AtprotoDid } from '@atcute/lexicons/syntax'; 6 + 7 + import { getDidDocument } from '~/api/queries/did-doc'; 8 + import { resolveHandleViaAppView } from '~/api/queries/handle'; 9 + import { formatTotpCode, TOTP_RE } from '~/api/utils/auth'; 10 + import { decodeJwt } from '~/api/utils/jwt'; 11 + 12 + import { createMutation } from '~/lib/utils/mutation'; 13 + 14 + import { Accordion, StatusBadge, Subsection } from '~/components/accordion'; 15 + import Button from '~/components/inputs/button'; 16 + import TextInput from '~/components/inputs/text-input'; 17 + 18 + import { useMigration } from '../context'; 19 + 20 + interface SourceAccountSectionProps { 21 + onStarted?: () => void; 22 + } 23 + 24 + class InsufficientLoginError extends Error {} 25 + 26 + const SourceAccountSection = (props: SourceAccountSectionProps) => { 27 + const { source, setSource } = useMigration(); 28 + 29 + // Resolve state 30 + const [identifier, setIdentifier] = createSignal(''); 31 + const [resolveError, setResolveError] = createSignal<string>(); 32 + 33 + // Auth state 34 + const [password, setPassword] = createSignal(''); 35 + const [otp, setOtp] = createSignal(''); 36 + const [isTotpRequired, setIsTotpRequired] = createSignal(false); 37 + const [authError, setAuthError] = createSignal<string>(); 38 + 39 + const resolveMutation = createMutation({ 40 + async mutationFn({ identifier }: { identifier: string }) { 41 + let did: AtprotoDid; 42 + if (isAtprotoDid(identifier)) { 43 + did = identifier; 44 + } else if (isHandle(identifier)) { 45 + did = await resolveHandleViaAppView({ handle: identifier }); 46 + } else { 47 + throw new Error(`${identifier} is not a valid DID or handle`); 48 + } 49 + 50 + const didDoc = await getDidDocument({ did }); 51 + const pdsUrl = getPdsEndpoint(didDoc); 52 + 53 + if (!pdsUrl) { 54 + throw new Error(`No PDS endpoint found in DID document`); 55 + } 56 + 57 + return { did, didDoc, pdsUrl }; 58 + }, 59 + onMutate() { 60 + setResolveError(); 61 + }, 62 + onSuccess({ did, didDoc, pdsUrl }) { 63 + setSource({ did, didDoc, pdsUrl, manager: null }); 64 + props.onStarted?.(); 65 + }, 66 + onError(err) { 67 + if (err instanceof ClientResponseError) { 68 + if (err.error === 'InvalidRequest' && err.description?.includes('resolve handle')) { 69 + setResolveError(`Can't resolve handle, is it typed correctly?`); 70 + return; 71 + } 72 + } 73 + console.error(err); 74 + setResolveError(`${err}`); 75 + }, 76 + }); 77 + 78 + const authMutation = createMutation({ 79 + async mutationFn({ pdsUrl, did, password, otp }: { pdsUrl: string; did: string; password: string; otp: string }) { 80 + const manager = new CredentialManager({ service: pdsUrl }); 81 + const session = await manager.login({ 82 + identifier: did, 83 + password: password, 84 + code: formatTotpCode(otp), 85 + }); 86 + 87 + const decoded = decodeJwt(session.accessJwt) as AtpAccessJwt; 88 + if (decoded.scope !== 'com.atproto.access') { 89 + throw new InsufficientLoginError(`You need to sign in with a main password, not an app password`); 90 + } 91 + 92 + return manager; 93 + }, 94 + onMutate() { 95 + setAuthError(); 96 + }, 97 + onSuccess(manager) { 98 + setSource({ ...source()!, manager }); 99 + setPassword(''); 100 + setOtp(''); 101 + setIsTotpRequired(false); 102 + }, 103 + onError(err) { 104 + if (err instanceof ClientResponseError) { 105 + if (err.error === 'AuthFactorTokenRequired') { 106 + setOtp(''); 107 + setIsTotpRequired(true); 108 + return; 109 + } 110 + if (err.error === 'AuthenticationRequired') { 111 + setAuthError(`Invalid identifier or password`); 112 + return; 113 + } 114 + if (err.error === 'AccountTakedown') { 115 + setAuthError(`Account has been taken down`); 116 + return; 117 + } 118 + if (err.description?.includes('Token is invalid')) { 119 + setAuthError(`Invalid one-time confirmation code`); 120 + setIsTotpRequired(true); 121 + return; 122 + } 123 + } 124 + if (err instanceof InsufficientLoginError) { 125 + setAuthError(err.message); 126 + return; 127 + } 128 + console.error(err); 129 + setAuthError(`${err}`); 130 + }, 131 + }); 132 + 133 + const isResolved = () => source() !== null; 134 + const isAuthenticated = () => source()?.manager != null; 135 + 136 + return ( 137 + <Accordion title="Source Account" defaultOpen> 138 + <Subsection title="Resolve identity"> 139 + <Show when={!isResolved()}> 140 + <form 141 + onSubmit={(ev) => { 142 + ev.preventDefault(); 143 + resolveMutation.mutate({ identifier: identifier() }); 144 + }} 145 + class="flex flex-col gap-3" 146 + > 147 + <TextInput 148 + label="Handle or DID" 149 + placeholder="alice.bsky.social" 150 + value={identifier()} 151 + required 152 + autofocus 153 + onChange={setIdentifier} 154 + /> 155 + 156 + <Show when={resolveError()}> 157 + <p class="text-sm text-red-600">{resolveError()}</p> 158 + </Show> 159 + 160 + <div> 161 + <Button type="submit" disabled={resolveMutation.isPending}> 162 + {resolveMutation.isPending ? 'Resolving...' : 'Resolve'} 163 + </Button> 164 + </div> 165 + </form> 166 + </Show> 167 + 168 + <Show when={isResolved()}> 169 + <div class="flex flex-col gap-2 text-sm"> 170 + <p> 171 + <span class="text-gray-500">DID:</span>{' '} 172 + <span class="font-mono">{source()!.did}</span> 173 + </p> 174 + <p> 175 + <span class="text-gray-500">PDS:</span>{' '} 176 + <span class="font-mono">{source()!.pdsUrl}</span> 177 + </p> 178 + <div class="mt-1"> 179 + <button 180 + type="button" 181 + onClick={() => setSource(null)} 182 + class="text-sm text-purple-800 hover:underline" 183 + > 184 + Change account 185 + </button> 186 + </div> 187 + </div> 188 + </Show> 189 + </Subsection> 190 + 191 + <Show when={isResolved()}> 192 + <Subsection title="Authenticate"> 193 + <p class="text-sm text-gray-600"> 194 + Authentication is required for some operations like exporting preferences or signing PLC operations. 195 + </p> 196 + 197 + <Show when={!isAuthenticated()}> 198 + <form 199 + onSubmit={(ev) => { 200 + ev.preventDefault(); 201 + const src = source()!; 202 + authMutation.mutate({ 203 + pdsUrl: src.pdsUrl, 204 + did: src.did, 205 + password: password(), 206 + otp: otp(), 207 + }); 208 + }} 209 + class="flex flex-col gap-3" 210 + > 211 + <TextInput 212 + label="Main password" 213 + blurb="Your credentials stay entirely within your browser." 214 + type="password" 215 + value={password()} 216 + required 217 + onChange={setPassword} 218 + /> 219 + 220 + <Show when={isTotpRequired()}> 221 + <TextInput 222 + label="One-time confirmation code" 223 + blurb="A code has been sent to your email address." 224 + type="text" 225 + autocomplete="one-time-code" 226 + pattern={TOTP_RE.source} 227 + placeholder="AAAAA-BBBBB" 228 + value={otp()} 229 + required 230 + onChange={setOtp} 231 + monospace 232 + /> 233 + </Show> 234 + 235 + <Show when={authError()}> 236 + <p class="text-sm text-red-600">{authError()}</p> 237 + </Show> 238 + 239 + <div> 240 + <Button type="submit" disabled={authMutation.isPending}> 241 + {authMutation.isPending ? 'Signing in...' : 'Sign in'} 242 + </Button> 243 + </div> 244 + </form> 245 + </Show> 246 + 247 + <Show when={isAuthenticated()}> 248 + <div class="flex items-center gap-2"> 249 + <StatusBadge variant="success">Signed in</StatusBadge> 250 + <button 251 + type="button" 252 + onClick={() => setSource({ ...source()!, manager: null })} 253 + class="text-sm text-purple-800 hover:underline" 254 + > 255 + Sign out 256 + </button> 257 + </div> 258 + </Show> 259 + </Subsection> 260 + </Show> 261 + </Accordion> 262 + ); 263 + }; 264 + 265 + export default SourceAccountSection;
+2 -5
src/views/blob/blob-export.tsx
··· 17 17 import Button from '~/components/inputs/button'; 18 18 import TextInput from '~/components/inputs/text-input'; 19 19 import Logger, { createLogger } from '~/components/logger'; 20 + import PageHeader from '~/components/page-header'; 20 21 21 22 const BlobExportPage = () => { 22 23 const logger = createLogger(); ··· 229 230 230 231 return ( 231 232 <> 232 - <div class="p-4"> 233 - <h1 class="text-lg font-bold text-purple-800">Export blobs</h1> 234 - <p class="text-gray-600">Download all blobs from an account into a tarball</p> 235 - </div> 236 - <hr class="mx-4 border-gray-300" /> 233 + <PageHeader title="Export blobs" subtitle="Download all blobs from an account into a tarball" /> 237 234 238 235 <form 239 236 onSubmit={(ev) => {
+8 -9
src/views/bluesky/threadgate-applicator/page.tsx
··· 2 2 3 3 import { AppBskyFeedDefs, AppBskyFeedThreadgate } from '@atcute/bluesky'; 4 4 import { CredentialManager } from '@atcute/client'; 5 - import { DidDocument } from '@atcute/identity'; 5 + import type { DidDocument } from '@atcute/identity'; 6 6 7 - import { UnwrapArray } from '~/api/utils/types'; 7 + import type { UnwrapArray } from '~/api/utils/types'; 8 8 9 9 import { history } from '~/globals/navigation'; 10 10 11 11 import { useTitle } from '~/lib/navigation/router'; 12 12 13 + import PageHeader from '~/components/page-header'; 13 14 import { Wizard } from '~/components/wizard'; 14 15 15 16 import Step1_HandleInput from './steps/step1_handle-input'; ··· 18 19 import Step4_Confirmation from './steps/step4_confirmation'; 19 20 import Step5_Finished from './steps/step5_finished'; 20 21 21 - export interface ThreadgateState 22 - extends Pick<AppBskyFeedThreadgate.Main, 'allow' | 'hiddenReplies' | 'createdAt'> { 22 + export interface ThreadgateState extends Pick< 23 + AppBskyFeedThreadgate.Main, 24 + 'allow' | 'hiddenReplies' | 'createdAt' 25 + > { 23 26 uri: string; 24 27 } 25 28 ··· 78 81 79 82 return ( 80 83 <> 81 - <div class="p-4"> 82 - <h1 class="text-lg font-bold text-purple-800">Retroactive thread gating</h1> 83 - <p class="text-gray-600">Set reply permissions on all of your past Bluesky posts</p> 84 - </div> 85 - <hr class="mx-4 border-gray-300" /> 84 + <PageHeader title="Retroactive thread gating" subtitle="Set reply permissions on all of your past Bluesky posts" /> 86 85 87 86 <Wizard<ThreadgateApplicatorConstraints> 88 87 initialStep="Step1_HandleInput"
+2 -2
src/views/bluesky/threadgate-applicator/steps/step1_handle-input.tsx
··· 14 14 15 15 import Button from '~/components/inputs/button'; 16 16 import TextInput from '~/components/inputs/text-input'; 17 - import { Stage, StageActions, StageErrorView, WizardStepProps } from '~/components/wizard'; 17 + import { Stage, StageActions, StageErrorView, type WizardStepProps } from '~/components/wizard'; 18 18 19 - import { ThreadgateApplicatorConstraints, ThreadgateState, ThreadItem } from '../page'; 19 + import type { ThreadgateApplicatorConstraints, ThreadgateState, ThreadItem } from '../page'; 20 20 import { sortThreadgateState } from '../utils'; 21 21 22 22 class NoThreadsError extends Error {}
+3 -10
src/views/bluesky/threadgate-applicator/steps/step2_rules-input.tsx
··· 2 2 3 3 import { AppBskyFeedThreadgate } from '@atcute/bluesky'; 4 4 import { ok } from '@atcute/client'; 5 - import { $type } from '@atcute/lexicons'; 5 + import type { $type } from '@atcute/lexicons'; 6 6 7 7 import { appViewRpc } from '~/globals/rpc'; 8 8 ··· 11 11 import { createQuery } from '~/lib/utils/query'; 12 12 13 13 import RadioInput from '~/components/inputs/radio-input'; 14 - import { Stage, StageActions, WizardStepProps } from '~/components/wizard'; 14 + import { Stage, StageActions, type WizardStepProps } from '~/components/wizard'; 15 15 16 16 import CircularProgressView from '~/components/circular-progress-view'; 17 17 import Button from '~/components/inputs/button'; 18 18 import ToggleInput from '~/components/inputs/toggle-input'; 19 19 20 - import { ThreadgateApplicatorConstraints, ThreadgateRule } from '../page'; 20 + import type { ThreadgateApplicatorConstraints, ThreadgateRule } from '../page'; 21 21 import { sortThreadgateAllow } from '../utils'; 22 22 23 23 const enum FilterType { ··· 255 255 blurb={ 256 256 <> 257 257 <span>This will apply to {filteredThreads().length} threads. </span> 258 - {/* <button 259 - type="button" 260 - hidden={filteredThreads().length < 1} 261 - class="font-medium text-purple-800 hover:underline" 262 - > 263 - View 264 - </button> */} 265 258 </> 266 259 } 267 260 value={filter()}
+2 -2
src/views/bluesky/threadgate-applicator/steps/step3_authentication.tsx
··· 2 2 3 3 import { CredentialManager } from '@atcute/client'; 4 4 5 - import { WizardStepProps } from '~/components/wizard'; 5 + import type { WizardStepProps } from '~/components/wizard'; 6 6 import BlueskyLoginStep from '~/components/wizards/bluesky-login-step'; 7 7 8 - import { ThreadgateApplicatorConstraints } from '../page'; 8 + import type { ThreadgateApplicatorConstraints } from '../page'; 9 9 10 10 const Step3_Authentication = ({ 11 11 data,
+4 -5
src/views/bluesky/threadgate-applicator/steps/step4_confirmation.tsx
··· 3 3 import type { ComAtprotoRepoApplyWrites } from '@atcute/atproto'; 4 4 import type { AppBskyFeedThreadgate } from '@atcute/bluesky'; 5 5 import { Client, ClientResponseError } from '@atcute/client'; 6 - import { InferXRPCBodyInput } from '@atcute/lexicons'; 6 + import { parseCanonicalResourceUri } from '@atcute/lexicons'; 7 7 import { chunked } from '@mary/array-fns'; 8 - import { parseCanonicalResourceUri } from '@atcute/lexicons'; 9 8 10 9 import { dequal } from '~/lib/utils/dequal'; 11 10 import { createMutation } from '~/lib/utils/mutation'; ··· 13 12 import Button from '~/components/inputs/button'; 14 13 import ToggleInput from '~/components/inputs/toggle-input'; 15 14 import Logger, { createLogger } from '~/components/logger'; 16 - import { Stage, StageActions, StageErrorView, WizardStepProps } from '~/components/wizard'; 15 + import { Stage, StageActions, StageErrorView, type WizardStepProps } from '~/components/wizard'; 17 16 18 - import { ThreadgateApplicatorConstraints } from '../page'; 17 + import type { ThreadgateApplicatorConstraints } from '../page'; 19 18 20 19 const Step4_Confirmation = ({ 21 20 data, ··· 35 34 logger.log(`Preparing writes`); 36 35 37 36 const rules = data.rules; 38 - const writes: InferXRPCBodyInput<ComAtprotoRepoApplyWrites.mainSchema['input']>['writes'] = []; 37 + const writes: ComAtprotoRepoApplyWrites.$input['writes'] = []; 39 38 40 39 const now = new Date().toISOString(); 41 40 for (const { post, threadgate } of data.threads) {
+2 -2
src/views/bluesky/threadgate-applicator/steps/step5_finished.tsx
··· 1 - import { Stage, WizardStepProps } from '~/components/wizard'; 1 + import { Stage, type WizardStepProps } from '~/components/wizard'; 2 2 3 - import { ThreadgateApplicatorConstraints } from '../page'; 3 + import type { ThreadgateApplicatorConstraints } from '../page'; 4 4 5 5 export const Step5_Finished = ({}: WizardStepProps<ThreadgateApplicatorConstraints, 'Step5_Finished'>) => { 6 6 return (
+1 -1
src/views/bluesky/threadgate-applicator/utils.ts
··· 1 - import { ThreadgateState } from './page'; 1 + import type { ThreadgateState } from './page'; 2 2 3 3 const collator = new Intl.Collator('en'); 4 4
+3 -6
src/views/crypto/crypto-generate.tsx
··· 6 6 7 7 import Button from '~/components/inputs/button'; 8 8 import RadioInput from '~/components/inputs/radio-input'; 9 + import PageHeader from '~/components/page-header'; 9 10 10 11 type KeyType = 'p256' | 'secp256k1'; 11 12 ··· 26 27 27 28 return ( 28 29 <> 29 - <div class="p-4"> 30 - <h1 class="text-lg font-bold text-purple-800">Generate secret keys</h1> 31 - <p class="text-gray-600">Create a new secp256k1/nistp256 keypair</p> 32 - </div> 33 - <hr class="mx-4 border-gray-300" /> 30 + <PageHeader title="Generate secret keys" subtitle="Create a new secp256k1/nistp256 keypair" /> 34 31 35 32 <form 36 33 onSubmit={async (ev) => { ··· 54 51 ]); 55 52 56 53 const result: KeypairResult = { 57 - type: keypair.type, 54 + type: keypair.type as KeyType, 58 55 publicDidKey, 59 56 privateHex, 60 57 privateMultikey,
+255
src/views/crypto/crypto-info.tsx
··· 1 + import { createMemo, createSignal, Match, Show, Switch } from 'solid-js'; 2 + 3 + import { 4 + type DidKeyString, 5 + P256PrivateKeyExportable, 6 + P256PublicKey, 7 + parseDidKey, 8 + parsePrivateMultikey, 9 + parsePublicMultikey, 10 + Secp256k1PrivateKeyExportable, 11 + Secp256k1PublicKey, 12 + } from '@atcute/crypto'; 13 + import { fromBase16 } from '@atcute/multibase'; 14 + 15 + import { useTitle } from '~/lib/navigation/router'; 16 + 17 + import Button from '~/components/inputs/button'; 18 + import RadioInput from '~/components/inputs/radio-input'; 19 + import TextInput from '~/components/inputs/text-input'; 20 + import PageHeader from '~/components/page-header'; 21 + 22 + type KeyType = 'p256' | 'secp256k1'; 23 + type KeyFormat = 'did:key' | 'multikey' | 'hex'; 24 + 25 + interface KeyInfo { 26 + keyType: KeyType; 27 + isPrivate: boolean; 28 + inputFormat: KeyFormat; 29 + publicDidKey: DidKeyString; 30 + publicMultikey: string; 31 + privateHex?: string; 32 + privateMultikey?: string; 33 + } 34 + 35 + const DID_KEY_REGEX = /^did:key:z[a-km-zA-HJ-NP-Z1-9]+$/; 36 + const MULTIKEY_REGEX = /^z[a-km-zA-HJ-NP-Z1-9]+$/; 37 + const HEX_REGEX = /^[0-9a-f]+$/; 38 + 39 + const CryptoInfoPage = () => { 40 + const [input, setInput] = createSignal(''); 41 + const [hexKeyType, setHexKeyType] = createSignal<KeyType>(); 42 + const [result, setResult] = createSignal<KeyInfo>(); 43 + const [error, setError] = createSignal<string>(); 44 + 45 + const detectedFormat = createMemo((): KeyFormat | undefined => { 46 + const $input = input().trim(); 47 + 48 + if (DID_KEY_REGEX.test($input)) { 49 + return 'did:key'; 50 + } 51 + if (MULTIKEY_REGEX.test($input)) { 52 + return 'multikey'; 53 + } 54 + if (HEX_REGEX.test($input)) { 55 + return 'hex'; 56 + } 57 + }); 58 + 59 + const canSubmit = createMemo(() => { 60 + const format = detectedFormat(); 61 + if (!format) { 62 + return false; 63 + } 64 + if (format === 'hex' && !hexKeyType()) { 65 + return false; 66 + } 67 + return true; 68 + }); 69 + 70 + useTitle(() => `View crypto key info โ€” boat`); 71 + 72 + return ( 73 + <> 74 + <PageHeader title="View crypto key info" subtitle="Show basic metadata about a public or private key" /> 75 + 76 + <form 77 + onSubmit={async (ev) => { 78 + ev.preventDefault(); 79 + 80 + const $input = input().trim(); 81 + const format = detectedFormat(); 82 + 83 + setResult(); 84 + setError(); 85 + 86 + try { 87 + let info: KeyInfo; 88 + 89 + if (format === 'did:key') { 90 + const parsed = parseDidKey($input); 91 + const pubKey = 92 + parsed.type === 'p256' 93 + ? await P256PublicKey.importRaw(parsed.publicKeyBytes) 94 + : await Secp256k1PublicKey.importRaw(parsed.publicKeyBytes); 95 + 96 + info = { 97 + keyType: parsed.type, 98 + isPrivate: false, 99 + inputFormat: 'did:key', 100 + publicDidKey: await pubKey.exportPublicKey('did'), 101 + publicMultikey: await pubKey.exportPublicKey('multikey'), 102 + }; 103 + } else if (format === 'multikey') { 104 + // try parsing as private key first 105 + try { 106 + const parsed = parsePrivateMultikey($input); 107 + const privKey = 108 + parsed.type === 'p256' 109 + ? await P256PrivateKeyExportable.importRaw(parsed.privateKeyBytes) 110 + : await Secp256k1PrivateKeyExportable.importRaw(parsed.privateKeyBytes); 111 + 112 + info = { 113 + keyType: parsed.type, 114 + isPrivate: true, 115 + inputFormat: 'multikey', 116 + publicDidKey: await privKey.exportPublicKey('did'), 117 + publicMultikey: await privKey.exportPublicKey('multikey'), 118 + privateHex: await privKey.exportPrivateKey('rawHex'), 119 + privateMultikey: await privKey.exportPrivateKey('multikey'), 120 + }; 121 + } catch { 122 + // try parsing as public key 123 + const parsed = parsePublicMultikey($input); 124 + const pubKey = 125 + parsed.type === 'p256' 126 + ? await P256PublicKey.importRaw(parsed.publicKeyBytes) 127 + : await Secp256k1PublicKey.importRaw(parsed.publicKeyBytes); 128 + 129 + info = { 130 + keyType: parsed.type, 131 + isPrivate: false, 132 + inputFormat: 'multikey', 133 + publicDidKey: await pubKey.exportPublicKey('did'), 134 + publicMultikey: await pubKey.exportPublicKey('multikey'), 135 + }; 136 + } 137 + } else if (format === 'hex') { 138 + const keyType = hexKeyType()!; 139 + const privateKeyBytes = fromBase16($input); 140 + 141 + const privKey = 142 + keyType === 'p256' 143 + ? await P256PrivateKeyExportable.importRaw(privateKeyBytes) 144 + : await Secp256k1PrivateKeyExportable.importRaw(privateKeyBytes); 145 + 146 + info = { 147 + keyType: keyType, 148 + isPrivate: true, 149 + inputFormat: 'hex', 150 + publicDidKey: await privKey.exportPublicKey('did'), 151 + publicMultikey: await privKey.exportPublicKey('multikey'), 152 + privateHex: await privKey.exportPrivateKey('rawHex'), 153 + privateMultikey: await privKey.exportPrivateKey('multikey'), 154 + }; 155 + } else { 156 + throw new Error('Unknown key format'); 157 + } 158 + 159 + setResult(info); 160 + } catch (err) { 161 + console.error(err); 162 + setError(`Failed to parse key: ${err}`); 163 + } 164 + }} 165 + class="flex flex-col gap-4 p-4" 166 + > 167 + <TextInput 168 + label="Public or private key" 169 + blurb="Accepts did:key, multikey, or hex format" 170 + monospace 171 + autocomplete="off" 172 + autocorrect="off" 173 + placeholder="did:key:z... or z... or a5973930f9d348..." 174 + value={input()} 175 + required 176 + onChange={setInput} 177 + /> 178 + 179 + <Show when={detectedFormat() === 'hex'}> 180 + <RadioInput 181 + label="This is a..." 182 + value={hexKeyType()} 183 + required 184 + options={[ 185 + { value: 'secp256k1', label: `ES256K (secp256k1) private key` }, 186 + { value: 'p256', label: `ES256 (p256) private key` }, 187 + ]} 188 + onChange={setHexKeyType} 189 + /> 190 + </Show> 191 + 192 + <div> 193 + <Button type="submit" disabled={!canSubmit()}> 194 + Inspect 195 + </Button> 196 + </div> 197 + </form> 198 + 199 + <hr class="mx-4 border-gray-300" /> 200 + 201 + <Switch> 202 + <Match when={error()}> 203 + <div class="p-4 text-red-600">{error()}</div> 204 + </Match> 205 + 206 + <Match when={result()} keyed> 207 + {(info) => ( 208 + <div class="flex flex-col gap-6 break-words p-4 text-gray-900"> 209 + <div> 210 + <p class="font-semibold text-gray-600">Key type</p> 211 + <span> 212 + {/* @once */ info.keyType === 'p256' 213 + ? 'ES256 (p256)' 214 + : 'ES256K (secp256k1)'}{' '} 215 + {/* @once */ info.isPrivate ? 'private' : 'public'} key 216 + </span> 217 + </div> 218 + 219 + <div> 220 + <p class="font-semibold text-gray-600">Input encoding</p> 221 + <span>{/* @once */ info.inputFormat}</span> 222 + </div> 223 + 224 + <div> 225 + <p class="font-semibold text-gray-600">Public key (did:key)</p> 226 + <span class="font-mono">{/* @once */ info.publicDidKey}</span> 227 + </div> 228 + 229 + <div> 230 + <p class="font-semibold text-gray-600">Public key (multikey)</p> 231 + <span class="font-mono">{/* @once */ info.publicMultikey}</span> 232 + </div> 233 + 234 + <Show when={info.privateHex}> 235 + <div> 236 + <p class="font-semibold text-gray-600">Private key (hex)</p> 237 + <span class="font-mono">{/* @once */ info.privateHex}</span> 238 + </div> 239 + </Show> 240 + 241 + <Show when={info.privateMultikey}> 242 + <div> 243 + <p class="font-semibold text-gray-600">Private key (multikey)</p> 244 + <span class="font-mono">{/* @once */ info.privateMultikey}</span> 245 + </div> 246 + </Show> 247 + </div> 248 + )} 249 + </Match> 250 + </Switch> 251 + </> 252 + ); 253 + }; 254 + 255 + export default CryptoInfoPage;
+6 -8
src/views/frontpage.tsx
··· 1 - import { Component, ComponentProps } from 'solid-js'; 1 + import type { Component, ComponentProps } from 'solid-js'; 2 2 3 3 import { useTitle } from '~/lib/navigation/router'; 4 + 5 + import PageHeader from '~/components/page-header'; 4 6 5 7 import HistoryIcon from '~/components/ic-icons/baseline-history'; 6 8 import KeyIcon from '~/components/ic-icons/baseline-key'; ··· 102 104 { 103 105 name: `Migrate account`, 104 106 description: `Move your account data to another server`, 105 - href: null, 107 + href: '/account-migrate', 106 108 icon: MoveUpOutlinedIcon, 107 109 }, 108 110 ], ··· 119 121 { 120 122 name: `View crypto key info`, 121 123 description: `Show basic metadata about a public or private key`, 122 - href: null, 124 + href: `/crypto-info`, 123 125 icon: KeyVisualizerIcon, 124 126 }, 125 127 ], ··· 170 172 171 173 return ( 172 174 <> 173 - <div class="p-4"> 174 - <h1 class="text-lg font-bold text-purple-800">boat</h1> 175 - <p class="text-gray-600">handy online tools for AT Protocol</p> 176 - </div> 177 - <hr class="mx-4 border-gray-300" /> 175 + <PageHeader title="boat" subtitle="handy online tools for AT Protocol" /> 178 176 179 177 <div class="flex grow flex-col pb-2">{nodes}</div> 180 178
+18 -29
src/views/identity/did-lookup.tsx
··· 15 15 import ErrorView from '~/components/error-view'; 16 16 import Button from '~/components/inputs/button'; 17 17 import TextInput from '~/components/inputs/text-input'; 18 + import PageHeader from '~/components/page-header'; 18 19 19 20 const DidLookupPage = () => { 20 21 const [params, setParams] = useSearchParams({ ··· 46 47 47 48 return ( 48 49 <> 49 - <div class="p-4"> 50 - <h1 class="text-lg font-bold text-purple-800">View identity info</h1> 51 - <p class="text-gray-600">Look up an account's DID document</p> 52 - </div> 53 - <hr class="mx-4 border-gray-300" /> 50 + <PageHeader title="View identity info" subtitle="Look up an account's DID document" /> 54 51 55 52 <form 56 53 onSubmit={(ev) => { ··· 100 97 101 98 <div> 102 99 <p class="font-semibold text-gray-600">Identifies as</p> 103 - <ol class="list-disc pl-4">{doc.alsoKnownAs?.map((ident) => <li>{ident}</li>)}</ol> 100 + <ol class="list-disc pl-4"> 101 + {doc.alsoKnownAs?.map((ident) => ( 102 + <li>{ident}</li> 103 + ))} 104 + </ol> 104 105 </div> 105 106 106 107 <div> ··· 129 130 130 131 <div class="mt-2 flex flex-wrap gap-2 empty:hidden"> 131 132 {isPDS && isServiceUrl && ( 132 - <button 133 - disabled 134 - class="flex h-9 select-none items-center rounded border border-gray-300 px-4 text-sm font-semibold text-gray-800 hover:bg-gray-100 active:bg-gray-100 disabled:pointer-events-none disabled:opacity-50" 135 - > 133 + <Button variant="outline" disabled> 136 134 View PDS info 137 - </button> 135 + </Button> 138 136 )} 139 137 140 138 {isPDS && isServiceUrl && ( 141 - <button 142 - disabled 143 - class="flex h-9 select-none items-center rounded border border-gray-300 px-4 text-sm font-semibold text-gray-800 hover:bg-gray-100 active:bg-gray-100 disabled:pointer-events-none disabled:opacity-50" 144 - > 139 + <Button variant="outline" disabled> 145 140 Explore account repository 146 - </button> 141 + </Button> 147 142 )} 148 143 149 144 {isLabeler && isServiceUrl && ( 150 - <button 151 - disabled 152 - class="flex h-9 select-none items-center rounded border border-gray-300 px-4 text-sm font-semibold text-gray-800 hover:bg-gray-100 active:bg-gray-100 disabled:pointer-events-none disabled:opacity-50" 153 - > 145 + <Button variant="outline" disabled> 154 146 View emitted labels 155 - </button> 147 + </Button> 156 148 )} 157 149 </div> 158 150 </li> ··· 181 173 </div> 182 174 183 175 <div class="flex flex-wrap gap-4 p-4 pt-2"> 184 - <button 176 + <Button 177 + variant="outline" 185 178 onClick={() => { 186 179 navigator.clipboard.writeText(JSON.stringify(doc, null, 2)); 187 180 }} 188 - class="flex h-9 select-none items-center rounded border border-gray-300 px-4 text-sm font-semibold text-gray-800 hover:bg-gray-100 active:bg-gray-100" 189 181 > 190 182 Copy DID document 191 - </button> 183 + </Button> 192 184 193 185 {isDidPlc && ( 194 - <a 195 - href={`/plc-oplogs?q=${params.q!}`} 196 - class="flex h-9 select-none items-center rounded border border-gray-300 px-4 text-sm font-semibold text-gray-800 hover:bg-gray-100 active:bg-gray-100" 197 - > 186 + <Button variant="outline" href={`/plc-oplogs?q=${params.q!}`}> 198 187 View PLC operation logs 199 - </a> 188 + </Button> 200 189 )} 201 190 </div> 202 191 </>
+4 -8
src/views/identity/plc-applicator/page.tsx
··· 5 5 import type { P256PrivateKey, Secp256k1PrivateKey } from '@atcute/crypto'; 6 6 import type { CompatibleOperation, IndexedEntry, IndexedEntryWithSigner } from '@atcute/did-plc'; 7 7 import type { DidDocument } from '@atcute/identity'; 8 - import { InferXRPCBodyInput } from '@atcute/lexicons'; 9 8 import type { Did } from '@atcute/lexicons/syntax'; 10 9 11 - import { UpdatePayload } from '~/api/types/plc'; 10 + import type { UpdatePayload } from '~/api/types/plc'; 12 11 13 12 import { history } from '~/globals/navigation'; 14 13 15 14 import { useTitle } from '~/lib/navigation/router'; 16 15 16 + import PageHeader from '~/components/page-header'; 17 17 import { Wizard } from '~/components/wizard'; 18 18 19 19 import Step1_HandleInput from './steps/step1_handle-input'; ··· 33 33 export interface PdsSigningMethod { 34 34 type: 'pds'; 35 35 manager: CredentialManager; 36 - recommendedDidDoc: InferXRPCBodyInput<ComAtprotoIdentityGetRecommendedDidCredentials.mainSchema['output']>; 36 + recommendedDidDoc: ComAtprotoIdentityGetRecommendedDidCredentials.$output; 37 37 } 38 38 39 39 export type Keypair = P256PrivateKey | Secp256k1PrivateKey; ··· 102 102 103 103 return ( 104 104 <> 105 - <div class="p-4"> 106 - <h1 class="text-lg font-bold text-purple-800">Apply PLC operations</h1> 107 - <p class="text-gray-600">Submit operations to your did:plc identity</p> 108 - </div> 109 - <hr class="mx-4 border-gray-300" /> 105 + <PageHeader title="Apply PLC operations" subtitle="Submit operations to your did:plc identity" /> 110 106 111 107 <Wizard<PlcApplicatorConstraints> 112 108 initialStep="Step1_HandleInput"
+1 -1
src/views/identity/plc-applicator/plc-utils.ts
··· 1 1 import type { IndexedEntry } from '@atcute/did-plc'; 2 2 3 - import { UpdatePayload } from '~/api/types/plc'; 3 + import type { UpdatePayload } from '~/api/types/plc'; 4 4 5 5 import { assert } from '~/lib/utils/invariant'; 6 6
+4 -2
src/views/identity/plc-applicator/steps/step1_handle-input.tsx
··· 14 14 import Button from '~/components/inputs/button'; 15 15 import RadioInput from '~/components/inputs/radio-input'; 16 16 import TextInput from '~/components/inputs/text-input'; 17 - import { Stage, StageActions, StageErrorView, WizardStepProps } from '~/components/wizard'; 17 + import { Stage, StageActions, StageErrorView, type WizardStepProps } from '~/components/wizard'; 18 18 19 - import { PlcApplicatorConstraints, type PlcInformation } from '../page'; 19 + import type { PlcApplicatorConstraints, PlcInformation } from '../page'; 20 20 21 21 type Method = 'pds' | 'key'; 22 22 ··· 84 84 if (message !== undefined) { 85 85 setError(message); 86 86 } else { 87 + console.error(err); 88 + 87 89 setError(`Something went wrong: ${err}`); 88 90 } 89 91 },
+3 -3
src/views/identity/plc-applicator/steps/step2_pds-authentication.tsx
··· 1 1 import { createSignal, Match, Show, Switch } from 'solid-js'; 2 2 3 - import { AtpAccessJwt, Client, ClientResponseError, CredentialManager, ok } from '@atcute/client'; 3 + import { type AtpAccessJwt, Client, ClientResponseError, CredentialManager, ok } from '@atcute/client'; 4 4 import { getPdsEndpoint } from '@atcute/identity'; 5 5 6 6 import { formatTotpCode, TOTP_RE } from '~/api/utils/auth'; ··· 10 10 11 11 import Button from '~/components/inputs/button'; 12 12 import TextInput from '~/components/inputs/text-input'; 13 - import { Stage, StageActions, StageErrorView, WizardStepProps } from '~/components/wizard'; 13 + import { Stage, StageActions, StageErrorView, type WizardStepProps } from '~/components/wizard'; 14 14 15 - import { PlcApplicatorConstraints } from '../page'; 15 + import type { PlcApplicatorConstraints } from '../page'; 16 16 17 17 class InsufficientLoginError extends Error {} 18 18
+3 -9
src/views/identity/plc-applicator/steps/step2_private-key-input.tsx
··· 8 8 import Button from '~/components/inputs/button'; 9 9 import RadioInput from '~/components/inputs/radio-input'; 10 10 import TextInput from '~/components/inputs/text-input'; 11 - import { Stage, StageActions, StageErrorView, WizardStepProps } from '~/components/wizard'; 11 + import { Stage, StageActions, StageErrorView, type WizardStepProps } from '~/components/wizard'; 12 12 13 13 import type { Keypair, PlcApplicatorConstraints, PrivateKeySigningMethod } from '../page'; 14 14 ··· 97 97 }); 98 98 }, 99 99 onError(error) { 100 - let message: string | undefined; 101 - 102 - if (message !== undefined) { 103 - setError(message); 104 - } else { 105 - console.error(error); 106 - setError(`Something went wrong: ${error}`); 107 - } 100 + console.error(error); 101 + setError(`Something went wrong: ${error}`); 108 102 }, 109 103 }); 110 104
+2 -2
src/views/identity/plc-applicator/steps/step3_operation-select.tsx
··· 12 12 import Button from '~/components/inputs/button'; 13 13 import RadioInput from '~/components/inputs/radio-input'; 14 14 import SelectInput from '~/components/inputs/select-input'; 15 - import { Stage, StageActions, StageErrorView, WizardStepProps } from '~/components/wizard'; 15 + import { Stage, StageActions, StageErrorView, type WizardStepProps } from '~/components/wizard'; 16 16 17 - import { PlcApplicatorConstraints } from '../page'; 17 + import type { PlcApplicatorConstraints } from '../page'; 18 18 19 19 const Step3_OperationSelect = ({ 20 20 data,
+2 -2
src/views/identity/plc-applicator/steps/step4_payload-input.tsx
··· 4 4 5 5 import Button from '~/components/inputs/button'; 6 6 import MultilineInput from '~/components/inputs/multiline-input'; 7 - import { Stage, StageActions, StageErrorView, WizardStepProps } from '~/components/wizard'; 7 + import { Stage, StageActions, StageErrorView, type WizardStepProps } from '~/components/wizard'; 8 8 9 - import { PlcApplicatorConstraints } from '../page'; 9 + import type { PlcApplicatorConstraints } from '../page'; 10 10 import { getPlcPayload } from '../plc-utils'; 11 11 12 12 export const Step4_PayloadInput = ({
+2 -2
src/views/identity/plc-applicator/steps/step5_pds-confirmation.tsx
··· 9 9 import CheckIcon from '~/components/ic-icons/baseline-check'; 10 10 import Button from '~/components/inputs/button'; 11 11 import TextInput from '~/components/inputs/text-input'; 12 - import { Stage, StageActions, StageErrorView, WizardStepProps } from '~/components/wizard'; 12 + import { Stage, StageActions, StageErrorView, type WizardStepProps } from '~/components/wizard'; 13 13 14 - import { PlcApplicatorConstraints } from '../page'; 14 + import type { PlcApplicatorConstraints } from '../page'; 15 15 16 16 export const Step5_PdsConfirmation = ({ 17 17 data,
+5 -6
src/views/identity/plc-applicator/steps/step5_private-key-confirmation.tsx
··· 9 9 10 10 import Button from '~/components/inputs/button'; 11 11 import TextInput from '~/components/inputs/text-input'; 12 - import { Stage, StageActions, StageErrorView, WizardStepProps } from '~/components/wizard'; 12 + import { Stage, StageActions, StageErrorView, type WizardStepProps } from '~/components/wizard'; 13 13 14 - import { PlcApplicatorConstraints } from '../page'; 14 + import type { PlcApplicatorConstraints } from '../page'; 15 15 16 16 const Step5_PrivateKeyConfirmation = ({ 17 17 data, ··· 78 78 }} 79 79 > 80 80 <p class="text-pretty"> 81 - To continue with this submission, type in the following code{' '} 82 - <code class="whitespace-nowrap font-bold">{code}</code> to the confirmation box below. 81 + To continue with this submission, type in <code class="whitespace-nowrap font-bold">{code}</code> to 82 + the confirmation box below. 83 83 </p> 84 84 85 85 <TextInput 86 - label="Confirmation code" 86 + label="Confirmation" 87 87 type="text" 88 88 autocomplete="one-time-code" 89 89 autocorrect="off" 90 90 required 91 91 pattern={code} 92 - placeholder="AAAAA-BBBBB" 93 92 autofocus={isActive()} 94 93 monospace 95 94 />
+2 -2
src/views/identity/plc-applicator/steps/step6_finished.tsx
··· 1 - import { Stage, WizardStepProps } from '~/components/wizard'; 1 + import { Stage, type WizardStepProps } from '~/components/wizard'; 2 2 3 - import { PlcApplicatorConstraints } from '../page'; 3 + import type { PlcApplicatorConstraints } from '../page'; 4 4 5 5 export const Step6_Finished = ({}: WizardStepProps<PlcApplicatorConstraints, 'Step6_Finished'>) => { 6 6 return (
+3 -6
src/views/identity/plc-oplogs.tsx
··· 1 - import { createSignal, JSX, Match, onCleanup, Switch } from 'solid-js'; 1 + import { createSignal, Match, onCleanup, Switch, type JSX } from 'solid-js'; 2 2 3 3 import type { IndexedEntry, Service } from '@atcute/did-plc'; 4 4 import { isPlcDid } from '@atcute/identity'; ··· 20 20 import ContentCopyIcon from '~/components/ic-icons/baseline-content-copy'; 21 21 import Button from '~/components/inputs/button'; 22 22 import TextInput from '~/components/inputs/text-input'; 23 + import PageHeader from '~/components/page-header'; 23 24 24 25 const PlcOperationLogPage = () => { 25 26 const [params, setParams] = useSearchParams({ ··· 55 56 56 57 return ( 57 58 <> 58 - <div class="p-4"> 59 - <h1 class="text-lg font-bold text-purple-800">View PLC operation logs</h1> 60 - <p class="text-gray-600">Show history of a did:plc identity</p> 61 - </div> 62 - <hr class="mx-4 border-gray-300" /> 59 + <PageHeader title="View PLC operation logs" subtitle="Show history of a did:plc identity" /> 63 60 64 61 <form 65 62 onSubmit={(ev) => {
+4 -5
src/views/repository/repo-archive-explore/page.tsx
··· 1 1 import { Match, Switch } from 'solid-js'; 2 2 3 - import { RepoReader } from '@atcute/car/v4'; 3 + import { fromStream } from '@atcute/repo'; 4 4 5 5 import { createMutation } from '~/lib/utils/mutation'; 6 6 7 + import type { Archive, RecordEntry } from './types'; 8 + import ExploreView from './views/explore'; 7 9 import WelcomeView from './views/welcome'; 8 10 9 - import { Archive, RecordEntry } from './types'; 10 - import ExploreView from './views/explore'; 11 - 12 11 const ArchiveExplorePage = () => { 13 12 const mutation = createMutation({ 14 13 async mutationFn({ file }: { file: File }): Promise<Archive> { 15 14 const stream = file.stream(); 16 - await using repo = RepoReader.fromStream(stream); 15 + await using repo = fromStream(stream); 17 16 18 17 const collections = new Map<string, RecordEntry[]>(); 19 18 const archive: Archive = {
+1 -1
src/views/repository/repo-archive-explore/views/explore/record.tsx
··· 4 4 5 5 import { createQuery } from '~/lib/utils/query'; 6 6 7 - import { Archive, RecordEntry } from '../../types'; 7 + import type { Archive, RecordEntry } from '../../types'; 8 8 9 9 interface RecordSubviewProps { 10 10 archive: Archive;
+9 -42
src/views/repository/repo-archive-explore/views/welcome.tsx
··· 3 3 import type { MutationReturn } from '~/lib/utils/mutation'; 4 4 5 5 import CircularProgress from '~/components/circular-progress'; 6 + import FileDropZone from '~/components/file-drop-zone'; 7 + import PageHeader from '~/components/page-header'; 6 8 7 - import { Archive } from '../types'; 8 - import { createDropZone } from '~/lib/hooks/dropzone'; 9 + import type { Archive } from '../types'; 9 10 10 11 interface WelcomeViewProps { 11 12 mutation: MutationReturn<Archive, { file: File }>; 12 13 } 13 14 14 15 const WelcomeView = ({ mutation }: WelcomeViewProps) => { 15 - const { ref: dropRef, isDropping } = createDropZone({ 16 - // Checked, the mime type for CAR files is blank. 17 - dataTypes: [''], 18 - multiple: false, 19 - onDrop(files) { 20 - if (files) { 21 - mutation.mutate({ file: files[0] }); 22 - } 23 - }, 24 - }); 25 - 26 16 return ( 27 17 <> 28 - <div class="p-4"> 29 - <h1 class="text-lg font-bold text-purple-800">Explore archive</h1> 30 - <p class="text-gray-600">Explore a repository archive</p> 31 - </div> 32 - <hr class="mx-4 border-gray-300" /> 18 + <PageHeader title="Explore archive" subtitle="Explore a repository archive" /> 33 19 34 20 <div class="flex flex-col gap-4 p-4"> 35 - <fieldset 36 - ref={dropRef} 37 - class={ 38 - `grid place-items-center rounded border border-gray-300 px-6 py-12 disabled:opacity-50` + 39 - (!isDropping() ? ` bg-gray-100` : ` bg-green-100`) 40 - } 21 + <FileDropZone 22 + accept=".car,application/vnd.ipld.car" 23 + dataTypes={['']} 24 + onFiles={(files) => mutation.mutate({ file: files[0] })} 41 25 > 42 - <div class="flex flex-col items-center gap-4"> 43 - <button 44 - onClick={() => { 45 - const input = document.createElement('input'); 46 - input.type = 'file'; 47 - input.accept = '.car,application/vnd.ipld.car'; 48 - input.oninput = () => mutation.mutate({ file: input.files![0] }); 49 - 50 - input.click(); 51 - }} 52 - class="flex h-9 select-none items-center rounded border border-gray-400 px-4 text-sm font-semibold text-gray-800 hover:bg-gray-200 active:bg-gray-200 disabled:pointer-events-none" 53 - > 54 - Browse files 55 - </button> 56 - <p class="select-none font-medium text-gray-600">or drop your file here</p> 57 - </div> 58 - 59 26 <div 60 27 hidden={!mutation.isPending} 61 28 class="absolute inset-0 flex flex-col items-center justify-center gap-3 bg-gray-50" ··· 63 30 <CircularProgress /> 64 31 <span class="font-medium">Reading CAR file</span> 65 32 </div> 66 - </fieldset> 33 + </FileDropZone> 67 34 68 35 <Show when={mutation.error}> 69 36 <p class="whitespace-pre-wrap text-[0.8125rem] font-medium leading-5 text-red-800">
+10 -43
src/views/repository/repo-archive-unpack.tsx
··· 1 1 import { FileSystemWritableFileStream, showSaveFilePicker } from 'native-file-system-adapter'; 2 2 import { createSignal } from 'solid-js'; 3 3 4 - import { RepoReader } from '@atcute/car/v4'; 4 + import { fromStream } from '@atcute/repo'; 5 5 import { writeTarEntry } from '@mary/tar'; 6 6 7 - import { createDropZone } from '~/lib/hooks/dropzone'; 8 7 import { useTitle } from '~/lib/navigation/router'; 9 8 import { makeAbortable } from '~/lib/utils/abortable'; 10 9 10 + import FileDropZone from '~/components/file-drop-zone'; 11 11 import Logger, { createLogger } from '~/components/logger'; 12 + import PageHeader from '~/components/page-header'; 12 13 13 14 // @ts-expect-error: new API 14 15 const yieldToScheduler: () => Promise<void> = window?.scheduler?.yield ··· 22 23 const [getSignal, cleanup] = makeAbortable(); 23 24 const [pending, setPending] = createSignal(false); 24 25 25 - const { ref: dropRef, isDropping } = createDropZone({ 26 - // Checked, the mime type for CAR files is blank. 27 - dataTypes: [''], 28 - multiple: false, 29 - onDrop(files) { 30 - if (files) { 31 - onFileDrop(files); 32 - } 33 - }, 34 - }); 35 - 36 26 const mutate = async (file: File, signal: AbortSignal) => { 37 27 logger.log(`Starting extraction`); 38 28 39 29 const stream = file.stream(); 40 - await using repo = RepoReader.fromStream(stream); 30 + await using repo = fromStream(stream); 41 31 42 32 let count = 0; 43 33 ··· 155 145 156 146 return ( 157 147 <> 158 - <div class="p-4"> 159 - <h1 class="text-lg font-bold text-purple-800">Unpack archive</h1> 160 - <p class="text-gray-600">Extract a repository archive into a tarball</p> 161 - </div> 162 - <hr class="mx-4 border-gray-300" /> 148 + <PageHeader title="Unpack archive" subtitle="Extract a repository archive into a tarball" /> 163 149 164 150 <div class="p-4"> 165 - <fieldset 166 - ref={dropRef} 151 + <FileDropZone 152 + accept=".car,application/vnd.ipld.car" 153 + dataTypes={['']} 167 154 disabled={pending()} 168 - class={ 169 - `grid place-items-center rounded border border-gray-300 px-6 py-12 disabled:opacity-50` + 170 - (pending() || !isDropping() ? ` bg-gray-100` : ` bg-green-100`) 171 - } 172 - > 173 - <div class="flex flex-col items-center gap-4"> 174 - <button 175 - onClick={() => { 176 - const input = document.createElement('input'); 177 - input.type = 'file'; 178 - input.accept = '.car,application/vnd.ipld.car'; 179 - input.oninput = () => onFileDrop(Array.from(input.files!)); 180 - 181 - input.click(); 182 - }} 183 - class="flex h-9 select-none items-center rounded border border-gray-400 px-4 text-sm font-semibold text-gray-800 hover:bg-gray-200 active:bg-gray-200 disabled:pointer-events-none" 184 - > 185 - Browse files 186 - </button> 187 - <p class="select-none font-medium text-gray-600">or drop your file here</p> 188 - </div> 189 - </fieldset> 155 + onFiles={onFileDrop} 156 + /> 190 157 </div> 191 158 <hr class="mx-4 border-gray-300" /> 192 159
+3 -24
src/views/repository/repo-export.tsx
··· 11 11 import { useTitle } from '~/lib/navigation/router'; 12 12 import { makeAbortable } from '~/lib/utils/abortable'; 13 13 import { formatBytes } from '~/lib/utils/intl/bytes'; 14 + import { iterateStream } from '~/lib/utils/stream'; 14 15 15 16 import Button from '~/components/inputs/button'; 16 17 import TextInput from '~/components/inputs/text-input'; 17 18 import Logger, { createLogger } from '~/components/logger'; 19 + import PageHeader from '~/components/page-header'; 18 20 19 21 const RepoExportPage = () => { 20 22 const logger = createLogger(); ··· 135 137 136 138 return ( 137 139 <> 138 - <div class="p-4"> 139 - <h1 class="text-lg font-bold text-purple-800">Export repository</h1> 140 - <p class="text-gray-600">Download an archive of an account's repository</p> 141 - </div> 142 - <hr class="mx-4 border-gray-300" /> 140 + <PageHeader title="Export repository" subtitle="Download an archive of an account's repository" /> 143 141 144 142 <form 145 143 onSubmit={(ev) => { ··· 222 220 }; 223 221 224 222 export default RepoExportPage; 225 - 226 - export async function* iterateStream<T>(stream: ReadableStream<T>) { 227 - // Get a lock on the stream 228 - const reader = stream.getReader(); 229 - 230 - try { 231 - while (true) { 232 - const { done, value } = await reader.read(); 233 - 234 - if (done) { 235 - return; 236 - } 237 - 238 - yield value; 239 - } 240 - } finally { 241 - reader.releaseLock(); 242 - } 243 - }
+1
tsconfig.app.json
··· 9 9 "moduleResolution": "Bundler", 10 10 "allowImportingTsExtensions": true, 11 11 "isolatedModules": true, 12 + "verbatimModuleSyntax": true, 12 13 "moduleDetection": "force", 13 14 "noEmit": true, 14 15
+9
wrangler.jsonc
··· 1 + { 2 + "$schema": "https://unpkg.com/wrangler@latest/config-schema.json", 3 + "name": "boat", 4 + "compatibility_date": "2025-10-05", 5 + "assets": { 6 + "directory": "dist", 7 + "not_found_handling": "single-page-application", 8 + }, 9 + }