everything-dev
Version:
A consolidated product package for building Module Federation apps with oRPC APIs.
1 lines • 13.2 kB
Source Map (JSON)
{"version":3,"file":"auth.mjs","names":["createBetterAuthClient"],"sources":["../../src/ui/auth.ts"],"sourcesContent":["import { apiKeyClient } from \"@better-auth/api-key/client\";\nimport { passkeyClient } from \"@better-auth/passkey/client\";\nimport { type QueryClient, useQuery } from \"@tanstack/react-query\";\nimport { useRouter } from \"@tanstack/react-router\";\nimport {\n adminClient,\n anonymousClient,\n deviceAuthorizationClient,\n inferAdditionalFields,\n organizationClient,\n phoneNumberClient,\n} from \"better-auth/client/plugins\";\nimport { createAuthClient as createBetterAuthClient } from \"better-auth/react\";\nimport type { PasskeyWalletLink, RelayedTransactionT } from \"better-near-auth\";\nimport { DEFAULT_DEVICE_LINK_CLIENT_ID, siwnClient } from \"better-near-auth/client\";\nimport type { ClientRuntimeConfig } from \"../types\";\nimport { getRuntimeConfig } from \"./runtime\";\n\ntype RuntimeAuthVariables = {\n siwn: {\n recipient?: string;\n recipients?: {\n mainnet?: string;\n testnet?: string;\n };\n };\n deviceLink?: {\n clientId?: string;\n };\n};\n\nexport type CreateAuthClientOptions = {\n runtimeConfig?: Partial<ClientRuntimeConfig>;\n headers?: HeadersInit;\n cspNonce?: string;\n};\n\ntype SiwnClientConfig = Parameters<typeof siwnClient>[0] & {\n cspNonce?: string;\n};\n\nfunction hasAuthVariables(auth: ClientRuntimeConfig[\"auth\"] | undefined): auth is NonNullable<\n ClientRuntimeConfig[\"auth\"]\n> & {\n variables: RuntimeAuthVariables;\n} {\n return !!auth && typeof auth === \"object\" && typeof auth.variables === \"object\";\n}\n\nfunction readRuntimeConfig(config?: Partial<ClientRuntimeConfig>) {\n if (config) return config;\n if (typeof window === \"undefined\") return undefined;\n try {\n return getRuntimeConfig();\n } catch {\n return undefined;\n }\n}\n\nfunction getAuthVariables(config?: Partial<ClientRuntimeConfig>): RuntimeAuthVariables {\n const runtimeConfig = readRuntimeConfig(config);\n if (!runtimeConfig || !hasAuthVariables(runtimeConfig.auth)) {\n throw new Error(\"Missing auth runtime configuration\");\n }\n return runtimeConfig.auth.variables;\n}\n\nfunction getSiwnClientConfig(options: CreateAuthClientOptions): SiwnClientConfig {\n const runtimeConfig = readRuntimeConfig(options.runtimeConfig);\n const variables = getAuthVariables(options.runtimeConfig);\n const siwn = variables.siwn;\n\n const mainnetRecipient = siwn.recipients?.mainnet ?? siwn.recipient;\n if (!mainnetRecipient) {\n throw new Error(\"Missing auth SIWN recipient\");\n }\n\n const networkId =\n runtimeConfig?.networkId ?? (mainnetRecipient.endsWith(\".testnet\") ? \"testnet\" : \"mainnet\");\n const testnetRecipient = siwn.recipients?.testnet;\n\n if (testnetRecipient) {\n return {\n recipients: { mainnet: mainnetRecipient, testnet: testnetRecipient },\n networkId,\n cspNonce: options.cspNonce,\n };\n }\n\n return { recipient: mainnetRecipient, networkId, cspNonce: options.cspNonce };\n}\n\nfunction getHostUrl(config?: Partial<ClientRuntimeConfig>) {\n const runtimeConfig = readRuntimeConfig(config);\n if (runtimeConfig?.hostUrl) return runtimeConfig.hostUrl;\n if (typeof window !== \"undefined\") return window.location.origin;\n return \"\";\n}\n\nexport function getDeviceLinkClientId(config?: Partial<ClientRuntimeConfig>): string {\n const runtimeConfig = readRuntimeConfig(config);\n const variables = runtimeConfig?.auth?.variables as RuntimeAuthVariables | undefined;\n return variables?.deviceLink?.clientId ?? DEFAULT_DEVICE_LINK_CLIENT_ID;\n}\n\nexport function createAuthClient(options: CreateAuthClientOptions = {}) {\n const nearAuthConfig = getSiwnClientConfig(options);\n\n return createBetterAuthClient({\n baseURL: getHostUrl(options.runtimeConfig),\n fetchOptions: {\n credentials: \"include\",\n ...(options.headers ? { headers: options.headers } : {}),\n },\n plugins: [\n inferAdditionalFields({\n user: {\n locale: { type: \"string\", required: false, input: true },\n },\n }),\n siwnClient(nearAuthConfig),\n adminClient(),\n anonymousClient(),\n phoneNumberClient(),\n passkeyClient(),\n organizationClient({ teams: { enabled: true } }),\n apiKeyClient(),\n deviceAuthorizationClient(),\n ],\n });\n}\n\nexport type { AuthContext } from \"./auth-guards\";\nexport {\n clearAuthenticatedQueries,\n requireAdmin,\n requireSession,\n} from \"./auth-guards\";\nexport { pluginHref, pluginPath, pluginSearch } from \"./plugin-path\";\n\nexport type AuthClient = ReturnType<typeof createAuthClient>;\n\nexport type SessionData = AuthClient[\"$Infer\"][\"Session\"];\n\n/**\n * Explicit shapes for the organization/passkey records — better-auth's client\n * inference collapses to `any` for these plugin endpoints, which would leak\n * `any` into every consumer union.\n */\nexport interface Organization {\n id: string;\n name: string;\n slug?: string | null;\n logo?: string | null;\n createdAt?: Date | string | null;\n metadata?: Record<string, unknown> | null;\n}\n\nexport interface Passkey {\n id: string;\n name?: string | null;\n createdAt?: Date | string | null;\n lastUsedAt?: Date | string | null;\n}\n\nexport function useAuthClient(): AuthClient {\n return useRouter().options.context.authClient as AuthClient;\n}\n\nexport const sessionQueryKey = [\"session\"] as const;\n\nexport function sessionQueryOptions(authClient: AuthClient) {\n return {\n queryKey: sessionQueryKey,\n queryFn: async () => {\n const { data: session, error } = await authClient.getSession({\n query: { disableCookieCache: true },\n });\n if (error) throw new Error(error.message || \"Unable to load your session\");\n return session ?? null;\n },\n staleTime: 60 * 1000,\n gcTime: 10 * 60 * 1000,\n };\n}\n\nexport async function refreshSessionCache(\n authClient: AuthClient,\n queryClient: QueryClient,\n): Promise<SessionData | null> {\n return queryClient.fetchQuery({ ...sessionQueryOptions(authClient), staleTime: 0 });\n}\n\n/**\n * Resolves the session for the root route: the query cache wins (it is kept\n * authoritative by the single sessionQueryOptions read path), and a populated\n * router-context session — the host's SSR resolution — seeds an empty cache so\n * the dehydrated state carries it to the client.\n */\nexport function resolveSessionFromCache<T>(\n queryClient: QueryClient | undefined,\n contextSession: T | null | undefined,\n): T | null | undefined {\n if (!queryClient) return contextSession;\n\n const cachedSession = queryClient.getQueryData<T | null>(sessionQueryKey);\n if (cachedSession !== undefined) return cachedSession;\n\n if (contextSession !== undefined) {\n queryClient.setQueryData(sessionQueryKey, contextSession);\n }\n return contextSession;\n}\n\nexport function useRelayHistory(session: SessionData | null | undefined, authClient: AuthClient) {\n return useQuery({\n queryKey: [\"relay-history\"],\n queryFn: async (): Promise<RelayedTransactionT[]> => {\n const res = await authClient.near.relayHistory();\n return res?.data?.transactions ?? [];\n },\n enabled: !!session,\n refetchInterval: 2000,\n });\n}\n\nexport type PasskeyWalletStatus = PasskeyWalletLink;\n\nexport type PasskeyCeremonyError = Error & { code?: string };\n\nconst UNSUPPORTED_AUTHENTICATOR_CODES = new Set([\n \"PASSKEY_UNSUPPORTED_AUTHENTICATOR\",\n \"ERROR_AUTHENTICATOR_NO_SUPPORTED_PUBKEYCREDPARAMS_ALG\",\n \"ERROR_AUTHENTICATOR_MISSING_DISCOVERABLE_CREDENTIAL_SUPPORT\",\n \"ERROR_AUTHENTICATOR_MISSING_USER_VERIFICATION_SUPPORT\",\n]);\n\nexport function isUnsupportedAuthenticatorError(error: unknown): boolean {\n if (!(error instanceof Error) || !(\"code\" in error)) return false;\n return typeof error.code === \"string\" && UNSUPPORTED_AUTHENTICATOR_CODES.has(error.code);\n}\n\nfunction toPasskeyError(\n error: { code?: string; message?: string } | null | undefined,\n fallback: string,\n): PasskeyCeremonyError {\n return Object.assign(new Error(error?.message || fallback), { code: error?.code });\n}\n\nexport async function isPasskeyAutofillAvailable(): Promise<boolean> {\n if (typeof window === \"undefined\" || !window.PublicKeyCredential) return false;\n try {\n return (await window.PublicKeyCredential.isConditionalMediationAvailable?.()) === true;\n } catch {\n return false;\n }\n}\n\nexport async function createAccountWithPasskey(\n authClient: AuthClient,\n options?: {\n onSuccess?: (result: { passkeyWallet?: PasskeyWalletStatus }) => void;\n onError?: (error: PasskeyCeremonyError) => void;\n },\n): Promise<void> {\n try {\n const { data, error } = await authClient.passkey.addPasskey();\n if (error || !data) {\n options?.onError?.(toPasskeyError(error, \"Could not create your account\"));\n return;\n }\n const { passkeyWallet } = data as { passkeyWallet?: PasskeyWalletStatus };\n options?.onSuccess?.({ passkeyWallet });\n } catch (error) {\n options?.onError?.(\n toPasskeyError(error instanceof Error ? error : null, \"Could not create your account\"),\n );\n }\n}\n\nexport async function signInWithPasskey(\n authClient: AuthClient,\n options?: {\n autoFill?: boolean;\n onSuccess?: () => void;\n onError?: (error: PasskeyCeremonyError) => void;\n },\n): Promise<void> {\n try {\n const { data, error } = await authClient.signIn.passkey({ autoFill: options?.autoFill });\n if (error || !data) {\n options?.onError?.(toPasskeyError(error, \"Passkey sign-in failed\"));\n return;\n }\n options?.onSuccess?.();\n } catch (error) {\n options?.onError?.(\n toPasskeyError(error instanceof Error ? error : null, \"Passkey sign-in failed\"),\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;AAyCA,SAAS,iBAAiB,MAIxB;CACA,OAAO,CAAC,CAAC,QAAQ,OAAO,SAAS,YAAY,OAAO,KAAK,cAAc;AACzE;AAEA,SAAS,kBAAkB,QAAuC;CAChE,IAAI,QAAQ,OAAO;CACnB,IAAI,OAAO,WAAW,aAAa,OAAO;CAC1C,IAAI;EACF,OAAO,iBAAiB;CAC1B,QAAQ;EACN;CACF;AACF;AAEA,SAAS,iBAAiB,QAA6D;CACrF,MAAM,gBAAgB,kBAAkB,MAAM;CAC9C,IAAI,CAAC,iBAAiB,CAAC,iBAAiB,cAAc,IAAI,GACxD,MAAM,IAAI,MAAM,oCAAoC;CAEtD,OAAO,cAAc,KAAK;AAC5B;AAEA,SAAS,oBAAoB,SAAoD;CAC/E,MAAM,gBAAgB,kBAAkB,QAAQ,aAAa;CAE7D,MAAM,OADY,iBAAiB,QAAQ,aACtB,CAAC,CAAC;CAEvB,MAAM,mBAAmB,KAAK,YAAY,WAAW,KAAK;CAC1D,IAAI,CAAC,kBACH,MAAM,IAAI,MAAM,6BAA6B;CAG/C,MAAM,YACJ,eAAe,cAAc,iBAAiB,SAAS,UAAU,IAAI,YAAY;CACnF,MAAM,mBAAmB,KAAK,YAAY;CAE1C,IAAI,kBACF,OAAO;EACL,YAAY;GAAE,SAAS;GAAkB,SAAS;EAAiB;EACnE;EACA,UAAU,QAAQ;CACpB;CAGF,OAAO;EAAE,WAAW;EAAkB;EAAW,UAAU,QAAQ;CAAS;AAC9E;AAEA,SAAS,WAAW,QAAuC;CACzD,MAAM,gBAAgB,kBAAkB,MAAM;CAC9C,IAAI,eAAe,SAAS,OAAO,cAAc;CACjD,IAAI,OAAO,WAAW,aAAa,OAAO,OAAO,SAAS;CAC1D,OAAO;AACT;AAEA,SAAgB,sBAAsB,QAA+C;CAGnF,QAFsB,kBAAkB,MACV,CAAC,EAAE,MAAM,UACvB,EAAE,YAAY,YAAY;AAC5C;AAEA,SAAgB,iBAAiB,UAAmC,CAAC,GAAG;CACtE,MAAM,iBAAiB,oBAAoB,OAAO;CAElD,OAAOA,mBAAuB;EAC5B,SAAS,WAAW,QAAQ,aAAa;EACzC,cAAc;GACZ,aAAa;GACb,GAAI,QAAQ,UAAU,EAAE,SAAS,QAAQ,QAAQ,IAAI,CAAC;EACxD;EACA,SAAS;GACP,sBAAsB,EACpB,MAAM,EACJ,QAAQ;IAAE,MAAM;IAAU,UAAU;IAAO,OAAO;GAAK,EACzD,EACF,CAAC;GACD,WAAW,cAAc;GACzB,YAAY;GACZ,gBAAgB;GAChB,kBAAkB;GAClB,cAAc;GACd,mBAAmB,EAAE,OAAO,EAAE,SAAS,KAAK,EAAE,CAAC;GAC/C,aAAa;GACb,0BAA0B;EAC5B;CACF,CAAC;AACH;AAmCA,SAAgB,gBAA4B;CAC1C,OAAO,UAAU,CAAC,CAAC,QAAQ,QAAQ;AACrC;AAEA,MAAa,kBAAkB,CAAC,SAAS;AAEzC,SAAgB,oBAAoB,YAAwB;CAC1D,OAAO;EACL,UAAU;EACV,SAAS,YAAY;GACnB,MAAM,EAAE,MAAM,SAAS,UAAU,MAAM,WAAW,WAAW,EAC3D,OAAO,EAAE,oBAAoB,KAAK,EACpC,CAAC;GACD,IAAI,OAAO,MAAM,IAAI,MAAM,MAAM,WAAW,6BAA6B;GACzE,OAAO,WAAW;EACpB;EACA,WAAW;EACX,QAAQ;CACV;AACF;AAEA,eAAsB,oBACpB,YACA,aAC6B;CAC7B,OAAO,YAAY,WAAW;EAAE,GAAG,oBAAoB,UAAU;EAAG,WAAW;CAAE,CAAC;AACpF;;;;;;;AAQA,SAAgB,wBACd,aACA,gBACsB;CACtB,IAAI,CAAC,aAAa,OAAO;CAEzB,MAAM,gBAAgB,YAAY,aAAuB,eAAe;CACxE,IAAI,kBAAkB,QAAW,OAAO;CAExC,IAAI,mBAAmB,QACrB,YAAY,aAAa,iBAAiB,cAAc;CAE1D,OAAO;AACT;AAEA,SAAgB,gBAAgB,SAAyC,YAAwB;CAC/F,OAAO,SAAS;EACd,UAAU,CAAC,eAAe;EAC1B,SAAS,YAA4C;GAEnD,QAAO,MADW,WAAW,KAAK,aAAa,EACrC,EAAE,MAAM,gBAAgB,CAAC;EACrC;EACA,SAAS,CAAC,CAAC;EACX,iBAAiB;CACnB,CAAC;AACH;AAMA,MAAM,kDAAkC,IAAI,IAAI;CAC9C;CACA;CACA;CACA;AACF,CAAC;AAED,SAAgB,gCAAgC,OAAyB;CACvE,IAAI,EAAE,iBAAiB,UAAU,EAAE,UAAU,QAAQ,OAAO;CAC5D,OAAO,OAAO,MAAM,SAAS,YAAY,gCAAgC,IAAI,MAAM,IAAI;AACzF;AAEA,SAAS,eACP,OACA,UACsB;CACtB,OAAO,OAAO,OAAO,IAAI,MAAM,OAAO,WAAW,QAAQ,GAAG,EAAE,MAAM,OAAO,KAAK,CAAC;AACnF;AAEA,eAAsB,6BAA+C;CACnE,IAAI,OAAO,WAAW,eAAe,CAAC,OAAO,qBAAqB,OAAO;CACzE,IAAI;EACF,OAAQ,MAAM,OAAO,oBAAoB,kCAAkC,MAAO;CACpF,QAAQ;EACN,OAAO;CACT;AACF;AAEA,eAAsB,yBACpB,YACA,SAIe;CACf,IAAI;EACF,MAAM,EAAE,MAAM,UAAU,MAAM,WAAW,QAAQ,WAAW;EAC5D,IAAI,SAAS,CAAC,MAAM;GAClB,SAAS,UAAU,eAAe,OAAO,+BAA+B,CAAC;GACzE;EACF;EACA,MAAM,EAAE,kBAAkB;EAC1B,SAAS,YAAY,EAAE,cAAc,CAAC;CACxC,SAAS,OAAO;EACd,SAAS,UACP,eAAe,iBAAiB,QAAQ,QAAQ,MAAM,+BAA+B,CACvF;CACF;AACF;AAEA,eAAsB,kBACpB,YACA,SAKe;CACf,IAAI;EACF,MAAM,EAAE,MAAM,UAAU,MAAM,WAAW,OAAO,QAAQ,EAAE,UAAU,SAAS,SAAS,CAAC;EACvF,IAAI,SAAS,CAAC,MAAM;GAClB,SAAS,UAAU,eAAe,OAAO,wBAAwB,CAAC;GAClE;EACF;EACA,SAAS,YAAY;CACvB,SAAS,OAAO;EACd,SAAS,UACP,eAAe,iBAAiB,QAAQ,QAAQ,MAAM,wBAAwB,CAChF;CACF;AACF"}