From e17cc71548b03c50c75a7f11a1f832e7c50e82a5 Mon Sep 17 00:00:00 2001 From: Nico Domino Date: Sat, 11 May 2024 14:25:20 +0200 Subject: [PATCH] feat(sveltekit): webauthn provider support (#9924) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Balázs Orbán Co-authored-by: Vishal Kashi Co-authored-by: Gustavo Maronato Co-authored-by: Gustavo Maronato --- apps/dev/sveltekit/.gitignore | 1 + apps/dev/sveltekit/package.json | 3 +- apps/dev/sveltekit/src/auth.ts | 15 +- .../src/routes/signin/+page.server.ts | 2 +- .../src/routes/signout/+page.server.ts | 2 +- apps/dev/sveltekit/vite.config.js | 8 +- .../getting-started/providers/passkey.mdx | 5 +- packages/core/src/types.ts | 2 + packages/frameworks-sveltekit/package.json | 18 + .../frameworks-sveltekit/src/lib/client.ts | 10 +- .../frameworks-sveltekit/src/lib/types.ts | 4 + .../frameworks-sveltekit/src/lib/webauthn.ts | 118 ++++++ packages/next-auth/src/webauthn.ts | 2 +- pnpm-lock.yaml | 371 +++++++++++++++++- 14 files changed, 532 insertions(+), 29 deletions(-) create mode 100644 packages/frameworks-sveltekit/src/lib/webauthn.ts diff --git a/apps/dev/sveltekit/.gitignore b/apps/dev/sveltekit/.gitignore index 8f6c617ecf..84a23ae879 100644 --- a/apps/dev/sveltekit/.gitignore +++ b/apps/dev/sveltekit/.gitignore @@ -10,3 +10,4 @@ node_modules .output vite.config.js.timestamp-* vite.config.ts.timestamp-* +tmp-unstorage diff --git a/apps/dev/sveltekit/package.json b/apps/dev/sveltekit/package.json index e07561ee1d..041ab51f08 100644 --- a/apps/dev/sveltekit/package.json +++ b/apps/dev/sveltekit/package.json @@ -21,8 +21,7 @@ "dependencies": { "@auth/sveltekit": "workspace:*", "@auth/unstorage-adapter": "workspace:*", - "nodemailer": "^6.9.3", - "unstorage": "^1.10.1" + "unstorage": "^1.10.2" }, "type": "module" } diff --git a/apps/dev/sveltekit/src/auth.ts b/apps/dev/sveltekit/src/auth.ts index 8a2c83c2d3..89d1aa900d 100644 --- a/apps/dev/sveltekit/src/auth.ts +++ b/apps/dev/sveltekit/src/auth.ts @@ -4,15 +4,21 @@ import Credentials from "@auth/sveltekit/providers/credentials" import Facebook from "@auth/sveltekit/providers/facebook" import Discord from "@auth/sveltekit/providers/discord" import Google from "@auth/sveltekit/providers/google" +import Passkey from "@auth/sveltekit/providers/passkey" import { createStorage } from "unstorage" import { UnstorageAdapter } from "@auth/unstorage-adapter" +import fsDriver from "unstorage/drivers/fs" +import { dev } from "$app/environment" + +const storage = createStorage({ + driver: fsDriver({ base: "./tmp-unstorage" }), +}) -const storage = createStorage() export const { handle, signIn, signOut } = SvelteKitAuth({ - debug: true, + debug: dev ? true : false, adapter: UnstorageAdapter(storage), - session: { - strategy: "jwt", + experimental: { + enableWebAuthn: true, }, providers: [ Credentials({ @@ -31,6 +37,7 @@ export const { handle, signIn, signOut } = SvelteKitAuth({ Google, Facebook, Discord, + Passkey, ], theme: { logo: "https://authjs.dev/img/logo-sm.png", diff --git a/apps/dev/sveltekit/src/routes/signin/+page.server.ts b/apps/dev/sveltekit/src/routes/signin/+page.server.ts index 915d6bec6f..5469b19b22 100644 --- a/apps/dev/sveltekit/src/routes/signin/+page.server.ts +++ b/apps/dev/sveltekit/src/routes/signin/+page.server.ts @@ -1,4 +1,4 @@ -import { signIn } from "../../auth" +import { signIn } from "$/auth" import type { Actions } from "./$types" export const actions = { default: signIn } satisfies Actions diff --git a/apps/dev/sveltekit/src/routes/signout/+page.server.ts b/apps/dev/sveltekit/src/routes/signout/+page.server.ts index 1bc8b77279..70ea3de935 100644 --- a/apps/dev/sveltekit/src/routes/signout/+page.server.ts +++ b/apps/dev/sveltekit/src/routes/signout/+page.server.ts @@ -1,4 +1,4 @@ -import { signOut } from "../../auth" +import { signOut } from "$/auth" import type { Actions } from "./$types" export const actions = { default: signOut } satisfies Actions diff --git a/apps/dev/sveltekit/vite.config.js b/apps/dev/sveltekit/vite.config.js index 58eb2bf3b5..f73de7976d 100644 --- a/apps/dev/sveltekit/vite.config.js +++ b/apps/dev/sveltekit/vite.config.js @@ -1,11 +1,9 @@ +import { defineConfig } from "vite" import { sveltekit } from "@sveltejs/kit/vite" -/** @type {import('vite').UserConfig} */ -const config = { +export default defineConfig({ server: { port: 3000, }, plugins: [sveltekit()], -} - -export default config +}) diff --git a/docs/pages/getting-started/providers/passkey.mdx b/docs/pages/getting-started/providers/passkey.mdx index f7f7019689..7a11cb44b2 100644 --- a/docs/pages/getting-started/providers/passkey.mdx +++ b/docs/pages/getting-started/providers/passkey.mdx @@ -17,9 +17,10 @@ as any database adapter that plans to support it. Therefore, the WebAuthn provid is currently only supported in the following framework integration and database adapters. Support for more frameworks and adapters are coming soon.{" "} -- `next-auth@5.0.0-beta.9` or above +- `next-auth@5.0.0-beta.17` or above +- `@auth/sveltekit@1.0.2` or above - `@auth/prisma-adapter@1.3.3` or above -- `@prisma/client@5.9.1` or above +- `@prisma/client@5.12.0` or above ### Install peer dependencies diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 88d8465d7e..11bd474849 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -73,6 +73,8 @@ import type { WebAuthnProviderType, } from "./providers/webauthn.js" +export type { WebAuthnOptionsResponseBody } from "./lib/utils/webauthn-utils.js" +export type { AuthConfig } from "./index.js" export type { LoggerInstance } export type Awaitable = T | PromiseLike export type Awaited = T extends Promise ? U : T diff --git a/packages/frameworks-sveltekit/package.json b/packages/frameworks-sveltekit/package.json index 0bab20a81b..132ebebdad 100644 --- a/packages/frameworks-sveltekit/package.json +++ b/packages/frameworks-sveltekit/package.json @@ -50,9 +50,23 @@ "set-cookie-parser": "^2.6.0" }, "peerDependencies": { + "@simplewebauthn/browser": "^9.0.1", + "@simplewebauthn/server": "^9.0.3", "@sveltejs/kit": "^1.0.0 || ^2.0.0", + "nodemailer": "^6.6.5", "svelte": "^3.54.0 || ^4.0.0 || ^5" }, + "peerDependenciesMeta": { + "@simplewebauthn/browser": { + "optional": true + }, + "@simplewebauthn/server": { + "optional": true + }, + "nodemailer": { + "optional": true + } + }, "type": "module", "types": "./dist/index.d.ts", "files": [ @@ -68,6 +82,10 @@ "types": "./dist/client.d.ts", "import": "./dist/client.js" }, + "./webauthn": { + "types": "./dist/webauthn.d.ts", + "import": "./dist/webauthn.js" + }, "./components": { "types": "./dist/components/index.d.ts", "svelte": "./dist/components/index.js" diff --git a/packages/frameworks-sveltekit/src/lib/client.ts b/packages/frameworks-sveltekit/src/lib/client.ts index 258120e3c2..830c39972b 100644 --- a/packages/frameworks-sveltekit/src/lib/client.ts +++ b/packages/frameworks-sveltekit/src/lib/client.ts @@ -1,12 +1,14 @@ +import { base } from "$app/paths" import type { BuiltInProviderType, RedirectableProviderType, } from "@auth/core/providers" -import { base } from "$app/paths" +import type { LiteralUnion } from "./types.js" -type LiteralUnion = T | (U & Record) - -interface SignInOptions extends Record { +/* + * @internal + */ +export interface SignInOptions extends Record { /** * Specify to which URL the user will be redirected after signing in. Defaults to the page URL the sign-in is initiated from. * diff --git a/packages/frameworks-sveltekit/src/lib/types.ts b/packages/frameworks-sveltekit/src/lib/types.ts index 742fe88e51..a1cfdff1d8 100644 --- a/packages/frameworks-sveltekit/src/lib/types.ts +++ b/packages/frameworks-sveltekit/src/lib/types.ts @@ -2,6 +2,10 @@ import type { AuthConfig } from "@auth/core" import type { BuiltInProviderType } from "@auth/core/providers" import type { Session } from "@auth/core/types" +export type LiteralUnion = + | T + | (U & Record) + /** Configure the {@link SvelteKitAuth} method. */ export interface SvelteKitAuthConfig extends Omit {} diff --git a/packages/frameworks-sveltekit/src/lib/webauthn.ts b/packages/frameworks-sveltekit/src/lib/webauthn.ts new file mode 100644 index 0000000000..df5c6224b3 --- /dev/null +++ b/packages/frameworks-sveltekit/src/lib/webauthn.ts @@ -0,0 +1,118 @@ +import { base } from "$app/paths" +import { startAuthentication, startRegistration } from "@simplewebauthn/browser" + +import type { + BuiltInProviderType, + RedirectableProviderType, +} from "@auth/core/providers" +import type { WebAuthnOptionsResponseBody } from "@auth/core/types" +import type { SignInOptions, SignInAuthorizationParams } from "./client.js" +import type { LiteralUnion } from "./types.js" + +/** + * Fetch webauthn options from server and prompt user for authentication or registration. + * Returns either the completed WebAuthn response or an error request. + * + * @param providerId provider ID + * @param options SignInOptions + * @returns WebAuthn response or error + */ +async function webAuthnOptions(providerId: string, options?: SignInOptions) { + const baseUrl = `${base}/auth/` + + // @ts-expect-error + const params = new URLSearchParams(options) + + const optionsResp = await fetch( + `${baseUrl}/webauthn-options/${providerId}?${params}` + ) + if (!optionsResp.ok) { + return { error: optionsResp } + } + const optionsData: WebAuthnOptionsResponseBody = await optionsResp.json() + + if (optionsData.action === "authenticate") { + const webAuthnResponse = await startAuthentication(optionsData.options) + return { data: webAuthnResponse, action: "authenticate" } + } else { + const webAuthnResponse = await startRegistration(optionsData.options) + return { data: webAuthnResponse, action: "register" } + } +} + +/** + * Client-side method to initiate a webauthn signin flow + * or send the user to the signin page listing all possible providers. + * Automatically adds the CSRF token to the request. + * + * [Documentation](https://authjs.dev/reference/sveltekit/client#signin) + */ +export async function signIn< + P extends RedirectableProviderType | undefined = undefined, +>( + providerId?: LiteralUnion< + P extends RedirectableProviderType + ? P | BuiltInProviderType + : BuiltInProviderType + >, + options?: SignInOptions, + authorizationParams?: SignInAuthorizationParams +) { + const { callbackUrl = window.location.href, redirect = true } = options ?? {} + + // TODO: Support custom providers + const isCredentials = providerId === "credentials" + const isEmail = providerId === "email" + const isWebAuthn = providerId === "webauthn" + const isSupportingReturn = isCredentials || isEmail || isWebAuthn + + const basePath = base ?? "" + const signInUrl = `${basePath}/auth/${ + isCredentials || isWebAuthn ? "callback" : "signin" + }/${providerId}` + + const _signInUrl = `${signInUrl}?${new URLSearchParams(authorizationParams)}` + + // Execute WebAuthn client flow if needed + const webAuthnBody: Record = {} + if (isWebAuthn) { + const { data, error, action } = await webAuthnOptions(providerId, options) + if (error) { + // logger.error(new Error(await error.text())) + return + } + webAuthnBody.data = JSON.stringify(data) + webAuthnBody.action = action + } + + // TODO: Remove this since Sveltekit offers the CSRF protection via origin check + const csrfTokenResponse = await fetch(`${basePath}/auth/csrf`) + const { csrfToken } = await csrfTokenResponse.json() + + const res = await fetch(_signInUrl, { + method: "post", + headers: { + "Content-Type": "application/x-www-form-urlencoded", + "X-Auth-Return-Redirect": "1", + }, + // @ts-ignore + body: new URLSearchParams({ + ...options, + csrfToken, + callbackUrl, + ...webAuthnBody, + }), + }) + + const data = await res.clone().json() + + if (redirect || !isSupportingReturn) { + // TODO: Do not redirect for Credentials and Email providers by default in next major + window.location.href = data.url ?? callbackUrl + // If url contains a hash, the browser does not reload the page. We reload manually + if (data.url.includes("#")) window.location.reload() + return + } + + return res +} diff --git a/packages/next-auth/src/webauthn.ts b/packages/next-auth/src/webauthn.ts index f719b66bff..54f7a1af6b 100644 --- a/packages/next-auth/src/webauthn.ts +++ b/packages/next-auth/src/webauthn.ts @@ -3,7 +3,7 @@ import { startAuthentication, startRegistration } from "@simplewebauthn/browser" import { getCsrfToken, getProviders, __NEXTAUTH } from "./react.js" import type { LoggerInstance } from "@auth/core/types" -import type { WebAuthnOptionsResponseBody } from "@auth/core/lib/utils/webauthn-utils" +import type { WebAuthnOptionsResponseBody } from "@auth/core/types" import type { BuiltInProviderType, RedirectableProviderType, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 728df7f3cf..b869d6824f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -180,12 +180,9 @@ importers: '@auth/unstorage-adapter': specifier: workspace:* version: link:../../../packages/adapter-unstorage - nodemailer: - specifier: ^6.9.3 - version: 6.9.8 unstorage: - specifier: ^1.10.1 - version: 1.10.1(@azure/data-tables@13.2.2)(@azure/identity@1.5.2)(@upstash/redis@1.28.2) + specifier: ^1.10.2 + version: 1.10.2(@azure/data-tables@13.2.2)(@azure/identity@1.5.2)(@upstash/redis@1.28.2)(ioredis@5.4.1) devDependencies: '@sveltejs/adapter-auto': specifier: next @@ -720,6 +717,15 @@ importers: '@auth/core': specifier: workspace:* version: link:../core + '@simplewebauthn/browser': + specifier: ^9.0.1 + version: 9.0.1 + '@simplewebauthn/server': + specifier: ^9.0.3 + version: 9.0.3(encoding@0.1.13) + nodemailer: + specifier: ^6.6.5 + version: 6.9.8 set-cookie-parser: specifier: ^2.6.0 version: 2.6.0 @@ -2921,6 +2927,9 @@ packages: '@kamilkisiela/fast-url-parser@1.1.4': resolution: {integrity: sha512-gbkePEBupNydxCelHCESvFSFM8XPh1Zs/OAVRW/rKpEqPAl5PbOM90Si8mv9bvnR53uPD2s/FiRxdvSejpRJew==} + '@levischuck/tiny-cbor@0.2.2': + resolution: {integrity: sha512-f5CnPw997Y2GQ8FAvtuVVC19FX8mwNNC+1XJcIi16n/LTJifKO6QBgGLgN3YEmqtGMk17SKSuoWES3imJVxAVw==} + '@libsql/client@0.6.0': resolution: {integrity: sha512-qhQzTG/y2IEVbL3+9PULDvlQFWJ/RnjFXECr/Nc3nRngGiiMysDaOV5VUzYk7DulUX98EA4wi+z3FspKrUplUA==} @@ -3475,82 +3484,164 @@ packages: cpu: [arm64] os: [android] + '@parcel/watcher-android-arm64@2.4.1': + resolution: {integrity: sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [android] + '@parcel/watcher-darwin-arm64@2.4.0': resolution: {integrity: sha512-T/At5pansFuQ8VJLRx0C6C87cgfqIYhW2N/kBfLCUvDhCah0EnLLwaD/6MW3ux+rpgkpQAnMELOCTKlbwncwiA==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [darwin] + '@parcel/watcher-darwin-arm64@2.4.1': + resolution: {integrity: sha512-ln41eihm5YXIY043vBrrHfn94SIBlqOWmoROhsMVTSXGh0QahKGy77tfEywQ7v3NywyxBBkGIfrWRHm0hsKtzA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [darwin] + '@parcel/watcher-darwin-x64@2.4.0': resolution: {integrity: sha512-vZMv9jl+szz5YLsSqEGCMSllBl1gU1snfbRL5ysJU03MEa6gkVy9OMcvXV1j4g0++jHEcvzhs3Z3LpeEbVmY6Q==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [darwin] + '@parcel/watcher-darwin-x64@2.4.1': + resolution: {integrity: sha512-yrw81BRLjjtHyDu7J61oPuSoeYWR3lDElcPGJyOvIXmor6DEo7/G2u1o7I38cwlcoBHQFULqF6nesIX3tsEXMg==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [darwin] + '@parcel/watcher-freebsd-x64@2.4.0': resolution: {integrity: sha512-dHTRMIplPDT1M0+BkXjtMN+qLtqq24sLDUhmU+UxxLP2TEY2k8GIoqIJiVrGWGomdWsy5IO27aDV1vWyQ6gfHA==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [freebsd] + '@parcel/watcher-freebsd-x64@2.4.1': + resolution: {integrity: sha512-TJa3Pex/gX3CWIx/Co8k+ykNdDCLx+TuZj3f3h7eOjgpdKM+Mnix37RYsYU4LHhiYJz3DK5nFCCra81p6g050w==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [freebsd] + '@parcel/watcher-linux-arm-glibc@2.4.0': resolution: {integrity: sha512-9NQXD+qk46RwATNC3/UB7HWurscY18CnAPMTFcI9Y8CTbtm63/eex1SNt+BHFinEQuLBjaZwR2Lp+n7pmEJPpQ==} engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] + '@parcel/watcher-linux-arm-glibc@2.4.1': + resolution: {integrity: sha512-4rVYDlsMEYfa537BRXxJ5UF4ddNwnr2/1O4MHM5PjI9cvV2qymvhwZSFgXqbS8YoTk5i/JR0L0JDs69BUn45YA==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + '@parcel/watcher-linux-arm64-glibc@2.4.0': resolution: {integrity: sha512-QuJTAQdsd7PFW9jNGaV9Pw+ZMWV9wKThEzzlY3Lhnnwy7iW23qtQFPql8iEaSFMCVI5StNNmONUopk+MFKpiKg==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] + '@parcel/watcher-linux-arm64-glibc@2.4.1': + resolution: {integrity: sha512-BJ7mH985OADVLpbrzCLgrJ3TOpiZggE9FMblfO65PlOCdG++xJpKUJ0Aol74ZUIYfb8WsRlUdgrZxKkz3zXWYA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + '@parcel/watcher-linux-arm64-musl@2.4.0': resolution: {integrity: sha512-oyN+uA9xcTDo/45bwsd6TFHa7Lc7hKujyMlvwrCLvSckvWogndCEoVYFNfZ6JJ2KNL/6fFiGPcbjp8jJmEh5Ng==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] + '@parcel/watcher-linux-arm64-musl@2.4.1': + resolution: {integrity: sha512-p4Xb7JGq3MLgAfYhslU2SjoV9G0kI0Xry0kuxeG/41UfpjHGOhv7UoUDAz/jb1u2elbhazy4rRBL8PegPJFBhA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + '@parcel/watcher-linux-x64-glibc@2.4.0': resolution: {integrity: sha512-KphV8awJmxU3q52JQvJot0QMu07CIyEjV+2Tb2ZtbucEgqyRcxOBDMsqp1JNq5nuDXtcCC0uHQICeiEz38dPBQ==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] + '@parcel/watcher-linux-x64-glibc@2.4.1': + resolution: {integrity: sha512-s9O3fByZ/2pyYDPoLM6zt92yu6P4E39a03zvO0qCHOTjxmt3GHRMLuRZEWhWLASTMSrrnVNWdVI/+pUElJBBBg==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + '@parcel/watcher-linux-x64-musl@2.4.0': resolution: {integrity: sha512-7jzcOonpXNWcSijPpKD5IbC6xC7yTibjJw9jviVzZostYLGxbz8LDJLUnLzLzhASPlPGgpeKLtFUMjAAzM+gSA==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] + '@parcel/watcher-linux-x64-musl@2.4.1': + resolution: {integrity: sha512-L2nZTYR1myLNST0O632g0Dx9LyMNHrn6TOt76sYxWLdff3cB22/GZX2UPtJnaqQPdCRoszoY5rcOj4oMTtp5fQ==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + '@parcel/watcher-wasm@2.3.0': resolution: {integrity: sha512-ejBAX8H0ZGsD8lSICDNyMbSEtPMWgDL0WFCt/0z7hyf5v8Imz4rAM8xY379mBsECkq/Wdqa5WEDLqtjZ+6NxfA==} engines: {node: '>= 10.0.0'} bundledDependencies: - napi-wasm + '@parcel/watcher-wasm@2.4.1': + resolution: {integrity: sha512-/ZR0RxqxU/xxDGzbzosMjh4W6NdYFMqq2nvo2b8SLi7rsl/4jkL8S5stIikorNkdR50oVDvqb/3JT05WM+CRRA==} + engines: {node: '>= 10.0.0'} + bundledDependencies: + - napi-wasm + '@parcel/watcher-win32-arm64@2.4.0': resolution: {integrity: sha512-NOej2lqlq8bQNYhUMnOD0nwvNql8ToQF+1Zhi9ULZoG+XTtJ9hNnCFfyICxoZLXor4bBPTOnzs/aVVoefYnjIg==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [win32] + '@parcel/watcher-win32-arm64@2.4.1': + resolution: {integrity: sha512-Uq2BPp5GWhrq/lcuItCHoqxjULU1QYEcyjSO5jqqOK8RNFDBQnenMMx4gAl3v8GiWa59E9+uDM7yZ6LxwUIfRg==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [win32] + '@parcel/watcher-win32-ia32@2.4.0': resolution: {integrity: sha512-IO/nM+K2YD/iwjWAfHFMBPz4Zqn6qBDqZxY4j2n9s+4+OuTSRM/y/irksnuqcspom5DjkSeF9d0YbO+qpys+JA==} engines: {node: '>= 10.0.0'} cpu: [ia32] os: [win32] + '@parcel/watcher-win32-ia32@2.4.1': + resolution: {integrity: sha512-maNRit5QQV2kgHFSYwftmPBxiuK5u4DXjbXx7q6eKjq5dsLXZ4FJiVvlcw35QXzk0KrUecJmuVFbj4uV9oYrcw==} + engines: {node: '>= 10.0.0'} + cpu: [ia32] + os: [win32] + '@parcel/watcher-win32-x64@2.4.0': resolution: {integrity: sha512-pAUyUVjfFjWaf/pShmJpJmNxZhbMvJASUpdes9jL6bTEJ+gDxPRSpXTIemNyNsb9AtbiGXs9XduP1reThmd+dA==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [win32] + '@parcel/watcher-win32-x64@2.4.1': + resolution: {integrity: sha512-+DvS92F9ezicfswqrvIRM2njcYJbd5mb9CUgtrHCHmvn7pPPa+nMDRu1o1bYYz/l5IB2NVGNJWiH7h1E58IF2A==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [win32] + '@parcel/watcher@2.4.0': resolution: {integrity: sha512-XJLGVL0DEclX5pcWa2N9SX1jCGTDd8l972biNooLFtjneuGqodupPQh6XseXIBBeVIMaaJ7bTcs3qGvXwsp4vg==} engines: {node: '>= 10.0.0'} + '@parcel/watcher@2.4.1': + resolution: {integrity: sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==} + engines: {node: '>= 10.0.0'} + '@peculiar/asn1-android@2.3.10': resolution: {integrity: sha512-z9Rx9cFJv7UUablZISe7uksNbFJCq13hO0yEAOoIpAymALTLlvUOSLnGiQS7okPaM5dP42oTLhezH6XDXRXjGw==} @@ -4009,6 +4100,10 @@ packages: resolution: {integrity: sha512-aaWA+qVOU4byk5IDb/l+M1+7dmrAJhTb4ISJHucpsgRQcMMEes76tbGIqO2JQuA7N50tc/OBrnGKBjoKYG1kSw==} engines: {node: '>=16.0.0'} + '@simplewebauthn/server@9.0.3': + resolution: {integrity: sha512-FMZieoBosrVLFxCnxPFD9Enhd1U7D8nidVDT4MsHc6l4fdVcjoeHjDueeXCloO1k5O/fZg1fsSXXPKbY2XTzDA==} + engines: {node: '>=16.0.0'} + '@simplewebauthn/types@9.0.0': resolution: {integrity: sha512-Lo6LLNQee66D//KueYy9AyX7oiQ7BBKJgdLzP3l0HJDrV4GRSzSAii8AtigBGOeNc8hOQsF/D8itItyuZX9djA==} @@ -5878,6 +5973,10 @@ packages: resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} engines: {node: '>= 8.10.0'} + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + chownr@1.1.4: resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} @@ -5888,6 +5987,9 @@ packages: citty@0.1.5: resolution: {integrity: sha512-AS7n5NSc0OQVMV9v6wt3ByujNIrne0/cTjiC2MYqhvao57VNfiuVksTSr2p17nVOhEr2KtqiAkGwHcgMC/qUuQ==} + citty@0.1.6: + resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==} + classnames@2.5.1: resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} @@ -6091,6 +6193,9 @@ packages: concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + confbox@0.1.7: + resolution: {integrity: sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==} + connect@3.7.0: resolution: {integrity: sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==} engines: {node: '>= 0.10.0'} @@ -6197,6 +6302,14 @@ packages: resolution: {integrity: sha512-ju88BYCQ2uvjO2bR+SsgLSTwTSctU+6Vp2ePbKPgSCZyy4MWZxYsT738DlKVRE5utUjobjPRm1MkTYKJxCmpTA==} engines: {node: '>=14.9.0'} + crossws@0.2.4: + resolution: {integrity: sha512-DAxroI2uSOgUKLz00NX6A8U/8EE3SZHmIND+10jkVSaypvyt57J5JEOxAQOL6lQxyzi/wZbTIwssU1uy69h5Vg==} + peerDependencies: + uWebSockets.js: '*' + peerDependenciesMeta: + uWebSockets.js: + optional: true + crypto-js@4.2.0: resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} @@ -6542,6 +6655,9 @@ packages: destr@2.0.2: resolution: {integrity: sha512-65AlobnZMiCET00KaFFjUefxDX0khFA/E4myqZ7a6Sq1yZtR8+FVIvilVX66vF2uobSumxooYZChiRPCKNqhmg==} + destr@2.0.3: + resolution: {integrity: sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ==} + destroy@1.2.0: resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} @@ -7663,6 +7779,9 @@ packages: h3@1.10.1: resolution: {integrity: sha512-UBAUp47hmm4BB5/njB4LrEa9gpuvZj4/Qf/ynSMzO6Ku2RXaouxEfiG2E2IFnv6fxbhAkzjasDxmo6DFdEeXRg==} + h3@1.11.1: + resolution: {integrity: sha512-AbaH6IDnZN6nmbnJOH72y3c5Wwh9P97soSVdGSBbcDACRdkC0FEWf25pzx4f/NuOCK6quHmW18yF2Wx+G4Zi1A==} + hanji@0.0.5: resolution: {integrity: sha512-Abxw1Lq+TnYiL4BueXqMau222fPSPMFtya8HdpWsz/xVAhifXou71mPh/kY2+08RgFcVccjG3uZHs6K5HAe3zw==} @@ -8629,6 +8748,10 @@ packages: resolution: {integrity: sha512-gTpEJhT5L85L0bFgmu+Boqu5rP4DwDtEb4Exq5gdQUxWRwx4jbzdInZkmyLONo5EwIcQB0k7ZpWlpCDPdL77EQ==} hasBin: true + listhen@1.7.2: + resolution: {integrity: sha512-7/HamOm5YD9Wb7CFgAZkKgVPA96WwhcTQoqtm2VTZGVbVVn3IWKRBTgrU7cchA3Q8k9iCsG8Osoi9GX4JsGM9g==} + hasBin: true + listr2@4.0.5: resolution: {integrity: sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA==} engines: {node: '>=12'} @@ -9292,6 +9415,9 @@ packages: mlly@1.5.0: resolution: {integrity: sha512-NPVQvAY1xr1QoVeG0cy8yUYC7FQcOx6evl/RjT1wL5FvzPnzOysoqB/jmx/DhssT2dYa8nxECLAaFI/+gVLhDQ==} + mlly@1.7.0: + resolution: {integrity: sha512-U9SDaXGEREBYQgfejV97coK0UL1r+qnF2SyO9A3qcI8MzKnsIFKHNVEkrDyNncQTKQQumsasmeq84eNMdBfsNQ==} + mnemonist@0.38.3: resolution: {integrity: sha512-2K9QYubXx/NAjv4VLq1d1Ly8pWNC5L3BrixtdkyTegXWJIqY+zLNDhhX/A+ZwWt70tB1S8H4BE8FLYEFyNoOBw==} @@ -9547,6 +9673,9 @@ packages: node-fetch-native@1.6.1: resolution: {integrity: sha512-bW9T/uJDPAJB2YNYEpWzE54U5O3MQidXsOyTfnbKYtTtFexRvGzb1waphBN4ZwP6EcIvYYEOwW0b72BpAqydTw==} + node-fetch-native@1.6.4: + resolution: {integrity: sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==} + node-fetch@2.6.7: resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} engines: {node: 4.x || >=6.0.0} @@ -10021,6 +10150,9 @@ packages: pkg-types@1.0.3: resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==} + pkg-types@1.1.1: + resolution: {integrity: sha512-ko14TjmDuQJ14zsotODv7dBlwxKhUKQEhuhmbqo1uCi9BB0Z2alo/wAXg6q1dTR5TyuqYyWhjtfe/Tsh+X28jQ==} + playwright-core@1.41.2: resolution: {integrity: sha512-VaTvwCA4Y8kxEe+kfm2+uUUw5Lubf38RxF7FpBxLPmGe5sdNkSg5e3ChEigaGrX7qdqT3pt2m/98LiyvU2x6CA==} engines: {node: '>=16'} @@ -12139,6 +12271,9 @@ packages: ufo@1.3.2: resolution: {integrity: sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA==} + ufo@1.5.3: + resolution: {integrity: sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==} + uglify-js@3.17.4: resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} engines: {node: '>=0.8.0'} @@ -12324,6 +12459,50 @@ packages: idb-keyval: optional: true + unstorage@1.10.2: + resolution: {integrity: sha512-cULBcwDqrS8UhlIysUJs2Dk0Mmt8h7B0E6mtR+relW9nZvsf/u4SkAYyNliPiPW7XtFNb5u3IUMkxGxFTTRTgQ==} + peerDependencies: + '@azure/app-configuration': ^1.5.0 + '@azure/cosmos': ^4.0.0 + '@azure/data-tables': ^13.2.2 + '@azure/identity': ^4.0.1 + '@azure/keyvault-secrets': ^4.8.0 + '@azure/storage-blob': ^12.17.0 + '@capacitor/preferences': ^5.0.7 + '@netlify/blobs': ^6.5.0 || ^7.0.0 + '@planetscale/database': ^1.16.0 + '@upstash/redis': ^1.28.4 + '@vercel/kv': ^1.0.1 + idb-keyval: ^6.2.1 + ioredis: ^5.3.2 + peerDependenciesMeta: + '@azure/app-configuration': + optional: true + '@azure/cosmos': + optional: true + '@azure/data-tables': + optional: true + '@azure/identity': + optional: true + '@azure/keyvault-secrets': + optional: true + '@azure/storage-blob': + optional: true + '@capacitor/preferences': + optional: true + '@netlify/blobs': + optional: true + '@planetscale/database': + optional: true + '@upstash/redis': + optional: true + '@vercel/kv': + optional: true + idb-keyval: + optional: true + ioredis: + optional: true + untildify@4.0.0: resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} engines: {node: '>=8'} @@ -15768,6 +15947,8 @@ snapshots: '@kamilkisiela/fast-url-parser@1.1.4': {} + '@levischuck/tiny-cbor@0.2.2': {} + '@libsql/client@0.6.0': dependencies: '@libsql/core': 0.6.0 @@ -16426,44 +16607,85 @@ snapshots: '@parcel/watcher-android-arm64@2.4.0': optional: true + '@parcel/watcher-android-arm64@2.4.1': + optional: true + '@parcel/watcher-darwin-arm64@2.4.0': optional: true + '@parcel/watcher-darwin-arm64@2.4.1': + optional: true + '@parcel/watcher-darwin-x64@2.4.0': optional: true + '@parcel/watcher-darwin-x64@2.4.1': + optional: true + '@parcel/watcher-freebsd-x64@2.4.0': optional: true + '@parcel/watcher-freebsd-x64@2.4.1': + optional: true + '@parcel/watcher-linux-arm-glibc@2.4.0': optional: true + '@parcel/watcher-linux-arm-glibc@2.4.1': + optional: true + '@parcel/watcher-linux-arm64-glibc@2.4.0': optional: true + '@parcel/watcher-linux-arm64-glibc@2.4.1': + optional: true + '@parcel/watcher-linux-arm64-musl@2.4.0': optional: true + '@parcel/watcher-linux-arm64-musl@2.4.1': + optional: true + '@parcel/watcher-linux-x64-glibc@2.4.0': optional: true + '@parcel/watcher-linux-x64-glibc@2.4.1': + optional: true + '@parcel/watcher-linux-x64-musl@2.4.0': optional: true + '@parcel/watcher-linux-x64-musl@2.4.1': + optional: true + '@parcel/watcher-wasm@2.3.0': dependencies: is-glob: 4.0.3 micromatch: 4.0.5 + '@parcel/watcher-wasm@2.4.1': + dependencies: + is-glob: 4.0.3 + micromatch: 4.0.5 + '@parcel/watcher-win32-arm64@2.4.0': optional: true + '@parcel/watcher-win32-arm64@2.4.1': + optional: true + '@parcel/watcher-win32-ia32@2.4.0': optional: true + '@parcel/watcher-win32-ia32@2.4.1': + optional: true + '@parcel/watcher-win32-x64@2.4.0': optional: true + '@parcel/watcher-win32-x64@2.4.1': + optional: true + '@parcel/watcher@2.4.0': dependencies: detect-libc: 1.0.3 @@ -16484,6 +16706,26 @@ snapshots: '@parcel/watcher-win32-ia32': 2.4.0 '@parcel/watcher-win32-x64': 2.4.0 + '@parcel/watcher@2.4.1': + dependencies: + detect-libc: 1.0.3 + is-glob: 4.0.3 + micromatch: 4.0.5 + node-addon-api: 7.1.0 + optionalDependencies: + '@parcel/watcher-android-arm64': 2.4.1 + '@parcel/watcher-darwin-arm64': 2.4.1 + '@parcel/watcher-darwin-x64': 2.4.1 + '@parcel/watcher-freebsd-x64': 2.4.1 + '@parcel/watcher-linux-arm-glibc': 2.4.1 + '@parcel/watcher-linux-arm64-glibc': 2.4.1 + '@parcel/watcher-linux-arm64-musl': 2.4.1 + '@parcel/watcher-linux-x64-glibc': 2.4.1 + '@parcel/watcher-linux-x64-musl': 2.4.1 + '@parcel/watcher-win32-arm64': 2.4.1 + '@parcel/watcher-win32-ia32': 2.4.1 + '@parcel/watcher-win32-x64': 2.4.1 + '@peculiar/asn1-android@2.3.10': dependencies: '@peculiar/asn1-schema': 2.3.8 @@ -16973,6 +17215,20 @@ snapshots: transitivePeerDependencies: - encoding + '@simplewebauthn/server@9.0.3(encoding@0.1.13)': + dependencies: + '@hexagon/base64': 1.1.28 + '@levischuck/tiny-cbor': 0.2.2 + '@peculiar/asn1-android': 2.3.10 + '@peculiar/asn1-ecc': 2.3.8 + '@peculiar/asn1-rsa': 2.3.8 + '@peculiar/asn1-schema': 2.3.8 + '@peculiar/asn1-x509': 2.3.8 + '@simplewebauthn/types': 9.0.1 + cross-fetch: 4.0.0(encoding@0.1.13) + transitivePeerDependencies: + - encoding + '@simplewebauthn/types@9.0.0': {} '@simplewebauthn/types@9.0.1': {} @@ -19801,6 +20057,18 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + chownr@1.1.4: {} chownr@2.0.0: {} @@ -19809,6 +20077,10 @@ snapshots: dependencies: consola: 3.2.3 + citty@0.1.6: + dependencies: + consola: 3.2.3 + classnames@2.5.1: {} clean-stack@2.2.0: {} @@ -20014,6 +20286,8 @@ snapshots: concat-map@0.0.1: {} + confbox@0.1.7: {} + connect@3.7.0: dependencies: debug: 2.6.9 @@ -20130,6 +20404,8 @@ snapshots: dependencies: '@types/node': 17.0.45 + crossws@0.2.4: {} + crypto-js@4.2.0: {} css-color-keywords@1.0.0: {} @@ -20479,6 +20755,8 @@ snapshots: destr@2.0.2: {} + destr@2.0.3: {} + destroy@1.2.0: {} detect-indent@6.1.0: {} @@ -22020,6 +22298,21 @@ snapshots: uncrypto: 0.1.3 unenv: 1.9.0 + h3@1.11.1: + dependencies: + cookie-es: 1.0.0 + crossws: 0.2.4 + defu: 6.1.4 + destr: 2.0.3 + iron-webcrypto: 1.0.0 + ohash: 1.1.3 + radix3: 1.1.0 + ufo: 1.5.3 + uncrypto: 0.1.3 + unenv: 1.9.0 + transitivePeerDependencies: + - uWebSockets.js + hanji@0.0.5: dependencies: lodash.throttle: 4.1.1 @@ -23164,6 +23457,29 @@ snapshots: untun: 0.1.3 uqr: 0.1.2 + listhen@1.7.2: + dependencies: + '@parcel/watcher': 2.4.1 + '@parcel/watcher-wasm': 2.4.1 + citty: 0.1.6 + clipboardy: 4.0.0 + consola: 3.2.3 + crossws: 0.2.4 + defu: 6.1.4 + get-port-please: 3.1.2 + h3: 1.11.1 + http-shutdown: 1.2.2 + jiti: 1.21.0 + mlly: 1.7.0 + node-forge: 1.3.1 + pathe: 1.1.2 + std-env: 3.7.0 + ufo: 1.5.3 + untun: 0.1.3 + uqr: 0.1.2 + transitivePeerDependencies: + - uWebSockets.js + listr2@4.0.5: dependencies: cli-truncate: 2.1.0 @@ -24259,6 +24575,13 @@ snapshots: pkg-types: 1.0.3 ufo: 1.3.2 + mlly@1.7.0: + dependencies: + acorn: 8.11.3 + pathe: 1.1.2 + pkg-types: 1.1.1 + ufo: 1.5.3 + mnemonist@0.38.3: dependencies: obliterator: 1.6.1 @@ -24585,6 +24908,8 @@ snapshots: node-fetch-native@1.6.1: {} + node-fetch-native@1.6.4: {} + node-fetch@2.6.7(encoding@0.1.13): dependencies: whatwg-url: 5.0.0 @@ -24777,9 +25102,9 @@ snapshots: ofetch@1.3.3: dependencies: - destr: 2.0.2 - node-fetch-native: 1.6.1 - ufo: 1.3.2 + destr: 2.0.3 + node-fetch-native: 1.6.4 + ufo: 1.5.3 ohash@1.1.3: {} @@ -25098,6 +25423,12 @@ snapshots: mlly: 1.5.0 pathe: 1.1.2 + pkg-types@1.1.1: + dependencies: + confbox: 0.1.7 + mlly: 1.7.0 + pathe: 1.1.2 + playwright-core@1.41.2: {} playwright@1.41.2: @@ -27554,6 +27885,8 @@ snapshots: ufo@1.3.2: {} + ufo@1.5.3: {} + uglify-js@3.17.4: optional: true @@ -27581,7 +27914,7 @@ snapshots: consola: 3.2.3 defu: 6.1.4 mime: 3.0.0 - node-fetch-native: 1.6.1 + node-fetch-native: 1.6.4 pathe: 1.1.2 unherit@3.0.1: {} @@ -27763,6 +28096,26 @@ snapshots: transitivePeerDependencies: - supports-color + unstorage@1.10.2(@azure/data-tables@13.2.2)(@azure/identity@1.5.2)(@upstash/redis@1.28.2)(ioredis@5.4.1): + dependencies: + anymatch: 3.1.3 + chokidar: 3.6.0 + destr: 2.0.3 + h3: 1.11.1 + listhen: 1.7.2 + lru-cache: 10.2.0 + mri: 1.2.0 + node-fetch-native: 1.6.4 + ofetch: 1.3.3 + ufo: 1.5.3 + optionalDependencies: + '@azure/data-tables': 13.2.2 + '@azure/identity': 1.5.2(debug@4.3.4) + '@upstash/redis': 1.28.2 + ioredis: 5.4.1 + transitivePeerDependencies: + - uWebSockets.js + untildify@4.0.0: {} untun@0.1.3: