@korajs/auth 1.0.0-beta.0 → 1.0.0-beta.10

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.
package/dist/react.cjs CHANGED
@@ -154,9 +154,39 @@ var import_react = require("react");
154
154
  var AuthContext = (0, import_react.createContext)(null);
155
155
 
156
156
  // src/react/AuthProvider.tsx
157
+ var sessionEntries = /* @__PURE__ */ new WeakMap();
158
+ function getSessionEntry(client) {
159
+ const existing = sessionEntries.get(client);
160
+ if (existing) return existing;
161
+ const entry = {
162
+ session: createAuthSession(client),
163
+ refs: 0,
164
+ destroyTimer: null
165
+ };
166
+ sessionEntries.set(client, entry);
167
+ return entry;
168
+ }
169
+ function retainSession(entry) {
170
+ if (entry.destroyTimer) {
171
+ clearTimeout(entry.destroyTimer);
172
+ entry.destroyTimer = null;
173
+ }
174
+ entry.refs++;
175
+ return () => {
176
+ entry.refs = Math.max(0, entry.refs - 1);
177
+ if (entry.refs > 0 || entry.destroyTimer) return;
178
+ entry.destroyTimer = setTimeout(() => {
179
+ entry.destroyTimer = null;
180
+ if (entry.refs > 0) return;
181
+ entry.session.destroy();
182
+ sessionEntries.delete(entry.session.client);
183
+ }, 0);
184
+ };
185
+ }
157
186
  function AuthProvider({ client, children, fallback }) {
158
- const session = (0, import_react2.useMemo)(() => createAuthSession(client), [client]);
159
- (0, import_react2.useEffect)(() => () => session.destroy(), [session]);
187
+ const entry = (0, import_react2.useMemo)(() => getSessionEntry(client), [client]);
188
+ const session = entry.session;
189
+ (0, import_react2.useEffect)(() => retainSession(entry), [entry]);
160
190
  const snapshot = (0, import_react2.useSyncExternalStore)(
161
191
  (onStoreChange) => session.subscribe(onStoreChange),
162
192
  () => session.getSnapshot(),
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/react.ts","../src/react/AuthProvider.tsx","../src/bindings/create-auth-session.ts","../src/react/auth-context.ts","../src/react/hooks.ts","../src/react/OrgProvider.tsx","../src/bindings/create-org-session.ts","../src/react/org-hooks.ts"],"sourcesContent":["// @korajs/auth/react — React-specific public API\n// Every export here is a public API commitment. Be explicit.\n\n// === Provider ===\nexport { AuthProvider } from './react/AuthProvider'\nexport type { AuthProviderProps } from './react/AuthProvider'\n\n// === Hooks ===\nexport { useAuth, useCurrentUser, useAuthStatus } from './react/hooks'\nexport type { UseAuthResult, AuthStatus } from './react/hooks'\n\n// === Context (for advanced use cases) ===\nexport { AuthContext } from './react/auth-context'\nexport type { AuthContextValue } from './react/auth-context'\n\n// === Organization Hooks ===\nexport { OrgProvider } from './react/OrgProvider'\nexport type { OrgProviderProps } from './react/OrgProvider'\nexport {\n\tOrgContext,\n\tuseOrg,\n\tuseOrgMembers,\n\tusePermission,\n\tcheckOrgPermission,\n} from './react/org-hooks'\nexport type { OrgContextValue, UseOrgResult, UseOrgMembersResult } from './react/org-hooks'\n","import { createElement, useEffect, useMemo, useSyncExternalStore } from 'react'\nimport type { ReactElement, ReactNode } from 'react'\nimport { createAuthSession } from '../bindings/create-auth-session'\nimport type { AuthClient } from '../client/auth-client'\nimport { AuthContext } from './auth-context'\n\ninterface AuthProviderProps {\n\tclient: AuthClient\n\tchildren: ReactNode\n\tfallback?: ReactNode\n}\n\nfunction AuthProvider({ client, children, fallback }: AuthProviderProps): ReactElement {\n\tconst session = useMemo(() => createAuthSession(client), [client])\n\n\tuseEffect(() => () => session.destroy(), [session])\n\n\tconst snapshot = useSyncExternalStore(\n\t\t(onStoreChange) => session.subscribe(onStoreChange),\n\t\t() => session.getSnapshot(),\n\t\t() => session.getSnapshot(),\n\t)\n\n\tif (snapshot.initError) {\n\t\treturn createElement(\n\t\t\t'div',\n\t\t\t{\n\t\t\t\tstyle: { color: 'red', padding: '1rem', fontFamily: 'monospace' },\n\t\t\t\trole: 'alert',\n\t\t\t},\n\t\t\tcreateElement('strong', null, 'Kora Auth initialization error: '),\n\t\t\tsnapshot.initError.message,\n\t\t)\n\t}\n\n\tif (snapshot.isLoading && fallback !== undefined) {\n\t\treturn fallback as ReactElement\n\t}\n\n\tconst contextValue = {\n\t\tclient,\n\t\tsession,\n\t\tstate: snapshot.state,\n\t\tisLoading: snapshot.isLoading,\n\t}\n\n\treturn createElement(AuthContext.Provider, { value: contextValue }, children)\n}\n\nexport { AuthProvider }\nexport type { AuthProviderProps }\n","import type {\n\tAuthClient,\n\tAuthState,\n\tAuthUser,\n\tLinkedOAuthAccount,\n\tOAuthAuthorizationOptions,\n\tOAuthAuthorizationResult,\n\tOAuthCallbackParams,\n} from '../client/auth-client'\n\nexport interface AuthSessionSnapshot {\n\tstate: AuthState\n\tuser: AuthUser | null\n\tisAuthenticated: boolean\n\tisLoading: boolean\n\tinitError: Error | null\n\terror: string | null\n}\n\nexport interface AuthSession {\n\treadonly client: AuthClient\n\tgetSnapshot(): AuthSessionSnapshot\n\tsubscribe(listener: () => void): () => void\n\tsignUp(params: {\n\t\temail: string\n\t\tpassword: string\n\t\tname?: string\n\t\tdeviceId?: string\n\t\tdevicePublicKey?: string\n\t}): Promise<void>\n\tsignIn(params: {\n\t\temail: string\n\t\tpassword: string\n\t\tdeviceId?: string\n\t\tdevicePublicKey?: string\n\t}): Promise<void>\n\tsignInWithOAuth(\n\t\tprovider: string,\n\t\toptions?: OAuthAuthorizationOptions,\n\t): Promise<OAuthAuthorizationResult>\n\tcompleteOAuthSignIn(provider: string, params: OAuthCallbackParams): Promise<void>\n\tgetOAuthAuthorizationUrl(\n\t\tprovider: string,\n\t\toptions?: OAuthAuthorizationOptions,\n\t): Promise<OAuthAuthorizationResult>\n\tlinkOAuth(provider: string, params: OAuthCallbackParams): Promise<LinkedOAuthAccount | null>\n\tlistLinkedAccounts(): Promise<LinkedOAuthAccount[]>\n\tunlinkOAuth(provider: string): Promise<void>\n\tsignOut(): Promise<void>\n\tdestroy(): void\n}\n\n/**\n * Framework-agnostic auth session: initialization, reactive snapshot, and client methods.\n */\nexport function createAuthSession(client: AuthClient): AuthSession {\n\tlet state: AuthState = client.state\n\tlet isLoading = true\n\tlet initError: Error | null = null\n\tlet lastError: string | null = null\n\n\tconst listeners = new Set<() => void>()\n\tlet snapshot = buildSnapshot()\n\n\tconst refreshSnapshot = (): void => {\n\t\tsnapshot = buildSnapshot()\n\t}\n\n\tconst notify = (): void => {\n\t\trefreshSnapshot()\n\t\tfor (const listener of listeners) {\n\t\t\tlistener()\n\t\t}\n\t}\n\n\tfunction buildSnapshot(): AuthSessionSnapshot {\n\t\treturn {\n\t\t\tstate,\n\t\t\tuser: client.currentUser,\n\t\t\tisAuthenticated: state === 'authenticated',\n\t\t\tisLoading,\n\t\t\tinitError,\n\t\t\terror: lastError,\n\t\t}\n\t}\n\n\tconst captureError = (error: unknown): void => {\n\t\tlastError = error instanceof Error ? error.message : String(error)\n\t\tnotify()\n\t}\n\n\tconst run = async (action: () => Promise<void>): Promise<void> => {\n\t\tlastError = null\n\t\ttry {\n\t\t\tawait action()\n\t\t} catch (error) {\n\t\t\tcaptureError(error)\n\t\t}\n\t}\n\n\tconst runWithResult = async <T>(action: () => Promise<T>): Promise<T | null> => {\n\t\tlastError = null\n\t\ttry {\n\t\t\treturn await action()\n\t\t} catch (error) {\n\t\t\tcaptureError(error)\n\t\t\treturn null\n\t\t}\n\t}\n\n\tconst unsubscribeAuth = client.onAuthChange((nextState) => {\n\t\tstate = nextState\n\t\tnotify()\n\t})\n\n\tvoid client\n\t\t.initialize()\n\t\t.then(() => {\n\t\t\tstate = client.state\n\t\t\tisLoading = false\n\t\t\tnotify()\n\t\t})\n\t\t.catch((error: unknown) => {\n\t\t\tinitError = error instanceof Error ? error : new Error(String(error))\n\t\t\tisLoading = false\n\t\t\tnotify()\n\t\t})\n\n\treturn {\n\t\tclient,\n\t\tgetSnapshot: () => snapshot,\n\t\tsubscribe(listener) {\n\t\t\tlisteners.add(listener)\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete(listener)\n\t\t\t}\n\t\t},\n\t\tsignUp: (params) =>\n\t\t\trun(async () => {\n\t\t\t\tawait client.signUp(params)\n\t\t\t}),\n\t\tsignIn: (params) =>\n\t\t\trun(async () => {\n\t\t\t\tawait client.signIn(params)\n\t\t\t}),\n\t\tsignInWithOAuth: async (provider, options) => {\n\t\t\tlastError = null\n\t\t\ttry {\n\t\t\t\treturn await client.signInWithOAuth(provider, options)\n\t\t\t} catch (error) {\n\t\t\t\tcaptureError(error)\n\t\t\t\tthrow error instanceof Error ? error : new Error(String(error))\n\t\t\t}\n\t\t},\n\t\tcompleteOAuthSignIn: (provider, params) =>\n\t\t\trun(async () => {\n\t\t\t\tawait client.completeOAuthSignIn(provider, params)\n\t\t\t}),\n\t\tgetOAuthAuthorizationUrl: async (provider, options) => {\n\t\t\tlastError = null\n\t\t\ttry {\n\t\t\t\treturn await client.getOAuthAuthorizationUrl(provider, options)\n\t\t\t} catch (error) {\n\t\t\t\tcaptureError(error)\n\t\t\t\tthrow error instanceof Error ? error : new Error(String(error))\n\t\t\t}\n\t\t},\n\t\tlinkOAuth: (provider, params) => runWithResult(async () => client.linkOAuth(provider, params)),\n\t\tlistLinkedAccounts: () =>\n\t\t\trunWithResult(async () => client.listLinkedAccounts()).then((value) => value ?? []),\n\t\tunlinkOAuth: (provider) =>\n\t\t\trun(async () => {\n\t\t\t\tawait client.unlinkOAuth(provider)\n\t\t\t}),\n\t\tsignOut: () =>\n\t\t\trun(async () => {\n\t\t\t\tawait client.signOut()\n\t\t\t}),\n\t\tdestroy() {\n\t\t\tunsubscribeAuth()\n\t\t\tlisteners.clear()\n\t\t},\n\t}\n}\n","import { createContext } from 'react'\nimport type { AuthSession } from '../bindings/create-auth-session'\nimport type { AuthClient } from '../client/auth-client'\n\n/**\n * Possible authentication states for the client.\n */\ntype AuthState = 'loading' | 'authenticated' | 'unauthenticated'\n\n/**\n * Shape of the value provided by the AuthContext.\n */\ninterface AuthContextValue {\n\tclient: AuthClient\n\tsession: AuthSession\n\tstate: AuthState\n\tisLoading: boolean\n}\n\n/**\n * React context for Kora authentication.\n */\nconst AuthContext = createContext<AuthContextValue | null>(null)\n\nexport { AuthContext }\nexport type { AuthContextValue, AuthState }\n","import { useContext, useSyncExternalStore } from 'react'\nimport type {\n\tAuthState,\n\tAuthUser,\n\tLinkedOAuthAccount,\n\tOAuthAuthorizationOptions,\n\tOAuthAuthorizationResult,\n\tOAuthCallbackParams,\n} from '../client/auth-client'\nimport { AuthContext } from './auth-context'\n\nfunction useAuthContext() {\n\tconst ctx = useContext(AuthContext)\n\tif (ctx === null) {\n\t\tthrow new Error(\n\t\t\t'useAuth / useCurrentUser / useAuthStatus must be used within an <AuthProvider>. ' +\n\t\t\t\t'Wrap your component tree with <AuthProvider client={authClient}>.',\n\t\t)\n\t}\n\treturn ctx\n}\n\ninterface UseAuthResult {\n\tuser: AuthUser | null\n\tisAuthenticated: boolean\n\tisLoading: boolean\n\tsignUp: (params: {\n\t\temail: string\n\t\tpassword: string\n\t\tname?: string\n\t\tdeviceId?: string\n\t\tdevicePublicKey?: string\n\t}) => Promise<void>\n\tsignIn: (params: {\n\t\temail: string\n\t\tpassword: string\n\t\tdeviceId?: string\n\t\tdevicePublicKey?: string\n\t}) => Promise<void>\n\tsignInWithOAuth: (\n\t\tprovider: string,\n\t\toptions?: OAuthAuthorizationOptions,\n\t) => Promise<OAuthAuthorizationResult>\n\tcompleteOAuthSignIn: (provider: string, params: OAuthCallbackParams) => Promise<void>\n\tgetOAuthAuthorizationUrl: (\n\t\tprovider: string,\n\t\toptions?: OAuthAuthorizationOptions,\n\t) => Promise<OAuthAuthorizationResult>\n\tlinkOAuth: (provider: string, params: OAuthCallbackParams) => Promise<LinkedOAuthAccount | null>\n\tlistLinkedAccounts: () => Promise<LinkedOAuthAccount[]>\n\tunlinkOAuth: (provider: string) => Promise<void>\n\tsignOut: () => Promise<void>\n\terror: string | null\n\tinitError: Error | null\n}\n\ninterface AuthStatus {\n\tstate: AuthState\n\tisAuthenticated: boolean\n\tisLoading: boolean\n}\n\nfunction useAuthSessionSnapshot() {\n\tconst { session } = useAuthContext()\n\n\treturn useSyncExternalStore(\n\t\t(onStoreChange) => session.subscribe(onStoreChange),\n\t\t() => session.getSnapshot(),\n\t\t() => session.getSnapshot(),\n\t)\n}\n\nfunction useAuth(): UseAuthResult {\n\tconst { session } = useAuthContext()\n\tconst snapshot = useAuthSessionSnapshot()\n\n\treturn {\n\t\tuser: snapshot.user,\n\t\tisAuthenticated: snapshot.isAuthenticated,\n\t\tisLoading: snapshot.isLoading,\n\t\terror: snapshot.error,\n\t\tinitError: snapshot.initError,\n\t\tsignUp: (params) => session.signUp(params),\n\t\tsignIn: (params) => session.signIn(params),\n\t\tsignInWithOAuth: (provider, options) => session.signInWithOAuth(provider, options),\n\t\tcompleteOAuthSignIn: (provider, params) => session.completeOAuthSignIn(provider, params),\n\t\tgetOAuthAuthorizationUrl: (provider, options) =>\n\t\t\tsession.getOAuthAuthorizationUrl(provider, options),\n\t\tlinkOAuth: (provider, params) => session.linkOAuth(provider, params),\n\t\tlistLinkedAccounts: () => session.listLinkedAccounts(),\n\t\tunlinkOAuth: (provider) => session.unlinkOAuth(provider),\n\t\tsignOut: () => session.signOut(),\n\t}\n}\n\nfunction useCurrentUser(): AuthUser | null {\n\treturn useAuthSessionSnapshot().user\n}\n\nfunction useAuthStatus(): AuthStatus {\n\tconst snapshot = useAuthSessionSnapshot()\n\treturn {\n\t\tstate: snapshot.state,\n\t\tisAuthenticated: snapshot.isAuthenticated,\n\t\tisLoading: snapshot.isLoading,\n\t}\n}\n\nexport { useAuth, useCurrentUser, useAuthStatus }\nexport type { UseAuthResult, AuthStatus }\n","import { type ReactNode, useEffect, useMemo, useRef } from 'react'\nimport { type OrgSession, createOrgSession } from '../bindings/create-org-session'\nimport type { OrgClient } from '../client/org-client'\nimport { OrgContext, type OrgContextValue } from './org-hooks'\n\nexport interface OrgProviderProps {\n\tclient: OrgClient\n\tchildren?: ReactNode\n}\n\n/**\n * Provides organization context for {@link useOrg}, {@link useOrgMembers}, and {@link usePermission}.\n */\nexport function OrgProvider({ client, children }: OrgProviderProps) {\n\tconst sessionRef = useRef<OrgSession | null>(null)\n\n\tif (sessionRef.current === null || sessionRef.current.client !== client) {\n\t\tsessionRef.current?.destroy()\n\t\tsessionRef.current = createOrgSession(client)\n\t}\n\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tsessionRef.current?.destroy()\n\t\t\tsessionRef.current = null\n\t\t}\n\t}, [])\n\n\tconst session = sessionRef.current\n\tconst value = useMemo<OrgContextValue>(\n\t\t() => ({\n\t\t\tclient,\n\t\t\tsession,\n\t\t}),\n\t\t[client, session],\n\t)\n\n\treturn <OrgContext.Provider value={value}>{children}</OrgContext.Provider>\n}\n\nexport type { OrgContextValue }\n","import type {\n\tClientInvitation,\n\tClientMembership,\n\tClientOrganization,\n\tOrgClient,\n} from '../client/org-client'\n\nexport interface OrgSnapshot {\n\torgId: string | null\n\torg: ClientOrganization | null\n\trole: string | null\n}\n\nexport interface OrgSession {\n\treadonly client: OrgClient\n\tgetSnapshot(): OrgSnapshot\n\tsubscribe(listener: () => void): () => void\n\tcheckPermission(requiredRole: string): boolean\n\tdestroy(): void\n}\n\nconst ROLE_LEVELS: Record<string, number> = {\n\tviewer: 10,\n\tbilling: 15,\n\tmember: 20,\n\tadmin: 30,\n\towner: 40,\n}\n\nexport function checkOrgPermission(currentRole: string | null, requiredRole: string): boolean {\n\tif (!currentRole) return false\n\tconst currentLevel = ROLE_LEVELS[currentRole] ?? 0\n\tconst requiredLevel = ROLE_LEVELS[requiredRole] ?? 0\n\treturn currentLevel >= requiredLevel\n}\n\n/**\n * Framework-agnostic org session with reactive snapshot subscription.\n */\nexport function createOrgSession(client: OrgClient): OrgSession {\n\tlet snapshot = buildSnapshot(client)\n\tconst listeners = new Set<() => void>()\n\n\tconst notify = (): void => {\n\t\tsnapshot = buildSnapshot(client)\n\t\tfor (const listener of listeners) {\n\t\t\tlistener()\n\t\t}\n\t}\n\n\tconst unsubscribeOrgChange = client.onOrgChange(notify)\n\n\treturn {\n\t\tclient,\n\t\tgetSnapshot: () => snapshot,\n\t\tsubscribe(listener: () => void): () => void {\n\t\t\tlisteners.add(listener)\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete(listener)\n\t\t\t}\n\t\t},\n\t\tcheckPermission(requiredRole: string): boolean {\n\t\t\treturn checkOrgPermission(snapshot.role, requiredRole)\n\t\t},\n\t\tdestroy(): void {\n\t\t\tunsubscribeOrgChange()\n\t\t\tlisteners.clear()\n\t\t},\n\t}\n}\n\nfunction buildSnapshot(client: OrgClient): OrgSnapshot {\n\treturn {\n\t\torgId: client.activeOrgId,\n\t\torg: client.activeOrg,\n\t\trole: client.activeRole,\n\t}\n}\n\nexport interface UseOrgMembersActions {\n\trefresh: () => Promise<void>\n\tinvite: (email: string, role: string) => Promise<ClientInvitation>\n\tremoveMember: (userId: string) => Promise<void>\n\tupdateRole: (userId: string, role: string) => Promise<void>\n}\n\n/**\n * Shared org member management actions (loading state remains framework-specific).\n */\nexport function createOrgMembersActions(\n\tclient: OrgClient,\n\torgId: string,\n\tonError: (message: string) => void,\n): UseOrgMembersActions {\n\treturn {\n\t\tasync refresh(): Promise<void> {\n\t\t\tawait client.listMembers(orgId)\n\t\t},\n\t\tasync invite(email: string, role: string): Promise<ClientInvitation> {\n\t\t\ttry {\n\t\t\t\treturn await client.inviteMember(orgId, { email, role })\n\t\t\t} catch (error) {\n\t\t\t\tconst message = error instanceof Error ? error.message : String(error)\n\t\t\t\tonError(message)\n\t\t\t\tthrow error\n\t\t\t}\n\t\t},\n\t\tasync removeMember(userId: string): Promise<void> {\n\t\t\ttry {\n\t\t\t\tawait client.removeMember(orgId, userId)\n\t\t\t} catch (error) {\n\t\t\t\tonError(error instanceof Error ? error.message : String(error))\n\t\t\t}\n\t\t},\n\t\tasync updateRole(userId: string, role: string): Promise<void> {\n\t\t\ttry {\n\t\t\t\tawait client.updateMemberRole(orgId, userId, role)\n\t\t\t} catch (error) {\n\t\t\t\tonError(error instanceof Error ? error.message : String(error))\n\t\t\t}\n\t\t},\n\t}\n}\n\nexport async function loadOrgMembers(\n\tclient: OrgClient,\n\torgId: string,\n): Promise<ClientMembership[]> {\n\treturn client.listMembers(orgId)\n}\n","import {\n\tcreateContext,\n\tuseCallback,\n\tuseContext,\n\tuseEffect,\n\tuseRef,\n\tuseState,\n\tuseSyncExternalStore,\n} from 'react'\nimport {\n\ttype OrgSession,\n\ttype OrgSnapshot,\n\tcheckOrgPermission,\n\tcreateOrgMembersActions,\n\tcreateOrgSession,\n\tloadOrgMembers,\n} from '../bindings/create-org-session'\nimport type {\n\tClientInvitation,\n\tClientMembership,\n\tClientOrganization,\n\tOrgClient,\n} from '../client/org-client'\n\nexport interface OrgContextValue {\n\tclient: OrgClient\n\tsession: OrgSession\n}\n\nexport const OrgContext = createContext<OrgContextValue | null>(null)\n\nfunction useOrgContext(): OrgContextValue {\n\tconst ctx = useContext(OrgContext)\n\tif (ctx === null) {\n\t\tthrow new Error(\n\t\t\t'useOrg / useOrgMembers / usePermission must be used within an <OrgProvider>. ' +\n\t\t\t\t'Wrap your component tree with <OrgProvider client={orgClient}>.',\n\t\t)\n\t}\n\treturn ctx\n}\n\nfunction useOrgSnapshot(session: OrgSession): OrgSnapshot {\n\tconst snapshotRef = useRef(session.getSnapshot())\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\treturn session.subscribe(() => {\n\t\t\t\tsnapshotRef.current = session.getSnapshot()\n\t\t\t\tonStoreChange()\n\t\t\t})\n\t\t},\n\t\t[session],\n\t)\n\n\tconst getSnapshot = useCallback(() => snapshotRef.current, [])\n\n\treturn useSyncExternalStore(subscribe, getSnapshot)\n}\n\nexport interface UseOrgResult {\n\torg: ClientOrganization | null\n\trole: string | null\n\torgId: string | null\n\tswitchOrg: (orgId: string) => Promise<void>\n\tcreateOrg: (params: { name: string; slug?: string }) => Promise<ClientOrganization>\n\tleaveOrg: () => Promise<void>\n\tclearOrg: () => void\n\tlistOrgs: () => Promise<ClientOrganization[]>\n\terror: string | null\n}\n\nexport function useOrg(): UseOrgResult {\n\tconst { client, session } = useOrgContext()\n\tconst { orgId, org, role } = useOrgSnapshot(session)\n\tconst [error, setError] = useState<string | null>(null)\n\n\tconst switchOrg = useCallback(\n\t\tasync (newOrgId: string): Promise<void> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\tawait client.switchOrg(newOrgId)\n\t\t\t} catch (err) {\n\t\t\t\tsetError(err instanceof Error ? err.message : String(err))\n\t\t\t}\n\t\t},\n\t\t[client],\n\t)\n\n\tconst createOrg = useCallback(\n\t\tasync (params: { name: string; slug?: string }): Promise<ClientOrganization> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\treturn await client.createOrg(params)\n\t\t\t} catch (err) {\n\t\t\t\tconst msg = err instanceof Error ? err.message : String(err)\n\t\t\t\tsetError(msg)\n\t\t\t\tthrow err\n\t\t\t}\n\t\t},\n\t\t[client],\n\t)\n\n\tconst leaveOrg = useCallback(async (): Promise<void> => {\n\t\tif (!orgId) return\n\t\tsetError(null)\n\t\ttry {\n\t\t\tawait client.leaveOrg(orgId)\n\t\t} catch (err) {\n\t\t\tsetError(err instanceof Error ? err.message : String(err))\n\t\t}\n\t}, [client, orgId])\n\n\tconst clearOrg = useCallback((): void => {\n\t\tclient.clearActiveOrg()\n\t}, [client])\n\n\tconst listOrgs = useCallback(async (): Promise<ClientOrganization[]> => {\n\t\ttry {\n\t\t\treturn await client.listOrgs()\n\t\t} catch (err) {\n\t\t\tsetError(err instanceof Error ? err.message : String(err))\n\t\t\treturn []\n\t\t}\n\t}, [client])\n\n\treturn { org, role, orgId, switchOrg, createOrg, leaveOrg, clearOrg, listOrgs, error }\n}\n\nexport interface UseOrgMembersResult {\n\tmembers: ClientMembership[]\n\tisLoading: boolean\n\trefresh: () => Promise<void>\n\tinvite: (email: string, role: string) => Promise<ClientInvitation>\n\tremoveMember: (userId: string) => Promise<void>\n\tupdateRole: (userId: string, role: string) => Promise<void>\n\terror: string | null\n}\n\nexport function useOrgMembers(orgId: string): UseOrgMembersResult {\n\tconst { client } = useOrgContext()\n\tconst [members, setMembers] = useState<ClientMembership[]>([])\n\tconst [isLoading, setIsLoading] = useState(true)\n\tconst [error, setError] = useState<string | null>(null)\n\n\tconst refresh = useCallback(async () => {\n\t\tsetIsLoading(true)\n\t\tsetError(null)\n\t\ttry {\n\t\t\tsetMembers(await loadOrgMembers(client, orgId))\n\t\t} catch (err) {\n\t\t\tsetError(err instanceof Error ? err.message : String(err))\n\t\t} finally {\n\t\t\tsetIsLoading(false)\n\t\t}\n\t}, [client, orgId])\n\n\tuseEffect(() => {\n\t\tvoid refresh()\n\t}, [refresh])\n\n\tconst actions = createOrgMembersActions(client, orgId, setError)\n\n\tconst invite = useCallback(\n\t\tasync (email: string, role: string): Promise<ClientInvitation> => {\n\t\t\tconst result = await actions.invite(email, role)\n\t\t\tawait refresh()\n\t\t\treturn result\n\t\t},\n\t\t[actions, refresh],\n\t)\n\n\tconst removeMember = useCallback(\n\t\tasync (userId: string): Promise<void> => {\n\t\t\tawait actions.removeMember(userId)\n\t\t\tawait refresh()\n\t\t},\n\t\t[actions, refresh],\n\t)\n\n\tconst updateRole = useCallback(\n\t\tasync (userId: string, role: string): Promise<void> => {\n\t\t\tawait actions.updateRole(userId, role)\n\t\t\tawait refresh()\n\t\t},\n\t\t[actions, refresh],\n\t)\n\n\treturn { members, isLoading, refresh, invite, removeMember, updateRole, error }\n}\n\nexport function usePermission(requiredRole: string): boolean {\n\tconst { session } = useOrgContext()\n\tconst snapshotRef = useRef(session.checkPermission(requiredRole))\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\treturn session.subscribe(() => {\n\t\t\t\tconst next = session.checkPermission(requiredRole)\n\t\t\t\tif (next !== snapshotRef.current) {\n\t\t\t\t\tsnapshotRef.current = next\n\t\t\t\t\tonStoreChange()\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\t\t[session, requiredRole],\n\t)\n\n\tconst getSnapshot = useCallback(() => snapshotRef.current, [])\n\n\treturn useSyncExternalStore(subscribe, getSnapshot)\n}\n\nexport { checkOrgPermission }\n"],"mappings":"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","names":["import_react","buildSnapshot","import_react","import_react","import_react"]}
1
+ {"version":3,"sources":["../src/react.ts","../src/react/AuthProvider.tsx","../src/bindings/create-auth-session.ts","../src/react/auth-context.ts","../src/react/hooks.ts","../src/react/OrgProvider.tsx","../src/bindings/create-org-session.ts","../src/react/org-hooks.ts"],"sourcesContent":["// @korajs/auth/react — React-specific public API\n// Every export here is a public API commitment. Be explicit.\n\n// === Provider ===\nexport { AuthProvider } from './react/AuthProvider'\nexport type { AuthProviderProps } from './react/AuthProvider'\n\n// === Hooks ===\nexport { useAuth, useCurrentUser, useAuthStatus } from './react/hooks'\nexport type { UseAuthResult, AuthStatus } from './react/hooks'\n\n// === Context (for advanced use cases) ===\nexport { AuthContext } from './react/auth-context'\nexport type { AuthContextValue } from './react/auth-context'\n\n// === Organization Hooks ===\nexport { OrgProvider } from './react/OrgProvider'\nexport type { OrgProviderProps } from './react/OrgProvider'\nexport {\n\tOrgContext,\n\tuseOrg,\n\tuseOrgMembers,\n\tusePermission,\n\tcheckOrgPermission,\n} from './react/org-hooks'\nexport type { OrgContextValue, UseOrgResult, UseOrgMembersResult } from './react/org-hooks'\n","import { createElement, useEffect, useMemo, useSyncExternalStore } from 'react'\nimport type { ReactElement, ReactNode } from 'react'\nimport { createAuthSession } from '../bindings/create-auth-session'\nimport type { AuthSession } from '../bindings/create-auth-session'\nimport type { AuthClient } from '../client/auth-client'\nimport { AuthContext } from './auth-context'\n\ninterface AuthProviderProps {\n\tclient: AuthClient\n\tchildren: ReactNode\n\tfallback?: ReactNode\n}\n\ntype SessionEntry = {\n\tsession: AuthSession\n\trefs: number\n\tdestroyTimer: ReturnType<typeof setTimeout> | null\n}\n\nconst sessionEntries = new WeakMap<AuthClient, SessionEntry>()\n\nfunction getSessionEntry(client: AuthClient): SessionEntry {\n\tconst existing = sessionEntries.get(client)\n\tif (existing) return existing\n\n\tconst entry: SessionEntry = {\n\t\tsession: createAuthSession(client),\n\t\trefs: 0,\n\t\tdestroyTimer: null,\n\t}\n\tsessionEntries.set(client, entry)\n\treturn entry\n}\n\nfunction retainSession(entry: SessionEntry): () => void {\n\tif (entry.destroyTimer) {\n\t\tclearTimeout(entry.destroyTimer)\n\t\tentry.destroyTimer = null\n\t}\n\tentry.refs++\n\n\treturn () => {\n\t\tentry.refs = Math.max(0, entry.refs - 1)\n\t\tif (entry.refs > 0 || entry.destroyTimer) return\n\n\t\t// React StrictMode intentionally runs effect cleanup and setup back-to-back\n\t\t// on mount. Deferring disposal lets the second setup retain the same session,\n\t\t// while a real unmount still releases the auth subscription shortly after.\n\t\tentry.destroyTimer = setTimeout(() => {\n\t\t\tentry.destroyTimer = null\n\t\t\tif (entry.refs > 0) return\n\t\t\tentry.session.destroy()\n\t\t\tsessionEntries.delete(entry.session.client)\n\t\t}, 0)\n\t}\n}\n\nfunction AuthProvider({ client, children, fallback }: AuthProviderProps): ReactElement {\n\tconst entry = useMemo(() => getSessionEntry(client), [client])\n\tconst session = entry.session\n\n\tuseEffect(() => retainSession(entry), [entry])\n\n\tconst snapshot = useSyncExternalStore(\n\t\t(onStoreChange) => session.subscribe(onStoreChange),\n\t\t() => session.getSnapshot(),\n\t\t() => session.getSnapshot(),\n\t)\n\n\tif (snapshot.initError) {\n\t\treturn createElement(\n\t\t\t'div',\n\t\t\t{\n\t\t\t\tstyle: { color: 'red', padding: '1rem', fontFamily: 'monospace' },\n\t\t\t\trole: 'alert',\n\t\t\t},\n\t\t\tcreateElement('strong', null, 'Kora Auth initialization error: '),\n\t\t\tsnapshot.initError.message,\n\t\t)\n\t}\n\n\tif (snapshot.isLoading && fallback !== undefined) {\n\t\treturn fallback as ReactElement\n\t}\n\n\tconst contextValue = {\n\t\tclient,\n\t\tsession,\n\t\tstate: snapshot.state,\n\t\tisLoading: snapshot.isLoading,\n\t}\n\n\treturn createElement(AuthContext.Provider, { value: contextValue }, children)\n}\n\nexport { AuthProvider }\nexport type { AuthProviderProps }\n","import type {\n\tAuthClient,\n\tAuthState,\n\tAuthUser,\n\tLinkedOAuthAccount,\n\tOAuthAuthorizationOptions,\n\tOAuthAuthorizationResult,\n\tOAuthCallbackParams,\n} from '../client/auth-client'\n\nexport interface AuthSessionSnapshot {\n\tstate: AuthState\n\tuser: AuthUser | null\n\tisAuthenticated: boolean\n\tisLoading: boolean\n\tinitError: Error | null\n\terror: string | null\n}\n\nexport interface AuthSession {\n\treadonly client: AuthClient\n\tgetSnapshot(): AuthSessionSnapshot\n\tsubscribe(listener: () => void): () => void\n\tsignUp(params: {\n\t\temail: string\n\t\tpassword: string\n\t\tname?: string\n\t\tdeviceId?: string\n\t\tdevicePublicKey?: string\n\t}): Promise<void>\n\tsignIn(params: {\n\t\temail: string\n\t\tpassword: string\n\t\tdeviceId?: string\n\t\tdevicePublicKey?: string\n\t}): Promise<void>\n\tsignInWithOAuth(\n\t\tprovider: string,\n\t\toptions?: OAuthAuthorizationOptions,\n\t): Promise<OAuthAuthorizationResult>\n\tcompleteOAuthSignIn(provider: string, params: OAuthCallbackParams): Promise<void>\n\tgetOAuthAuthorizationUrl(\n\t\tprovider: string,\n\t\toptions?: OAuthAuthorizationOptions,\n\t): Promise<OAuthAuthorizationResult>\n\tlinkOAuth(provider: string, params: OAuthCallbackParams): Promise<LinkedOAuthAccount | null>\n\tlistLinkedAccounts(): Promise<LinkedOAuthAccount[]>\n\tunlinkOAuth(provider: string): Promise<void>\n\tsignOut(): Promise<void>\n\tdestroy(): void\n}\n\n/**\n * Framework-agnostic auth session: initialization, reactive snapshot, and client methods.\n */\nexport function createAuthSession(client: AuthClient): AuthSession {\n\tlet state: AuthState = client.state\n\tlet isLoading = true\n\tlet initError: Error | null = null\n\tlet lastError: string | null = null\n\n\tconst listeners = new Set<() => void>()\n\tlet snapshot = buildSnapshot()\n\n\tconst refreshSnapshot = (): void => {\n\t\tsnapshot = buildSnapshot()\n\t}\n\n\tconst notify = (): void => {\n\t\trefreshSnapshot()\n\t\tfor (const listener of listeners) {\n\t\t\tlistener()\n\t\t}\n\t}\n\n\tfunction buildSnapshot(): AuthSessionSnapshot {\n\t\treturn {\n\t\t\tstate,\n\t\t\tuser: client.currentUser,\n\t\t\tisAuthenticated: state === 'authenticated',\n\t\t\tisLoading,\n\t\t\tinitError,\n\t\t\terror: lastError,\n\t\t}\n\t}\n\n\tconst captureError = (error: unknown): void => {\n\t\tlastError = error instanceof Error ? error.message : String(error)\n\t\tnotify()\n\t}\n\n\tconst run = async (action: () => Promise<void>): Promise<void> => {\n\t\tlastError = null\n\t\ttry {\n\t\t\tawait action()\n\t\t} catch (error) {\n\t\t\tcaptureError(error)\n\t\t}\n\t}\n\n\tconst runWithResult = async <T>(action: () => Promise<T>): Promise<T | null> => {\n\t\tlastError = null\n\t\ttry {\n\t\t\treturn await action()\n\t\t} catch (error) {\n\t\t\tcaptureError(error)\n\t\t\treturn null\n\t\t}\n\t}\n\n\tconst unsubscribeAuth = client.onAuthChange((nextState) => {\n\t\tstate = nextState\n\t\tnotify()\n\t})\n\n\tvoid client\n\t\t.initialize()\n\t\t.then(() => {\n\t\t\tstate = client.state\n\t\t\tisLoading = false\n\t\t\tnotify()\n\t\t})\n\t\t.catch((error: unknown) => {\n\t\t\tinitError = error instanceof Error ? error : new Error(String(error))\n\t\t\tisLoading = false\n\t\t\tnotify()\n\t\t})\n\n\treturn {\n\t\tclient,\n\t\tgetSnapshot: () => snapshot,\n\t\tsubscribe(listener) {\n\t\t\tlisteners.add(listener)\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete(listener)\n\t\t\t}\n\t\t},\n\t\tsignUp: (params) =>\n\t\t\trun(async () => {\n\t\t\t\tawait client.signUp(params)\n\t\t\t}),\n\t\tsignIn: (params) =>\n\t\t\trun(async () => {\n\t\t\t\tawait client.signIn(params)\n\t\t\t}),\n\t\tsignInWithOAuth: async (provider, options) => {\n\t\t\tlastError = null\n\t\t\ttry {\n\t\t\t\treturn await client.signInWithOAuth(provider, options)\n\t\t\t} catch (error) {\n\t\t\t\tcaptureError(error)\n\t\t\t\tthrow error instanceof Error ? error : new Error(String(error))\n\t\t\t}\n\t\t},\n\t\tcompleteOAuthSignIn: (provider, params) =>\n\t\t\trun(async () => {\n\t\t\t\tawait client.completeOAuthSignIn(provider, params)\n\t\t\t}),\n\t\tgetOAuthAuthorizationUrl: async (provider, options) => {\n\t\t\tlastError = null\n\t\t\ttry {\n\t\t\t\treturn await client.getOAuthAuthorizationUrl(provider, options)\n\t\t\t} catch (error) {\n\t\t\t\tcaptureError(error)\n\t\t\t\tthrow error instanceof Error ? error : new Error(String(error))\n\t\t\t}\n\t\t},\n\t\tlinkOAuth: (provider, params) => runWithResult(async () => client.linkOAuth(provider, params)),\n\t\tlistLinkedAccounts: () =>\n\t\t\trunWithResult(async () => client.listLinkedAccounts()).then((value) => value ?? []),\n\t\tunlinkOAuth: (provider) =>\n\t\t\trun(async () => {\n\t\t\t\tawait client.unlinkOAuth(provider)\n\t\t\t}),\n\t\tsignOut: () =>\n\t\t\trun(async () => {\n\t\t\t\tawait client.signOut()\n\t\t\t}),\n\t\tdestroy() {\n\t\t\tunsubscribeAuth()\n\t\t\tlisteners.clear()\n\t\t},\n\t}\n}\n","import { createContext } from 'react'\nimport type { AuthSession } from '../bindings/create-auth-session'\nimport type { AuthClient } from '../client/auth-client'\n\n/**\n * Possible authentication states for the client.\n */\ntype AuthState = 'loading' | 'authenticated' | 'unauthenticated'\n\n/**\n * Shape of the value provided by the AuthContext.\n */\ninterface AuthContextValue {\n\tclient: AuthClient\n\tsession: AuthSession\n\tstate: AuthState\n\tisLoading: boolean\n}\n\n/**\n * React context for Kora authentication.\n */\nconst AuthContext = createContext<AuthContextValue | null>(null)\n\nexport { AuthContext }\nexport type { AuthContextValue, AuthState }\n","import { useContext, useSyncExternalStore } from 'react'\nimport type {\n\tAuthState,\n\tAuthUser,\n\tLinkedOAuthAccount,\n\tOAuthAuthorizationOptions,\n\tOAuthAuthorizationResult,\n\tOAuthCallbackParams,\n} from '../client/auth-client'\nimport { AuthContext } from './auth-context'\n\nfunction useAuthContext() {\n\tconst ctx = useContext(AuthContext)\n\tif (ctx === null) {\n\t\tthrow new Error(\n\t\t\t'useAuth / useCurrentUser / useAuthStatus must be used within an <AuthProvider>. ' +\n\t\t\t\t'Wrap your component tree with <AuthProvider client={authClient}>.',\n\t\t)\n\t}\n\treturn ctx\n}\n\ninterface UseAuthResult {\n\tuser: AuthUser | null\n\tisAuthenticated: boolean\n\tisLoading: boolean\n\tsignUp: (params: {\n\t\temail: string\n\t\tpassword: string\n\t\tname?: string\n\t\tdeviceId?: string\n\t\tdevicePublicKey?: string\n\t}) => Promise<void>\n\tsignIn: (params: {\n\t\temail: string\n\t\tpassword: string\n\t\tdeviceId?: string\n\t\tdevicePublicKey?: string\n\t}) => Promise<void>\n\tsignInWithOAuth: (\n\t\tprovider: string,\n\t\toptions?: OAuthAuthorizationOptions,\n\t) => Promise<OAuthAuthorizationResult>\n\tcompleteOAuthSignIn: (provider: string, params: OAuthCallbackParams) => Promise<void>\n\tgetOAuthAuthorizationUrl: (\n\t\tprovider: string,\n\t\toptions?: OAuthAuthorizationOptions,\n\t) => Promise<OAuthAuthorizationResult>\n\tlinkOAuth: (provider: string, params: OAuthCallbackParams) => Promise<LinkedOAuthAccount | null>\n\tlistLinkedAccounts: () => Promise<LinkedOAuthAccount[]>\n\tunlinkOAuth: (provider: string) => Promise<void>\n\tsignOut: () => Promise<void>\n\terror: string | null\n\tinitError: Error | null\n}\n\ninterface AuthStatus {\n\tstate: AuthState\n\tisAuthenticated: boolean\n\tisLoading: boolean\n}\n\nfunction useAuthSessionSnapshot() {\n\tconst { session } = useAuthContext()\n\n\treturn useSyncExternalStore(\n\t\t(onStoreChange) => session.subscribe(onStoreChange),\n\t\t() => session.getSnapshot(),\n\t\t() => session.getSnapshot(),\n\t)\n}\n\nfunction useAuth(): UseAuthResult {\n\tconst { session } = useAuthContext()\n\tconst snapshot = useAuthSessionSnapshot()\n\n\treturn {\n\t\tuser: snapshot.user,\n\t\tisAuthenticated: snapshot.isAuthenticated,\n\t\tisLoading: snapshot.isLoading,\n\t\terror: snapshot.error,\n\t\tinitError: snapshot.initError,\n\t\tsignUp: (params) => session.signUp(params),\n\t\tsignIn: (params) => session.signIn(params),\n\t\tsignInWithOAuth: (provider, options) => session.signInWithOAuth(provider, options),\n\t\tcompleteOAuthSignIn: (provider, params) => session.completeOAuthSignIn(provider, params),\n\t\tgetOAuthAuthorizationUrl: (provider, options) =>\n\t\t\tsession.getOAuthAuthorizationUrl(provider, options),\n\t\tlinkOAuth: (provider, params) => session.linkOAuth(provider, params),\n\t\tlistLinkedAccounts: () => session.listLinkedAccounts(),\n\t\tunlinkOAuth: (provider) => session.unlinkOAuth(provider),\n\t\tsignOut: () => session.signOut(),\n\t}\n}\n\nfunction useCurrentUser(): AuthUser | null {\n\treturn useAuthSessionSnapshot().user\n}\n\nfunction useAuthStatus(): AuthStatus {\n\tconst snapshot = useAuthSessionSnapshot()\n\treturn {\n\t\tstate: snapshot.state,\n\t\tisAuthenticated: snapshot.isAuthenticated,\n\t\tisLoading: snapshot.isLoading,\n\t}\n}\n\nexport { useAuth, useCurrentUser, useAuthStatus }\nexport type { UseAuthResult, AuthStatus }\n","import { type ReactNode, useEffect, useMemo, useRef } from 'react'\nimport { type OrgSession, createOrgSession } from '../bindings/create-org-session'\nimport type { OrgClient } from '../client/org-client'\nimport { OrgContext, type OrgContextValue } from './org-hooks'\n\nexport interface OrgProviderProps {\n\tclient: OrgClient\n\tchildren?: ReactNode\n}\n\n/**\n * Provides organization context for {@link useOrg}, {@link useOrgMembers}, and {@link usePermission}.\n */\nexport function OrgProvider({ client, children }: OrgProviderProps) {\n\tconst sessionRef = useRef<OrgSession | null>(null)\n\n\tif (sessionRef.current === null || sessionRef.current.client !== client) {\n\t\tsessionRef.current?.destroy()\n\t\tsessionRef.current = createOrgSession(client)\n\t}\n\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tsessionRef.current?.destroy()\n\t\t\tsessionRef.current = null\n\t\t}\n\t}, [])\n\n\tconst session = sessionRef.current\n\tconst value = useMemo<OrgContextValue>(\n\t\t() => ({\n\t\t\tclient,\n\t\t\tsession,\n\t\t}),\n\t\t[client, session],\n\t)\n\n\treturn <OrgContext.Provider value={value}>{children}</OrgContext.Provider>\n}\n\nexport type { OrgContextValue }\n","import type {\n\tClientInvitation,\n\tClientMembership,\n\tClientOrganization,\n\tOrgClient,\n} from '../client/org-client'\n\nexport interface OrgSnapshot {\n\torgId: string | null\n\torg: ClientOrganization | null\n\trole: string | null\n}\n\nexport interface OrgSession {\n\treadonly client: OrgClient\n\tgetSnapshot(): OrgSnapshot\n\tsubscribe(listener: () => void): () => void\n\tcheckPermission(requiredRole: string): boolean\n\tdestroy(): void\n}\n\nconst ROLE_LEVELS: Record<string, number> = {\n\tviewer: 10,\n\tbilling: 15,\n\tmember: 20,\n\tadmin: 30,\n\towner: 40,\n}\n\nexport function checkOrgPermission(currentRole: string | null, requiredRole: string): boolean {\n\tif (!currentRole) return false\n\tconst currentLevel = ROLE_LEVELS[currentRole] ?? 0\n\tconst requiredLevel = ROLE_LEVELS[requiredRole] ?? 0\n\treturn currentLevel >= requiredLevel\n}\n\n/**\n * Framework-agnostic org session with reactive snapshot subscription.\n */\nexport function createOrgSession(client: OrgClient): OrgSession {\n\tlet snapshot = buildSnapshot(client)\n\tconst listeners = new Set<() => void>()\n\n\tconst notify = (): void => {\n\t\tsnapshot = buildSnapshot(client)\n\t\tfor (const listener of listeners) {\n\t\t\tlistener()\n\t\t}\n\t}\n\n\tconst unsubscribeOrgChange = client.onOrgChange(notify)\n\n\treturn {\n\t\tclient,\n\t\tgetSnapshot: () => snapshot,\n\t\tsubscribe(listener: () => void): () => void {\n\t\t\tlisteners.add(listener)\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete(listener)\n\t\t\t}\n\t\t},\n\t\tcheckPermission(requiredRole: string): boolean {\n\t\t\treturn checkOrgPermission(snapshot.role, requiredRole)\n\t\t},\n\t\tdestroy(): void {\n\t\t\tunsubscribeOrgChange()\n\t\t\tlisteners.clear()\n\t\t},\n\t}\n}\n\nfunction buildSnapshot(client: OrgClient): OrgSnapshot {\n\treturn {\n\t\torgId: client.activeOrgId,\n\t\torg: client.activeOrg,\n\t\trole: client.activeRole,\n\t}\n}\n\nexport interface UseOrgMembersActions {\n\trefresh: () => Promise<void>\n\tinvite: (email: string, role: string) => Promise<ClientInvitation>\n\tremoveMember: (userId: string) => Promise<void>\n\tupdateRole: (userId: string, role: string) => Promise<void>\n}\n\n/**\n * Shared org member management actions (loading state remains framework-specific).\n */\nexport function createOrgMembersActions(\n\tclient: OrgClient,\n\torgId: string,\n\tonError: (message: string) => void,\n): UseOrgMembersActions {\n\treturn {\n\t\tasync refresh(): Promise<void> {\n\t\t\tawait client.listMembers(orgId)\n\t\t},\n\t\tasync invite(email: string, role: string): Promise<ClientInvitation> {\n\t\t\ttry {\n\t\t\t\treturn await client.inviteMember(orgId, { email, role })\n\t\t\t} catch (error) {\n\t\t\t\tconst message = error instanceof Error ? error.message : String(error)\n\t\t\t\tonError(message)\n\t\t\t\tthrow error\n\t\t\t}\n\t\t},\n\t\tasync removeMember(userId: string): Promise<void> {\n\t\t\ttry {\n\t\t\t\tawait client.removeMember(orgId, userId)\n\t\t\t} catch (error) {\n\t\t\t\tonError(error instanceof Error ? error.message : String(error))\n\t\t\t}\n\t\t},\n\t\tasync updateRole(userId: string, role: string): Promise<void> {\n\t\t\ttry {\n\t\t\t\tawait client.updateMemberRole(orgId, userId, role)\n\t\t\t} catch (error) {\n\t\t\t\tonError(error instanceof Error ? error.message : String(error))\n\t\t\t}\n\t\t},\n\t}\n}\n\nexport async function loadOrgMembers(\n\tclient: OrgClient,\n\torgId: string,\n): Promise<ClientMembership[]> {\n\treturn client.listMembers(orgId)\n}\n","import {\n\tcreateContext,\n\tuseCallback,\n\tuseContext,\n\tuseEffect,\n\tuseRef,\n\tuseState,\n\tuseSyncExternalStore,\n} from 'react'\nimport {\n\ttype OrgSession,\n\ttype OrgSnapshot,\n\tcheckOrgPermission,\n\tcreateOrgMembersActions,\n\tcreateOrgSession,\n\tloadOrgMembers,\n} from '../bindings/create-org-session'\nimport type {\n\tClientInvitation,\n\tClientMembership,\n\tClientOrganization,\n\tOrgClient,\n} from '../client/org-client'\n\nexport interface OrgContextValue {\n\tclient: OrgClient\n\tsession: OrgSession\n}\n\nexport const OrgContext = createContext<OrgContextValue | null>(null)\n\nfunction useOrgContext(): OrgContextValue {\n\tconst ctx = useContext(OrgContext)\n\tif (ctx === null) {\n\t\tthrow new Error(\n\t\t\t'useOrg / useOrgMembers / usePermission must be used within an <OrgProvider>. ' +\n\t\t\t\t'Wrap your component tree with <OrgProvider client={orgClient}>.',\n\t\t)\n\t}\n\treturn ctx\n}\n\nfunction useOrgSnapshot(session: OrgSession): OrgSnapshot {\n\tconst snapshotRef = useRef(session.getSnapshot())\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\treturn session.subscribe(() => {\n\t\t\t\tsnapshotRef.current = session.getSnapshot()\n\t\t\t\tonStoreChange()\n\t\t\t})\n\t\t},\n\t\t[session],\n\t)\n\n\tconst getSnapshot = useCallback(() => snapshotRef.current, [])\n\n\treturn useSyncExternalStore(subscribe, getSnapshot)\n}\n\nexport interface UseOrgResult {\n\torg: ClientOrganization | null\n\trole: string | null\n\torgId: string | null\n\tswitchOrg: (orgId: string) => Promise<void>\n\tcreateOrg: (params: { name: string; slug?: string }) => Promise<ClientOrganization>\n\tleaveOrg: () => Promise<void>\n\tclearOrg: () => void\n\tlistOrgs: () => Promise<ClientOrganization[]>\n\terror: string | null\n}\n\nexport function useOrg(): UseOrgResult {\n\tconst { client, session } = useOrgContext()\n\tconst { orgId, org, role } = useOrgSnapshot(session)\n\tconst [error, setError] = useState<string | null>(null)\n\n\tconst switchOrg = useCallback(\n\t\tasync (newOrgId: string): Promise<void> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\tawait client.switchOrg(newOrgId)\n\t\t\t} catch (err) {\n\t\t\t\tsetError(err instanceof Error ? err.message : String(err))\n\t\t\t}\n\t\t},\n\t\t[client],\n\t)\n\n\tconst createOrg = useCallback(\n\t\tasync (params: { name: string; slug?: string }): Promise<ClientOrganization> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\treturn await client.createOrg(params)\n\t\t\t} catch (err) {\n\t\t\t\tconst msg = err instanceof Error ? err.message : String(err)\n\t\t\t\tsetError(msg)\n\t\t\t\tthrow err\n\t\t\t}\n\t\t},\n\t\t[client],\n\t)\n\n\tconst leaveOrg = useCallback(async (): Promise<void> => {\n\t\tif (!orgId) return\n\t\tsetError(null)\n\t\ttry {\n\t\t\tawait client.leaveOrg(orgId)\n\t\t} catch (err) {\n\t\t\tsetError(err instanceof Error ? err.message : String(err))\n\t\t}\n\t}, [client, orgId])\n\n\tconst clearOrg = useCallback((): void => {\n\t\tclient.clearActiveOrg()\n\t}, [client])\n\n\tconst listOrgs = useCallback(async (): Promise<ClientOrganization[]> => {\n\t\ttry {\n\t\t\treturn await client.listOrgs()\n\t\t} catch (err) {\n\t\t\tsetError(err instanceof Error ? err.message : String(err))\n\t\t\treturn []\n\t\t}\n\t}, [client])\n\n\treturn { org, role, orgId, switchOrg, createOrg, leaveOrg, clearOrg, listOrgs, error }\n}\n\nexport interface UseOrgMembersResult {\n\tmembers: ClientMembership[]\n\tisLoading: boolean\n\trefresh: () => Promise<void>\n\tinvite: (email: string, role: string) => Promise<ClientInvitation>\n\tremoveMember: (userId: string) => Promise<void>\n\tupdateRole: (userId: string, role: string) => Promise<void>\n\terror: string | null\n}\n\nexport function useOrgMembers(orgId: string): UseOrgMembersResult {\n\tconst { client } = useOrgContext()\n\tconst [members, setMembers] = useState<ClientMembership[]>([])\n\tconst [isLoading, setIsLoading] = useState(true)\n\tconst [error, setError] = useState<string | null>(null)\n\n\tconst refresh = useCallback(async () => {\n\t\tsetIsLoading(true)\n\t\tsetError(null)\n\t\ttry {\n\t\t\tsetMembers(await loadOrgMembers(client, orgId))\n\t\t} catch (err) {\n\t\t\tsetError(err instanceof Error ? err.message : String(err))\n\t\t} finally {\n\t\t\tsetIsLoading(false)\n\t\t}\n\t}, [client, orgId])\n\n\tuseEffect(() => {\n\t\tvoid refresh()\n\t}, [refresh])\n\n\tconst actions = createOrgMembersActions(client, orgId, setError)\n\n\tconst invite = useCallback(\n\t\tasync (email: string, role: string): Promise<ClientInvitation> => {\n\t\t\tconst result = await actions.invite(email, role)\n\t\t\tawait refresh()\n\t\t\treturn result\n\t\t},\n\t\t[actions, refresh],\n\t)\n\n\tconst removeMember = useCallback(\n\t\tasync (userId: string): Promise<void> => {\n\t\t\tawait actions.removeMember(userId)\n\t\t\tawait refresh()\n\t\t},\n\t\t[actions, refresh],\n\t)\n\n\tconst updateRole = useCallback(\n\t\tasync (userId: string, role: string): Promise<void> => {\n\t\t\tawait actions.updateRole(userId, role)\n\t\t\tawait refresh()\n\t\t},\n\t\t[actions, refresh],\n\t)\n\n\treturn { members, isLoading, refresh, invite, removeMember, updateRole, error }\n}\n\nexport function usePermission(requiredRole: string): boolean {\n\tconst { session } = useOrgContext()\n\tconst snapshotRef = useRef(session.checkPermission(requiredRole))\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\treturn session.subscribe(() => {\n\t\t\t\tconst next = session.checkPermission(requiredRole)\n\t\t\t\tif (next !== snapshotRef.current) {\n\t\t\t\t\tsnapshotRef.current = next\n\t\t\t\t\tonStoreChange()\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\t\t[session, requiredRole],\n\t)\n\n\tconst getSnapshot = useCallback(() => snapshotRef.current, [])\n\n\treturn useSyncExternalStore(subscribe, getSnapshot)\n}\n\nexport { checkOrgPermission }\n"],"mappings":"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","names":["import_react","buildSnapshot","import_react","import_react","import_react"]}
package/dist/react.js CHANGED
@@ -14,9 +14,39 @@ import { createContext } from "react";
14
14
  var AuthContext = createContext(null);
15
15
 
16
16
  // src/react/AuthProvider.tsx
17
+ var sessionEntries = /* @__PURE__ */ new WeakMap();
18
+ function getSessionEntry(client) {
19
+ const existing = sessionEntries.get(client);
20
+ if (existing) return existing;
21
+ const entry = {
22
+ session: createAuthSession(client),
23
+ refs: 0,
24
+ destroyTimer: null
25
+ };
26
+ sessionEntries.set(client, entry);
27
+ return entry;
28
+ }
29
+ function retainSession(entry) {
30
+ if (entry.destroyTimer) {
31
+ clearTimeout(entry.destroyTimer);
32
+ entry.destroyTimer = null;
33
+ }
34
+ entry.refs++;
35
+ return () => {
36
+ entry.refs = Math.max(0, entry.refs - 1);
37
+ if (entry.refs > 0 || entry.destroyTimer) return;
38
+ entry.destroyTimer = setTimeout(() => {
39
+ entry.destroyTimer = null;
40
+ if (entry.refs > 0) return;
41
+ entry.session.destroy();
42
+ sessionEntries.delete(entry.session.client);
43
+ }, 0);
44
+ };
45
+ }
17
46
  function AuthProvider({ client, children, fallback }) {
18
- const session = useMemo(() => createAuthSession(client), [client]);
19
- useEffect(() => () => session.destroy(), [session]);
47
+ const entry = useMemo(() => getSessionEntry(client), [client]);
48
+ const session = entry.session;
49
+ useEffect(() => retainSession(entry), [entry]);
20
50
  const snapshot = useSyncExternalStore(
21
51
  (onStoreChange) => session.subscribe(onStoreChange),
22
52
  () => session.getSnapshot(),
package/dist/react.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/react/AuthProvider.tsx","../src/react/auth-context.ts","../src/react/hooks.ts","../src/react/OrgProvider.tsx","../src/react/org-hooks.ts"],"sourcesContent":["import { createElement, useEffect, useMemo, useSyncExternalStore } from 'react'\nimport type { ReactElement, ReactNode } from 'react'\nimport { createAuthSession } from '../bindings/create-auth-session'\nimport type { AuthClient } from '../client/auth-client'\nimport { AuthContext } from './auth-context'\n\ninterface AuthProviderProps {\n\tclient: AuthClient\n\tchildren: ReactNode\n\tfallback?: ReactNode\n}\n\nfunction AuthProvider({ client, children, fallback }: AuthProviderProps): ReactElement {\n\tconst session = useMemo(() => createAuthSession(client), [client])\n\n\tuseEffect(() => () => session.destroy(), [session])\n\n\tconst snapshot = useSyncExternalStore(\n\t\t(onStoreChange) => session.subscribe(onStoreChange),\n\t\t() => session.getSnapshot(),\n\t\t() => session.getSnapshot(),\n\t)\n\n\tif (snapshot.initError) {\n\t\treturn createElement(\n\t\t\t'div',\n\t\t\t{\n\t\t\t\tstyle: { color: 'red', padding: '1rem', fontFamily: 'monospace' },\n\t\t\t\trole: 'alert',\n\t\t\t},\n\t\t\tcreateElement('strong', null, 'Kora Auth initialization error: '),\n\t\t\tsnapshot.initError.message,\n\t\t)\n\t}\n\n\tif (snapshot.isLoading && fallback !== undefined) {\n\t\treturn fallback as ReactElement\n\t}\n\n\tconst contextValue = {\n\t\tclient,\n\t\tsession,\n\t\tstate: snapshot.state,\n\t\tisLoading: snapshot.isLoading,\n\t}\n\n\treturn createElement(AuthContext.Provider, { value: contextValue }, children)\n}\n\nexport { AuthProvider }\nexport type { AuthProviderProps }\n","import { createContext } from 'react'\nimport type { AuthSession } from '../bindings/create-auth-session'\nimport type { AuthClient } from '../client/auth-client'\n\n/**\n * Possible authentication states for the client.\n */\ntype AuthState = 'loading' | 'authenticated' | 'unauthenticated'\n\n/**\n * Shape of the value provided by the AuthContext.\n */\ninterface AuthContextValue {\n\tclient: AuthClient\n\tsession: AuthSession\n\tstate: AuthState\n\tisLoading: boolean\n}\n\n/**\n * React context for Kora authentication.\n */\nconst AuthContext = createContext<AuthContextValue | null>(null)\n\nexport { AuthContext }\nexport type { AuthContextValue, AuthState }\n","import { useContext, useSyncExternalStore } from 'react'\nimport type {\n\tAuthState,\n\tAuthUser,\n\tLinkedOAuthAccount,\n\tOAuthAuthorizationOptions,\n\tOAuthAuthorizationResult,\n\tOAuthCallbackParams,\n} from '../client/auth-client'\nimport { AuthContext } from './auth-context'\n\nfunction useAuthContext() {\n\tconst ctx = useContext(AuthContext)\n\tif (ctx === null) {\n\t\tthrow new Error(\n\t\t\t'useAuth / useCurrentUser / useAuthStatus must be used within an <AuthProvider>. ' +\n\t\t\t\t'Wrap your component tree with <AuthProvider client={authClient}>.',\n\t\t)\n\t}\n\treturn ctx\n}\n\ninterface UseAuthResult {\n\tuser: AuthUser | null\n\tisAuthenticated: boolean\n\tisLoading: boolean\n\tsignUp: (params: {\n\t\temail: string\n\t\tpassword: string\n\t\tname?: string\n\t\tdeviceId?: string\n\t\tdevicePublicKey?: string\n\t}) => Promise<void>\n\tsignIn: (params: {\n\t\temail: string\n\t\tpassword: string\n\t\tdeviceId?: string\n\t\tdevicePublicKey?: string\n\t}) => Promise<void>\n\tsignInWithOAuth: (\n\t\tprovider: string,\n\t\toptions?: OAuthAuthorizationOptions,\n\t) => Promise<OAuthAuthorizationResult>\n\tcompleteOAuthSignIn: (provider: string, params: OAuthCallbackParams) => Promise<void>\n\tgetOAuthAuthorizationUrl: (\n\t\tprovider: string,\n\t\toptions?: OAuthAuthorizationOptions,\n\t) => Promise<OAuthAuthorizationResult>\n\tlinkOAuth: (provider: string, params: OAuthCallbackParams) => Promise<LinkedOAuthAccount | null>\n\tlistLinkedAccounts: () => Promise<LinkedOAuthAccount[]>\n\tunlinkOAuth: (provider: string) => Promise<void>\n\tsignOut: () => Promise<void>\n\terror: string | null\n\tinitError: Error | null\n}\n\ninterface AuthStatus {\n\tstate: AuthState\n\tisAuthenticated: boolean\n\tisLoading: boolean\n}\n\nfunction useAuthSessionSnapshot() {\n\tconst { session } = useAuthContext()\n\n\treturn useSyncExternalStore(\n\t\t(onStoreChange) => session.subscribe(onStoreChange),\n\t\t() => session.getSnapshot(),\n\t\t() => session.getSnapshot(),\n\t)\n}\n\nfunction useAuth(): UseAuthResult {\n\tconst { session } = useAuthContext()\n\tconst snapshot = useAuthSessionSnapshot()\n\n\treturn {\n\t\tuser: snapshot.user,\n\t\tisAuthenticated: snapshot.isAuthenticated,\n\t\tisLoading: snapshot.isLoading,\n\t\terror: snapshot.error,\n\t\tinitError: snapshot.initError,\n\t\tsignUp: (params) => session.signUp(params),\n\t\tsignIn: (params) => session.signIn(params),\n\t\tsignInWithOAuth: (provider, options) => session.signInWithOAuth(provider, options),\n\t\tcompleteOAuthSignIn: (provider, params) => session.completeOAuthSignIn(provider, params),\n\t\tgetOAuthAuthorizationUrl: (provider, options) =>\n\t\t\tsession.getOAuthAuthorizationUrl(provider, options),\n\t\tlinkOAuth: (provider, params) => session.linkOAuth(provider, params),\n\t\tlistLinkedAccounts: () => session.listLinkedAccounts(),\n\t\tunlinkOAuth: (provider) => session.unlinkOAuth(provider),\n\t\tsignOut: () => session.signOut(),\n\t}\n}\n\nfunction useCurrentUser(): AuthUser | null {\n\treturn useAuthSessionSnapshot().user\n}\n\nfunction useAuthStatus(): AuthStatus {\n\tconst snapshot = useAuthSessionSnapshot()\n\treturn {\n\t\tstate: snapshot.state,\n\t\tisAuthenticated: snapshot.isAuthenticated,\n\t\tisLoading: snapshot.isLoading,\n\t}\n}\n\nexport { useAuth, useCurrentUser, useAuthStatus }\nexport type { UseAuthResult, AuthStatus }\n","import { type ReactNode, useEffect, useMemo, useRef } from 'react'\nimport { type OrgSession, createOrgSession } from '../bindings/create-org-session'\nimport type { OrgClient } from '../client/org-client'\nimport { OrgContext, type OrgContextValue } from './org-hooks'\n\nexport interface OrgProviderProps {\n\tclient: OrgClient\n\tchildren?: ReactNode\n}\n\n/**\n * Provides organization context for {@link useOrg}, {@link useOrgMembers}, and {@link usePermission}.\n */\nexport function OrgProvider({ client, children }: OrgProviderProps) {\n\tconst sessionRef = useRef<OrgSession | null>(null)\n\n\tif (sessionRef.current === null || sessionRef.current.client !== client) {\n\t\tsessionRef.current?.destroy()\n\t\tsessionRef.current = createOrgSession(client)\n\t}\n\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tsessionRef.current?.destroy()\n\t\t\tsessionRef.current = null\n\t\t}\n\t}, [])\n\n\tconst session = sessionRef.current\n\tconst value = useMemo<OrgContextValue>(\n\t\t() => ({\n\t\t\tclient,\n\t\t\tsession,\n\t\t}),\n\t\t[client, session],\n\t)\n\n\treturn <OrgContext.Provider value={value}>{children}</OrgContext.Provider>\n}\n\nexport type { OrgContextValue }\n","import {\n\tcreateContext,\n\tuseCallback,\n\tuseContext,\n\tuseEffect,\n\tuseRef,\n\tuseState,\n\tuseSyncExternalStore,\n} from 'react'\nimport {\n\ttype OrgSession,\n\ttype OrgSnapshot,\n\tcheckOrgPermission,\n\tcreateOrgMembersActions,\n\tcreateOrgSession,\n\tloadOrgMembers,\n} from '../bindings/create-org-session'\nimport type {\n\tClientInvitation,\n\tClientMembership,\n\tClientOrganization,\n\tOrgClient,\n} from '../client/org-client'\n\nexport interface OrgContextValue {\n\tclient: OrgClient\n\tsession: OrgSession\n}\n\nexport const OrgContext = createContext<OrgContextValue | null>(null)\n\nfunction useOrgContext(): OrgContextValue {\n\tconst ctx = useContext(OrgContext)\n\tif (ctx === null) {\n\t\tthrow new Error(\n\t\t\t'useOrg / useOrgMembers / usePermission must be used within an <OrgProvider>. ' +\n\t\t\t\t'Wrap your component tree with <OrgProvider client={orgClient}>.',\n\t\t)\n\t}\n\treturn ctx\n}\n\nfunction useOrgSnapshot(session: OrgSession): OrgSnapshot {\n\tconst snapshotRef = useRef(session.getSnapshot())\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\treturn session.subscribe(() => {\n\t\t\t\tsnapshotRef.current = session.getSnapshot()\n\t\t\t\tonStoreChange()\n\t\t\t})\n\t\t},\n\t\t[session],\n\t)\n\n\tconst getSnapshot = useCallback(() => snapshotRef.current, [])\n\n\treturn useSyncExternalStore(subscribe, getSnapshot)\n}\n\nexport interface UseOrgResult {\n\torg: ClientOrganization | null\n\trole: string | null\n\torgId: string | null\n\tswitchOrg: (orgId: string) => Promise<void>\n\tcreateOrg: (params: { name: string; slug?: string }) => Promise<ClientOrganization>\n\tleaveOrg: () => Promise<void>\n\tclearOrg: () => void\n\tlistOrgs: () => Promise<ClientOrganization[]>\n\terror: string | null\n}\n\nexport function useOrg(): UseOrgResult {\n\tconst { client, session } = useOrgContext()\n\tconst { orgId, org, role } = useOrgSnapshot(session)\n\tconst [error, setError] = useState<string | null>(null)\n\n\tconst switchOrg = useCallback(\n\t\tasync (newOrgId: string): Promise<void> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\tawait client.switchOrg(newOrgId)\n\t\t\t} catch (err) {\n\t\t\t\tsetError(err instanceof Error ? err.message : String(err))\n\t\t\t}\n\t\t},\n\t\t[client],\n\t)\n\n\tconst createOrg = useCallback(\n\t\tasync (params: { name: string; slug?: string }): Promise<ClientOrganization> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\treturn await client.createOrg(params)\n\t\t\t} catch (err) {\n\t\t\t\tconst msg = err instanceof Error ? err.message : String(err)\n\t\t\t\tsetError(msg)\n\t\t\t\tthrow err\n\t\t\t}\n\t\t},\n\t\t[client],\n\t)\n\n\tconst leaveOrg = useCallback(async (): Promise<void> => {\n\t\tif (!orgId) return\n\t\tsetError(null)\n\t\ttry {\n\t\t\tawait client.leaveOrg(orgId)\n\t\t} catch (err) {\n\t\t\tsetError(err instanceof Error ? err.message : String(err))\n\t\t}\n\t}, [client, orgId])\n\n\tconst clearOrg = useCallback((): void => {\n\t\tclient.clearActiveOrg()\n\t}, [client])\n\n\tconst listOrgs = useCallback(async (): Promise<ClientOrganization[]> => {\n\t\ttry {\n\t\t\treturn await client.listOrgs()\n\t\t} catch (err) {\n\t\t\tsetError(err instanceof Error ? err.message : String(err))\n\t\t\treturn []\n\t\t}\n\t}, [client])\n\n\treturn { org, role, orgId, switchOrg, createOrg, leaveOrg, clearOrg, listOrgs, error }\n}\n\nexport interface UseOrgMembersResult {\n\tmembers: ClientMembership[]\n\tisLoading: boolean\n\trefresh: () => Promise<void>\n\tinvite: (email: string, role: string) => Promise<ClientInvitation>\n\tremoveMember: (userId: string) => Promise<void>\n\tupdateRole: (userId: string, role: string) => Promise<void>\n\terror: string | null\n}\n\nexport function useOrgMembers(orgId: string): UseOrgMembersResult {\n\tconst { client } = useOrgContext()\n\tconst [members, setMembers] = useState<ClientMembership[]>([])\n\tconst [isLoading, setIsLoading] = useState(true)\n\tconst [error, setError] = useState<string | null>(null)\n\n\tconst refresh = useCallback(async () => {\n\t\tsetIsLoading(true)\n\t\tsetError(null)\n\t\ttry {\n\t\t\tsetMembers(await loadOrgMembers(client, orgId))\n\t\t} catch (err) {\n\t\t\tsetError(err instanceof Error ? err.message : String(err))\n\t\t} finally {\n\t\t\tsetIsLoading(false)\n\t\t}\n\t}, [client, orgId])\n\n\tuseEffect(() => {\n\t\tvoid refresh()\n\t}, [refresh])\n\n\tconst actions = createOrgMembersActions(client, orgId, setError)\n\n\tconst invite = useCallback(\n\t\tasync (email: string, role: string): Promise<ClientInvitation> => {\n\t\t\tconst result = await actions.invite(email, role)\n\t\t\tawait refresh()\n\t\t\treturn result\n\t\t},\n\t\t[actions, refresh],\n\t)\n\n\tconst removeMember = useCallback(\n\t\tasync (userId: string): Promise<void> => {\n\t\t\tawait actions.removeMember(userId)\n\t\t\tawait refresh()\n\t\t},\n\t\t[actions, refresh],\n\t)\n\n\tconst updateRole = useCallback(\n\t\tasync (userId: string, role: string): Promise<void> => {\n\t\t\tawait actions.updateRole(userId, role)\n\t\t\tawait refresh()\n\t\t},\n\t\t[actions, refresh],\n\t)\n\n\treturn { members, isLoading, refresh, invite, removeMember, updateRole, error }\n}\n\nexport function usePermission(requiredRole: string): boolean {\n\tconst { session } = useOrgContext()\n\tconst snapshotRef = useRef(session.checkPermission(requiredRole))\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\treturn session.subscribe(() => {\n\t\t\t\tconst next = session.checkPermission(requiredRole)\n\t\t\t\tif (next !== snapshotRef.current) {\n\t\t\t\t\tsnapshotRef.current = next\n\t\t\t\t\tonStoreChange()\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\t\t[session, requiredRole],\n\t)\n\n\tconst getSnapshot = useCallback(() => snapshotRef.current, [])\n\n\treturn useSyncExternalStore(subscribe, getSnapshot)\n}\n\nexport { checkOrgPermission }\n"],"mappings":"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","names":["useSyncExternalStore","useSyncExternalStore","useEffect","useMemo","useRef","createContext","useContext","useEffect","useSyncExternalStore","createContext","useContext","useSyncExternalStore","useEffect","useRef","useEffect","useMemo"]}
1
+ {"version":3,"sources":["../src/react/AuthProvider.tsx","../src/react/auth-context.ts","../src/react/hooks.ts","../src/react/OrgProvider.tsx","../src/react/org-hooks.ts"],"sourcesContent":["import { createElement, useEffect, useMemo, useSyncExternalStore } from 'react'\nimport type { ReactElement, ReactNode } from 'react'\nimport { createAuthSession } from '../bindings/create-auth-session'\nimport type { AuthSession } from '../bindings/create-auth-session'\nimport type { AuthClient } from '../client/auth-client'\nimport { AuthContext } from './auth-context'\n\ninterface AuthProviderProps {\n\tclient: AuthClient\n\tchildren: ReactNode\n\tfallback?: ReactNode\n}\n\ntype SessionEntry = {\n\tsession: AuthSession\n\trefs: number\n\tdestroyTimer: ReturnType<typeof setTimeout> | null\n}\n\nconst sessionEntries = new WeakMap<AuthClient, SessionEntry>()\n\nfunction getSessionEntry(client: AuthClient): SessionEntry {\n\tconst existing = sessionEntries.get(client)\n\tif (existing) return existing\n\n\tconst entry: SessionEntry = {\n\t\tsession: createAuthSession(client),\n\t\trefs: 0,\n\t\tdestroyTimer: null,\n\t}\n\tsessionEntries.set(client, entry)\n\treturn entry\n}\n\nfunction retainSession(entry: SessionEntry): () => void {\n\tif (entry.destroyTimer) {\n\t\tclearTimeout(entry.destroyTimer)\n\t\tentry.destroyTimer = null\n\t}\n\tentry.refs++\n\n\treturn () => {\n\t\tentry.refs = Math.max(0, entry.refs - 1)\n\t\tif (entry.refs > 0 || entry.destroyTimer) return\n\n\t\t// React StrictMode intentionally runs effect cleanup and setup back-to-back\n\t\t// on mount. Deferring disposal lets the second setup retain the same session,\n\t\t// while a real unmount still releases the auth subscription shortly after.\n\t\tentry.destroyTimer = setTimeout(() => {\n\t\t\tentry.destroyTimer = null\n\t\t\tif (entry.refs > 0) return\n\t\t\tentry.session.destroy()\n\t\t\tsessionEntries.delete(entry.session.client)\n\t\t}, 0)\n\t}\n}\n\nfunction AuthProvider({ client, children, fallback }: AuthProviderProps): ReactElement {\n\tconst entry = useMemo(() => getSessionEntry(client), [client])\n\tconst session = entry.session\n\n\tuseEffect(() => retainSession(entry), [entry])\n\n\tconst snapshot = useSyncExternalStore(\n\t\t(onStoreChange) => session.subscribe(onStoreChange),\n\t\t() => session.getSnapshot(),\n\t\t() => session.getSnapshot(),\n\t)\n\n\tif (snapshot.initError) {\n\t\treturn createElement(\n\t\t\t'div',\n\t\t\t{\n\t\t\t\tstyle: { color: 'red', padding: '1rem', fontFamily: 'monospace' },\n\t\t\t\trole: 'alert',\n\t\t\t},\n\t\t\tcreateElement('strong', null, 'Kora Auth initialization error: '),\n\t\t\tsnapshot.initError.message,\n\t\t)\n\t}\n\n\tif (snapshot.isLoading && fallback !== undefined) {\n\t\treturn fallback as ReactElement\n\t}\n\n\tconst contextValue = {\n\t\tclient,\n\t\tsession,\n\t\tstate: snapshot.state,\n\t\tisLoading: snapshot.isLoading,\n\t}\n\n\treturn createElement(AuthContext.Provider, { value: contextValue }, children)\n}\n\nexport { AuthProvider }\nexport type { AuthProviderProps }\n","import { createContext } from 'react'\nimport type { AuthSession } from '../bindings/create-auth-session'\nimport type { AuthClient } from '../client/auth-client'\n\n/**\n * Possible authentication states for the client.\n */\ntype AuthState = 'loading' | 'authenticated' | 'unauthenticated'\n\n/**\n * Shape of the value provided by the AuthContext.\n */\ninterface AuthContextValue {\n\tclient: AuthClient\n\tsession: AuthSession\n\tstate: AuthState\n\tisLoading: boolean\n}\n\n/**\n * React context for Kora authentication.\n */\nconst AuthContext = createContext<AuthContextValue | null>(null)\n\nexport { AuthContext }\nexport type { AuthContextValue, AuthState }\n","import { useContext, useSyncExternalStore } from 'react'\nimport type {\n\tAuthState,\n\tAuthUser,\n\tLinkedOAuthAccount,\n\tOAuthAuthorizationOptions,\n\tOAuthAuthorizationResult,\n\tOAuthCallbackParams,\n} from '../client/auth-client'\nimport { AuthContext } from './auth-context'\n\nfunction useAuthContext() {\n\tconst ctx = useContext(AuthContext)\n\tif (ctx === null) {\n\t\tthrow new Error(\n\t\t\t'useAuth / useCurrentUser / useAuthStatus must be used within an <AuthProvider>. ' +\n\t\t\t\t'Wrap your component tree with <AuthProvider client={authClient}>.',\n\t\t)\n\t}\n\treturn ctx\n}\n\ninterface UseAuthResult {\n\tuser: AuthUser | null\n\tisAuthenticated: boolean\n\tisLoading: boolean\n\tsignUp: (params: {\n\t\temail: string\n\t\tpassword: string\n\t\tname?: string\n\t\tdeviceId?: string\n\t\tdevicePublicKey?: string\n\t}) => Promise<void>\n\tsignIn: (params: {\n\t\temail: string\n\t\tpassword: string\n\t\tdeviceId?: string\n\t\tdevicePublicKey?: string\n\t}) => Promise<void>\n\tsignInWithOAuth: (\n\t\tprovider: string,\n\t\toptions?: OAuthAuthorizationOptions,\n\t) => Promise<OAuthAuthorizationResult>\n\tcompleteOAuthSignIn: (provider: string, params: OAuthCallbackParams) => Promise<void>\n\tgetOAuthAuthorizationUrl: (\n\t\tprovider: string,\n\t\toptions?: OAuthAuthorizationOptions,\n\t) => Promise<OAuthAuthorizationResult>\n\tlinkOAuth: (provider: string, params: OAuthCallbackParams) => Promise<LinkedOAuthAccount | null>\n\tlistLinkedAccounts: () => Promise<LinkedOAuthAccount[]>\n\tunlinkOAuth: (provider: string) => Promise<void>\n\tsignOut: () => Promise<void>\n\terror: string | null\n\tinitError: Error | null\n}\n\ninterface AuthStatus {\n\tstate: AuthState\n\tisAuthenticated: boolean\n\tisLoading: boolean\n}\n\nfunction useAuthSessionSnapshot() {\n\tconst { session } = useAuthContext()\n\n\treturn useSyncExternalStore(\n\t\t(onStoreChange) => session.subscribe(onStoreChange),\n\t\t() => session.getSnapshot(),\n\t\t() => session.getSnapshot(),\n\t)\n}\n\nfunction useAuth(): UseAuthResult {\n\tconst { session } = useAuthContext()\n\tconst snapshot = useAuthSessionSnapshot()\n\n\treturn {\n\t\tuser: snapshot.user,\n\t\tisAuthenticated: snapshot.isAuthenticated,\n\t\tisLoading: snapshot.isLoading,\n\t\terror: snapshot.error,\n\t\tinitError: snapshot.initError,\n\t\tsignUp: (params) => session.signUp(params),\n\t\tsignIn: (params) => session.signIn(params),\n\t\tsignInWithOAuth: (provider, options) => session.signInWithOAuth(provider, options),\n\t\tcompleteOAuthSignIn: (provider, params) => session.completeOAuthSignIn(provider, params),\n\t\tgetOAuthAuthorizationUrl: (provider, options) =>\n\t\t\tsession.getOAuthAuthorizationUrl(provider, options),\n\t\tlinkOAuth: (provider, params) => session.linkOAuth(provider, params),\n\t\tlistLinkedAccounts: () => session.listLinkedAccounts(),\n\t\tunlinkOAuth: (provider) => session.unlinkOAuth(provider),\n\t\tsignOut: () => session.signOut(),\n\t}\n}\n\nfunction useCurrentUser(): AuthUser | null {\n\treturn useAuthSessionSnapshot().user\n}\n\nfunction useAuthStatus(): AuthStatus {\n\tconst snapshot = useAuthSessionSnapshot()\n\treturn {\n\t\tstate: snapshot.state,\n\t\tisAuthenticated: snapshot.isAuthenticated,\n\t\tisLoading: snapshot.isLoading,\n\t}\n}\n\nexport { useAuth, useCurrentUser, useAuthStatus }\nexport type { UseAuthResult, AuthStatus }\n","import { type ReactNode, useEffect, useMemo, useRef } from 'react'\nimport { type OrgSession, createOrgSession } from '../bindings/create-org-session'\nimport type { OrgClient } from '../client/org-client'\nimport { OrgContext, type OrgContextValue } from './org-hooks'\n\nexport interface OrgProviderProps {\n\tclient: OrgClient\n\tchildren?: ReactNode\n}\n\n/**\n * Provides organization context for {@link useOrg}, {@link useOrgMembers}, and {@link usePermission}.\n */\nexport function OrgProvider({ client, children }: OrgProviderProps) {\n\tconst sessionRef = useRef<OrgSession | null>(null)\n\n\tif (sessionRef.current === null || sessionRef.current.client !== client) {\n\t\tsessionRef.current?.destroy()\n\t\tsessionRef.current = createOrgSession(client)\n\t}\n\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tsessionRef.current?.destroy()\n\t\t\tsessionRef.current = null\n\t\t}\n\t}, [])\n\n\tconst session = sessionRef.current\n\tconst value = useMemo<OrgContextValue>(\n\t\t() => ({\n\t\t\tclient,\n\t\t\tsession,\n\t\t}),\n\t\t[client, session],\n\t)\n\n\treturn <OrgContext.Provider value={value}>{children}</OrgContext.Provider>\n}\n\nexport type { OrgContextValue }\n","import {\n\tcreateContext,\n\tuseCallback,\n\tuseContext,\n\tuseEffect,\n\tuseRef,\n\tuseState,\n\tuseSyncExternalStore,\n} from 'react'\nimport {\n\ttype OrgSession,\n\ttype OrgSnapshot,\n\tcheckOrgPermission,\n\tcreateOrgMembersActions,\n\tcreateOrgSession,\n\tloadOrgMembers,\n} from '../bindings/create-org-session'\nimport type {\n\tClientInvitation,\n\tClientMembership,\n\tClientOrganization,\n\tOrgClient,\n} from '../client/org-client'\n\nexport interface OrgContextValue {\n\tclient: OrgClient\n\tsession: OrgSession\n}\n\nexport const OrgContext = createContext<OrgContextValue | null>(null)\n\nfunction useOrgContext(): OrgContextValue {\n\tconst ctx = useContext(OrgContext)\n\tif (ctx === null) {\n\t\tthrow new Error(\n\t\t\t'useOrg / useOrgMembers / usePermission must be used within an <OrgProvider>. ' +\n\t\t\t\t'Wrap your component tree with <OrgProvider client={orgClient}>.',\n\t\t)\n\t}\n\treturn ctx\n}\n\nfunction useOrgSnapshot(session: OrgSession): OrgSnapshot {\n\tconst snapshotRef = useRef(session.getSnapshot())\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\treturn session.subscribe(() => {\n\t\t\t\tsnapshotRef.current = session.getSnapshot()\n\t\t\t\tonStoreChange()\n\t\t\t})\n\t\t},\n\t\t[session],\n\t)\n\n\tconst getSnapshot = useCallback(() => snapshotRef.current, [])\n\n\treturn useSyncExternalStore(subscribe, getSnapshot)\n}\n\nexport interface UseOrgResult {\n\torg: ClientOrganization | null\n\trole: string | null\n\torgId: string | null\n\tswitchOrg: (orgId: string) => Promise<void>\n\tcreateOrg: (params: { name: string; slug?: string }) => Promise<ClientOrganization>\n\tleaveOrg: () => Promise<void>\n\tclearOrg: () => void\n\tlistOrgs: () => Promise<ClientOrganization[]>\n\terror: string | null\n}\n\nexport function useOrg(): UseOrgResult {\n\tconst { client, session } = useOrgContext()\n\tconst { orgId, org, role } = useOrgSnapshot(session)\n\tconst [error, setError] = useState<string | null>(null)\n\n\tconst switchOrg = useCallback(\n\t\tasync (newOrgId: string): Promise<void> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\tawait client.switchOrg(newOrgId)\n\t\t\t} catch (err) {\n\t\t\t\tsetError(err instanceof Error ? err.message : String(err))\n\t\t\t}\n\t\t},\n\t\t[client],\n\t)\n\n\tconst createOrg = useCallback(\n\t\tasync (params: { name: string; slug?: string }): Promise<ClientOrganization> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\treturn await client.createOrg(params)\n\t\t\t} catch (err) {\n\t\t\t\tconst msg = err instanceof Error ? err.message : String(err)\n\t\t\t\tsetError(msg)\n\t\t\t\tthrow err\n\t\t\t}\n\t\t},\n\t\t[client],\n\t)\n\n\tconst leaveOrg = useCallback(async (): Promise<void> => {\n\t\tif (!orgId) return\n\t\tsetError(null)\n\t\ttry {\n\t\t\tawait client.leaveOrg(orgId)\n\t\t} catch (err) {\n\t\t\tsetError(err instanceof Error ? err.message : String(err))\n\t\t}\n\t}, [client, orgId])\n\n\tconst clearOrg = useCallback((): void => {\n\t\tclient.clearActiveOrg()\n\t}, [client])\n\n\tconst listOrgs = useCallback(async (): Promise<ClientOrganization[]> => {\n\t\ttry {\n\t\t\treturn await client.listOrgs()\n\t\t} catch (err) {\n\t\t\tsetError(err instanceof Error ? err.message : String(err))\n\t\t\treturn []\n\t\t}\n\t}, [client])\n\n\treturn { org, role, orgId, switchOrg, createOrg, leaveOrg, clearOrg, listOrgs, error }\n}\n\nexport interface UseOrgMembersResult {\n\tmembers: ClientMembership[]\n\tisLoading: boolean\n\trefresh: () => Promise<void>\n\tinvite: (email: string, role: string) => Promise<ClientInvitation>\n\tremoveMember: (userId: string) => Promise<void>\n\tupdateRole: (userId: string, role: string) => Promise<void>\n\terror: string | null\n}\n\nexport function useOrgMembers(orgId: string): UseOrgMembersResult {\n\tconst { client } = useOrgContext()\n\tconst [members, setMembers] = useState<ClientMembership[]>([])\n\tconst [isLoading, setIsLoading] = useState(true)\n\tconst [error, setError] = useState<string | null>(null)\n\n\tconst refresh = useCallback(async () => {\n\t\tsetIsLoading(true)\n\t\tsetError(null)\n\t\ttry {\n\t\t\tsetMembers(await loadOrgMembers(client, orgId))\n\t\t} catch (err) {\n\t\t\tsetError(err instanceof Error ? err.message : String(err))\n\t\t} finally {\n\t\t\tsetIsLoading(false)\n\t\t}\n\t}, [client, orgId])\n\n\tuseEffect(() => {\n\t\tvoid refresh()\n\t}, [refresh])\n\n\tconst actions = createOrgMembersActions(client, orgId, setError)\n\n\tconst invite = useCallback(\n\t\tasync (email: string, role: string): Promise<ClientInvitation> => {\n\t\t\tconst result = await actions.invite(email, role)\n\t\t\tawait refresh()\n\t\t\treturn result\n\t\t},\n\t\t[actions, refresh],\n\t)\n\n\tconst removeMember = useCallback(\n\t\tasync (userId: string): Promise<void> => {\n\t\t\tawait actions.removeMember(userId)\n\t\t\tawait refresh()\n\t\t},\n\t\t[actions, refresh],\n\t)\n\n\tconst updateRole = useCallback(\n\t\tasync (userId: string, role: string): Promise<void> => {\n\t\t\tawait actions.updateRole(userId, role)\n\t\t\tawait refresh()\n\t\t},\n\t\t[actions, refresh],\n\t)\n\n\treturn { members, isLoading, refresh, invite, removeMember, updateRole, error }\n}\n\nexport function usePermission(requiredRole: string): boolean {\n\tconst { session } = useOrgContext()\n\tconst snapshotRef = useRef(session.checkPermission(requiredRole))\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\treturn session.subscribe(() => {\n\t\t\t\tconst next = session.checkPermission(requiredRole)\n\t\t\t\tif (next !== snapshotRef.current) {\n\t\t\t\t\tsnapshotRef.current = next\n\t\t\t\t\tonStoreChange()\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\t\t[session, requiredRole],\n\t)\n\n\tconst getSnapshot = useCallback(() => snapshotRef.current, [])\n\n\treturn useSyncExternalStore(subscribe, getSnapshot)\n}\n\nexport { checkOrgPermission }\n"],"mappings":"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","names":["useSyncExternalStore","useSyncExternalStore","useEffect","useMemo","useRef","createContext","useContext","useEffect","useSyncExternalStore","createContext","useContext","useSyncExternalStore","useEffect","useRef","useEffect","useMemo"]}
package/dist/server.cjs CHANGED
@@ -405,7 +405,7 @@ var MAX_PASSWORD_LENGTH = 128;
405
405
  var MAX_NAME_LENGTH = 200;
406
406
  var CHALLENGE_TTL_MS = 6e4;
407
407
  function isValidEmail(email) {
408
- if (email.length === 0 || email.length > 254) {
408
+ if (typeof email !== "string" || email.length === 0 || email.length > 254) {
409
409
  return false;
410
410
  }
411
411
  const atIndex = email.indexOf("@");
@@ -425,6 +425,9 @@ function isValidEmail(email) {
425
425
  return true;
426
426
  }
427
427
  function sanitizeName(name) {
428
+ if (typeof name !== "string") {
429
+ return "";
430
+ }
428
431
  const cleaned = name.replace(/[\x00-\x1f\x7f]/g, "");
429
432
  const trimmed = cleaned.trim();
430
433
  if (trimmed.length > MAX_NAME_LENGTH) {
@@ -475,7 +478,7 @@ var BuiltInAuthRoutes = class {
475
478
  }
476
479
  };
477
480
  }
478
- if (body.password.length < MIN_PASSWORD_LENGTH) {
481
+ if (typeof body.password !== "string" || body.password.length < MIN_PASSWORD_LENGTH) {
479
482
  return {
480
483
  status: 400,
481
484
  body: {
@@ -539,6 +542,12 @@ var BuiltInAuthRoutes = class {
539
542
  * @returns Auth response with the user and tokens, or an error
540
543
  */
541
544
  async handleSignIn(body, clientIp) {
545
+ if (typeof body.email !== "string" || typeof body.password !== "string") {
546
+ return {
547
+ status: 400,
548
+ body: { error: "Email and password are required." }
549
+ };
550
+ }
542
551
  const rateLimitKey = clientIp ? `signin:${body.email.toLowerCase()}:${clientIp}` : `signin:${body.email.toLowerCase()}`;
543
552
  if (!await this.rateLimiter.isAllowed(rateLimitKey)) {
544
553
  return {
@@ -1046,6 +1055,9 @@ function decodeJwt(token) {
1046
1055
  }
1047
1056
  }
1048
1057
  function verifyJwt(token, secret) {
1058
+ if (typeof token !== "string") {
1059
+ return null;
1060
+ }
1049
1061
  const parts = token.split(".");
1050
1062
  if (parts.length !== 3) {
1051
1063
  return null;
@@ -2057,6 +2069,11 @@ function createDefaultTokenManager(options) {
2057
2069
  "createKoraAuthServer requires jwtSecret in production. Set KORA_AUTH_SECRET or pass jwtSecret."
2058
2070
  );
2059
2071
  }
2072
+ if (!secret) {
2073
+ console.warn(
2074
+ "[kora] No JWT secret configured; using an ephemeral random secret. Every token is invalidated when the process restarts. Set KORA_AUTH_SECRET or pass jwtSecret to createKoraAuthServer for stable sessions."
2075
+ );
2076
+ }
2060
2077
  return new TokenManager({
2061
2078
  secret: secret ?? TokenManager.generateSecret(),
2062
2079
  revocationStore: new InMemoryTokenRevocationStore(),
@@ -2359,7 +2376,11 @@ function notFound() {
2359
2376
  return { status: 404, body: { error: "Not found" } };
2360
2377
  }
2361
2378
  function readEnvSecret() {
2362
- return typeof process !== "undefined" ? process.env.KORA_AUTH_SECRET : void 0;
2379
+ if (typeof process === "undefined") {
2380
+ return void 0;
2381
+ }
2382
+ const value = process.env.KORA_AUTH_SECRET;
2383
+ return value && value.trim().length > 0 ? value : void 0;
2363
2384
  }
2364
2385
  function isProduction() {
2365
2386
  return typeof process !== "undefined" && process.env.NODE_ENV === "production";
@@ -4222,7 +4243,7 @@ var MAX_ORG_NAME_LENGTH = 200;
4222
4243
  var MAX_SLUG_LENGTH = 100;
4223
4244
  var SLUG_PATTERN = /^[a-z0-9][a-z0-9-]{0,98}[a-z0-9]$/;
4224
4245
  function isValidEmail2(email) {
4225
- if (email.length === 0 || email.length > 254) return false;
4246
+ if (typeof email !== "string" || email.length === 0 || email.length > 254) return false;
4226
4247
  const atIndex = email.indexOf("@");
4227
4248
  if (atIndex < 1) return false;
4228
4249
  const domain = email.slice(atIndex + 1);