@archlast/client 0.0.1
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 -0
- package/README.md +60 -0
- package/dist/admin/index.cjs +93 -0
- package/dist/admin/index.cjs.map +1 -0
- package/dist/admin/index.d.cts +51 -0
- package/dist/admin/index.d.ts +51 -0
- package/dist/admin/index.js +59 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/auth/index.cjs +174 -0
- package/dist/auth/index.cjs.map +1 -0
- package/dist/auth/index.d.cts +128 -0
- package/dist/auth/index.d.ts +128 -0
- package/dist/auth/index.js +141 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/client.cjs +677 -0
- package/dist/client.cjs.map +1 -0
- package/dist/client.d.cts +84 -0
- package/dist/client.d.ts +84 -0
- package/dist/client.js +642 -0
- package/dist/client.js.map +1 -0
- package/dist/function-reference.cjs +50 -0
- package/dist/function-reference.cjs.map +1 -0
- package/dist/function-reference.d.cts +22 -0
- package/dist/function-reference.d.ts +22 -0
- package/dist/function-reference.js +24 -0
- package/dist/function-reference.js.map +1 -0
- package/dist/index.cjs +1163 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +12 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +1111 -0
- package/dist/index.js.map +1 -0
- package/dist/react.cjs +455 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +137 -0
- package/dist/react.d.ts +137 -0
- package/dist/react.js +410 -0
- package/dist/react.js.map +1 -0
- package/dist/storage/index.cjs +150 -0
- package/dist/storage/index.cjs.map +1 -0
- package/dist/storage/index.d.cts +59 -0
- package/dist/storage/index.d.ts +59 -0
- package/dist/storage/index.js +117 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/trpc.cjs +66 -0
- package/dist/trpc.cjs.map +1 -0
- package/dist/trpc.d.cts +59 -0
- package/dist/trpc.d.ts +59 -0
- package/dist/trpc.js +41 -0
- package/dist/trpc.js.map +1 -0
- package/package.json +90 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/auth/index.ts","../src/storage/index.ts","../src/admin/index.ts","../src/client.ts","../src/react.tsx","../src/function-reference.ts","../src/trpc.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","\"use client\";\n\nimport { useEffect, useState, createContext, useContext, useCallback, type ReactNode } from \"react\";\nimport { ArchlastClient } from \"./client\";\nimport { FunctionReference } from \"./function-reference\";\nimport {\n useQuery as useTanStackQuery,\n useMutation as useTanStackMutation,\n useQueryClient,\n QueryClient,\n QueryClientProvider,\n UseQueryOptions,\n} from \"@tanstack/react-query\";\nimport axios from \"axios\";\n\nimport {\n type AuthState,\n type SignInInput,\n type SignUpInput,\n} from \"./auth/index\";\n\n// Context for the client\nexport const ArchlastContext = createContext<ArchlastClient | null>(null);\n\ntype UploadResult = {\n id: string;\n url?: string;\n};\n\nexport const useArchlast = () => {\n const client = useContext(ArchlastContext);\n if (!client) throw new Error(\"ArchlastProvider not found\");\n return client;\n};\n\ninterface ArchlastProviderProps {\n client: ArchlastClient;\n children: ReactNode;\n}\n\nexport function ArchlastProvider({ client, children }: ArchlastProviderProps) {\n const [queryClient] = useState(() => new QueryClient());\n\n return (\n <ArchlastContext.Provider value={client}>\n <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>\n </ArchlastContext.Provider>\n );\n}\n\nexport function useQuery<Name extends string, Args, Return>(\n queryRef: FunctionReference<\"query\", Name, Args, Return>,\n args: Args,\n options?: Omit<UseQueryOptions<Return, Error, Return, [string, Args]>, \"queryKey\" | \"queryFn\">\n): Return | undefined {\n const client = useArchlast();\n const queryClient = useQueryClient();\n const queryKey = [queryRef._name, args] as [string, Args];\n\n useEffect(() => {\n const unsubscribe = client.subscribe(queryRef._name, args, (data) => {\n queryClient.setQueryData(queryKey, data);\n });\n\n return () => unsubscribe();\n }, [client, queryRef._name, JSON.stringify(args), queryClient]);\n\n const query = useTanStackQuery({\n queryKey,\n queryFn: async () => {\n const result = await client.fetch(queryRef._name, args);\n // Convert undefined to null to satisfy React Query\n return result === undefined ? (null as Return) : result;\n },\n // staleTime: 0,\n // gcTime: 1000 * 60 * 5,\n ...options,\n });\n\n return query.data;\n}\n\nexport function useMutation<Name extends string, Args, Return>(\n mutationRef: FunctionReference<\"mutation\", Name, Args, Return>\n) {\n const client = useArchlast();\n const queryClient = useQueryClient();\n\n const mutation = useTanStackMutation({\n mutationFn: async (args: Args) => {\n return client.mutate(mutationRef._name, args);\n },\n onSuccess: () => {\n queryClient.invalidateQueries();\n },\n });\n\n return mutation.mutateAsync;\n}\n\n// Pagination types\nexport interface PaginatedResponse<T> {\n items: T[];\n continueCursor: string | null;\n isDone: boolean;\n page?: number;\n pageSize?: number;\n total?: number;\n}\n\n/**\n * Upload hook that streams a Blob/Uint8Array/ReadableStream to the backend.\n * It returns the content-addressed storage id and an optional pre-signed download URL.\n */\nexport function useUpload(options?: { baseUrl?: string }) {\n const client = useArchlast();\n const [isUploading, setUploading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [result, setResult] = useState<UploadResult | null>(null);\n\n const upload = useCallback(\n async (\n file: Blob | Uint8Array | ReadableStream | File,\n contentType?: string\n ): Promise<UploadResult> => {\n setUploading(true);\n setError(null);\n setResult(null);\n\n try {\n const result = await client.storage.upload(file, contentType);\n setResult({ id: result.id, url: result.url });\n return { id: result.id, url: result.url };\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n throw e;\n } finally {\n setUploading(false);\n }\n },\n [client]\n );\n\n const presign = useCallback(\n async (id: string, expiresInSeconds: number = 300): Promise<string> => {\n // Call the server's presign endpoint to get a token-signed public URL\n const { url: relativeUrl } = await client.storage.presign(id, expiresInSeconds);\n // Make it absolute based on baseUrl\n const absoluteUrl = relativeUrl.startsWith(\"http\")\n ? relativeUrl\n : `${options?.baseUrl ?? \"\"}${relativeUrl.startsWith(\"/\") ? \"\" : \"/\"}${relativeUrl}`;\n setResult((prev) => (prev ? { ...prev, url: absoluteUrl } : { id, url: absoluteUrl }));\n return absoluteUrl;\n },\n [client, options?.baseUrl]\n );\n\n return { upload, presign, isUploading, error, result };\n}\n\nconst DEFAULT_AUTH_STATE: AuthState = {\n isAuthenticated: false,\n user: null,\n session: null,\n};\n\nexport interface UseAuthResult extends AuthState {\n isLoading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n signIn: (input: SignInInput) => Promise<void>;\n signUp: (input: SignUpInput) => Promise<void>;\n signOut: () => Promise<void>;\n}\n\nexport function useAuth(options?: { enabled?: boolean; pollIntervalMs?: number }): UseAuthResult {\n const client = useArchlast();\n const queryClient = useQueryClient();\n const enabled = options?.enabled ?? true;\n const pollInterval = options?.pollIntervalMs ?? 30000; // Check every 30s by default\n\n // Cache auth state\n const {\n data: authState,\n isLoading,\n error,\n refetch,\n } = useTanStackQuery({\n queryKey: [\"auth\", \"state\"],\n queryFn: async () => {\n try {\n return await client.auth.getState();\n } catch (err: any) {\n // Determine if this is a 401. If so, return default unauthenticated state.\n // Axios throws specific error structures.\n if (axios.isAxiosError(err) && err.response?.status === 401) {\n return DEFAULT_AUTH_STATE;\n }\n throw err;\n }\n },\n retry: false, // Don't retry auth checks, fail fast\n staleTime: 0, // Auth state is volatile, consider it always stale\n refetchInterval: enabled ? pollInterval : false,\n refetchOnWindowFocus: true, // Security: re-check when user tabbs back\n refetchOnReconnect: true,\n enabled,\n initialData: DEFAULT_AUTH_STATE, // Optimistic default\n });\n\n // Helper to invalidate auth state\n const invalidateAuth = useCallback(() => {\n return queryClient.invalidateQueries({ queryKey: [\"auth\", \"state\"] });\n }, [queryClient]);\n\n // Mutation wrappers\n const signIn = useCallback(\n async (input: SignInInput) => {\n await client.auth.signIn(input);\n await invalidateAuth();\n },\n [client, invalidateAuth]\n );\n\n const signUp = useCallback(\n async (input: SignUpInput) => {\n await client.auth.signUp(input);\n await invalidateAuth();\n },\n [client, invalidateAuth]\n );\n\n const signOut = useCallback(async () => {\n try {\n await client.auth.signOut();\n } finally {\n // Always clear state even if server errors\n queryClient.setQueryData([\"auth\", \"state\"], DEFAULT_AUTH_STATE);\n await invalidateAuth();\n }\n }, [client, queryClient, invalidateAuth]);\n\n // Derived state\n const currentState = authState ?? DEFAULT_AUTH_STATE;\n\n return {\n ...currentState,\n // Ensure booleans\n isAuthenticated: !!currentState.isAuthenticated,\n isLoading,\n error: error as Error | null,\n refresh: async () => {\n await refetch();\n },\n signIn,\n signUp,\n signOut,\n };\n}\n\nexport function useRequestPasswordReset() {\n const client = useArchlast();\n return useTanStackMutation({\n mutationFn: async (email: string) => {\n return client.auth.requestPasswordReset(email);\n },\n });\n}\n\nexport function useResetPassword() {\n const client = useArchlast();\n return useTanStackMutation({\n mutationFn: async ({ token, password }: { token: string; password: string }) => {\n return client.auth.resetPassword(token, password);\n },\n });\n}\n\n/**\n * Download hook to presign and download a storage object.\n */\nexport function useDownload(options?: { baseUrl?: string }) {\n const client = useArchlast();\n const [isDownloading, setDownloading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const presign = useCallback(\n async (id: string, expiresInSeconds: number = 300): Promise<string> => {\n // Get presigned URL which points to /_storage/download?token=...\n const { url: relativeUrl } = await client.storage.presign(id, expiresInSeconds);\n\n // Make it absolute based on baseUrl if needed, or if it's already absolute leave it.\n // The server returns `/_storage/download?token=...`\n const absoluteUrl = relativeUrl.startsWith(\"http\")\n ? relativeUrl\n : `${options?.baseUrl ?? client.baseUrl ?? \"\"}${relativeUrl.startsWith(\"/\") ? \"\" : \"/\"}${relativeUrl}`;\n\n return absoluteUrl;\n },\n [client, options?.baseUrl]\n );\n\n const download = useCallback(\n async (\n id: string,\n expiresInSeconds: number = 300\n ): Promise<{ blob: Blob; url: string }> => {\n setDownloading(true);\n setError(null);\n try {\n const signedUrl = await presign(id, expiresInSeconds);\n // The signed URL is public (token-authed), so we don't strictly need withCredentials\n // But sending them doesn't hurt for same-origin.\n // However, for pure public access simulation, we might shouldn't.\n // But since we are likely same-origin or allowed CORS, standard GET is fine.\n const response = await axios.get(signedUrl, {\n responseType: \"blob\",\n });\n const blob = response.data;\n const objectUrl = URL.createObjectURL(blob);\n return { blob, url: objectUrl };\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n throw e;\n } finally {\n setDownloading(false);\n }\n },\n [presign]\n );\n\n return { getUrl: presign, download, isDownloading, error };\n}\n\n/**\n * Delete hook to remove a storage object by id.\n */\nexport function useStorageDelete(options?: { baseUrl?: string }) {\n const client = useArchlast();\n const [isDeleting, setDeleting] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const deleteFile = useCallback(\n async (id: string): Promise<void> => {\n setDeleting(true);\n setError(null);\n try {\n const deleteUrl = `${options?.baseUrl ?? \"\"}/_archlast/storage/files/${encodeURIComponent(id)}`;\n await axios.delete(deleteUrl, {\n withCredentials: true,\n });\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n throw e;\n } finally {\n setDeleting(false);\n }\n },\n [options?.baseUrl]\n );\n\n return { deleteFile, isDeleting, error };\n}\n\nexport interface ClientPaginationResult<T> {\n items: T[];\n page: number;\n pageSize: number;\n total: number;\n totalPages: number;\n hasMore: boolean;\n hasPrevious: boolean;\n nextPage: () => void;\n previousPage: () => void;\n setPage: (page: number) => void;\n setPageSize: (size: number) => void;\n}\n\nexport interface ServerPaginationResult<T> {\n items: T[];\n cursor: string | null;\n isDone: boolean;\n page?: number;\n pageSize?: number;\n total?: number;\n hasMore: boolean;\n loadMore: () => void;\n refresh: () => void;\n isLoading: boolean;\n}\n\n/**\n * Client-side pagination hook - paginates data in memory\n */\nexport function useClientPagination<T>(\n data: T[] | undefined,\n initialPageSize = 10\n): ClientPaginationResult<T> {\n const [page, setPage] = useState(1);\n const [pageSize, setPageSize] = useState(initialPageSize);\n\n const items = data || [];\n const total = items.length;\n const totalPages = Math.ceil(total / pageSize);\n const startIndex = (page - 1) * pageSize;\n const endIndex = startIndex + pageSize;\n const paginatedItems = items.slice(startIndex, endIndex);\n\n const hasMore = page < totalPages;\n const hasPrevious = page > 1;\n\n const nextPage = () => {\n if (hasMore) setPage((p) => p + 1);\n };\n\n const previousPage = () => {\n if (hasPrevious) setPage((p) => p - 1);\n };\n\n const handleSetPage = (newPage: number) => {\n const validPage = Math.max(1, Math.min(newPage, totalPages || 1));\n setPage(validPage);\n };\n\n const handleSetPageSize = (size: number) => {\n setPageSize(size);\n setPage(1); // Reset to first page when changing page size\n };\n\n // Reset to first page if data changes\n useEffect(() => {\n setPage(1);\n }, [data?.length]);\n\n return {\n items: paginatedItems,\n page,\n pageSize,\n total,\n totalPages,\n hasMore,\n hasPrevious,\n nextPage,\n previousPage,\n setPage: handleSetPage,\n setPageSize: handleSetPageSize,\n };\n}\n\n/**\n * Server-side pagination hook - for queries that return PaginatedResponse\n */\nexport function usePagination<Name extends string, Args extends Record<string, any>, T>(\n queryRef: FunctionReference<\"query\", Name, Args, PaginatedResponse<T>>,\n baseArgs: Omit<Args, \"cursor\" | \"limit\">,\n options?: {\n limit?: number;\n enabled?: boolean;\n }\n): ServerPaginationResult<T> {\n const client = useArchlast();\n const queryClient = useQueryClient();\n const [cursor, setCursor] = useState<string | null>(null);\n const [allItems, setAllItems] = useState<T[]>([]);\n const limit = options?.limit || 20;\n\n const args = { ...baseArgs, cursor, limit } as unknown as Args;\n const queryKey = [queryRef._name, args] as [string, Args];\n\n useEffect(() => {\n const unsubscribe = client.subscribe(queryRef._name, args, (data) => {\n queryClient.setQueryData(queryKey, data);\n });\n\n return () => unsubscribe();\n }, [client, queryRef._name, JSON.stringify(args), queryClient]);\n\n const query = useTanStackQuery({\n queryKey,\n queryFn: async () => {\n const result = await client.fetch(queryRef._name, args);\n return result === undefined\n ? ({ items: [], continueCursor: null, isDone: true } as PaginatedResponse<T>)\n : result;\n },\n // staleTime: 0,\n // gcTime: 1000 * 60 * 5,\n enabled: options?.enabled !== false,\n });\n\n const data = query.data;\n\n // Update accumulated items when new data arrives\n useEffect(() => {\n if (data?.items) {\n if (cursor === null) {\n // First page - replace all items\n setAllItems(data.items);\n } else {\n // Subsequent pages - append items\n setAllItems((prev) => [...prev, ...data.items]);\n }\n }\n }, [data, cursor]);\n\n const loadMore = () => {\n if (data && !data.isDone && data.continueCursor) {\n setCursor(data.continueCursor);\n }\n };\n\n const refresh = () => {\n setCursor(null);\n setAllItems([]);\n queryClient.invalidateQueries({ queryKey: [queryRef._name] });\n };\n\n return {\n items: allItems,\n cursor: data?.continueCursor ?? null,\n isDone: data?.isDone ?? false,\n page: data?.page,\n pageSize: data?.pageSize,\n total: data?.total,\n hasMore: !data?.isDone && !!data?.continueCursor,\n loadMore,\n refresh,\n isLoading: query.isLoading,\n };\n}\n\n// ----------------------------------------------------------------------------\n// New Storage Hooks (using client.storage)\n// ----------------------------------------------------------------------------\n\nexport function useStorageList(limit = 20, offset = 0) {\n const client = useArchlast();\n return useTanStackQuery({\n queryKey: [\"storage\", \"list\", limit, offset],\n queryFn: () => client.storage.list(limit, offset),\n });\n}\n\nexport function useStorageMetadata(id: string) {\n const client = useArchlast();\n return useTanStackQuery({\n queryKey: [\"storage\", \"file\", id],\n queryFn: () => client.storage.getMetadata(id),\n enabled: !!id,\n });\n}\n\nexport function useStorageUpload() {\n const client = useArchlast();\n const queryClient = useQueryClient();\n\n return useTanStackMutation({\n mutationFn: (file: File) => client.storage.upload(file),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: [\"storage\", \"list\"] });\n },\n });\n}\n\nexport function useStorageDeleteFile() {\n const client = useArchlast();\n const queryClient = useQueryClient();\n\n return useTanStackMutation({\n mutationFn: (id: string) => client.storage.delete(id),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: [\"storage\", \"list\"] });\n },\n });\n}\n\nexport function useStorageHelpers() {\n const client = useArchlast();\n return {\n getPublicUrl: (id: string) => client.storage.getPublicUrl(id),\n };\n}\n","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","/**\r\n * tRPC Client Factory\r\n * Provides a type-safe tRPC client for calling Archlast RPC procedures\r\n */\r\n\r\nimport { createTRPCClient, httpBatchLink } from \"@trpc/client\";\r\nimport type { AnyRouter } from \"@trpc/server\";\r\n\r\nconst BETTER_AUTH_API_KEY_PREFIX = \"arch_\";\r\n\r\n/**\r\n * Check if a token is a Better-Auth API key\r\n */\r\nfunction isBetterAuthApiKey(token: string): boolean {\r\n return token.startsWith(BETTER_AUTH_API_KEY_PREFIX);\r\n}\r\n\r\n/**\r\n * Options for creating the tRPC client\r\n */\r\nexport interface CreateTRPCClientOptions {\r\n /**\r\n * Base URL of the Archlast server\r\n * @default http://localhost:4000\r\n */\r\n baseUrl?: string;\r\n\r\n /**\r\n * API key for authentication\r\n * Better-Auth API keys (arch_* prefix) use x-api-key header\r\n * Legacy tokens use Authorization: Bearer header\r\n */\r\n apiKey?: string;\r\n\r\n /**\r\n * Session token for authentication\r\n */\r\n sessionToken?: string;\r\n\r\n /**\r\n * Whether to use batching for multiple requests\r\n * @default true\r\n */\r\n batch?: boolean;\r\n\r\n /**\r\n * Custom headers to include in requests\r\n */\r\n headers?: Record<string, string>;\r\n}\r\n\r\n/**\r\n * Create a typed tRPC client for the Archlast server\r\n *\r\n * @example\r\n * ```ts\r\n * import { createArchlastTRPCClient } from \"@archlast/client/trpc\";\r\n * import type { AppRouter } from \"./_generated/rpc\";\r\n *\r\n * const client = createArchlastTRPCClient<AppRouter>({\r\n * baseUrl: \"http://localhost:4000\",\r\n * apiKey: \"arch_your-api-key\" // Better-Auth API key\r\n * });\r\n *\r\n * // Call RPC procedures\r\n * const result = await client.tasks.list.query();\r\n * const created = await client.tasks.create.mutate({ text: \"New task\" });\r\n * ```\r\n */\r\nexport function createArchlastTRPCClient<TRouter extends AnyRouter>(\r\n options: CreateTRPCClientOptions = {}\r\n): any {\r\n const {\r\n baseUrl = \"http://localhost:4000\",\r\n apiKey,\r\n sessionToken,\r\n batch = true,\r\n headers: customHeaders = {},\r\n } = options;\r\n\r\n // Build headers\r\n const headers: Record<string, string> = {\r\n \"Content-Type\": \"application/json\",\r\n ...customHeaders,\r\n };\r\n\r\n if (apiKey) {\r\n if (isBetterAuthApiKey(apiKey)) {\r\n // Better-Auth API key - use x-api-key header\r\n headers[\"x-api-key\"] = apiKey;\r\n } else {\r\n // Legacy token - use Authorization: Bearer header\r\n headers[\"Authorization\"] = `Bearer ${apiKey}`;\r\n }\r\n }\r\n\r\n if (sessionToken) {\r\n headers[\"Cookie\"] = `archlast-session=${sessionToken}`;\r\n }\r\n\r\n return createTRPCClient<TRouter>({\r\n links: [\r\n httpBatchLink({\r\n url: `${baseUrl}/api/trpc`,\r\n headers: headers as any,\r\n } as any),\r\n ],\r\n });\r\n}\r\n\r\n/**\r\n * Re-export tRPC types for convenience\r\n */\r\nexport type { TRPCClientError, createTRPCClient, httpBatchLink } from \"@trpc/client\";\r\nexport type { AnyRouter } from \"@trpc/server\";\r\n"],"mappings":"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","names":["axios","axios","axios","axios","axios","result","data"]}
|
package/dist/react.cjs
ADDED
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
+
mod
|
|
28
|
+
));
|
|
29
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
|
+
|
|
31
|
+
// src/react.tsx
|
|
32
|
+
var react_exports = {};
|
|
33
|
+
__export(react_exports, {
|
|
34
|
+
ArchlastContext: () => ArchlastContext,
|
|
35
|
+
ArchlastProvider: () => ArchlastProvider,
|
|
36
|
+
useArchlast: () => useArchlast,
|
|
37
|
+
useAuth: () => useAuth,
|
|
38
|
+
useClientPagination: () => useClientPagination,
|
|
39
|
+
useDownload: () => useDownload,
|
|
40
|
+
useMutation: () => useMutation,
|
|
41
|
+
usePagination: () => usePagination,
|
|
42
|
+
useQuery: () => useQuery,
|
|
43
|
+
useRequestPasswordReset: () => useRequestPasswordReset,
|
|
44
|
+
useResetPassword: () => useResetPassword,
|
|
45
|
+
useStorageDelete: () => useStorageDelete,
|
|
46
|
+
useStorageDeleteFile: () => useStorageDeleteFile,
|
|
47
|
+
useStorageHelpers: () => useStorageHelpers,
|
|
48
|
+
useStorageList: () => useStorageList,
|
|
49
|
+
useStorageMetadata: () => useStorageMetadata,
|
|
50
|
+
useStorageUpload: () => useStorageUpload,
|
|
51
|
+
useUpload: () => useUpload
|
|
52
|
+
});
|
|
53
|
+
module.exports = __toCommonJS(react_exports);
|
|
54
|
+
var import_react = require("react");
|
|
55
|
+
var import_react_query = require("@tanstack/react-query");
|
|
56
|
+
var import_axios = __toESM(require("axios"), 1);
|
|
57
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
58
|
+
var ArchlastContext = (0, import_react.createContext)(null);
|
|
59
|
+
var useArchlast = () => {
|
|
60
|
+
const client = (0, import_react.useContext)(ArchlastContext);
|
|
61
|
+
if (!client) throw new Error("ArchlastProvider not found");
|
|
62
|
+
return client;
|
|
63
|
+
};
|
|
64
|
+
function ArchlastProvider({ client, children }) {
|
|
65
|
+
const [queryClient] = (0, import_react.useState)(() => new import_react_query.QueryClient());
|
|
66
|
+
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 }) });
|
|
67
|
+
}
|
|
68
|
+
function useQuery(queryRef, args, options) {
|
|
69
|
+
const client = useArchlast();
|
|
70
|
+
const queryClient = (0, import_react_query.useQueryClient)();
|
|
71
|
+
const queryKey = [queryRef._name, args];
|
|
72
|
+
(0, import_react.useEffect)(() => {
|
|
73
|
+
const unsubscribe = client.subscribe(queryRef._name, args, (data) => {
|
|
74
|
+
queryClient.setQueryData(queryKey, data);
|
|
75
|
+
});
|
|
76
|
+
return () => unsubscribe();
|
|
77
|
+
}, [client, queryRef._name, JSON.stringify(args), queryClient]);
|
|
78
|
+
const query = (0, import_react_query.useQuery)({
|
|
79
|
+
queryKey,
|
|
80
|
+
queryFn: async () => {
|
|
81
|
+
const result = await client.fetch(queryRef._name, args);
|
|
82
|
+
return result === void 0 ? null : result;
|
|
83
|
+
},
|
|
84
|
+
// staleTime: 0,
|
|
85
|
+
// gcTime: 1000 * 60 * 5,
|
|
86
|
+
...options
|
|
87
|
+
});
|
|
88
|
+
return query.data;
|
|
89
|
+
}
|
|
90
|
+
function useMutation(mutationRef) {
|
|
91
|
+
const client = useArchlast();
|
|
92
|
+
const queryClient = (0, import_react_query.useQueryClient)();
|
|
93
|
+
const mutation = (0, import_react_query.useMutation)({
|
|
94
|
+
mutationFn: async (args) => {
|
|
95
|
+
return client.mutate(mutationRef._name, args);
|
|
96
|
+
},
|
|
97
|
+
onSuccess: () => {
|
|
98
|
+
queryClient.invalidateQueries();
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
return mutation.mutateAsync;
|
|
102
|
+
}
|
|
103
|
+
function useUpload(options) {
|
|
104
|
+
const client = useArchlast();
|
|
105
|
+
const [isUploading, setUploading] = (0, import_react.useState)(false);
|
|
106
|
+
const [error, setError] = (0, import_react.useState)(null);
|
|
107
|
+
const [result, setResult] = (0, import_react.useState)(null);
|
|
108
|
+
const upload = (0, import_react.useCallback)(
|
|
109
|
+
async (file, contentType) => {
|
|
110
|
+
setUploading(true);
|
|
111
|
+
setError(null);
|
|
112
|
+
setResult(null);
|
|
113
|
+
try {
|
|
114
|
+
const result2 = await client.storage.upload(file, contentType);
|
|
115
|
+
setResult({ id: result2.id, url: result2.url });
|
|
116
|
+
return { id: result2.id, url: result2.url };
|
|
117
|
+
} catch (err) {
|
|
118
|
+
const e = err instanceof Error ? err : new Error(String(err));
|
|
119
|
+
setError(e);
|
|
120
|
+
throw e;
|
|
121
|
+
} finally {
|
|
122
|
+
setUploading(false);
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
[client]
|
|
126
|
+
);
|
|
127
|
+
const presign = (0, import_react.useCallback)(
|
|
128
|
+
async (id, expiresInSeconds = 300) => {
|
|
129
|
+
const { url: relativeUrl } = await client.storage.presign(id, expiresInSeconds);
|
|
130
|
+
const absoluteUrl = relativeUrl.startsWith("http") ? relativeUrl : `${options?.baseUrl ?? ""}${relativeUrl.startsWith("/") ? "" : "/"}${relativeUrl}`;
|
|
131
|
+
setResult((prev) => prev ? { ...prev, url: absoluteUrl } : { id, url: absoluteUrl });
|
|
132
|
+
return absoluteUrl;
|
|
133
|
+
},
|
|
134
|
+
[client, options?.baseUrl]
|
|
135
|
+
);
|
|
136
|
+
return { upload, presign, isUploading, error, result };
|
|
137
|
+
}
|
|
138
|
+
var DEFAULT_AUTH_STATE = {
|
|
139
|
+
isAuthenticated: false,
|
|
140
|
+
user: null,
|
|
141
|
+
session: null
|
|
142
|
+
};
|
|
143
|
+
function useAuth(options) {
|
|
144
|
+
const client = useArchlast();
|
|
145
|
+
const queryClient = (0, import_react_query.useQueryClient)();
|
|
146
|
+
const enabled = options?.enabled ?? true;
|
|
147
|
+
const pollInterval = options?.pollIntervalMs ?? 3e4;
|
|
148
|
+
const {
|
|
149
|
+
data: authState,
|
|
150
|
+
isLoading,
|
|
151
|
+
error,
|
|
152
|
+
refetch
|
|
153
|
+
} = (0, import_react_query.useQuery)({
|
|
154
|
+
queryKey: ["auth", "state"],
|
|
155
|
+
queryFn: async () => {
|
|
156
|
+
try {
|
|
157
|
+
return await client.auth.getState();
|
|
158
|
+
} catch (err) {
|
|
159
|
+
if (import_axios.default.isAxiosError(err) && err.response?.status === 401) {
|
|
160
|
+
return DEFAULT_AUTH_STATE;
|
|
161
|
+
}
|
|
162
|
+
throw err;
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
retry: false,
|
|
166
|
+
// Don't retry auth checks, fail fast
|
|
167
|
+
staleTime: 0,
|
|
168
|
+
// Auth state is volatile, consider it always stale
|
|
169
|
+
refetchInterval: enabled ? pollInterval : false,
|
|
170
|
+
refetchOnWindowFocus: true,
|
|
171
|
+
// Security: re-check when user tabbs back
|
|
172
|
+
refetchOnReconnect: true,
|
|
173
|
+
enabled,
|
|
174
|
+
initialData: DEFAULT_AUTH_STATE
|
|
175
|
+
// Optimistic default
|
|
176
|
+
});
|
|
177
|
+
const invalidateAuth = (0, import_react.useCallback)(() => {
|
|
178
|
+
return queryClient.invalidateQueries({ queryKey: ["auth", "state"] });
|
|
179
|
+
}, [queryClient]);
|
|
180
|
+
const signIn = (0, import_react.useCallback)(
|
|
181
|
+
async (input) => {
|
|
182
|
+
await client.auth.signIn(input);
|
|
183
|
+
await invalidateAuth();
|
|
184
|
+
},
|
|
185
|
+
[client, invalidateAuth]
|
|
186
|
+
);
|
|
187
|
+
const signUp = (0, import_react.useCallback)(
|
|
188
|
+
async (input) => {
|
|
189
|
+
await client.auth.signUp(input);
|
|
190
|
+
await invalidateAuth();
|
|
191
|
+
},
|
|
192
|
+
[client, invalidateAuth]
|
|
193
|
+
);
|
|
194
|
+
const signOut = (0, import_react.useCallback)(async () => {
|
|
195
|
+
try {
|
|
196
|
+
await client.auth.signOut();
|
|
197
|
+
} finally {
|
|
198
|
+
queryClient.setQueryData(["auth", "state"], DEFAULT_AUTH_STATE);
|
|
199
|
+
await invalidateAuth();
|
|
200
|
+
}
|
|
201
|
+
}, [client, queryClient, invalidateAuth]);
|
|
202
|
+
const currentState = authState ?? DEFAULT_AUTH_STATE;
|
|
203
|
+
return {
|
|
204
|
+
...currentState,
|
|
205
|
+
// Ensure booleans
|
|
206
|
+
isAuthenticated: !!currentState.isAuthenticated,
|
|
207
|
+
isLoading,
|
|
208
|
+
error,
|
|
209
|
+
refresh: async () => {
|
|
210
|
+
await refetch();
|
|
211
|
+
},
|
|
212
|
+
signIn,
|
|
213
|
+
signUp,
|
|
214
|
+
signOut
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
function useRequestPasswordReset() {
|
|
218
|
+
const client = useArchlast();
|
|
219
|
+
return (0, import_react_query.useMutation)({
|
|
220
|
+
mutationFn: async (email) => {
|
|
221
|
+
return client.auth.requestPasswordReset(email);
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
function useResetPassword() {
|
|
226
|
+
const client = useArchlast();
|
|
227
|
+
return (0, import_react_query.useMutation)({
|
|
228
|
+
mutationFn: async ({ token, password }) => {
|
|
229
|
+
return client.auth.resetPassword(token, password);
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
function useDownload(options) {
|
|
234
|
+
const client = useArchlast();
|
|
235
|
+
const [isDownloading, setDownloading] = (0, import_react.useState)(false);
|
|
236
|
+
const [error, setError] = (0, import_react.useState)(null);
|
|
237
|
+
const presign = (0, import_react.useCallback)(
|
|
238
|
+
async (id, expiresInSeconds = 300) => {
|
|
239
|
+
const { url: relativeUrl } = await client.storage.presign(id, expiresInSeconds);
|
|
240
|
+
const absoluteUrl = relativeUrl.startsWith("http") ? relativeUrl : `${options?.baseUrl ?? client.baseUrl ?? ""}${relativeUrl.startsWith("/") ? "" : "/"}${relativeUrl}`;
|
|
241
|
+
return absoluteUrl;
|
|
242
|
+
},
|
|
243
|
+
[client, options?.baseUrl]
|
|
244
|
+
);
|
|
245
|
+
const download = (0, import_react.useCallback)(
|
|
246
|
+
async (id, expiresInSeconds = 300) => {
|
|
247
|
+
setDownloading(true);
|
|
248
|
+
setError(null);
|
|
249
|
+
try {
|
|
250
|
+
const signedUrl = await presign(id, expiresInSeconds);
|
|
251
|
+
const response = await import_axios.default.get(signedUrl, {
|
|
252
|
+
responseType: "blob"
|
|
253
|
+
});
|
|
254
|
+
const blob = response.data;
|
|
255
|
+
const objectUrl = URL.createObjectURL(blob);
|
|
256
|
+
return { blob, url: objectUrl };
|
|
257
|
+
} catch (err) {
|
|
258
|
+
const e = err instanceof Error ? err : new Error(String(err));
|
|
259
|
+
setError(e);
|
|
260
|
+
throw e;
|
|
261
|
+
} finally {
|
|
262
|
+
setDownloading(false);
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
[presign]
|
|
266
|
+
);
|
|
267
|
+
return { getUrl: presign, download, isDownloading, error };
|
|
268
|
+
}
|
|
269
|
+
function useStorageDelete(options) {
|
|
270
|
+
const client = useArchlast();
|
|
271
|
+
const [isDeleting, setDeleting] = (0, import_react.useState)(false);
|
|
272
|
+
const [error, setError] = (0, import_react.useState)(null);
|
|
273
|
+
const deleteFile = (0, import_react.useCallback)(
|
|
274
|
+
async (id) => {
|
|
275
|
+
setDeleting(true);
|
|
276
|
+
setError(null);
|
|
277
|
+
try {
|
|
278
|
+
const deleteUrl = `${options?.baseUrl ?? ""}/_archlast/storage/files/${encodeURIComponent(id)}`;
|
|
279
|
+
await import_axios.default.delete(deleteUrl, {
|
|
280
|
+
withCredentials: true
|
|
281
|
+
});
|
|
282
|
+
} catch (err) {
|
|
283
|
+
const e = err instanceof Error ? err : new Error(String(err));
|
|
284
|
+
setError(e);
|
|
285
|
+
throw e;
|
|
286
|
+
} finally {
|
|
287
|
+
setDeleting(false);
|
|
288
|
+
}
|
|
289
|
+
},
|
|
290
|
+
[options?.baseUrl]
|
|
291
|
+
);
|
|
292
|
+
return { deleteFile, isDeleting, error };
|
|
293
|
+
}
|
|
294
|
+
function useClientPagination(data, initialPageSize = 10) {
|
|
295
|
+
const [page, setPage] = (0, import_react.useState)(1);
|
|
296
|
+
const [pageSize, setPageSize] = (0, import_react.useState)(initialPageSize);
|
|
297
|
+
const items = data || [];
|
|
298
|
+
const total = items.length;
|
|
299
|
+
const totalPages = Math.ceil(total / pageSize);
|
|
300
|
+
const startIndex = (page - 1) * pageSize;
|
|
301
|
+
const endIndex = startIndex + pageSize;
|
|
302
|
+
const paginatedItems = items.slice(startIndex, endIndex);
|
|
303
|
+
const hasMore = page < totalPages;
|
|
304
|
+
const hasPrevious = page > 1;
|
|
305
|
+
const nextPage = () => {
|
|
306
|
+
if (hasMore) setPage((p) => p + 1);
|
|
307
|
+
};
|
|
308
|
+
const previousPage = () => {
|
|
309
|
+
if (hasPrevious) setPage((p) => p - 1);
|
|
310
|
+
};
|
|
311
|
+
const handleSetPage = (newPage) => {
|
|
312
|
+
const validPage = Math.max(1, Math.min(newPage, totalPages || 1));
|
|
313
|
+
setPage(validPage);
|
|
314
|
+
};
|
|
315
|
+
const handleSetPageSize = (size) => {
|
|
316
|
+
setPageSize(size);
|
|
317
|
+
setPage(1);
|
|
318
|
+
};
|
|
319
|
+
(0, import_react.useEffect)(() => {
|
|
320
|
+
setPage(1);
|
|
321
|
+
}, [data?.length]);
|
|
322
|
+
return {
|
|
323
|
+
items: paginatedItems,
|
|
324
|
+
page,
|
|
325
|
+
pageSize,
|
|
326
|
+
total,
|
|
327
|
+
totalPages,
|
|
328
|
+
hasMore,
|
|
329
|
+
hasPrevious,
|
|
330
|
+
nextPage,
|
|
331
|
+
previousPage,
|
|
332
|
+
setPage: handleSetPage,
|
|
333
|
+
setPageSize: handleSetPageSize
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
function usePagination(queryRef, baseArgs, options) {
|
|
337
|
+
const client = useArchlast();
|
|
338
|
+
const queryClient = (0, import_react_query.useQueryClient)();
|
|
339
|
+
const [cursor, setCursor] = (0, import_react.useState)(null);
|
|
340
|
+
const [allItems, setAllItems] = (0, import_react.useState)([]);
|
|
341
|
+
const limit = options?.limit || 20;
|
|
342
|
+
const args = { ...baseArgs, cursor, limit };
|
|
343
|
+
const queryKey = [queryRef._name, args];
|
|
344
|
+
(0, import_react.useEffect)(() => {
|
|
345
|
+
const unsubscribe = client.subscribe(queryRef._name, args, (data2) => {
|
|
346
|
+
queryClient.setQueryData(queryKey, data2);
|
|
347
|
+
});
|
|
348
|
+
return () => unsubscribe();
|
|
349
|
+
}, [client, queryRef._name, JSON.stringify(args), queryClient]);
|
|
350
|
+
const query = (0, import_react_query.useQuery)({
|
|
351
|
+
queryKey,
|
|
352
|
+
queryFn: async () => {
|
|
353
|
+
const result = await client.fetch(queryRef._name, args);
|
|
354
|
+
return result === void 0 ? { items: [], continueCursor: null, isDone: true } : result;
|
|
355
|
+
},
|
|
356
|
+
// staleTime: 0,
|
|
357
|
+
// gcTime: 1000 * 60 * 5,
|
|
358
|
+
enabled: options?.enabled !== false
|
|
359
|
+
});
|
|
360
|
+
const data = query.data;
|
|
361
|
+
(0, import_react.useEffect)(() => {
|
|
362
|
+
if (data?.items) {
|
|
363
|
+
if (cursor === null) {
|
|
364
|
+
setAllItems(data.items);
|
|
365
|
+
} else {
|
|
366
|
+
setAllItems((prev) => [...prev, ...data.items]);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}, [data, cursor]);
|
|
370
|
+
const loadMore = () => {
|
|
371
|
+
if (data && !data.isDone && data.continueCursor) {
|
|
372
|
+
setCursor(data.continueCursor);
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
const refresh = () => {
|
|
376
|
+
setCursor(null);
|
|
377
|
+
setAllItems([]);
|
|
378
|
+
queryClient.invalidateQueries({ queryKey: [queryRef._name] });
|
|
379
|
+
};
|
|
380
|
+
return {
|
|
381
|
+
items: allItems,
|
|
382
|
+
cursor: data?.continueCursor ?? null,
|
|
383
|
+
isDone: data?.isDone ?? false,
|
|
384
|
+
page: data?.page,
|
|
385
|
+
pageSize: data?.pageSize,
|
|
386
|
+
total: data?.total,
|
|
387
|
+
hasMore: !data?.isDone && !!data?.continueCursor,
|
|
388
|
+
loadMore,
|
|
389
|
+
refresh,
|
|
390
|
+
isLoading: query.isLoading
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
function useStorageList(limit = 20, offset = 0) {
|
|
394
|
+
const client = useArchlast();
|
|
395
|
+
return (0, import_react_query.useQuery)({
|
|
396
|
+
queryKey: ["storage", "list", limit, offset],
|
|
397
|
+
queryFn: () => client.storage.list(limit, offset)
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
function useStorageMetadata(id) {
|
|
401
|
+
const client = useArchlast();
|
|
402
|
+
return (0, import_react_query.useQuery)({
|
|
403
|
+
queryKey: ["storage", "file", id],
|
|
404
|
+
queryFn: () => client.storage.getMetadata(id),
|
|
405
|
+
enabled: !!id
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
function useStorageUpload() {
|
|
409
|
+
const client = useArchlast();
|
|
410
|
+
const queryClient = (0, import_react_query.useQueryClient)();
|
|
411
|
+
return (0, import_react_query.useMutation)({
|
|
412
|
+
mutationFn: (file) => client.storage.upload(file),
|
|
413
|
+
onSuccess: () => {
|
|
414
|
+
queryClient.invalidateQueries({ queryKey: ["storage", "list"] });
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
function useStorageDeleteFile() {
|
|
419
|
+
const client = useArchlast();
|
|
420
|
+
const queryClient = (0, import_react_query.useQueryClient)();
|
|
421
|
+
return (0, import_react_query.useMutation)({
|
|
422
|
+
mutationFn: (id) => client.storage.delete(id),
|
|
423
|
+
onSuccess: () => {
|
|
424
|
+
queryClient.invalidateQueries({ queryKey: ["storage", "list"] });
|
|
425
|
+
}
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
function useStorageHelpers() {
|
|
429
|
+
const client = useArchlast();
|
|
430
|
+
return {
|
|
431
|
+
getPublicUrl: (id) => client.storage.getPublicUrl(id)
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
435
|
+
0 && (module.exports = {
|
|
436
|
+
ArchlastContext,
|
|
437
|
+
ArchlastProvider,
|
|
438
|
+
useArchlast,
|
|
439
|
+
useAuth,
|
|
440
|
+
useClientPagination,
|
|
441
|
+
useDownload,
|
|
442
|
+
useMutation,
|
|
443
|
+
usePagination,
|
|
444
|
+
useQuery,
|
|
445
|
+
useRequestPasswordReset,
|
|
446
|
+
useResetPassword,
|
|
447
|
+
useStorageDelete,
|
|
448
|
+
useStorageDeleteFile,
|
|
449
|
+
useStorageHelpers,
|
|
450
|
+
useStorageList,
|
|
451
|
+
useStorageMetadata,
|
|
452
|
+
useStorageUpload,
|
|
453
|
+
useUpload
|
|
454
|
+
});
|
|
455
|
+
//# sourceMappingURL=react.cjs.map
|