@korajs/auth 0.4.0 → 0.5.0
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/README.md +81 -28
- package/dist/index.cjs +915 -523
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +77 -118
- package/dist/index.d.ts +77 -118
- package/dist/index.js +646 -258
- package/dist/index.js.map +1 -1
- package/dist/org-client-q2u55qod.d.cts +665 -0
- package/dist/org-client-q2u55qod.d.ts +665 -0
- package/dist/react.cjs +79 -0
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +17 -1
- package/dist/react.d.ts +17 -1
- package/dist/react.js +79 -0
- package/dist/react.js.map +1 -1
- package/dist/server.cjs +1611 -730
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +415 -224
- package/dist/server.d.ts +415 -224
- package/dist/server.js +1565 -704
- package/dist/server.js.map +1 -1
- package/package.json +5 -5
- package/dist/org-client-BVTLKcIk.d.cts +0 -355
- package/dist/org-client-BVTLKcIk.d.ts +0 -355
package/dist/react.cjs
CHANGED
|
@@ -149,6 +149,79 @@ function useAuth() {
|
|
|
149
149
|
},
|
|
150
150
|
[client]
|
|
151
151
|
);
|
|
152
|
+
const signInWithOAuth = (0, import_react3.useCallback)(
|
|
153
|
+
async (provider, options) => {
|
|
154
|
+
setError(null);
|
|
155
|
+
try {
|
|
156
|
+
return await client.signInWithOAuth(provider, options);
|
|
157
|
+
} catch (err) {
|
|
158
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
159
|
+
setError(message);
|
|
160
|
+
throw err;
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
[client]
|
|
164
|
+
);
|
|
165
|
+
const completeOAuthSignIn = (0, import_react3.useCallback)(
|
|
166
|
+
async (provider, params) => {
|
|
167
|
+
setError(null);
|
|
168
|
+
try {
|
|
169
|
+
await client.completeOAuthSignIn(provider, params);
|
|
170
|
+
} catch (err) {
|
|
171
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
172
|
+
setError(message);
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
[client]
|
|
176
|
+
);
|
|
177
|
+
const getOAuthAuthorizationUrl = (0, import_react3.useCallback)(
|
|
178
|
+
async (provider, options) => {
|
|
179
|
+
setError(null);
|
|
180
|
+
try {
|
|
181
|
+
return await client.getOAuthAuthorizationUrl(provider, options);
|
|
182
|
+
} catch (err) {
|
|
183
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
184
|
+
setError(message);
|
|
185
|
+
throw err;
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
[client]
|
|
189
|
+
);
|
|
190
|
+
const linkOAuth = (0, import_react3.useCallback)(
|
|
191
|
+
async (provider, params) => {
|
|
192
|
+
setError(null);
|
|
193
|
+
try {
|
|
194
|
+
return await client.linkOAuth(provider, params);
|
|
195
|
+
} catch (err) {
|
|
196
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
197
|
+
setError(message);
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
[client]
|
|
202
|
+
);
|
|
203
|
+
const listLinkedAccounts = (0, import_react3.useCallback)(async () => {
|
|
204
|
+
setError(null);
|
|
205
|
+
try {
|
|
206
|
+
return await client.listLinkedAccounts();
|
|
207
|
+
} catch (err) {
|
|
208
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
209
|
+
setError(message);
|
|
210
|
+
return [];
|
|
211
|
+
}
|
|
212
|
+
}, [client]);
|
|
213
|
+
const unlinkOAuth = (0, import_react3.useCallback)(
|
|
214
|
+
async (provider) => {
|
|
215
|
+
setError(null);
|
|
216
|
+
try {
|
|
217
|
+
await client.unlinkOAuth(provider);
|
|
218
|
+
} catch (err) {
|
|
219
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
220
|
+
setError(message);
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
[client]
|
|
224
|
+
);
|
|
152
225
|
const signOut = (0, import_react3.useCallback)(async () => {
|
|
153
226
|
setError(null);
|
|
154
227
|
try {
|
|
@@ -164,6 +237,12 @@ function useAuth() {
|
|
|
164
237
|
isLoading,
|
|
165
238
|
signUp,
|
|
166
239
|
signIn,
|
|
240
|
+
signInWithOAuth,
|
|
241
|
+
completeOAuthSignIn,
|
|
242
|
+
getOAuthAuthorizationUrl,
|
|
243
|
+
linkOAuth,
|
|
244
|
+
listLinkedAccounts,
|
|
245
|
+
unlinkOAuth,
|
|
167
246
|
signOut,
|
|
168
247
|
error
|
|
169
248
|
};
|
package/dist/react.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/react.ts","../src/react/AuthProvider.tsx","../src/react/auth-context.ts","../src/react/hooks.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 { OrgContext, useOrg, useOrgMembers, usePermission } from './react/org-hooks'\nexport type { OrgContextValue, UseOrgResult, UseOrgMembersResult } from './react/org-hooks'\n","import { createElement, useEffect, useState } from 'react'\nimport type { ReactElement, ReactNode } from 'react'\nimport type { AuthClient, AuthState } from '../client/auth-client'\nimport { AuthContext } from './auth-context'\n\n/**\n * Props for the AuthProvider component.\n */\ninterface AuthProviderProps {\n\t/** The AuthClient instance to provide to child components */\n\tclient: AuthClient\n\n\t/** Child components that will have access to auth context */\n\tchildren: ReactNode\n\n\t/**\n\t * Optional fallback content to render while the auth client is initializing.\n\t * If not provided, children are rendered with `isLoading: true` in the context.\n\t */\n\tfallback?: ReactNode\n}\n\n/**\n * React context provider that wraps the AuthClient for use with auth hooks.\n *\n * Calls `client.initialize()` on mount to restore any existing session from\n * stored tokens. Subscribes to auth state changes and re-renders children\n * when the state transitions.\n *\n * Must be placed above any component that uses {@link useAuth},\n * {@link useCurrentUser}, or {@link useAuthStatus}.\n *\n * @param props - Provider props including the AuthClient instance and children\n * @returns A React element wrapping children in the AuthContext\n *\n * @example\n * ```typescript\n * import { AuthClient } from '@korajs/auth'\n * import { AuthProvider } from '@korajs/auth/react'\n *\n * const authClient = new AuthClient({ serverUrl: 'http://localhost:3001' })\n *\n * function App() {\n * return (\n * <AuthProvider client={authClient} fallback={<div>Loading...</div>}>\n * <MyApp />\n * </AuthProvider>\n * )\n * }\n * ```\n */\nfunction AuthProvider({ client, children, fallback }: AuthProviderProps): ReactElement {\n\tconst [state, setState] = useState<AuthState>(client.state)\n\tconst [isLoading, setIsLoading] = useState(true)\n\tconst [initError, setInitError] = useState<Error | null>(null)\n\n\t// Initialize the auth client on mount\n\tuseEffect(() => {\n\t\tlet cancelled = false\n\n\t\t// Subscribe to auth state changes\n\t\tconst unsubscribe = client.onAuthChange((newState) => {\n\t\t\tif (!cancelled) {\n\t\t\t\tsetState(newState)\n\t\t\t}\n\t\t})\n\n\t\tclient\n\t\t\t.initialize()\n\t\t\t.then(() => {\n\t\t\t\tif (!cancelled) {\n\t\t\t\t\tsetState(client.state)\n\t\t\t\t\tsetIsLoading(false)\n\t\t\t\t}\n\t\t\t})\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tif (!cancelled) {\n\t\t\t\t\tconst err = error instanceof Error ? error : new Error(String(error))\n\t\t\t\t\tconsole.error('[Kora Auth] Initialization failed:', err)\n\t\t\t\t\tsetInitError(err)\n\t\t\t\t\tsetIsLoading(false)\n\t\t\t\t}\n\t\t\t})\n\n\t\treturn () => {\n\t\t\tcancelled = true\n\t\t\tunsubscribe()\n\t\t}\n\t}, [client])\n\n\t// Show error if initialization failed\n\tif (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\tinitError.message,\n\t\t)\n\t}\n\n\t// Show fallback while loading\n\tif (isLoading && fallback !== undefined) {\n\t\treturn fallback as ReactElement\n\t}\n\n\tconst contextValue = {\n\t\tclient,\n\t\tstate,\n\t\tisLoading,\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 { AuthClient } from '../client/auth-client'\n\n/**\n * Possible authentication states for the client.\n * - 'loading': Initial state while restoring tokens from storage\n * - 'authenticated': User is signed in with a valid session\n * - 'unauthenticated': No valid session exists\n */\ntype AuthState = 'loading' | 'authenticated' | 'unauthenticated'\n\n/**\n * Shape of the value provided by the AuthContext.\n * Includes the AuthClient instance, reactive state, and a loading flag.\n */\ninterface AuthContextValue {\n\t/** The underlying AuthClient instance for direct access */\n\tclient: AuthClient\n\n\t/** Current authentication state */\n\tstate: AuthState\n\n\t/** Whether the client is still initializing (restoring session from storage) */\n\tisLoading: boolean\n}\n\n/**\n * React context for Kora authentication.\n *\n * Provides the AuthClient and reactive auth state to child components.\n * Must be provided by an AuthProvider higher in the component tree.\n * Defaults to null — hooks that consume this context throw if it is missing.\n */\nconst AuthContext = createContext<AuthContextValue | null>(null)\n\nexport { AuthContext }\nexport type { AuthContextValue, AuthState }\n","import { useCallback, useContext, useEffect, useRef, useState, useSyncExternalStore } from 'react'\nimport type { AuthState, AuthUser } from '../client/auth-client'\nimport { AuthContext } from './auth-context'\n\n// ---------------------------------------------------------------------------\n// Internal context accessor\n// ---------------------------------------------------------------------------\n\n/**\n * Internal hook that reads and validates the AuthContext.\n * Throws a descriptive error if used outside an AuthProvider.\n */\nfunction useAuthContext(): {\n\tclient: import('../client/auth-client').AuthClient\n\tstate: AuthState\n\tisLoading: boolean\n} {\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\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * Return value of the {@link useAuth} hook.\n */\ninterface UseAuthResult {\n\t/** Current authenticated user, or null if not signed in */\n\tuser: AuthUser | null\n\n\t/** Whether the user is currently authenticated */\n\tisAuthenticated: boolean\n\n\t/** Whether the auth client is still initializing (restoring session) */\n\tisLoading: boolean\n\n\t/** Sign up a new user account */\n\tsignUp: (params: { email: string; password: string; name?: string }) => Promise<void>\n\n\t/** Sign in with email and password */\n\tsignIn: (params: { email: string; password: string }) => Promise<void>\n\n\t/** Sign out the current user */\n\tsignOut: () => Promise<void>\n\n\t/** Last error message from a sign-up, sign-in, or sign-out attempt, or null */\n\terror: string | null\n}\n\n/**\n * Auth status information returned by {@link useAuthStatus}.\n */\ninterface AuthStatus {\n\t/** Current authentication state */\n\tstate: AuthState\n\n\t/** Whether the user is currently authenticated */\n\tisAuthenticated: boolean\n\n\t/** Whether the auth client is still initializing */\n\tisLoading: boolean\n}\n\n// ---------------------------------------------------------------------------\n// useAuth\n// ---------------------------------------------------------------------------\n\n/**\n * React hook providing full authentication functionality.\n *\n * Returns the current user, loading state, error state, and methods for\n * sign-up, sign-in, and sign-out. Re-renders when auth state changes.\n *\n * Must be used within an {@link AuthProvider}.\n *\n * @returns An object with user info, auth methods, and status flags\n *\n * @example\n * ```typescript\n * function LoginPage() {\n * const { user, isAuthenticated, isLoading, signIn, error } = useAuth()\n *\n * if (isLoading) return <div>Loading...</div>\n * if (isAuthenticated) return <div>Welcome, {user?.name}</div>\n *\n * return (\n * <form onSubmit={async (e) => {\n * e.preventDefault()\n * await signIn({ email: 'user@example.com', password: 'secret' })\n * }}>\n * {error && <p>{error}</p>}\n * <button type=\"submit\">Sign In</button>\n * </form>\n * )\n * }\n * ```\n */\nfunction useAuth(): UseAuthResult {\n\tconst { client, state, isLoading } = useAuthContext()\n\tconst [error, setError] = useState<string | null>(null)\n\n\t// Use useSyncExternalStore to track the user reactively via auth state changes\n\tconst userSnapshotRef = useRef<AuthUser | null>(client.currentUser)\n\tconst stateSerializedRef = useRef<string>(JSON.stringify(client.currentUser))\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\treturn client.onAuthChange(() => {\n\t\t\t\tconst newUser = client.currentUser\n\t\t\t\tconst newSerialized = JSON.stringify(newUser)\n\t\t\t\tif (newSerialized !== stateSerializedRef.current) {\n\t\t\t\t\tuserSnapshotRef.current = newUser\n\t\t\t\t\tstateSerializedRef.current = newSerialized\n\t\t\t\t\tonStoreChange()\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\t\t[client],\n\t)\n\n\tconst getSnapshot = useCallback((): AuthUser | null => {\n\t\treturn userSnapshotRef.current\n\t}, [])\n\n\tconst user = useSyncExternalStore(subscribe, getSnapshot)\n\n\tconst signUp = useCallback(\n\t\tasync (params: { email: string; password: string; name?: string }): Promise<void> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\tawait client.signUp(params)\n\t\t\t} catch (err: unknown) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err)\n\t\t\t\tsetError(message)\n\t\t\t}\n\t\t},\n\t\t[client],\n\t)\n\n\tconst signIn = useCallback(\n\t\tasync (params: { email: string; password: string }): Promise<void> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\tawait client.signIn(params)\n\t\t\t} catch (err: unknown) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err)\n\t\t\t\tsetError(message)\n\t\t\t}\n\t\t},\n\t\t[client],\n\t)\n\n\tconst signOut = useCallback(async (): Promise<void> => {\n\t\tsetError(null)\n\t\ttry {\n\t\t\tawait client.signOut()\n\t\t} catch (err: unknown) {\n\t\t\tconst message = err instanceof Error ? err.message : String(err)\n\t\t\tsetError(message)\n\t\t}\n\t}, [client])\n\n\treturn {\n\t\tuser,\n\t\tisAuthenticated: state === 'authenticated',\n\t\tisLoading,\n\t\tsignUp,\n\t\tsignIn,\n\t\tsignOut,\n\t\terror,\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// useCurrentUser\n// ---------------------------------------------------------------------------\n\n/**\n * React hook that returns the currently authenticated user, or null.\n *\n * A lightweight alternative to {@link useAuth} when you only need the user\n * object and do not need auth methods or error state.\n *\n * Must be used within an {@link AuthProvider}.\n *\n * @returns The current AuthUser or null if not authenticated\n *\n * @example\n * ```typescript\n * function UserAvatar() {\n * const user = useCurrentUser()\n * if (!user) return null\n * return <span>{user.name ?? user.email}</span>\n * }\n * ```\n */\nfunction useCurrentUser(): AuthUser | null {\n\tconst { client } = useAuthContext()\n\n\tconst userSnapshotRef = useRef<AuthUser | null>(client.currentUser)\n\tconst stateSerializedRef = useRef<string>(JSON.stringify(client.currentUser))\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\treturn client.onAuthChange(() => {\n\t\t\t\tconst newUser = client.currentUser\n\t\t\t\tconst newSerialized = JSON.stringify(newUser)\n\t\t\t\tif (newSerialized !== stateSerializedRef.current) {\n\t\t\t\t\tuserSnapshotRef.current = newUser\n\t\t\t\t\tstateSerializedRef.current = newSerialized\n\t\t\t\t\tonStoreChange()\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\t\t[client],\n\t)\n\n\tconst getSnapshot = useCallback((): AuthUser | null => {\n\t\treturn userSnapshotRef.current\n\t}, [])\n\n\treturn useSyncExternalStore(subscribe, getSnapshot)\n}\n\n// ---------------------------------------------------------------------------\n// useAuthStatus\n// ---------------------------------------------------------------------------\n\n/**\n * React hook that returns the current authentication status.\n *\n * Re-renders only when the auth state changes, not on every auth event.\n * Use this for status indicators, route guards, and conditional rendering.\n *\n * Must be used within an {@link AuthProvider}.\n *\n * @returns An AuthStatus object with state, isAuthenticated, and isLoading flags\n *\n * @example\n * ```typescript\n * function AuthGuard({ children }: { children: React.ReactNode }) {\n * const { isAuthenticated, isLoading } = useAuthStatus()\n * if (isLoading) return <Spinner />\n * if (!isAuthenticated) return <Navigate to=\"/login\" />\n * return <>{children}</>\n * }\n * ```\n */\nfunction useAuthStatus(): AuthStatus {\n\tconst { state, isLoading } = useAuthContext()\n\n\treturn {\n\t\tstate,\n\t\tisAuthenticated: state === 'authenticated',\n\t\tisLoading,\n\t}\n}\n\nexport { useAuth, useCurrentUser, useAuthStatus }\nexport type { UseAuthResult, AuthStatus }\n","import {\n\tcreateContext,\n\tuseCallback,\n\tuseContext,\n\tuseEffect,\n\tuseRef,\n\tuseState,\n\tuseSyncExternalStore,\n} from 'react'\nimport type {\n\tClientInvitation,\n\tClientMembership,\n\tClientOrganization,\n\tOrgClient,\n} from '../client/org-client'\n\n// ============================================================================\n// OrgContext\n// ============================================================================\n\n/**\n * Shape of the OrgContext value.\n */\nexport interface OrgContextValue {\n\t/** The OrgClient instance */\n\tclient: OrgClient\n}\n\n/**\n * React context for organization state.\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\n// ============================================================================\n// useOrg\n// ============================================================================\n\n/**\n * Return value of the {@link useOrg} hook.\n */\nexport interface UseOrgResult {\n\t/** Currently active organization, or null */\n\torg: ClientOrganization | null\n\t/** Current user's role in the active organization, or null */\n\trole: string | null\n\t/** Active organization ID, or null */\n\torgId: string | null\n\t/** Switch to a different organization */\n\tswitchOrg: (orgId: string) => Promise<void>\n\t/** Create a new organization */\n\tcreateOrg: (params: { name: string; slug?: string }) => Promise<ClientOrganization>\n\t/** Leave the active organization */\n\tleaveOrg: () => Promise<void>\n\t/** Clear the active organization */\n\tclearOrg: () => void\n\t/** List all organizations the user belongs to */\n\tlistOrgs: () => Promise<ClientOrganization[]>\n\t/** Last error, or null */\n\terror: string | null\n}\n\n/**\n * React hook for organization management and context switching.\n *\n * Re-renders when the active organization changes.\n *\n * @example\n * ```typescript\n * function OrgSwitcher() {\n * const { org, switchOrg, listOrgs, error } = useOrg()\n * const [orgs, setOrgs] = useState<ClientOrganization[]>([])\n *\n * useEffect(() => { listOrgs().then(setOrgs) }, [listOrgs])\n *\n * return (\n * <select value={org?.id ?? ''} onChange={(e) => switchOrg(e.target.value)}>\n * <option value=\"\">Select org...</option>\n * {orgs.map(o => <option key={o.id} value={o.id}>{o.name}</option>)}\n * </select>\n * )\n * }\n * ```\n */\nexport function useOrg(): UseOrgResult {\n\tconst { client } = useOrgContext()\n\tconst [error, setError] = useState<string | null>(null)\n\n\t// Track active org reactively\n\tconst orgSnapshotRef = useRef({\n\t\torgId: client.activeOrgId,\n\t\torg: client.activeOrg,\n\t\trole: client.activeRole,\n\t})\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\treturn client.onOrgChange(() => {\n\t\t\t\torgSnapshotRef.current = {\n\t\t\t\t\torgId: client.activeOrgId,\n\t\t\t\t\torg: client.activeOrg,\n\t\t\t\t\trole: client.activeRole,\n\t\t\t\t}\n\t\t\t\tonStoreChange()\n\t\t\t})\n\t\t},\n\t\t[client],\n\t)\n\n\tconst getSnapshot = useCallback(() => orgSnapshotRef.current, [])\n\n\tconst { orgId, org, role } = useSyncExternalStore(subscribe, getSnapshot)\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\n// ============================================================================\n// useOrgMembers\n// ============================================================================\n\n/**\n * Return value of the {@link useOrgMembers} hook.\n */\nexport interface UseOrgMembersResult {\n\t/** Members of the organization (empty until loaded) */\n\tmembers: ClientMembership[]\n\t/** Whether members are being loaded */\n\tisLoading: boolean\n\t/** Reload the members list */\n\trefresh: () => Promise<void>\n\t/** Invite a user by email */\n\tinvite: (email: string, role: string) => Promise<ClientInvitation>\n\t/** Remove a member */\n\tremoveMember: (userId: string) => Promise<void>\n\t/** Update a member's role */\n\tupdateRole: (userId: string, role: string) => Promise<void>\n\t/** Last error, or null */\n\terror: string | null\n}\n\n/**\n * React hook for managing organization members.\n *\n * Automatically loads members when the orgId changes.\n *\n * @param orgId - Organization ID to manage members for\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\tconst result = await client.listMembers(orgId)\n\t\t\tsetMembers(result)\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\trefresh()\n\t}, [refresh])\n\n\tconst invite = useCallback(\n\t\tasync (email: string, role: string): Promise<ClientInvitation> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\tconst result = await client.inviteMember(orgId, { email, role })\n\t\t\t\treturn result\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, orgId],\n\t)\n\n\tconst removeMember = useCallback(\n\t\tasync (userId: string): Promise<void> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\tawait client.removeMember(orgId, userId)\n\t\t\t\tawait refresh()\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, orgId, refresh],\n\t)\n\n\tconst updateRole = useCallback(\n\t\tasync (userId: string, role: string): Promise<void> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\tawait client.updateMemberRole(orgId, userId, role)\n\t\t\t\tawait refresh()\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, orgId, refresh],\n\t)\n\n\treturn { members, isLoading, refresh, invite, removeMember, updateRole, error }\n}\n\n// ============================================================================\n// usePermission\n// ============================================================================\n\n/**\n * React hook that checks if the current user has a specific role level\n * in the active organization.\n *\n * @param requiredRole - Minimum role required (uses ROLE_HIERARCHY from org-types)\n * @returns true if the user's role is at least requiredRole\n *\n * @example\n * ```typescript\n * function AdminPanel() {\n * const canManage = usePermission('admin')\n * if (!canManage) return <p>Access denied</p>\n * return <AdminSettings />\n * }\n * ```\n */\nexport function usePermission(requiredRole: string): boolean {\n\tconst { client } = useOrgContext()\n\n\tconst snapshotRef = useRef(checkPermission(client.activeRole, requiredRole))\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\treturn client.onOrgChange(() => {\n\t\t\t\tconst newValue = checkPermission(client.activeRole, requiredRole)\n\t\t\t\tif (newValue !== snapshotRef.current) {\n\t\t\t\t\tsnapshotRef.current = newValue\n\t\t\t\t\tonStoreChange()\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\t\t[client, requiredRole],\n\t)\n\n\tconst getSnapshot = useCallback(() => snapshotRef.current, [])\n\n\treturn useSyncExternalStore(subscribe, getSnapshot)\n}\n\n// Simple role hierarchy check (mirrors ROLE_HIERARCHY from org-types)\nconst ROLE_LEVELS: Record<string, number> = {\n\tviewer: 10,\n\tbilling: 15,\n\tmember: 20,\n\tadmin: 30,\n\towner: 40,\n}\n\nfunction checkPermission(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"],"mappings":"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","names":["import_react","import_react","import_react"]}
|
|
1
|
+
{"version":3,"sources":["../src/react.ts","../src/react/AuthProvider.tsx","../src/react/auth-context.ts","../src/react/hooks.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 { OrgContext, useOrg, useOrgMembers, usePermission } from './react/org-hooks'\nexport type { OrgContextValue, UseOrgResult, UseOrgMembersResult } from './react/org-hooks'\n","import { createElement, useEffect, useState } from 'react'\nimport type { ReactElement, ReactNode } from 'react'\nimport type { AuthClient, AuthState } from '../client/auth-client'\nimport { AuthContext } from './auth-context'\n\n/**\n * Props for the AuthProvider component.\n */\ninterface AuthProviderProps {\n\t/** The AuthClient instance to provide to child components */\n\tclient: AuthClient\n\n\t/** Child components that will have access to auth context */\n\tchildren: ReactNode\n\n\t/**\n\t * Optional fallback content to render while the auth client is initializing.\n\t * If not provided, children are rendered with `isLoading: true` in the context.\n\t */\n\tfallback?: ReactNode\n}\n\n/**\n * React context provider that wraps the AuthClient for use with auth hooks.\n *\n * Calls `client.initialize()` on mount to restore any existing session from\n * stored tokens. Subscribes to auth state changes and re-renders children\n * when the state transitions.\n *\n * Must be placed above any component that uses {@link useAuth},\n * {@link useCurrentUser}, or {@link useAuthStatus}.\n *\n * @param props - Provider props including the AuthClient instance and children\n * @returns A React element wrapping children in the AuthContext\n *\n * @example\n * ```typescript\n * import { AuthClient } from '@korajs/auth'\n * import { AuthProvider } from '@korajs/auth/react'\n *\n * const authClient = new AuthClient({ serverUrl: 'http://localhost:3001' })\n *\n * function App() {\n * return (\n * <AuthProvider client={authClient} fallback={<div>Loading...</div>}>\n * <MyApp />\n * </AuthProvider>\n * )\n * }\n * ```\n */\nfunction AuthProvider({ client, children, fallback }: AuthProviderProps): ReactElement {\n\tconst [state, setState] = useState<AuthState>(client.state)\n\tconst [isLoading, setIsLoading] = useState(true)\n\tconst [initError, setInitError] = useState<Error | null>(null)\n\n\t// Initialize the auth client on mount\n\tuseEffect(() => {\n\t\tlet cancelled = false\n\n\t\t// Subscribe to auth state changes\n\t\tconst unsubscribe = client.onAuthChange((newState) => {\n\t\t\tif (!cancelled) {\n\t\t\t\tsetState(newState)\n\t\t\t}\n\t\t})\n\n\t\tclient\n\t\t\t.initialize()\n\t\t\t.then(() => {\n\t\t\t\tif (!cancelled) {\n\t\t\t\t\tsetState(client.state)\n\t\t\t\t\tsetIsLoading(false)\n\t\t\t\t}\n\t\t\t})\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tif (!cancelled) {\n\t\t\t\t\tconst err = error instanceof Error ? error : new Error(String(error))\n\t\t\t\t\tconsole.error('[Kora Auth] Initialization failed:', err)\n\t\t\t\t\tsetInitError(err)\n\t\t\t\t\tsetIsLoading(false)\n\t\t\t\t}\n\t\t\t})\n\n\t\treturn () => {\n\t\t\tcancelled = true\n\t\t\tunsubscribe()\n\t\t}\n\t}, [client])\n\n\t// Show error if initialization failed\n\tif (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\tinitError.message,\n\t\t)\n\t}\n\n\t// Show fallback while loading\n\tif (isLoading && fallback !== undefined) {\n\t\treturn fallback as ReactElement\n\t}\n\n\tconst contextValue = {\n\t\tclient,\n\t\tstate,\n\t\tisLoading,\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 { AuthClient } from '../client/auth-client'\n\n/**\n * Possible authentication states for the client.\n * - 'loading': Initial state while restoring tokens from storage\n * - 'authenticated': User is signed in with a valid session\n * - 'unauthenticated': No valid session exists\n */\ntype AuthState = 'loading' | 'authenticated' | 'unauthenticated'\n\n/**\n * Shape of the value provided by the AuthContext.\n * Includes the AuthClient instance, reactive state, and a loading flag.\n */\ninterface AuthContextValue {\n\t/** The underlying AuthClient instance for direct access */\n\tclient: AuthClient\n\n\t/** Current authentication state */\n\tstate: AuthState\n\n\t/** Whether the client is still initializing (restoring session from storage) */\n\tisLoading: boolean\n}\n\n/**\n * React context for Kora authentication.\n *\n * Provides the AuthClient and reactive auth state to child components.\n * Must be provided by an AuthProvider higher in the component tree.\n * Defaults to null — hooks that consume this context throw if it is missing.\n */\nconst AuthContext = createContext<AuthContextValue | null>(null)\n\nexport { AuthContext }\nexport type { AuthContextValue, AuthState }\n","import { useCallback, useContext, useEffect, useRef, useState, 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\n// ---------------------------------------------------------------------------\n// Internal context accessor\n// ---------------------------------------------------------------------------\n\n/**\n * Internal hook that reads and validates the AuthContext.\n * Throws a descriptive error if used outside an AuthProvider.\n */\nfunction useAuthContext(): {\n\tclient: import('../client/auth-client').AuthClient\n\tstate: AuthState\n\tisLoading: boolean\n} {\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\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * Return value of the {@link useAuth} hook.\n */\ninterface UseAuthResult {\n\t/** Current authenticated user, or null if not signed in */\n\tuser: AuthUser | null\n\n\t/** Whether the user is currently authenticated */\n\tisAuthenticated: boolean\n\n\t/** Whether the auth client is still initializing (restoring session) */\n\tisLoading: boolean\n\n\t/** Sign up a new user account */\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\n\t/** Sign in with email and password */\n\tsignIn: (params: {\n\t\temail: string\n\t\tpassword: string\n\t\tdeviceId?: string\n\t\tdevicePublicKey?: string\n\t}) => Promise<void>\n\n\t/** Start OAuth sign-in. Web apps can redirect; desktop/mobile can open the returned URL. */\n\tsignInWithOAuth: (\n\t\tprovider: string,\n\t\toptions?: OAuthAuthorizationOptions,\n\t) => Promise<OAuthAuthorizationResult>\n\n\t/** Complete an OAuth sign-in callback with code and state. */\n\tcompleteOAuthSignIn: (provider: string, params: OAuthCallbackParams) => Promise<void>\n\n\t/** Create an OAuth authorization URL without redirecting. */\n\tgetOAuthAuthorizationUrl: (\n\t\tprovider: string,\n\t\toptions?: OAuthAuthorizationOptions,\n\t) => Promise<OAuthAuthorizationResult>\n\n\t/** Link an OAuth provider to the current user. */\n\tlinkOAuth: (provider: string, params: OAuthCallbackParams) => Promise<LinkedOAuthAccount | null>\n\n\t/** List OAuth accounts linked to the current user. */\n\tlistLinkedAccounts: () => Promise<LinkedOAuthAccount[]>\n\n\t/** Unlink an OAuth provider from the current user. */\n\tunlinkOAuth: (provider: string) => Promise<void>\n\n\t/** Sign out the current user */\n\tsignOut: () => Promise<void>\n\n\t/** Last error message from a sign-up, sign-in, or sign-out attempt, or null */\n\terror: string | null\n}\n\n/**\n * Auth status information returned by {@link useAuthStatus}.\n */\ninterface AuthStatus {\n\t/** Current authentication state */\n\tstate: AuthState\n\n\t/** Whether the user is currently authenticated */\n\tisAuthenticated: boolean\n\n\t/** Whether the auth client is still initializing */\n\tisLoading: boolean\n}\n\n// ---------------------------------------------------------------------------\n// useAuth\n// ---------------------------------------------------------------------------\n\n/**\n * React hook providing full authentication functionality.\n *\n * Returns the current user, loading state, error state, and methods for\n * sign-up, sign-in, and sign-out. Re-renders when auth state changes.\n *\n * Must be used within an {@link AuthProvider}.\n *\n * @returns An object with user info, auth methods, and status flags\n *\n * @example\n * ```typescript\n * function LoginPage() {\n * const { user, isAuthenticated, isLoading, signIn, error } = useAuth()\n *\n * if (isLoading) return <div>Loading...</div>\n * if (isAuthenticated) return <div>Welcome, {user?.name}</div>\n *\n * return (\n * <form onSubmit={async (e) => {\n * e.preventDefault()\n * await signIn({ email: 'user@example.com', password: 'secret' })\n * }}>\n * {error && <p>{error}</p>}\n * <button type=\"submit\">Sign In</button>\n * </form>\n * )\n * }\n * ```\n */\nfunction useAuth(): UseAuthResult {\n\tconst { client, state, isLoading } = useAuthContext()\n\tconst [error, setError] = useState<string | null>(null)\n\n\t// Use useSyncExternalStore to track the user reactively via auth state changes\n\tconst userSnapshotRef = useRef<AuthUser | null>(client.currentUser)\n\tconst stateSerializedRef = useRef<string>(JSON.stringify(client.currentUser))\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\treturn client.onAuthChange(() => {\n\t\t\t\tconst newUser = client.currentUser\n\t\t\t\tconst newSerialized = JSON.stringify(newUser)\n\t\t\t\tif (newSerialized !== stateSerializedRef.current) {\n\t\t\t\t\tuserSnapshotRef.current = newUser\n\t\t\t\t\tstateSerializedRef.current = newSerialized\n\t\t\t\t\tonStoreChange()\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\t\t[client],\n\t)\n\n\tconst getSnapshot = useCallback((): AuthUser | null => {\n\t\treturn userSnapshotRef.current\n\t}, [])\n\n\tconst user = useSyncExternalStore(subscribe, getSnapshot)\n\n\tconst signUp = useCallback(\n\t\tasync (params: {\n\t\t\temail: string\n\t\t\tpassword: string\n\t\t\tname?: string\n\t\t\tdeviceId?: string\n\t\t\tdevicePublicKey?: string\n\t\t}): Promise<void> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\tawait client.signUp(params)\n\t\t\t} catch (err: unknown) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err)\n\t\t\t\tsetError(message)\n\t\t\t}\n\t\t},\n\t\t[client],\n\t)\n\n\tconst signIn = useCallback(\n\t\tasync (params: {\n\t\t\temail: string\n\t\t\tpassword: string\n\t\t\tdeviceId?: string\n\t\t\tdevicePublicKey?: string\n\t\t}): Promise<void> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\tawait client.signIn(params)\n\t\t\t} catch (err: unknown) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err)\n\t\t\t\tsetError(message)\n\t\t\t}\n\t\t},\n\t\t[client],\n\t)\n\n\tconst signInWithOAuth = useCallback(\n\t\tasync (\n\t\t\tprovider: string,\n\t\t\toptions?: OAuthAuthorizationOptions,\n\t\t): Promise<OAuthAuthorizationResult> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\treturn await client.signInWithOAuth(provider, options)\n\t\t\t} catch (err: unknown) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err)\n\t\t\t\tsetError(message)\n\t\t\t\tthrow err\n\t\t\t}\n\t\t},\n\t\t[client],\n\t)\n\n\tconst completeOAuthSignIn = useCallback(\n\t\tasync (provider: string, params: OAuthCallbackParams): Promise<void> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\tawait client.completeOAuthSignIn(provider, params)\n\t\t\t} catch (err: unknown) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err)\n\t\t\t\tsetError(message)\n\t\t\t}\n\t\t},\n\t\t[client],\n\t)\n\n\tconst getOAuthAuthorizationUrl = useCallback(\n\t\tasync (\n\t\t\tprovider: string,\n\t\t\toptions?: OAuthAuthorizationOptions,\n\t\t): Promise<OAuthAuthorizationResult> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\treturn await client.getOAuthAuthorizationUrl(provider, options)\n\t\t\t} catch (err: unknown) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err)\n\t\t\t\tsetError(message)\n\t\t\t\tthrow err\n\t\t\t}\n\t\t},\n\t\t[client],\n\t)\n\n\tconst linkOAuth = useCallback(\n\t\tasync (provider: string, params: OAuthCallbackParams): Promise<LinkedOAuthAccount | null> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\treturn await client.linkOAuth(provider, params)\n\t\t\t} catch (err: unknown) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err)\n\t\t\t\tsetError(message)\n\t\t\t\treturn null\n\t\t\t}\n\t\t},\n\t\t[client],\n\t)\n\n\tconst listLinkedAccounts = useCallback(async (): Promise<LinkedOAuthAccount[]> => {\n\t\tsetError(null)\n\t\ttry {\n\t\t\treturn await client.listLinkedAccounts()\n\t\t} catch (err: unknown) {\n\t\t\tconst message = err instanceof Error ? err.message : String(err)\n\t\t\tsetError(message)\n\t\t\treturn []\n\t\t}\n\t}, [client])\n\n\tconst unlinkOAuth = useCallback(\n\t\tasync (provider: string): Promise<void> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\tawait client.unlinkOAuth(provider)\n\t\t\t} catch (err: unknown) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err)\n\t\t\t\tsetError(message)\n\t\t\t}\n\t\t},\n\t\t[client],\n\t)\n\n\tconst signOut = useCallback(async (): Promise<void> => {\n\t\tsetError(null)\n\t\ttry {\n\t\t\tawait client.signOut()\n\t\t} catch (err: unknown) {\n\t\t\tconst message = err instanceof Error ? err.message : String(err)\n\t\t\tsetError(message)\n\t\t}\n\t}, [client])\n\n\treturn {\n\t\tuser,\n\t\tisAuthenticated: state === 'authenticated',\n\t\tisLoading,\n\t\tsignUp,\n\t\tsignIn,\n\t\tsignInWithOAuth,\n\t\tcompleteOAuthSignIn,\n\t\tgetOAuthAuthorizationUrl,\n\t\tlinkOAuth,\n\t\tlistLinkedAccounts,\n\t\tunlinkOAuth,\n\t\tsignOut,\n\t\terror,\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// useCurrentUser\n// ---------------------------------------------------------------------------\n\n/**\n * React hook that returns the currently authenticated user, or null.\n *\n * A lightweight alternative to {@link useAuth} when you only need the user\n * object and do not need auth methods or error state.\n *\n * Must be used within an {@link AuthProvider}.\n *\n * @returns The current AuthUser or null if not authenticated\n *\n * @example\n * ```typescript\n * function UserAvatar() {\n * const user = useCurrentUser()\n * if (!user) return null\n * return <span>{user.name ?? user.email}</span>\n * }\n * ```\n */\nfunction useCurrentUser(): AuthUser | null {\n\tconst { client } = useAuthContext()\n\n\tconst userSnapshotRef = useRef<AuthUser | null>(client.currentUser)\n\tconst stateSerializedRef = useRef<string>(JSON.stringify(client.currentUser))\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\treturn client.onAuthChange(() => {\n\t\t\t\tconst newUser = client.currentUser\n\t\t\t\tconst newSerialized = JSON.stringify(newUser)\n\t\t\t\tif (newSerialized !== stateSerializedRef.current) {\n\t\t\t\t\tuserSnapshotRef.current = newUser\n\t\t\t\t\tstateSerializedRef.current = newSerialized\n\t\t\t\t\tonStoreChange()\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\t\t[client],\n\t)\n\n\tconst getSnapshot = useCallback((): AuthUser | null => {\n\t\treturn userSnapshotRef.current\n\t}, [])\n\n\treturn useSyncExternalStore(subscribe, getSnapshot)\n}\n\n// ---------------------------------------------------------------------------\n// useAuthStatus\n// ---------------------------------------------------------------------------\n\n/**\n * React hook that returns the current authentication status.\n *\n * Re-renders only when the auth state changes, not on every auth event.\n * Use this for status indicators, route guards, and conditional rendering.\n *\n * Must be used within an {@link AuthProvider}.\n *\n * @returns An AuthStatus object with state, isAuthenticated, and isLoading flags\n *\n * @example\n * ```typescript\n * function AuthGuard({ children }: { children: React.ReactNode }) {\n * const { isAuthenticated, isLoading } = useAuthStatus()\n * if (isLoading) return <Spinner />\n * if (!isAuthenticated) return <Navigate to=\"/login\" />\n * return <>{children}</>\n * }\n * ```\n */\nfunction useAuthStatus(): AuthStatus {\n\tconst { state, isLoading } = useAuthContext()\n\n\treturn {\n\t\tstate,\n\t\tisAuthenticated: state === 'authenticated',\n\t\tisLoading,\n\t}\n}\n\nexport { useAuth, useCurrentUser, useAuthStatus }\nexport type { UseAuthResult, AuthStatus }\n","import {\n\tcreateContext,\n\tuseCallback,\n\tuseContext,\n\tuseEffect,\n\tuseRef,\n\tuseState,\n\tuseSyncExternalStore,\n} from 'react'\nimport type {\n\tClientInvitation,\n\tClientMembership,\n\tClientOrganization,\n\tOrgClient,\n} from '../client/org-client'\n\n// ============================================================================\n// OrgContext\n// ============================================================================\n\n/**\n * Shape of the OrgContext value.\n */\nexport interface OrgContextValue {\n\t/** The OrgClient instance */\n\tclient: OrgClient\n}\n\n/**\n * React context for organization state.\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\n// ============================================================================\n// useOrg\n// ============================================================================\n\n/**\n * Return value of the {@link useOrg} hook.\n */\nexport interface UseOrgResult {\n\t/** Currently active organization, or null */\n\torg: ClientOrganization | null\n\t/** Current user's role in the active organization, or null */\n\trole: string | null\n\t/** Active organization ID, or null */\n\torgId: string | null\n\t/** Switch to a different organization */\n\tswitchOrg: (orgId: string) => Promise<void>\n\t/** Create a new organization */\n\tcreateOrg: (params: { name: string; slug?: string }) => Promise<ClientOrganization>\n\t/** Leave the active organization */\n\tleaveOrg: () => Promise<void>\n\t/** Clear the active organization */\n\tclearOrg: () => void\n\t/** List all organizations the user belongs to */\n\tlistOrgs: () => Promise<ClientOrganization[]>\n\t/** Last error, or null */\n\terror: string | null\n}\n\n/**\n * React hook for organization management and context switching.\n *\n * Re-renders when the active organization changes.\n *\n * @example\n * ```typescript\n * function OrgSwitcher() {\n * const { org, switchOrg, listOrgs, error } = useOrg()\n * const [orgs, setOrgs] = useState<ClientOrganization[]>([])\n *\n * useEffect(() => { listOrgs().then(setOrgs) }, [listOrgs])\n *\n * return (\n * <select value={org?.id ?? ''} onChange={(e) => switchOrg(e.target.value)}>\n * <option value=\"\">Select org...</option>\n * {orgs.map(o => <option key={o.id} value={o.id}>{o.name}</option>)}\n * </select>\n * )\n * }\n * ```\n */\nexport function useOrg(): UseOrgResult {\n\tconst { client } = useOrgContext()\n\tconst [error, setError] = useState<string | null>(null)\n\n\t// Track active org reactively\n\tconst orgSnapshotRef = useRef({\n\t\torgId: client.activeOrgId,\n\t\torg: client.activeOrg,\n\t\trole: client.activeRole,\n\t})\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\treturn client.onOrgChange(() => {\n\t\t\t\torgSnapshotRef.current = {\n\t\t\t\t\torgId: client.activeOrgId,\n\t\t\t\t\torg: client.activeOrg,\n\t\t\t\t\trole: client.activeRole,\n\t\t\t\t}\n\t\t\t\tonStoreChange()\n\t\t\t})\n\t\t},\n\t\t[client],\n\t)\n\n\tconst getSnapshot = useCallback(() => orgSnapshotRef.current, [])\n\n\tconst { orgId, org, role } = useSyncExternalStore(subscribe, getSnapshot)\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\n// ============================================================================\n// useOrgMembers\n// ============================================================================\n\n/**\n * Return value of the {@link useOrgMembers} hook.\n */\nexport interface UseOrgMembersResult {\n\t/** Members of the organization (empty until loaded) */\n\tmembers: ClientMembership[]\n\t/** Whether members are being loaded */\n\tisLoading: boolean\n\t/** Reload the members list */\n\trefresh: () => Promise<void>\n\t/** Invite a user by email */\n\tinvite: (email: string, role: string) => Promise<ClientInvitation>\n\t/** Remove a member */\n\tremoveMember: (userId: string) => Promise<void>\n\t/** Update a member's role */\n\tupdateRole: (userId: string, role: string) => Promise<void>\n\t/** Last error, or null */\n\terror: string | null\n}\n\n/**\n * React hook for managing organization members.\n *\n * Automatically loads members when the orgId changes.\n *\n * @param orgId - Organization ID to manage members for\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\tconst result = await client.listMembers(orgId)\n\t\t\tsetMembers(result)\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\trefresh()\n\t}, [refresh])\n\n\tconst invite = useCallback(\n\t\tasync (email: string, role: string): Promise<ClientInvitation> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\tconst result = await client.inviteMember(orgId, { email, role })\n\t\t\t\treturn result\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, orgId],\n\t)\n\n\tconst removeMember = useCallback(\n\t\tasync (userId: string): Promise<void> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\tawait client.removeMember(orgId, userId)\n\t\t\t\tawait refresh()\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, orgId, refresh],\n\t)\n\n\tconst updateRole = useCallback(\n\t\tasync (userId: string, role: string): Promise<void> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\tawait client.updateMemberRole(orgId, userId, role)\n\t\t\t\tawait refresh()\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, orgId, refresh],\n\t)\n\n\treturn { members, isLoading, refresh, invite, removeMember, updateRole, error }\n}\n\n// ============================================================================\n// usePermission\n// ============================================================================\n\n/**\n * React hook that checks if the current user has a specific role level\n * in the active organization.\n *\n * @param requiredRole - Minimum role required (uses ROLE_HIERARCHY from org-types)\n * @returns true if the user's role is at least requiredRole\n *\n * @example\n * ```typescript\n * function AdminPanel() {\n * const canManage = usePermission('admin')\n * if (!canManage) return <p>Access denied</p>\n * return <AdminSettings />\n * }\n * ```\n */\nexport function usePermission(requiredRole: string): boolean {\n\tconst { client } = useOrgContext()\n\n\tconst snapshotRef = useRef(checkPermission(client.activeRole, requiredRole))\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\treturn client.onOrgChange(() => {\n\t\t\t\tconst newValue = checkPermission(client.activeRole, requiredRole)\n\t\t\t\tif (newValue !== snapshotRef.current) {\n\t\t\t\t\tsnapshotRef.current = newValue\n\t\t\t\t\tonStoreChange()\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\t\t[client, requiredRole],\n\t)\n\n\tconst getSnapshot = useCallback(() => snapshotRef.current, [])\n\n\treturn useSyncExternalStore(subscribe, getSnapshot)\n}\n\n// Simple role hierarchy check (mirrors ROLE_HIERARCHY from org-types)\nconst ROLE_LEVELS: Record<string, number> = {\n\tviewer: 10,\n\tbilling: 15,\n\tmember: 20,\n\tadmin: 30,\n\towner: 40,\n}\n\nfunction checkPermission(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"],"mappings":"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","names":["import_react","import_react","import_react"]}
|
package/dist/react.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode, ReactElement } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { d as AuthClient, e as AuthState$1, j as AuthUser, O as OAuthAuthorizationOptions, o as OAuthAuthorizationResult, p as OAuthCallbackParams, L as LinkedOAuthAccount, q as OrgClient, k as ClientMembership, C as ClientInvitation, l as ClientOrganization } from './org-client-q2u55qod.cjs';
|
|
4
4
|
import '@korajs/core';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -63,12 +63,28 @@ interface UseAuthResult {
|
|
|
63
63
|
email: string;
|
|
64
64
|
password: string;
|
|
65
65
|
name?: string;
|
|
66
|
+
deviceId?: string;
|
|
67
|
+
devicePublicKey?: string;
|
|
66
68
|
}) => Promise<void>;
|
|
67
69
|
/** Sign in with email and password */
|
|
68
70
|
signIn: (params: {
|
|
69
71
|
email: string;
|
|
70
72
|
password: string;
|
|
73
|
+
deviceId?: string;
|
|
74
|
+
devicePublicKey?: string;
|
|
71
75
|
}) => Promise<void>;
|
|
76
|
+
/** Start OAuth sign-in. Web apps can redirect; desktop/mobile can open the returned URL. */
|
|
77
|
+
signInWithOAuth: (provider: string, options?: OAuthAuthorizationOptions) => Promise<OAuthAuthorizationResult>;
|
|
78
|
+
/** Complete an OAuth sign-in callback with code and state. */
|
|
79
|
+
completeOAuthSignIn: (provider: string, params: OAuthCallbackParams) => Promise<void>;
|
|
80
|
+
/** Create an OAuth authorization URL without redirecting. */
|
|
81
|
+
getOAuthAuthorizationUrl: (provider: string, options?: OAuthAuthorizationOptions) => Promise<OAuthAuthorizationResult>;
|
|
82
|
+
/** Link an OAuth provider to the current user. */
|
|
83
|
+
linkOAuth: (provider: string, params: OAuthCallbackParams) => Promise<LinkedOAuthAccount | null>;
|
|
84
|
+
/** List OAuth accounts linked to the current user. */
|
|
85
|
+
listLinkedAccounts: () => Promise<LinkedOAuthAccount[]>;
|
|
86
|
+
/** Unlink an OAuth provider from the current user. */
|
|
87
|
+
unlinkOAuth: (provider: string) => Promise<void>;
|
|
72
88
|
/** Sign out the current user */
|
|
73
89
|
signOut: () => Promise<void>;
|
|
74
90
|
/** Last error message from a sign-up, sign-in, or sign-out attempt, or null */
|
package/dist/react.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode, ReactElement } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { d as AuthClient, e as AuthState$1, j as AuthUser, O as OAuthAuthorizationOptions, o as OAuthAuthorizationResult, p as OAuthCallbackParams, L as LinkedOAuthAccount, q as OrgClient, k as ClientMembership, C as ClientInvitation, l as ClientOrganization } from './org-client-q2u55qod.js';
|
|
4
4
|
import '@korajs/core';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -63,12 +63,28 @@ interface UseAuthResult {
|
|
|
63
63
|
email: string;
|
|
64
64
|
password: string;
|
|
65
65
|
name?: string;
|
|
66
|
+
deviceId?: string;
|
|
67
|
+
devicePublicKey?: string;
|
|
66
68
|
}) => Promise<void>;
|
|
67
69
|
/** Sign in with email and password */
|
|
68
70
|
signIn: (params: {
|
|
69
71
|
email: string;
|
|
70
72
|
password: string;
|
|
73
|
+
deviceId?: string;
|
|
74
|
+
devicePublicKey?: string;
|
|
71
75
|
}) => Promise<void>;
|
|
76
|
+
/** Start OAuth sign-in. Web apps can redirect; desktop/mobile can open the returned URL. */
|
|
77
|
+
signInWithOAuth: (provider: string, options?: OAuthAuthorizationOptions) => Promise<OAuthAuthorizationResult>;
|
|
78
|
+
/** Complete an OAuth sign-in callback with code and state. */
|
|
79
|
+
completeOAuthSignIn: (provider: string, params: OAuthCallbackParams) => Promise<void>;
|
|
80
|
+
/** Create an OAuth authorization URL without redirecting. */
|
|
81
|
+
getOAuthAuthorizationUrl: (provider: string, options?: OAuthAuthorizationOptions) => Promise<OAuthAuthorizationResult>;
|
|
82
|
+
/** Link an OAuth provider to the current user. */
|
|
83
|
+
linkOAuth: (provider: string, params: OAuthCallbackParams) => Promise<LinkedOAuthAccount | null>;
|
|
84
|
+
/** List OAuth accounts linked to the current user. */
|
|
85
|
+
listLinkedAccounts: () => Promise<LinkedOAuthAccount[]>;
|
|
86
|
+
/** Unlink an OAuth provider from the current user. */
|
|
87
|
+
unlinkOAuth: (provider: string) => Promise<void>;
|
|
72
88
|
/** Sign out the current user */
|
|
73
89
|
signOut: () => Promise<void>;
|
|
74
90
|
/** Last error message from a sign-up, sign-in, or sign-out attempt, or null */
|
package/dist/react.js
CHANGED
|
@@ -115,6 +115,79 @@ function useAuth() {
|
|
|
115
115
|
},
|
|
116
116
|
[client]
|
|
117
117
|
);
|
|
118
|
+
const signInWithOAuth = useCallback(
|
|
119
|
+
async (provider, options) => {
|
|
120
|
+
setError(null);
|
|
121
|
+
try {
|
|
122
|
+
return await client.signInWithOAuth(provider, options);
|
|
123
|
+
} catch (err) {
|
|
124
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
125
|
+
setError(message);
|
|
126
|
+
throw err;
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
[client]
|
|
130
|
+
);
|
|
131
|
+
const completeOAuthSignIn = useCallback(
|
|
132
|
+
async (provider, params) => {
|
|
133
|
+
setError(null);
|
|
134
|
+
try {
|
|
135
|
+
await client.completeOAuthSignIn(provider, params);
|
|
136
|
+
} catch (err) {
|
|
137
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
138
|
+
setError(message);
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
[client]
|
|
142
|
+
);
|
|
143
|
+
const getOAuthAuthorizationUrl = useCallback(
|
|
144
|
+
async (provider, options) => {
|
|
145
|
+
setError(null);
|
|
146
|
+
try {
|
|
147
|
+
return await client.getOAuthAuthorizationUrl(provider, options);
|
|
148
|
+
} catch (err) {
|
|
149
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
150
|
+
setError(message);
|
|
151
|
+
throw err;
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
[client]
|
|
155
|
+
);
|
|
156
|
+
const linkOAuth = useCallback(
|
|
157
|
+
async (provider, params) => {
|
|
158
|
+
setError(null);
|
|
159
|
+
try {
|
|
160
|
+
return await client.linkOAuth(provider, params);
|
|
161
|
+
} catch (err) {
|
|
162
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
163
|
+
setError(message);
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
[client]
|
|
168
|
+
);
|
|
169
|
+
const listLinkedAccounts = useCallback(async () => {
|
|
170
|
+
setError(null);
|
|
171
|
+
try {
|
|
172
|
+
return await client.listLinkedAccounts();
|
|
173
|
+
} catch (err) {
|
|
174
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
175
|
+
setError(message);
|
|
176
|
+
return [];
|
|
177
|
+
}
|
|
178
|
+
}, [client]);
|
|
179
|
+
const unlinkOAuth = useCallback(
|
|
180
|
+
async (provider) => {
|
|
181
|
+
setError(null);
|
|
182
|
+
try {
|
|
183
|
+
await client.unlinkOAuth(provider);
|
|
184
|
+
} catch (err) {
|
|
185
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
186
|
+
setError(message);
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
[client]
|
|
190
|
+
);
|
|
118
191
|
const signOut = useCallback(async () => {
|
|
119
192
|
setError(null);
|
|
120
193
|
try {
|
|
@@ -130,6 +203,12 @@ function useAuth() {
|
|
|
130
203
|
isLoading,
|
|
131
204
|
signUp,
|
|
132
205
|
signIn,
|
|
206
|
+
signInWithOAuth,
|
|
207
|
+
completeOAuthSignIn,
|
|
208
|
+
getOAuthAuthorizationUrl,
|
|
209
|
+
linkOAuth,
|
|
210
|
+
listLinkedAccounts,
|
|
211
|
+
unlinkOAuth,
|
|
133
212
|
signOut,
|
|
134
213
|
error
|
|
135
214
|
};
|
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/org-hooks.ts"],"sourcesContent":["import { createElement, useEffect, useState } from 'react'\nimport type { ReactElement, ReactNode } from 'react'\nimport type { AuthClient, AuthState } from '../client/auth-client'\nimport { AuthContext } from './auth-context'\n\n/**\n * Props for the AuthProvider component.\n */\ninterface AuthProviderProps {\n\t/** The AuthClient instance to provide to child components */\n\tclient: AuthClient\n\n\t/** Child components that will have access to auth context */\n\tchildren: ReactNode\n\n\t/**\n\t * Optional fallback content to render while the auth client is initializing.\n\t * If not provided, children are rendered with `isLoading: true` in the context.\n\t */\n\tfallback?: ReactNode\n}\n\n/**\n * React context provider that wraps the AuthClient for use with auth hooks.\n *\n * Calls `client.initialize()` on mount to restore any existing session from\n * stored tokens. Subscribes to auth state changes and re-renders children\n * when the state transitions.\n *\n * Must be placed above any component that uses {@link useAuth},\n * {@link useCurrentUser}, or {@link useAuthStatus}.\n *\n * @param props - Provider props including the AuthClient instance and children\n * @returns A React element wrapping children in the AuthContext\n *\n * @example\n * ```typescript\n * import { AuthClient } from '@korajs/auth'\n * import { AuthProvider } from '@korajs/auth/react'\n *\n * const authClient = new AuthClient({ serverUrl: 'http://localhost:3001' })\n *\n * function App() {\n * return (\n * <AuthProvider client={authClient} fallback={<div>Loading...</div>}>\n * <MyApp />\n * </AuthProvider>\n * )\n * }\n * ```\n */\nfunction AuthProvider({ client, children, fallback }: AuthProviderProps): ReactElement {\n\tconst [state, setState] = useState<AuthState>(client.state)\n\tconst [isLoading, setIsLoading] = useState(true)\n\tconst [initError, setInitError] = useState<Error | null>(null)\n\n\t// Initialize the auth client on mount\n\tuseEffect(() => {\n\t\tlet cancelled = false\n\n\t\t// Subscribe to auth state changes\n\t\tconst unsubscribe = client.onAuthChange((newState) => {\n\t\t\tif (!cancelled) {\n\t\t\t\tsetState(newState)\n\t\t\t}\n\t\t})\n\n\t\tclient\n\t\t\t.initialize()\n\t\t\t.then(() => {\n\t\t\t\tif (!cancelled) {\n\t\t\t\t\tsetState(client.state)\n\t\t\t\t\tsetIsLoading(false)\n\t\t\t\t}\n\t\t\t})\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tif (!cancelled) {\n\t\t\t\t\tconst err = error instanceof Error ? error : new Error(String(error))\n\t\t\t\t\tconsole.error('[Kora Auth] Initialization failed:', err)\n\t\t\t\t\tsetInitError(err)\n\t\t\t\t\tsetIsLoading(false)\n\t\t\t\t}\n\t\t\t})\n\n\t\treturn () => {\n\t\t\tcancelled = true\n\t\t\tunsubscribe()\n\t\t}\n\t}, [client])\n\n\t// Show error if initialization failed\n\tif (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\tinitError.message,\n\t\t)\n\t}\n\n\t// Show fallback while loading\n\tif (isLoading && fallback !== undefined) {\n\t\treturn fallback as ReactElement\n\t}\n\n\tconst contextValue = {\n\t\tclient,\n\t\tstate,\n\t\tisLoading,\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 { AuthClient } from '../client/auth-client'\n\n/**\n * Possible authentication states for the client.\n * - 'loading': Initial state while restoring tokens from storage\n * - 'authenticated': User is signed in with a valid session\n * - 'unauthenticated': No valid session exists\n */\ntype AuthState = 'loading' | 'authenticated' | 'unauthenticated'\n\n/**\n * Shape of the value provided by the AuthContext.\n * Includes the AuthClient instance, reactive state, and a loading flag.\n */\ninterface AuthContextValue {\n\t/** The underlying AuthClient instance for direct access */\n\tclient: AuthClient\n\n\t/** Current authentication state */\n\tstate: AuthState\n\n\t/** Whether the client is still initializing (restoring session from storage) */\n\tisLoading: boolean\n}\n\n/**\n * React context for Kora authentication.\n *\n * Provides the AuthClient and reactive auth state to child components.\n * Must be provided by an AuthProvider higher in the component tree.\n * Defaults to null — hooks that consume this context throw if it is missing.\n */\nconst AuthContext = createContext<AuthContextValue | null>(null)\n\nexport { AuthContext }\nexport type { AuthContextValue, AuthState }\n","import { useCallback, useContext, useEffect, useRef, useState, useSyncExternalStore } from 'react'\nimport type { AuthState, AuthUser } from '../client/auth-client'\nimport { AuthContext } from './auth-context'\n\n// ---------------------------------------------------------------------------\n// Internal context accessor\n// ---------------------------------------------------------------------------\n\n/**\n * Internal hook that reads and validates the AuthContext.\n * Throws a descriptive error if used outside an AuthProvider.\n */\nfunction useAuthContext(): {\n\tclient: import('../client/auth-client').AuthClient\n\tstate: AuthState\n\tisLoading: boolean\n} {\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\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * Return value of the {@link useAuth} hook.\n */\ninterface UseAuthResult {\n\t/** Current authenticated user, or null if not signed in */\n\tuser: AuthUser | null\n\n\t/** Whether the user is currently authenticated */\n\tisAuthenticated: boolean\n\n\t/** Whether the auth client is still initializing (restoring session) */\n\tisLoading: boolean\n\n\t/** Sign up a new user account */\n\tsignUp: (params: { email: string; password: string; name?: string }) => Promise<void>\n\n\t/** Sign in with email and password */\n\tsignIn: (params: { email: string; password: string }) => Promise<void>\n\n\t/** Sign out the current user */\n\tsignOut: () => Promise<void>\n\n\t/** Last error message from a sign-up, sign-in, or sign-out attempt, or null */\n\terror: string | null\n}\n\n/**\n * Auth status information returned by {@link useAuthStatus}.\n */\ninterface AuthStatus {\n\t/** Current authentication state */\n\tstate: AuthState\n\n\t/** Whether the user is currently authenticated */\n\tisAuthenticated: boolean\n\n\t/** Whether the auth client is still initializing */\n\tisLoading: boolean\n}\n\n// ---------------------------------------------------------------------------\n// useAuth\n// ---------------------------------------------------------------------------\n\n/**\n * React hook providing full authentication functionality.\n *\n * Returns the current user, loading state, error state, and methods for\n * sign-up, sign-in, and sign-out. Re-renders when auth state changes.\n *\n * Must be used within an {@link AuthProvider}.\n *\n * @returns An object with user info, auth methods, and status flags\n *\n * @example\n * ```typescript\n * function LoginPage() {\n * const { user, isAuthenticated, isLoading, signIn, error } = useAuth()\n *\n * if (isLoading) return <div>Loading...</div>\n * if (isAuthenticated) return <div>Welcome, {user?.name}</div>\n *\n * return (\n * <form onSubmit={async (e) => {\n * e.preventDefault()\n * await signIn({ email: 'user@example.com', password: 'secret' })\n * }}>\n * {error && <p>{error}</p>}\n * <button type=\"submit\">Sign In</button>\n * </form>\n * )\n * }\n * ```\n */\nfunction useAuth(): UseAuthResult {\n\tconst { client, state, isLoading } = useAuthContext()\n\tconst [error, setError] = useState<string | null>(null)\n\n\t// Use useSyncExternalStore to track the user reactively via auth state changes\n\tconst userSnapshotRef = useRef<AuthUser | null>(client.currentUser)\n\tconst stateSerializedRef = useRef<string>(JSON.stringify(client.currentUser))\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\treturn client.onAuthChange(() => {\n\t\t\t\tconst newUser = client.currentUser\n\t\t\t\tconst newSerialized = JSON.stringify(newUser)\n\t\t\t\tif (newSerialized !== stateSerializedRef.current) {\n\t\t\t\t\tuserSnapshotRef.current = newUser\n\t\t\t\t\tstateSerializedRef.current = newSerialized\n\t\t\t\t\tonStoreChange()\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\t\t[client],\n\t)\n\n\tconst getSnapshot = useCallback((): AuthUser | null => {\n\t\treturn userSnapshotRef.current\n\t}, [])\n\n\tconst user = useSyncExternalStore(subscribe, getSnapshot)\n\n\tconst signUp = useCallback(\n\t\tasync (params: { email: string; password: string; name?: string }): Promise<void> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\tawait client.signUp(params)\n\t\t\t} catch (err: unknown) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err)\n\t\t\t\tsetError(message)\n\t\t\t}\n\t\t},\n\t\t[client],\n\t)\n\n\tconst signIn = useCallback(\n\t\tasync (params: { email: string; password: string }): Promise<void> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\tawait client.signIn(params)\n\t\t\t} catch (err: unknown) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err)\n\t\t\t\tsetError(message)\n\t\t\t}\n\t\t},\n\t\t[client],\n\t)\n\n\tconst signOut = useCallback(async (): Promise<void> => {\n\t\tsetError(null)\n\t\ttry {\n\t\t\tawait client.signOut()\n\t\t} catch (err: unknown) {\n\t\t\tconst message = err instanceof Error ? err.message : String(err)\n\t\t\tsetError(message)\n\t\t}\n\t}, [client])\n\n\treturn {\n\t\tuser,\n\t\tisAuthenticated: state === 'authenticated',\n\t\tisLoading,\n\t\tsignUp,\n\t\tsignIn,\n\t\tsignOut,\n\t\terror,\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// useCurrentUser\n// ---------------------------------------------------------------------------\n\n/**\n * React hook that returns the currently authenticated user, or null.\n *\n * A lightweight alternative to {@link useAuth} when you only need the user\n * object and do not need auth methods or error state.\n *\n * Must be used within an {@link AuthProvider}.\n *\n * @returns The current AuthUser or null if not authenticated\n *\n * @example\n * ```typescript\n * function UserAvatar() {\n * const user = useCurrentUser()\n * if (!user) return null\n * return <span>{user.name ?? user.email}</span>\n * }\n * ```\n */\nfunction useCurrentUser(): AuthUser | null {\n\tconst { client } = useAuthContext()\n\n\tconst userSnapshotRef = useRef<AuthUser | null>(client.currentUser)\n\tconst stateSerializedRef = useRef<string>(JSON.stringify(client.currentUser))\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\treturn client.onAuthChange(() => {\n\t\t\t\tconst newUser = client.currentUser\n\t\t\t\tconst newSerialized = JSON.stringify(newUser)\n\t\t\t\tif (newSerialized !== stateSerializedRef.current) {\n\t\t\t\t\tuserSnapshotRef.current = newUser\n\t\t\t\t\tstateSerializedRef.current = newSerialized\n\t\t\t\t\tonStoreChange()\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\t\t[client],\n\t)\n\n\tconst getSnapshot = useCallback((): AuthUser | null => {\n\t\treturn userSnapshotRef.current\n\t}, [])\n\n\treturn useSyncExternalStore(subscribe, getSnapshot)\n}\n\n// ---------------------------------------------------------------------------\n// useAuthStatus\n// ---------------------------------------------------------------------------\n\n/**\n * React hook that returns the current authentication status.\n *\n * Re-renders only when the auth state changes, not on every auth event.\n * Use this for status indicators, route guards, and conditional rendering.\n *\n * Must be used within an {@link AuthProvider}.\n *\n * @returns An AuthStatus object with state, isAuthenticated, and isLoading flags\n *\n * @example\n * ```typescript\n * function AuthGuard({ children }: { children: React.ReactNode }) {\n * const { isAuthenticated, isLoading } = useAuthStatus()\n * if (isLoading) return <Spinner />\n * if (!isAuthenticated) return <Navigate to=\"/login\" />\n * return <>{children}</>\n * }\n * ```\n */\nfunction useAuthStatus(): AuthStatus {\n\tconst { state, isLoading } = useAuthContext()\n\n\treturn {\n\t\tstate,\n\t\tisAuthenticated: state === 'authenticated',\n\t\tisLoading,\n\t}\n}\n\nexport { useAuth, useCurrentUser, useAuthStatus }\nexport type { UseAuthResult, AuthStatus }\n","import {\n\tcreateContext,\n\tuseCallback,\n\tuseContext,\n\tuseEffect,\n\tuseRef,\n\tuseState,\n\tuseSyncExternalStore,\n} from 'react'\nimport type {\n\tClientInvitation,\n\tClientMembership,\n\tClientOrganization,\n\tOrgClient,\n} from '../client/org-client'\n\n// ============================================================================\n// OrgContext\n// ============================================================================\n\n/**\n * Shape of the OrgContext value.\n */\nexport interface OrgContextValue {\n\t/** The OrgClient instance */\n\tclient: OrgClient\n}\n\n/**\n * React context for organization state.\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\n// ============================================================================\n// useOrg\n// ============================================================================\n\n/**\n * Return value of the {@link useOrg} hook.\n */\nexport interface UseOrgResult {\n\t/** Currently active organization, or null */\n\torg: ClientOrganization | null\n\t/** Current user's role in the active organization, or null */\n\trole: string | null\n\t/** Active organization ID, or null */\n\torgId: string | null\n\t/** Switch to a different organization */\n\tswitchOrg: (orgId: string) => Promise<void>\n\t/** Create a new organization */\n\tcreateOrg: (params: { name: string; slug?: string }) => Promise<ClientOrganization>\n\t/** Leave the active organization */\n\tleaveOrg: () => Promise<void>\n\t/** Clear the active organization */\n\tclearOrg: () => void\n\t/** List all organizations the user belongs to */\n\tlistOrgs: () => Promise<ClientOrganization[]>\n\t/** Last error, or null */\n\terror: string | null\n}\n\n/**\n * React hook for organization management and context switching.\n *\n * Re-renders when the active organization changes.\n *\n * @example\n * ```typescript\n * function OrgSwitcher() {\n * const { org, switchOrg, listOrgs, error } = useOrg()\n * const [orgs, setOrgs] = useState<ClientOrganization[]>([])\n *\n * useEffect(() => { listOrgs().then(setOrgs) }, [listOrgs])\n *\n * return (\n * <select value={org?.id ?? ''} onChange={(e) => switchOrg(e.target.value)}>\n * <option value=\"\">Select org...</option>\n * {orgs.map(o => <option key={o.id} value={o.id}>{o.name}</option>)}\n * </select>\n * )\n * }\n * ```\n */\nexport function useOrg(): UseOrgResult {\n\tconst { client } = useOrgContext()\n\tconst [error, setError] = useState<string | null>(null)\n\n\t// Track active org reactively\n\tconst orgSnapshotRef = useRef({\n\t\torgId: client.activeOrgId,\n\t\torg: client.activeOrg,\n\t\trole: client.activeRole,\n\t})\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\treturn client.onOrgChange(() => {\n\t\t\t\torgSnapshotRef.current = {\n\t\t\t\t\torgId: client.activeOrgId,\n\t\t\t\t\torg: client.activeOrg,\n\t\t\t\t\trole: client.activeRole,\n\t\t\t\t}\n\t\t\t\tonStoreChange()\n\t\t\t})\n\t\t},\n\t\t[client],\n\t)\n\n\tconst getSnapshot = useCallback(() => orgSnapshotRef.current, [])\n\n\tconst { orgId, org, role } = useSyncExternalStore(subscribe, getSnapshot)\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\n// ============================================================================\n// useOrgMembers\n// ============================================================================\n\n/**\n * Return value of the {@link useOrgMembers} hook.\n */\nexport interface UseOrgMembersResult {\n\t/** Members of the organization (empty until loaded) */\n\tmembers: ClientMembership[]\n\t/** Whether members are being loaded */\n\tisLoading: boolean\n\t/** Reload the members list */\n\trefresh: () => Promise<void>\n\t/** Invite a user by email */\n\tinvite: (email: string, role: string) => Promise<ClientInvitation>\n\t/** Remove a member */\n\tremoveMember: (userId: string) => Promise<void>\n\t/** Update a member's role */\n\tupdateRole: (userId: string, role: string) => Promise<void>\n\t/** Last error, or null */\n\terror: string | null\n}\n\n/**\n * React hook for managing organization members.\n *\n * Automatically loads members when the orgId changes.\n *\n * @param orgId - Organization ID to manage members for\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\tconst result = await client.listMembers(orgId)\n\t\t\tsetMembers(result)\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\trefresh()\n\t}, [refresh])\n\n\tconst invite = useCallback(\n\t\tasync (email: string, role: string): Promise<ClientInvitation> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\tconst result = await client.inviteMember(orgId, { email, role })\n\t\t\t\treturn result\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, orgId],\n\t)\n\n\tconst removeMember = useCallback(\n\t\tasync (userId: string): Promise<void> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\tawait client.removeMember(orgId, userId)\n\t\t\t\tawait refresh()\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, orgId, refresh],\n\t)\n\n\tconst updateRole = useCallback(\n\t\tasync (userId: string, role: string): Promise<void> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\tawait client.updateMemberRole(orgId, userId, role)\n\t\t\t\tawait refresh()\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, orgId, refresh],\n\t)\n\n\treturn { members, isLoading, refresh, invite, removeMember, updateRole, error }\n}\n\n// ============================================================================\n// usePermission\n// ============================================================================\n\n/**\n * React hook that checks if the current user has a specific role level\n * in the active organization.\n *\n * @param requiredRole - Minimum role required (uses ROLE_HIERARCHY from org-types)\n * @returns true if the user's role is at least requiredRole\n *\n * @example\n * ```typescript\n * function AdminPanel() {\n * const canManage = usePermission('admin')\n * if (!canManage) return <p>Access denied</p>\n * return <AdminSettings />\n * }\n * ```\n */\nexport function usePermission(requiredRole: string): boolean {\n\tconst { client } = useOrgContext()\n\n\tconst snapshotRef = useRef(checkPermission(client.activeRole, requiredRole))\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\treturn client.onOrgChange(() => {\n\t\t\t\tconst newValue = checkPermission(client.activeRole, requiredRole)\n\t\t\t\tif (newValue !== snapshotRef.current) {\n\t\t\t\t\tsnapshotRef.current = newValue\n\t\t\t\t\tonStoreChange()\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\t\t[client, requiredRole],\n\t)\n\n\tconst getSnapshot = useCallback(() => snapshotRef.current, [])\n\n\treturn useSyncExternalStore(subscribe, getSnapshot)\n}\n\n// Simple role hierarchy check (mirrors ROLE_HIERARCHY from org-types)\nconst ROLE_LEVELS: Record<string, number> = {\n\tviewer: 10,\n\tbilling: 15,\n\tmember: 20,\n\tadmin: 30,\n\towner: 40,\n}\n\nfunction checkPermission(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"],"mappings":"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","names":["useState","useState","createContext","useCallback","useContext","useEffect","useRef","useState","useSyncExternalStore"]}
|
|
1
|
+
{"version":3,"sources":["../src/react/AuthProvider.tsx","../src/react/auth-context.ts","../src/react/hooks.ts","../src/react/org-hooks.ts"],"sourcesContent":["import { createElement, useEffect, useState } from 'react'\nimport type { ReactElement, ReactNode } from 'react'\nimport type { AuthClient, AuthState } from '../client/auth-client'\nimport { AuthContext } from './auth-context'\n\n/**\n * Props for the AuthProvider component.\n */\ninterface AuthProviderProps {\n\t/** The AuthClient instance to provide to child components */\n\tclient: AuthClient\n\n\t/** Child components that will have access to auth context */\n\tchildren: ReactNode\n\n\t/**\n\t * Optional fallback content to render while the auth client is initializing.\n\t * If not provided, children are rendered with `isLoading: true` in the context.\n\t */\n\tfallback?: ReactNode\n}\n\n/**\n * React context provider that wraps the AuthClient for use with auth hooks.\n *\n * Calls `client.initialize()` on mount to restore any existing session from\n * stored tokens. Subscribes to auth state changes and re-renders children\n * when the state transitions.\n *\n * Must be placed above any component that uses {@link useAuth},\n * {@link useCurrentUser}, or {@link useAuthStatus}.\n *\n * @param props - Provider props including the AuthClient instance and children\n * @returns A React element wrapping children in the AuthContext\n *\n * @example\n * ```typescript\n * import { AuthClient } from '@korajs/auth'\n * import { AuthProvider } from '@korajs/auth/react'\n *\n * const authClient = new AuthClient({ serverUrl: 'http://localhost:3001' })\n *\n * function App() {\n * return (\n * <AuthProvider client={authClient} fallback={<div>Loading...</div>}>\n * <MyApp />\n * </AuthProvider>\n * )\n * }\n * ```\n */\nfunction AuthProvider({ client, children, fallback }: AuthProviderProps): ReactElement {\n\tconst [state, setState] = useState<AuthState>(client.state)\n\tconst [isLoading, setIsLoading] = useState(true)\n\tconst [initError, setInitError] = useState<Error | null>(null)\n\n\t// Initialize the auth client on mount\n\tuseEffect(() => {\n\t\tlet cancelled = false\n\n\t\t// Subscribe to auth state changes\n\t\tconst unsubscribe = client.onAuthChange((newState) => {\n\t\t\tif (!cancelled) {\n\t\t\t\tsetState(newState)\n\t\t\t}\n\t\t})\n\n\t\tclient\n\t\t\t.initialize()\n\t\t\t.then(() => {\n\t\t\t\tif (!cancelled) {\n\t\t\t\t\tsetState(client.state)\n\t\t\t\t\tsetIsLoading(false)\n\t\t\t\t}\n\t\t\t})\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tif (!cancelled) {\n\t\t\t\t\tconst err = error instanceof Error ? error : new Error(String(error))\n\t\t\t\t\tconsole.error('[Kora Auth] Initialization failed:', err)\n\t\t\t\t\tsetInitError(err)\n\t\t\t\t\tsetIsLoading(false)\n\t\t\t\t}\n\t\t\t})\n\n\t\treturn () => {\n\t\t\tcancelled = true\n\t\t\tunsubscribe()\n\t\t}\n\t}, [client])\n\n\t// Show error if initialization failed\n\tif (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\tinitError.message,\n\t\t)\n\t}\n\n\t// Show fallback while loading\n\tif (isLoading && fallback !== undefined) {\n\t\treturn fallback as ReactElement\n\t}\n\n\tconst contextValue = {\n\t\tclient,\n\t\tstate,\n\t\tisLoading,\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 { AuthClient } from '../client/auth-client'\n\n/**\n * Possible authentication states for the client.\n * - 'loading': Initial state while restoring tokens from storage\n * - 'authenticated': User is signed in with a valid session\n * - 'unauthenticated': No valid session exists\n */\ntype AuthState = 'loading' | 'authenticated' | 'unauthenticated'\n\n/**\n * Shape of the value provided by the AuthContext.\n * Includes the AuthClient instance, reactive state, and a loading flag.\n */\ninterface AuthContextValue {\n\t/** The underlying AuthClient instance for direct access */\n\tclient: AuthClient\n\n\t/** Current authentication state */\n\tstate: AuthState\n\n\t/** Whether the client is still initializing (restoring session from storage) */\n\tisLoading: boolean\n}\n\n/**\n * React context for Kora authentication.\n *\n * Provides the AuthClient and reactive auth state to child components.\n * Must be provided by an AuthProvider higher in the component tree.\n * Defaults to null — hooks that consume this context throw if it is missing.\n */\nconst AuthContext = createContext<AuthContextValue | null>(null)\n\nexport { AuthContext }\nexport type { AuthContextValue, AuthState }\n","import { useCallback, useContext, useEffect, useRef, useState, 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\n// ---------------------------------------------------------------------------\n// Internal context accessor\n// ---------------------------------------------------------------------------\n\n/**\n * Internal hook that reads and validates the AuthContext.\n * Throws a descriptive error if used outside an AuthProvider.\n */\nfunction useAuthContext(): {\n\tclient: import('../client/auth-client').AuthClient\n\tstate: AuthState\n\tisLoading: boolean\n} {\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\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * Return value of the {@link useAuth} hook.\n */\ninterface UseAuthResult {\n\t/** Current authenticated user, or null if not signed in */\n\tuser: AuthUser | null\n\n\t/** Whether the user is currently authenticated */\n\tisAuthenticated: boolean\n\n\t/** Whether the auth client is still initializing (restoring session) */\n\tisLoading: boolean\n\n\t/** Sign up a new user account */\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\n\t/** Sign in with email and password */\n\tsignIn: (params: {\n\t\temail: string\n\t\tpassword: string\n\t\tdeviceId?: string\n\t\tdevicePublicKey?: string\n\t}) => Promise<void>\n\n\t/** Start OAuth sign-in. Web apps can redirect; desktop/mobile can open the returned URL. */\n\tsignInWithOAuth: (\n\t\tprovider: string,\n\t\toptions?: OAuthAuthorizationOptions,\n\t) => Promise<OAuthAuthorizationResult>\n\n\t/** Complete an OAuth sign-in callback with code and state. */\n\tcompleteOAuthSignIn: (provider: string, params: OAuthCallbackParams) => Promise<void>\n\n\t/** Create an OAuth authorization URL without redirecting. */\n\tgetOAuthAuthorizationUrl: (\n\t\tprovider: string,\n\t\toptions?: OAuthAuthorizationOptions,\n\t) => Promise<OAuthAuthorizationResult>\n\n\t/** Link an OAuth provider to the current user. */\n\tlinkOAuth: (provider: string, params: OAuthCallbackParams) => Promise<LinkedOAuthAccount | null>\n\n\t/** List OAuth accounts linked to the current user. */\n\tlistLinkedAccounts: () => Promise<LinkedOAuthAccount[]>\n\n\t/** Unlink an OAuth provider from the current user. */\n\tunlinkOAuth: (provider: string) => Promise<void>\n\n\t/** Sign out the current user */\n\tsignOut: () => Promise<void>\n\n\t/** Last error message from a sign-up, sign-in, or sign-out attempt, or null */\n\terror: string | null\n}\n\n/**\n * Auth status information returned by {@link useAuthStatus}.\n */\ninterface AuthStatus {\n\t/** Current authentication state */\n\tstate: AuthState\n\n\t/** Whether the user is currently authenticated */\n\tisAuthenticated: boolean\n\n\t/** Whether the auth client is still initializing */\n\tisLoading: boolean\n}\n\n// ---------------------------------------------------------------------------\n// useAuth\n// ---------------------------------------------------------------------------\n\n/**\n * React hook providing full authentication functionality.\n *\n * Returns the current user, loading state, error state, and methods for\n * sign-up, sign-in, and sign-out. Re-renders when auth state changes.\n *\n * Must be used within an {@link AuthProvider}.\n *\n * @returns An object with user info, auth methods, and status flags\n *\n * @example\n * ```typescript\n * function LoginPage() {\n * const { user, isAuthenticated, isLoading, signIn, error } = useAuth()\n *\n * if (isLoading) return <div>Loading...</div>\n * if (isAuthenticated) return <div>Welcome, {user?.name}</div>\n *\n * return (\n * <form onSubmit={async (e) => {\n * e.preventDefault()\n * await signIn({ email: 'user@example.com', password: 'secret' })\n * }}>\n * {error && <p>{error}</p>}\n * <button type=\"submit\">Sign In</button>\n * </form>\n * )\n * }\n * ```\n */\nfunction useAuth(): UseAuthResult {\n\tconst { client, state, isLoading } = useAuthContext()\n\tconst [error, setError] = useState<string | null>(null)\n\n\t// Use useSyncExternalStore to track the user reactively via auth state changes\n\tconst userSnapshotRef = useRef<AuthUser | null>(client.currentUser)\n\tconst stateSerializedRef = useRef<string>(JSON.stringify(client.currentUser))\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\treturn client.onAuthChange(() => {\n\t\t\t\tconst newUser = client.currentUser\n\t\t\t\tconst newSerialized = JSON.stringify(newUser)\n\t\t\t\tif (newSerialized !== stateSerializedRef.current) {\n\t\t\t\t\tuserSnapshotRef.current = newUser\n\t\t\t\t\tstateSerializedRef.current = newSerialized\n\t\t\t\t\tonStoreChange()\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\t\t[client],\n\t)\n\n\tconst getSnapshot = useCallback((): AuthUser | null => {\n\t\treturn userSnapshotRef.current\n\t}, [])\n\n\tconst user = useSyncExternalStore(subscribe, getSnapshot)\n\n\tconst signUp = useCallback(\n\t\tasync (params: {\n\t\t\temail: string\n\t\t\tpassword: string\n\t\t\tname?: string\n\t\t\tdeviceId?: string\n\t\t\tdevicePublicKey?: string\n\t\t}): Promise<void> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\tawait client.signUp(params)\n\t\t\t} catch (err: unknown) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err)\n\t\t\t\tsetError(message)\n\t\t\t}\n\t\t},\n\t\t[client],\n\t)\n\n\tconst signIn = useCallback(\n\t\tasync (params: {\n\t\t\temail: string\n\t\t\tpassword: string\n\t\t\tdeviceId?: string\n\t\t\tdevicePublicKey?: string\n\t\t}): Promise<void> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\tawait client.signIn(params)\n\t\t\t} catch (err: unknown) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err)\n\t\t\t\tsetError(message)\n\t\t\t}\n\t\t},\n\t\t[client],\n\t)\n\n\tconst signInWithOAuth = useCallback(\n\t\tasync (\n\t\t\tprovider: string,\n\t\t\toptions?: OAuthAuthorizationOptions,\n\t\t): Promise<OAuthAuthorizationResult> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\treturn await client.signInWithOAuth(provider, options)\n\t\t\t} catch (err: unknown) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err)\n\t\t\t\tsetError(message)\n\t\t\t\tthrow err\n\t\t\t}\n\t\t},\n\t\t[client],\n\t)\n\n\tconst completeOAuthSignIn = useCallback(\n\t\tasync (provider: string, params: OAuthCallbackParams): Promise<void> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\tawait client.completeOAuthSignIn(provider, params)\n\t\t\t} catch (err: unknown) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err)\n\t\t\t\tsetError(message)\n\t\t\t}\n\t\t},\n\t\t[client],\n\t)\n\n\tconst getOAuthAuthorizationUrl = useCallback(\n\t\tasync (\n\t\t\tprovider: string,\n\t\t\toptions?: OAuthAuthorizationOptions,\n\t\t): Promise<OAuthAuthorizationResult> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\treturn await client.getOAuthAuthorizationUrl(provider, options)\n\t\t\t} catch (err: unknown) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err)\n\t\t\t\tsetError(message)\n\t\t\t\tthrow err\n\t\t\t}\n\t\t},\n\t\t[client],\n\t)\n\n\tconst linkOAuth = useCallback(\n\t\tasync (provider: string, params: OAuthCallbackParams): Promise<LinkedOAuthAccount | null> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\treturn await client.linkOAuth(provider, params)\n\t\t\t} catch (err: unknown) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err)\n\t\t\t\tsetError(message)\n\t\t\t\treturn null\n\t\t\t}\n\t\t},\n\t\t[client],\n\t)\n\n\tconst listLinkedAccounts = useCallback(async (): Promise<LinkedOAuthAccount[]> => {\n\t\tsetError(null)\n\t\ttry {\n\t\t\treturn await client.listLinkedAccounts()\n\t\t} catch (err: unknown) {\n\t\t\tconst message = err instanceof Error ? err.message : String(err)\n\t\t\tsetError(message)\n\t\t\treturn []\n\t\t}\n\t}, [client])\n\n\tconst unlinkOAuth = useCallback(\n\t\tasync (provider: string): Promise<void> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\tawait client.unlinkOAuth(provider)\n\t\t\t} catch (err: unknown) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err)\n\t\t\t\tsetError(message)\n\t\t\t}\n\t\t},\n\t\t[client],\n\t)\n\n\tconst signOut = useCallback(async (): Promise<void> => {\n\t\tsetError(null)\n\t\ttry {\n\t\t\tawait client.signOut()\n\t\t} catch (err: unknown) {\n\t\t\tconst message = err instanceof Error ? err.message : String(err)\n\t\t\tsetError(message)\n\t\t}\n\t}, [client])\n\n\treturn {\n\t\tuser,\n\t\tisAuthenticated: state === 'authenticated',\n\t\tisLoading,\n\t\tsignUp,\n\t\tsignIn,\n\t\tsignInWithOAuth,\n\t\tcompleteOAuthSignIn,\n\t\tgetOAuthAuthorizationUrl,\n\t\tlinkOAuth,\n\t\tlistLinkedAccounts,\n\t\tunlinkOAuth,\n\t\tsignOut,\n\t\terror,\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// useCurrentUser\n// ---------------------------------------------------------------------------\n\n/**\n * React hook that returns the currently authenticated user, or null.\n *\n * A lightweight alternative to {@link useAuth} when you only need the user\n * object and do not need auth methods or error state.\n *\n * Must be used within an {@link AuthProvider}.\n *\n * @returns The current AuthUser or null if not authenticated\n *\n * @example\n * ```typescript\n * function UserAvatar() {\n * const user = useCurrentUser()\n * if (!user) return null\n * return <span>{user.name ?? user.email}</span>\n * }\n * ```\n */\nfunction useCurrentUser(): AuthUser | null {\n\tconst { client } = useAuthContext()\n\n\tconst userSnapshotRef = useRef<AuthUser | null>(client.currentUser)\n\tconst stateSerializedRef = useRef<string>(JSON.stringify(client.currentUser))\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\treturn client.onAuthChange(() => {\n\t\t\t\tconst newUser = client.currentUser\n\t\t\t\tconst newSerialized = JSON.stringify(newUser)\n\t\t\t\tif (newSerialized !== stateSerializedRef.current) {\n\t\t\t\t\tuserSnapshotRef.current = newUser\n\t\t\t\t\tstateSerializedRef.current = newSerialized\n\t\t\t\t\tonStoreChange()\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\t\t[client],\n\t)\n\n\tconst getSnapshot = useCallback((): AuthUser | null => {\n\t\treturn userSnapshotRef.current\n\t}, [])\n\n\treturn useSyncExternalStore(subscribe, getSnapshot)\n}\n\n// ---------------------------------------------------------------------------\n// useAuthStatus\n// ---------------------------------------------------------------------------\n\n/**\n * React hook that returns the current authentication status.\n *\n * Re-renders only when the auth state changes, not on every auth event.\n * Use this for status indicators, route guards, and conditional rendering.\n *\n * Must be used within an {@link AuthProvider}.\n *\n * @returns An AuthStatus object with state, isAuthenticated, and isLoading flags\n *\n * @example\n * ```typescript\n * function AuthGuard({ children }: { children: React.ReactNode }) {\n * const { isAuthenticated, isLoading } = useAuthStatus()\n * if (isLoading) return <Spinner />\n * if (!isAuthenticated) return <Navigate to=\"/login\" />\n * return <>{children}</>\n * }\n * ```\n */\nfunction useAuthStatus(): AuthStatus {\n\tconst { state, isLoading } = useAuthContext()\n\n\treturn {\n\t\tstate,\n\t\tisAuthenticated: state === 'authenticated',\n\t\tisLoading,\n\t}\n}\n\nexport { useAuth, useCurrentUser, useAuthStatus }\nexport type { UseAuthResult, AuthStatus }\n","import {\n\tcreateContext,\n\tuseCallback,\n\tuseContext,\n\tuseEffect,\n\tuseRef,\n\tuseState,\n\tuseSyncExternalStore,\n} from 'react'\nimport type {\n\tClientInvitation,\n\tClientMembership,\n\tClientOrganization,\n\tOrgClient,\n} from '../client/org-client'\n\n// ============================================================================\n// OrgContext\n// ============================================================================\n\n/**\n * Shape of the OrgContext value.\n */\nexport interface OrgContextValue {\n\t/** The OrgClient instance */\n\tclient: OrgClient\n}\n\n/**\n * React context for organization state.\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\n// ============================================================================\n// useOrg\n// ============================================================================\n\n/**\n * Return value of the {@link useOrg} hook.\n */\nexport interface UseOrgResult {\n\t/** Currently active organization, or null */\n\torg: ClientOrganization | null\n\t/** Current user's role in the active organization, or null */\n\trole: string | null\n\t/** Active organization ID, or null */\n\torgId: string | null\n\t/** Switch to a different organization */\n\tswitchOrg: (orgId: string) => Promise<void>\n\t/** Create a new organization */\n\tcreateOrg: (params: { name: string; slug?: string }) => Promise<ClientOrganization>\n\t/** Leave the active organization */\n\tleaveOrg: () => Promise<void>\n\t/** Clear the active organization */\n\tclearOrg: () => void\n\t/** List all organizations the user belongs to */\n\tlistOrgs: () => Promise<ClientOrganization[]>\n\t/** Last error, or null */\n\terror: string | null\n}\n\n/**\n * React hook for organization management and context switching.\n *\n * Re-renders when the active organization changes.\n *\n * @example\n * ```typescript\n * function OrgSwitcher() {\n * const { org, switchOrg, listOrgs, error } = useOrg()\n * const [orgs, setOrgs] = useState<ClientOrganization[]>([])\n *\n * useEffect(() => { listOrgs().then(setOrgs) }, [listOrgs])\n *\n * return (\n * <select value={org?.id ?? ''} onChange={(e) => switchOrg(e.target.value)}>\n * <option value=\"\">Select org...</option>\n * {orgs.map(o => <option key={o.id} value={o.id}>{o.name}</option>)}\n * </select>\n * )\n * }\n * ```\n */\nexport function useOrg(): UseOrgResult {\n\tconst { client } = useOrgContext()\n\tconst [error, setError] = useState<string | null>(null)\n\n\t// Track active org reactively\n\tconst orgSnapshotRef = useRef({\n\t\torgId: client.activeOrgId,\n\t\torg: client.activeOrg,\n\t\trole: client.activeRole,\n\t})\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\treturn client.onOrgChange(() => {\n\t\t\t\torgSnapshotRef.current = {\n\t\t\t\t\torgId: client.activeOrgId,\n\t\t\t\t\torg: client.activeOrg,\n\t\t\t\t\trole: client.activeRole,\n\t\t\t\t}\n\t\t\t\tonStoreChange()\n\t\t\t})\n\t\t},\n\t\t[client],\n\t)\n\n\tconst getSnapshot = useCallback(() => orgSnapshotRef.current, [])\n\n\tconst { orgId, org, role } = useSyncExternalStore(subscribe, getSnapshot)\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\n// ============================================================================\n// useOrgMembers\n// ============================================================================\n\n/**\n * Return value of the {@link useOrgMembers} hook.\n */\nexport interface UseOrgMembersResult {\n\t/** Members of the organization (empty until loaded) */\n\tmembers: ClientMembership[]\n\t/** Whether members are being loaded */\n\tisLoading: boolean\n\t/** Reload the members list */\n\trefresh: () => Promise<void>\n\t/** Invite a user by email */\n\tinvite: (email: string, role: string) => Promise<ClientInvitation>\n\t/** Remove a member */\n\tremoveMember: (userId: string) => Promise<void>\n\t/** Update a member's role */\n\tupdateRole: (userId: string, role: string) => Promise<void>\n\t/** Last error, or null */\n\terror: string | null\n}\n\n/**\n * React hook for managing organization members.\n *\n * Automatically loads members when the orgId changes.\n *\n * @param orgId - Organization ID to manage members for\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\tconst result = await client.listMembers(orgId)\n\t\t\tsetMembers(result)\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\trefresh()\n\t}, [refresh])\n\n\tconst invite = useCallback(\n\t\tasync (email: string, role: string): Promise<ClientInvitation> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\tconst result = await client.inviteMember(orgId, { email, role })\n\t\t\t\treturn result\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, orgId],\n\t)\n\n\tconst removeMember = useCallback(\n\t\tasync (userId: string): Promise<void> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\tawait client.removeMember(orgId, userId)\n\t\t\t\tawait refresh()\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, orgId, refresh],\n\t)\n\n\tconst updateRole = useCallback(\n\t\tasync (userId: string, role: string): Promise<void> => {\n\t\t\tsetError(null)\n\t\t\ttry {\n\t\t\t\tawait client.updateMemberRole(orgId, userId, role)\n\t\t\t\tawait refresh()\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, orgId, refresh],\n\t)\n\n\treturn { members, isLoading, refresh, invite, removeMember, updateRole, error }\n}\n\n// ============================================================================\n// usePermission\n// ============================================================================\n\n/**\n * React hook that checks if the current user has a specific role level\n * in the active organization.\n *\n * @param requiredRole - Minimum role required (uses ROLE_HIERARCHY from org-types)\n * @returns true if the user's role is at least requiredRole\n *\n * @example\n * ```typescript\n * function AdminPanel() {\n * const canManage = usePermission('admin')\n * if (!canManage) return <p>Access denied</p>\n * return <AdminSettings />\n * }\n * ```\n */\nexport function usePermission(requiredRole: string): boolean {\n\tconst { client } = useOrgContext()\n\n\tconst snapshotRef = useRef(checkPermission(client.activeRole, requiredRole))\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\treturn client.onOrgChange(() => {\n\t\t\t\tconst newValue = checkPermission(client.activeRole, requiredRole)\n\t\t\t\tif (newValue !== snapshotRef.current) {\n\t\t\t\t\tsnapshotRef.current = newValue\n\t\t\t\t\tonStoreChange()\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\t\t[client, requiredRole],\n\t)\n\n\tconst getSnapshot = useCallback(() => snapshotRef.current, [])\n\n\treturn useSyncExternalStore(subscribe, getSnapshot)\n}\n\n// Simple role hierarchy check (mirrors ROLE_HIERARCHY from org-types)\nconst ROLE_LEVELS: Record<string, number> = {\n\tviewer: 10,\n\tbilling: 15,\n\tmember: 20,\n\tadmin: 30,\n\towner: 40,\n}\n\nfunction checkPermission(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"],"mappings":"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","names":["useState","useState","createContext","useCallback","useContext","useEffect","useRef","useState","useSyncExternalStore"]}
|