@archlast/client 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +173 -173
- package/dist/admin/index.cjs.map +1 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/auth/index.cjs +53 -2
- package/dist/auth/index.cjs.map +1 -1
- package/dist/auth/index.d.cts +4170 -1
- package/dist/auth/index.d.ts +4170 -1
- package/dist/auth/index.js +49 -1
- package/dist/auth/index.js.map +1 -1
- package/dist/client.cjs +28 -0
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +3 -0
- package/dist/client.d.ts +3 -0
- package/dist/client.js +28 -0
- package/dist/client.js.map +1 -1
- package/dist/function-reference.cjs.map +1 -1
- package/dist/function-reference.js.map +1 -1
- package/dist/index.cjs +79 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +48 -2
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +0 -2
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +3 -0
- package/dist/react.d.ts +3 -0
- package/dist/react.js +0 -2
- package/dist/react.js.map +1 -1
- package/dist/storage/index.cjs.map +1 -1
- package/dist/storage/index.js.map +1 -1
- package/package.json +9 -2
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/auth/index.ts","../src/storage/index.ts","../src/admin/index.ts","../src/client.ts"],"sourcesContent":["/**\n * Client-side auth API wrapper for Archlast.\n *\n * This now uses Better-Auth endpoints via the proxy:\n * - GET /api/auth/get-session\n * - POST /api/auth/sign-up\n * - POST /api/auth/sign-in\n * - POST /api/auth/sign-out\n *\n * Migration from legacy /_auth/* endpoints:\n * - /_auth/state → /api/auth/get-session\n * - /_auth/sign-up → /api/auth/sign-up (email)\n * - /_auth/sign-in → /api/auth/sign-in (email)\n * - /_auth/sign-out → /api/auth/sign-out\n *\n * Notes:\n * - Uses cookie-based sessions by default (credentials: \"include\").\n * - For programmatic access, use Better-Auth API keys (arch_* prefix) via x-api-key header.\n * - Better-Auth supports username, OAuth, magic link, and more.\n */\n\nimport axios, { type AxiosInstance } from \"axios\";\n\nexport type AuthUser = {\n id: string;\n email: string;\n emailVerified: boolean;\n name?: string;\n image?: string;\n createdAt?: Date;\n updatedAt?: Date;\n role?: string;\n banned?: boolean;\n};\n\nexport type AuthSession = {\n token: string;\n expiresAt: Date;\n userId: string;\n ipAddress?: string;\n userAgent?: string;\n};\n\nexport type AuthState = {\n user: AuthUser | null;\n session: AuthSession | null;\n isAuthenticated: boolean;\n};\n\nexport type SignUpInput = {\n email: string;\n password: string;\n name?: string;\n username?: string;\n};\n\nexport type SignInInput = {\n email?: string;\n username?: string;\n password: string;\n};\n\nexport type ArchlastAuthClientOptions = {\n /**\n * Base URL for the Archlast server.\n * Example: \"http://localhost:4000\"\n *\n * If omitted, it will default to:\n * - window.location.origin in the browser\n * - \"\" in non-browser contexts\n */\n baseUrl?: string;\n\n /**\n * App ID for session isolation (e.g. \"web\", \"admin\").\n * When set, adds x-archlast-app-id header.\n */\n appId?: string;\n\n /**\n * Better-Auth API key for authentication.\n * When provided, uses x-api-key header instead of cookies.\n */\n apiKey?: string;\n};\n\nfunction resolveBaseUrl(explicit?: string): string {\n if (explicit && explicit.trim()) return explicit.replace(/\\/+$/, \"\");\n if (typeof window !== \"undefined\" && window.location?.origin) return window.location.origin;\n return \"\";\n}\n\nexport class ArchlastAuthClient {\n private readonly baseUrl: string;\n private readonly axios: AxiosInstance;\n private readonly appId?: string;\n private readonly apiKey?: string;\n\n constructor(options: ArchlastAuthClientOptions = {}) {\n this.baseUrl = resolveBaseUrl(options.baseUrl);\n this.appId = options.appId;\n this.apiKey = options.apiKey;\n this.axios = axios.create({\n baseURL: this.baseUrl,\n withCredentials: !options.apiKey, // Only use cookies if no API key\n headers: {\n \"content-type\": \"application/json\",\n ...(this.appId ? { \"x-archlast-app-id\": this.appId } : {}),\n ...(options.apiKey ? { \"x-api-key\": options.apiKey } : {}),\n },\n });\n }\n\n /**\n * Get current authentication state\n * Uses Better-Auth's getSession endpoint\n */\n async getState(): Promise<AuthState> {\n try {\n const response = await this.axios.get<{\n user: AuthUser | null;\n session: AuthSession | null;\n }>(\"/api/auth/get-session\");\n\n const { user, session } = response.data;\n\n return {\n user,\n session,\n isAuthenticated: !!user,\n };\n } catch (error) {\n // Return unauthenticated state on error\n return {\n user: null,\n session: null,\n isAuthenticated: false,\n };\n }\n }\n\n /**\n * Sign up new user\n * Uses Better-Auth's email signUp endpoint\n */\n async signUp(input: SignUpInput): Promise<AuthState> {\n const response = await this.axios.post<{ user: AuthUser }>(\"/api/auth/sign-up/email\", {\n email: input.email,\n password: input.password,\n name: input.name,\n username: input.username,\n });\n\n return {\n user: response.data.user,\n session: null, // Session is managed via cookies\n isAuthenticated: !!response.data.user,\n };\n }\n\n /**\n * Sign in with email/username and password\n * Uses Better-Auth's credential sign-in endpoint\n */\n async signIn(input: SignInInput): Promise<AuthState> {\n // Support email or username sign-in\n if (!input.email && !input.username) {\n throw new Error(\"Either email or username is required\");\n }\n\n const response = await this.axios.post<{ user: AuthUser }>(\"/api/auth/sign-in/email\", {\n email: input.email,\n username: input.username,\n password: input.password,\n });\n\n return {\n user: response.data.user,\n session: null, // Session is managed via cookies\n isAuthenticated: !!response.data.user,\n };\n }\n\n /**\n * Sign out and revoke session\n * Uses Better-Auth's sign-out endpoint\n */\n async signOut(): Promise<{ success: boolean }> {\n const response = await this.axios.post<{ success: boolean }>(\n \"/api/auth/sign-out\",\n {},\n { withCredentials: true }\n );\n\n return response.data;\n }\n\n /**\n * Request password reset email\n * Uses Better-Auth's password reset flow\n */\n async requestPasswordReset(email: string, callbackURL?: string): Promise<{ success: boolean }> {\n const response = await this.axios.post<{ success: boolean }>(\"/api/auth/forgot-password\", {\n email,\n redirectTo: callbackURL,\n });\n\n return response.data;\n }\n\n /**\n * Reset password with token\n * Uses Better-Auth's reset password endpoint\n */\n async resetPassword(token: string, password: string): Promise<{ success: boolean }> {\n const response = await this.axios.post<{ success: boolean }>(\"/api/auth/reset-password\", {\n token,\n password,\n });\n\n return response.data;\n }\n\n /**\n * Verify email with token\n * Uses Better-Auth's email verification endpoint\n */\n async verifyEmail(token: string): Promise<{ success: boolean; user?: AuthUser }> {\n const response = await this.axios.post<{ success: boolean; user?: AuthUser }>(\"/api/auth/verify-email\", {\n token,\n });\n\n return response.data;\n }\n}\n\n/**\n * Default export for backward compatibility\n */\nexport default ArchlastAuthClient;\n","import axios, { AxiosInstance } from \"axios\";\n\nexport type StorageFile = {\n id: string; // The storage key/path\n url: string; // Public URL\n downloadUrl: string; // Authenticated download URL\n name: string;\n fileName: string | null;\n hash: string;\n refCount: number;\n contentType: string;\n size: number;\n createdAt: number;\n updatedAt: number;\n};\n\nexport type StorageListResponse = {\n items: StorageFile[];\n};\n\nexport type StorageClientOptions = {\n /**\n * Better-Auth API key for authentication\n * When provided, uses x-api-key header instead of cookies\n */\n apiKey?: string;\n};\n\nexport class StorageClient {\n private readonly axios: AxiosInstance;\n\n constructor(baseUrl: string, appId?: string, options?: StorageClientOptions) {\n this.axios = axios.create({\n baseURL: baseUrl,\n withCredentials: !options?.apiKey, // Only use cookies if no API key\n headers: {\n ...(appId ? { \"x-archlast-app-id\": appId } : {}),\n ...(options?.apiKey ? { \"x-api-key\": options.apiKey } : {}),\n },\n });\n }\n\n /**\n * Upload a file\n */\n async upload(\n file: Blob | Uint8Array | ReadableStream | File,\n contentType?: string\n ): Promise<StorageFile> {\n let body: FormData | Blob | Uint8Array | ReadableStream = file;\n let headers: Record<string, string> = {};\n\n if (file instanceof File) {\n const formData = new FormData();\n formData.append(\"file\", file);\n body = formData;\n } else {\n // Raw binary upload\n if (contentType) {\n headers[\"Content-Type\"] = contentType;\n }\n\n // Convert ReadableStream if needed, or pass through if supported by axios/adapter\n // For browser axios, usually Blob/ArrayBuffer/FormData\n if (file instanceof Uint8Array) {\n // wrap in Blob if possible or send directly\n }\n }\n\n const response = await this.axios.post<Partial<StorageFile>>(\n \"/_archlast/storage/upload\",\n body,\n {\n headers,\n }\n );\n\n // Hydrate URLs\n const data = response.data;\n if (!data.id) throw new Error(\"Upload failed: No ID returned\");\n\n return this.hydrate(data as StorageFile);\n }\n\n /**\n * List files\n */\n async list(limit = 20, offset = 0): Promise<StorageListResponse> {\n const response = await this.axios.get<StorageListResponse>(\"/_archlast/storage/list\", {\n params: { limit, offset },\n });\n return {\n items: response.data.items.map((item) => this.hydrate(item)),\n };\n }\n\n /**\n * Get file metadata\n */\n async getMetadata(id: string): Promise<StorageFile> {\n const response = await this.axios.get<StorageFile>(`/_archlast/storage/files/${id}`);\n return this.hydrate(response.data);\n }\n\n /**\n * Generate a presigned download URL\n */\n async presign(id: string, expiresInSeconds: number = 300): Promise<{ url: string }> {\n const response = await this.axios.post<{ url: string }>(\"/_archlast/storage/presign\", {\n id,\n expiresInSeconds,\n });\n return response.data;\n }\n\n /**\n * Delete file\n */\n async delete(id: string): Promise<{ success: boolean }> {\n const response = await this.axios.delete<{ success: boolean }>(\n `/_archlast/storage/files/${id}`\n );\n return response.data;\n }\n\n /**\n * Get public URL for a file\n */\n getPublicUrl(id: string): string {\n const base = this.axios.defaults.baseURL?.replace(/\\/+$/, \"\") || \"\";\n // If base is relative (starts with /), assumes same origin\n return `${base}/_storage/${id}`;\n }\n\n getDownloadUrl(id: string): string {\n // Direct authenticated download endpoint\n const base = this.axios.defaults.baseURL?.replace(/\\/+$/, \"\") || \"\";\n return `${base}/_archlast/storage/files/${id}/download`;\n }\n\n private hydrate(file: Partial<StorageFile>): StorageFile {\n if (!file.id) throw new Error(\"Invalid file object: missing id\");\n return {\n id: file.id,\n name: file.name ?? file.fileName ?? \"Untitled\", // Handle aliasing\n fileName: file.fileName ?? file.name ?? null,\n url: file.url ?? this.getPublicUrl(file.id),\n downloadUrl: file.downloadUrl ?? this.getDownloadUrl(file.id),\n hash: file.hash ?? \"\",\n contentType: file.contentType ?? \"application/octet-stream\",\n size: file.size ?? 0,\n createdAt: file.createdAt ?? Date.now(),\n updatedAt: file.updatedAt ?? Date.now(),\n refCount: file.refCount ?? 1,\n };\n }\n}\n","import axios, { AxiosInstance } from \"axios\";\n\nexport type AdminSession = {\n id: string;\n userId: string;\n createdAt: number;\n lastAccess: number;\n userAgent: string | null;\n ipAddress: string | null;\n current: boolean;\n};\n\nexport type AdminProfile = {\n id: string;\n email: string;\n is_super_admin: boolean;\n created_at: number;\n};\n\nexport type AdminClientOptions = {\n /**\n * Better-Auth API key for authentication\n * When provided, uses x-api-key header instead of cookies\n */\n apiKey?: string;\n};\n\nexport class AdminAuthClient {\n private readonly axios: AxiosInstance;\n\n constructor(baseUrl: string, options?: AdminClientOptions) {\n this.axios = axios.create({\n baseURL: baseUrl,\n withCredentials: !options?.apiKey,\n headers: {\n ...(options?.apiKey ? { \"x-api-key\": options.apiKey } : {}),\n },\n });\n }\n\n async signIn(\n email: string,\n password: string\n ): Promise<{ success: boolean; user: AdminProfile }> {\n const response = await this.axios.post(\"/_archlast/admin/auth/sign-in\", {\n email,\n password,\n });\n return response.data;\n }\n\n async signOut(): Promise<{ success: boolean }> {\n const response = await this.axios.post(\"/_archlast/admin/auth/sign-out\");\n return response.data;\n }\n\n async getProfile(): Promise<{ user: AdminProfile }> {\n const response = await this.axios.get(\"/_archlast/admin/auth/me\");\n return response.data;\n }\n\n async getSessions(): Promise<{ sessions: AdminSession[] }> {\n const response = await this.axios.get(\"/_archlast/admin/auth/sessions\");\n return response.data;\n }\n\n async revokeSession(sessionId: string): Promise<{ success: boolean }> {\n const response = await this.axios.post(\"/_archlast/admin/auth/revoke-session\", {\n sessionId,\n });\n return response.data;\n }\n\n async signOutAll(): Promise<{ success: boolean }> {\n const response = await this.axios.post(\"/_archlast/admin/auth/sign-out-all\");\n return response.data;\n }\n}\n\nexport class AdminClient {\n public auth: AdminAuthClient;\n // Add other admin clients here (users, tenants, etc.)\n\n constructor(baseUrl: string, options?: AdminClientOptions) {\n this.auth = new AdminAuthClient(baseUrl, options);\n }\n}\n","import { ArchlastAuthClient } from \"./auth/index\";\nimport { StorageClient } from \"./storage/index\";\nimport { AdminClient } from \"./admin/index\";\n\nexport interface ArchlastClientOptions {\n autoConnect?: boolean;\n isAdmin?: boolean;\n /**\n * Better-Auth API key for authenticating function calls.\n * Uses the Better-Auth API key plugin (arch_* prefix).\n * This is the recommended authentication method.\n * Can be set via ARCHLAST_API_KEY environment variable.\n */\n apiKey?: string;\n /**\n * Better-Auth session cookies to include with WebSocket connection.\n * This enables Better-Auth authentication for WebSocket connections.\n */\n betterAuthCookies?: Record<string, string>;\n}\n\nexport class ArchlastClient {\n private ws: WebSocket | null = null;\n private url: string;\n private listeners: Map<string, Set<(data: any) => void>> = new Map();\n private subscriptions: Map<string, { name: string; args: any }> = new Map();\n private pendingMutations: Map<\n string,\n { resolve: (data: any) => void; reject: (err: Error) => void; timeout: any }\n > = new Map();\n private messageQueue: string[] = [];\n private isConnected = false;\n private reconnectAttempts = 0;\n private maxReconnectAttempts = 5;\n private reconnectDelay = 1000;\n private reconnectTimeout: any = null;\n private isExplicitlyClosed = false;\n private sessionId: string | null = null;\n\n // Event listeners\n private connectionListeners = new Set<(sessionId: string) => void>();\n private disconnectionListeners = new Set<(reason: string) => void>();\n private errorListeners = new Set<(error: string) => void>();\n\n public readonly auth: ArchlastAuthClient;\n public readonly storage: StorageClient;\n public readonly admin: AdminClient;\n public readonly baseUrl: string;\n private appId?: string;\n private isAdmin: boolean;\n private apiKey?: string;\n private betterAuthCookies?: Record<string, string>;\n\n /**\n * @param url WebSocket URL\n * @param httpUrl Backend HTTP URL (used for WS derivation fallback)\n * @param appId App ID for session isolation\n * @param authUrl Optional same-origin URL for auth requests (to avoid cross-origin cookie issues)\n * @param options Configuration options\n */\n constructor(\n url: string,\n httpUrl?: string,\n appId?: string,\n authUrl?: string,\n options: ArchlastClientOptions = {}\n ) {\n this.url = url;\n this.appId = appId;\n this.isAdmin = options.isAdmin ?? false;\n this.apiKey = options.apiKey;\n this.betterAuthCookies = options.betterAuthCookies;\n\n // authUrl: if provided, use it for auth client (same-origin proxy)\n // Otherwise, derive from httpUrl or WS url\n const derivedHttpUrl = httpUrl !== undefined ? httpUrl : url.replace(/^ws/, \"http\");\n const authBaseUrl = authUrl !== undefined ? authUrl : derivedHttpUrl;\n this.baseUrl = authBaseUrl;\n\n this.auth = new ArchlastAuthClient({ baseUrl: authBaseUrl, appId, apiKey: options.apiKey });\n this.storage = new StorageClient(authBaseUrl, appId, { apiKey: options.apiKey });\n this.admin = new AdminClient(authBaseUrl, { apiKey: options.apiKey });\n\n if (options.autoConnect !== false) {\n this.connect();\n }\n }\n\n /**\n * Update Better-Auth cookies (call this when session changes)\n */\n public setBetterAuthCookies(cookies: Record<string, string>) {\n this.betterAuthCookies = cookies;\n // If already connected, reconnect to send new cookies\n if (this.isConnected) {\n this.connect();\n }\n }\n\n /**\n * Update Better-Auth API key (call this when API key changes)\n */\n public setApiKey(apiKey: string) {\n this.apiKey = apiKey;\n // If already connected, reconnect to send new API key\n if (this.isConnected) {\n this.connect();\n }\n }\n\n public connect() {\n // SSR protection: don't connect on the server\n if (typeof window === \"undefined\") {\n return;\n }\n\n this.isExplicitlyClosed = false;\n\n if (this.ws) {\n if (\n this.ws.readyState === WebSocket.OPEN ||\n this.ws.readyState === WebSocket.CONNECTING\n ) {\n return;\n }\n try {\n this.ws.close();\n } catch (e) {\n // ignore\n }\n this.ws = null;\n }\n\n try {\n this.ws = new WebSocket(this.url);\n } catch (e) {\n this.handleClose();\n return;\n }\n\n this.ws.onopen = async () => {\n console.log(\"Connected to Archlast Server\");\n this.isConnected = true;\n this.reconnectAttempts = 0;\n\n // Build auth headers\n const headers: Record<string, string> = {};\n if (this.appId) {\n headers[\"x-archlast-app-id\"] = this.appId;\n }\n // Better-Auth API key - use x-api-key header\n if (this.apiKey) {\n headers[\"x-api-key\"] = this.apiKey;\n }\n\n // Build cookies object for auth (merge Better-Auth cookies)\n const cookies: Record<string, string> = {};\n if (this.betterAuthCookies) {\n Object.assign(cookies, this.betterAuthCookies);\n }\n\n this.sendMessage({\n type: \"connect\",\n auth: {\n headers: Object.keys(headers).length > 0 ? headers : undefined,\n cookies: Object.keys(cookies).length > 0 ? cookies : undefined,\n },\n });\n\n // Subscribe to logs and admin events\n // For admin dashboard (isAdmin=true), always subscribe since it requires auth\n // For app clients, check authentication state\n if (this.isAdmin) {\n // Admin dashboard - always subscribe to admin events\n this.sendMessage({\n type: \"subscribe_logs\",\n });\n this.sendMessage({\n type: \"subscribe_admin_events\",\n });\n } else {\n // App client - only subscribe if authenticated\n try {\n const state = await this.auth.getState();\n console.log(\"Auth state:\", state);\n if (state.isAuthenticated) {\n this.sendMessage({\n type: \"subscribe_logs\",\n });\n this.sendMessage({\n type: \"subscribe_admin_events\",\n });\n }\n } catch (err) {\n // Ignore auth fetch errors\n }\n }\n\n this.flushQueue();\n this.resubscribeAll();\n this.startHeartbeat();\n };\n\n this.ws.onmessage = (event) => this.handleMessage(event);\n\n this.ws.onclose = () => this.handleClose();\n this.ws.onerror = (err) => {\n // Only log if not explicitly closed (sometimes error fires before close)\n if (!this.isExplicitlyClosed) {\n console.error(\"WebSocket error:\", err);\n this.ws?.close();\n }\n };\n }\n\n private heartbeatInterval: any = null;\n\n private startHeartbeat() {\n this.stopHeartbeat();\n this.heartbeatInterval = setInterval(() => {\n if (this.isConnected) {\n this.sendMessage({ type: \"ping\" });\n }\n }, 30000); // 30 seconds\n }\n\n private stopHeartbeat() {\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = null;\n }\n }\n\n private handleClose() {\n this.isConnected = false;\n this.sessionId = null;\n this.disconnectionListeners.forEach((l) => l(\"Disconnected\"));\n\n if (this.isExplicitlyClosed) return;\n\n if (this.reconnectAttempts < this.maxReconnectAttempts) {\n const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts);\n console.log(`Disconnected. Reconnecting in ${delay}ms...`);\n this.reconnectTimeout = setTimeout(() => {\n this.reconnectAttempts++;\n this.connect();\n }, delay);\n }\n }\n\n private handleMessage(event: MessageEvent) {\n try {\n const msg = JSON.parse(event.data);\n\n if (msg.type === \"data\" || msg.type === \"patch\") {\n const queryId = msg.queryId;\n const data = msg.data || msg.patch; // Handle patch logic if needed\n\n // Notify all listeners (React Query handles caching)\n const listeners = this.listeners.get(queryId);\n if (listeners) {\n listeners.forEach((l) => l(data));\n }\n } else if (msg.type === \"mutationResponse\") {\n const pending = this.pendingMutations.get(msg.mutationId);\n if (pending) {\n clearTimeout(pending.timeout);\n this.pendingMutations.delete(msg.mutationId);\n if (msg.success) {\n pending.resolve(msg.data);\n } else {\n pending.reject(new Error(msg.error));\n }\n }\n } else if (msg.type === \"connected\") {\n console.log(\"Session established:\", msg.sessionId);\n this.sessionId = msg.sessionId;\n this.isConnected = true;\n this.reconnectAttempts = 0;\n this.connectionListeners.forEach((l) => l(msg.sessionId));\n } else if (msg.type === \"error\") {\n console.error(\"Server error:\", msg.message);\n this.errorListeners.forEach((l) => l(msg.message));\n\n if (msg.message === \"Authentication required\") {\n // Fatal auth error - do not reconnect\n this.isExplicitlyClosed = true;\n this.ws?.close();\n }\n }\n } catch (e) {\n console.error(\"Error handling message:\", e);\n }\n }\n\n public getWs() {\n return this.ws;\n }\n\n public onConnected(cb: (sessionId: string) => void) {\n this.connectionListeners.add(cb);\n return () => this.connectionListeners.delete(cb);\n }\n\n public onDisconnected(cb: (reason: string) => void) {\n this.disconnectionListeners.add(cb);\n return () => this.disconnectionListeners.delete(cb);\n }\n\n public onError(cb: (error: string) => void) {\n this.errorListeners.add(cb);\n return () => this.errorListeners.delete(cb);\n }\n\n public getStatus() {\n return this.isConnected ? \"connected\" : \"disconnected\";\n }\n\n public getSessionId() {\n return this.sessionId;\n }\n\n private sendMessage(msg: any) {\n const data = JSON.stringify(msg);\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.send(data);\n } else {\n this.messageQueue.push(data);\n }\n }\n\n private flushQueue() {\n while (this.messageQueue.length > 0) {\n const msg = this.messageQueue.shift();\n if (msg) this.ws?.send(msg);\n }\n }\n\n private resubscribeAll() {\n for (const [queryId, sub] of Array.from(this.subscriptions.entries())) {\n this.sendMessage({\n type: \"query\",\n queryId,\n name: sub.name,\n args: sub.args,\n });\n }\n }\n\n private getQueryId(name: string, args: any) {\n // Sort keys to ensure stable ID\n const stableArgs = JSON.stringify(args, Object.keys(args || {}).sort());\n return `${name}:${stableArgs}`;\n }\n\n subscribe(queryName: string, args: any, onUpdate: (data: any) => void): () => void {\n const queryId = this.getQueryId(queryName, args);\n\n if (!this.listeners.has(queryId)) {\n this.listeners.set(queryId, new Set());\n this.subscriptions.set(queryId, { name: queryName, args });\n // Send subscribe message\n this.sendMessage({\n type: \"query\",\n queryId,\n name: queryName,\n args,\n });\n }\n\n this.listeners.get(queryId)!.add(onUpdate);\n\n return () => {\n const set = this.listeners.get(queryId);\n if (set) {\n set.delete(onUpdate);\n if (set.size === 0) {\n this.listeners.delete(queryId);\n this.subscriptions.delete(queryId);\n // Send unsubscribe message (not implemented in server yet)\n }\n }\n };\n }\n\n async fetch(name: string, args: any): Promise<any> {\n const queryId = this.getQueryId(name, args);\n\n return new Promise((resolve, reject) => {\n let resolved = false;\n const unsubscribe = this.subscribe(name, args, (data) => {\n if (!resolved) {\n resolved = true;\n unsubscribe();\n resolve(data);\n }\n });\n\n setTimeout(() => {\n if (!resolved) {\n resolved = true;\n unsubscribe();\n reject(new Error(\"Timeout waiting for data\"));\n }\n }, 5000);\n });\n }\n\n async mutate(name: string, args: any): Promise<any> {\n return new Promise((resolve, reject) => {\n const mutationId = Math.random().toString(36).slice(2);\n\n const timeout = setTimeout(() => {\n this.pendingMutations.delete(mutationId);\n reject(new Error(\"Mutation timeout\"));\n }, 10000);\n\n this.pendingMutations.set(mutationId, { resolve, reject, timeout });\n\n this.sendMessage({\n type: \"mutation\",\n mutationId,\n name,\n args,\n });\n });\n }\n\n close() {\n this.isExplicitlyClosed = true;\n if (this.reconnectTimeout) {\n clearTimeout(this.reconnectTimeout);\n this.reconnectTimeout = null;\n }\n\n if (this.ws) {\n // Prevent handlers from firing during closure\n this.ws.onclose = null;\n this.ws.onopen = null;\n this.ws.onerror = null;\n this.ws.onmessage = null;\n\n this.ws.close();\n this.ws = null;\n }\n this.isConnected = false;\n this.stopHeartbeat();\n }\n}\n"],"mappings":"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","names":["axios","axios","axios","axios"]}
|
|
1
|
+
{"version":3,"sources":["../src/auth/index.ts","../src/auth/better-auth.ts","../src/storage/index.ts","../src/admin/index.ts","../src/client.ts"],"sourcesContent":["/**\r\n * Client-side auth API wrapper for Archlast.\r\n *\r\n * This now uses Better-Auth endpoints via the proxy:\r\n * - GET /api/auth/get-session\r\n * - POST /api/auth/sign-up\r\n * - POST /api/auth/sign-in\r\n * - POST /api/auth/sign-out\r\n *\r\n * Migration from legacy /_auth/* endpoints:\r\n * - /_auth/state → /api/auth/get-session\r\n * - /_auth/sign-up → /api/auth/sign-up (email)\r\n * - /_auth/sign-in → /api/auth/sign-in (email)\r\n * - /_auth/sign-out → /api/auth/sign-out\r\n *\r\n * Notes:\r\n * - Uses cookie-based sessions by default (credentials: \"include\").\r\n * - For programmatic access, use Better-Auth API keys (arch_* prefix) via x-api-key header.\r\n * - Better-Auth supports username, OAuth, magic link, and more.\r\n */\r\n\r\nimport axios, { type AxiosInstance } from \"axios\";\r\n\r\nexport type AuthUser = {\r\n id: string;\r\n email: string;\r\n emailVerified: boolean;\r\n name?: string;\r\n image?: string;\r\n createdAt?: Date;\r\n updatedAt?: Date;\r\n role?: string;\r\n banned?: boolean;\r\n};\r\n\r\nexport type AuthSession = {\r\n token: string;\r\n expiresAt: Date;\r\n userId: string;\r\n ipAddress?: string;\r\n userAgent?: string;\r\n};\r\n\r\nexport type AuthState = {\r\n user: AuthUser | null;\r\n session: AuthSession | null;\r\n isAuthenticated: boolean;\r\n};\r\n\r\nexport type SignUpInput = {\r\n email: string;\r\n password: string;\r\n name?: string;\r\n username?: string;\r\n};\r\n\r\nexport type SignInInput = {\r\n email?: string;\r\n username?: string;\r\n password: string;\r\n};\r\n\r\nexport type ArchlastAuthClientOptions = {\r\n /**\r\n * Base URL for the Archlast server.\r\n * Example: \"http://localhost:4000\"\r\n *\r\n * If omitted, it will default to:\r\n * - window.location.origin in the browser\r\n * - \"\" in non-browser contexts\r\n */\r\n baseUrl?: string;\r\n\r\n /**\r\n * App ID for session isolation (e.g. \"web\", \"admin\").\r\n * When set, adds x-archlast-app-id header.\r\n */\r\n appId?: string;\r\n\r\n /**\r\n * Better-Auth API key for authentication.\r\n * When provided, uses x-api-key header instead of cookies.\r\n */\r\n apiKey?: string;\r\n};\r\n\r\nfunction resolveBaseUrl(explicit?: string): string {\r\n if (explicit && explicit.trim()) return explicit.replace(/\\/+$/, \"\");\r\n if (typeof window !== \"undefined\" && window.location?.origin) return window.location.origin;\r\n return \"\";\r\n}\r\n\r\nexport class ArchlastAuthClient {\r\n private readonly baseUrl: string;\r\n private readonly axios: AxiosInstance;\r\n private readonly appId?: string;\r\n private readonly apiKey?: string;\r\n\r\n constructor(options: ArchlastAuthClientOptions = {}) {\r\n this.baseUrl = resolveBaseUrl(options.baseUrl);\r\n this.appId = options.appId;\r\n this.apiKey = options.apiKey;\r\n this.axios = axios.create({\r\n baseURL: this.baseUrl,\r\n withCredentials: !options.apiKey, // Only use cookies if no API key\r\n headers: {\r\n \"content-type\": \"application/json\",\r\n ...(this.appId ? { \"x-archlast-app-id\": this.appId } : {}),\r\n ...(options.apiKey ? { \"x-api-key\": options.apiKey } : {}),\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * Get current authentication state\r\n * Uses Better-Auth's getSession endpoint\r\n */\r\n async getState(): Promise<AuthState> {\r\n try {\r\n const response = await this.axios.get<{\r\n user: AuthUser | null;\r\n session: AuthSession | null;\r\n }>(\"/api/auth/get-session\");\r\n\r\n const { user, session } = response.data;\r\n\r\n return {\r\n user,\r\n session,\r\n isAuthenticated: !!user,\r\n };\r\n } catch (error) {\r\n // Return unauthenticated state on error\r\n return {\r\n user: null,\r\n session: null,\r\n isAuthenticated: false,\r\n };\r\n }\r\n }\r\n\r\n /**\r\n * Sign up new user\r\n * Uses Better-Auth's email signUp endpoint\r\n */\r\n async signUp(input: SignUpInput): Promise<AuthState> {\r\n const response = await this.axios.post<{ user: AuthUser }>(\"/api/auth/sign-up/email\", {\r\n email: input.email,\r\n password: input.password,\r\n name: input.name,\r\n username: input.username,\r\n });\r\n\r\n return {\r\n user: response.data.user,\r\n session: null, // Session is managed via cookies\r\n isAuthenticated: !!response.data.user,\r\n };\r\n }\r\n\r\n /**\r\n * Sign in with email/username and password\r\n * Uses Better-Auth's credential sign-in endpoint\r\n */\r\n async signIn(input: SignInInput): Promise<AuthState> {\r\n // Support email or username sign-in\r\n if (!input.email && !input.username) {\r\n throw new Error(\"Either email or username is required\");\r\n }\r\n\r\n const response = await this.axios.post<{ user: AuthUser }>(\"/api/auth/sign-in/email\", {\r\n email: input.email,\r\n username: input.username,\r\n password: input.password,\r\n });\r\n\r\n return {\r\n user: response.data.user,\r\n session: null, // Session is managed via cookies\r\n isAuthenticated: !!response.data.user,\r\n };\r\n }\r\n\r\n /**\r\n * Sign out and revoke session\r\n * Uses Better-Auth's sign-out endpoint\r\n */\r\n async signOut(): Promise<{ success: boolean }> {\r\n const response = await this.axios.post<{ success: boolean }>(\r\n \"/api/auth/sign-out\",\r\n {},\r\n { withCredentials: true }\r\n );\r\n\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Request password reset email\r\n * Uses Better-Auth's password reset flow\r\n */\r\n async requestPasswordReset(email: string, callbackURL?: string): Promise<{ success: boolean }> {\r\n const response = await this.axios.post<{ success: boolean }>(\"/api/auth/forgot-password\", {\r\n email,\r\n redirectTo: callbackURL,\r\n });\r\n\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Reset password with token\r\n * Uses Better-Auth's reset password endpoint\r\n */\r\n async resetPassword(token: string, password: string): Promise<{ success: boolean }> {\r\n const response = await this.axios.post<{ success: boolean }>(\"/api/auth/reset-password\", {\r\n token,\r\n password,\r\n });\r\n\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Verify email with token\r\n * Uses Better-Auth's email verification endpoint\r\n */\r\n async verifyEmail(token: string): Promise<{ success: boolean; user?: AuthUser }> {\r\n const response = await this.axios.post<{ success: boolean; user?: AuthUser }>(\"/api/auth/verify-email\", {\r\n token,\r\n });\r\n\r\n return response.data;\r\n }\r\n}\r\n\r\n/**\r\n * Default export for backward compatibility\r\n */\r\nexport default ArchlastAuthClient;\r\n\r\n/**\r\n * Better-Auth wrapper exports\r\n *\r\n * These provide direct access to Better-Auth client for advanced usage.\r\n * Most users should use the hooks from @archlast/client/react instead.\r\n *\r\n * @example\r\n * ```ts\r\n * import { betterAuthClient, useBetterAuthSession } from \"@archlast/client/auth\";\r\n *\r\n * // In React component\r\n * const { data: session } = useBetterAuthSession();\r\n *\r\n * // Anywhere\r\n * await betterAuthClient.signIn.email({ email, password });\r\n * ```\r\n */\r\nexport {\r\n authClient as betterAuthClient,\r\n useSession as useBetterAuthSession,\r\n createArchlastAuthClient,\r\n} from \"./better-auth.js\";\r\n\r\n","/**\n * Better-Auth wrapper for Archlast React client\n *\n * This module wraps Better-Auth and re-exports it under the @archlast/client namespace.\n * End-users should NOT need to install better-auth directly.\n */\n\nimport { createAuthClient } from \"better-auth/react\";\nimport { adminClient, organizationClient, usernameClient } from \"better-auth/client/plugins\";\n\n/**\n * Get the Better-Auth base URL from environment or construct from server URL\n */\nfunction getBetterAuthBaseURL(): string {\n // Try environment variable first\n const envURL = process.env.NEXT_PUBLIC_BETTER_AUTH_URL ||\n process.env.NEXT_PUBLIC_ARCHLAST_HTTP_URL ||\n process.env.ARCHLAST_HTTP_URL;\n\n if (envURL) {\n return `${envURL}/api/auth`;\n }\n\n // Fallback to localhost\n return \"http://localhost:4000/api/auth\";\n}\n\n/**\n * Create a Better-Auth client configured for Archlast\n *\n * This is the main export - users import this from @archlast/client/auth\n *\n * @example\n * ```ts\n * import { authClient, useSession } from \"@archlast/client/auth\";\n *\n * // In component\n * export default function Profile() {\n * const { data: session } = useSession();\n * return <div>Welcome {session?.user?.name}</div>;\n * }\n *\n * // Anywhere\n * await authClient.signIn.email({ email, password });\n * ```\n */\nexport const authClient = createAuthClient({\n baseURL: getBetterAuthBaseURL(),\n fetchOptions: {\n credentials: \"include\", // Required for cookies\n },\n plugins: [\n // Admin plugin - user management, roles, bans\n adminClient(),\n\n // Organization plugin - multi-tenancy\n organizationClient(),\n\n // Username plugin - username-based sign-in\n usernameClient(),\n ],\n});\n\n/**\n * Type-safe session hook\n *\n * @example\n * ```tsx\n * import { useSession } from \"@archlast/client/auth\";\n *\n * function MyComponent() {\n * const { data: session, isPending } = useSession();\n * if (isPending) return <div>Loading...</div>;\n * if (!session) return <div>Not authenticated</div>;\n * return <div>Hello {session.user.name}</div>;\n * }\n * ```\n */\nexport function useSession() {\n return authClient.useSession();\n}\n\n/**\n * Re-export Better-Auth types for convenience\n */\nexport type { Session, User } from \"better-auth\";\n\n/**\n * Re-export createAuthClient for advanced use cases\n *\n * Most users should use the default `authClient` export, but if you need\n * a custom configuration (e.g., different base URL), you can create a new client:\n *\n * @example\n * ```ts\n * import { createArchlastAuthClient } from \"@archlast/client/auth\";\n *\n * const customAuth = createArchlastAuthClient({\n * baseURL: \"https://api.example.com/api/auth\",\n * });\n * ```\n */\nexport function createArchlastAuthClient(options: {\n baseURL?: string;\n fetchOptions?: RequestInit;\n}) {\n return createAuthClient({\n baseURL: options.baseURL || getBetterAuthBaseURL(),\n fetchOptions: {\n credentials: \"include\",\n ...options.fetchOptions,\n },\n plugins: [\n adminClient(),\n organizationClient(),\n usernameClient(),\n ],\n });\n}\n\n/**\n * Default export for backward compatibility\n */\nexport default authClient;\n","import axios, { AxiosInstance } from \"axios\";\r\n\r\nexport type StorageFile = {\r\n id: string; // The storage key/path\r\n url: string; // Public URL\r\n downloadUrl: string; // Authenticated download URL\r\n name: string;\r\n fileName: string | null;\r\n hash: string;\r\n refCount: number;\r\n contentType: string;\r\n size: number;\r\n createdAt: number;\r\n updatedAt: number;\r\n};\r\n\r\nexport type StorageListResponse = {\r\n items: StorageFile[];\r\n};\r\n\r\nexport type StorageClientOptions = {\r\n /**\r\n * Better-Auth API key for authentication\r\n * When provided, uses x-api-key header instead of cookies\r\n */\r\n apiKey?: string;\r\n};\r\n\r\nexport class StorageClient {\r\n private readonly axios: AxiosInstance;\r\n\r\n constructor(baseUrl: string, appId?: string, options?: StorageClientOptions) {\r\n this.axios = axios.create({\r\n baseURL: baseUrl,\r\n withCredentials: !options?.apiKey, // Only use cookies if no API key\r\n headers: {\r\n ...(appId ? { \"x-archlast-app-id\": appId } : {}),\r\n ...(options?.apiKey ? { \"x-api-key\": options.apiKey } : {}),\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * Upload a file\r\n */\r\n async upload(\r\n file: Blob | Uint8Array | ReadableStream | File,\r\n contentType?: string\r\n ): Promise<StorageFile> {\r\n let body: FormData | Blob | Uint8Array | ReadableStream = file;\r\n let headers: Record<string, string> = {};\r\n\r\n if (file instanceof File) {\r\n const formData = new FormData();\r\n formData.append(\"file\", file);\r\n body = formData;\r\n } else {\r\n // Raw binary upload\r\n if (contentType) {\r\n headers[\"Content-Type\"] = contentType;\r\n }\r\n\r\n // Convert ReadableStream if needed, or pass through if supported by axios/adapter\r\n // For browser axios, usually Blob/ArrayBuffer/FormData\r\n if (file instanceof Uint8Array) {\r\n // wrap in Blob if possible or send directly\r\n }\r\n }\r\n\r\n const response = await this.axios.post<Partial<StorageFile>>(\r\n \"/_archlast/storage/upload\",\r\n body,\r\n {\r\n headers,\r\n }\r\n );\r\n\r\n // Hydrate URLs\r\n const data = response.data;\r\n if (!data.id) throw new Error(\"Upload failed: No ID returned\");\r\n\r\n return this.hydrate(data as StorageFile);\r\n }\r\n\r\n /**\r\n * List files\r\n */\r\n async list(limit = 20, offset = 0): Promise<StorageListResponse> {\r\n const response = await this.axios.get<StorageListResponse>(\"/_archlast/storage/list\", {\r\n params: { limit, offset },\r\n });\r\n return {\r\n items: response.data.items.map((item) => this.hydrate(item)),\r\n };\r\n }\r\n\r\n /**\r\n * Get file metadata\r\n */\r\n async getMetadata(id: string): Promise<StorageFile> {\r\n const response = await this.axios.get<StorageFile>(`/_archlast/storage/files/${id}`);\r\n return this.hydrate(response.data);\r\n }\r\n\r\n /**\r\n * Generate a presigned download URL\r\n */\r\n async presign(id: string, expiresInSeconds: number = 300): Promise<{ url: string }> {\r\n const response = await this.axios.post<{ url: string }>(\"/_archlast/storage/presign\", {\r\n id,\r\n expiresInSeconds,\r\n });\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Delete file\r\n */\r\n async delete(id: string): Promise<{ success: boolean }> {\r\n const response = await this.axios.delete<{ success: boolean }>(\r\n `/_archlast/storage/files/${id}`\r\n );\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get public URL for a file\r\n */\r\n getPublicUrl(id: string): string {\r\n const base = this.axios.defaults.baseURL?.replace(/\\/+$/, \"\") || \"\";\r\n // If base is relative (starts with /), assumes same origin\r\n return `${base}/_storage/${id}`;\r\n }\r\n\r\n getDownloadUrl(id: string): string {\r\n // Direct authenticated download endpoint\r\n const base = this.axios.defaults.baseURL?.replace(/\\/+$/, \"\") || \"\";\r\n return `${base}/_archlast/storage/files/${id}/download`;\r\n }\r\n\r\n private hydrate(file: Partial<StorageFile>): StorageFile {\r\n if (!file.id) throw new Error(\"Invalid file object: missing id\");\r\n return {\r\n id: file.id,\r\n name: file.name ?? file.fileName ?? \"Untitled\", // Handle aliasing\r\n fileName: file.fileName ?? file.name ?? null,\r\n url: file.url ?? this.getPublicUrl(file.id),\r\n downloadUrl: file.downloadUrl ?? this.getDownloadUrl(file.id),\r\n hash: file.hash ?? \"\",\r\n contentType: file.contentType ?? \"application/octet-stream\",\r\n size: file.size ?? 0,\r\n createdAt: file.createdAt ?? Date.now(),\r\n updatedAt: file.updatedAt ?? Date.now(),\r\n refCount: file.refCount ?? 1,\r\n };\r\n }\r\n}\r\n","import axios, { AxiosInstance } from \"axios\";\r\n\r\nexport type AdminSession = {\r\n id: string;\r\n userId: string;\r\n createdAt: number;\r\n lastAccess: number;\r\n userAgent: string | null;\r\n ipAddress: string | null;\r\n current: boolean;\r\n};\r\n\r\nexport type AdminProfile = {\r\n id: string;\r\n email: string;\r\n is_super_admin: boolean;\r\n created_at: number;\r\n};\r\n\r\nexport type AdminClientOptions = {\r\n /**\r\n * Better-Auth API key for authentication\r\n * When provided, uses x-api-key header instead of cookies\r\n */\r\n apiKey?: string;\r\n};\r\n\r\nexport class AdminAuthClient {\r\n private readonly axios: AxiosInstance;\r\n\r\n constructor(baseUrl: string, options?: AdminClientOptions) {\r\n this.axios = axios.create({\r\n baseURL: baseUrl,\r\n withCredentials: !options?.apiKey,\r\n headers: {\r\n ...(options?.apiKey ? { \"x-api-key\": options.apiKey } : {}),\r\n },\r\n });\r\n }\r\n\r\n async signIn(\r\n email: string,\r\n password: string\r\n ): Promise<{ success: boolean; user: AdminProfile }> {\r\n const response = await this.axios.post(\"/_archlast/admin/auth/sign-in\", {\r\n email,\r\n password,\r\n });\r\n return response.data;\r\n }\r\n\r\n async signOut(): Promise<{ success: boolean }> {\r\n const response = await this.axios.post(\"/_archlast/admin/auth/sign-out\");\r\n return response.data;\r\n }\r\n\r\n async getProfile(): Promise<{ user: AdminProfile }> {\r\n const response = await this.axios.get(\"/_archlast/admin/auth/me\");\r\n return response.data;\r\n }\r\n\r\n async getSessions(): Promise<{ sessions: AdminSession[] }> {\r\n const response = await this.axios.get(\"/_archlast/admin/auth/sessions\");\r\n return response.data;\r\n }\r\n\r\n async revokeSession(sessionId: string): Promise<{ success: boolean }> {\r\n const response = await this.axios.post(\"/_archlast/admin/auth/revoke-session\", {\r\n sessionId,\r\n });\r\n return response.data;\r\n }\r\n\r\n async signOutAll(): Promise<{ success: boolean }> {\r\n const response = await this.axios.post(\"/_archlast/admin/auth/sign-out-all\");\r\n return response.data;\r\n }\r\n}\r\n\r\nexport class AdminClient {\r\n public auth: AdminAuthClient;\r\n // Add other admin clients here (users, tenants, etc.)\r\n\r\n constructor(baseUrl: string, options?: AdminClientOptions) {\r\n this.auth = new AdminAuthClient(baseUrl, options);\r\n }\r\n}\r\n","import { ArchlastAuthClient } from \"./auth/index\";\r\nimport { StorageClient } from \"./storage/index\";\r\nimport { AdminClient } from \"./admin/index\";\r\n\r\nexport interface ArchlastClientOptions {\r\n autoConnect?: boolean;\r\n isAdmin?: boolean;\r\n /**\r\n * Better-Auth API key for authenticating function calls.\r\n * Uses the Better-Auth API key plugin (arch_* prefix).\r\n * This is the recommended authentication method.\r\n * Can be set via ARCHLAST_API_KEY environment variable.\r\n */\r\n apiKey?: string;\r\n /**\r\n * Better-Auth session cookies to include with WebSocket connection.\r\n * This enables Better-Auth authentication for WebSocket connections.\r\n */\r\n betterAuthCookies?: Record<string, string>;\r\n}\r\n\r\nexport class ArchlastClient {\r\n private ws: WebSocket | null = null;\r\n private url: string;\r\n private listeners: Map<string, Set<(data: any) => void>> = new Map();\r\n private subscriptions: Map<string, { name: string; args: any }> = new Map();\r\n private pendingMutations: Map<\r\n string,\r\n { resolve: (data: any) => void; reject: (err: Error) => void; timeout: any }\r\n > = new Map();\r\n private messageQueue: string[] = [];\r\n private isConnected = false;\r\n private reconnectAttempts = 0;\r\n private maxReconnectAttempts = 5;\r\n private reconnectDelay = 1000;\r\n private reconnectTimeout: any = null;\r\n private isExplicitlyClosed = false;\r\n private sessionId: string | null = null;\r\n\r\n // Event listeners\r\n private connectionListeners = new Set<(sessionId: string) => void>();\r\n private disconnectionListeners = new Set<(reason: string) => void>();\r\n private errorListeners = new Set<(error: string) => void>();\r\n\r\n public readonly auth: ArchlastAuthClient;\r\n public readonly storage: StorageClient;\r\n public readonly admin: AdminClient;\r\n public readonly baseUrl: string;\r\n private appId?: string;\r\n private isAdmin: boolean;\r\n private apiKey?: string;\r\n private betterAuthCookies?: Record<string, string>;\r\n\r\n /**\r\n * @param url WebSocket URL\r\n * @param httpUrl Backend HTTP URL (used for WS derivation fallback)\r\n * @param appId App ID for session isolation\r\n * @param authUrl Optional same-origin URL for auth requests (to avoid cross-origin cookie issues)\r\n * @param options Configuration options\r\n */\r\n constructor(\r\n url: string,\r\n httpUrl?: string,\r\n appId?: string,\r\n authUrl?: string,\r\n options: ArchlastClientOptions = {}\r\n ) {\r\n this.url = url;\r\n this.appId = appId;\r\n this.isAdmin = options.isAdmin ?? false;\r\n this.apiKey = options.apiKey;\r\n this.betterAuthCookies = options.betterAuthCookies;\r\n\r\n // authUrl: if provided, use it for auth client (same-origin proxy)\r\n // Otherwise, derive from httpUrl or WS url\r\n const derivedHttpUrl = httpUrl !== undefined ? httpUrl : url.replace(/^ws/, \"http\");\r\n const authBaseUrl = authUrl !== undefined ? authUrl : derivedHttpUrl;\r\n this.baseUrl = authBaseUrl;\r\n\r\n this.auth = new ArchlastAuthClient({ baseUrl: authBaseUrl, appId, apiKey: options.apiKey });\r\n this.storage = new StorageClient(authBaseUrl, appId, { apiKey: options.apiKey });\r\n this.admin = new AdminClient(authBaseUrl, { apiKey: options.apiKey });\r\n\r\n if (options.autoConnect !== false) {\r\n this.connect();\r\n }\r\n }\r\n\r\n /**\r\n * Update Better-Auth cookies (call this when session changes)\r\n */\r\n public setBetterAuthCookies(cookies: Record<string, string>) {\r\n this.betterAuthCookies = cookies;\r\n // If already connected, reconnect to send new cookies\r\n if (this.isConnected) {\r\n this.connect();\r\n }\r\n }\r\n\r\n /**\r\n * Update Better-Auth API key (call this when API key changes)\r\n */\r\n public setApiKey(apiKey: string) {\r\n this.apiKey = apiKey;\r\n // If already connected, reconnect to send new API key\r\n if (this.isConnected) {\r\n this.connect();\r\n }\r\n }\r\n\r\n public connect() {\r\n // SSR protection: don't connect on the server\r\n if (typeof window === \"undefined\") {\r\n return;\r\n }\r\n\r\n this.isExplicitlyClosed = false;\r\n\r\n if (this.ws) {\r\n if (\r\n this.ws.readyState === WebSocket.OPEN ||\r\n this.ws.readyState === WebSocket.CONNECTING\r\n ) {\r\n return;\r\n }\r\n try {\r\n this.ws.close();\r\n } catch (e) {\r\n // ignore\r\n }\r\n this.ws = null;\r\n }\r\n\r\n try {\r\n this.ws = new WebSocket(this.url);\r\n } catch (e) {\r\n this.handleClose();\r\n return;\r\n }\r\n\r\n this.ws.onopen = async () => {\r\n console.log(\"Connected to Archlast Server\");\r\n this.isConnected = true;\r\n this.reconnectAttempts = 0;\r\n\r\n // Build auth headers\r\n const headers: Record<string, string> = {};\r\n if (this.appId) {\r\n headers[\"x-archlast-app-id\"] = this.appId;\r\n }\r\n // Better-Auth API key - use x-api-key header\r\n if (this.apiKey) {\r\n headers[\"x-api-key\"] = this.apiKey;\r\n }\r\n\r\n // Build cookies object for auth (merge Better-Auth cookies)\r\n const cookies: Record<string, string> = {};\r\n if (this.betterAuthCookies) {\r\n Object.assign(cookies, this.betterAuthCookies);\r\n }\r\n\r\n this.sendMessage({\r\n type: \"connect\",\r\n auth: {\r\n headers: Object.keys(headers).length > 0 ? headers : undefined,\r\n cookies: Object.keys(cookies).length > 0 ? cookies : undefined,\r\n },\r\n });\r\n\r\n // Subscribe to logs and admin events\r\n // For admin dashboard (isAdmin=true), always subscribe since it requires auth\r\n // For app clients, check authentication state\r\n if (this.isAdmin) {\r\n // Admin dashboard - always subscribe to admin events\r\n this.sendMessage({\r\n type: \"subscribe_logs\",\r\n });\r\n this.sendMessage({\r\n type: \"subscribe_admin_events\",\r\n });\r\n } else {\r\n // App client - only subscribe if authenticated\r\n try {\r\n const state = await this.auth.getState();\r\n console.log(\"Auth state:\", state);\r\n if (state.isAuthenticated) {\r\n this.sendMessage({\r\n type: \"subscribe_logs\",\r\n });\r\n this.sendMessage({\r\n type: \"subscribe_admin_events\",\r\n });\r\n }\r\n } catch (err) {\r\n // Ignore auth fetch errors\r\n }\r\n }\r\n\r\n this.flushQueue();\r\n this.resubscribeAll();\r\n this.startHeartbeat();\r\n };\r\n\r\n this.ws.onmessage = (event) => this.handleMessage(event);\r\n\r\n this.ws.onclose = () => this.handleClose();\r\n this.ws.onerror = (err) => {\r\n // Only log if not explicitly closed (sometimes error fires before close)\r\n if (!this.isExplicitlyClosed) {\r\n console.error(\"WebSocket error:\", err);\r\n this.ws?.close();\r\n }\r\n };\r\n }\r\n\r\n private heartbeatInterval: any = null;\r\n\r\n private startHeartbeat() {\r\n this.stopHeartbeat();\r\n this.heartbeatInterval = setInterval(() => {\r\n if (this.isConnected) {\r\n this.sendMessage({ type: \"ping\" });\r\n }\r\n }, 30000); // 30 seconds\r\n }\r\n\r\n private stopHeartbeat() {\r\n if (this.heartbeatInterval) {\r\n clearInterval(this.heartbeatInterval);\r\n this.heartbeatInterval = null;\r\n }\r\n }\r\n\r\n private handleClose() {\r\n this.isConnected = false;\r\n this.sessionId = null;\r\n this.disconnectionListeners.forEach((l) => l(\"Disconnected\"));\r\n\r\n if (this.isExplicitlyClosed) return;\r\n\r\n if (this.reconnectAttempts < this.maxReconnectAttempts) {\r\n const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts);\r\n console.log(`Disconnected. Reconnecting in ${delay}ms...`);\r\n this.reconnectTimeout = setTimeout(() => {\r\n this.reconnectAttempts++;\r\n this.connect();\r\n }, delay);\r\n }\r\n }\r\n\r\n private handleMessage(event: MessageEvent) {\r\n try {\r\n const msg = JSON.parse(event.data);\r\n\r\n if (msg.type === \"data\" || msg.type === \"patch\") {\r\n const queryId = msg.queryId;\r\n const data = msg.data || msg.patch; // Handle patch logic if needed\r\n\r\n // Notify all listeners (React Query handles caching)\r\n const listeners = this.listeners.get(queryId);\r\n if (listeners) {\r\n listeners.forEach((l) => l(data));\r\n }\r\n } else if (msg.type === \"mutationResponse\") {\r\n const pending = this.pendingMutations.get(msg.mutationId);\r\n if (pending) {\r\n clearTimeout(pending.timeout);\r\n this.pendingMutations.delete(msg.mutationId);\r\n if (msg.success) {\r\n pending.resolve(msg.data);\r\n } else {\r\n pending.reject(new Error(msg.error));\r\n }\r\n }\r\n } else if (msg.type === \"connected\") {\r\n console.log(\"Session established:\", msg.sessionId);\r\n this.sessionId = msg.sessionId;\r\n this.isConnected = true;\r\n this.reconnectAttempts = 0;\r\n this.connectionListeners.forEach((l) => l(msg.sessionId));\r\n } else if (msg.type === \"error\") {\r\n console.error(\"Server error:\", msg.message);\r\n this.errorListeners.forEach((l) => l(msg.message));\r\n\r\n if (msg.message === \"Authentication required\") {\r\n // Fatal auth error - do not reconnect\r\n this.isExplicitlyClosed = true;\r\n this.ws?.close();\r\n }\r\n }\r\n } catch (e) {\r\n console.error(\"Error handling message:\", e);\r\n }\r\n }\r\n\r\n public getWs() {\r\n return this.ws;\r\n }\r\n\r\n public onConnected(cb: (sessionId: string) => void) {\r\n this.connectionListeners.add(cb);\r\n return () => this.connectionListeners.delete(cb);\r\n }\r\n\r\n public onDisconnected(cb: (reason: string) => void) {\r\n this.disconnectionListeners.add(cb);\r\n return () => this.disconnectionListeners.delete(cb);\r\n }\r\n\r\n public onError(cb: (error: string) => void) {\r\n this.errorListeners.add(cb);\r\n return () => this.errorListeners.delete(cb);\r\n }\r\n\r\n public getStatus() {\r\n return this.isConnected ? \"connected\" : \"disconnected\";\r\n }\r\n\r\n public getSessionId() {\r\n return this.sessionId;\r\n }\r\n\r\n private sendMessage(msg: any) {\r\n const data = JSON.stringify(msg);\r\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\r\n this.ws.send(data);\r\n } else {\r\n this.messageQueue.push(data);\r\n }\r\n }\r\n\r\n private flushQueue() {\r\n while (this.messageQueue.length > 0) {\r\n const msg = this.messageQueue.shift();\r\n if (msg) this.ws?.send(msg);\r\n }\r\n }\r\n\r\n private resubscribeAll() {\r\n for (const [queryId, sub] of Array.from(this.subscriptions.entries())) {\r\n this.sendMessage({\r\n type: \"query\",\r\n queryId,\r\n name: sub.name,\r\n args: sub.args,\r\n });\r\n }\r\n }\r\n\r\n private getQueryId(name: string, args: any) {\r\n // Sort keys to ensure stable ID\r\n const stableArgs = JSON.stringify(args, Object.keys(args || {}).sort());\r\n return `${name}:${stableArgs}`;\r\n }\r\n\r\n subscribe(queryName: string, args: any, onUpdate: (data: any) => void): () => void {\r\n const queryId = this.getQueryId(queryName, args);\r\n\r\n if (!this.listeners.has(queryId)) {\r\n this.listeners.set(queryId, new Set());\r\n this.subscriptions.set(queryId, { name: queryName, args });\r\n // Send subscribe message\r\n this.sendMessage({\r\n type: \"query\",\r\n queryId,\r\n name: queryName,\r\n args,\r\n });\r\n }\r\n\r\n this.listeners.get(queryId)!.add(onUpdate);\r\n\r\n return () => {\r\n const set = this.listeners.get(queryId);\r\n if (set) {\r\n set.delete(onUpdate);\r\n if (set.size === 0) {\r\n this.listeners.delete(queryId);\r\n this.subscriptions.delete(queryId);\r\n // Send unsubscribe message (not implemented in server yet)\r\n }\r\n }\r\n };\r\n }\r\n\r\n async fetch(name: string, args: any): Promise<any> {\r\n const queryId = this.getQueryId(name, args);\r\n\r\n return new Promise((resolve, reject) => {\r\n let resolved = false;\r\n const unsubscribe = this.subscribe(name, args, (data) => {\r\n if (!resolved) {\r\n resolved = true;\r\n unsubscribe();\r\n resolve(data);\r\n }\r\n });\r\n\r\n setTimeout(() => {\r\n if (!resolved) {\r\n resolved = true;\r\n unsubscribe();\r\n reject(new Error(\"Timeout waiting for data\"));\r\n }\r\n }, 5000);\r\n });\r\n }\r\n\r\n async mutate(name: string, args: any): Promise<any> {\r\n return new Promise((resolve, reject) => {\r\n const mutationId = Math.random().toString(36).slice(2);\r\n\r\n const timeout = setTimeout(() => {\r\n this.pendingMutations.delete(mutationId);\r\n reject(new Error(\"Mutation timeout\"));\r\n }, 10000);\r\n\r\n this.pendingMutations.set(mutationId, { resolve, reject, timeout });\r\n\r\n this.sendMessage({\r\n type: \"mutation\",\r\n mutationId,\r\n name,\r\n args,\r\n });\r\n });\r\n }\r\n\r\n close() {\r\n this.isExplicitlyClosed = true;\r\n if (this.reconnectTimeout) {\r\n clearTimeout(this.reconnectTimeout);\r\n this.reconnectTimeout = null;\r\n }\r\n\r\n if (this.ws) {\r\n // Prevent handlers from firing during closure\r\n this.ws.onclose = null;\r\n this.ws.onopen = null;\r\n this.ws.onerror = null;\r\n this.ws.onmessage = null;\r\n\r\n this.ws.close();\r\n this.ws = null;\r\n }\r\n this.isConnected = false;\r\n this.stopHeartbeat();\r\n }\r\n}\r\n"],"mappings":"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","names":["axios","axios","axios","axios"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/function-reference.ts"],"sourcesContent":["export type FunctionReference<\n Type extends \"query\" | \"mutation\" | \"action\",\n Name extends string,\n Args = any,\n Return = any,\n> = {\n _type: Type;\n _name: Name;\n _args: Args;\n _return: Return;\n _auth?: \"required\" | \"optional\" | \"public\";\n};\n\nexport function makeFunctionReference<\n Type extends \"query\" | \"mutation\" | \"action\",\n Name extends string,\n Args = any,\n Return = any,\n>(name: Name): FunctionReference<Type, Name, Args, Return> {\n return {\n _type: \"query\" as any,\n _name: name,\n _args: undefined as any,\n _return: undefined as any,\n _auth: undefined,\n };\n}\n\n/**\n * Reference type for RPC (tRPC-style) procedures\n * Used for client-side type-safe RPC calls\n */\nexport type RpcReference<\n ProcedureType extends \"query\" | \"mutation\",\n Name extends string,\n Args = any,\n Return = any,\n> = {\n _procedureType: ProcedureType;\n _name: Name;\n _args: Args;\n _return: Return;\n _auth?: \"required\" | \"optional\" | \"public\";\n};\n\nexport function makeRpcReference<\n ProcedureType extends \"query\" | \"mutation\",\n Name extends string,\n Args = any,\n Return = any,\n>(name: Name): RpcReference<ProcedureType, Name, Args, Return> {\n return {\n _procedureType: \"query\" as any,\n _name: name,\n _args: undefined as any,\n _return: undefined as any,\n _auth: undefined,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAaO,SAAS,sBAKd,MAAyD;AACvD,SAAO;AAAA,IACH,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,SAAS;AAAA,IACT,OAAO;AAAA,EACX;AACJ;AAmBO,SAAS,iBAKd,MAA6D;AAC3D,SAAO;AAAA,IACH,gBAAgB;AAAA,IAChB,OAAO;AAAA,IACP,OAAO;AAAA,IACP,SAAS;AAAA,IACT,OAAO;AAAA,EACX;AACJ;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/function-reference.ts"],"sourcesContent":["export type FunctionReference<\r\n Type extends \"query\" | \"mutation\" | \"action\",\r\n Name extends string,\r\n Args = any,\r\n Return = any,\r\n> = {\r\n _type: Type;\r\n _name: Name;\r\n _args: Args;\r\n _return: Return;\r\n _auth?: \"required\" | \"optional\" | \"public\";\r\n};\r\n\r\nexport function makeFunctionReference<\r\n Type extends \"query\" | \"mutation\" | \"action\",\r\n Name extends string,\r\n Args = any,\r\n Return = any,\r\n>(name: Name): FunctionReference<Type, Name, Args, Return> {\r\n return {\r\n _type: \"query\" as any,\r\n _name: name,\r\n _args: undefined as any,\r\n _return: undefined as any,\r\n _auth: undefined,\r\n };\r\n}\r\n\r\n/**\r\n * Reference type for RPC (tRPC-style) procedures\r\n * Used for client-side type-safe RPC calls\r\n */\r\nexport type RpcReference<\r\n ProcedureType extends \"query\" | \"mutation\",\r\n Name extends string,\r\n Args = any,\r\n Return = any,\r\n> = {\r\n _procedureType: ProcedureType;\r\n _name: Name;\r\n _args: Args;\r\n _return: Return;\r\n _auth?: \"required\" | \"optional\" | \"public\";\r\n};\r\n\r\nexport function makeRpcReference<\r\n ProcedureType extends \"query\" | \"mutation\",\r\n Name extends string,\r\n Args = any,\r\n Return = any,\r\n>(name: Name): RpcReference<ProcedureType, Name, Args, Return> {\r\n return {\r\n _procedureType: \"query\" as any,\r\n _name: name,\r\n _args: undefined as any,\r\n _return: undefined as any,\r\n _auth: undefined,\r\n };\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAaO,SAAS,sBAKd,MAAyD;AACvD,SAAO;AAAA,IACH,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,SAAS;AAAA,IACT,OAAO;AAAA,EACX;AACJ;AAmBO,SAAS,iBAKd,MAA6D;AAC3D,SAAO;AAAA,IACH,gBAAgB;AAAA,IAChB,OAAO;AAAA,IACP,OAAO;AAAA,IACP,SAAS;AAAA,IACT,OAAO;AAAA,EACX;AACJ;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/function-reference.ts"],"sourcesContent":["export type FunctionReference<\n Type extends \"query\" | \"mutation\" | \"action\",\n Name extends string,\n Args = any,\n Return = any,\n> = {\n _type: Type;\n _name: Name;\n _args: Args;\n _return: Return;\n _auth?: \"required\" | \"optional\" | \"public\";\n};\n\nexport function makeFunctionReference<\n Type extends \"query\" | \"mutation\" | \"action\",\n Name extends string,\n Args = any,\n Return = any,\n>(name: Name): FunctionReference<Type, Name, Args, Return> {\n return {\n _type: \"query\" as any,\n _name: name,\n _args: undefined as any,\n _return: undefined as any,\n _auth: undefined,\n };\n}\n\n/**\n * Reference type for RPC (tRPC-style) procedures\n * Used for client-side type-safe RPC calls\n */\nexport type RpcReference<\n ProcedureType extends \"query\" | \"mutation\",\n Name extends string,\n Args = any,\n Return = any,\n> = {\n _procedureType: ProcedureType;\n _name: Name;\n _args: Args;\n _return: Return;\n _auth?: \"required\" | \"optional\" | \"public\";\n};\n\nexport function makeRpcReference<\n ProcedureType extends \"query\" | \"mutation\",\n Name extends string,\n Args = any,\n Return = any,\n>(name: Name): RpcReference<ProcedureType, Name, Args, Return> {\n return {\n _procedureType: \"query\" as any,\n _name: name,\n _args: undefined as any,\n _return: undefined as any,\n _auth: undefined,\n };\n}\n"],"mappings":";AAaO,SAAS,sBAKd,MAAyD;AACvD,SAAO;AAAA,IACH,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,SAAS;AAAA,IACT,OAAO;AAAA,EACX;AACJ;AAmBO,SAAS,iBAKd,MAA6D;AAC3D,SAAO;AAAA,IACH,gBAAgB;AAAA,IAChB,OAAO;AAAA,IACP,OAAO;AAAA,IACP,SAAS;AAAA,IACT,OAAO;AAAA,EACX;AACJ;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/function-reference.ts"],"sourcesContent":["export type FunctionReference<\r\n Type extends \"query\" | \"mutation\" | \"action\",\r\n Name extends string,\r\n Args = any,\r\n Return = any,\r\n> = {\r\n _type: Type;\r\n _name: Name;\r\n _args: Args;\r\n _return: Return;\r\n _auth?: \"required\" | \"optional\" | \"public\";\r\n};\r\n\r\nexport function makeFunctionReference<\r\n Type extends \"query\" | \"mutation\" | \"action\",\r\n Name extends string,\r\n Args = any,\r\n Return = any,\r\n>(name: Name): FunctionReference<Type, Name, Args, Return> {\r\n return {\r\n _type: \"query\" as any,\r\n _name: name,\r\n _args: undefined as any,\r\n _return: undefined as any,\r\n _auth: undefined,\r\n };\r\n}\r\n\r\n/**\r\n * Reference type for RPC (tRPC-style) procedures\r\n * Used for client-side type-safe RPC calls\r\n */\r\nexport type RpcReference<\r\n ProcedureType extends \"query\" | \"mutation\",\r\n Name extends string,\r\n Args = any,\r\n Return = any,\r\n> = {\r\n _procedureType: ProcedureType;\r\n _name: Name;\r\n _args: Args;\r\n _return: Return;\r\n _auth?: \"required\" | \"optional\" | \"public\";\r\n};\r\n\r\nexport function makeRpcReference<\r\n ProcedureType extends \"query\" | \"mutation\",\r\n Name extends string,\r\n Args = any,\r\n Return = any,\r\n>(name: Name): RpcReference<ProcedureType, Name, Args, Return> {\r\n return {\r\n _procedureType: \"query\" as any,\r\n _name: name,\r\n _args: undefined as any,\r\n _return: undefined as any,\r\n _auth: undefined,\r\n };\r\n}\r\n"],"mappings":";AAaO,SAAS,sBAKd,MAAyD;AACvD,SAAO;AAAA,IACH,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,SAAS;AAAA,IACT,OAAO;AAAA,EACX;AACJ;AAmBO,SAAS,iBAKd,MAA6D;AAC3D,SAAO;AAAA,IACH,gBAAgB;AAAA,IAChB,OAAO;AAAA,IACP,OAAO;AAAA,IACP,SAAS;AAAA,IACT,OAAO;AAAA,EACX;AACJ;","names":[]}
|
package/dist/index.cjs
CHANGED
|
@@ -37,11 +37,14 @@ __export(index_exports, {
|
|
|
37
37
|
ArchlastContext: () => ArchlastContext,
|
|
38
38
|
ArchlastProvider: () => ArchlastProvider,
|
|
39
39
|
StorageClient: () => StorageClient,
|
|
40
|
+
betterAuthClient: () => authClient,
|
|
41
|
+
createArchlastAuthClient: () => createArchlastAuthClient,
|
|
40
42
|
createArchlastTRPCClient: () => createArchlastTRPCClient,
|
|
41
43
|
makeFunctionReference: () => makeFunctionReference,
|
|
42
44
|
makeRpcReference: () => makeRpcReference,
|
|
43
45
|
useArchlast: () => useArchlast,
|
|
44
46
|
useAuth: () => useAuth,
|
|
47
|
+
useBetterAuthSession: () => useSession,
|
|
45
48
|
useClientPagination: () => useClientPagination,
|
|
46
49
|
useDownload: () => useDownload,
|
|
47
50
|
useMutation: () => useMutation,
|
|
@@ -61,6 +64,51 @@ module.exports = __toCommonJS(index_exports);
|
|
|
61
64
|
|
|
62
65
|
// src/auth/index.ts
|
|
63
66
|
var import_axios = __toESM(require("axios"), 1);
|
|
67
|
+
|
|
68
|
+
// src/auth/better-auth.ts
|
|
69
|
+
var import_react = require("better-auth/react");
|
|
70
|
+
var import_plugins = require("better-auth/client/plugins");
|
|
71
|
+
function getBetterAuthBaseURL() {
|
|
72
|
+
const envURL = process.env.NEXT_PUBLIC_BETTER_AUTH_URL || process.env.NEXT_PUBLIC_ARCHLAST_HTTP_URL || process.env.ARCHLAST_HTTP_URL;
|
|
73
|
+
if (envURL) {
|
|
74
|
+
return `${envURL}/api/auth`;
|
|
75
|
+
}
|
|
76
|
+
return "http://localhost:4000/api/auth";
|
|
77
|
+
}
|
|
78
|
+
var authClient = (0, import_react.createAuthClient)({
|
|
79
|
+
baseURL: getBetterAuthBaseURL(),
|
|
80
|
+
fetchOptions: {
|
|
81
|
+
credentials: "include"
|
|
82
|
+
// Required for cookies
|
|
83
|
+
},
|
|
84
|
+
plugins: [
|
|
85
|
+
// Admin plugin - user management, roles, bans
|
|
86
|
+
(0, import_plugins.adminClient)(),
|
|
87
|
+
// Organization plugin - multi-tenancy
|
|
88
|
+
(0, import_plugins.organizationClient)(),
|
|
89
|
+
// Username plugin - username-based sign-in
|
|
90
|
+
(0, import_plugins.usernameClient)()
|
|
91
|
+
]
|
|
92
|
+
});
|
|
93
|
+
function useSession() {
|
|
94
|
+
return authClient.useSession();
|
|
95
|
+
}
|
|
96
|
+
function createArchlastAuthClient(options) {
|
|
97
|
+
return (0, import_react.createAuthClient)({
|
|
98
|
+
baseURL: options.baseURL || getBetterAuthBaseURL(),
|
|
99
|
+
fetchOptions: {
|
|
100
|
+
credentials: "include",
|
|
101
|
+
...options.fetchOptions
|
|
102
|
+
},
|
|
103
|
+
plugins: [
|
|
104
|
+
(0, import_plugins.adminClient)(),
|
|
105
|
+
(0, import_plugins.organizationClient)(),
|
|
106
|
+
(0, import_plugins.usernameClient)()
|
|
107
|
+
]
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// src/auth/index.ts
|
|
64
112
|
function resolveBaseUrl(explicit) {
|
|
65
113
|
if (explicit && explicit.trim()) return explicit.replace(/\/+$/, "");
|
|
66
114
|
if (typeof window !== "undefined" && window.location?.origin) return window.location.origin;
|
|
@@ -695,25 +743,25 @@ var ArchlastClient = class {
|
|
|
695
743
|
};
|
|
696
744
|
|
|
697
745
|
// src/react.tsx
|
|
698
|
-
var
|
|
746
|
+
var import_react2 = require("react");
|
|
699
747
|
var import_react_query = require("@tanstack/react-query");
|
|
700
748
|
var import_axios4 = __toESM(require("axios"), 1);
|
|
701
749
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
702
|
-
var ArchlastContext = (0,
|
|
750
|
+
var ArchlastContext = (0, import_react2.createContext)(null);
|
|
703
751
|
var useArchlast = () => {
|
|
704
|
-
const client = (0,
|
|
752
|
+
const client = (0, import_react2.useContext)(ArchlastContext);
|
|
705
753
|
if (!client) throw new Error("ArchlastProvider not found");
|
|
706
754
|
return client;
|
|
707
755
|
};
|
|
708
756
|
function ArchlastProvider({ client, children }) {
|
|
709
|
-
const [queryClient] = (0,
|
|
757
|
+
const [queryClient] = (0, import_react2.useState)(() => new import_react_query.QueryClient());
|
|
710
758
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArchlastContext.Provider, { value: client, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_query.QueryClientProvider, { client: queryClient, children }) });
|
|
711
759
|
}
|
|
712
760
|
function useQuery(queryRef, args, options) {
|
|
713
761
|
const client = useArchlast();
|
|
714
762
|
const queryClient = (0, import_react_query.useQueryClient)();
|
|
715
763
|
const queryKey = [queryRef._name, args];
|
|
716
|
-
(0,
|
|
764
|
+
(0, import_react2.useEffect)(() => {
|
|
717
765
|
const unsubscribe = client.subscribe(queryRef._name, args, (data) => {
|
|
718
766
|
queryClient.setQueryData(queryKey, data);
|
|
719
767
|
});
|
|
@@ -725,8 +773,6 @@ function useQuery(queryRef, args, options) {
|
|
|
725
773
|
const result = await client.fetch(queryRef._name, args);
|
|
726
774
|
return result === void 0 ? null : result;
|
|
727
775
|
},
|
|
728
|
-
// staleTime: 0,
|
|
729
|
-
// gcTime: 1000 * 60 * 5,
|
|
730
776
|
...options
|
|
731
777
|
});
|
|
732
778
|
return query.data;
|
|
@@ -746,10 +792,10 @@ function useMutation(mutationRef) {
|
|
|
746
792
|
}
|
|
747
793
|
function useUpload(options) {
|
|
748
794
|
const client = useArchlast();
|
|
749
|
-
const [isUploading, setUploading] = (0,
|
|
750
|
-
const [error, setError] = (0,
|
|
751
|
-
const [result, setResult] = (0,
|
|
752
|
-
const upload = (0,
|
|
795
|
+
const [isUploading, setUploading] = (0, import_react2.useState)(false);
|
|
796
|
+
const [error, setError] = (0, import_react2.useState)(null);
|
|
797
|
+
const [result, setResult] = (0, import_react2.useState)(null);
|
|
798
|
+
const upload = (0, import_react2.useCallback)(
|
|
753
799
|
async (file, contentType) => {
|
|
754
800
|
setUploading(true);
|
|
755
801
|
setError(null);
|
|
@@ -768,7 +814,7 @@ function useUpload(options) {
|
|
|
768
814
|
},
|
|
769
815
|
[client]
|
|
770
816
|
);
|
|
771
|
-
const presign = (0,
|
|
817
|
+
const presign = (0, import_react2.useCallback)(
|
|
772
818
|
async (id, expiresInSeconds = 300) => {
|
|
773
819
|
const { url: relativeUrl } = await client.storage.presign(id, expiresInSeconds);
|
|
774
820
|
const absoluteUrl = relativeUrl.startsWith("http") ? relativeUrl : `${options?.baseUrl ?? ""}${relativeUrl.startsWith("/") ? "" : "/"}${relativeUrl}`;
|
|
@@ -818,24 +864,24 @@ function useAuth(options) {
|
|
|
818
864
|
initialData: DEFAULT_AUTH_STATE
|
|
819
865
|
// Optimistic default
|
|
820
866
|
});
|
|
821
|
-
const invalidateAuth = (0,
|
|
867
|
+
const invalidateAuth = (0, import_react2.useCallback)(() => {
|
|
822
868
|
return queryClient.invalidateQueries({ queryKey: ["auth", "state"] });
|
|
823
869
|
}, [queryClient]);
|
|
824
|
-
const signIn = (0,
|
|
870
|
+
const signIn = (0, import_react2.useCallback)(
|
|
825
871
|
async (input) => {
|
|
826
872
|
await client.auth.signIn(input);
|
|
827
873
|
await invalidateAuth();
|
|
828
874
|
},
|
|
829
875
|
[client, invalidateAuth]
|
|
830
876
|
);
|
|
831
|
-
const signUp = (0,
|
|
877
|
+
const signUp = (0, import_react2.useCallback)(
|
|
832
878
|
async (input) => {
|
|
833
879
|
await client.auth.signUp(input);
|
|
834
880
|
await invalidateAuth();
|
|
835
881
|
},
|
|
836
882
|
[client, invalidateAuth]
|
|
837
883
|
);
|
|
838
|
-
const signOut = (0,
|
|
884
|
+
const signOut = (0, import_react2.useCallback)(async () => {
|
|
839
885
|
try {
|
|
840
886
|
await client.auth.signOut();
|
|
841
887
|
} finally {
|
|
@@ -876,9 +922,9 @@ function useResetPassword() {
|
|
|
876
922
|
}
|
|
877
923
|
function useDownload(options) {
|
|
878
924
|
const client = useArchlast();
|
|
879
|
-
const [isDownloading, setDownloading] = (0,
|
|
880
|
-
const [error, setError] = (0,
|
|
881
|
-
const presign = (0,
|
|
925
|
+
const [isDownloading, setDownloading] = (0, import_react2.useState)(false);
|
|
926
|
+
const [error, setError] = (0, import_react2.useState)(null);
|
|
927
|
+
const presign = (0, import_react2.useCallback)(
|
|
882
928
|
async (id, expiresInSeconds = 300) => {
|
|
883
929
|
const { url: relativeUrl } = await client.storage.presign(id, expiresInSeconds);
|
|
884
930
|
const absoluteUrl = relativeUrl.startsWith("http") ? relativeUrl : `${options?.baseUrl ?? client.baseUrl ?? ""}${relativeUrl.startsWith("/") ? "" : "/"}${relativeUrl}`;
|
|
@@ -886,7 +932,7 @@ function useDownload(options) {
|
|
|
886
932
|
},
|
|
887
933
|
[client, options?.baseUrl]
|
|
888
934
|
);
|
|
889
|
-
const download = (0,
|
|
935
|
+
const download = (0, import_react2.useCallback)(
|
|
890
936
|
async (id, expiresInSeconds = 300) => {
|
|
891
937
|
setDownloading(true);
|
|
892
938
|
setError(null);
|
|
@@ -912,9 +958,9 @@ function useDownload(options) {
|
|
|
912
958
|
}
|
|
913
959
|
function useStorageDelete(options) {
|
|
914
960
|
const client = useArchlast();
|
|
915
|
-
const [isDeleting, setDeleting] = (0,
|
|
916
|
-
const [error, setError] = (0,
|
|
917
|
-
const deleteFile = (0,
|
|
961
|
+
const [isDeleting, setDeleting] = (0, import_react2.useState)(false);
|
|
962
|
+
const [error, setError] = (0, import_react2.useState)(null);
|
|
963
|
+
const deleteFile = (0, import_react2.useCallback)(
|
|
918
964
|
async (id) => {
|
|
919
965
|
setDeleting(true);
|
|
920
966
|
setError(null);
|
|
@@ -936,8 +982,8 @@ function useStorageDelete(options) {
|
|
|
936
982
|
return { deleteFile, isDeleting, error };
|
|
937
983
|
}
|
|
938
984
|
function useClientPagination(data, initialPageSize = 10) {
|
|
939
|
-
const [page, setPage] = (0,
|
|
940
|
-
const [pageSize, setPageSize] = (0,
|
|
985
|
+
const [page, setPage] = (0, import_react2.useState)(1);
|
|
986
|
+
const [pageSize, setPageSize] = (0, import_react2.useState)(initialPageSize);
|
|
941
987
|
const items = data || [];
|
|
942
988
|
const total = items.length;
|
|
943
989
|
const totalPages = Math.ceil(total / pageSize);
|
|
@@ -960,7 +1006,7 @@ function useClientPagination(data, initialPageSize = 10) {
|
|
|
960
1006
|
setPageSize(size);
|
|
961
1007
|
setPage(1);
|
|
962
1008
|
};
|
|
963
|
-
(0,
|
|
1009
|
+
(0, import_react2.useEffect)(() => {
|
|
964
1010
|
setPage(1);
|
|
965
1011
|
}, [data?.length]);
|
|
966
1012
|
return {
|
|
@@ -980,12 +1026,12 @@ function useClientPagination(data, initialPageSize = 10) {
|
|
|
980
1026
|
function usePagination(queryRef, baseArgs, options) {
|
|
981
1027
|
const client = useArchlast();
|
|
982
1028
|
const queryClient = (0, import_react_query.useQueryClient)();
|
|
983
|
-
const [cursor, setCursor] = (0,
|
|
984
|
-
const [allItems, setAllItems] = (0,
|
|
1029
|
+
const [cursor, setCursor] = (0, import_react2.useState)(null);
|
|
1030
|
+
const [allItems, setAllItems] = (0, import_react2.useState)([]);
|
|
985
1031
|
const limit = options?.limit || 20;
|
|
986
1032
|
const args = { ...baseArgs, cursor, limit };
|
|
987
1033
|
const queryKey = [queryRef._name, args];
|
|
988
|
-
(0,
|
|
1034
|
+
(0, import_react2.useEffect)(() => {
|
|
989
1035
|
const unsubscribe = client.subscribe(queryRef._name, args, (data2) => {
|
|
990
1036
|
queryClient.setQueryData(queryKey, data2);
|
|
991
1037
|
});
|
|
@@ -1002,7 +1048,7 @@ function usePagination(queryRef, baseArgs, options) {
|
|
|
1002
1048
|
enabled: options?.enabled !== false
|
|
1003
1049
|
});
|
|
1004
1050
|
const data = query.data;
|
|
1005
|
-
(0,
|
|
1051
|
+
(0, import_react2.useEffect)(() => {
|
|
1006
1052
|
if (data?.items) {
|
|
1007
1053
|
if (cursor === null) {
|
|
1008
1054
|
setAllItems(data.items);
|
|
@@ -1140,11 +1186,14 @@ function createArchlastTRPCClient(options = {}) {
|
|
|
1140
1186
|
ArchlastContext,
|
|
1141
1187
|
ArchlastProvider,
|
|
1142
1188
|
StorageClient,
|
|
1189
|
+
betterAuthClient,
|
|
1190
|
+
createArchlastAuthClient,
|
|
1143
1191
|
createArchlastTRPCClient,
|
|
1144
1192
|
makeFunctionReference,
|
|
1145
1193
|
makeRpcReference,
|
|
1146
1194
|
useArchlast,
|
|
1147
1195
|
useAuth,
|
|
1196
|
+
useBetterAuthSession,
|
|
1148
1197
|
useClientPagination,
|
|
1149
1198
|
useDownload,
|
|
1150
1199
|
useMutation,
|