diff --git a/modules/oauth.ts b/modules/oauth.ts index 51f08a7837..7bf26d0ebd 100644 --- a/modules/oauth.ts +++ b/modules/oauth.ts @@ -12,8 +12,11 @@ export default defineNuxtModule({ async setup() { const nuxt = useNuxt() - const { previewUrl, productionUrl } = await getEnv(nuxt.options.dev) - const clientUri = productionUrl || previewUrl || 'http://127.0.0.1:3000' + const { previewUrl, productionUrl, env } = await getEnv(nuxt.options.dev) + const clientUri = + productionUrl || + (env === 'canary' ? 'https://main.npmx.dev' : previewUrl) || + 'http://127.0.0.1:3000' // bake it into a virtual file addServerTemplate({ diff --git a/package.json b/package.json index 63d18a4b9a..fdae01fcc3 100644 --- a/package.json +++ b/package.json @@ -45,11 +45,14 @@ }, "dependencies": { "@atcute/bluesky-richtext-segmenter": "3.0.1", + "@atcute/identity-resolver": "2.0.1", + "@atcute/identity-resolver-node": "2.0.1", + "@atcute/lexicons": "2.0.2", + "@atcute/oauth-node-client": "2.0.1", "@atcute/tid": "1.1.3", "@atproto/api": "0.20.25", "@atproto/lex": "0.1.7", "@atproto/lex-password-session": "0.1.4", - "@atproto/oauth-client-node": "0.3.15", "@deno/doc": "jsr:^0.189.1", "@floating-ui/vue": "2.0.0", "@iconify-json/lucide": "1.2.101", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 83c1d080e9..38cf1ca035 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -64,6 +64,18 @@ importers: '@atcute/bluesky-richtext-segmenter': specifier: 3.0.1 version: 3.0.1 + '@atcute/identity-resolver': + specifier: 2.0.1 + version: 2.0.1(@atcute/identity@2.0.1)(@atcute/lexicons@2.0.2)(typescript@6.0.2) + '@atcute/identity-resolver-node': + specifier: 2.0.1 + version: 2.0.1(@atcute/identity-resolver@2.0.1)(@atcute/identity@2.0.1)(@atcute/lexicons@2.0.2) + '@atcute/lexicons': + specifier: 2.0.2 + version: 2.0.2 + '@atcute/oauth-node-client': + specifier: 2.0.1 + version: 2.0.1(@atcute/identity-resolver@2.0.1)(@atcute/lexicons@2.0.2)(typescript@6.0.2) '@atcute/tid': specifier: 1.1.3 version: 1.1.3 @@ -76,9 +88,6 @@ importers: '@atproto/lex-password-session': specifier: 0.1.4 version: 0.1.4 - '@atproto/oauth-client-node': - specifier: 0.3.15 - version: 0.3.15 '@deno/doc': specifier: jsr:^0.189.1 version: '@jsr/deno__doc@0.189.1(patch_hash=24f326e123c822a07976329a5afe91a8713e82d53134b5586625b72431c87832)' @@ -425,7 +434,7 @@ importers: dependencies: '@nuxt/ui': specifier: 4.6.1 - version: 4.6.1(@nuxt/content@3.12.0)(@tiptap/extensions@3.24.0)(@tiptap/y-tiptap@3.0.2)(@upstash/redis@1.37.0)(@voidzero-dev/vite-plus-core@0.2.2)(db0@0.3.4)(embla-carousel@8.6.0)(focus-trap@8.0.0)(ioredis@5.10.1)(magicast@0.5.3)(react-dom@19.2.4)(react@19.2.4)(tailwindcss@4.2.2)(typescript@6.0.2)(valibot@1.4.2)(vue-router@5.0.4)(vue@3.5.39)(yjs@13.6.29)(zod@4.3.6) + version: 4.6.1(@nuxt/content@3.12.0)(@tiptap/extensions@3.24.0)(@tiptap/y-tiptap@3.0.2)(@upstash/redis@1.37.0)(db0@0.3.4)(embla-carousel@8.6.0)(focus-trap@8.0.0)(ioredis@5.10.1)(magicast@0.5.3)(react-dom@19.2.4)(react@19.2.4)(tailwindcss@4.2.2)(typescript@6.0.3)(valibot@1.4.2)(vite@8.1.3)(vue-router@5.0.4)(vue@3.5.39)(yjs@13.6.29)(zod@4.3.6) '@nuxtjs/mdc': specifier: 0.21.1 version: 0.21.1(magicast@0.5.3) @@ -434,10 +443,10 @@ importers: version: 12.8.0 docus: specifier: 5.9.0 - version: 5.9.0(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@nuxt/schema@4.4.8)(@takumi-rs/wasm@1.0.9)(@tiptap/extensions@3.24.0)(@tiptap/y-tiptap@3.0.2)(@unhead/vue@2.1.15)(@upstash/redis@1.37.0)(@voidzero-dev/vite-plus-core@0.2.2)(@vue/compiler-dom@3.5.39)(better-sqlite3@12.8.0)(db0@0.3.4)(embla-carousel@8.6.0)(eslint@9.39.2)(focus-trap@8.0.0)(fontless@0.2.1)(h3@1.15.11)(ioredis@5.10.1)(magicast@0.5.3)(nitropack@2.13.4)(nuxt@4.4.8)(playwright-core@1.61.1)(react-dom@19.2.4)(react@19.2.4)(rolldown@1.1.4)(rollup@4.60.3)(sharp@0.34.5)(typescript@6.0.2)(unifont@0.7.4)(unstorage@1.17.5)(valibot@1.4.2)(vue-router@5.0.4)(vue@3.5.39)(yjs@13.6.29) + version: 5.9.0(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@nuxt/schema@4.4.8)(@takumi-rs/wasm@1.0.9)(@tiptap/extensions@3.24.0)(@tiptap/y-tiptap@3.0.2)(@unhead/vue@2.1.15)(@upstash/redis@1.37.0)(@vue/compiler-dom@3.5.39)(better-sqlite3@12.8.0)(db0@0.3.4)(embla-carousel@8.6.0)(eslint@9.39.2)(focus-trap@8.0.0)(fontless@0.2.1)(h3@2.0.1-rc.22)(ioredis@5.10.1)(magicast@0.5.3)(nitropack@2.13.4)(nuxt@4.4.8)(playwright-core@1.61.1)(react-dom@19.2.4)(react@19.2.4)(rolldown@1.1.4)(rollup@4.60.3)(sharp@0.34.5)(typescript@6.0.3)(unifont@0.7.4)(unstorage@1.17.5)(valibot@1.4.2)(vite@8.1.3)(vue-router@5.0.4)(vue@3.5.39)(yjs@13.6.29) nuxt: specifier: 4.4.8 - version: 4.4.8(@babel/plugin-syntax-jsx@7.28.6)(@babel/plugin-syntax-typescript@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@voidzero-dev/vite-plus-core@0.2.2)(@vue/compiler-sfc@3.5.39)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.28.0)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.3)(optionator@0.9.4)(oxlint@1.72.0)(rolldown@1.1.4)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.48.0)(typescript@6.0.2)(vue-tsc@3.2.6)(yaml@2.9.0) + version: 4.4.8(@babel/plugin-syntax-jsx@7.28.6)(@babel/plugin-syntax-typescript@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@vue/compiler-sfc@3.5.39)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.28.0)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.3)(optionator@0.9.4)(oxlint@1.72.0)(rolldown@1.1.4)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.48.0)(typescript@6.0.3)(vite@8.1.3)(vue-tsc@3.2.6)(yaml@2.9.0) tailwindcss: specifier: 4.2.2 version: 4.2.2 @@ -563,57 +572,81 @@ packages: '@atcute/bluesky-richtext-segmenter@3.0.1': resolution: {integrity: sha512-5TrzZTpPkVchiNG+YAW8MmBVnN/gLPN/V3nJgpQcnLrQOebqTV+lR+yZ0d4T70NsBD32vJHyxoX5PY+6hY2KlA==} + '@atcute/client@5.1.1': + resolution: {integrity: sha512-cn5/Zi/qo37WtQG6gzIC7JPs0RDzX9Z4eaceX45SpKgLZoc3fCFDJcE7C8xsbxBNfjry2T6PmUxWA8obebZsEQ==} + peerDependencies: + '@atcute/lexicons': ^2.0.0 + + '@atcute/identity-resolver-node@2.0.1': + resolution: {integrity: sha512-UtcmhY4Oxk9tk1elTHmilcIXA1EFtGQae7mp3l8Xqs6EZsZyH3cUDf/2jS1CoRT1GE/i3WfnLaxYmdMIVau1kg==} + peerDependencies: + '@atcute/identity': ^2.0.0 + '@atcute/identity-resolver': ^2.0.0 + '@atcute/lexicons': ^2.0.0 + + '@atcute/identity-resolver@2.0.1': + resolution: {integrity: sha512-0enA9w7XnbbqsZ5Rcl6jXLf7ZZuwFQ9dBmxFq3qOxPHLaCETsqsrQflXDPqiM27TnZwYq8sqCV5D1mFOksggDQ==} + peerDependencies: + '@atcute/identity': ^2.0.0 + '@atcute/lexicons': ^2.0.0 + + '@atcute/identity@2.0.1': + resolution: {integrity: sha512-FEURUvl30SyyWWikkvm+MLz0Snuf0OF10L/qxRhWjj6qDB5Ib+XWhiBuwidjvhCkrCepTUNLbj4TlUm/gHaUig==} + peerDependencies: + '@atcute/lexicons': ^2.0.0 + + '@atcute/lexicons@2.0.2': + resolution: {integrity: sha512-ATBADJAy4KQ76NB86BjgYKrRdbDRUo76Cbqna4WIfQAgN105Rcy972MiNKs+BSmcOOM3WakilgTm0CXD4RC0iA==} + + '@atcute/multibase@1.2.4': + resolution: {integrity: sha512-WeX12hvFZEim6C+cyv7Eqd93w6DzubNWQGmTFBghjsEuXvMe4HbBCYvsti0OUnbA5qLBPlsTyssQUJeLlHCzIw==} + + '@atcute/oauth-crypto@1.0.1': + resolution: {integrity: sha512-ghC8ceFx0r6pi5X3dNoET1K6PNg8afeAOZLD4PKLhrpVYdRtRrgY4uqAe3ojtSIjoS6GXmVm063CoJ2xtg/MoQ==} + + '@atcute/oauth-keyset@0.1.2': + resolution: {integrity: sha512-2CUazWBWRjSEoYZDaLS4zEPgCOcr9LgnMhPr1pzr9I+DytRnoXmrdbRs4xBVg4iUdXtdzU48DsMaGi6bHXaFcg==} + + '@atcute/oauth-node-client@2.0.1': + resolution: {integrity: sha512-MgqN9Rnt5nuUH5zriETtbQrwcx/tWaELKaFVQtqggMtRI4k4IP5+ZbnG40tiJjbZfSclapA2kwOnT14kO0nAxg==} + peerDependencies: + '@atcute/identity-resolver': ^2.0.0 + '@atcute/lexicons': ^2.0.0 + + '@atcute/oauth-types@1.0.1': + resolution: {integrity: sha512-9uFP/nK0PgPDsaNbLArzrCHvTZO1k04cSEX5jZ75W2Jh7Jxbh/CSTenSrad3CZXuX6y6hDquEtl6H/IqLtTmHw==} + '@atcute/tid@1.1.3': resolution: {integrity: sha512-Ox9KRz8i1QC2ILNKP4JY7q2s1Vnf0xIRiS2CL5RVhQ+k248462mOUdZJkPfPnlprALv6sATDIJMbWioGkXoQRA==} '@atcute/time-ms@1.3.3': resolution: {integrity: sha512-FeK2Xsv4ymP+PoTWtmMFuJmpxDBQsj+jNMnd/YpIm3etcIPj1YFb7DeTAG1c/Xvp8AM38MLdqUCc35/mANnBtw==} - '@atproto-labs/did-resolver@0.2.5': - resolution: {integrity: sha512-he7EC6OMSifNs01a4RT9mta/yYitoKDzlK9ty2TFV5Uj/+HpB4vYMRdIDFrRW0Hcsehy90E2t/dw0t7361MEKQ==} + '@atcute/uint8array@1.1.3': + resolution: {integrity: sha512-2KLcMQHUFtntY3tEjdyqqq1tR9hvPFndluWFCa637QY0cMyvq0fHSnhmZeWaSRIXMCwVDY3TLLWHNOHEWFb11g==} + + '@atcute/util-fetch@2.0.1': + resolution: {integrity: sha512-ugWTOLemA8OxSOj7c8q6ncRmBGFDHSwwE1YinO+PCtaw6WLQFGBfHn+yikQ0e3wTK2t4IPjQ5PxZcRXm961ZVA==} + + '@atcute/util-text@1.3.3': + resolution: {integrity: sha512-WhedTmg/msFhrdwXw9RjnNcDl8Vmisxl4+Vzyf5k3+8Gj5TKQg72dLSDtBNmNLd61RbHjgfQRBgE0ez6q/jciw==} '@atproto-labs/did-resolver@0.3.4': resolution: {integrity: sha512-nBECoVG59NfbYthayxfR0s1dLFVdN+RKMaL0p0uaNX/U1SAETksN6Yydmr4oWOKSkyyU3GO9XZeo1yzwHnRcZw==} engines: {node: '>=22'} - '@atproto-labs/fetch-node@0.2.0': - resolution: {integrity: sha512-Krq09nH/aeoiU2s9xdHA0FjTEFWG9B5FFenipv1iRixCcPc7V3DhTNDawxG9gI8Ny0k4dBVS9WTRN/IDzBx86Q==} - engines: {node: '>=18.7.0'} - - '@atproto-labs/fetch@0.2.3': - resolution: {integrity: sha512-NZtbJOCbxKUFRFKMpamT38PUQMY0hX0p7TG5AEYOPhZKZEP7dHZ1K2s1aB8MdVH0qxmqX7nQleNrrvLf09Zfdw==} - '@atproto-labs/fetch@0.3.3': resolution: {integrity: sha512-2gABLf0VEI86Sxo6YhGKQYK1tGhTZ4y+3TrCWputnupEZxuS/hw6+pFw9ceXZ3v9nnMNthzsAEcaAQ3V/tXsqg==} engines: {node: '>=22'} - '@atproto-labs/handle-resolver-node@0.1.24': - resolution: {integrity: sha512-w/zvktigmRQpOLQQclp48tbb2K/2XW8j1szoIpT8T8v6P5dZ8GGVDIEF142xQMX9vWToFqMTu1P2yOuz8e3Ilg==} - engines: {node: '>=18.7.0'} - - '@atproto-labs/handle-resolver@0.3.5': - resolution: {integrity: sha512-r3b+plCh/0arN535Aool9gL6yTSbAPDOyReURbA2TWAaeW4vrSJPwR6yYUx0k0vmVPjkZPIdUVd63bG/+VG5MA==} - - '@atproto-labs/identity-resolver@0.3.5': - resolution: {integrity: sha512-kSxnreUSPhKL77doUbSl/9I6Y9qpkpD7MMJoYFQVU/WG0PB90tzfIb6DNuWsjbU2I5Q91Nzc4Tm4VJMV+OPKGQ==} - - '@atproto-labs/pipe@0.1.1': - resolution: {integrity: sha512-hdNw2oUs2B6BN1lp+32pF7cp8EMKuIN5Qok2Vvv/aOpG/3tNSJ9YkvfI0k6Zd188LeDDYRUpYpxcoFIcGH/FNg==} - '@atproto-labs/pipe@0.2.3': resolution: {integrity: sha512-hsjkaKGdhEGKhXuOOfIeYyZSQZfw007AXQJak/QTd9pLY1wHUJG85a9+u13xoMeav95gHkBRzswti7+kqsxgdw==} engines: {node: '>=22'} - '@atproto-labs/simple-store-memory@0.1.4': - resolution: {integrity: sha512-3mKY4dP8I7yKPFj9VKpYyCRzGJOi5CEpOLPlRhoJyLmgs3J4RzDrjn323Oakjz2Aj2JzRU/AIvWRAZVhpYNJHw==} - '@atproto-labs/simple-store-memory@0.2.3': resolution: {integrity: sha512-RtL48op8Db/QFNbW+9Y+Os6DOMqysOkoG5QelTZ0qcZt/j0pUBY8v2zSr5/faVJ5Y30h1cONxMydV48tVWf8pg==} engines: {node: '>=22'} - '@atproto-labs/simple-store@0.3.0': - resolution: {integrity: sha512-nOb6ONKBRJHRlukW1sVawUkBqReLlLx6hT35VS3imaNPwiXDxLnTK7lxw3Lrl9k5yugSBDQAkZAq3MPTEFSUBQ==} - '@atproto-labs/simple-store@0.4.3': resolution: {integrity: sha512-ML1HAEtQIixkcU4FCGbZtAkoHTfmXDi63tNVuSSPG/cVUKyrUURg6Cr1bcfvbbkMTwRj9abEwa3JZR7UUYi4Ew==} engines: {node: '>=22'} @@ -622,9 +655,6 @@ packages: resolution: {integrity: sha512-PTwt6X0U45C9vikr8NRi0Qzcep9VqJet52HtfcxgG9R7ofRHxqLVPzfVuN/f2xOaYM6H5IG/Nk1E9kXZcI0mSQ==} engines: {node: '>=22'} - '@atproto/common-web@0.4.21': - resolution: {integrity: sha512-Odq+wdk3YNasGCjjlpl3bCIPvqYHige5DLfMkIffNv/2PI/iIj5ZvAvMvJlJ59OhReKSxtpI0invx5UQPc3+fw==} - '@atproto/common-web@0.5.3': resolution: {integrity: sha512-FkMhOcNv1y7r5984+zXB+uMN4zJ4QFLEbZrYyQo6bNCf/Kfav/pEHXXENlaZEOweq2NYXf+tr2giMssBuM9u5A==} engines: {node: '>=22'} @@ -637,22 +667,10 @@ packages: resolution: {integrity: sha512-Ea5VwU+ofVXrm4BWpTa7gI9kz7A6NwPpCY6r0f5k8UJpNq0GDHSb1F5MdsFDVNnSK5bEI7DIMNZwspkNsAKOgA==} engines: {node: '>=22'} - '@atproto/did@0.2.4': - resolution: {integrity: sha512-nxNiCgXeo7pfjojq9fpfZxCO0X0xUipNVKW+AHNZwQKiUDt6zYL0VXEfm8HBUwQOCmKvj2pRRSM1Cur+tUWk3g==} - '@atproto/did@0.5.3': resolution: {integrity: sha512-nKcdu5qB9iNJFaBeQOQUJ+6mA1npFcZ3DmD0xB+etkMRd/3UvOQql/CvcMZaYzl+eGoVs1JDdEsvoZz+idfhaw==} engines: {node: '>=22'} - '@atproto/jwk-jose@0.1.11': - resolution: {integrity: sha512-i4Fnr2sTBYmMmHXl7NJh8GrCH+tDQEVWrcDMDnV5DjJfkgT17wIqvojIw9SNbSL4Uf0OtfEv6AgG0A+mgh8b5Q==} - - '@atproto/jwk-webcrypto@0.2.0': - resolution: {integrity: sha512-UmgRrrEAkWvxwhlwe30UmDOdTEFidlIzBC7C3cCbeJMcBN1x8B3KH+crXrsTqfWQBG58mXgt8wgSK3Kxs2LhFg==} - - '@atproto/jwk@0.6.0': - resolution: {integrity: sha512-bDoJPvt7TrQVi/rBfBrSSpGykhtIriKxeYCYQTiPRKFfyRhbgpElF0wPXADjIswnbzZdOwbY63az4E/CFVT3Tw==} - '@atproto/lex-builder@0.1.5': resolution: {integrity: sha512-wh4nOGD0NuXBbRfrb4XBQZruuboRZs+rfhv2yWCR2zeEAWEqVU2+hVVNdQPDfa+rkghXENF31JIKftbz9NF6Ww==} engines: {node: '>=22'} @@ -665,9 +683,6 @@ packages: resolution: {integrity: sha512-b/LXpLt3HZZEfItruCcPpHUbzoo+LjoOp0GetlTuHX0UnJYqzk4zLg5qSMTDo4JoHU4hFO1+26R6cg986ZvUAg==} engines: {node: '>=22'} - '@atproto/lex-data@0.0.15': - resolution: {integrity: sha512-ZsbGiaM5S3CnGrcTMbDGON3bLZzCi/Mx9UvcMREKSRujnF68eHgMiXxJqvykP7+QpOX6tYCK93axZkuJVhtSEw==} - '@atproto/lex-data@0.1.4': resolution: {integrity: sha512-f9U95sk0zUtxHktvK59peU+Shd0cIUYV68p//GS7sfdkAxUIeaspvX6CY+Quv9Oa4aozmsXI52SjaNn1wuU8RQ==} engines: {node: '>=22'} @@ -680,9 +695,6 @@ packages: resolution: {integrity: sha512-H6AhjPPYbH+6sJ9xNY6zrA1t2IVdze8idk6SgJqQnGESL+v3bblVsfYsx394DveEnQ7pO2sikKwkxZ9emBnBbQ==} engines: {node: '>=22'} - '@atproto/lex-json@0.0.16': - resolution: {integrity: sha512-IgLgQ0krshVlrIYZ+heTBDbCnM3LmAgWvsaYn5MxvKA3LcBot3PG3ptdO8VOweVZ+WgCLuo39cz9EbUmIbqdtg==} - '@atproto/lex-json@0.1.3': resolution: {integrity: sha512-Ch2w9bCLFOwWINFFxpZo6DBW7+ZxkehciU3P8N94gSyENLe3/5WWXHdHvkiH7EXZrpI7fKY8nVWn4GIL0ttqxw==} engines: {node: '>=22'} @@ -704,37 +716,18 @@ packages: engines: {node: '>=22'} hasBin: true - '@atproto/lexicon@0.6.2': - resolution: {integrity: sha512-p3Ly6hinVZW0ETuAXZMeUGwuMm3g8HvQMQ41yyEE6AL0hAkfeKFaZKos6BdBrr6CjkpbrDZqE8M+5+QOceysMw==} - '@atproto/lexicon@0.7.4': resolution: {integrity: sha512-ulk4RGwMBp4vbkTOZcIwZJeTEPlj3PImOnx9TqxSxMDnBdySxarpd0Aprg7+iAvGyKTsMcrYHpeoLukZaquk0A==} engines: {node: '>=22'} - '@atproto/oauth-client-node@0.3.15': - resolution: {integrity: sha512-iuT7QrLli7IyB4px1+lHvm/YoIRfNRpbNG9seJRtu5eX4N5aLsBP6vpXs9rCygd1+/15LcLRAAGKVEcrLT9tXA==} - engines: {node: '>=18.7.0'} - - '@atproto/oauth-client@0.5.13': - resolution: {integrity: sha512-FLbqHkC7BAVZ90LHVzSxQf+s8ZNIQI4TsDuhYDyzi7lYtktFHDbgd88KuM2ClJFOtGCsSS17yR1Joy925tDSaA==} - - '@atproto/oauth-types@0.6.1': - resolution: {integrity: sha512-3z92GN/6zCq9E2GTTfZM27tWEbvi1qwFSA7KoS5+wqBC4kSsLvnLxmbKH402Z40DfWS4YWqw0DkHsgP0LNFDEA==} - '@atproto/repo@0.10.3': resolution: {integrity: sha512-Zk4xWtE/Mrf1+dAUwJLnWbeYwnvLMXF102mewzhPwsVkU63LsYO6nP9e5d4nqW/ClFDg9WKXo8zAv4792OnZNw==} engines: {node: '>=22'} - '@atproto/syntax@0.5.4': - resolution: {integrity: sha512-9XJOpMAgsGFxMEIp8nJ8AIWv+krrY1xQMj+wULbbXhQztQV+9aZ0TbG9Jtn3Op2or8Kr6OqyWR4ga9Z189kKDw==} - '@atproto/syntax@0.6.4': resolution: {integrity: sha512-ELgpShRGMF65cvLXcoMCZFL0HBzy67yz/Nlhox3yOtTh120B09KjjvZYXhMysVog3nUJqv2EW5rf1VRYCeM/hw==} engines: {node: '>=22'} - '@atproto/xrpc@0.7.7': - resolution: {integrity: sha512-K1ZyO/BU8JNtXX5dmPp7b5UrkLMMqpsIa/Lrj5D3Su+j1Xwq1m6QJ2XJ1AgjEjkI1v4Muzm7klianLE6XGxtmA==} - '@atproto/xrpc@0.8.3': resolution: {integrity: sha512-0gUGN71+bSqV3PI5U4cQ4fdnw4nI0eD6czHDQ6jB7hMYBwNcJpwAyfA9W+C1G1wayIvP0SIap/M0H/pSKDWFIQ==} engines: {node: '>=22'} @@ -7137,6 +7130,9 @@ packages: jiti: optional: true + esm-env@1.2.2: + resolution: {integrity: sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==} + esm-resolve@1.0.11: resolution: {integrity: sha512-LxF0wfUQm3ldUDHkkV2MIbvvY0TgzIpJ420jHSV1Dm+IlplBEWiJTKWM61GtxUfvjV6iD4OtTYFGAGM2uuIUWg==} @@ -8107,9 +8103,6 @@ packages: resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} hasBin: true - jose@5.10.0: - resolution: {integrity: sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==} - jose@6.1.3: resolution: {integrity: sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==} @@ -8724,9 +8717,6 @@ packages: multiformats@13.4.2: resolution: {integrity: sha512-eh6eHCrRi1+POZ3dA+Dq1C6jhP1GNtr9CRINMb67OKzqW9I5DUuZM/3jLPlzhgpGeiNUlEGEbkCYChXMCc/8DQ==} - multiformats@9.9.0: - resolution: {integrity: sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==} - mute-stream@2.0.0: resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==} engines: {node: ^18.17.0 || >=20.5.0} @@ -8736,6 +8726,11 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + nanoid@5.1.16: + resolution: {integrity: sha512-kVrnsrJqMR8+oLJnGEmSWw9BivK5mt7H3FZatVRjrc5wGqFYuBxX1yG7+A7Gi5AefkX6t/oCkizcQgpu0cY1dQ==} + engines: {node: ^18 || >=20} + hasBin: true + nanotar@0.3.0: resolution: {integrity: sha512-Kv2JYYiCzt16Kt5QwAc9BFG89xfPNBx+oQL4GQXD9nLqPkZBiNaqaCWtwnbk/q7UVsTYevvM1b0UF8zmEI4pCg==} @@ -10549,9 +10544,6 @@ packages: ufo@1.6.4: resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} - uint8arrays@3.0.0: - resolution: {integrity: sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==} - uint8arrays@5.1.1: resolution: {integrity: sha512-9muQwa4wZG4dKi9gMAIBtnk2Pw87SRpvWTH6lOGm19V2Uqxr4uomUf2PGqPnWc+qs06sN8owUU4jfcoWOcfwVQ==} @@ -10584,10 +10576,6 @@ packages: undici-types@7.16.0: resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} - undici@6.23.0: - resolution: {integrity: sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==} - engines: {node: '>=18.17'} - unenv@2.0.0-rc.24: resolution: {integrity: sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==} @@ -10987,6 +10975,49 @@ packages: '@vitest/browser-webdriverio': optional: true + vite@8.1.3: + resolution: {integrity: sha512-Ds+gBRbj0lwRO2Y5hwnUBdxSwlAve9LeRyU4sNnAr0ewW0gWF0n5bgXgUzbgZ49MV9BVUAQUFYVcDUcilUExMA==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': 24.12.0 + '@vitejs/devtools': ^0.3.0 + esbuild: ^0.27.0 || ^0.28.0 + jiti: '>=1.21.0' + less: ^4.0.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + '@vitejs/devtools': + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + vitest-environment-nuxt@2.0.0: resolution: {integrity: sha512-zEGFRiCAaRR3fHnqISHKMNTRvCzkQEI1XyFeqNgR2IBD0oYkfZ1rUHwi7C+h3Cns3KPykfB0av1B3MtLEbChDw==} @@ -11456,7 +11487,7 @@ snapshots: '@ai-sdk/provider-utils': 4.0.21(zod@4.3.6) ai: 6.0.141(zod@4.3.6) swrv: 1.1.0(vue@3.5.39) - vue: 3.5.39(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.3) transitivePeerDependencies: - zod @@ -11565,79 +11596,123 @@ snapshots: '@atcute/bluesky-richtext-segmenter@3.0.1': {} - '@atcute/tid@1.1.3': + '@atcute/client@5.1.1(@atcute/lexicons@2.0.2)(typescript@6.0.2)': dependencies: - '@atcute/time-ms': 1.3.3 + '@atcute/identity': 2.0.1(@atcute/lexicons@2.0.2)(typescript@6.0.2) + '@atcute/lexicons': 2.0.2 + transitivePeerDependencies: + - typescript - '@atcute/time-ms@1.3.3': {} + '@atcute/identity-resolver-node@2.0.1(@atcute/identity-resolver@2.0.1)(@atcute/identity@2.0.1)(@atcute/lexicons@2.0.2)': + dependencies: + '@atcute/identity': 2.0.1(@atcute/lexicons@2.0.2)(typescript@6.0.2) + '@atcute/identity-resolver': 2.0.1(@atcute/identity@2.0.1)(@atcute/lexicons@2.0.2)(typescript@6.0.2) + '@atcute/lexicons': 2.0.2 - '@atproto-labs/did-resolver@0.2.5': + '@atcute/identity-resolver@2.0.1(@atcute/identity@2.0.1)(@atcute/lexicons@2.0.2)(typescript@6.0.2)': dependencies: - '@atproto-labs/fetch': 0.2.3 - '@atproto-labs/pipe': 0.1.1 - '@atproto-labs/simple-store': 0.3.0 - '@atproto-labs/simple-store-memory': 0.1.4 - '@atproto/did': 0.2.4 - zod: 3.25.76 + '@atcute/identity': 2.0.1(@atcute/lexicons@2.0.2)(typescript@6.0.2) + '@atcute/lexicons': 2.0.2 + '@atcute/util-fetch': 2.0.1(typescript@6.0.2) + valibot: 1.4.2(typescript@6.0.2) + transitivePeerDependencies: + - typescript - '@atproto-labs/did-resolver@0.3.4': + '@atcute/identity@2.0.1(@atcute/lexicons@2.0.2)(typescript@6.0.2)': dependencies: - '@atproto-labs/fetch': 0.3.3 - '@atproto-labs/pipe': 0.2.3 - '@atproto-labs/simple-store': 0.4.3 - '@atproto-labs/simple-store-memory': 0.2.3 - '@atproto/did': 0.5.3 - zod: 3.25.76 + '@atcute/lexicons': 2.0.2 + valibot: 1.4.2(typescript@6.0.2) + transitivePeerDependencies: + - typescript - '@atproto-labs/fetch-node@0.2.0': + '@atcute/lexicons@2.0.2': dependencies: - '@atproto-labs/fetch': 0.2.3 - '@atproto-labs/pipe': 0.1.1 - ipaddr.js: 2.3.0 - undici: 6.23.0 + '@atcute/uint8array': 1.1.3 + '@atcute/util-text': 1.3.3 + '@standard-schema/spec': 1.1.0 + esm-env: 1.2.2 - '@atproto-labs/fetch@0.2.3': + '@atcute/multibase@1.2.4': dependencies: - '@atproto-labs/pipe': 0.1.1 + '@atcute/uint8array': 1.1.3 - '@atproto-labs/fetch@0.3.3': + '@atcute/oauth-crypto@1.0.1(typescript@6.0.2)': dependencies: - '@atproto-labs/pipe': 0.2.3 + '@atcute/multibase': 1.2.4 + '@atcute/uint8array': 1.1.3 + nanoid: 5.1.16 + valibot: 1.4.2(typescript@6.0.2) + transitivePeerDependencies: + - typescript - '@atproto-labs/handle-resolver-node@0.1.24': + '@atcute/oauth-keyset@0.1.2(typescript@6.0.2)': dependencies: - '@atproto-labs/fetch-node': 0.2.0 - '@atproto-labs/handle-resolver': 0.3.5 - '@atproto/did': 0.2.4 + '@atcute/oauth-crypto': 1.0.1(typescript@6.0.2) + transitivePeerDependencies: + - typescript + + '@atcute/oauth-node-client@2.0.1(@atcute/identity-resolver@2.0.1)(@atcute/lexicons@2.0.2)(typescript@6.0.2)': + dependencies: + '@atcute/client': 5.1.1(@atcute/lexicons@2.0.2)(typescript@6.0.2) + '@atcute/identity': 2.0.1(@atcute/lexicons@2.0.2)(typescript@6.0.2) + '@atcute/identity-resolver': 2.0.1(@atcute/identity@2.0.1)(@atcute/lexicons@2.0.2)(typescript@6.0.2) + '@atcute/lexicons': 2.0.2 + '@atcute/oauth-crypto': 1.0.1(typescript@6.0.2) + '@atcute/oauth-keyset': 0.1.2(typescript@6.0.2) + '@atcute/oauth-types': 1.0.1(typescript@6.0.2) + '@atcute/util-fetch': 2.0.1(typescript@6.0.2) + nanoid: 5.1.16 + valibot: 1.4.2(typescript@6.0.2) + transitivePeerDependencies: + - typescript - '@atproto-labs/handle-resolver@0.3.5': + '@atcute/oauth-types@1.0.1(typescript@6.0.2)': dependencies: - '@atproto-labs/simple-store': 0.3.0 - '@atproto-labs/simple-store-memory': 0.1.4 - '@atproto/did': 0.2.4 - zod: 3.25.76 + '@atcute/identity': 2.0.1(@atcute/lexicons@2.0.2)(typescript@6.0.2) + '@atcute/lexicons': 2.0.2 + '@atcute/oauth-keyset': 0.1.2(typescript@6.0.2) + valibot: 1.4.2(typescript@6.0.2) + transitivePeerDependencies: + - typescript - '@atproto-labs/identity-resolver@0.3.5': + '@atcute/tid@1.1.3': dependencies: - '@atproto-labs/did-resolver': 0.2.5 - '@atproto-labs/handle-resolver': 0.3.5 + '@atcute/time-ms': 1.3.3 - '@atproto-labs/pipe@0.1.1': {} + '@atcute/time-ms@1.3.3': {} - '@atproto-labs/pipe@0.2.3': {} + '@atcute/uint8array@1.1.3': {} - '@atproto-labs/simple-store-memory@0.1.4': + '@atcute/util-fetch@2.0.1(typescript@6.0.2)': dependencies: - '@atproto-labs/simple-store': 0.3.0 - lru-cache: 10.4.3 + valibot: 1.4.2(typescript@6.0.2) + transitivePeerDependencies: + - typescript + + '@atcute/util-text@1.3.3': + dependencies: + unicode-segmenter: 0.14.5 + + '@atproto-labs/did-resolver@0.3.4': + dependencies: + '@atproto-labs/fetch': 0.3.3 + '@atproto-labs/pipe': 0.2.3 + '@atproto-labs/simple-store': 0.4.3 + '@atproto-labs/simple-store-memory': 0.2.3 + '@atproto/did': 0.5.3 + zod: 3.25.76 + + '@atproto-labs/fetch@0.3.3': + dependencies: + '@atproto-labs/pipe': 0.2.3 + + '@atproto-labs/pipe@0.2.3': {} '@atproto-labs/simple-store-memory@0.2.3': dependencies: '@atproto-labs/simple-store': 0.4.3 lru-cache: 10.4.3 - '@atproto-labs/simple-store@0.3.0': {} - '@atproto-labs/simple-store@0.4.3': {} '@atproto/api@0.20.25': @@ -11651,13 +11726,6 @@ snapshots: tlds: 1.261.0 zod: 3.25.76 - '@atproto/common-web@0.4.21': - dependencies: - '@atproto/lex-data': 0.0.15 - '@atproto/lex-json': 0.0.16 - '@atproto/syntax': 0.5.4 - zod: 3.25.76 - '@atproto/common-web@0.5.3': dependencies: '@atproto/lex-data': 0.1.4 @@ -11679,30 +11747,10 @@ snapshots: '@noble/hashes': 1.8.0 uint8arrays: 5.1.1 - '@atproto/did@0.2.4': - dependencies: - zod: 3.25.76 - '@atproto/did@0.5.3': dependencies: zod: 3.25.76 - '@atproto/jwk-jose@0.1.11': - dependencies: - '@atproto/jwk': 0.6.0 - jose: 5.10.0 - - '@atproto/jwk-webcrypto@0.2.0': - dependencies: - '@atproto/jwk': 0.6.0 - '@atproto/jwk-jose': 0.1.11 - zod: 3.25.76 - - '@atproto/jwk@0.6.0': - dependencies: - multiformats: 9.9.0 - zod: 3.25.76 - '@atproto/lex-builder@0.1.5': dependencies: '@atproto/lex-document': 0.1.3 @@ -11724,13 +11772,6 @@ snapshots: '@atproto/lex-schema': 0.1.6 tslib: 2.8.1 - '@atproto/lex-data@0.0.15': - dependencies: - multiformats: 9.9.0 - tslib: 2.8.1 - uint8arrays: 3.0.0 - unicode-segmenter: 0.14.5 - '@atproto/lex-data@0.1.4': dependencies: multiformats: 13.4.2 @@ -11755,11 +11796,6 @@ snapshots: '@atproto/syntax': 0.6.4 tslib: 2.8.1 - '@atproto/lex-json@0.0.16': - dependencies: - '@atproto/lex-data': 0.0.15 - tslib: 2.8.1 - '@atproto/lex-json@0.1.3': dependencies: '@atproto/lex-data': 0.1.4 @@ -11801,14 +11837,6 @@ snapshots: tslib: 2.8.1 yargs: 18.0.0 - '@atproto/lexicon@0.6.2': - dependencies: - '@atproto/common-web': 0.4.21 - '@atproto/syntax': 0.5.4 - iso-datestring-validator: 2.2.2 - multiformats: 9.9.0 - zod: 3.25.76 - '@atproto/lexicon@0.7.4': dependencies: '@atproto/common-web': 0.5.3 @@ -11816,40 +11844,6 @@ snapshots: multiformats: 13.4.2 zod: 3.25.76 - '@atproto/oauth-client-node@0.3.15': - dependencies: - '@atproto-labs/did-resolver': 0.2.5 - '@atproto-labs/handle-resolver-node': 0.1.24 - '@atproto-labs/simple-store': 0.3.0 - '@atproto/did': 0.2.4 - '@atproto/jwk': 0.6.0 - '@atproto/jwk-jose': 0.1.11 - '@atproto/jwk-webcrypto': 0.2.0 - '@atproto/oauth-client': 0.5.13 - '@atproto/oauth-types': 0.6.1 - - '@atproto/oauth-client@0.5.13': - dependencies: - '@atproto-labs/did-resolver': 0.2.5 - '@atproto-labs/fetch': 0.2.3 - '@atproto-labs/handle-resolver': 0.3.5 - '@atproto-labs/identity-resolver': 0.3.5 - '@atproto-labs/simple-store': 0.3.0 - '@atproto-labs/simple-store-memory': 0.1.4 - '@atproto/did': 0.2.4 - '@atproto/jwk': 0.6.0 - '@atproto/oauth-types': 0.6.1 - '@atproto/xrpc': 0.7.7 - core-js: 3.48.0 - multiformats: 9.9.0 - zod: 3.25.76 - - '@atproto/oauth-types@0.6.1': - dependencies: - '@atproto/did': 0.2.4 - '@atproto/jwk': 0.6.0 - zod: 3.25.76 - '@atproto/repo@0.10.3': dependencies: '@atproto/common': 0.6.5 @@ -11861,20 +11855,11 @@ snapshots: varint: 6.0.0 zod: 3.25.76 - '@atproto/syntax@0.5.4': - dependencies: - tslib: 2.8.1 - '@atproto/syntax@0.6.4': dependencies: iso-datestring-validator: 2.2.2 tslib: 2.8.1 - '@atproto/xrpc@0.7.7': - dependencies: - '@atproto/lexicon': 0.6.2 - zod: 3.25.76 - '@atproto/xrpc@0.8.3': dependencies: '@atproto/lexicon': 0.7.4 @@ -12619,6 +12604,18 @@ snapshots: transitivePeerDependencies: - magicast + '@dxup/nuxt@0.4.1(magicast@0.5.3)(typescript@6.0.3)': + dependencies: + '@dxup/unimport': 0.1.2 + '@nuxt/kit': 4.4.8(magicast@0.5.3) + chokidar: 5.0.0 + pathe: 2.0.3 + tinyglobby: 0.2.17 + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - magicast + '@dxup/unimport@0.1.2': {} '@e18e/eslint-plugin@0.5.1(eslint@9.39.2)(oxlint@1.72.0)': @@ -13039,7 +13036,7 @@ snapshots: '@iconify/vue@5.0.0(vue@3.5.39)': dependencies: '@iconify/types': 2.0.0 - vue: 3.5.39(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.3) '@img/colour@1.0.0': {} @@ -13251,6 +13248,30 @@ snapshots: - supports-color - typescript + '@intlify/unplugin-vue-i18n@11.0.7(@vue/compiler-dom@3.5.39)(eslint@9.39.2)(rollup@4.60.3)(typescript@6.0.3)(vue-i18n@11.2.8)(vue@3.5.39)': + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2) + '@intlify/bundle-utils': 11.0.7(vue-i18n@11.2.8) + '@intlify/shared': 11.3.0 + '@intlify/vue-i18n-extensions': 8.0.0(@intlify/shared@11.3.0)(@vue/compiler-dom@3.5.39)(vue-i18n@11.2.8)(vue@3.5.39) + '@rollup/pluginutils': 5.4.0(rollup@4.60.3) + '@typescript-eslint/scope-manager': 8.56.1 + '@typescript-eslint/typescript-estree': 8.56.1(typescript@6.0.3) + debug: 4.4.3 + fast-glob: 3.3.3 + pathe: 2.0.3 + picocolors: 1.1.1 + unplugin: 2.3.11 + vue: 3.5.39(typescript@6.0.3) + optionalDependencies: + vue-i18n: 11.2.8(vue@3.5.39) + transitivePeerDependencies: + - '@vue/compiler-dom' + - eslint + - rollup + - supports-color + - typescript + '@intlify/utils@0.13.0': {} '@intlify/utils@0.14.1': {} @@ -13651,7 +13672,7 @@ snapshots: zod-to-json-schema: 3.25.2(zod@3.25.76) optionalDependencies: better-sqlite3: 12.8.0 - valibot: 1.4.2(typescript@6.0.2) + valibot: 1.4.2(typescript@6.0.3) transitivePeerDependencies: - bufferutil - drizzle-orm @@ -13678,6 +13699,14 @@ snapshots: transitivePeerDependencies: - magicast + '@nuxt/devtools-kit@3.2.4(magicast@0.5.3)(vite@8.1.3)': + dependencies: + '@nuxt/kit': 4.4.8(magicast@0.5.3) + execa: 8.0.1 + vite: 8.1.3(@types/node@24.12.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0) + transitivePeerDependencies: + - magicast + '@nuxt/devtools-kit@4.0.0-alpha.3(@voidzero-dev/vite-plus-core@0.2.2)(magicast@0.5.3)': dependencies: '@nuxt/kit': 4.4.8(magicast@0.5.3) @@ -13686,6 +13715,14 @@ snapshots: transitivePeerDependencies: - magicast + '@nuxt/devtools-kit@4.0.0-alpha.3(magicast@0.5.3)(vite@8.1.3)': + dependencies: + '@nuxt/kit': 4.4.8(magicast@0.5.3) + tinyexec: 1.2.4 + vite: 8.1.3(@types/node@24.12.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0) + transitivePeerDependencies: + - magicast + '@nuxt/devtools-wizard@3.2.4': dependencies: '@clack/prompts': 1.7.0 @@ -13738,27 +13775,68 @@ snapshots: - utf-8-validate - vue - '@nuxt/fonts@0.14.0(@upstash/redis@1.37.0)(@voidzero-dev/vite-plus-core@0.2.2)(db0@0.3.4)(ioredis@5.10.1)(magicast@0.5.3)': + '@nuxt/devtools@3.2.4(vite@8.1.3)(vue@3.5.39)': dependencies: - '@nuxt/devtools-kit': 3.2.4(@voidzero-dev/vite-plus-core@0.2.2)(magicast@0.5.3) + '@nuxt/devtools-kit': 3.2.4(magicast@0.5.3)(vite@8.1.3) + '@nuxt/devtools-wizard': 3.2.4 '@nuxt/kit': 4.4.8(magicast@0.5.3) + '@vue/devtools-core': 8.1.0(vue@3.5.39) + '@vue/devtools-kit': 8.1.0 + birpc: 4.0.0 consola: 3.4.2 - defu: 6.1.6 - fontless: 0.2.1(@upstash/redis@1.37.0)(@voidzero-dev/vite-plus-core@0.2.2)(db0@0.3.4)(ioredis@5.10.1) - h3: 1.15.11 - magic-regexp: 0.10.0 - ofetch: 1.5.1 - pathe: 2.0.3 - sirv: 3.0.2 - tinyglobby: 0.2.17 - ufo: 1.6.3 - unifont: 0.7.4 - unplugin: 3.0.0 - unstorage: 1.17.5(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1) - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' + destr: 2.0.5 + error-stack-parser-es: 1.0.5 + execa: 8.0.1 + fast-npm-meta: 1.4.2 + get-port-please: 3.2.0 + hookable: 6.1.1 + image-meta: 0.2.2 + is-installed-globally: 1.0.0 + launch-editor: 2.13.1 + local-pkg: 1.2.1 + magicast: 0.5.3 + nypm: 0.6.7 + ohash: 2.0.11 + pathe: 2.0.3 + perfect-debounce: 2.1.0 + pkg-types: 2.3.1 + semver: 7.7.4 + simple-git: 3.33.0 + sirv: 3.0.2 + structured-clone-es: 2.0.0 + tinyglobby: 0.2.17 + vite: 8.1.3(@types/node@24.12.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0) + vite-plugin-inspect: 11.3.3(@nuxt/kit@4.4.8)(vite@8.1.3) + vite-plugin-vue-tracer: 1.3.0(vite@8.1.3)(vue@3.5.39) + which: 6.0.1 + ws: 8.19.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + - vue + + '@nuxt/fonts@0.14.0(@upstash/redis@1.37.0)(@voidzero-dev/vite-plus-core@0.2.2)(db0@0.3.4)(ioredis@5.10.1)(magicast@0.5.3)': + dependencies: + '@nuxt/devtools-kit': 3.2.4(@voidzero-dev/vite-plus-core@0.2.2)(magicast@0.5.3) + '@nuxt/kit': 4.4.8(magicast@0.5.3) + consola: 3.4.2 + defu: 6.1.6 + fontless: 0.2.1(@upstash/redis@1.37.0)(@voidzero-dev/vite-plus-core@0.2.2)(db0@0.3.4)(ioredis@5.10.1) + h3: 1.15.11 + magic-regexp: 0.10.0 + ofetch: 1.5.1 + pathe: 2.0.3 + sirv: 3.0.2 + tinyglobby: 0.2.17 + ufo: 1.6.3 + unifont: 0.7.4 + unplugin: 3.0.0 + unstorage: 1.17.5(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1) + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' - '@azure/identity' - '@azure/keyvault-secrets' - '@azure/storage-blob' @@ -13778,13 +13856,53 @@ snapshots: - uploadthing - vite - '@nuxt/icon@2.2.1(@voidzero-dev/vite-plus-core@0.2.2)(magicast@0.5.3)(vue@3.5.39)': + '@nuxt/fonts@0.14.0(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1)(magicast@0.5.3)(vite@8.1.3)': + dependencies: + '@nuxt/devtools-kit': 3.2.4(magicast@0.5.3)(vite@8.1.3) + '@nuxt/kit': 4.4.8(magicast@0.5.3) + consola: 3.4.2 + defu: 6.1.6 + fontless: 0.2.1(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1)(vite@8.1.3) + h3: 1.15.11 + magic-regexp: 0.10.0 + ofetch: 1.5.1 + pathe: 2.0.3 + sirv: 3.0.2 + tinyglobby: 0.2.17 + ufo: 1.6.3 + unifont: 0.7.4 + unplugin: 3.0.0 + unstorage: 1.17.5(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1) + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - db0 + - idb-keyval + - ioredis + - magicast + - uploadthing + - vite + + '@nuxt/icon@2.2.1(magicast@0.5.3)(vite@8.1.3)(vue@3.5.39)': dependencies: '@iconify/collections': 1.0.654 '@iconify/types': 2.0.0 '@iconify/utils': 3.1.0 '@iconify/vue': 5.0.0(vue@3.5.39) - '@nuxt/devtools-kit': 3.2.4(@voidzero-dev/vite-plus-core@0.2.2)(magicast@0.5.3) + '@nuxt/devtools-kit': 3.2.4(magicast@0.5.3)(vite@8.1.3) '@nuxt/kit': 4.4.8(magicast@0.5.3) consola: 3.4.2 local-pkg: 1.2.1 @@ -13954,6 +14072,74 @@ snapshots: - uploadthing - xml2js + '@nuxt/nitro-server@4.4.8(@babel/plugin-syntax-typescript@7.28.6)(@upstash/redis@1.37.0)(better-sqlite3@12.8.0)(db0@0.3.4)(ioredis@5.10.1)(magicast@0.5.3)(nuxt@4.4.8)(oxc-parser@0.133.0)(rolldown@1.1.4)(typescript@6.0.3)': + dependencies: + '@nuxt/devalue': 2.0.2 + '@nuxt/kit': 4.4.8(magicast@0.5.3) + '@unhead/vue': 2.1.15(vue@3.5.39) + '@vue/shared': 3.5.39 + consola: 3.4.2 + defu: 6.1.7 + destr: 2.0.5 + devalue: 5.8.1 + errx: 0.1.0 + escape-string-regexp: 5.0.0 + exsolve: 1.0.8 + h3: 1.15.11 + impound: 1.1.5 + klona: 2.0.6 + mocked-exports: 0.1.1 + nitropack: 2.13.4(@upstash/redis@1.37.0)(better-sqlite3@12.8.0)(oxc-parser@0.133.0)(rolldown@1.1.4) + nuxt: 4.4.8(@babel/plugin-syntax-jsx@7.28.6)(@babel/plugin-syntax-typescript@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@vue/compiler-sfc@3.5.39)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.28.0)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.3)(optionator@0.9.4)(oxlint@1.72.0)(rolldown@1.1.4)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.48.0)(typescript@6.0.3)(vite@8.1.3)(vue-tsc@3.2.6)(yaml@2.9.0) + nypm: 0.6.7 + ohash: 2.0.11 + pathe: 2.0.3 + rou3: 0.8.1 + std-env: 4.1.0 + ufo: 1.6.4 + unctx: 2.5.0 + unstorage: 1.17.5(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1) + vue: 3.5.39(typescript@6.0.3) + vue-bundle-renderer: 2.2.0 + vue-devtools-stub: 0.1.0 + optionalDependencies: + '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.7) + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@electric-sql/pglite' + - '@libsql/client' + - '@netlify/blobs' + - '@planetscale/database' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bare-abort-controller + - better-sqlite3 + - db0 + - drizzle-orm + - encoding + - idb-keyval + - ioredis + - magicast + - mysql2 + - oxc-parser + - react-native-b4a + - rolldown + - sqlite3 + - supports-color + - typescript + - uploadthing + - xml2js + '@nuxt/schema@4.4.8': dependencies: '@vue/shared': 3.5.39 @@ -14063,20 +14249,20 @@ snapshots: - typescript - vite - '@nuxt/ui@4.6.1(@nuxt/content@3.12.0)(@tiptap/extensions@3.24.0)(@tiptap/y-tiptap@3.0.2)(@upstash/redis@1.37.0)(@voidzero-dev/vite-plus-core@0.2.2)(db0@0.3.4)(embla-carousel@8.6.0)(focus-trap@8.0.0)(ioredis@5.10.1)(magicast@0.5.3)(react-dom@19.2.4)(react@19.2.4)(tailwindcss@4.2.2)(typescript@6.0.2)(valibot@1.4.2)(vue-router@5.0.4)(vue@3.5.39)(yjs@13.6.29)(zod@4.3.6)': + '@nuxt/ui@4.6.1(@nuxt/content@3.12.0)(@tiptap/extensions@3.24.0)(@tiptap/y-tiptap@3.0.2)(@upstash/redis@1.37.0)(db0@0.3.4)(embla-carousel@8.6.0)(focus-trap@8.0.0)(ioredis@5.10.1)(magicast@0.5.3)(react-dom@19.2.4)(react@19.2.4)(tailwindcss@4.2.2)(typescript@6.0.3)(valibot@1.4.2)(vite@8.1.3)(vue-router@5.0.4)(vue@3.5.39)(yjs@13.6.29)(zod@4.3.6)': dependencies: '@floating-ui/dom': 1.7.6 '@iconify/vue': 5.0.0(vue@3.5.39) '@internationalized/date': 3.12.2 '@internationalized/number': 3.6.5 - '@nuxt/fonts': 0.14.0(@upstash/redis@1.37.0)(@voidzero-dev/vite-plus-core@0.2.2)(db0@0.3.4)(ioredis@5.10.1)(magicast@0.5.3) - '@nuxt/icon': 2.2.1(@voidzero-dev/vite-plus-core@0.2.2)(magicast@0.5.3)(vue@3.5.39) + '@nuxt/fonts': 0.14.0(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1)(magicast@0.5.3)(vite@8.1.3) + '@nuxt/icon': 2.2.1(magicast@0.5.3)(vite@8.1.3)(vue@3.5.39) '@nuxt/kit': 4.4.8(magicast@0.5.3) '@nuxt/schema': 4.4.8 '@nuxtjs/color-mode': 3.5.2(magicast@0.5.3) '@standard-schema/spec': 1.1.0 '@tailwindcss/postcss': 4.3.0 - '@tailwindcss/vite': 4.3.0(@voidzero-dev/vite-plus-core@0.2.2) + '@tailwindcss/vite': 4.3.0(vite@8.1.3) '@tanstack/vue-table': 8.21.3(vue@3.5.39) '@tanstack/vue-virtual': 3.13.26(vue@3.5.39) '@tiptap/core': 3.24.0(@tiptap/pm@3.24.0) @@ -14124,7 +14310,7 @@ snapshots: tailwind-variants: 3.2.2(tailwind-merge@3.5.0)(tailwindcss@4.2.2) tailwindcss: 4.2.2 tinyglobby: 0.2.17 - typescript: 6.0.2 + typescript: 6.0.3 ufo: 1.6.3 unplugin: 3.0.0 unplugin-auto-import: 21.0.0(@nuxt/kit@4.4.8)(@vueuse/core@14.3.0) @@ -14133,7 +14319,7 @@ snapshots: vue-component-type-helpers: 3.3.6 optionalDependencies: '@nuxt/content': 3.12.0(better-sqlite3@12.8.0)(magicast@0.5.3)(valibot@1.4.2) - valibot: 1.4.2(typescript@6.0.2) + valibot: 1.4.2(typescript@6.0.3) vue-router: 5.0.4(@vue/compiler-sfc@3.5.39)(vue@3.5.39) zod: 4.3.6 transitivePeerDependencies: @@ -14242,6 +14428,70 @@ snapshots: - vue-tsc - yaml + '@nuxt/vite-builder@4.4.8(@babel/plugin-syntax-jsx@7.28.6)(@types/node@24.12.0)(esbuild@0.28.0)(eslint@9.39.2)(magicast@0.5.3)(nuxt@4.4.8)(optionator@0.9.4)(oxlint@1.72.0)(rolldown@1.1.4)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.48.0)(typescript@6.0.3)(vue-tsc@3.2.6)(vue@3.5.39)(yaml@2.9.0)': + dependencies: + '@nuxt/kit': 4.4.8(magicast@0.5.3) + '@rollup/plugin-replace': 6.0.3(rollup@4.60.3) + '@vitejs/plugin-vue': 6.0.7(@voidzero-dev/vite-plus-core@0.2.2)(vue@3.5.39) + '@vitejs/plugin-vue-jsx': 5.1.5(@voidzero-dev/vite-plus-core@0.2.2)(vue@3.5.39) + autoprefixer: 10.5.0(postcss@8.5.16) + consola: 3.4.2 + cssnano: 8.0.2(postcss@8.5.16) + defu: 6.1.7 + escape-string-regexp: 5.0.0 + exsolve: 1.0.8 + get-port-please: 3.2.0 + jiti: 2.7.0 + knitwork: 1.3.0 + magic-string: 0.30.21 + mlly: 1.8.2 + mocked-exports: 0.1.1 + nuxt: 4.4.8(@babel/plugin-syntax-jsx@7.28.6)(@babel/plugin-syntax-typescript@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@vue/compiler-sfc@3.5.39)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.28.0)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.3)(optionator@0.9.4)(oxlint@1.72.0)(rolldown@1.1.4)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.48.0)(typescript@6.0.3)(vite@8.1.3)(vue-tsc@3.2.6)(yaml@2.9.0) + nypm: 0.6.7 + pathe: 2.0.3 + pkg-types: 2.3.1 + postcss: 8.5.16 + seroval: 1.5.4 + std-env: 4.1.0 + ufo: 1.6.4 + unenv: 2.0.0-rc.24 + vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(yaml@2.9.0)' + vite-node: 5.3.0(@types/node@24.12.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(yaml@2.9.0) + vite-plugin-checker: 0.14.4(@voidzero-dev/vite-plus-core@0.2.2)(eslint@9.39.2)(optionator@0.9.4)(oxlint@1.72.0)(typescript@6.0.3)(vue-tsc@3.2.6) + vue: 3.5.39(typescript@6.0.3) + vue-bundle-renderer: 2.2.0 + optionalDependencies: + '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.7) + rolldown: 1.1.4 + rollup-plugin-visualizer: 7.0.1(rolldown@1.1.4)(rollup@4.60.3) + transitivePeerDependencies: + - '@arethetypeswrong/core' + - '@biomejs/biome' + - '@types/node' + - '@vitejs/devtools' + - esbuild + - eslint + - less + - magicast + - meow + - optionator + - oxlint + - publint + - rollup + - sass + - sass-embedded + - stylelint + - stylus + - sugarss + - supports-color + - terser + - tsx + - typescript + - unplugin-unused + - unrun + - vue-tsc + - yaml + '@nuxtjs/color-mode@3.5.2(magicast@0.5.3)': dependencies: '@nuxt/kit': 3.21.2(magicast@0.5.3) @@ -14339,11 +14589,73 @@ snapshots: - uploadthing - vue - '@nuxtjs/mcp-toolkit@0.13.4(h3@1.15.11)(magicast@0.5.3)(zod@4.3.6)': + '@nuxtjs/i18n@10.2.4(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@upstash/redis@1.37.0)(@vue/compiler-dom@3.5.39)(db0@0.3.4)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.3)(rollup@4.60.3)(typescript@6.0.3)(vue@3.5.39)': dependencies: - '@modelcontextprotocol/sdk': 1.29.0(zod@4.3.6) + '@intlify/core': 11.2.8 + '@intlify/h3': 0.7.4 + '@intlify/shared': 11.3.0 + '@intlify/unplugin-vue-i18n': 11.0.7(@vue/compiler-dom@3.5.39)(eslint@9.39.2)(rollup@4.60.3)(typescript@6.0.3)(vue-i18n@11.2.8)(vue@3.5.39) + '@intlify/utils': 0.14.1 + '@miyaneee/rollup-plugin-json5': 1.2.0(rollup@4.60.3) '@nuxt/kit': 4.4.8(magicast@0.5.3) + '@rollup/plugin-yaml': 4.1.2(rollup@4.60.3) + '@vue/compiler-sfc': 3.5.39 + defu: 6.1.6 + devalue: 5.6.4 h3: 1.15.11 + knitwork: 1.3.0 + magic-string: 0.30.21 + mlly: 1.8.2 + nuxt-define: 1.0.0 + ohash: 2.0.11 + oxc-parser: 0.112.0(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + oxc-transform: 0.112.0(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + oxc-walker: 0.7.0(oxc-parser@0.112.0) + pathe: 2.0.3 + ufo: 1.6.3 + unplugin: 2.3.11 + unrouting: 0.1.7 + unstorage: 1.17.5(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1) + vue-i18n: 11.2.8(vue@3.5.39) + vue-router: 5.0.4(@vue/compiler-sfc@3.5.39)(vue@3.5.39) + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@emnapi/core' + - '@emnapi/runtime' + - '@netlify/blobs' + - '@pinia/colada' + - '@planetscale/database' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - '@vue/compiler-dom' + - aws4fetch + - db0 + - eslint + - idb-keyval + - ioredis + - magicast + - petite-vue-i18n + - pinia + - rollup + - supports-color + - typescript + - uploadthing + - vue + + '@nuxtjs/mcp-toolkit@0.13.4(h3@2.0.1-rc.22)(magicast@0.5.3)(zod@4.3.6)': + dependencies: + '@modelcontextprotocol/sdk': 1.29.0(zod@4.3.6) + '@nuxt/kit': 4.4.8(magicast@0.5.3) + h3: 2.0.1-rc.22 tinyglobby: 0.2.17 zod: 4.3.6 transitivePeerDependencies: @@ -14450,15 +14762,15 @@ snapshots: - magicast - supports-color - '@nuxtjs/robots@6.0.9(@nuxt/schema@4.4.8)(@voidzero-dev/vite-plus-core@0.2.2)(magicast@0.5.3)(nuxt@4.4.8)(vue@3.5.39)(zod@4.3.6)': + '@nuxtjs/robots@6.0.9(@nuxt/schema@4.4.8)(magicast@0.5.3)(nuxt@4.4.8)(vite@8.1.3)(vue@3.5.39)(zod@4.3.6)': dependencies: '@fingerprintjs/botd': 2.0.0 '@nuxt/kit': 4.4.8(magicast@0.5.3) consola: 3.4.2 defu: 6.1.7 h3: 1.15.11 - nuxt-site-config: 4.0.8(@nuxt/schema@4.4.8)(@voidzero-dev/vite-plus-core@0.2.2)(magicast@0.5.3)(nuxt@4.4.8)(vue@3.5.39)(zod@4.3.6) - nuxtseo-shared: 5.3.0(@nuxt/schema@4.4.8)(@voidzero-dev/vite-plus-core@0.2.2)(magicast@0.5.3)(nuxt-site-config@4.0.8)(nuxt@4.4.8)(vue@3.5.39)(zod@4.3.6) + nuxt-site-config: 4.0.8(@nuxt/schema@4.4.8)(magicast@0.5.3)(nuxt@4.4.8)(vite@8.1.3)(vue@3.5.39)(zod@4.3.6) + nuxtseo-shared: 5.3.0(@nuxt/schema@4.4.8)(magicast@0.5.3)(nuxt-site-config@4.0.8)(nuxt@4.4.8)(vite@8.1.3)(vue@3.5.39)(zod@4.3.6) pathe: 2.0.3 pkg-types: 2.3.1 ufo: 1.6.4 @@ -15900,12 +16212,12 @@ snapshots: postcss: 8.5.16 tailwindcss: 4.3.0 - '@tailwindcss/vite@4.3.0(@voidzero-dev/vite-plus-core@0.2.2)': + '@tailwindcss/vite@4.3.0(vite@8.1.3)': dependencies: '@tailwindcss/node': 4.3.0 '@tailwindcss/oxide': 4.3.0 tailwindcss: 4.3.0 - vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.2)(yaml@2.9.0)' + vite: 8.1.3(@types/node@24.12.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0) '@takumi-rs/core-darwin-arm64@0.73.1': optional: true @@ -16006,12 +16318,12 @@ snapshots: '@tanstack/vue-table@8.21.3(vue@3.5.39)': dependencies: '@tanstack/table-core': 8.21.3 - vue: 3.5.39(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.3) '@tanstack/vue-virtual@3.13.26(vue@3.5.39)': dependencies: '@tanstack/virtual-core': 3.16.0 - vue: 3.5.39(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.3) '@testing-library/dom@10.4.1': dependencies: @@ -16084,7 +16396,7 @@ snapshots: '@tiptap/extension-drag-handle': 3.24.0(@tiptap/core@3.24.0)(@tiptap/extension-collaboration@3.24.0)(@tiptap/extension-node-range@3.24.0)(@tiptap/pm@3.24.0)(@tiptap/y-tiptap@3.0.2) '@tiptap/pm': 3.24.0 '@tiptap/vue-3': 3.24.0(@floating-ui/dom@1.7.6)(@tiptap/core@3.24.0)(@tiptap/pm@3.24.0)(vue@3.5.39) - vue: 3.5.39(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.3) '@tiptap/extension-drag-handle@3.24.0(@tiptap/core@3.24.0)(@tiptap/extension-collaboration@3.24.0)(@tiptap/extension-node-range@3.24.0)(@tiptap/pm@3.24.0)(@tiptap/y-tiptap@3.0.2)': dependencies: @@ -16248,7 +16560,7 @@ snapshots: '@floating-ui/dom': 1.7.6 '@tiptap/core': 3.24.0(@tiptap/pm@3.24.0) '@tiptap/pm': 3.24.0 - vue: 3.5.39(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.3) optionalDependencies: '@tiptap/extension-bubble-menu': 3.24.0(@tiptap/core@3.24.0)(@tiptap/pm@3.24.0) '@tiptap/extension-floating-menu': 3.24.0(@floating-ui/dom@1.7.6)(@tiptap/core@3.24.0)(@tiptap/pm@3.24.0) @@ -16370,6 +16682,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/project-service@8.56.1(typescript@6.0.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.56.1(typescript@6.0.3) + '@typescript-eslint/types': 8.56.1 + debug: 4.4.3 + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/scope-manager@8.56.1': dependencies: '@typescript-eslint/types': 8.56.1 @@ -16379,6 +16700,10 @@ snapshots: dependencies: typescript: 6.0.2 + '@typescript-eslint/tsconfig-utils@8.56.1(typescript@6.0.3)': + dependencies: + typescript: 6.0.3 + '@typescript-eslint/types@8.56.1': {} '@typescript-eslint/typescript-estree@8.56.1(typescript@6.0.2)': @@ -16396,6 +16721,21 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@8.56.1(typescript@6.0.3)': + dependencies: + '@typescript-eslint/project-service': 8.56.1(typescript@6.0.3) + '@typescript-eslint/tsconfig-utils': 8.56.1(typescript@6.0.3) + '@typescript-eslint/types': 8.56.1 + '@typescript-eslint/visitor-keys': 8.56.1 + debug: 4.4.3 + minimatch: 10.2.5 + semver: 7.7.4 + tinyglobby: 0.2.17 + ts-api-utils: 2.4.0(typescript@6.0.3) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/visitor-keys@8.56.1': dependencies: '@typescript-eslint/types': 8.56.1 @@ -16802,6 +17142,21 @@ snapshots: typescript: 6.0.2 yaml: 2.9.0 + '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(yaml@2.9.0)': + dependencies: + '@oxc-project/runtime': 0.138.0 + '@oxc-project/types': 0.138.0 + lightningcss: 1.32.0 + postcss: 8.5.16 + optionalDependencies: + '@types/node': 24.12.0 + esbuild: 0.28.0 + fsevents: 2.3.3 + jiti: 2.7.0 + terser: 5.48.0 + typescript: 6.0.3 + yaml: 2.9.0 + '@voidzero-dev/vite-plus-darwin-arm64@0.2.2': optional: true @@ -17938,7 +18293,7 @@ snapshots: doctypes@1.1.0: {} - docus@5.9.0(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@nuxt/schema@4.4.8)(@takumi-rs/wasm@1.0.9)(@tiptap/extensions@3.24.0)(@tiptap/y-tiptap@3.0.2)(@unhead/vue@2.1.15)(@upstash/redis@1.37.0)(@voidzero-dev/vite-plus-core@0.2.2)(@vue/compiler-dom@3.5.39)(better-sqlite3@12.8.0)(db0@0.3.4)(embla-carousel@8.6.0)(eslint@9.39.2)(focus-trap@8.0.0)(fontless@0.2.1)(h3@1.15.11)(ioredis@5.10.1)(magicast@0.5.3)(nitropack@2.13.4)(nuxt@4.4.8)(playwright-core@1.61.1)(react-dom@19.2.4)(react@19.2.4)(rolldown@1.1.4)(rollup@4.60.3)(sharp@0.34.5)(typescript@6.0.2)(unifont@0.7.4)(unstorage@1.17.5)(valibot@1.4.2)(vue-router@5.0.4)(vue@3.5.39)(yjs@13.6.29): + docus@5.9.0(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@nuxt/schema@4.4.8)(@takumi-rs/wasm@1.0.9)(@tiptap/extensions@3.24.0)(@tiptap/y-tiptap@3.0.2)(@unhead/vue@2.1.15)(@upstash/redis@1.37.0)(@vue/compiler-dom@3.5.39)(better-sqlite3@12.8.0)(db0@0.3.4)(embla-carousel@8.6.0)(eslint@9.39.2)(focus-trap@8.0.0)(fontless@0.2.1)(h3@2.0.1-rc.22)(ioredis@5.10.1)(magicast@0.5.3)(nitropack@2.13.4)(nuxt@4.4.8)(playwright-core@1.61.1)(react-dom@19.2.4)(react@19.2.4)(rolldown@1.1.4)(rollup@4.60.3)(sharp@0.34.5)(typescript@6.0.3)(unifont@0.7.4)(unstorage@1.17.5)(valibot@1.4.2)(vite@8.1.3)(vue-router@5.0.4)(vue@3.5.39)(yjs@13.6.29): dependencies: '@ai-sdk/gateway': 3.0.101(zod@4.3.6) '@ai-sdk/mcp': 1.0.36(zod@4.3.6) @@ -17949,11 +18304,11 @@ snapshots: '@nuxt/content': 3.12.0(better-sqlite3@12.8.0)(magicast@0.5.3)(valibot@1.4.2) '@nuxt/image': 2.0.0(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1)(magicast@0.5.3) '@nuxt/kit': 4.4.8(magicast@0.5.3) - '@nuxt/ui': 4.6.1(@nuxt/content@3.12.0)(@tiptap/extensions@3.24.0)(@tiptap/y-tiptap@3.0.2)(@upstash/redis@1.37.0)(@voidzero-dev/vite-plus-core@0.2.2)(db0@0.3.4)(embla-carousel@8.6.0)(focus-trap@8.0.0)(ioredis@5.10.1)(magicast@0.5.3)(react-dom@19.2.4)(react@19.2.4)(tailwindcss@4.2.2)(typescript@6.0.2)(valibot@1.4.2)(vue-router@5.0.4)(vue@3.5.39)(yjs@13.6.29)(zod@4.3.6) - '@nuxtjs/i18n': 10.2.4(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@upstash/redis@1.37.0)(@vue/compiler-dom@3.5.39)(db0@0.3.4)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.3)(rollup@4.60.3)(typescript@6.0.2)(vue@3.5.39) - '@nuxtjs/mcp-toolkit': 0.13.4(h3@1.15.11)(magicast@0.5.3)(zod@4.3.6) + '@nuxt/ui': 4.6.1(@nuxt/content@3.12.0)(@tiptap/extensions@3.24.0)(@tiptap/y-tiptap@3.0.2)(@upstash/redis@1.37.0)(db0@0.3.4)(embla-carousel@8.6.0)(focus-trap@8.0.0)(ioredis@5.10.1)(magicast@0.5.3)(react-dom@19.2.4)(react@19.2.4)(tailwindcss@4.2.2)(typescript@6.0.3)(valibot@1.4.2)(vite@8.1.3)(vue-router@5.0.4)(vue@3.5.39)(yjs@13.6.29)(zod@4.3.6) + '@nuxtjs/i18n': 10.2.4(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@upstash/redis@1.37.0)(@vue/compiler-dom@3.5.39)(db0@0.3.4)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.3)(rollup@4.60.3)(typescript@6.0.3)(vue@3.5.39) + '@nuxtjs/mcp-toolkit': 0.13.4(h3@2.0.1-rc.22)(magicast@0.5.3)(zod@4.3.6) '@nuxtjs/mdc': 0.21.1(magicast@0.5.3) - '@nuxtjs/robots': 6.0.9(@nuxt/schema@4.4.8)(@voidzero-dev/vite-plus-core@0.2.2)(magicast@0.5.3)(nuxt@4.4.8)(vue@3.5.39)(zod@4.3.6) + '@nuxtjs/robots': 6.0.9(@nuxt/schema@4.4.8)(magicast@0.5.3)(nuxt@4.4.8)(vite@8.1.3)(vue@3.5.39)(zod@4.3.6) '@shikijs/core': 4.1.0 '@shikijs/engine-javascript': 4.0.2 '@shikijs/langs': 4.0.2 @@ -17966,9 +18321,9 @@ snapshots: exsolve: 1.0.8 git-url-parse: 16.1.0 motion-v: 2.2.1(@vueuse/core@14.3.0)(react-dom@19.2.4)(react@19.2.4)(vue@3.5.39) - nuxt: 4.4.8(@babel/plugin-syntax-jsx@7.28.6)(@babel/plugin-syntax-typescript@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@voidzero-dev/vite-plus-core@0.2.2)(@vue/compiler-sfc@3.5.39)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.28.0)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.3)(optionator@0.9.4)(oxlint@1.72.0)(rolldown@1.1.4)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.48.0)(typescript@6.0.2)(vue-tsc@3.2.6)(yaml@2.9.0) + nuxt: 4.4.8(@babel/plugin-syntax-jsx@7.28.6)(@babel/plugin-syntax-typescript@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@vue/compiler-sfc@3.5.39)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.28.0)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.3)(optionator@0.9.4)(oxlint@1.72.0)(rolldown@1.1.4)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.48.0)(typescript@6.0.3)(vite@8.1.3)(vue-tsc@3.2.6)(yaml@2.9.0) nuxt-llms: 0.2.0(magicast@0.5.3) - nuxt-og-image: 6.6.0(@nuxt/schema@4.4.8)(@takumi-rs/core@0.73.1)(@takumi-rs/wasm@1.0.9)(@unhead/vue@2.1.15)(@voidzero-dev/vite-plus-core@0.2.2)(fontless@0.2.1)(nitropack@2.13.4)(nuxt@4.4.8)(playwright-core@1.61.1)(rolldown@1.1.4)(sharp@0.34.5)(tailwindcss@4.2.2)(unifont@0.7.4)(unstorage@1.17.5)(vue@3.5.39)(zod@4.3.6) + nuxt-og-image: 6.6.0(@nuxt/schema@4.4.8)(@takumi-rs/core@0.73.1)(@takumi-rs/wasm@1.0.9)(@unhead/vue@2.1.15)(fontless@0.2.1)(nitropack@2.13.4)(nuxt@4.4.8)(playwright-core@1.61.1)(rolldown@1.1.4)(sharp@0.34.5)(tailwindcss@4.2.2)(unifont@0.7.4)(unstorage@1.17.5)(vite@8.1.3)(vue@3.5.39)(zod@4.3.6) pkg-types: 2.3.1 scule: 1.3.0 shiki-stream: 0.1.4(react@19.2.4)(vue@3.5.39) @@ -18147,7 +18502,7 @@ snapshots: dependencies: embla-carousel: 8.6.0 embla-carousel-reactive-utils: 8.6.0(embla-carousel@8.6.0) - vue: 3.5.39(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.3) embla-carousel-wheel-gestures@8.1.0(embla-carousel@8.6.0): dependencies: @@ -18464,6 +18819,8 @@ snapshots: transitivePeerDependencies: - supports-color + esm-env@1.2.2: {} + esm-resolve@1.0.11: {} espree@10.4.0: @@ -18737,6 +19094,44 @@ snapshots: - ioredis - uploadthing + fontless@0.2.1(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1)(vite@8.1.3): + dependencies: + consola: 3.4.2 + css-tree: 3.1.0 + defu: 6.1.6 + esbuild: 0.27.3 + fontaine: 0.8.0 + jiti: 2.7.0 + lightningcss: 1.32.0 + magic-string: 0.30.21 + ohash: 2.0.11 + pathe: 2.0.3 + ufo: 1.6.3 + unifont: 0.7.4 + unstorage: 1.17.5(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1) + optionalDependencies: + vite: 8.1.3(@types/node@24.12.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0) + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - db0 + - idb-keyval + - ioredis + - uploadthing + for-each@0.3.5: dependencies: is-callable: 1.2.7 @@ -19571,8 +19966,6 @@ snapshots: jiti@2.7.0: {} - jose@5.10.0: {} - jose@6.1.3: {} js-beautify@1.15.4: @@ -20317,7 +20710,7 @@ snapshots: hey-listen: 1.0.8 motion-dom: 12.40.0 motion-utils: 12.39.0 - vue: 3.5.39(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.3) transitivePeerDependencies: - '@emotion/is-prop-valid' - react @@ -20363,12 +20756,12 @@ snapshots: multiformats@13.4.2: {} - multiformats@9.9.0: {} - mute-stream@2.0.0: {} nanoid@3.3.14: {} + nanoid@5.1.16: {} + nanotar@0.3.0: {} napi-build-utils@2.0.0: {} @@ -20763,7 +21156,7 @@ snapshots: transitivePeerDependencies: - magicast - nuxt-og-image@6.6.0(@nuxt/schema@4.4.8)(@takumi-rs/core@0.73.1)(@takumi-rs/wasm@1.0.9)(@unhead/vue@2.1.15)(@voidzero-dev/vite-plus-core@0.2.2)(fontless@0.2.1)(nitropack@2.13.4)(nuxt@4.4.8)(playwright-core@1.61.1)(rolldown@1.1.4)(sharp@0.34.5)(tailwindcss@4.2.2)(unifont@0.7.4)(unstorage@1.17.5)(vue@3.5.39)(zod@4.3.6): + nuxt-og-image@6.6.0(@nuxt/schema@4.4.8)(@takumi-rs/core@0.73.1)(@takumi-rs/wasm@1.0.9)(@unhead/vue@2.1.15)(fontless@0.2.1)(nitropack@2.13.4)(nuxt@4.4.8)(playwright-core@1.61.1)(rolldown@1.1.4)(sharp@0.34.5)(tailwindcss@4.2.2)(unifont@0.7.4)(unstorage@1.17.5)(vite@8.1.3)(vue@3.5.39)(zod@4.3.6): dependencies: '@clack/prompts': 1.7.0 '@nuxt/kit': 4.4.8(magicast@0.5.3) @@ -20781,8 +21174,8 @@ snapshots: magic-string: 0.30.21 magicast: 0.5.3 mocked-exports: 0.1.1 - nuxt-site-config: 4.0.8(@nuxt/schema@4.4.8)(@voidzero-dev/vite-plus-core@0.2.2)(magicast@0.5.3)(nuxt@4.4.8)(vue@3.5.39)(zod@4.3.6) - nuxtseo-shared: 5.3.0(@nuxt/schema@4.4.8)(@voidzero-dev/vite-plus-core@0.2.2)(magicast@0.5.3)(nuxt-site-config@4.0.8)(nuxt@4.4.8)(vue@3.5.39)(zod@4.3.6) + nuxt-site-config: 4.0.8(@nuxt/schema@4.4.8)(magicast@0.5.3)(nuxt@4.4.8)(vite@8.1.3)(vue@3.5.39)(zod@4.3.6) + nuxtseo-shared: 5.3.0(@nuxt/schema@4.4.8)(magicast@0.5.3)(nuxt-site-config@4.0.8)(nuxt@4.4.8)(vite@8.1.3)(vue@3.5.39)(zod@4.3.6) nypm: 0.6.7 ofetch: 1.5.1 ohash: 2.0.11 @@ -20802,7 +21195,7 @@ snapshots: optionalDependencies: '@takumi-rs/core': 0.73.1 '@takumi-rs/wasm': 1.0.9(react-dom@19.2.4)(react@19.2.4) - fontless: 0.2.1(@upstash/redis@1.37.0)(@voidzero-dev/vite-plus-core@0.2.2)(db0@0.3.4)(ioredis@5.10.1) + fontless: 0.2.1(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1)(vite@8.1.3) nitropack: 2.13.4(@upstash/redis@1.37.0)(better-sqlite3@12.8.0)(oxc-parser@0.135.0)(rolldown@1.1.4) playwright-core: 1.61.1 sharp: 0.34.5 @@ -20875,18 +21268,36 @@ snapshots: dependencies: '@nuxt/kit': 4.4.8(magicast@0.5.3) site-config-stack: 4.0.8(vue@3.5.39) - std-env: 4.0.0 + std-env: 4.0.0 + ufo: 1.6.3 + transitivePeerDependencies: + - magicast + - vue + + nuxt-site-config@4.0.8(@nuxt/schema@4.4.8)(@voidzero-dev/vite-plus-core@0.2.2)(magicast@0.5.3)(nuxt@4.4.8)(vue@3.5.39)(zod@4.3.6): + dependencies: + '@nuxt/kit': 4.4.8(magicast@0.5.3) + h3: 1.15.11 + nuxt-site-config-kit: 4.0.8(magicast@0.5.3)(vue@3.5.39) + nuxtseo-shared: 5.3.0(@nuxt/schema@4.4.8)(@voidzero-dev/vite-plus-core@0.2.2)(magicast@0.5.3)(nuxt-site-config@4.0.8)(nuxt@4.4.8)(vue@3.5.39)(zod@4.3.6) + pathe: 2.0.3 + pkg-types: 2.3.1 + site-config-stack: 4.0.8(vue@3.5.39) ufo: 1.6.3 transitivePeerDependencies: + - '@nuxt/schema' - magicast + - nuxt + - vite - vue + - zod - nuxt-site-config@4.0.8(@nuxt/schema@4.4.8)(@voidzero-dev/vite-plus-core@0.2.2)(magicast@0.5.3)(nuxt@4.4.8)(vue@3.5.39)(zod@4.3.6): + nuxt-site-config@4.0.8(@nuxt/schema@4.4.8)(magicast@0.5.3)(nuxt@4.4.8)(vite@8.1.3)(vue@3.5.39)(zod@4.3.6): dependencies: '@nuxt/kit': 4.4.8(magicast@0.5.3) h3: 1.15.11 nuxt-site-config-kit: 4.0.8(magicast@0.5.3)(vue@3.5.39) - nuxtseo-shared: 5.3.0(@nuxt/schema@4.4.8)(@voidzero-dev/vite-plus-core@0.2.2)(magicast@0.5.3)(nuxt-site-config@4.0.8)(nuxt@4.4.8)(vue@3.5.39)(zod@4.3.6) + nuxtseo-shared: 5.3.0(@nuxt/schema@4.4.8)(magicast@0.5.3)(nuxt-site-config@4.0.8)(nuxt@4.4.8)(vite@8.1.3)(vue@3.5.39)(zod@4.3.6) pathe: 2.0.3 pkg-types: 2.3.1 site-config-stack: 4.0.8(vue@3.5.39) @@ -21030,6 +21441,137 @@ snapshots: - xml2js - yaml + nuxt@4.4.8(@babel/plugin-syntax-jsx@7.28.6)(@babel/plugin-syntax-typescript@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@vue/compiler-sfc@3.5.39)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.28.0)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.3)(optionator@0.9.4)(oxlint@1.72.0)(rolldown@1.1.4)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.48.0)(typescript@6.0.3)(vite@8.1.3)(vue-tsc@3.2.6)(yaml@2.9.0): + dependencies: + '@dxup/nuxt': 0.4.1(magicast@0.5.3)(typescript@6.0.3) + '@nuxt/cli': 3.36.0(@nuxt/schema@4.4.8)(cac@6.7.14)(magicast@0.5.3) + '@nuxt/devtools': 3.2.4(vite@8.1.3)(vue@3.5.39) + '@nuxt/kit': 4.4.8(magicast@0.5.3) + '@nuxt/nitro-server': 4.4.8(@babel/plugin-syntax-typescript@7.28.6)(@upstash/redis@1.37.0)(better-sqlite3@12.8.0)(db0@0.3.4)(ioredis@5.10.1)(magicast@0.5.3)(nuxt@4.4.8)(oxc-parser@0.133.0)(rolldown@1.1.4)(typescript@6.0.3) + '@nuxt/schema': 4.4.8 + '@nuxt/telemetry': 2.8.0(@nuxt/kit@4.4.8) + '@nuxt/vite-builder': 4.4.8(@babel/plugin-syntax-jsx@7.28.6)(@types/node@24.12.0)(esbuild@0.28.0)(eslint@9.39.2)(magicast@0.5.3)(nuxt@4.4.8)(optionator@0.9.4)(oxlint@1.72.0)(rolldown@1.1.4)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.48.0)(typescript@6.0.3)(vue-tsc@3.2.6)(vue@3.5.39)(yaml@2.9.0) + '@unhead/vue': 2.1.15(vue@3.5.39) + '@vue/shared': 3.5.39 + chokidar: 5.0.0 + compatx: 0.2.0 + consola: 3.4.2 + cookie-es: 3.1.1 + defu: 6.1.7 + devalue: 5.8.1 + errx: 0.1.0 + escape-string-regexp: 5.0.0 + exsolve: 1.0.8 + hookable: 6.1.1 + ignore: 7.0.5 + impound: 1.1.5 + jiti: 2.7.0 + klona: 2.0.6 + knitwork: 1.3.0 + magic-string: 0.30.21 + mlly: 1.8.2 + nanotar: 0.3.0 + nypm: 0.6.7 + ofetch: 1.5.1 + ohash: 2.0.11 + on-change: 6.0.2 + oxc-minify: 0.133.0 + oxc-parser: 0.133.0 + oxc-transform: 0.133.0 + oxc-walker: 1.0.0(oxc-parser@0.133.0)(rolldown@1.1.4) + pathe: 2.0.3 + perfect-debounce: 2.1.0 + picomatch: 4.0.5 + pkg-types: 2.3.1 + rou3: 0.8.1 + scule: 1.3.0 + semver: 7.8.5 + std-env: 4.1.0 + tinyglobby: 0.2.17 + ufo: 1.6.4 + ultrahtml: 1.6.0 + uncrypto: 0.1.3 + unctx: 2.5.0 + unhead: 2.1.15 + unimport: 6.3.0(oxc-parser@0.133.0)(rolldown@1.1.4) + unplugin: 3.0.0 + unrouting: 0.1.7 + untyped: 2.0.0 + vue: 3.5.39(typescript@6.0.3) + vue-router: 5.0.4(@vue/compiler-sfc@3.5.39)(vue@3.5.39) + optionalDependencies: + '@parcel/watcher': 2.5.6 + '@types/node': 24.12.0 + transitivePeerDependencies: + - '@arethetypeswrong/core' + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@babel/plugin-proposal-decorators' + - '@babel/plugin-syntax-jsx' + - '@babel/plugin-syntax-typescript' + - '@biomejs/biome' + - '@capacitor/preferences' + - '@deno/kv' + - '@electric-sql/pglite' + - '@libsql/client' + - '@netlify/blobs' + - '@pinia/colada' + - '@planetscale/database' + - '@rollup/plugin-babel' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - '@vitejs/devtools' + - '@vue/compiler-sfc' + - aws4fetch + - bare-abort-controller + - better-sqlite3 + - bufferutil + - cac + - commander + - db0 + - drizzle-orm + - encoding + - esbuild + - eslint + - idb-keyval + - ioredis + - less + - magicast + - meow + - mysql2 + - optionator + - oxlint + - pinia + - publint + - react-native-b4a + - rolldown + - rollup + - rollup-plugin-visualizer + - sass + - sass-embedded + - sqlite3 + - stylelint + - stylus + - sugarss + - supports-color + - terser + - tsx + - typescript + - unplugin-unused + - unrun + - uploadthing + - utf-8-validate + - vite + - vue-tsc + - xml2js + - yaml + nuxtseo-shared@5.3.0(@nuxt/schema@4.4.8)(@voidzero-dev/vite-plus-core@0.2.2)(magicast@0.5.3)(nuxt-site-config@4.0.8)(nuxt@4.4.8)(vue@3.5.39)(zod@4.3.6): dependencies: '@clack/prompts': 1.7.0 @@ -21056,6 +21598,32 @@ snapshots: - magicast - vite + nuxtseo-shared@5.3.0(@nuxt/schema@4.4.8)(magicast@0.5.3)(nuxt-site-config@4.0.8)(nuxt@4.4.8)(vite@8.1.3)(vue@3.5.39)(zod@4.3.6): + dependencies: + '@clack/prompts': 1.7.0 + '@nuxt/devtools-kit': 4.0.0-alpha.3(magicast@0.5.3)(vite@8.1.3) + '@nuxt/kit': 4.4.8(magicast@0.5.3) + '@nuxt/schema': 4.4.8 + birpc: 4.0.0 + consola: 3.4.2 + defu: 6.1.7 + nuxt: 4.4.8(@babel/plugin-syntax-jsx@7.28.6)(@babel/plugin-syntax-typescript@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@vue/compiler-sfc@3.5.39)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.28.0)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.3)(optionator@0.9.4)(oxlint@1.72.0)(rolldown@1.1.4)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.48.0)(typescript@6.0.3)(vite@8.1.3)(vue-tsc@3.2.6)(yaml@2.9.0) + nypm: 0.6.7 + ofetch: 1.5.1 + pathe: 2.0.3 + pkg-types: 2.3.1 + radix3: 1.1.2 + sirv: 3.0.2 + std-env: 4.1.0 + ufo: 1.6.4 + vue: 3.5.39(typescript@6.0.3) + optionalDependencies: + nuxt-site-config: 4.0.8(@nuxt/schema@4.4.8)(magicast@0.5.3)(nuxt@4.4.8)(vite@8.1.3)(vue@3.5.39)(zod@4.3.6) + zod: 4.3.6 + transitivePeerDependencies: + - magicast + - vite + nypm@0.6.7: dependencies: citty: 0.2.2 @@ -22208,7 +22776,7 @@ snapshots: aria-hidden: 1.2.6 defu: 6.1.6 ohash: 2.0.11 - vue: 3.5.39(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.3) transitivePeerDependencies: - '@vue/composition-api' @@ -22579,7 +23147,7 @@ snapshots: '@shikijs/core': 3.23.0 optionalDependencies: react: 19.2.4 - vue: 3.5.39(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.3) shiki@3.23.0: dependencies: @@ -22924,7 +23492,7 @@ snapshots: swrv@1.1.0(vue@3.5.39): dependencies: - vue: 3.5.39(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.3) tabbable@6.4.0: {} @@ -23084,6 +23652,10 @@ snapshots: dependencies: typescript: 6.0.2 + ts-api-utils@2.4.0(typescript@6.0.3): + dependencies: + typescript: 6.0.3 + ts-dedent@2.2.0: {} ts-map@1.0.3: {} @@ -23164,10 +23736,6 @@ snapshots: ufo@1.6.4: {} - uint8arrays@3.0.0: - dependencies: - multiformats: 9.9.0 - uint8arrays@5.1.1: dependencies: multiformats: 13.4.2 @@ -23209,8 +23777,6 @@ snapshots: undici-types@7.16.0: {} - undici@6.23.0: {} - unenv@2.0.0-rc.24: dependencies: pathe: 2.0.3 @@ -23427,7 +23993,7 @@ snapshots: tinyglobby: 0.2.17 unplugin: 3.0.0 unplugin-utils: 0.3.1 - vue: 3.5.39(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.3) optionalDependencies: '@nuxt/kit': 4.4.8(magicast@0.5.3) @@ -23541,7 +24107,7 @@ snapshots: dependencies: '@vueuse/core': 10.11.1(vue@3.5.39) reka-ui: 2.9.3(vue@3.5.39) - vue: 3.5.39(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.3) transitivePeerDependencies: - '@vue/composition-api' @@ -23572,10 +24138,20 @@ snapshots: vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.2)(yaml@2.9.0)' vite-hot-client: 2.1.0(@voidzero-dev/vite-plus-core@0.2.2) + vite-dev-rpc@1.1.0(vite@8.1.3): + dependencies: + birpc: 2.9.0 + vite: 8.1.3(@types/node@24.12.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0) + vite-hot-client: 2.1.0(vite@8.1.3) + vite-hot-client@2.1.0(@voidzero-dev/vite-plus-core@0.2.2): dependencies: vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.2)(yaml@2.9.0)' + vite-hot-client@2.1.0(vite@8.1.3): + dependencies: + vite: 8.1.3(@types/node@24.12.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0) + vite-node@5.3.0(@types/node@24.12.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.2)(yaml@2.9.0): dependencies: cac: 6.7.14 @@ -23602,6 +24178,32 @@ snapshots: - unrun - yaml + vite-node@5.3.0(@types/node@24.12.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(yaml@2.9.0): + dependencies: + cac: 6.7.14 + es-module-lexer: 2.3.0 + obug: 2.1.3 + pathe: 2.0.3 + vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(yaml@2.9.0)' + transitivePeerDependencies: + - '@arethetypeswrong/core' + - '@types/node' + - '@vitejs/devtools' + - esbuild + - jiti + - less + - publint + - sass + - sass-embedded + - stylus + - sugarss + - terser + - tsx + - typescript + - unplugin-unused + - unrun + - yaml + vite-plugin-checker@0.14.4(@voidzero-dev/vite-plus-core@0.2.2)(eslint@9.39.2)(optionator@0.9.4)(oxlint@1.72.0)(typescript@6.0.2)(vue-tsc@3.2.6): dependencies: '@babel/code-frame': 7.29.7 @@ -23619,6 +24221,23 @@ snapshots: typescript: 6.0.2 vue-tsc: 3.2.6(typescript@6.0.2) + vite-plugin-checker@0.14.4(@voidzero-dev/vite-plus-core@0.2.2)(eslint@9.39.2)(optionator@0.9.4)(oxlint@1.72.0)(typescript@6.0.3)(vue-tsc@3.2.6): + dependencies: + '@babel/code-frame': 7.29.7 + chokidar: 5.0.0 + npm-run-path: 6.0.0 + picocolors: 1.1.1 + picomatch: 4.0.5 + proper-lockfile: 4.1.2 + tiny-invariant: 1.3.3 + vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(yaml@2.9.0)' + optionalDependencies: + eslint: 9.39.2(jiti@2.7.0) + optionator: 0.9.4 + oxlint: 1.72.0(oxlint-tsgolint@0.24.0)(vite-plus@0.2.2) + typescript: 6.0.3 + vue-tsc: 3.2.6(typescript@6.0.2) + vite-plugin-inspect@11.3.3(@nuxt/kit@4.4.8)(@voidzero-dev/vite-plus-core@0.2.2): dependencies: ansis: 4.2.0 @@ -23636,6 +24255,23 @@ snapshots: transitivePeerDependencies: - supports-color + vite-plugin-inspect@11.3.3(@nuxt/kit@4.4.8)(vite@8.1.3): + dependencies: + ansis: 4.2.0 + debug: 4.4.3 + error-stack-parser-es: 1.0.5 + ohash: 2.0.11 + open: 10.2.0 + perfect-debounce: 2.1.0 + sirv: 3.0.2 + unplugin-utils: 0.3.1 + vite: 8.1.3(@types/node@24.12.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0) + vite-dev-rpc: 1.1.0(vite@8.1.3) + optionalDependencies: + '@nuxt/kit': 4.4.8(magicast@0.5.3) + transitivePeerDependencies: + - supports-color + vite-plugin-pwa@1.3.0(@vite-pwa/assets-generator@1.0.2)(@voidzero-dev/vite-plus-core@0.2.2)(workbox-build@7.4.0)(workbox-window@7.4.0): dependencies: debug: 4.4.3 @@ -23659,6 +24295,16 @@ snapshots: vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.2)(yaml@2.9.0)' vue: 3.5.39(typescript@6.0.2) + vite-plugin-vue-tracer@1.3.0(vite@8.1.3)(vue@3.5.39): + dependencies: + estree-walker: 3.0.3 + exsolve: 1.0.8 + magic-string: 0.30.21 + pathe: 2.0.3 + source-map-js: 1.2.1 + vite: 8.1.3(@types/node@24.12.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0) + vue: 3.5.39(typescript@6.0.3) + vite-plus@0.2.2(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(@vitest/browser-playwright@4.1.9)(@vitest/coverage-v8@4.1.9)(@voidzero-dev/vite-plus-core@0.2.2)(esbuild@0.28.0)(jiti@2.7.0)(msw@2.13.3)(terser@5.48.0)(typescript@6.0.2)(yaml@2.9.0): dependencies: '@oxc-project/types': 0.138.0 @@ -23718,6 +24364,21 @@ snapshots: - vite - yaml + vite@8.1.3(@types/node@24.12.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0): + dependencies: + lightningcss: 1.32.0 + picomatch: 4.0.5 + postcss: 8.5.16 + rolldown: 1.1.4 + tinyglobby: 0.2.17 + optionalDependencies: + '@types/node': 24.12.0 + esbuild: 0.28.0 + fsevents: 2.3.3 + jiti: 2.7.0 + terser: 5.48.0 + yaml: 2.9.0 + vitest-environment-nuxt@2.0.0(@playwright/test@1.61.1)(@voidzero-dev/vite-plus-core@0.2.2)(@vue/test-utils@2.4.6)(magicast@0.5.3)(playwright-core@1.61.1)(typescript@6.0.2)(vitest@4.1.9): dependencies: '@nuxt/test-utils': 4.0.3(patch_hash=8438d6588e19230d3392ce53e45dd8e9bff54eaa3ce18092602fefd40c2eefe9)(@playwright/test@1.61.1)(@voidzero-dev/vite-plus-core@0.2.2)(@vue/test-utils@2.4.6)(magicast@0.5.3)(playwright-core@1.61.1)(typescript@6.0.2)(vitest@4.1.9) @@ -23803,7 +24464,7 @@ snapshots: vue-demi@0.14.10(vue@3.5.39): dependencies: - vue: 3.5.39(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.3) vue-devtools-stub@0.1.0: {} @@ -23881,6 +24542,16 @@ snapshots: optionalDependencies: typescript: 6.0.2 + vue@3.5.39(typescript@6.0.3): + dependencies: + '@vue/compiler-dom': 3.5.39 + '@vue/compiler-sfc': 3.5.39 + '@vue/runtime-dom': 3.5.39 + '@vue/server-renderer': 3.5.39(vue@3.5.39) + '@vue/shared': 3.5.39 + optionalDependencies: + typescript: 6.0.3 + w3c-keyname@2.2.8: {} walk-up-path@4.0.0: {} diff --git a/scripts/gen-jwk.ts b/scripts/gen-jwk.ts index 39a2740c87..852d32d8af 100644 --- a/scripts/gen-jwk.ts +++ b/scripts/gen-jwk.ts @@ -1,9 +1,8 @@ -import { JoseKey } from '@atproto/oauth-client-node' +import { generateClientAssertionKey } from '@atcute/oauth-node-client' async function run() { const kid = Date.now().toString() - const key = await JoseKey.generate(['ES256'], kid) - const jwk = key.privateJwk + const jwk = await generateClientAssertionKey(kid, 'ES256') console.log(JSON.stringify(jwk)) } diff --git a/server/api/auth/atproto.get.ts b/server/api/auth/atproto.get.ts index 0b58fcc9a1..3af7f571e1 100644 --- a/server/api/auth/atproto.get.ts +++ b/server/api/auth/atproto.get.ts @@ -1,5 +1,5 @@ -import type { OAuthSession } from '@atproto/oauth-client-node' -import { OAuthCallbackError } from '@atproto/oauth-client-node' +import type { AuthorizeTarget, OAuthSession } from '@atcute/oauth-node-client' +import { OAuthCallbackError } from '@atcute/oauth-node-client' import { createError, getQuery, sendRedirect, setCookie, getCookie, deleteCookie } from 'h3' import type { H3Event } from 'h3' import { SLINGSHOT_HOST } from '#shared/utils/constants' @@ -10,14 +10,23 @@ import { Client, isAtUriString, isTypedBlobRef } from '@atproto/lex' import * as app from '#shared/types/lexicons/app' import * as blue from '#shared/types/lexicons/blue' import { isAtIdentifierString } from '@atproto/lex' -import { scope } from '#server/utils/atproto/oauth' +import { sessionAsAgent } from '#server/utils/atproto/oauth' import { UNSET_NUXT_SESSION_PASSWORD } from '#shared/utils/constants' // @ts-expect-error virtual file from oauth module import { clientUri } from '#oauth/config' +import type { ActorIdentifier } from '@atcute/lexicons' +import { isActorIdentifier } from '@atcute/lexicons/syntax' const OAUTH_REQUEST_COOKIE_PREFIX = 'atproto_oauth_req' const slingshotClient = new Client({ service: `https://${SLINGSHOT_HOST}` }) +function isValidTarget(target: unknown): target is `https://${string}` | ActorIdentifier { + return ( + typeof target === 'string' && + (isAtIdentifierString(target) || (URL.canParse(target) && target.startsWith('https://'))) + ) +} + export default defineEventHandler(async event => { const config = useRuntimeConfig(event) if (!config.sessionPassword) { @@ -32,10 +41,7 @@ export default defineEventHandler(async event => { if (query.handle) { // Initiate auth flow - if ( - typeof query.handle !== 'string' || - (!query.handle.startsWith('https://') && !isAtIdentifierString(query.handle)) - ) { + if (!isValidTarget(query.handle)) { throw createError({ statusCode: 400, message: 'Invalid handle parameter', @@ -55,9 +61,13 @@ export default defineEventHandler(async event => { // Invalid URL, fall back to root } + const target: AuthorizeTarget = isActorIdentifier(query.handle) + ? { type: 'account', identifier: query.handle } + : { type: 'pds', serviceUrl: query.handle } + try { - const redirectUrl = await event.context.oauthClient.authorize(query.handle, { - scope, + const { url } = await event.context.oauthClient.authorize({ + target, prompt: query.create ? 'create' : undefined, // TODO: I do not believe this is working as expected on // an unsupported locale on the PDS. Gives Invalid at body.ui_locales @@ -66,7 +76,7 @@ export default defineEventHandler(async event => { state: encodeOAuthState(event, { redirectPath }), }) - return sendRedirect(event, redirectUrl.toString()) + return sendRedirect(event, url.toString()) } catch (error) { const message = error instanceof Error ? error.message : 'Failed to initiate authentication.' @@ -182,8 +192,8 @@ function generateRandomHexString(byteLength: number = 16): string { * @returns The original OAuth state if the id is valid * @throws An error if the id is missing or invalid, indicating a potential issue with cookies or expired state */ -function decodeOAuthState(event: H3Event, state: string | null): OAuthStateData { - if (!state) { +function decodeOAuthState(event: H3Event, state: unknown): OAuthStateData { + if (!state || typeof state !== 'string') { // May happen during transition period (if a user initiated auth flow before // the release with the new state handling, then tries to complete it after // the release). @@ -233,7 +243,7 @@ async function getMiniProfile(authSession: OAuthSession) { if (response.success) { const miniDoc = response.body - let avatar: string | undefined = await getAvatar(authSession.did, miniDoc.pds) + const avatar: string | undefined = await getAvatar(authSession.did, miniDoc.pds) return { ...miniDoc, @@ -242,7 +252,7 @@ async function getMiniProfile(authSession: OAuthSession) { } else { //If slingshot fails we still want to set some key info we need. const pdsBase = (await authSession.getTokenInfo()).aud - let avatar: string | undefined = await getAvatar(authSession.did, pdsBase) + const avatar: string | undefined = await getAvatar(authSession.did, pdsBase) return { did: authSession.did, handle: 'Not available', @@ -285,7 +295,7 @@ async function getAvatar(did: DidString, pds: string) { } async function getNpmxProfile(handle: string, authSession: OAuthSession) { - const client = new Client(authSession) + const client = new Client(sessionAsAgent(authSession)) // get existing npmx profile OR create a new one const profileUri = `at://${client.did}/dev.npmx.actor.profile/self` diff --git a/server/api/social/like.delete.ts b/server/api/social/like.delete.ts index 103d16cca8..ec9b71a2bb 100644 --- a/server/api/social/like.delete.ts +++ b/server/api/social/like.delete.ts @@ -1,5 +1,6 @@ import * as v from 'valibot' import { Client } from '@atproto/lex' +import { sessionAsAgent } from '#server/utils/atproto/oauth' import * as dev from '#shared/types/lexicons/dev' import { PackageLikeBodySchema } from '#shared/schemas/social' import { throwOnMissingOAuthScope } from '#server/utils/atproto/oauth' @@ -11,8 +12,8 @@ export default eventHandlerWithOAuthSession(async (event, oAuthSession) => { throw createError({ statusCode: 401, statusMessage: 'Unauthorized' }) } - //Checks if the user has a scope to like packages - await throwOnMissingOAuthScope(oAuthSession, LIKES_SCOPE) + // Checks if the user has a scope to like packages + await throwOnMissingOAuthScope(oAuthSession, dev.npmx.feed.like.$nsid) const body = v.parse(PackageLikeBodySchema, await readBody(event)) @@ -24,7 +25,7 @@ export default eventHandlerWithOAuthSession(async (event, oAuthSession) => { ) if (getTheUsersLikedRecord) { - const client = new Client(oAuthSession) + const client = new Client(sessionAsAgent(oAuthSession)) await client.delete(dev.npmx.feed.like, { rkey: getTheUsersLikedRecord.rkey, diff --git a/server/api/social/like.post.ts b/server/api/social/like.post.ts index 3bdcf54105..5cdafa0976 100644 --- a/server/api/social/like.post.ts +++ b/server/api/social/like.post.ts @@ -1,8 +1,8 @@ import * as v from 'valibot' import { Client, toDatetimeString } from '@atproto/lex' +import { sessionAsAgent } from '#server/utils/atproto/oauth' import * as dev from '#shared/types/lexicons/dev' import type { UriString } from '@atproto/lex' -import { LIKES_SCOPE } from '#shared/utils/constants' import { PackageLikeBodySchema } from '#shared/schemas/social' import { throwOnMissingOAuthScope } from '#server/utils/atproto/oauth' @@ -13,8 +13,8 @@ export default eventHandlerWithOAuthSession(async (event, oAuthSession) => { throw createError({ statusCode: 401, statusMessage: 'Unauthorized' }) } - //Checks if the user has a scope to like packages - await throwOnMissingOAuthScope(oAuthSession, LIKES_SCOPE) + // Checks if the user has a scope to like packages + await throwOnMissingOAuthScope(oAuthSession, dev.npmx.feed.like.$nsid) const body = v.parse(PackageLikeBodySchema, await readBody(event)) @@ -27,7 +27,7 @@ export default eventHandlerWithOAuthSession(async (event, oAuthSession) => { } const subjectRef = PACKAGE_SUBJECT_REF(body.packageName) - const client = new Client(oAuthSession) + const client = new Client(sessionAsAgent(oAuthSession)) const like = dev.npmx.feed.like.$build({ createdAt: toDatetimeString(new Date()), diff --git a/server/api/social/profile/[identifier]/index.put.ts b/server/api/social/profile/[identifier]/index.put.ts index f71e234d8b..79df38aa2a 100644 --- a/server/api/social/profile/[identifier]/index.put.ts +++ b/server/api/social/profile/[identifier]/index.put.ts @@ -1,5 +1,6 @@ import { parse } from 'valibot' import { Client } from '@atproto/lex' +import { sessionAsAgent } from '#server/utils/atproto/oauth' import * as dev from '#shared/types/lexicons/dev' import type { NPMXProfile } from '#shared/types/social' import { ProfileEditBodySchema } from '#shared/schemas/social' @@ -11,7 +12,7 @@ export default eventHandlerWithOAuthSession(async (event, oAuthSession) => { throw createError({ statusCode: 401, statusMessage: 'Unauthorized' }) } - await throwOnMissingOAuthScope(oAuthSession, PROFILE_SCOPE) + await throwOnMissingOAuthScope(oAuthSession, dev.npmx.actor.profile.$nsid) const requestBody = await readBody(event) if (requestBody.website && !URL.canParse(requestBody.website)) { @@ -19,7 +20,7 @@ export default eventHandlerWithOAuthSession(async (event, oAuthSession) => { } const body = parse(ProfileEditBodySchema, requestBody) - const client = new Client(oAuthSession) + const client = new Client(sessionAsAgent(oAuthSession)) const profile = dev.npmx.actor.profile.$build({ displayName: body.displayName, diff --git a/server/plugins/oauth-client.ts b/server/plugins/oauth-client.ts index 7f888271ba..6bc90792f4 100644 --- a/server/plugins/oauth-client.ts +++ b/server/plugins/oauth-client.ts @@ -1,7 +1,7 @@ -import type { NodeOAuthClient } from '@atproto/oauth-client-node' +import type { OAuthClient } from '@atcute/oauth-node-client' /** - * Creates a long living instance of the NodeOAuthClient. + * Creates a long living instance of the OAuthClient. */ export default defineNitroPlugin(async nitroApp => { const oauthClient = await getNodeOAuthClient() @@ -15,6 +15,6 @@ export default defineNitroPlugin(async nitroApp => { // Extend the H3EventContext type declare module 'h3' { interface H3EventContext { - oauthClient: NodeOAuthClient + oauthClient: OAuthClient } } diff --git a/server/routes/.well-known/jwks.json.get.ts b/server/routes/.well-known/jwks.json.get.ts index f7c2eda628..ef7921914a 100644 --- a/server/routes/.well-known/jwks.json.get.ts +++ b/server/routes/.well-known/jwks.json.get.ts @@ -1,11 +1,8 @@ -import { loadJWKs } from '#server/utils/atproto/oauth' - -export default defineEventHandler(async _ => { - const keys = await loadJWKs() - if (!keys) { - console.error('Failed to load JWKs. May not be set') - return [] +export default defineEventHandler(event => { + const jwks = event.context.oauthClient.jwks + if (!jwks) { + console.error('JWKS not configured (running as public client)') + return { keys: [] } } - - return keys.publicJwks + return jwks }) diff --git a/server/routes/oauth-client-metadata.json.get.ts b/server/routes/oauth-client-metadata.json.get.ts index 60706d617e..f57db77f02 100644 --- a/server/routes/oauth-client-metadata.json.get.ts +++ b/server/routes/oauth-client-metadata.json.get.ts @@ -1,5 +1,3 @@ -export default defineEventHandler(async _ => { - const keyset = await loadJWKs() - const pk = keyset?.findPrivateKey({ usage: 'sign' }) - return getOauthClientMetadata(pk?.alg) +export default defineEventHandler(event => { + return event.context.oauthClient.metadata }) diff --git a/server/utils/atproto/lock.ts b/server/utils/atproto/lock.ts index b91a1ac812..a6b0f51e39 100644 --- a/server/utils/atproto/lock.ts +++ b/server/utils/atproto/lock.ts @@ -1,16 +1,13 @@ import { setTimeout } from 'node:timers/promises' -import type { RuntimeLock } from '@atproto/oauth-client-node' -import { requestLocalLock } from '@atproto/oauth-client-node' +import type { LockFunction } from '@atcute/oauth-node-client' import { Redis } from '@upstash/redis' -type Awaitable = T | PromiseLike - /** * Creates a distributed lock using Upstash Redis. * Falls back gracefully if the lock cannot be acquired. */ -function createUpstashLock(redis: Redis): RuntimeLock { - return async (key: string, fn: () => Awaitable): Promise => { +function createUpstashLock(redis: Redis): LockFunction { + return async (key: string, fn: () => Promise): Promise => { const lockKey = `oauth:lock:${key}` const lockValue = crypto.randomUUID() const lockTTL = 30 // seconds @@ -50,9 +47,9 @@ function createUpstashLock(redis: Redis): RuntimeLock { /** * Returns the appropriate lock mechanism based on environment: * - Production with Upstash config: distributed Redis lock - * - Otherwise: in-memory lock (sufficient for single instance) + * - Otherwise: undefined (OAuthClient uses its own in-memory lock by default) */ -export function getOAuthLock(): RuntimeLock { +export function getOAuthLock(): LockFunction | undefined { const config = useRuntimeConfig() // Use distributed lock in production if Upstash is configured @@ -64,6 +61,6 @@ export function getOAuthLock(): RuntimeLock { return createUpstashLock(redis) } - // Fall back to in-memory lock for dev/preview or when Redis isn't configured - return requestLocalLock + // Fall back to undefined for dev/preview — OAuthClient defaults to in-memory lock + return undefined } diff --git a/server/utils/atproto/oauth-session-store.ts b/server/utils/atproto/oauth-session-store.ts index 9bdc52f054..5b511dbc93 100644 --- a/server/utils/atproto/oauth-session-store.ts +++ b/server/utils/atproto/oauth-session-store.ts @@ -1,4 +1,4 @@ -import type { NodeSavedSession, NodeSavedSessionStore } from '@atproto/oauth-client-node' +import type { SessionStore, StoredSession } from '@atcute/oauth-node-client' import { OAUTH_CACHE_STORAGE_BASE } from '#server/utils/atproto/storage' // Refresh tokens from a confidential client should last for 180 days, each new refresh of access token resets @@ -6,7 +6,7 @@ import { OAUTH_CACHE_STORAGE_BASE } from '#server/utils/atproto/storage' // Note: This expiration only lasts this long in production. Local dev is 2 weeks const SESSION_EXPIRATION = CACHE_MAX_AGE_ONE_DAY * 179 -export class OAuthSessionStore implements NodeSavedSessionStore { +export class OAuthSessionStore implements SessionStore { private readonly cache: CacheAdapter constructor() { @@ -17,16 +17,20 @@ export class OAuthSessionStore implements NodeSavedSessionStore { return `sessions:${did}` } - async get(key: string): Promise { - let session = await this.cache.get(this.createStorageKey(key)) + async get(key: string): Promise { + const session = await this.cache.get(this.createStorageKey(key)) return session ?? undefined } - async set(key: string, val: NodeSavedSession) { - await this.cache.set(this.createStorageKey(key), val, SESSION_EXPIRATION) + async set(key: string, val: StoredSession) { + await this.cache.set(this.createStorageKey(key), val, SESSION_EXPIRATION) } - async del(key: string) { + async delete(key: string) { await this.cache.delete(this.createStorageKey(key)) } + + async clear() { + // Cache adapter does not expose bulk-clear; individual sessions expire via TTL + } } diff --git a/server/utils/atproto/oauth-state-store.ts b/server/utils/atproto/oauth-state-store.ts index b04da8ff8c..ae4b85858f 100644 --- a/server/utils/atproto/oauth-state-store.ts +++ b/server/utils/atproto/oauth-state-store.ts @@ -1,10 +1,10 @@ -import type { NodeSavedState, NodeSavedStateStore } from '@atproto/oauth-client-node' +import type { StateStore, StoredState } from '@atcute/oauth-node-client' import { OAUTH_CACHE_STORAGE_BASE } from './storage' // It is recommended that oauth state is only saved for 30 minutes const STATE_EXPIRATION = CACHE_MAX_AGE_ONE_MINUTE * 30 -export class OAuthStateStore implements NodeSavedStateStore { +export class OAuthStateStore implements StateStore { private readonly cache: CacheAdapter constructor() { @@ -15,16 +15,20 @@ export class OAuthStateStore implements NodeSavedStateStore { return `state:${key}` } - async get(key: string): Promise { - const state = await this.cache.get(this.createStorageKey(key)) + async get(key: string): Promise { + const state = await this.cache.get(this.createStorageKey(key)) return state ?? undefined } - async set(key: string, val: NodeSavedState) { - await this.cache.set(this.createStorageKey(key), val, STATE_EXPIRATION) + async set(key: string, val: StoredState) { + await this.cache.set(this.createStorageKey(key), val, STATE_EXPIRATION) } - async del(key: string) { + async delete(key: string) { await this.cache.delete(this.createStorageKey(key)) } + + async clear() { + // Cache adapter does not expose bulk-clear; individual states expire via TTL + } } diff --git a/server/utils/atproto/oauth.ts b/server/utils/atproto/oauth.ts index ae9ba489d2..b195be23b0 100644 --- a/server/utils/atproto/oauth.ts +++ b/server/utils/atproto/oauth.ts @@ -1,63 +1,42 @@ -import type { - OAuthClientMetadata, - OAuthRedirectUri, - OAuthSession, - WebUri, -} from '@atproto/oauth-client-node' -import { JoseKey, Keyset, oauthRedirectUriSchema, webUriSchema } from '@atproto/oauth-client-node' +import { + scope, + OAuthClient, + type OAuthSession, + type ClientAssertionPrivateJwk, +} from '@atcute/oauth-node-client' +import { + LocalActorResolver, + CompositeHandleResolver, + CompositeDidDocumentResolver, + PlcDidDocumentResolver, + WebDidDocumentResolver, + DohJsonHandleResolver, +} from '@atcute/identity-resolver' +import { NodeDnsHandleResolver } from '@atcute/identity-resolver-node' +import type { Agent } from '@atproto/lex' import type { EventHandlerRequest, H3Event, SessionManager } from 'h3' -import { NodeOAuthClient, AtprotoDohHandleResolver } from '@atproto/oauth-client-node' import { getOAuthLock } from '#server/utils/atproto/lock' import { useOAuthStorage } from '#server/utils/atproto/storage' -import { LIKES_SCOPE, PROFILE_SCOPE } from '#shared/utils/constants' import type { UserServerSession } from '#shared/types/userSession' // @ts-expect-error virtual file from oauth module import { clientUri } from '#oauth/config' +import * as dev from '#shared/types/lexicons/dev' -// TODO: If you add writing a new record you will need to add a scope for it -export const scope = `atproto ${LIKES_SCOPE} ${PROFILE_SCOPE}` +const SCOPES = [ + scope.repo({ + collection: [dev.npmx.feed.like.$nsid, dev.npmx.actor.profile.$nsid], + action: ['create', 'update', 'delete'], + }), +] /** - * Resolves a did to a handle via DoH or via the http website calls + * Creates an @atproto/lex-compatible Agent from an atcute OAuthSession. + * Required for compatibility while @atproto/lex is still in use. */ -export const handleResolver = new AtprotoDohHandleResolver({ - dohEndpoint: 'https://cloudflare-dns.com/dns-query', -}) - -/** - * Generates the OAuth client metadata. pkAlg is used to signify that the OAuth client is confidential - */ -export function getOauthClientMetadata(pkAlg: string | undefined = undefined): OAuthClientMetadata { - const redirect_uri: OAuthRedirectUri = oauthRedirectUriSchema.parse( - `${clientUri}/api/auth/atproto`, - ) - - const client_id = - import.meta.dev || import.meta.test - ? `http://localhost?redirect_uri=${encodeURIComponent(redirect_uri)}&scope=${encodeURIComponent(scope)}` - : `${clientUri}/oauth-client-metadata.json` - - const jwks_uri: WebUri | undefined = pkAlg - ? webUriSchema.parse(`${clientUri}/.well-known/jwks.json`) - : undefined - +export function sessionAsAgent(session: OAuthSession): Agent { return { - client_name: 'npmx.dev', - client_id, - client_uri: clientUri, - logo_uri: webUriSchema.parse(`${clientUri}/logo-icon.svg`), - scope, - redirect_uris: [redirect_uri], - grant_types: ['authorization_code', 'refresh_token'], - application_type: 'web', - dpop_bound_access_tokens: true, - response_types: ['code'], - subject_type: 'public', - authorization_signed_response_alg: 'RS256', - // confidential client values - token_endpoint_auth_method: pkAlg ? 'private_key_jwt' : 'none', - jwks_uri, - token_endpoint_auth_signing_alg: pkAlg, + did: session.did, + fetchHandler: (path, init) => session.handle(path, init), } } @@ -67,35 +46,65 @@ type EventHandlerWithOAuthSession = ( serverSession: SessionManager, ) => Promise -export async function getNodeOAuthClient(): Promise { - const { stateStore, sessionStore } = useOAuthStorage() - - // These are optional and not expected or can be used easily in local development, only in production +export async function getNodeOAuthClient(): Promise { + const { sessions, states } = useOAuthStorage() const keyset = await loadJWKs() - const pk = keyset?.findPrivateKey({ usage: 'sign' }) - const clientMetadata = getOauthClientMetadata(pk?.alg) + const stores = { sessions, states } + const requestLock = getOAuthLock() + const redirectUri = new URL('/api/auth/atproto', clientUri).toString() + + const actorResolver = new LocalActorResolver({ + handleResolver: new CompositeHandleResolver({ + strategy: 'race', + methods: { + dns: new NodeDnsHandleResolver(), + http: new DohJsonHandleResolver({ dohUrl: 'https://cloudflare-dns.com/dns-query' }), + }, + }), + didDocumentResolver: new CompositeDidDocumentResolver({ + methods: { + plc: new PlcDidDocumentResolver(), + web: new WebDidDocumentResolver(), + }, + }), + }) + + if (keyset) { + return new OAuthClient({ + metadata: { + client_id: `${clientUri}/oauth-client-metadata.json`, + redirect_uris: [redirectUri], + client_name: 'npmx.dev', + client_uri: clientUri, + logo_uri: `${clientUri}/logo-icon.svg`, + jwks_uri: `${clientUri}/.well-known/jwks.json`, + scope: SCOPES, + }, + keyset, + stores, + requestLock, + actorResolver, + }) + } - return new NodeOAuthClient({ - stateStore, - sessionStore, - clientMetadata, - requestLock: getOAuthLock(), - handleResolver, - keyset, + return new OAuthClient({ + metadata: { + redirect_uris: [redirectUri], + scope: SCOPES, + }, + stores, + requestLock, + actorResolver, }) } -export async function loadJWKs(): Promise { +export async function loadJWKs(): Promise { // If we ever need to add multiple JWKs to rotate keys we will need to add a new one // under a new variable and update here const jwkOne = useRuntimeConfig().oauthJwkOne if (!jwkOne) return undefined - // For multiple keys if we need to rotate - // const keys = await Promise.all([JoseKey.fromImportable(jwkOne)]) - - const keys = await JoseKey.fromImportable(jwkOne) - return new Keyset([keys]) + return [JSON.parse(jwkOne) as ClientAssertionPrivateJwk] } async function getOAuthSession(event: H3Event): Promise<{ @@ -114,8 +123,6 @@ async function getOAuthSession(event: H3Event): Promise<{ const oauthSession = await event.context.oauthClient.restore(currentSession.public.did) return { oauthSession, serverSession } } catch (error) { - // Log error safely without using util.inspect on potentially problematic objects - // The @atproto library creates error objects with getters that crash Node's util.inspect // eslint-disable-next-line no-console console.error( '[oauth] Failed to get session:', @@ -129,6 +136,9 @@ async function getOAuthSession(event: H3Event): Promise<{ * Throws if the logged in OAuth Session does not have the required scopes. * As we add new scopes we need to check if the client has the ability to use it. * If not need to let the client know to redirect the user to the PDS to upgrade their scopes. + * + * @todo should do a more thorough check by parsing scopes + * * @param oAuthSession - The current OAuth session from the event * @param requiredScopes - The required scope you are checking if you can use */ diff --git a/server/utils/atproto/storage.ts b/server/utils/atproto/storage.ts index a62c9ceb71..99549af9ce 100644 --- a/server/utils/atproto/storage.ts +++ b/server/utils/atproto/storage.ts @@ -5,7 +5,7 @@ export const OAUTH_CACHE_STORAGE_BASE = 'atproto:oauth' export const useOAuthStorage = () => { return { - stateStore: new OAuthStateStore(), - sessionStore: new OAuthSessionStore(), + sessions: new OAuthSessionStore(), + states: new OAuthStateStore(), } } diff --git a/shared/types/userSession.ts b/shared/types/userSession.ts index 53bb09d71e..5f2724fa85 100644 --- a/shared/types/userSession.ts +++ b/shared/types/userSession.ts @@ -1,9 +1,9 @@ -import type { NodeSavedSession } from '@atproto/oauth-client-node' +import type { Did } from '@atcute/lexicons' export interface UserServerSession { public?: | { - did: string + did: Did handle: string pds: string avatar?: string @@ -19,5 +19,5 @@ export interface UserServerSession { // DO NOT USE // Here for historic reasons to redirect users logged in with the previous oauth to login again - oauthSession?: NodeSavedSession | undefined + oauthSession?: unknown } diff --git a/shared/utils/constants.ts b/shared/utils/constants.ts index 955cfe76ce..417470188a 100644 --- a/shared/utils/constants.ts +++ b/shared/utils/constants.ts @@ -1,5 +1,3 @@ -import * as dev from '../types/lexicons/dev' - // Duration export const CACHE_MAX_AGE_ONE_MINUTE = 60 export const CACHE_MAX_AGE_FIVE_MINUTES = 60 * 5 @@ -63,8 +61,6 @@ export const SLINGSHOT_HOST = 'slingshot.microcosm.blue' export const PACKAGE_SUBJECT_REF = (packageName: string) => `https://npmx.dev/package/${packageName}` // OAuth scopes as we add new ones we need to check these on certain actions. If not redirect the user to login again to upgrade the scopes -export const LIKES_SCOPE = `repo:${dev.npmx.feed.like.$nsid}` -export const PROFILE_SCOPE = `repo:${dev.npmx.actor.profile.$nsid}` export const NPMX_DEV_DID = 'did:plc:u5zp7npt5kpueado77kuihyz' export const TID_CLOCK_ID = 3 diff --git a/test/unit/server/utils/atproto/lock.spec.ts b/test/unit/server/utils/atproto/lock.spec.ts index 0cf6abb037..1c47bdf30e 100644 --- a/test/unit/server/utils/atproto/lock.spec.ts +++ b/test/unit/server/utils/atproto/lock.spec.ts @@ -13,11 +13,6 @@ vi.mock('@upstash/redis', () => ({ }, })) -const mockLocalLock = vi.fn() -vi.mock('@atproto/oauth-client-node', () => ({ - requestLocalLock: mockLocalLock, -})) - const mockConfig = { upstash: { redisRestUrl: '', @@ -44,28 +39,28 @@ describe('lock', () => { mockConfig.upstash.redisRestToken = '' }) - it('returns local lock when upstash is not configured', () => { + it('returns undefined when upstash is not configured', () => { const lock = getOAuthLock() - expect(lock).toBe(mockLocalLock) + expect(lock).toBeUndefined() }) - it('returns local lock when only redisRestUrl is set', () => { + it('returns undefined when only redisRestUrl is set', () => { mockConfig.upstash.redisRestUrl = 'https://totally-a-redis-server.com' const lock = getOAuthLock() - expect(lock).toBe(mockLocalLock) + expect(lock).toBeUndefined() }) - it('returns local lock when only redisRestToken is set', () => { + it('returns undefined when only redisRestToken is set', () => { mockConfig.upstash.redisRestToken = 'super-fancy-secret-token' const lock = getOAuthLock() - expect(lock).toBe(mockLocalLock) + expect(lock).toBeUndefined() }) it('returns upstash lock when both url and token are configured', () => { mockConfig.upstash.redisRestUrl = 'https://redis.redis.redis' mockConfig.upstash.redisRestToken = 'token-123' const lock = getOAuthLock() - expect(lock).not.toBe(mockLocalLock) + expect(lock).not.toBeUndefined() expect(typeof lock).toBe('function') }) @@ -75,7 +70,7 @@ describe('lock', () => { mockRedisDel.mockResolvedValueOnce(1) const lock = getUpstashLock() - const result = await lock('test-key', () => 'hello') + const result = await lock!('test-key', () => Promise.resolve('hello')) expect(result).toBe('hello') expect(mockRedisSet).toHaveBeenCalledOnce() @@ -94,7 +89,7 @@ describe('lock', () => { mockRedisDel.mockResolvedValueOnce(1) const lock = getUpstashLock() - const result = await lock('retry-key', () => 42) + const result = await lock!('retry-key', () => Promise.resolve(42)) expect(result).toBe(42) expect(mockRedisSet).toHaveBeenCalledTimes(2) @@ -105,7 +100,7 @@ describe('lock', () => { mockRedisSet.mockResolvedValueOnce(null).mockResolvedValueOnce(null) const lock = getUpstashLock() - const result = await lock('no-lock-key', () => 'fallback') + const result = await lock!('no-lock-key', () => Promise.resolve('fallback')) expect(result).toBe('fallback') expect(mockRedisSet).toHaveBeenCalledTimes(2) @@ -118,7 +113,7 @@ describe('lock', () => { mockRedisGet.mockResolvedValueOnce('some-other-uuid') const lock = getUpstashLock() - await lock('stolen-key', () => 'done') + await lock!('stolen-key', () => Promise.resolve('done')) expect(mockRedisGet).toHaveBeenCalledWith('oauth:lock:stolen-key') expect(mockRedisDel).not.toHaveBeenCalled() @@ -131,7 +126,7 @@ describe('lock', () => { const lock = getUpstashLock() await expect( - lock('error-key', () => { + lock!('error-key', () => { throw new Error('boom') }), ).rejects.toThrow('boom') @@ -145,7 +140,7 @@ describe('lock', () => { mockRedisDel.mockResolvedValueOnce(1) const lock = getUpstashLock() - const result = await lock('async-key', async () => { + const result = await lock!('async-key', async () => { await setTimeout(10) return 'async-result' })