better-auth 0.0.10-beta.2 → 0.0.10-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,8 +2,8 @@ import * as nanostores from 'nanostores';
2
2
  import { A as AccessControl, S as StatementsPrimitive, R as Role } from '../statement-BUvhzMmI.js';
3
3
  import * as _better_fetch_fetch from '@better-fetch/fetch';
4
4
  import { BetterFetchOption } from '@better-fetch/fetch';
5
- import { o as organization, O as Organization, M as Member, I as Invitation, u as username } from '../index-BAR_7S7m.js';
6
- export { g as getPasskeyActions, p as passkeyClient, t as twoFactorClient } from '../index-BAR_7S7m.js';
5
+ import { o as organization, O as Organization, M as Member, I as Invitation, u as username } from '../index-TgPPn8w5.js';
6
+ export { g as getPasskeyActions, p as passkeyClient, t as twoFactorClient } from '../index-TgPPn8w5.js';
7
7
  import { P as Prettify } from '../helper-vUH9Oq11.js';
8
8
  import '../schema-deEs0FFi.js';
9
9
  import 'arctic';
@@ -479,7 +479,6 @@ var twoFactorClient = (options = {
479
479
  }
480
480
  ],
481
481
  pathMethods: {
482
- "enable/totp": "POST",
483
482
  "/two-factor/disable": "POST",
484
483
  "/two-factor/enable": "POST",
485
484
  "/two-factor/send-otp": "POST"
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/plugins/organization/client.ts","../../src/plugins/organization/access/src/access.ts","../../src/plugins/organization/access/statement.ts","../../src/client/config.ts","../../src/client/fetch-plugins.ts","../../src/client/session-atom.ts","../../src/client/query.ts","../../src/plugins/username/client.ts","../../src/plugins/passkey/client.ts","../../src/utils/logger.ts","../../src/plugins/two-factor/client.ts"],"sourcesContent":["import { atom } from \"nanostores\";\nimport type {\n\tInvitation,\n\tMember,\n\tOrganization,\n} from \"../../plugins/organization/schema\";\nimport type { Prettify } from \"../../types/helper\";\nimport { defaultStatements, type AccessControl, type Role } from \"./access\";\nimport type { AuthClientPlugin } from \"../../client/types\";\nimport type { organization } from \"./organization\";\nimport type { BetterFetchOption } from \"@better-fetch/fetch\";\nimport { useAuthQuery } from \"../../client\";\n\ninterface OrganizationClientOptions {\n\tac: AccessControl;\n\troles?: {\n\t\t[key in \"admin\" | \"member\" | \"owner\"]?: Role<any>;\n\t};\n}\n\nexport const organizationClient = <O extends OrganizationClientOptions>(\n\toptions?: O,\n) => {\n\tconst activeOrgId = atom<string | null | undefined>(undefined);\n\tconst _listOrg = atom<boolean>(false);\n\tconst _activeOrgSignal = atom<boolean>(false);\n\n\ttype DefaultStatements = typeof defaultStatements;\n\ttype Statements = O[\"ac\"] extends AccessControl<infer S>\n\t\t? S extends Record<string, Array<any>>\n\t\t\t? S & DefaultStatements\n\t\t\t: DefaultStatements\n\t\t: DefaultStatements;\n\treturn {\n\t\tid: \"organization\",\n\t\t$InferServerPlugin: {} as ReturnType<typeof organization>,\n\t\tgetActions: ($fetch) => ({\n\t\t\torganization: {\n\t\t\t\t$Infer: {\n\t\t\t\t\tActiveOrganization: {} as Prettify<\n\t\t\t\t\t\tOrganization & {\n\t\t\t\t\t\t\tmembers: Prettify<\n\t\t\t\t\t\t\t\tMember & {\n\t\t\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\t\t\tid: string;\n\t\t\t\t\t\t\t\t\t\tname: string;\n\t\t\t\t\t\t\t\t\t\temail: string;\n\t\t\t\t\t\t\t\t\t\timage: string;\n\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t>[];\n\t\t\t\t\t\t\tinvitations: Invitation[];\n\t\t\t\t\t\t}\n\t\t\t\t\t>,\n\t\t\t\t\tOrganization: {} as Organization,\n\t\t\t\t\tInvitation: {} as Invitation,\n\t\t\t\t\tMember: {} as Member,\n\t\t\t\t},\n\t\t\t\tsetActive(orgId: string | null) {\n\t\t\t\t\tactiveOrgId.set(orgId);\n\t\t\t\t},\n\t\t\t\thasPermission: async (data: {\n\t\t\t\t\tpermission: Partial<{\n\t\t\t\t\t\t//@ts-expect-error fix this later\n\t\t\t\t\t\t[key in keyof Statements]: Statements[key][number][];\n\t\t\t\t\t}>;\n\t\t\t\t\tfetchOptions?: BetterFetchOption;\n\t\t\t\t}) => {\n\t\t\t\t\treturn await $fetch<{\n\t\t\t\t\t\tsuccess: boolean;\n\t\t\t\t\t}>(\"/organization/has-permission\", {\n\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\tpermission: data.permission,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t...data.fetchOptions,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t},\n\t\t}),\n\t\tgetAtoms: ($fetch) => {\n\t\t\tconst listOrganizations = useAuthQuery<Organization[]>(\n\t\t\t\t_listOrg,\n\t\t\t\t\"/organization/list\",\n\t\t\t\t$fetch,\n\t\t\t\t{\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t},\n\t\t\t);\n\t\t\tconst activeOrganization = useAuthQuery<\n\t\t\t\tPrettify<\n\t\t\t\t\tOrganization & {\n\t\t\t\t\t\tmembers: (Member & {\n\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\tid: string;\n\t\t\t\t\t\t\t\tname: string;\n\t\t\t\t\t\t\t\temail: string;\n\t\t\t\t\t\t\t\timage: string;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t})[];\n\t\t\t\t\t\tinvitations: Invitation[];\n\t\t\t\t\t}\n\t\t\t\t>\n\t\t\t>(\n\t\t\t\t[activeOrgId, _activeOrgSignal],\n\t\t\t\t\"/organization/activate\",\n\t\t\t\t$fetch,\n\t\t\t\t() => ({\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tcredentials: \"include\",\n\t\t\t\t\tbody: {\n\t\t\t\t\t\torgId: activeOrgId.get(),\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\t_listOrg,\n\t\t\t\t_activeOrgSignal,\n\t\t\t\tactiveOrganization,\n\t\t\t\tlistOrganizations,\n\t\t\t};\n\t\t},\n\t\tatomListeners: [\n\t\t\t{\n\t\t\t\tmatcher(path) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\tpath === \"/organization/create\" || path === \"/organization/delete\"\n\t\t\t\t\t);\n\t\t\t\t},\n\t\t\t\tsignal: \"_listOrg\",\n\t\t\t},\n\t\t\t{\n\t\t\t\tmatcher(path) {\n\t\t\t\t\treturn path.startsWith(\"/organization\");\n\t\t\t\t},\n\t\t\t\tsignal: \"_activeOrgSignal\",\n\t\t\t},\n\t\t],\n\t} satisfies AuthClientPlugin;\n};\n","import type { StatementsPrimitive as Statements, Subset } from \"./types\";\n\nexport class ParsingError extends Error {\n\tpublic readonly path: string;\n\tconstructor(message: string, path: string) {\n\t\tsuper(message);\n\t\tthis.path = path;\n\t}\n}\n\ntype Connector = \"OR\" | \"AND\";\n\nexport class AccessControl<TStatements extends Statements = Statements> {\n\tprivate readonly statements: TStatements;\n\tconstructor(private readonly s: TStatements) {\n\t\tthis.statements = s;\n\t}\n\tpublic newRole<K extends keyof TStatements>(\n\t\tstatements: Subset<K, TStatements>,\n\t) {\n\t\treturn new Role<Subset<K, TStatements>>(statements);\n\t}\n}\n\nexport type AuthortizeResponse =\n\t| { success: false; error: string }\n\t| { success: true; error?: never };\n\nexport class Role<TStatements extends Statements> {\n\tpublic readonly statements: TStatements;\n\n\tconstructor(statements: TStatements) {\n\t\tthis.statements = statements;\n\t}\n\n\tpublic authorize<K extends keyof TStatements>(\n\t\trequest: Subset<K, TStatements>,\n\t\tconnector?: Connector,\n\t): AuthortizeResponse {\n\t\tfor (const [requestedResource, requestedActions] of Object.entries(\n\t\t\trequest,\n\t\t)) {\n\t\t\tconst allowedActions = this.statements[requestedResource];\n\t\t\tif (!allowedActions) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: `You are not allowed to access resource: ${requestedResource}`,\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst success =\n\t\t\t\tconnector === \"OR\"\n\t\t\t\t\t? (requestedActions as string[]).some((requestedAction) =>\n\t\t\t\t\t\t\tallowedActions.includes(requestedAction),\n\t\t\t\t\t\t)\n\t\t\t\t\t: (requestedActions as string[]).every((requestedAction) =>\n\t\t\t\t\t\t\tallowedActions.includes(requestedAction),\n\t\t\t\t\t\t);\n\t\t\tif (success) {\n\t\t\t\treturn { success };\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: `unauthorized to access resource \"${requestedResource}\"`,\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: \"Not authorized\",\n\t\t};\n\t}\n\n\tstatic fromString<TStatements extends Statements>(s: string) {\n\t\tconst statements = JSON.parse(s) as TStatements;\n\n\t\tif (typeof statements !== \"object\") {\n\t\t\tthrow new ParsingError(\"statements is not an object\", \".\");\n\t\t}\n\t\tfor (const [resource, actions] of Object.entries(statements)) {\n\t\t\tif (typeof resource !== \"string\") {\n\t\t\t\tthrow new ParsingError(\"invalid resource identifier\", resource);\n\t\t\t}\n\t\t\tif (!Array.isArray(actions)) {\n\t\t\t\tthrow new ParsingError(\"actions is not an array\", resource);\n\t\t\t}\n\t\t\tfor (let i = 0; i < actions.length; i++) {\n\t\t\t\tif (typeof actions[i] !== \"string\") {\n\t\t\t\t\tthrow new ParsingError(\"action is not a string\", `${resource}[${i}]`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn new Role<TStatements>(statements);\n\t}\n\n\tpublic toString(): string {\n\t\treturn JSON.stringify(this.statements);\n\t}\n}\n","import { AccessControl } from \"./src/access\";\nimport type { StatementsPrimitive } from \"./src/types\";\n\nexport const createAccessControl = <S extends StatementsPrimitive>(\n\tstatements: S,\n) => {\n\treturn new AccessControl<S>(statements);\n};\n\nexport const defaultStatements = {\n\torganization: [\"update\", \"delete\"],\n\tmember: [\"create\", \"update\", \"delete\"],\n\tinvitation: [\"create\", \"cancel\"],\n} as const;\n\nexport const defaultAc = createAccessControl(defaultStatements);\n\nexport const adminAc = defaultAc.newRole({\n\torganization: [\"update\"],\n\tinvitation: [\"create\", \"cancel\"],\n\tmember: [\"create\", \"update\", \"delete\"],\n});\n\nexport const ownerAc = defaultAc.newRole({\n\torganization: [\"update\", \"delete\"],\n\tmember: [\"create\", \"update\", \"delete\"],\n\tinvitation: [\"create\", \"cancel\"],\n});\n\nexport const memberAc = defaultAc.newRole({\n\torganization: [],\n\tmember: [],\n\tinvitation: [],\n});\n\nexport const defaultRoles = {\n\tadmin: adminAc,\n\towner: ownerAc,\n\tmember: memberAc,\n};\n","import { createFetch } from \"@better-fetch/fetch\";\nimport { getBaseURL } from \"../utils/base-url\";\nimport { type Atom } from \"nanostores\";\nimport type { AtomListener, ClientOptions } from \"./types\";\nimport { addCurrentURL, csrfPlugin, redirectPlugin } from \"./fetch-plugins\";\n\nexport const getClientConfig = <O extends ClientOptions>(options?: O) => {\n\tconst $fetch = createFetch({\n\t\tbaseURL: getBaseURL(options?.fetchOptions?.baseURL || options?.baseURL),\n\t\tcredentials: \"include\",\n\t\t...options?.fetchOptions,\n\t\tplugins: [\n\t\t\tcsrfPlugin,\n\t\t\tredirectPlugin,\n\t\t\taddCurrentURL,\n\t\t\t...(options?.fetchOptions?.plugins?.filter((pl) => pl !== undefined) ||\n\t\t\t\t[]),\n\t\t\t...(options?.plugins\n\t\t\t\t?.flatMap((plugin) => plugin.fetchPlugins)\n\t\t\t\t.filter((pl) => pl !== undefined) || []),\n\t\t],\n\t});\n\tconst plugins = options?.plugins || [];\n\tlet pluginsActions = {} as Record<string, any>;\n\tlet pluginsAtoms = {} as Record<string, Atom<any>>;\n\tlet pluginPathMethods: Record<string, \"POST\" | \"GET\"> = {\n\t\t\"/sign-out\": \"POST\",\n\t\t\"/user/revoke-sessions\": \"POST\",\n\t};\n\tconst atomListeners: AtomListener[] = [\n\t\t{\n\t\t\tsignal: \"_sessionSignal\",\n\t\t\tmatcher(path) {\n\t\t\t\treturn (\n\t\t\t\t\tpath === \"/sign-out\" ||\n\t\t\t\t\tpath === \"sign-up/email\" ||\n\t\t\t\t\tpath === \"/user/update\"\n\t\t\t\t);\n\t\t\t},\n\t\t},\n\t];\n\tfor (const plugin of plugins) {\n\t\tif (plugin.getActions) {\n\t\t\tObject.assign(pluginsActions, plugin.getActions?.($fetch));\n\t\t}\n\t\tif (plugin.getAtoms) {\n\t\t\tObject.assign(pluginsAtoms, plugin.getAtoms?.($fetch));\n\t\t}\n\t\tif (plugin.pathMethods) {\n\t\t\tObject.assign(pluginPathMethods, plugin.pathMethods);\n\t\t}\n\t\tif (plugin.atomListeners) {\n\t\t\tatomListeners.push(...plugin.atomListeners);\n\t\t}\n\t}\n\treturn {\n\t\tpluginsActions,\n\t\tpluginsAtoms,\n\t\tpluginPathMethods,\n\t\tatomListeners,\n\t\t$fetch,\n\t};\n};\n","import { type BetterFetchPlugin, betterFetch } from \"@better-fetch/fetch\";\nimport { BetterAuthError } from \"../error/better-auth-error\";\n\nexport const redirectPlugin = {\n\tid: \"redirect\",\n\tname: \"Redirect\",\n\thooks: {\n\t\tonSuccess(context) {\n\t\t\tif (context.data?.url && context.data?.redirect) {\n\t\t\t\tif (typeof window !== \"undefined\") {\n\t\t\t\t\twindow.location.href = context.data.url;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t},\n} satisfies BetterFetchPlugin;\n\nexport const addCurrentURL = {\n\tid: \"add-current-url\",\n\tname: \"Add current URL\",\n\thooks: {\n\t\tonRequest(context) {\n\t\t\tif (typeof window !== \"undefined\") {\n\t\t\t\tconst url = new URL(context.url);\n\t\t\t\turl.searchParams.set(\"currentURL\", window.location.href);\n\t\t\t\tcontext.url = url;\n\t\t\t}\n\t\t\treturn context;\n\t\t},\n\t},\n} satisfies BetterFetchPlugin;\n\nconst cache = new Map<string, string>();\nexport const csrfPlugin = {\n\tid: \"csrf\",\n\tname: \"CSRF Check\",\n\tasync init(url, options) {\n\t\tif (!options?.baseURL) {\n\t\t\tthrow new BetterAuthError(\n\t\t\t\t\"API Base URL on the auth client isn't configured. Please pass it directly to the client `baseURL`\",\n\t\t\t);\n\t\t}\n\n\t\tif (options?.method !== \"GET\") {\n\t\t\toptions = options || {};\n\t\t\tconst csrfToken = cache.get(\"CSRF_TOKEN\");\n\t\t\tif (!csrfToken) {\n\t\t\t\tconst { data, error } = await betterFetch<{\n\t\t\t\t\tcsrfToken: string;\n\t\t\t\t}>(\"/csrf\", {\n\t\t\t\t\tbody: undefined,\n\t\t\t\t\tbaseURL: options.baseURL,\n\t\t\t\t\tplugins: [],\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\tcredentials: \"include\",\n\t\t\t\t\tcustomFetchImpl: options.customFetchImpl,\n\t\t\t\t});\n\t\t\t\tif (error) {\n\t\t\t\t\tif (error.status === 404) {\n\t\t\t\t\t\tthrow new BetterAuthError(\n\t\t\t\t\t\t\t\"CSRF route not found. Make sure the server is running and the base URL is correct and includes the path (e.g. http://localhost:3000/api/auth).\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (error.status === 429) {\n\t\t\t\t\t\treturn new Response(null, {\n\t\t\t\t\t\t\tstatus: 429,\n\t\t\t\t\t\t\tstatusText: \"Too Many Requests\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tthrow new BetterAuthError(\n\t\t\t\t\t\t\"Failed to fetch CSRF token: \" + error.message,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tcache.set(\"CSRF_TOKEN\", data.csrfToken);\n\t\t\t}\n\t\t\toptions.body = {\n\t\t\t\t...options?.body,\n\t\t\t\tcsrfToken: csrfToken,\n\t\t\t};\n\t\t}\n\t\toptions.credentials = \"include\";\n\t\treturn { url, options };\n\t},\n} satisfies BetterFetchPlugin;\n","import type { BetterFetch } from \"@better-fetch/fetch\";\nimport { atom } from \"nanostores\";\nimport type { Auth as BetterAuth } from \"../auth\";\nimport type { Prettify, UnionToIntersection } from \"../types/helper\";\nimport type { InferSession, InferUser } from \"../types/models\";\nimport type { AuthClientPlugin, ClientOptions } from \"./types\";\nimport { useAuthQuery } from \"./query\";\nimport type { BetterAuthPlugin } from \"../plugins\";\n\nexport function getSessionAtom<Option extends ClientOptions>(\n\tclient: BetterFetch,\n) {\n\ttype Plugins = Option[\"plugins\"] extends Array<AuthClientPlugin>\n\t\t? Array<\n\t\t\t\tOption[\"plugins\"][number] extends infer T\n\t\t\t\t\t? T extends AuthClientPlugin\n\t\t\t\t\t\t? T[\"$InferServerPlugin\"] extends infer U\n\t\t\t\t\t\t\t? U extends BetterAuthPlugin\n\t\t\t\t\t\t\t\t? U\n\t\t\t\t\t\t\t\t: never\n\t\t\t\t\t\t\t: never\n\t\t\t\t\t\t: never\n\t\t\t\t\t: never\n\t\t\t>\n\t\t: never;\n\n\ttype Auth = {\n\t\thandler: any;\n\t\tapi: any;\n\t\toptions: {\n\t\t\tdatabase: any;\n\t\t\tplugins: Plugins;\n\t\t};\n\t};\n\n\ttype UserWithAdditionalFields = InferUser<Auth[\"options\"]>;\n\ttype SessionWithAdditionalFields = InferSession<Auth[\"options\"]>;\n\tconst $signal = atom<boolean>(false);\n\tconst session = useAuthQuery<{\n\t\tuser: Prettify<UserWithAdditionalFields>;\n\t\tsession: Prettify<SessionWithAdditionalFields>;\n\t}>($signal, \"/session\", client, {\n\t\tmethod: \"GET\",\n\t});\n\treturn {\n\t\t$session: session,\n\t\t_sessionSignal: $signal,\n\t\t$Infer: {} as {\n\t\t\tSession: {\n\t\t\t\tsession: Prettify<SessionWithAdditionalFields>;\n\t\t\t\tuser: Prettify<UserWithAdditionalFields>;\n\t\t\t};\n\t\t},\n\t};\n}\n","import {\n\tBetterFetchError,\n\ttype BetterFetch,\n\ttype BetterFetchOption,\n} from \"@better-fetch/fetch\";\nimport { atom, type PreinitializedWritableAtom } from \"nanostores\";\n\nexport const useAuthQuery = <T>(\n\tinitializedAtom:\n\t\t| PreinitializedWritableAtom<any>\n\t\t| PreinitializedWritableAtom<any>[],\n\tpath: string,\n\t$fetch: BetterFetch,\n\toptions?:\n\t\t| ((value: {\n\t\t\t\tdata: null | T;\n\t\t\t\terror: null | BetterFetchError;\n\t\t\t\tisPending: boolean;\n\t\t }) => BetterFetchOption)\n\t\t| BetterFetchOption,\n) => {\n\tconst value = atom<{\n\t\tdata: null | T;\n\t\terror: null | BetterFetchError;\n\t\tisPending: boolean;\n\t}>({\n\t\tdata: null,\n\t\terror: null,\n\t\tisPending: false,\n\t});\n\n\tconst fn = () => {\n\t\tconst opts =\n\t\t\ttypeof options === \"function\"\n\t\t\t\t? options({\n\t\t\t\t\t\tdata: value.get().data,\n\t\t\t\t\t\terror: value.get().error,\n\t\t\t\t\t\tisPending: value.get().isPending,\n\t\t\t\t\t})\n\t\t\t\t: options;\n\t\treturn $fetch<T>(path, {\n\t\t\t...opts,\n\t\t\tonSuccess: async (context) => {\n\t\t\t\tvalue.set({\n\t\t\t\t\tdata: context.data,\n\t\t\t\t\terror: null,\n\t\t\t\t\tisPending: false,\n\t\t\t\t});\n\t\t\t\tawait opts?.onSuccess?.(context);\n\t\t\t},\n\t\t\tasync onError(context) {\n\t\t\t\tvalue.set({\n\t\t\t\t\terror: context.error,\n\t\t\t\t\tdata: null,\n\t\t\t\t\tisPending: false,\n\t\t\t\t});\n\t\t\t\tawait opts?.onError?.(context);\n\t\t\t},\n\t\t\tasync onRequest(context) {\n\t\t\t\tconst currentValue = value.get();\n\t\t\t\tvalue.set({\n\t\t\t\t\tisPending: true,\n\t\t\t\t\tdata: currentValue.data,\n\t\t\t\t\terror: currentValue.error,\n\t\t\t\t});\n\t\t\t\tawait opts?.onRequest?.(context);\n\t\t\t},\n\t\t});\n\t};\n\tfn();\n\tinitializedAtom = Array.isArray(initializedAtom)\n\t\t? initializedAtom\n\t\t: [initializedAtom];\n\tlet firstRun = true;\n\tfor (const initAtom of initializedAtom) {\n\t\tinitAtom.subscribe((value) => {\n\t\t\tif (!firstRun) {\n\t\t\t\tfn();\n\t\t\t}\n\t\t});\n\t}\n\tfirstRun = false;\n\treturn value;\n};\n","import type { username } from \".\";\nimport type { AuthClientPlugin } from \"../../client/types\";\n\nexport const usernameClient = () => {\n\treturn {\n\t\tid: \"username\",\n\t\t$InferServerPlugin: {} as ReturnType<typeof username>,\n\t} satisfies AuthClientPlugin;\n};\n","import type { BetterFetch, BetterFetchOption } from \"@better-fetch/fetch\";\nimport {\n\tWebAuthnError,\n\tstartAuthentication,\n\tstartRegistration,\n} from \"@simplewebauthn/browser\";\nimport type {\n\tPublicKeyCredentialCreationOptionsJSON,\n\tPublicKeyCredentialRequestOptionsJSON,\n} from \"@simplewebauthn/types\";\nimport type { Session } from \"inspector\";\nimport type { User } from \"../../adapters/schema\";\nimport type { passkey as passkeyPl, Passkey } from \"../../plugins\";\nimport type { AuthClientPlugin } from \"../../client/types\";\nimport { logger } from \"../../utils/logger\";\nimport { useAuthQuery } from \"../../client\";\nimport { atom } from \"nanostores\";\n\nexport const getPasskeyActions = (\n\t$fetch: BetterFetch,\n\t{\n\t\t_listPasskeys,\n\t}: {\n\t\t_listPasskeys: ReturnType<typeof atom<any>>;\n\t},\n) => {\n\tconst signInPasskey = async (opts?: {\n\t\tautoFill?: boolean;\n\t\temail?: string;\n\t\tcallbackURL?: string;\n\t}) => {\n\t\tconst response = await $fetch<PublicKeyCredentialRequestOptionsJSON>(\n\t\t\t\"/passkey/generate-authenticate-options\",\n\t\t\t{\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: {\n\t\t\t\t\temail: opts?.email,\n\t\t\t\t\tcallbackURL: opts?.callbackURL,\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t\tif (!response.data) {\n\t\t\treturn response;\n\t\t}\n\t\ttry {\n\t\t\tconst res = await startAuthentication(\n\t\t\t\tresponse.data,\n\t\t\t\topts?.autoFill || false,\n\t\t\t);\n\t\t\tconst verified = await $fetch<{\n\t\t\t\tsession: Session;\n\t\t\t\tuser: User;\n\t\t\t}>(\"/passkey/verify-authentication\", {\n\t\t\t\tbody: {\n\t\t\t\t\tresponse: res,\n\t\t\t\t},\n\t\t\t});\n\t\t\tif (!verified.data) {\n\t\t\t\treturn verified;\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tconsole.log(e);\n\t\t}\n\t};\n\n\tconst registerPasskey = async (opts?: {\n\t\toptions?: BetterFetchOption;\n\t\t/**\n\t\t * The name of the passkey. This is used to\n\t\t * identify the passkey in the UI.\n\t\t */\n\t\tname?: string;\n\t}) => {\n\t\tconst options = await $fetch<PublicKeyCredentialCreationOptionsJSON>(\n\t\t\t\"/passkey/generate-register-options\",\n\t\t\t{\n\t\t\t\tmethod: \"GET\",\n\t\t\t\t...opts?.options,\n\t\t\t},\n\t\t);\n\t\tif (!options.data) {\n\t\t\treturn options;\n\t\t}\n\t\ttry {\n\t\t\tconst res = await startRegistration(options.data);\n\t\t\tconst verified = await $fetch<{\n\t\t\t\tpasskey: Passkey;\n\t\t\t}>(\"/passkey/verify-registration\", {\n\t\t\t\t...opts?.options,\n\t\t\t\tbody: {\n\t\t\t\t\tresponse: res,\n\t\t\t\t\tname: opts?.name,\n\t\t\t\t},\n\t\t\t});\n\t\t\tif (!verified.data) {\n\t\t\t\treturn verified;\n\t\t\t}\n\t\t\t_listPasskeys.set(Math.random());\n\t\t} catch (e) {\n\t\t\tif (e instanceof WebAuthnError) {\n\t\t\t\tif (e.code === \"ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED\") {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tdata: null,\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tmessage: \"previously registered\",\n\t\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\t\tstatusText: \"BAD_REQUEST\",\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tif (e.code === \"ERROR_CEREMONY_ABORTED\") {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tdata: null,\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tmessage: \"registration cancelled\",\n\t\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\t\tstatusText: \"BAD_REQUEST\",\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tdata: null,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tmessage: e.message,\n\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\tstatusText: \"BAD_REQUEST\",\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t\tlogger.error(e, \"passkey registration error\");\n\t\t\treturn {\n\t\t\t\tdata: null,\n\t\t\t\terror: {\n\t\t\t\t\tmessage: e instanceof Error ? e.message : \"unknown error\",\n\t\t\t\t\tstatus: 500,\n\t\t\t\t\tstatusText: \"INTERNAL_SERVER_ERROR\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t};\n\n\treturn {\n\t\tsignIn: {\n\t\t\t/**\n\t\t\t * Sign in with a registered passkey\n\t\t\t */\n\t\t\tpasskey: signInPasskey,\n\t\t},\n\t\tpasskey: {\n\t\t\t/**\n\t\t\t * Add a passkey to the user account\n\t\t\t */\n\t\t\taddPasskey: registerPasskey,\n\t\t},\n\t\t/**\n\t\t * Inferred Internal Types\n\t\t */\n\t\t$Infer: {} as {\n\t\t\tPasskey: Passkey;\n\t\t},\n\t};\n};\n\nexport const passkeyClient = () => {\n\tconst _listPasskeys = atom<any>();\n\treturn {\n\t\tid: \"passkey\",\n\t\t$InferServerPlugin: {} as ReturnType<typeof passkeyPl>,\n\t\tgetActions: ($fetch) =>\n\t\t\tgetPasskeyActions($fetch, {\n\t\t\t\t_listPasskeys,\n\t\t\t}),\n\t\tgetAtoms($fetch) {\n\t\t\tconst listPasskeys = useAuthQuery<Passkey[]>(\n\t\t\t\t_listPasskeys,\n\t\t\t\t\"/passkey/list-user-passkeys\",\n\t\t\t\t$fetch,\n\t\t\t\t{\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\tcredentials: \"include\",\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tlistPasskeys,\n\t\t\t\t_listPasskeys,\n\t\t\t};\n\t\t\t444;\n\t\t},\n\t\tpathMethods: {\n\t\t\t\"/passkey/register\": \"POST\",\n\t\t\t\"/passkey/authenticate\": \"POST\",\n\t\t},\n\t\tatomListeners: [\n\t\t\t{\n\t\t\t\tmatcher(path) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\tpath === \"/passkey/verify-registration\" ||\n\t\t\t\t\t\tpath === \"/passkey/delete-passkey\"\n\t\t\t\t\t);\n\t\t\t\t},\n\t\t\t\tsignal: \"_listPasskeys\",\n\t\t\t},\n\t\t],\n\t} satisfies AuthClientPlugin;\n};\n","import { createConsola } from \"consola\";\n\nconst consola = createConsola({\n\tformatOptions: {\n\t\tdate: false,\n\t\tcolors: true,\n\t\tcompact: true,\n\t},\n\tdefaults: {\n\t\ttag: \"Better Auth\",\n\t},\n});\n\nexport const createLogger = (options?: {\n\tdisabled?: boolean;\n}) => {\n\treturn {\n\t\tlog: (...args: any[]) => {\n\t\t\t!options?.disabled && consola.log(\"\", ...args);\n\t\t},\n\t\terror: (...args: any[]) => {\n\t\t\t!options?.disabled && consola.error(\"\", ...args);\n\t\t},\n\t\twarn: (...args: any[]) => {\n\t\t\t!options?.disabled && consola.warn(\"\", ...args);\n\t\t},\n\t\tinfo: (...args: any[]) => {\n\t\t\t!options?.disabled && consola.info(\"\", ...args);\n\t\t},\n\t\tdebug: (...args: any[]) => {\n\t\t\t!options?.disabled && consola.debug(\"\", ...args);\n\t\t},\n\t\tbox: (...args: any[]) => {\n\t\t\t!options?.disabled && consola.box(\"\", ...args);\n\t\t},\n\t\tsuccess: (...args: any[]) => {\n\t\t\t!options?.disabled && consola.success(\"\", ...args);\n\t\t},\n\t\tbreak: (...args: any[]) => {\n\t\t\t!options?.disabled && console.log(\"\\n\");\n\t\t},\n\t};\n};\n\nexport const logger = createLogger();\n","import type { AuthClientPlugin } from \"../../client/types\";\nimport type { twoFactor as twoFa } from \"../../plugins/two-factor\";\n\nexport const twoFactorClient = (\n\toptions: {\n\t\ttwoFactorPage: string;\n\t\t/**\n\t\t * Redirect to the two factor page. If twoFactorPage\n\t\t * is not set this will redirect to the root path.\n\t\t * @default true\n\t\t */\n\t\tredirect?: boolean;\n\t} = {\n\t\tredirect: true,\n\t\ttwoFactorPage: \"/\",\n\t},\n) => {\n\treturn {\n\t\tid: \"two-factor\",\n\t\t$InferServerPlugin: {} as ReturnType<typeof twoFa>,\n\t\tatomListeners: [\n\t\t\t{\n\t\t\t\tmatcher: (path) =>\n\t\t\t\t\tpath === \"/two-factor/enable\" ||\n\t\t\t\t\tpath === \"/two-factor/send-otp\" ||\n\t\t\t\t\tpath === \"/two-factor/disable\",\n\t\t\t\tsignal: \"_sessionSignal\",\n\t\t\t},\n\t\t],\n\t\tpathMethods: {\n\t\t\t\"enable/totp\": \"POST\",\n\t\t\t\"/two-factor/disable\": \"POST\",\n\t\t\t\"/two-factor/enable\": \"POST\",\n\t\t\t\"/two-factor/send-otp\": \"POST\",\n\t\t},\n\t\tfetchPlugins: [\n\t\t\t{\n\t\t\t\tid: \"two-factor\",\n\t\t\t\tname: \"two-factor\",\n\t\t\t\thooks: {\n\t\t\t\t\tasync onSuccess(context) {\n\t\t\t\t\t\tif (context.data?.twoFactorRedirect) {\n\t\t\t\t\t\t\tif (options.redirect || options.twoFactorPage) {\n\t\t\t\t\t\t\t\tif (typeof window !== \"undefined\") {\n\t\t\t\t\t\t\t\t\twindow.location.href = options.twoFactorPage;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t} satisfies AuthClientPlugin;\n};\n"],"mappings":"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","names":["atom","atom","value","atom","atom"]}
1
+ {"version":3,"sources":["../../src/plugins/organization/client.ts","../../src/plugins/organization/access/src/access.ts","../../src/plugins/organization/access/statement.ts","../../src/client/config.ts","../../src/client/fetch-plugins.ts","../../src/client/session-atom.ts","../../src/client/query.ts","../../src/plugins/username/client.ts","../../src/plugins/passkey/client.ts","../../src/utils/logger.ts","../../src/plugins/two-factor/client.ts"],"sourcesContent":["import { atom } from \"nanostores\";\nimport type {\n\tInvitation,\n\tMember,\n\tOrganization,\n} from \"../../plugins/organization/schema\";\nimport type { Prettify } from \"../../types/helper\";\nimport { defaultStatements, type AccessControl, type Role } from \"./access\";\nimport type { AuthClientPlugin } from \"../../client/types\";\nimport type { organization } from \"./organization\";\nimport type { BetterFetchOption } from \"@better-fetch/fetch\";\nimport { useAuthQuery } from \"../../client\";\n\ninterface OrganizationClientOptions {\n\tac: AccessControl;\n\troles?: {\n\t\t[key in \"admin\" | \"member\" | \"owner\"]?: Role<any>;\n\t};\n}\n\nexport const organizationClient = <O extends OrganizationClientOptions>(\n\toptions?: O,\n) => {\n\tconst activeOrgId = atom<string | null | undefined>(undefined);\n\tconst _listOrg = atom<boolean>(false);\n\tconst _activeOrgSignal = atom<boolean>(false);\n\n\ttype DefaultStatements = typeof defaultStatements;\n\ttype Statements = O[\"ac\"] extends AccessControl<infer S>\n\t\t? S extends Record<string, Array<any>>\n\t\t\t? S & DefaultStatements\n\t\t\t: DefaultStatements\n\t\t: DefaultStatements;\n\treturn {\n\t\tid: \"organization\",\n\t\t$InferServerPlugin: {} as ReturnType<typeof organization>,\n\t\tgetActions: ($fetch) => ({\n\t\t\torganization: {\n\t\t\t\t$Infer: {\n\t\t\t\t\tActiveOrganization: {} as Prettify<\n\t\t\t\t\t\tOrganization & {\n\t\t\t\t\t\t\tmembers: Prettify<\n\t\t\t\t\t\t\t\tMember & {\n\t\t\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\t\t\tid: string;\n\t\t\t\t\t\t\t\t\t\tname: string;\n\t\t\t\t\t\t\t\t\t\temail: string;\n\t\t\t\t\t\t\t\t\t\timage: string;\n\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t>[];\n\t\t\t\t\t\t\tinvitations: Invitation[];\n\t\t\t\t\t\t}\n\t\t\t\t\t>,\n\t\t\t\t\tOrganization: {} as Organization,\n\t\t\t\t\tInvitation: {} as Invitation,\n\t\t\t\t\tMember: {} as Member,\n\t\t\t\t},\n\t\t\t\tsetActive(orgId: string | null) {\n\t\t\t\t\tactiveOrgId.set(orgId);\n\t\t\t\t},\n\t\t\t\thasPermission: async (data: {\n\t\t\t\t\tpermission: Partial<{\n\t\t\t\t\t\t//@ts-expect-error fix this later\n\t\t\t\t\t\t[key in keyof Statements]: Statements[key][number][];\n\t\t\t\t\t}>;\n\t\t\t\t\tfetchOptions?: BetterFetchOption;\n\t\t\t\t}) => {\n\t\t\t\t\treturn await $fetch<{\n\t\t\t\t\t\tsuccess: boolean;\n\t\t\t\t\t}>(\"/organization/has-permission\", {\n\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\tpermission: data.permission,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t...data.fetchOptions,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t},\n\t\t}),\n\t\tgetAtoms: ($fetch) => {\n\t\t\tconst listOrganizations = useAuthQuery<Organization[]>(\n\t\t\t\t_listOrg,\n\t\t\t\t\"/organization/list\",\n\t\t\t\t$fetch,\n\t\t\t\t{\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t},\n\t\t\t);\n\t\t\tconst activeOrganization = useAuthQuery<\n\t\t\t\tPrettify<\n\t\t\t\t\tOrganization & {\n\t\t\t\t\t\tmembers: (Member & {\n\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\tid: string;\n\t\t\t\t\t\t\t\tname: string;\n\t\t\t\t\t\t\t\temail: string;\n\t\t\t\t\t\t\t\timage: string;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t})[];\n\t\t\t\t\t\tinvitations: Invitation[];\n\t\t\t\t\t}\n\t\t\t\t>\n\t\t\t>(\n\t\t\t\t[activeOrgId, _activeOrgSignal],\n\t\t\t\t\"/organization/activate\",\n\t\t\t\t$fetch,\n\t\t\t\t() => ({\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tcredentials: \"include\",\n\t\t\t\t\tbody: {\n\t\t\t\t\t\torgId: activeOrgId.get(),\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\t_listOrg,\n\t\t\t\t_activeOrgSignal,\n\t\t\t\tactiveOrganization,\n\t\t\t\tlistOrganizations,\n\t\t\t};\n\t\t},\n\t\tatomListeners: [\n\t\t\t{\n\t\t\t\tmatcher(path) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\tpath === \"/organization/create\" || path === \"/organization/delete\"\n\t\t\t\t\t);\n\t\t\t\t},\n\t\t\t\tsignal: \"_listOrg\",\n\t\t\t},\n\t\t\t{\n\t\t\t\tmatcher(path) {\n\t\t\t\t\treturn path.startsWith(\"/organization\");\n\t\t\t\t},\n\t\t\t\tsignal: \"_activeOrgSignal\",\n\t\t\t},\n\t\t],\n\t} satisfies AuthClientPlugin;\n};\n","import type { StatementsPrimitive as Statements, Subset } from \"./types\";\n\nexport class ParsingError extends Error {\n\tpublic readonly path: string;\n\tconstructor(message: string, path: string) {\n\t\tsuper(message);\n\t\tthis.path = path;\n\t}\n}\n\ntype Connector = \"OR\" | \"AND\";\n\nexport class AccessControl<TStatements extends Statements = Statements> {\n\tprivate readonly statements: TStatements;\n\tconstructor(private readonly s: TStatements) {\n\t\tthis.statements = s;\n\t}\n\tpublic newRole<K extends keyof TStatements>(\n\t\tstatements: Subset<K, TStatements>,\n\t) {\n\t\treturn new Role<Subset<K, TStatements>>(statements);\n\t}\n}\n\nexport type AuthortizeResponse =\n\t| { success: false; error: string }\n\t| { success: true; error?: never };\n\nexport class Role<TStatements extends Statements> {\n\tpublic readonly statements: TStatements;\n\n\tconstructor(statements: TStatements) {\n\t\tthis.statements = statements;\n\t}\n\n\tpublic authorize<K extends keyof TStatements>(\n\t\trequest: Subset<K, TStatements>,\n\t\tconnector?: Connector,\n\t): AuthortizeResponse {\n\t\tfor (const [requestedResource, requestedActions] of Object.entries(\n\t\t\trequest,\n\t\t)) {\n\t\t\tconst allowedActions = this.statements[requestedResource];\n\t\t\tif (!allowedActions) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: `You are not allowed to access resource: ${requestedResource}`,\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst success =\n\t\t\t\tconnector === \"OR\"\n\t\t\t\t\t? (requestedActions as string[]).some((requestedAction) =>\n\t\t\t\t\t\t\tallowedActions.includes(requestedAction),\n\t\t\t\t\t\t)\n\t\t\t\t\t: (requestedActions as string[]).every((requestedAction) =>\n\t\t\t\t\t\t\tallowedActions.includes(requestedAction),\n\t\t\t\t\t\t);\n\t\t\tif (success) {\n\t\t\t\treturn { success };\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: `unauthorized to access resource \"${requestedResource}\"`,\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: \"Not authorized\",\n\t\t};\n\t}\n\n\tstatic fromString<TStatements extends Statements>(s: string) {\n\t\tconst statements = JSON.parse(s) as TStatements;\n\n\t\tif (typeof statements !== \"object\") {\n\t\t\tthrow new ParsingError(\"statements is not an object\", \".\");\n\t\t}\n\t\tfor (const [resource, actions] of Object.entries(statements)) {\n\t\t\tif (typeof resource !== \"string\") {\n\t\t\t\tthrow new ParsingError(\"invalid resource identifier\", resource);\n\t\t\t}\n\t\t\tif (!Array.isArray(actions)) {\n\t\t\t\tthrow new ParsingError(\"actions is not an array\", resource);\n\t\t\t}\n\t\t\tfor (let i = 0; i < actions.length; i++) {\n\t\t\t\tif (typeof actions[i] !== \"string\") {\n\t\t\t\t\tthrow new ParsingError(\"action is not a string\", `${resource}[${i}]`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn new Role<TStatements>(statements);\n\t}\n\n\tpublic toString(): string {\n\t\treturn JSON.stringify(this.statements);\n\t}\n}\n","import { AccessControl } from \"./src/access\";\nimport type { StatementsPrimitive } from \"./src/types\";\n\nexport const createAccessControl = <S extends StatementsPrimitive>(\n\tstatements: S,\n) => {\n\treturn new AccessControl<S>(statements);\n};\n\nexport const defaultStatements = {\n\torganization: [\"update\", \"delete\"],\n\tmember: [\"create\", \"update\", \"delete\"],\n\tinvitation: [\"create\", \"cancel\"],\n} as const;\n\nexport const defaultAc = createAccessControl(defaultStatements);\n\nexport const adminAc = defaultAc.newRole({\n\torganization: [\"update\"],\n\tinvitation: [\"create\", \"cancel\"],\n\tmember: [\"create\", \"update\", \"delete\"],\n});\n\nexport const ownerAc = defaultAc.newRole({\n\torganization: [\"update\", \"delete\"],\n\tmember: [\"create\", \"update\", \"delete\"],\n\tinvitation: [\"create\", \"cancel\"],\n});\n\nexport const memberAc = defaultAc.newRole({\n\torganization: [],\n\tmember: [],\n\tinvitation: [],\n});\n\nexport const defaultRoles = {\n\tadmin: adminAc,\n\towner: ownerAc,\n\tmember: memberAc,\n};\n","import { createFetch } from \"@better-fetch/fetch\";\nimport { getBaseURL } from \"../utils/base-url\";\nimport { type Atom } from \"nanostores\";\nimport type { AtomListener, ClientOptions } from \"./types\";\nimport { addCurrentURL, csrfPlugin, redirectPlugin } from \"./fetch-plugins\";\n\nexport const getClientConfig = <O extends ClientOptions>(options?: O) => {\n\tconst $fetch = createFetch({\n\t\tbaseURL: getBaseURL(options?.fetchOptions?.baseURL || options?.baseURL),\n\t\tcredentials: \"include\",\n\t\t...options?.fetchOptions,\n\t\tplugins: [\n\t\t\tcsrfPlugin,\n\t\t\tredirectPlugin,\n\t\t\taddCurrentURL,\n\t\t\t...(options?.fetchOptions?.plugins?.filter((pl) => pl !== undefined) ||\n\t\t\t\t[]),\n\t\t\t...(options?.plugins\n\t\t\t\t?.flatMap((plugin) => plugin.fetchPlugins)\n\t\t\t\t.filter((pl) => pl !== undefined) || []),\n\t\t],\n\t});\n\tconst plugins = options?.plugins || [];\n\tlet pluginsActions = {} as Record<string, any>;\n\tlet pluginsAtoms = {} as Record<string, Atom<any>>;\n\tlet pluginPathMethods: Record<string, \"POST\" | \"GET\"> = {\n\t\t\"/sign-out\": \"POST\",\n\t\t\"/user/revoke-sessions\": \"POST\",\n\t};\n\tconst atomListeners: AtomListener[] = [\n\t\t{\n\t\t\tsignal: \"_sessionSignal\",\n\t\t\tmatcher(path) {\n\t\t\t\treturn (\n\t\t\t\t\tpath === \"/sign-out\" ||\n\t\t\t\t\tpath === \"sign-up/email\" ||\n\t\t\t\t\tpath === \"/user/update\"\n\t\t\t\t);\n\t\t\t},\n\t\t},\n\t];\n\tfor (const plugin of plugins) {\n\t\tif (plugin.getActions) {\n\t\t\tObject.assign(pluginsActions, plugin.getActions?.($fetch));\n\t\t}\n\t\tif (plugin.getAtoms) {\n\t\t\tObject.assign(pluginsAtoms, plugin.getAtoms?.($fetch));\n\t\t}\n\t\tif (plugin.pathMethods) {\n\t\t\tObject.assign(pluginPathMethods, plugin.pathMethods);\n\t\t}\n\t\tif (plugin.atomListeners) {\n\t\t\tatomListeners.push(...plugin.atomListeners);\n\t\t}\n\t}\n\treturn {\n\t\tpluginsActions,\n\t\tpluginsAtoms,\n\t\tpluginPathMethods,\n\t\tatomListeners,\n\t\t$fetch,\n\t};\n};\n","import { type BetterFetchPlugin, betterFetch } from \"@better-fetch/fetch\";\nimport { BetterAuthError } from \"../error/better-auth-error\";\n\nexport const redirectPlugin = {\n\tid: \"redirect\",\n\tname: \"Redirect\",\n\thooks: {\n\t\tonSuccess(context) {\n\t\t\tif (context.data?.url && context.data?.redirect) {\n\t\t\t\tif (typeof window !== \"undefined\") {\n\t\t\t\t\twindow.location.href = context.data.url;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t},\n} satisfies BetterFetchPlugin;\n\nexport const addCurrentURL = {\n\tid: \"add-current-url\",\n\tname: \"Add current URL\",\n\thooks: {\n\t\tonRequest(context) {\n\t\t\tif (typeof window !== \"undefined\") {\n\t\t\t\tconst url = new URL(context.url);\n\t\t\t\turl.searchParams.set(\"currentURL\", window.location.href);\n\t\t\t\tcontext.url = url;\n\t\t\t}\n\t\t\treturn context;\n\t\t},\n\t},\n} satisfies BetterFetchPlugin;\n\nconst cache = new Map<string, string>();\nexport const csrfPlugin = {\n\tid: \"csrf\",\n\tname: \"CSRF Check\",\n\tasync init(url, options) {\n\t\tif (!options?.baseURL) {\n\t\t\tthrow new BetterAuthError(\n\t\t\t\t\"API Base URL on the auth client isn't configured. Please pass it directly to the client `baseURL`\",\n\t\t\t);\n\t\t}\n\n\t\tif (options?.method !== \"GET\") {\n\t\t\toptions = options || {};\n\t\t\tconst csrfToken = cache.get(\"CSRF_TOKEN\");\n\t\t\tif (!csrfToken) {\n\t\t\t\tconst { data, error } = await betterFetch<{\n\t\t\t\t\tcsrfToken: string;\n\t\t\t\t}>(\"/csrf\", {\n\t\t\t\t\tbody: undefined,\n\t\t\t\t\tbaseURL: options.baseURL,\n\t\t\t\t\tplugins: [],\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\tcredentials: \"include\",\n\t\t\t\t\tcustomFetchImpl: options.customFetchImpl,\n\t\t\t\t});\n\t\t\t\tif (error) {\n\t\t\t\t\tif (error.status === 404) {\n\t\t\t\t\t\tthrow new BetterAuthError(\n\t\t\t\t\t\t\t\"CSRF route not found. Make sure the server is running and the base URL is correct and includes the path (e.g. http://localhost:3000/api/auth).\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (error.status === 429) {\n\t\t\t\t\t\treturn new Response(null, {\n\t\t\t\t\t\t\tstatus: 429,\n\t\t\t\t\t\t\tstatusText: \"Too Many Requests\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tthrow new BetterAuthError(\n\t\t\t\t\t\t\"Failed to fetch CSRF token: \" + error.message,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tcache.set(\"CSRF_TOKEN\", data.csrfToken);\n\t\t\t}\n\t\t\toptions.body = {\n\t\t\t\t...options?.body,\n\t\t\t\tcsrfToken: csrfToken,\n\t\t\t};\n\t\t}\n\t\toptions.credentials = \"include\";\n\t\treturn { url, options };\n\t},\n} satisfies BetterFetchPlugin;\n","import type { BetterFetch } from \"@better-fetch/fetch\";\nimport { atom } from \"nanostores\";\nimport type { Auth as BetterAuth } from \"../auth\";\nimport type { Prettify, UnionToIntersection } from \"../types/helper\";\nimport type { InferSession, InferUser } from \"../types/models\";\nimport type { AuthClientPlugin, ClientOptions } from \"./types\";\nimport { useAuthQuery } from \"./query\";\nimport type { BetterAuthPlugin } from \"../plugins\";\n\nexport function getSessionAtom<Option extends ClientOptions>(\n\tclient: BetterFetch,\n) {\n\ttype Plugins = Option[\"plugins\"] extends Array<AuthClientPlugin>\n\t\t? Array<\n\t\t\t\tOption[\"plugins\"][number] extends infer T\n\t\t\t\t\t? T extends AuthClientPlugin\n\t\t\t\t\t\t? T[\"$InferServerPlugin\"] extends infer U\n\t\t\t\t\t\t\t? U extends BetterAuthPlugin\n\t\t\t\t\t\t\t\t? U\n\t\t\t\t\t\t\t\t: never\n\t\t\t\t\t\t\t: never\n\t\t\t\t\t\t: never\n\t\t\t\t\t: never\n\t\t\t>\n\t\t: never;\n\n\ttype Auth = {\n\t\thandler: any;\n\t\tapi: any;\n\t\toptions: {\n\t\t\tdatabase: any;\n\t\t\tplugins: Plugins;\n\t\t};\n\t};\n\n\ttype UserWithAdditionalFields = InferUser<Auth[\"options\"]>;\n\ttype SessionWithAdditionalFields = InferSession<Auth[\"options\"]>;\n\tconst $signal = atom<boolean>(false);\n\tconst session = useAuthQuery<{\n\t\tuser: Prettify<UserWithAdditionalFields>;\n\t\tsession: Prettify<SessionWithAdditionalFields>;\n\t}>($signal, \"/session\", client, {\n\t\tmethod: \"GET\",\n\t});\n\treturn {\n\t\t$session: session,\n\t\t_sessionSignal: $signal,\n\t\t$Infer: {} as {\n\t\t\tSession: {\n\t\t\t\tsession: Prettify<SessionWithAdditionalFields>;\n\t\t\t\tuser: Prettify<UserWithAdditionalFields>;\n\t\t\t};\n\t\t},\n\t};\n}\n","import {\n\tBetterFetchError,\n\ttype BetterFetch,\n\ttype BetterFetchOption,\n} from \"@better-fetch/fetch\";\nimport { atom, type PreinitializedWritableAtom } from \"nanostores\";\n\nexport const useAuthQuery = <T>(\n\tinitializedAtom:\n\t\t| PreinitializedWritableAtom<any>\n\t\t| PreinitializedWritableAtom<any>[],\n\tpath: string,\n\t$fetch: BetterFetch,\n\toptions?:\n\t\t| ((value: {\n\t\t\t\tdata: null | T;\n\t\t\t\terror: null | BetterFetchError;\n\t\t\t\tisPending: boolean;\n\t\t }) => BetterFetchOption)\n\t\t| BetterFetchOption,\n) => {\n\tconst value = atom<{\n\t\tdata: null | T;\n\t\terror: null | BetterFetchError;\n\t\tisPending: boolean;\n\t}>({\n\t\tdata: null,\n\t\terror: null,\n\t\tisPending: false,\n\t});\n\n\tconst fn = () => {\n\t\tconst opts =\n\t\t\ttypeof options === \"function\"\n\t\t\t\t? options({\n\t\t\t\t\t\tdata: value.get().data,\n\t\t\t\t\t\terror: value.get().error,\n\t\t\t\t\t\tisPending: value.get().isPending,\n\t\t\t\t\t})\n\t\t\t\t: options;\n\t\treturn $fetch<T>(path, {\n\t\t\t...opts,\n\t\t\tonSuccess: async (context) => {\n\t\t\t\tvalue.set({\n\t\t\t\t\tdata: context.data,\n\t\t\t\t\terror: null,\n\t\t\t\t\tisPending: false,\n\t\t\t\t});\n\t\t\t\tawait opts?.onSuccess?.(context);\n\t\t\t},\n\t\t\tasync onError(context) {\n\t\t\t\tvalue.set({\n\t\t\t\t\terror: context.error,\n\t\t\t\t\tdata: null,\n\t\t\t\t\tisPending: false,\n\t\t\t\t});\n\t\t\t\tawait opts?.onError?.(context);\n\t\t\t},\n\t\t\tasync onRequest(context) {\n\t\t\t\tconst currentValue = value.get();\n\t\t\t\tvalue.set({\n\t\t\t\t\tisPending: true,\n\t\t\t\t\tdata: currentValue.data,\n\t\t\t\t\terror: currentValue.error,\n\t\t\t\t});\n\t\t\t\tawait opts?.onRequest?.(context);\n\t\t\t},\n\t\t});\n\t};\n\tfn();\n\tinitializedAtom = Array.isArray(initializedAtom)\n\t\t? initializedAtom\n\t\t: [initializedAtom];\n\tlet firstRun = true;\n\tfor (const initAtom of initializedAtom) {\n\t\tinitAtom.subscribe((value) => {\n\t\t\tif (!firstRun) {\n\t\t\t\tfn();\n\t\t\t}\n\t\t});\n\t}\n\tfirstRun = false;\n\treturn value;\n};\n","import type { username } from \".\";\nimport type { AuthClientPlugin } from \"../../client/types\";\n\nexport const usernameClient = () => {\n\treturn {\n\t\tid: \"username\",\n\t\t$InferServerPlugin: {} as ReturnType<typeof username>,\n\t} satisfies AuthClientPlugin;\n};\n","import type { BetterFetch, BetterFetchOption } from \"@better-fetch/fetch\";\nimport {\n\tWebAuthnError,\n\tstartAuthentication,\n\tstartRegistration,\n} from \"@simplewebauthn/browser\";\nimport type {\n\tPublicKeyCredentialCreationOptionsJSON,\n\tPublicKeyCredentialRequestOptionsJSON,\n} from \"@simplewebauthn/types\";\nimport type { Session } from \"inspector\";\nimport type { User } from \"../../adapters/schema\";\nimport type { passkey as passkeyPl, Passkey } from \"../../plugins\";\nimport type { AuthClientPlugin } from \"../../client/types\";\nimport { logger } from \"../../utils/logger\";\nimport { useAuthQuery } from \"../../client\";\nimport { atom } from \"nanostores\";\n\nexport const getPasskeyActions = (\n\t$fetch: BetterFetch,\n\t{\n\t\t_listPasskeys,\n\t}: {\n\t\t_listPasskeys: ReturnType<typeof atom<any>>;\n\t},\n) => {\n\tconst signInPasskey = async (opts?: {\n\t\tautoFill?: boolean;\n\t\temail?: string;\n\t\tcallbackURL?: string;\n\t}) => {\n\t\tconst response = await $fetch<PublicKeyCredentialRequestOptionsJSON>(\n\t\t\t\"/passkey/generate-authenticate-options\",\n\t\t\t{\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: {\n\t\t\t\t\temail: opts?.email,\n\t\t\t\t\tcallbackURL: opts?.callbackURL,\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t\tif (!response.data) {\n\t\t\treturn response;\n\t\t}\n\t\ttry {\n\t\t\tconst res = await startAuthentication(\n\t\t\t\tresponse.data,\n\t\t\t\topts?.autoFill || false,\n\t\t\t);\n\t\t\tconst verified = await $fetch<{\n\t\t\t\tsession: Session;\n\t\t\t\tuser: User;\n\t\t\t}>(\"/passkey/verify-authentication\", {\n\t\t\t\tbody: {\n\t\t\t\t\tresponse: res,\n\t\t\t\t},\n\t\t\t});\n\t\t\tif (!verified.data) {\n\t\t\t\treturn verified;\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tconsole.log(e);\n\t\t}\n\t};\n\n\tconst registerPasskey = async (opts?: {\n\t\toptions?: BetterFetchOption;\n\t\t/**\n\t\t * The name of the passkey. This is used to\n\t\t * identify the passkey in the UI.\n\t\t */\n\t\tname?: string;\n\t}) => {\n\t\tconst options = await $fetch<PublicKeyCredentialCreationOptionsJSON>(\n\t\t\t\"/passkey/generate-register-options\",\n\t\t\t{\n\t\t\t\tmethod: \"GET\",\n\t\t\t\t...opts?.options,\n\t\t\t},\n\t\t);\n\t\tif (!options.data) {\n\t\t\treturn options;\n\t\t}\n\t\ttry {\n\t\t\tconst res = await startRegistration(options.data);\n\t\t\tconst verified = await $fetch<{\n\t\t\t\tpasskey: Passkey;\n\t\t\t}>(\"/passkey/verify-registration\", {\n\t\t\t\t...opts?.options,\n\t\t\t\tbody: {\n\t\t\t\t\tresponse: res,\n\t\t\t\t\tname: opts?.name,\n\t\t\t\t},\n\t\t\t});\n\t\t\tif (!verified.data) {\n\t\t\t\treturn verified;\n\t\t\t}\n\t\t\t_listPasskeys.set(Math.random());\n\t\t} catch (e) {\n\t\t\tif (e instanceof WebAuthnError) {\n\t\t\t\tif (e.code === \"ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED\") {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tdata: null,\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tmessage: \"previously registered\",\n\t\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\t\tstatusText: \"BAD_REQUEST\",\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tif (e.code === \"ERROR_CEREMONY_ABORTED\") {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tdata: null,\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tmessage: \"registration cancelled\",\n\t\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\t\tstatusText: \"BAD_REQUEST\",\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tdata: null,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tmessage: e.message,\n\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\tstatusText: \"BAD_REQUEST\",\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t\tlogger.error(e, \"passkey registration error\");\n\t\t\treturn {\n\t\t\t\tdata: null,\n\t\t\t\terror: {\n\t\t\t\t\tmessage: e instanceof Error ? e.message : \"unknown error\",\n\t\t\t\t\tstatus: 500,\n\t\t\t\t\tstatusText: \"INTERNAL_SERVER_ERROR\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t};\n\n\treturn {\n\t\tsignIn: {\n\t\t\t/**\n\t\t\t * Sign in with a registered passkey\n\t\t\t */\n\t\t\tpasskey: signInPasskey,\n\t\t},\n\t\tpasskey: {\n\t\t\t/**\n\t\t\t * Add a passkey to the user account\n\t\t\t */\n\t\t\taddPasskey: registerPasskey,\n\t\t},\n\t\t/**\n\t\t * Inferred Internal Types\n\t\t */\n\t\t$Infer: {} as {\n\t\t\tPasskey: Passkey;\n\t\t},\n\t};\n};\n\nexport const passkeyClient = () => {\n\tconst _listPasskeys = atom<any>();\n\treturn {\n\t\tid: \"passkey\",\n\t\t$InferServerPlugin: {} as ReturnType<typeof passkeyPl>,\n\t\tgetActions: ($fetch) =>\n\t\t\tgetPasskeyActions($fetch, {\n\t\t\t\t_listPasskeys,\n\t\t\t}),\n\t\tgetAtoms($fetch) {\n\t\t\tconst listPasskeys = useAuthQuery<Passkey[]>(\n\t\t\t\t_listPasskeys,\n\t\t\t\t\"/passkey/list-user-passkeys\",\n\t\t\t\t$fetch,\n\t\t\t\t{\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\tcredentials: \"include\",\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tlistPasskeys,\n\t\t\t\t_listPasskeys,\n\t\t\t};\n\t\t\t444;\n\t\t},\n\t\tpathMethods: {\n\t\t\t\"/passkey/register\": \"POST\",\n\t\t\t\"/passkey/authenticate\": \"POST\",\n\t\t},\n\t\tatomListeners: [\n\t\t\t{\n\t\t\t\tmatcher(path) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\tpath === \"/passkey/verify-registration\" ||\n\t\t\t\t\t\tpath === \"/passkey/delete-passkey\"\n\t\t\t\t\t);\n\t\t\t\t},\n\t\t\t\tsignal: \"_listPasskeys\",\n\t\t\t},\n\t\t],\n\t} satisfies AuthClientPlugin;\n};\n","import { createConsola } from \"consola\";\n\nconst consola = createConsola({\n\tformatOptions: {\n\t\tdate: false,\n\t\tcolors: true,\n\t\tcompact: true,\n\t},\n\tdefaults: {\n\t\ttag: \"Better Auth\",\n\t},\n});\n\nexport const createLogger = (options?: {\n\tdisabled?: boolean;\n}) => {\n\treturn {\n\t\tlog: (...args: any[]) => {\n\t\t\t!options?.disabled && consola.log(\"\", ...args);\n\t\t},\n\t\terror: (...args: any[]) => {\n\t\t\t!options?.disabled && consola.error(\"\", ...args);\n\t\t},\n\t\twarn: (...args: any[]) => {\n\t\t\t!options?.disabled && consola.warn(\"\", ...args);\n\t\t},\n\t\tinfo: (...args: any[]) => {\n\t\t\t!options?.disabled && consola.info(\"\", ...args);\n\t\t},\n\t\tdebug: (...args: any[]) => {\n\t\t\t!options?.disabled && consola.debug(\"\", ...args);\n\t\t},\n\t\tbox: (...args: any[]) => {\n\t\t\t!options?.disabled && consola.box(\"\", ...args);\n\t\t},\n\t\tsuccess: (...args: any[]) => {\n\t\t\t!options?.disabled && consola.success(\"\", ...args);\n\t\t},\n\t\tbreak: (...args: any[]) => {\n\t\t\t!options?.disabled && console.log(\"\\n\");\n\t\t},\n\t};\n};\n\nexport const logger = createLogger();\n","import type { AuthClientPlugin } from \"../../client/types\";\nimport type { twoFactor as twoFa } from \"../../plugins/two-factor\";\n\nexport const twoFactorClient = (\n\toptions: {\n\t\ttwoFactorPage: string;\n\t\t/**\n\t\t * Redirect to the two factor page. If twoFactorPage\n\t\t * is not set this will redirect to the root path.\n\t\t * @default true\n\t\t */\n\t\tredirect?: boolean;\n\t} = {\n\t\tredirect: true,\n\t\ttwoFactorPage: \"/\",\n\t},\n) => {\n\treturn {\n\t\tid: \"two-factor\",\n\t\t$InferServerPlugin: {} as ReturnType<typeof twoFa>,\n\t\tatomListeners: [\n\t\t\t{\n\t\t\t\tmatcher: (path) =>\n\t\t\t\t\tpath === \"/two-factor/enable\" ||\n\t\t\t\t\tpath === \"/two-factor/send-otp\" ||\n\t\t\t\t\tpath === \"/two-factor/disable\",\n\t\t\t\tsignal: \"_sessionSignal\",\n\t\t\t},\n\t\t],\n\t\tpathMethods: {\n\t\t\t\"/two-factor/disable\": \"POST\",\n\t\t\t\"/two-factor/enable\": \"POST\",\n\t\t\t\"/two-factor/send-otp\": \"POST\",\n\t\t},\n\t\tfetchPlugins: [\n\t\t\t{\n\t\t\t\tid: \"two-factor\",\n\t\t\t\tname: \"two-factor\",\n\t\t\t\thooks: {\n\t\t\t\t\tasync onSuccess(context) {\n\t\t\t\t\t\tif (context.data?.twoFactorRedirect) {\n\t\t\t\t\t\t\tif (options.redirect || options.twoFactorPage) {\n\t\t\t\t\t\t\t\tif (typeof window !== \"undefined\") {\n\t\t\t\t\t\t\t\t\twindow.location.href = options.twoFactorPage;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t} satisfies AuthClientPlugin;\n};\n"],"mappings":"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","names":["atom","atom","value","atom","atom"]}
@@ -1898,7 +1898,6 @@ declare const twoFactorClient: (options?: {
1898
1898
  signal: string;
1899
1899
  }[];
1900
1900
  pathMethods: {
1901
- "enable/totp": "POST";
1902
1901
  "/two-factor/disable": "POST";
1903
1902
  "/two-factor/enable": "POST";
1904
1903
  "/two-factor/send-otp": "POST";
package/dist/plugins.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { a as OrganizationOptions, c as Passkey, P as PasskeyOptions, W as WebAuthnCookieType, g as getPasskeyActions, o as organization, d as passkey, p as passkeyClient, b as twoFactor, t as twoFactorClient, u as username } from './index-BAR_7S7m.js';
1
+ export { a as OrganizationOptions, c as Passkey, P as PasskeyOptions, W as WebAuthnCookieType, g as getPasskeyActions, o as organization, d as passkey, p as passkeyClient, b as twoFactor, t as twoFactorClient, u as username } from './index-TgPPn8w5.js';
2
2
  export { i as ac } from './index-BMwSnG5w.js';
3
3
  import { H as HookEndpointContext } from './internal-adapter-c3hLHHXV.js';
4
4
  export { A as AuthEndpoint, d as AuthMiddleware, B as BetterAuthPlugin, P as PluginSchema, b as createAuthEndpoint, c as createAuthMiddleware, o as optionsMiddleware } from './internal-adapter-c3hLHHXV.js';
@@ -129,32 +129,37 @@ declare const rateLimiter: (options: RateLimitOptions) => {
129
129
  middleware: better_call.Endpoint<better_call.Handler<string, better_call.EndpointOptions, Response | undefined>, better_call.EndpointOptions>;
130
130
  }[];
131
131
  schema: {
132
- readonly rateLimit: {
133
- readonly fields: {
134
- readonly key: {
135
- readonly type: "string";
132
+ rateLimit: {
133
+ fields: {
134
+ key: {
135
+ type: "string";
136
136
  };
137
- readonly count: {
138
- readonly type: "number";
137
+ count: {
138
+ type: "number";
139
139
  };
140
- readonly lastRequest: {
141
- readonly type: "number";
140
+ lastRequest: {
141
+ type: "number";
142
142
  };
143
143
  };
144
+ disableMigration: boolean;
144
145
  };
145
- } | undefined;
146
+ };
146
147
  };
147
148
 
148
149
  interface MagicLinkOptions {
149
150
  /**
150
151
  * Time in seconds until the magic link expires.
151
- * @default (60 * 60) // 1 hour
152
+ * @default (60 * 5) // 5 minutes
152
153
  */
153
154
  expiresIn?: number;
154
155
  /**
155
156
  * Send magic link implementation.
156
157
  */
157
- sendMagicLink: (email: string, url: string) => Promise<void> | void;
158
+ sendMagicLink: (data: {
159
+ email: string;
160
+ url: string;
161
+ token: string;
162
+ }) => Promise<void> | void;
158
163
  }
159
164
  declare const magicLink: (options: MagicLinkOptions) => {
160
165
  id: "magic-link";
package/dist/plugins.js CHANGED
@@ -4195,7 +4195,6 @@ var twoFactorClient = (options = {
4195
4195
  }
4196
4196
  ],
4197
4197
  pathMethods: {
4198
- "enable/totp": "POST",
4199
4198
  "/two-factor/disable": "POST",
4200
4199
  "/two-factor/enable": "POST",
4201
4200
  "/two-factor/send-otp": "POST"
@@ -5450,21 +5449,6 @@ var rateLimiter = (options) => {
5450
5449
  ],
5451
5450
  ...options
5452
5451
  };
5453
- const schema = opts.storage.provider === "database" ? {
5454
- rateLimit: {
5455
- fields: {
5456
- key: {
5457
- type: "string"
5458
- },
5459
- count: {
5460
- type: "number"
5461
- },
5462
- lastRequest: {
5463
- type: "number"
5464
- }
5465
- }
5466
- }
5467
- } : void 0;
5468
5452
  function createDBStorage(ctx) {
5469
5453
  const db = ctx.context.db;
5470
5454
  return {
@@ -5563,7 +5547,22 @@ var rateLimiter = (options) => {
5563
5547
  })
5564
5548
  }
5565
5549
  ],
5566
- schema
5550
+ schema: {
5551
+ rateLimit: {
5552
+ fields: {
5553
+ key: {
5554
+ type: "string"
5555
+ },
5556
+ count: {
5557
+ type: "number"
5558
+ },
5559
+ lastRequest: {
5560
+ type: "number"
5561
+ }
5562
+ },
5563
+ disableMigration: opts.storage.provider !== "database"
5564
+ }
5565
+ }
5567
5566
  };
5568
5567
  };
5569
5568
 
@@ -5571,6 +5570,7 @@ var rateLimiter = (options) => {
5571
5570
  import { z as z22 } from "zod";
5572
5571
  import { APIError as APIError12 } from "better-call";
5573
5572
  import { validateJWT as validateJWT3 } from "oslo/jwt";
5573
+ import "process";
5574
5574
  var magicLink = (options) => {
5575
5575
  return {
5576
5576
  id: "magic-link",
@@ -5600,7 +5600,11 @@ var magicLink = (options) => {
5600
5600
  );
5601
5601
  const url = `${ctx.context.baseURL}/magic-link/verify?token=${token}&callbackURL=${ctx.body.callbackURL || ctx.body.currentURL}`;
5602
5602
  try {
5603
- await options.sendMagicLink(email, url);
5603
+ await options.sendMagicLink({
5604
+ email,
5605
+ url,
5606
+ token
5607
+ });
5604
5608
  } catch (e) {
5605
5609
  ctx.context.logger.error("Failed to send magic link", e);
5606
5610
  throw new APIError12("INTERNAL_SERVER_ERROR", {
@@ -5633,6 +5637,9 @@ var magicLink = (options) => {
5633
5637
  );
5634
5638
  } catch (e) {
5635
5639
  ctx.context.logger.error("Failed to verify email", e);
5640
+ if (callbackURL) {
5641
+ throw ctx.redirect(`${callbackURL}?error=INVALID_TOKEN`);
5642
+ }
5636
5643
  return ctx.json(null, {
5637
5644
  status: 400,
5638
5645
  statusText: "INVALID_TOKEN",
@@ -5649,6 +5656,9 @@ var magicLink = (options) => {
5649
5656
  parsed.email
5650
5657
  );
5651
5658
  if (!user) {
5659
+ if (callbackURL) {
5660
+ throw ctx.redirect(`${callbackURL}?error=USER_NOT_FOUND`);
5661
+ }
5652
5662
  return ctx.json(null, {
5653
5663
  status: 400,
5654
5664
  statusText: "USER_NOT_FOUND",
@@ -5662,6 +5672,9 @@ var magicLink = (options) => {
5662
5672
  ctx.headers
5663
5673
  );
5664
5674
  if (!session) {
5675
+ if (callbackURL) {
5676
+ throw ctx.redirect(`${callbackURL}?error=SESSION_NOT_CREATED`);
5677
+ }
5665
5678
  return ctx.json(null, {
5666
5679
  status: 400,
5667
5680
  statusText: "SESSION NOT CREATED",