@insforge/sdk 1.1.6 → 1.2.0-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/types.ts","../src/lib/http-client.ts","../src/lib/token-manager.ts","../src/modules/auth/helpers.ts","../src/modules/auth/auth.ts","../src/modules/database-postgrest.ts","../src/modules/storage.ts","../src/modules/ai.ts","../src/modules/functions.ts","../src/modules/realtime.ts","../src/modules/email.ts","../src/client.ts"],"sourcesContent":["/**\n * @insforge/sdk - TypeScript SDK for InsForge Backend-as-a-Service\n * \n * @packageDocumentation\n */\n\n// Main client\nexport { InsForgeClient } from './client';\n\n// Types\nexport type {\n InsForgeConfig,\n InsForgeConfig as ClientOptions, // Alias for compatibility\n TokenStorage,\n AuthSession,\n ApiError,\n} from './types';\n\nexport { InsForgeError } from './types';\n\n// Re-export shared schemas that SDK users will need\nexport type {\n UserSchema,\n CreateUserRequest,\n CreateSessionRequest,\n AuthErrorResponse,\n} from '@insforge/shared-schemas';\n\n// Re-export auth module for advanced usage\nexport { Auth } from './modules/auth/auth';\n\n// Re-export database module (using postgrest-js)\nexport { Database } from './modules/database-postgrest';\n// Note: QueryBuilder is no longer exported as we use postgrest-js QueryBuilder internally\n\n// Re-export storage module and types\nexport { Storage, StorageBucket } from './modules/storage';\nexport type { StorageResponse } from './modules/storage';\n\n// Re-export AI module\nexport { AI } from './modules/ai';\n\n// Re-export Functions module\nexport { Functions } from './modules/functions';\nexport type { FunctionInvokeOptions } from './modules/functions';\n\n// Re-export Emails module (Resend-compatible API)\nexport { Emails } from './modules/email';\nexport type { SendEmailOptions, SendEmailResponse } from './modules/email';\n\n// Re-export Realtime module and types\nexport { Realtime } from './modules/realtime';\nexport type {\n RealtimeErrorPayload,\n SubscribeResponse,\n SocketMessage,\n ConnectionState,\n EventCallback,\n} from './modules/realtime';\n\n// Re-export utilities for advanced usage\nexport { HttpClient } from './lib/http-client';\nexport { TokenManager } from './lib/token-manager';\n\n// Factory function for creating clients (Supabase-style)\nimport { InsForgeClient } from './client';\nimport { InsForgeConfig } from './types';\n\nexport function createClient(config: InsForgeConfig): InsForgeClient {\n return new InsForgeClient(config);\n}\n\n// Default export for convenience\nexport default InsForgeClient;\n","/**\n * InsForge SDK Types - only SDK-specific types here\n * Use @insforge/shared-schemas directly for API types\n */\n\nimport type { UserSchema } from '@insforge/shared-schemas';\n\nexport interface InsForgeConfig {\n /**\n * The base URL of the InsForge backend API\n * @default \"http://localhost:7130\"\n */\n baseUrl?: string;\n\n /**\n * Anonymous API key (optional)\n * Used for public/unauthenticated requests when no user token is set\n */\n anonKey?: string;\n\n /**\n * Edge Function Token (optional)\n * Use this when running in edge functions/serverless with a user's JWT token\n * This token will be used for all authenticated requests\n */\n edgeFunctionToken?: string;\n\n /**\n * Direct URL to Deno Subhosting functions (optional)\n * When provided, SDK will try this URL first for function invocations.\n * Falls back to proxy URL if subhosting returns 404.\n * @example \"https://{appKey}.functions.insforge.app\"\n */\n functionsUrl?: string;\n\n /**\n * Custom fetch implementation (useful for Node.js environments)\n */\n fetch?: typeof fetch;\n\n /**\n * Storage adapter for persisting tokens\n */\n storage?: TokenStorage;\n\n /**\n * Whether to automatically refresh tokens before they expire\n * @default true\n */\n autoRefreshToken?: boolean;\n\n /**\n * Whether to persist session in storage\n * @default true\n */\n persistSession?: boolean;\n\n /**\n * Custom headers to include with every request\n */\n headers?: Record<string, string>;\n}\n\nexport interface TokenStorage {\n getItem(key: string): string | null | Promise<string | null>;\n setItem(key: string, value: string): void | Promise<void>;\n removeItem(key: string): void | Promise<void>;\n}\n\nexport interface AuthSession {\n user: UserSchema;\n accessToken: string;\n expiresAt?: Date;\n}\n\nexport interface ApiError {\n error: string;\n message: string;\n statusCode: number;\n nextActions?: string;\n}\n\nexport class InsForgeError extends Error {\n public statusCode: number;\n public error: string;\n public nextActions?: string;\n\n constructor(message: string, statusCode: number, error: string, nextActions?: string) {\n super(message);\n this.name = 'InsForgeError';\n this.statusCode = statusCode;\n this.error = error;\n this.nextActions = nextActions;\n }\n\n static fromApiError(apiError: ApiError): InsForgeError {\n return new InsForgeError(\n apiError.message,\n apiError.statusCode,\n apiError.error,\n apiError.nextActions\n );\n }\n}","import { InsForgeConfig, ApiError, InsForgeError } from '../types';\n\nexport interface RequestOptions extends RequestInit {\n params?: Record<string, string>;\n}\n\nexport class HttpClient {\n public readonly baseUrl: string;\n public readonly fetch: typeof fetch;\n private defaultHeaders: Record<string, string>;\n private anonKey: string | undefined;\n private userToken: string | null = null;\n\n constructor(config: InsForgeConfig) {\n this.baseUrl = config.baseUrl || 'http://localhost:7130';\n // Properly bind fetch to maintain its context\n this.fetch = config.fetch || (globalThis.fetch ? globalThis.fetch.bind(globalThis) : undefined as any);\n this.anonKey = config.anonKey;\n this.defaultHeaders = {\n ...config.headers,\n };\n\n if (!this.fetch) {\n throw new Error(\n 'Fetch is not available. Please provide a fetch implementation in the config.'\n );\n }\n }\n\n private buildUrl(path: string, params?: Record<string, string>): string {\n const url = new URL(path, this.baseUrl);\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n // For select parameter, preserve the exact formatting by normalizing whitespace\n // This ensures PostgREST relationship queries work correctly\n if (key === 'select') {\n // Normalize multiline select strings for PostgREST:\n // 1. Replace all whitespace (including newlines) with single space\n // 2. Remove spaces inside parentheses for proper PostgREST syntax\n // 3. Keep spaces after commas at the top level for readability\n let normalizedValue = value.replace(/\\s+/g, ' ').trim();\n\n // Fix spaces around parentheses and inside them\n normalizedValue = normalizedValue\n .replace(/\\s*\\(\\s*/g, '(') // Remove spaces around opening parens\n .replace(/\\s*\\)\\s*/g, ')') // Remove spaces around closing parens\n .replace(/\\(\\s+/g, '(') // Remove spaces after opening parens\n .replace(/\\s+\\)/g, ')') // Remove spaces before closing parens\n .replace(/,\\s+(?=[^()]*\\))/g, ','); // Remove spaces after commas inside parens\n \n url.searchParams.append(key, normalizedValue);\n } else {\n url.searchParams.append(key, value);\n }\n });\n }\n return url.toString();\n }\n\n async request<T>(\n method: string,\n path: string,\n options: RequestOptions = {}\n ): Promise<T> {\n const { params, headers = {}, body, ...fetchOptions } = options;\n \n const url = this.buildUrl(path, params);\n \n const requestHeaders: Record<string, string> = {\n ...this.defaultHeaders,\n };\n \n // Set Authorization header: prefer user token, fallback to anon key\n const authToken = this.userToken || this.anonKey;\n if (authToken) {\n requestHeaders['Authorization'] = `Bearer ${authToken}`;\n }\n \n // Handle body serialization\n let processedBody: any;\n if (body !== undefined) {\n // Check if body is FormData (for file uploads)\n if (typeof FormData !== 'undefined' && body instanceof FormData) {\n // Don't set Content-Type for FormData, let browser set it with boundary\n processedBody = body;\n } else {\n // JSON body\n if (method !== 'GET') {\n requestHeaders['Content-Type'] = 'application/json;charset=UTF-8';\n }\n processedBody = JSON.stringify(body);\n }\n }\n \n Object.assign(requestHeaders, headers);\n \n const response = await this.fetch(url, {\n method,\n headers: requestHeaders,\n body: processedBody,\n ...fetchOptions,\n });\n\n // Handle 204 No Content\n if (response.status === 204) {\n return undefined as T;\n }\n\n // Try to parse JSON response\n let data: any;\n const contentType = response.headers.get('content-type');\n // Check for any JSON content type (including PostgREST's vnd.pgrst.object+json)\n if (contentType?.includes('json')) {\n data = await response.json();\n } else {\n // For non-JSON responses, return text\n data = await response.text();\n }\n\n // Handle errors\n if (!response.ok) {\n if (data && typeof data === 'object' && 'error' in data) {\n // Add the HTTP status code if not already in the data\n if (!data.statusCode && !data.status) {\n data.statusCode = response.status;\n }\n const error = InsForgeError.fromApiError(data as ApiError);\n // Preserve all additional fields from the error response\n Object.keys(data).forEach(key => {\n if (key !== 'error' && key !== 'message' && key !== 'statusCode') {\n (error as any)[key] = data[key];\n }\n });\n throw error;\n }\n throw new InsForgeError(\n `Request failed: ${response.statusText}`,\n response.status,\n 'REQUEST_FAILED'\n );\n }\n\n return data as T;\n }\n\n get<T>(path: string, options?: RequestOptions): Promise<T> {\n return this.request<T>('GET', path, options);\n }\n\n post<T>(path: string, body?: any, options?: RequestOptions): Promise<T> {\n return this.request<T>('POST', path, { ...options, body });\n }\n\n put<T>(path: string, body?: any, options?: RequestOptions): Promise<T> {\n return this.request<T>('PUT', path, { ...options, body });\n }\n\n patch<T>(path: string, body?: any, options?: RequestOptions): Promise<T> {\n return this.request<T>('PATCH', path, { ...options, body });\n }\n\n delete<T>(path: string, options?: RequestOptions): Promise<T> {\n return this.request<T>('DELETE', path, options);\n }\n\n setAuthToken(token: string | null) {\n this.userToken = token;\n }\n\n getHeaders(): Record<string, string> {\n const headers = { ...this.defaultHeaders };\n \n // Include Authorization header if token is available (same logic as request method)\n const authToken = this.userToken || this.anonKey;\n if (authToken) {\n headers['Authorization'] = `Bearer ${authToken}`;\n }\n \n return headers;\n }\n}","/**\n * Token Manager for InsForge SDK\n * \n * Simple token storage that supports two modes:\n * - Memory mode (new backend): tokens stored in memory only, more secure\n * - Storage mode (legacy backend): tokens persisted in localStorage\n */\n\nimport type { UserSchema } from '@insforge/shared-schemas';\nimport type { AuthSession, TokenStorage } from '../types';\n\n// localStorage keys\nexport const TOKEN_KEY = 'insforge-auth-token';\nexport const USER_KEY = 'insforge-auth-user';\n\n// CSRF token cookie name\nexport const CSRF_TOKEN_COOKIE = 'insforge_csrf_token';\n\n/**\n * Get CSRF token from cookie\n * Used to include in X-CSRF-Token header for refresh requests\n */\nexport function getCsrfToken(): string | null {\n if (typeof document === 'undefined') return null;\n const match = document.cookie\n .split(';')\n .find(c => c.trim().startsWith(`${CSRF_TOKEN_COOKIE}=`));\n if (!match) return null;\n return match.split('=')[1] || null;\n}\n\n/**\n * Set CSRF token cookie\n * Called after login/register/refresh to store the CSRF token\n */\nexport function setCsrfToken(token: string): void {\n if (typeof document === 'undefined') return;\n const maxAge = 7 * 24 * 60 * 60; // 7 days (same as refresh token)\n const secure = (typeof window !== 'undefined' && window.location.protocol === 'https:') ? '; Secure' : '';\n document.cookie = `${CSRF_TOKEN_COOKIE}=${encodeURIComponent(token)}; path=/; max-age=${maxAge}; SameSite=Lax${secure}`;\n}\n\n/**\n * Clear CSRF token cookie\n * Called on logout\n */\nexport function clearCsrfToken(): void {\n if (typeof document === 'undefined') return;\n const secure = (typeof window !== 'undefined' && window.location.protocol === 'https:') ? '; Secure' : '';\n document.cookie = `${CSRF_TOKEN_COOKIE}=; path=/; max-age=0; SameSite=Lax${secure}`;\n}\n\nexport class TokenManager {\n // In-memory storage\n private accessToken: string | null = null;\n private user: UserSchema | null = null;\n\n // Persistent storage (for legacy backend)\n private storage: TokenStorage;\n\n // Mode: 'memory' (new backend) or 'storage' (legacy backend, default)\n private _mode: 'memory' | 'storage' = 'storage';\n\n // Callback for token changes (used by realtime to reconnect with new token)\n onTokenChange: (() => void) | null = null;\n\n constructor(storage?: TokenStorage) {\n if (storage) {\n // Use provided storage\n this.storage = storage;\n } else if (typeof window !== 'undefined' && window.localStorage) {\n // Browser: use localStorage\n this.storage = window.localStorage;\n } else {\n // Node.js: use in-memory storage\n const store = new Map<string, string>();\n this.storage = {\n getItem: (key: string) => store.get(key) || null,\n setItem: (key: string, value: string) => { store.set(key, value); },\n removeItem: (key: string) => { store.delete(key); }\n };\n }\n }\n\n /**\n * Get current mode\n */\n get mode(): 'memory' | 'storage' {\n return this._mode;\n }\n\n /**\n * Set mode to memory (new backend with cookies + memory)\n */\n setMemoryMode(): void {\n if (this._mode === 'storage') {\n // Clear localStorage when switching from storage to memory mode\n this.storage.removeItem(TOKEN_KEY);\n this.storage.removeItem(USER_KEY);\n }\n this._mode = 'memory';\n }\n\n /**\n * Set mode to storage (legacy backend with localStorage)\n * Also loads existing session from localStorage\n */\n setStorageMode(): void {\n this._mode = 'storage';\n this.loadFromStorage();\n }\n\n /**\n * Load session from localStorage\n */\n private loadFromStorage(): void {\n const token = this.storage.getItem(TOKEN_KEY) as string | null;\n const userStr = this.storage.getItem(USER_KEY) as string | null;\n\n if (token && userStr) {\n try {\n this.accessToken = token;\n this.user = JSON.parse(userStr);\n } catch {\n this.clearSession();\n }\n }\n }\n\n /**\n * Save session (memory always, localStorage only in storage mode)\n */\n saveSession(session: AuthSession): void {\n const tokenChanged = session.accessToken !== this.accessToken;\n this.accessToken = session.accessToken;\n this.user = session.user;\n\n // Persist to localStorage in storage mode\n if (this._mode === 'storage') {\n this.storage.setItem(TOKEN_KEY, session.accessToken);\n this.storage.setItem(USER_KEY, JSON.stringify(session.user));\n }\n\n if (tokenChanged && this.onTokenChange) {\n this.onTokenChange();\n }\n }\n\n /**\n * Get current session\n */\n getSession(): AuthSession | null {\n this.loadFromStorage();\n if (!this.accessToken || !this.user) return null;\n return {\n accessToken: this.accessToken,\n user: this.user,\n };\n }\n\n /**\n * Get access token\n */\n getAccessToken(): string | null {\n this.loadFromStorage();\n return this.accessToken;\n }\n\n /**\n * Set access token\n */\n setAccessToken(token: string): void {\n const tokenChanged = token !== this.accessToken;\n this.accessToken = token;\n if (this._mode === 'storage') {\n this.storage.setItem(TOKEN_KEY, token);\n }\n if (tokenChanged && this.onTokenChange) {\n this.onTokenChange();\n }\n }\n\n /**\n * Get user\n */\n getUser(): UserSchema | null {\n return this.user;\n }\n\n /**\n * Set user\n */\n setUser(user: UserSchema): void {\n this.user = user;\n if (this._mode === 'storage') {\n this.storage.setItem(USER_KEY, JSON.stringify(user));\n }\n }\n\n /**\n * Clear session (both memory and localStorage)\n */\n clearSession(): void {\n const hadToken = this.accessToken !== null;\n this.accessToken = null;\n this.user = null;\n this.storage.removeItem(TOKEN_KEY);\n this.storage.removeItem(USER_KEY);\n\n if (hadToken && this.onTokenChange) {\n this.onTokenChange();\n }\n }\n\n /**\n * Check if there's a session in localStorage (for legacy detection)\n */\n hasStoredSession(): boolean {\n const token = this.storage.getItem(TOKEN_KEY);\n return !!token;\n }\n}","/**\n * Auth module helper functions\n */\n\nimport { InsForgeError } from '../../types';\n\n// ============================================================================\n// PKCE (Proof Key for Code Exchange) - RFC 7636\n// ============================================================================\n\nconst PKCE_VERIFIER_KEY = 'insforge_pkce_verifier';\n\n/**\n * Base64 URL encode without padding (per RFC 7636)\n */\nfunction base64UrlEncode(buffer: Uint8Array): string {\n const base64 = btoa(String.fromCharCode(...buffer));\n return base64\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n}\n\n/**\n * Generate a cryptographically random code verifier for PKCE\n */\nexport function generateCodeVerifier(): string {\n const array = new Uint8Array(32);\n crypto.getRandomValues(array);\n return base64UrlEncode(array);\n}\n\n/**\n * Generate code challenge from verifier using SHA-256 (S256 method)\n */\nexport async function generateCodeChallenge(verifier: string): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(verifier);\n const hash = await crypto.subtle.digest('SHA-256', data);\n return base64UrlEncode(new Uint8Array(hash));\n}\n\n/**\n * Store PKCE code verifier in sessionStorage\n */\nexport function storePkceVerifier(verifier: string): void {\n if (typeof sessionStorage !== 'undefined') {\n sessionStorage.setItem(PKCE_VERIFIER_KEY, verifier);\n }\n}\n\n/**\n * Retrieve and clear PKCE code verifier from sessionStorage\n */\nexport function retrievePkceVerifier(): string | null {\n if (typeof sessionStorage === 'undefined') {\n return null;\n }\n const verifier = sessionStorage.getItem(PKCE_VERIFIER_KEY);\n if (verifier) {\n sessionStorage.removeItem(PKCE_VERIFIER_KEY);\n }\n return verifier;\n}\n\n// ============================================================================\n// Environment & Error Helpers\n// ============================================================================\n\n/**\n * Check if current environment is a hosted auth environment\n * Returns true for:\n * - localhost with port 7130 (hosted auth app dev)\n * - https://*.insforge.app (hosted auth app production)\n */\nexport function isHostedAuthEnvironment(): boolean {\n if (typeof window === 'undefined') {\n return false;\n }\n\n const { hostname, port, protocol } = window.location;\n\n if (hostname === 'localhost' && port === '7130') {\n return true;\n }\n\n if (protocol === 'https:' && hostname.endsWith('.insforge.app')) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Wrap an error into the standard { data, error } format\n * Passes through InsForgeError unchanged, wraps other errors\n */\nexport function wrapError<T>(\n error: unknown,\n fallbackMessage: string\n): { data: T | null; error: InsForgeError } {\n if (error instanceof InsForgeError) {\n return { data: null, error };\n }\n\n return {\n data: null,\n error: new InsForgeError(\n error instanceof Error ? error.message : fallbackMessage,\n 500,\n 'UNEXPECTED_ERROR'\n ),\n };\n}\n\n/**\n * Clean up URL parameters (removes sensitive data from URL after OAuth callback)\n */\nexport function cleanUrlParams(...params: string[]): void {\n if (typeof window === 'undefined') {\n return;\n }\n\n const url = new URL(window.location.href);\n params.forEach((p) => url.searchParams.delete(p));\n window.history.replaceState({}, document.title, url.toString());\n}\n","/**\n * Auth module for InsForge SDK\n * Handles authentication, sessions, profiles, and email verification\n */\n\nimport { HttpClient } from '../../lib/http-client';\nimport { TokenManager, getCsrfToken, setCsrfToken, clearCsrfToken } from '../../lib/token-manager';\nimport { AuthSession, InsForgeError } from '../../types';\nimport {\n generateCodeVerifier,\n generateCodeChallenge,\n storePkceVerifier,\n retrievePkceVerifier,\n isHostedAuthEnvironment,\n wrapError,\n cleanUrlParams,\n} from './helpers';\n\nimport type {\n CreateUserRequest,\n CreateUserResponse,\n CreateSessionRequest,\n CreateSessionResponse,\n GetOauthUrlResponse,\n GetPublicAuthConfigResponse,\n OAuthProvidersSchema,\n SendVerificationEmailRequest,\n SendResetPasswordEmailRequest,\n ExchangeResetPasswordTokenRequest,\n VerifyEmailRequest,\n VerifyEmailResponse,\n UserSchema,\n GetProfileResponse,\n OAuthCodeExchangeRequest,\n} from '@insforge/shared-schemas';\n\nexport class Auth {\n private authCallbackHandled: Promise<void>;\n\n constructor(\n private http: HttpClient,\n private tokenManager: TokenManager\n ) {\n this.authCallbackHandled = this.detectAuthCallback();\n }\n\n /**\n * Save session from API response\n * Handles token storage, CSRF token, and HTTP client auth header\n */\n private saveSessionFromResponse(response: {\n accessToken?: string | null;\n user?: UserSchema;\n csrfToken?: string | null;\n }): boolean {\n if (!response.accessToken || !response.user) {\n return false;\n }\n\n const session: AuthSession = {\n accessToken: response.accessToken,\n user: response.user,\n };\n\n if (response.csrfToken) {\n this.tokenManager.setMemoryMode();\n setCsrfToken(response.csrfToken);\n }\n\n this.tokenManager.saveSession(session);\n this.http.setAuthToken(response.accessToken);\n return true;\n }\n\n // ============================================================================\n // OAuth Callback Detection (runs on initialization)\n // ============================================================================\n\n /**\n * Detect and handle OAuth callback parameters in URL\n * Supports PKCE flow (insforge_code) and legacy flow (access_token in URL)\n */\n private async detectAuthCallback(): Promise<void> {\n if (typeof window === 'undefined') return;\n\n try {\n const params = new URLSearchParams(window.location.search);\n\n // Handle error callback\n const error = params.get('error');\n if (error) {\n cleanUrlParams('error');\n console.debug('OAuth callback error:', error);\n return;\n }\n\n // PKCE flow: exchange code for tokens\n const code = params.get('insforge_code');\n if (code) {\n cleanUrlParams('insforge_code');\n const { error: exchangeError } = await this.exchangeOAuthCode(code);\n if (exchangeError) {\n console.debug('OAuth code exchange failed:', exchangeError.message);\n }\n return;\n }\n\n // Legacy flow: tokens directly in URL (backward compatible)\n const accessToken = params.get('access_token');\n const userId = params.get('user_id');\n const email = params.get('email');\n\n if (accessToken && userId && email) {\n const csrfToken = params.get('csrf_token');\n const name = params.get('name');\n\n if (csrfToken) {\n this.tokenManager.setMemoryMode();\n setCsrfToken(csrfToken);\n }\n\n const session: AuthSession = {\n accessToken,\n user: {\n id: userId,\n email,\n profile: { name: name || '' },\n metadata: null,\n emailVerified: false,\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n },\n };\n\n this.tokenManager.saveSession(session);\n this.http.setAuthToken(accessToken);\n cleanUrlParams('access_token', 'user_id', 'email', 'name', 'csrf_token');\n }\n } catch (error) {\n console.debug('OAuth callback detection skipped:', error);\n }\n }\n\n // ============================================================================\n // Sign Up / Sign In / Sign Out\n // ============================================================================\n\n async signUp(request: CreateUserRequest): Promise<{\n data: CreateUserResponse | null;\n error: InsForgeError | null;\n }> {\n try {\n const response = await this.http.post<CreateUserResponse>(\n '/api/auth/users',\n request,\n { credentials: 'include' }\n );\n\n if (response.accessToken && response.user) {\n this.saveSessionFromResponse(response);\n }\n\n return { data: response, error: null };\n } catch (error) {\n return wrapError(error, 'An unexpected error occurred during sign up');\n }\n }\n\n async signInWithPassword(request: CreateSessionRequest): Promise<{\n data: CreateSessionResponse | null;\n error: InsForgeError | null;\n }> {\n try {\n const response = await this.http.post<CreateSessionResponse>(\n '/api/auth/sessions',\n request,\n { credentials: 'include' }\n );\n\n this.saveSessionFromResponse(response);\n return { data: response, error: null };\n } catch (error) {\n return wrapError(error, 'An unexpected error occurred during sign in');\n }\n }\n\n async signOut(): Promise<{ error: InsForgeError | null }> {\n try {\n // Try backend logout (may fail for legacy backends)\n try {\n await this.http.post('/api/auth/logout', undefined, { credentials: 'include' });\n } catch {\n // Ignore - legacy backend may not have this endpoint\n }\n\n this.tokenManager.clearSession();\n this.http.setAuthToken(null);\n clearCsrfToken();\n\n return { error: null };\n } catch {\n return { error: new InsForgeError('Failed to sign out', 500, 'SIGNOUT_ERROR') };\n }\n }\n\n // ============================================================================\n // OAuth Authentication\n // ============================================================================\n\n /**\n * Sign in with OAuth provider using PKCE flow\n */\n async signInWithOAuth(options: {\n provider: OAuthProvidersSchema;\n redirectTo?: string;\n skipBrowserRedirect?: boolean;\n }): Promise<{\n data: { url?: string; provider?: string; codeVerifier?: string };\n error: InsForgeError | null;\n }> {\n try {\n const { provider, redirectTo, skipBrowserRedirect } = options;\n\n const codeVerifier = generateCodeVerifier();\n const codeChallenge = await generateCodeChallenge(codeVerifier);\n storePkceVerifier(codeVerifier);\n\n const params: Record<string, string> = { code_challenge: codeChallenge };\n if (redirectTo) params.redirect_uri = redirectTo;\n\n const response = await this.http.get<GetOauthUrlResponse>(\n `/api/auth/oauth/${provider}`,\n { params }\n );\n\n if (typeof window !== 'undefined' && !skipBrowserRedirect) {\n window.location.href = response.authUrl;\n return { data: {}, error: null };\n }\n\n return {\n data: { url: response.authUrl, provider, codeVerifier },\n error: null,\n };\n } catch (error) {\n if (error instanceof InsForgeError) {\n return { data: {}, error };\n }\n return {\n data: {},\n error: new InsForgeError(\n 'An unexpected error occurred during OAuth initialization',\n 500,\n 'UNEXPECTED_ERROR'\n ),\n };\n }\n }\n\n /**\n * Exchange OAuth authorization code for tokens (PKCE flow)\n * Called automatically on initialization when insforge_code is in URL\n */\n async exchangeOAuthCode(\n code: string,\n codeVerifier?: string\n ): Promise<{\n data: { accessToken: string; user: UserSchema; redirectTo?: string } | null;\n error: InsForgeError | null;\n }> {\n try {\n const verifier = codeVerifier ?? retrievePkceVerifier();\n\n if (!verifier) {\n return {\n data: null,\n error: new InsForgeError(\n 'PKCE code verifier not found. Ensure signInWithOAuth was called in the same browser session.',\n 400,\n 'PKCE_VERIFIER_MISSING'\n ),\n };\n }\n\n const request: OAuthCodeExchangeRequest = { code, code_verifier: verifier };\n const response = await this.http.post<{\n accessToken: string;\n user: UserSchema;\n csrfToken?: string;\n redirectTo?: string;\n }>('/api/auth/oauth/exchange', request, { credentials: 'include' });\n\n this.saveSessionFromResponse(response);\n\n return {\n data: {\n accessToken: response.accessToken,\n user: response.user,\n redirectTo: response.redirectTo,\n },\n error: null,\n };\n } catch (error) {\n return wrapError(error, 'An unexpected error occurred during OAuth code exchange');\n }\n }\n\n /**\n * Sign in with an ID token from a native SDK (Google One Tap, etc.)\n * Use this for native mobile apps or Google One Tap on web.\n *\n * @param credentials.provider - The identity provider (currently only 'google' is supported)\n * @param credentials.token - The ID token from the native SDK\n */\n async signInWithIdToken(credentials: {\n provider: 'google';\n token: string;\n }): Promise<{\n data: { accessToken: string; refreshToken?: string; user: UserSchema } | null;\n error: InsForgeError | null;\n }> {\n try {\n const { provider, token } = credentials;\n\n const response = await this.http.post<{\n accessToken: string;\n refreshToken?: string;\n user: UserSchema;\n csrfToken?: string | null;\n }>('/api/auth/id-token?client_type=mobile', { provider, token }, { credentials: 'include' });\n\n this.saveSessionFromResponse(response);\n\n return {\n data: {\n accessToken: response.accessToken,\n refreshToken: response.refreshToken,\n user: response.user,\n },\n error: null,\n };\n } catch (error) {\n return wrapError(error, 'An unexpected error occurred during ID token sign in');\n }\n }\n\n // ============================================================================\n // Session Management\n // ============================================================================\n\n /**\n * Get current session, automatically waits for pending OAuth callback\n * @deprecated Use `getCurrentUser` instead\n */\n async getCurrentSession(): Promise<{\n data: { session: AuthSession | null };\n error: InsForgeError | null;\n }> {\n await this.authCallbackHandled;\n\n try {\n // Check memory first\n const session = this.tokenManager.getSession();\n if (session) {\n this.http.setAuthToken(session.accessToken);\n return { data: { session }, error: null };\n }\n\n // Try refresh via httpOnly cookie (browser only)\n if (typeof window !== 'undefined') {\n try {\n const csrfToken = getCsrfToken();\n const response = await this.http.post<{\n accessToken: string;\n user?: UserSchema;\n csrfToken?: string;\n }>('/api/auth/refresh', undefined, {\n headers: csrfToken ? { 'X-CSRF-Token': csrfToken } : {},\n credentials: 'include',\n });\n\n if (response.accessToken) {\n this.tokenManager.setMemoryMode();\n this.tokenManager.setAccessToken(response.accessToken);\n this.http.setAuthToken(response.accessToken);\n\n if (response.user) this.tokenManager.setUser(response.user);\n if (response.csrfToken) setCsrfToken(response.csrfToken);\n\n return { data: { session: this.tokenManager.getSession() }, error: null };\n }\n } catch (error) {\n if (error instanceof InsForgeError) {\n if (error.statusCode === 404) {\n // Legacy backend - try localStorage\n this.tokenManager.setStorageMode();\n const session = this.tokenManager.getSession();\n if (session?.accessToken) {\n+ this.http.setAuthToken(session.accessToken);\n }\n return { data: { session }, error: null };\n }\n return { data: { session: null }, error };\n }\n }\n }\n\n return { data: { session: null }, error: null };\n } catch (error) {\n if (error instanceof InsForgeError) {\n return { data: { session: null }, error };\n }\n return {\n data: { session: null },\n error: new InsForgeError(\n 'An unexpected error occurred while getting session',\n 500,\n 'UNEXPECTED_ERROR'\n ),\n };\n }\n }\n\n /**\n * Get current user, automatically waits for pending OAuth callback\n */\n async getCurrentUser(): Promise<{\n data: { user: UserSchema | null };\n error: InsForgeError | null;\n }> {\n await this.authCallbackHandled;\n\n if (isHostedAuthEnvironment()) {\n return { data: { user: null }, error: null };\n }\n\n try {\n // Check memory first\n const session = this.tokenManager.getSession();\n if (session) {\n this.http.setAuthToken(session.accessToken);\n return { data: { user: session.user }, error: null };\n }\n\n // Try refresh via httpOnly cookie (browser only)\n if (typeof window !== 'undefined') {\n try {\n const csrfToken = getCsrfToken();\n const response = await this.http.post<{\n accessToken: string;\n user?: UserSchema;\n csrfToken?: string;\n }>('/api/auth/refresh', undefined, {\n headers: csrfToken ? { 'X-CSRF-Token': csrfToken } : {},\n credentials: 'include',\n });\n\n if (response.accessToken) {\n this.tokenManager.setMemoryMode();\n this.tokenManager.setAccessToken(response.accessToken);\n this.http.setAuthToken(response.accessToken);\n\n if (response.user) this.tokenManager.setUser(response.user);\n if (response.csrfToken) setCsrfToken(response.csrfToken);\n\n return { data: { user: response.user ?? null }, error: null };\n }\n } catch (error) {\n if (error instanceof InsForgeError) {\n if (error.statusCode === 404) {\n // Legacy backend - try localStorage\n this.tokenManager.setStorageMode();\n const session = this.tokenManager.getSession();\n if (session?.accessToken) {\n+ this.http.setAuthToken(session.accessToken);\n }\n return { data: { user: session?.user ?? null }, error: null };\n }\n return { data: { user: null }, error };\n }\n }\n }\n\n return { data: { user: null }, error: null };\n } catch (error) {\n if (error instanceof InsForgeError) {\n return { data: { user: null }, error };\n }\n return {\n data: { user: null },\n error: new InsForgeError(\n 'An unexpected error occurred while getting user',\n 500,\n 'UNEXPECTED_ERROR'\n ),\n };\n }\n }\n\n // ============================================================================\n // Profile Management\n // ============================================================================\n\n async getProfile(userId: string): Promise<{\n data: GetProfileResponse | null;\n error: InsForgeError | null;\n }> {\n try {\n const response = await this.http.get<GetProfileResponse>(`/api/auth/profiles/${userId}`);\n return { data: response, error: null };\n } catch (error) {\n return wrapError(error, 'An unexpected error occurred while fetching user profile');\n }\n }\n\n async setProfile(profile: Record<string, unknown>): Promise<{\n data: GetProfileResponse | null;\n error: InsForgeError | null;\n }> {\n try {\n const response = await this.http.patch<GetProfileResponse>(\n '/api/auth/profiles/current',\n { profile }\n );\n\n const currentUser = this.tokenManager.getUser();\n if (currentUser && response.profile !== undefined) {\n this.tokenManager.setUser({ ...currentUser, profile: response.profile });\n }\n\n return { data: response, error: null };\n } catch (error) {\n return wrapError(error, 'An unexpected error occurred while updating user profile');\n }\n }\n\n // ============================================================================\n // Email Verification\n // ============================================================================\n\n async resendVerificationEmail(request: SendVerificationEmailRequest): Promise<{\n data: { success: boolean; message: string } | null;\n error: InsForgeError | null;\n }> {\n try {\n const response = await this.http.post<{ success: boolean; message: string }>(\n '/api/auth/email/send-verification',\n request\n );\n return { data: response, error: null };\n } catch (error) {\n return wrapError(error, 'An unexpected error occurred while sending verification code');\n }\n }\n\n /** @deprecated Use `resendVerificationEmail` instead */\n async sendVerificationEmail(request: SendVerificationEmailRequest) {\n return this.resendVerificationEmail(request);\n }\n\n async verifyEmail(request: VerifyEmailRequest): Promise<{\n data: VerifyEmailResponse | null;\n error: InsForgeError | null;\n }> {\n try {\n const response = await this.http.post<VerifyEmailResponse>(\n '/api/auth/email/verify',\n request,\n { credentials: 'include' }\n );\n\n this.saveSessionFromResponse(response);\n return { data: response, error: null };\n } catch (error) {\n return wrapError(error, 'An unexpected error occurred while verifying email');\n }\n }\n\n // ============================================================================\n // Password Reset\n // ============================================================================\n\n async sendResetPasswordEmail(request: SendResetPasswordEmailRequest): Promise<{\n data: { success: boolean; message: string } | null;\n error: InsForgeError | null;\n }> {\n try {\n const response = await this.http.post<{ success: boolean; message: string }>(\n '/api/auth/email/send-reset-password',\n request\n );\n return { data: response, error: null };\n } catch (error) {\n return wrapError(error, 'An unexpected error occurred while sending password reset code');\n }\n }\n\n async exchangeResetPasswordToken(request: ExchangeResetPasswordTokenRequest): Promise<{\n data: { token: string; expiresAt: string } | null;\n error: InsForgeError | null;\n }> {\n try {\n const response = await this.http.post<{ token: string; expiresAt: string }>(\n '/api/auth/email/exchange-reset-password-token',\n request\n );\n return { data: response, error: null };\n } catch (error) {\n return wrapError(error, 'An unexpected error occurred while verifying reset code');\n }\n }\n\n async resetPassword(request: { newPassword: string; otp: string }): Promise<{\n data: { message: string; redirectTo?: string } | null;\n error: InsForgeError | null;\n }> {\n try {\n const response = await this.http.post<{ message: string; redirectTo?: string }>(\n '/api/auth/email/reset-password',\n request\n );\n return { data: response, error: null };\n } catch (error) {\n return wrapError(error, 'An unexpected error occurred while resetting password');\n }\n }\n\n // ============================================================================\n // Configuration\n // ============================================================================\n\n async getPublicAuthConfig(): Promise<{\n data: GetPublicAuthConfigResponse | null;\n error: InsForgeError | null;\n }> {\n try {\n const response = await this.http.get<GetPublicAuthConfigResponse>('/api/auth/public-config');\n return { data: response, error: null };\n } catch (error) {\n return wrapError(error, 'An unexpected error occurred while fetching auth configuration');\n }\n }\n}\n","/**\n * Database module using @supabase/postgrest-js\n * Complete replacement for custom QueryBuilder with full PostgREST features\n */\n\nimport { PostgrestClient } from '@supabase/postgrest-js';\nimport { HttpClient } from '../lib/http-client';\nimport { TokenManager } from '../lib/token-manager';\n\n\n/**\n * Custom fetch that transforms URLs and adds auth\n */\nfunction createInsForgePostgrestFetch(\n httpClient: HttpClient,\n tokenManager: TokenManager\n): typeof fetch {\n return async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const url = typeof input === 'string' ? input : input.toString();\n const urlObj = new URL(url);\n\n // Extract pathname (remove leading /)\n // postgrest-js sends: http://dummy/tablename?params for tables\n // postgrest-js sends: http://dummy/rpc/functionname?params for RPC\n const pathname = urlObj.pathname.slice(1);\n\n // Route to appropriate InsForge endpoint\n const rpcMatch = pathname.match(/^rpc\\/(.+)$/);\n const endpoint = rpcMatch\n ? `/api/database/rpc/${rpcMatch[1]}`\n : `/api/database/records/${pathname}`;\n\n const insforgeUrl = `${httpClient.baseUrl}${endpoint}${urlObj.search}`;\n \n // Get auth token from TokenManager or HttpClient\n const token = tokenManager.getAccessToken();\n const httpHeaders = httpClient.getHeaders();\n const authToken = token || httpHeaders['Authorization']?.replace('Bearer ', '');\n \n // Prepare headers\n const headers = new Headers(init?.headers);\n if (authToken && !headers.has('Authorization')) {\n headers.set('Authorization', `Bearer ${authToken}`);\n }\n \n // Make the actual request using native fetch\n const response = await fetch(insforgeUrl, {\n ...init,\n headers\n });\n \n return response;\n };\n}\n\n/**\n * Database client using postgrest-js\n * Drop-in replacement with FULL PostgREST capabilities\n */\nexport class Database {\n private postgrest: PostgrestClient<any, any, any>;\n \n constructor(httpClient: HttpClient, tokenManager: TokenManager) {\n // Create postgrest client with custom fetch\n this.postgrest = new PostgrestClient<any, any, any>('http://dummy', {\n fetch: createInsForgePostgrestFetch(httpClient, tokenManager),\n headers: {}\n });\n }\n \n /**\n * Create a query builder for a table\n * \n * @example\n * // Basic query\n * const { data, error } = await client.database\n * .from('posts')\n * .select('*')\n * .eq('user_id', userId);\n * \n * // With count (Supabase style!)\n * const { data, error, count } = await client.database\n * .from('posts')\n * .select('*', { count: 'exact' })\n * .range(0, 9);\n * \n * // Just get count, no data\n * const { count } = await client.database\n * .from('posts')\n * .select('*', { count: 'exact', head: true });\n * \n * // Complex queries with OR\n * const { data } = await client.database\n * .from('posts')\n * .select('*, users!inner(*)')\n * .or('status.eq.active,status.eq.pending');\n * \n * // All features work:\n * - Nested selects\n * - Foreign key expansion \n * - OR/AND/NOT conditions\n * - Count with head\n * - Range pagination\n * - Upserts\n */\n from(table: string) {\n // Return postgrest query builder with all features\n return this.postgrest.from(table);\n }\n\n /**\n * Call a PostgreSQL function (RPC)\n *\n * @example\n * // Call a function with parameters\n * const { data, error } = await client.database\n * .rpc('get_user_stats', { user_id: 123 });\n *\n * // Call a function with no parameters\n * const { data, error } = await client.database\n * .rpc('get_all_active_users');\n *\n * // With options (head, count, get)\n * const { data, count } = await client.database\n * .rpc('search_posts', { query: 'hello' }, { count: 'exact' });\n */\n rpc(\n fn: string,\n args?: Record<string, unknown>,\n options?: { head?: boolean; get?: boolean; count?: 'exact' | 'planned' | 'estimated' }\n ) {\n return this.postgrest.rpc(fn, args, options);\n }\n}","/**\n * Storage module for InsForge SDK\n * Handles file uploads, downloads, and bucket management\n */\n\nimport { HttpClient } from '../lib/http-client';\nimport { InsForgeError } from '../types';\nimport type { \n StorageFileSchema,\n ListObjectsResponseSchema\n} from '@insforge/shared-schemas';\n\nexport interface StorageResponse<T> {\n data: T | null;\n error: InsForgeError | null;\n}\n\ninterface UploadStrategy {\n method: 'direct' | 'presigned';\n uploadUrl: string;\n fields?: Record<string, string>;\n key: string;\n confirmRequired: boolean;\n confirmUrl?: string;\n expiresAt?: Date;\n}\n\ninterface DownloadStrategy {\n method: 'direct' | 'presigned';\n url: string;\n expiresAt?: Date;\n}\n\n/**\n * Storage bucket operations\n */\nexport class StorageBucket {\n constructor(\n private bucketName: string,\n private http: HttpClient\n ) {}\n\n /**\n * Upload a file with a specific key\n * Uses the upload strategy from backend (direct or presigned)\n * @param path - The object key/path\n * @param file - File or Blob to upload\n */\n async upload(\n path: string,\n file: File | Blob\n ): Promise<StorageResponse<StorageFileSchema>> {\n try {\n // Get upload strategy from backend - this is required\n const strategyResponse = await this.http.post<UploadStrategy>(\n `/api/storage/buckets/${this.bucketName}/upload-strategy`,\n {\n filename: path,\n contentType: file.type || 'application/octet-stream',\n size: file.size\n }\n );\n\n // Use presigned URL if available\n if (strategyResponse.method === 'presigned') {\n return await this.uploadWithPresignedUrl(strategyResponse, file);\n }\n\n // Use direct upload if strategy says so\n if (strategyResponse.method === 'direct') {\n const formData = new FormData();\n formData.append('file', file);\n\n const response = await this.http.request<StorageFileSchema>(\n 'PUT',\n `/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}`,\n {\n body: formData as any,\n headers: {\n // Don't set Content-Type, let browser set multipart boundary\n }\n }\n );\n\n return { data: response, error: null };\n }\n\n throw new InsForgeError(\n `Unsupported upload method: ${strategyResponse.method}`,\n 500,\n 'STORAGE_ERROR'\n );\n } catch (error) {\n return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'Upload failed',\n 500,\n 'STORAGE_ERROR'\n )\n };\n }\n }\n\n /**\n * Upload a file with auto-generated key\n * Uses the upload strategy from backend (direct or presigned)\n * @param file - File or Blob to upload\n */\n async uploadAuto(\n file: File | Blob\n ): Promise<StorageResponse<StorageFileSchema>> {\n try {\n const filename = file instanceof File ? file.name : 'file';\n \n // Get upload strategy from backend - this is required\n const strategyResponse = await this.http.post<UploadStrategy>(\n `/api/storage/buckets/${this.bucketName}/upload-strategy`,\n {\n filename,\n contentType: file.type || 'application/octet-stream',\n size: file.size\n }\n );\n\n // Use presigned URL if available\n if (strategyResponse.method === 'presigned') {\n return await this.uploadWithPresignedUrl(strategyResponse, file);\n }\n\n // Use direct upload if strategy says so\n if (strategyResponse.method === 'direct') {\n const formData = new FormData();\n formData.append('file', file);\n\n const response = await this.http.request<StorageFileSchema>(\n 'POST',\n `/api/storage/buckets/${this.bucketName}/objects`,\n {\n body: formData as any,\n headers: {\n // Don't set Content-Type, let browser set multipart boundary\n }\n }\n );\n\n return { data: response, error: null };\n }\n\n throw new InsForgeError(\n `Unsupported upload method: ${strategyResponse.method}`,\n 500,\n 'STORAGE_ERROR'\n );\n } catch (error) {\n return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'Upload failed',\n 500,\n 'STORAGE_ERROR'\n )\n };\n }\n }\n\n /**\n * Internal method to handle presigned URL uploads\n */\n private async uploadWithPresignedUrl(\n strategy: UploadStrategy,\n file: File | Blob\n ): Promise<StorageResponse<StorageFileSchema>> {\n try {\n // Upload to presigned URL (e.g., S3)\n const formData = new FormData();\n \n // Add all fields from the presigned URL\n if (strategy.fields) {\n Object.entries(strategy.fields).forEach(([key, value]) => {\n formData.append(key, value);\n });\n }\n \n // File must be the last field for S3\n formData.append('file', file);\n\n const uploadResponse = await fetch(strategy.uploadUrl, {\n method: 'POST',\n body: formData\n });\n\n if (!uploadResponse.ok) {\n throw new InsForgeError(\n `Upload to storage failed: ${uploadResponse.statusText}`,\n uploadResponse.status,\n 'STORAGE_ERROR'\n );\n }\n\n // Confirm upload with backend if required\n if (strategy.confirmRequired && strategy.confirmUrl) {\n const confirmResponse = await this.http.post<StorageFileSchema>(\n strategy.confirmUrl,\n {\n size: file.size,\n contentType: file.type || 'application/octet-stream'\n }\n );\n\n return { data: confirmResponse, error: null };\n }\n\n // If no confirmation required, return basic file info\n return {\n data: {\n key: strategy.key,\n bucket: this.bucketName,\n size: file.size,\n mimeType: file.type || 'application/octet-stream',\n uploadedAt: new Date().toISOString(),\n url: this.getPublicUrl(strategy.key)\n } as StorageFileSchema,\n error: null\n };\n } catch (error) {\n throw error instanceof InsForgeError ? error : new InsForgeError(\n 'Presigned upload failed',\n 500,\n 'STORAGE_ERROR'\n );\n }\n }\n\n /**\n * Download a file\n * Uses the download strategy from backend (direct or presigned)\n * @param path - The object key/path\n * Returns the file as a Blob\n */\n async download(path: string): Promise<{ data: Blob | null; error: InsForgeError | null }> {\n try {\n // Get download strategy from backend - this is required\n const strategyResponse = await this.http.post<DownloadStrategy>(\n `/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}/download-strategy`,\n { expiresIn: 3600 }\n );\n\n // Use URL from strategy\n const downloadUrl = strategyResponse.url;\n \n // Download from the URL\n const headers: HeadersInit = {};\n \n // Only add auth header for direct downloads (not presigned URLs)\n if (strategyResponse.method === 'direct') {\n Object.assign(headers, this.http.getHeaders());\n }\n \n const response = await fetch(downloadUrl, {\n method: 'GET',\n headers\n });\n\n if (!response.ok) {\n try {\n const error = await response.json();\n throw InsForgeError.fromApiError(error);\n } catch {\n throw new InsForgeError(\n `Download failed: ${response.statusText}`,\n response.status,\n 'STORAGE_ERROR'\n );\n }\n }\n\n const blob = await response.blob();\n return { data: blob, error: null };\n } catch (error) {\n return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'Download failed',\n 500,\n 'STORAGE_ERROR'\n )\n };\n }\n }\n\n /**\n * Get public URL for a file\n * @param path - The object key/path\n */\n getPublicUrl(path: string): string {\n return `${this.http.baseUrl}/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}`;\n }\n\n /**\n * List objects in the bucket\n * @param prefix - Filter by key prefix\n * @param search - Search in file names\n * @param limit - Maximum number of results (default: 100, max: 1000)\n * @param offset - Number of results to skip\n */\n async list(options?: {\n prefix?: string;\n search?: string;\n limit?: number;\n offset?: number;\n }): Promise<StorageResponse<ListObjectsResponseSchema>> {\n try {\n const params: Record<string, string> = {};\n \n if (options?.prefix) params.prefix = options.prefix;\n if (options?.search) params.search = options.search;\n if (options?.limit) params.limit = options.limit.toString();\n if (options?.offset) params.offset = options.offset.toString();\n\n const response = await this.http.get<ListObjectsResponseSchema>(\n `/api/storage/buckets/${this.bucketName}/objects`,\n { params }\n );\n\n return { data: response, error: null };\n } catch (error) {\n return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'List failed',\n 500,\n 'STORAGE_ERROR'\n )\n };\n }\n }\n\n /**\n * Delete a file\n * @param path - The object key/path\n */\n async remove(path: string): Promise<StorageResponse<{ message: string }>> {\n try {\n const response = await this.http.delete<{ message: string }>(\n `/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}`\n );\n\n return { data: response, error: null };\n } catch (error) {\n return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'Delete failed',\n 500,\n 'STORAGE_ERROR'\n )\n };\n }\n }\n}\n\n/**\n * Storage module for file operations\n */\nexport class Storage {\n constructor(private http: HttpClient) {}\n\n /**\n * Get a bucket instance for operations\n * @param bucketName - Name of the bucket\n */\n from(bucketName: string): StorageBucket {\n return new StorageBucket(bucketName, this.http);\n }\n}","/**\n * AI Module for Insforge SDK\n * Response format roughly matches OpenAI SDK for compatibility\n *\n * The backend handles all the complexity of different AI providers\n * and returns a unified format. This SDK transforms responses to match OpenAI-like format.\n */\n\nimport { HttpClient } from \"../lib/http-client\";\nimport {\n ChatCompletionRequest,\n ChatCompletionResponse,\n ImageGenerationRequest,\n ImageGenerationResponse,\n EmbeddingsRequest,\n EmbeddingsResponse,\n} from \"@insforge/shared-schemas\";\n\nexport class AI {\n public readonly chat: Chat;\n public readonly images: Images;\n public readonly embeddings: Embeddings;\n\n constructor(private http: HttpClient) {\n this.chat = new Chat(http);\n this.images = new Images(http);\n this.embeddings = new Embeddings(http);\n }\n}\n\nclass Chat {\n public readonly completions: ChatCompletions;\n\n constructor(http: HttpClient) {\n this.completions = new ChatCompletions(http);\n }\n}\n\nclass ChatCompletions {\n constructor(private http: HttpClient) {}\n\n /**\n * Create a chat completion - OpenAI-like response format\n *\n * @example\n * ```typescript\n * // Non-streaming\n * const completion = await client.ai.chat.completions.create({\n * model: 'gpt-4',\n * messages: [{ role: 'user', content: 'Hello!' }]\n * });\n * console.log(completion.choices[0].message.content);\n *\n * // With images (OpenAI-compatible format)\n * const response = await client.ai.chat.completions.create({\n * model: 'gpt-4-vision',\n * messages: [{\n * role: 'user',\n * content: [\n * { type: 'text', text: 'What is in this image?' },\n * { type: 'image_url', image_url: { url: 'https://example.com/image.jpg' } }\n * ]\n * }]\n * });\n *\n * // With PDF files\n * const pdfResponse = await client.ai.chat.completions.create({\n * model: 'anthropic/claude-3.5-sonnet',\n * messages: [{\n * role: 'user',\n * content: [\n * { type: 'text', text: 'Summarize this document' },\n * { type: 'file', file: { filename: 'doc.pdf', file_data: 'https://example.com/doc.pdf' } }\n * ]\n * }],\n * fileParser: { enabled: true, pdf: { engine: 'mistral-ocr' } }\n * });\n *\n * // With web search\n * const searchResponse = await client.ai.chat.completions.create({\n * model: 'openai/gpt-4',\n * messages: [{ role: 'user', content: 'What are the latest news about AI?' }],\n * webSearch: { enabled: true, maxResults: 5 }\n * });\n * // Access citations from response.choices[0].message.annotations\n *\n * // With thinking/reasoning mode (Anthropic models)\n * const thinkingResponse = await client.ai.chat.completions.create({\n * model: 'anthropic/claude-3.5-sonnet',\n * messages: [{ role: 'user', content: 'Solve this complex math problem...' }],\n * thinking: true\n * });\n *\n * // Streaming - returns async iterable\n * const stream = await client.ai.chat.completions.create({\n * model: 'gpt-4',\n * messages: [{ role: 'user', content: 'Tell me a story' }],\n * stream: true\n * });\n *\n * for await (const chunk of stream) {\n * if (chunk.choices[0]?.delta?.content) {\n * process.stdout.write(chunk.choices[0].delta.content);\n * }\n * }\n * ```\n */\n async create(params: ChatCompletionRequest): Promise<any> {\n // Backend already expects camelCase, no transformation needed\n const backendParams = {\n model: params.model,\n messages: params.messages,\n temperature: params.temperature,\n maxTokens: params.maxTokens,\n topP: params.topP,\n stream: params.stream,\n // New plugin options\n webSearch: params.webSearch,\n fileParser: params.fileParser,\n thinking: params.thinking,\n // Tool calling options\n tools: params.tools,\n toolChoice: params.toolChoice,\n parallelToolCalls: params.parallelToolCalls,\n };\n\n // For streaming, return an async iterable that yields OpenAI-like chunks\n if (params.stream) {\n const headers = this.http.getHeaders();\n headers[\"Content-Type\"] = \"application/json\";\n\n const response = await this.http.fetch(\n `${this.http.baseUrl}/api/ai/chat/completion`,\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(backendParams),\n }\n );\n\n if (!response.ok) {\n const error = await response.json();\n throw new Error(error.error || \"Stream request failed\");\n }\n\n // Return async iterable that parses SSE and transforms to OpenAI-like format\n return this.parseSSEStream(response, params.model);\n }\n\n // Non-streaming: transform response to OpenAI-like format\n const response: ChatCompletionResponse = await this.http.post(\n \"/api/ai/chat/completion\",\n backendParams\n );\n\n // Transform to OpenAI-like format\n const content = response.text || \"\";\n\n return {\n id: `chatcmpl-${Date.now()}`,\n object: \"chat.completion\",\n created: Math.floor(Date.now() / 1000),\n model: response.metadata?.model,\n choices: [\n {\n index: 0,\n message: {\n role: \"assistant\",\n content,\n // Include tool_calls if present (from tool calling)\n ...(response.tool_calls?.length && { tool_calls: response.tool_calls }),\n // Include annotations if present (from web search or file parsing)\n ...(response.annotations?.length && { annotations: response.annotations }),\n },\n finish_reason: response.tool_calls?.length ? \"tool_calls\" : \"stop\",\n },\n ],\n usage: response.metadata?.usage || {\n prompt_tokens: 0,\n completion_tokens: 0,\n total_tokens: 0,\n },\n };\n }\n\n /**\n * Parse SSE stream into async iterable of OpenAI-like chunks\n */\n private async *parseSSEStream(\n response: Response,\n model: string\n ): AsyncIterableIterator<any> {\n const reader = response.body!.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() || \"\";\n\n for (const line of lines) {\n if (line.startsWith(\"data: \")) {\n const dataStr = line.slice(6).trim();\n if (dataStr) {\n try {\n const data = JSON.parse(dataStr);\n\n // Transform to OpenAI-like streaming format\n if (data.chunk || data.content) {\n yield {\n id: `chatcmpl-${Date.now()}`,\n object: \"chat.completion.chunk\",\n created: Math.floor(Date.now() / 1000),\n model,\n choices: [\n {\n index: 0,\n delta: {\n content: data.chunk || data.content,\n },\n finish_reason: null,\n },\n ],\n };\n }\n\n // Yield tool_calls when received from stream\n if (data.tool_calls?.length) {\n yield {\n id: `chatcmpl-${Date.now()}`,\n object: \"chat.completion.chunk\",\n created: Math.floor(Date.now() / 1000),\n model,\n choices: [\n {\n index: 0,\n delta: {\n tool_calls: data.tool_calls,\n },\n finish_reason: \"tool_calls\",\n },\n ],\n };\n }\n\n // If we received the done signal, we can stop\n if (data.done) {\n reader.releaseLock();\n return;\n }\n } catch (e) {\n // Skip invalid JSON\n console.warn(\"Failed to parse SSE data:\", dataStr);\n }\n }\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n}\n\nclass Embeddings {\n constructor(private http: HttpClient) {}\n\n /**\n * Create embeddings for text input - OpenAI-like response format\n *\n * @example\n * ```typescript\n * // Single text input\n * const response = await client.ai.embeddings.create({\n * model: 'openai/text-embedding-3-small',\n * input: 'Hello world'\n * });\n * console.log(response.data[0].embedding); // number[]\n *\n * // Multiple text inputs\n * const response = await client.ai.embeddings.create({\n * model: 'openai/text-embedding-3-small',\n * input: ['Hello world', 'Goodbye world']\n * });\n * response.data.forEach((item, i) => {\n * console.log(`Embedding ${i}:`, item.embedding.slice(0, 5)); // First 5 dimensions\n * });\n *\n * // With custom dimensions (if supported by model)\n * const response = await client.ai.embeddings.create({\n * model: 'openai/text-embedding-3-small',\n * input: 'Hello world',\n * dimensions: 256\n * });\n *\n * // With base64 encoding format\n * const response = await client.ai.embeddings.create({\n * model: 'openai/text-embedding-3-small',\n * input: 'Hello world',\n * encoding_format: 'base64'\n * });\n * ```\n */\n async create(params: EmbeddingsRequest): Promise<any> {\n const response: EmbeddingsResponse = await this.http.post(\n \"/api/ai/embeddings\",\n params\n );\n\n // Return OpenAI-compatible format\n return {\n object: response.object,\n data: response.data,\n model: response.metadata?.model,\n usage: response.metadata?.usage\n ? {\n prompt_tokens: response.metadata.usage.promptTokens || 0,\n total_tokens: response.metadata.usage.totalTokens || 0,\n }\n : {\n prompt_tokens: 0,\n total_tokens: 0,\n },\n };\n }\n}\n\nclass Images {\n constructor(private http: HttpClient) {}\n\n /**\n * Generate images - OpenAI-like response format\n *\n * @example\n * ```typescript\n * // Text-to-image\n * const response = await client.ai.images.generate({\n * model: 'dall-e-3',\n * prompt: 'A sunset over mountains',\n * });\n * console.log(response.images[0].url);\n *\n * // Image-to-image (with input images)\n * const response = await client.ai.images.generate({\n * model: 'stable-diffusion-xl',\n * prompt: 'Transform this into a watercolor painting',\n * images: [\n * { url: 'https://example.com/input.jpg' },\n * // or base64-encoded Data URI:\n * { url: 'data:image/jpeg;base64,/9j/4AAQ...' }\n * ]\n * });\n * ```\n */\n async generate(params: ImageGenerationRequest): Promise<any> {\n const response: ImageGenerationResponse = await this.http.post(\n \"/api/ai/image/generation\",\n params\n );\n \n // Build data array based on response content\n let data: Array<{ b64_json?: string; content?: string }> = [];\n \n if (response.images && response.images.length > 0) {\n // Has images - extract base64 and include text\n data = response.images.map(img => ({\n b64_json: img.imageUrl.replace(/^data:image\\/\\w+;base64,/, ''),\n content: response.text\n }));\n } else if (response.text) {\n // Text-only response\n data = [{ content: response.text }];\n }\n \n // Return OpenAI-compatible format\n return {\n created: Math.floor(Date.now() / 1000),\n data,\n ...(response.metadata?.usage && {\n usage: {\n total_tokens: response.metadata.usage.totalTokens || 0,\n input_tokens: response.metadata.usage.promptTokens || 0,\n output_tokens: response.metadata.usage.completionTokens || 0,\n }\n })\n };\n }\n}\n","import { HttpClient } from '../lib/http-client';\n\nexport interface FunctionInvokeOptions {\n /**\n * The body of the request\n */\n body?: any;\n\n /**\n * Custom headers to send with the request\n */\n headers?: Record<string, string>;\n\n /**\n * HTTP method (default: POST)\n */\n method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n}\n\n/**\n * Edge Functions client for invoking serverless functions\n *\n * @example\n * ```typescript\n * // Invoke a function with JSON body\n * const { data, error } = await client.functions.invoke('hello-world', {\n * body: { name: 'World' }\n * });\n *\n * // GET request\n * const { data, error } = await client.functions.invoke('get-data', {\n * method: 'GET'\n * });\n * ```\n */\nexport class Functions {\n private http: HttpClient;\n private functionsUrl: string | undefined;\n\n constructor(http: HttpClient, functionsUrl?: string) {\n this.http = http;\n this.functionsUrl = functionsUrl || Functions.deriveSubhostingUrl(http.baseUrl);\n }\n\n /**\n * Derive the subhosting URL from the base URL.\n * Base URL pattern: https://{appKey}.{region}.insforge.app\n * Functions URL: https://{appKey}.functions.insforge.app\n * Only applies to .insforge.app domains.\n */\n private static deriveSubhostingUrl(baseUrl: string): string | undefined {\n try {\n const { hostname } = new URL(baseUrl);\n if (!hostname.endsWith('.insforge.app')) return undefined;\n const appKey = hostname.split('.')[0];\n return `https://${appKey}.functions.insforge.app`;\n } catch {\n return undefined;\n }\n }\n\n /**\n * Invokes an Edge Function\n *\n * If functionsUrl is configured, tries direct subhosting first.\n * Falls back to proxy URL if subhosting returns 404.\n *\n * @param slug The function slug to invoke\n * @param options Request options\n */\n async invoke<T = any>(\n slug: string,\n options: FunctionInvokeOptions = {}\n ): Promise<{ data: T | null; error: Error | null }> {\n const { method = 'POST', body, headers = {} } = options;\n\n // Try direct subhosting URL first if configured\n if (this.functionsUrl) {\n try {\n const data = await this.http.request<T>(method, `${this.functionsUrl}/${slug}`, {\n body,\n headers,\n });\n return { data, error: null };\n } catch (error: any) {\n // If 404, fall through to proxy\n if (error?.statusCode === 404) {\n // Function not found on subhosting, try proxy\n } else {\n // Other errors, return immediately\n return { data: null, error };\n }\n }\n }\n\n // Fall back to proxy URL\n try {\n const path = `/functions/${slug}`;\n const data = await this.http.request<T>(method, path, { body, headers });\n return { data, error: null };\n } catch (error: any) {\n return { data: null, error };\n }\n }\n}","import { io, Socket } from 'socket.io-client';\nimport type { SubscribeResponse, RealtimeErrorPayload, SocketMessage } from '@insforge/shared-schemas';\nimport { TokenManager } from '../lib/token-manager';\n\nexport type { SubscribeResponse, RealtimeErrorPayload, SocketMessage };\n\nexport type ConnectionState = 'disconnected' | 'connecting' | 'connected';\n\nexport type EventCallback<T = unknown> = (payload: T) => void;\n\nconst CONNECT_TIMEOUT = 10000;\n\n/**\n * Realtime module for subscribing to channels and handling real-time events\n *\n * @example\n * ```typescript\n * const { realtime } = client;\n *\n * // Connect to the realtime server\n * await realtime.connect();\n *\n * // Subscribe to a channel\n * const response = await realtime.subscribe('orders:123');\n * if (!response.ok) {\n * console.error('Failed to subscribe:', response.error);\n * }\n *\n * // Listen for specific events\n * realtime.on('order_updated', (payload) => {\n * console.log('Order updated:', payload);\n * });\n *\n * // Listen for connection events\n * realtime.on('connect', () => console.log('Connected!'));\n * realtime.on('connect_error', (err) => console.error('Connection failed:', err));\n * realtime.on('disconnect', (reason) => console.log('Disconnected:', reason));\n * realtime.on('error', (error) => console.error('Realtime error:', error));\n *\n * // Publish a message to a channel\n * await realtime.publish('orders:123', 'status_changed', { status: 'shipped' });\n *\n * // Unsubscribe and disconnect when done\n * realtime.unsubscribe('orders:123');\n * realtime.disconnect();\n * ```\n */\nexport class Realtime {\n private baseUrl: string;\n private tokenManager: TokenManager;\n private socket: Socket | null = null;\n private connectPromise: Promise<void> | null = null;\n private subscribedChannels: Set<string> = new Set();\n private eventListeners: Map<string, Set<EventCallback>> = new Map();\n private anonKey?: string;\n\n constructor(baseUrl: string, tokenManager: TokenManager, anonKey?: string) {\n this.baseUrl = baseUrl;\n this.tokenManager = tokenManager;\n this.anonKey = anonKey;\n\n // Handle token changes (e.g., after refresh)\n this.tokenManager.onTokenChange = () => this.onTokenChange();\n }\n\n private notifyListeners(event: string, payload?: unknown): void {\n const listeners = this.eventListeners.get(event);\n if (!listeners) return;\n for (const cb of listeners) {\n try {\n cb(payload);\n } catch (err) {\n console.error(`Error in ${event} callback:`, err);\n }\n }\n }\n\n /**\n * Connect to the realtime server\n * @returns Promise that resolves when connected\n */\n connect(): Promise<void> {\n // Already connected\n if (this.socket?.connected) {\n return Promise.resolve();\n }\n\n // Connection already in progress, return existing promise\n if (this.connectPromise) {\n return this.connectPromise;\n }\n\n this.connectPromise = new Promise((resolve, reject) => {\n const session = this.tokenManager.getSession();\n const token = session?.accessToken ?? this.anonKey;\n \n\n this.socket = io(this.baseUrl, {\n transports: ['websocket'],\n auth: token ? { token } : undefined,\n });\n\n let initialConnection = true;\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n const cleanup = () => {\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n };\n\n timeoutId = setTimeout(() => {\n if (initialConnection) {\n initialConnection = false;\n this.connectPromise = null;\n this.socket?.disconnect();\n this.socket = null;\n reject(new Error(`Connection timeout after ${CONNECT_TIMEOUT}ms`));\n }\n }, CONNECT_TIMEOUT);\n\n this.socket.on('connect', () => {\n cleanup();\n // Re-subscribe to channels on every connect (initial + reconnects)\n for (const channel of this.subscribedChannels) {\n this.socket!.emit('realtime:subscribe', { channel });\n }\n this.notifyListeners('connect');\n\n if (initialConnection) {\n initialConnection = false;\n this.connectPromise = null;\n resolve();\n }\n });\n\n this.socket.on('connect_error', (error: Error) => {\n cleanup();\n this.notifyListeners('connect_error', error);\n\n if (initialConnection) {\n initialConnection = false;\n this.connectPromise = null;\n reject(error);\n }\n });\n\n this.socket.on('disconnect', (reason: string) => {\n this.notifyListeners('disconnect', reason);\n });\n\n this.socket.on('realtime:error', (error: RealtimeErrorPayload) => {\n this.notifyListeners('error', error);\n });\n\n // Route custom events to listeners (onAny doesn't catch socket reserved events)\n this.socket.onAny((event: string, message: SocketMessage) => {\n if (event === 'realtime:error') return; // Already handled above\n this.notifyListeners(event, message);\n });\n });\n\n return this.connectPromise;\n }\n\n /**\n * Disconnect from the realtime server\n */\n disconnect(): void {\n if (this.socket) {\n this.socket.disconnect();\n this.socket = null;\n }\n this.subscribedChannels.clear();\n }\n\n /**\n * Handle token changes (e.g., after auth refresh)\n * Updates socket auth so reconnects use the new token\n * If connected, triggers reconnect to apply new token immediately\n */\n private onTokenChange(): void {\n const token = this.tokenManager.getAccessToken() ?? this.anonKey;\n\n // Always update auth so socket.io auto-reconnect uses new token\n if (this.socket) {\n this.socket.auth = token ? { token } : {};\n }\n\n // Trigger reconnect if connected OR connecting (to avoid completing with stale token)\n if (this.socket && (this.socket.connected || this.connectPromise)) {\n this.socket.disconnect();\n this.socket.connect();\n // Note: on('connect') handler automatically re-subscribes to channels\n }\n }\n\n /**\n * Check if connected to the realtime server\n */\n get isConnected(): boolean {\n return this.socket?.connected ?? false;\n }\n\n /**\n * Get the current connection state\n */\n get connectionState(): ConnectionState {\n if (!this.socket) return 'disconnected';\n if (this.socket.connected) return 'connected';\n return 'connecting';\n }\n\n /**\n * Get the socket ID (if connected)\n */\n get socketId(): string | undefined {\n return this.socket?.id;\n }\n\n /**\n * Subscribe to a channel\n *\n * Automatically connects if not already connected.\n *\n * @param channel - Channel name (e.g., 'orders:123', 'broadcast')\n * @returns Promise with the subscription response\n */\n async subscribe(channel: string): Promise<SubscribeResponse> {\n // Already subscribed, return success\n if (this.subscribedChannels.has(channel)) {\n return { ok: true, channel };\n }\n\n // Auto-connect if not connected\n if (!this.socket?.connected) {\n try {\n await this.connect();\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Connection failed';\n return { ok: false, channel, error: { code: 'CONNECTION_FAILED', message } };\n }\n }\n\n return new Promise((resolve) => {\n this.socket!.emit('realtime:subscribe', { channel }, (response: SubscribeResponse) => {\n if (response.ok) {\n this.subscribedChannels.add(channel);\n }\n resolve(response);\n });\n });\n }\n\n /**\n * Unsubscribe from a channel (fire-and-forget)\n *\n * @param channel - Channel name to unsubscribe from\n */\n unsubscribe(channel: string): void {\n this.subscribedChannels.delete(channel);\n\n if (this.socket?.connected) {\n this.socket.emit('realtime:unsubscribe', { channel });\n }\n }\n\n /**\n * Publish a message to a channel\n *\n * @param channel - Channel name\n * @param event - Event name\n * @param payload - Message payload\n */\n async publish<T = unknown>(channel: string, event: string, payload: T): Promise<void> {\n if (!this.socket?.connected) {\n throw new Error('Not connected to realtime server. Call connect() first.');\n }\n\n this.socket!.emit('realtime:publish', { channel, event, payload });\n }\n\n /**\n * Listen for events\n *\n * Reserved event names:\n * - 'connect' - Fired when connected to the server\n * - 'connect_error' - Fired when connection fails (payload: Error)\n * - 'disconnect' - Fired when disconnected (payload: reason string)\n * - 'error' - Fired when a realtime error occurs (payload: RealtimeErrorPayload)\n *\n * All other events receive a `SocketMessage` payload with metadata.\n *\n * @param event - Event name to listen for\n * @param callback - Callback function when event is received\n */\n on<T = SocketMessage>(event: string, callback: EventCallback<T>): void {\n if (!this.eventListeners.has(event)) {\n this.eventListeners.set(event, new Set());\n }\n this.eventListeners.get(event)!.add(callback as EventCallback);\n }\n\n /**\n * Remove a listener for a specific event\n *\n * @param event - Event name\n * @param callback - The callback function to remove\n */\n off<T = SocketMessage>(event: string, callback: EventCallback<T>): void {\n const listeners = this.eventListeners.get(event);\n if (listeners) {\n listeners.delete(callback as EventCallback);\n if (listeners.size === 0) {\n this.eventListeners.delete(event);\n }\n }\n }\n\n /**\n * Listen for an event only once, then automatically remove the listener\n *\n * @param event - Event name to listen for\n * @param callback - Callback function when event is received\n */\n once<T = SocketMessage>(event: string, callback: EventCallback<T>): void {\n const wrapper: EventCallback<T> = (payload: T) => {\n this.off(event, wrapper);\n callback(payload);\n };\n this.on(event, wrapper);\n }\n\n /**\n * Get all currently subscribed channels\n *\n * @returns Array of channel names\n */\n getSubscribedChannels(): string[] {\n return Array.from(this.subscribedChannels);\n }\n}\n","import { HttpClient } from '../lib/http-client';\nimport type { SendRawEmailRequest, SendEmailResponse } from '@insforge/shared-schemas';\n\nexport type { SendRawEmailRequest as SendEmailOptions, SendEmailResponse } from '@insforge/shared-schemas';\n\n/**\n * Emails client for sending custom emails\n *\n * @example\n * ```typescript\n * // Send a simple email\n * const { data, error } = await client.emails.send({\n * to: 'user@example.com',\n * subject: 'Welcome!',\n * html: '<h1>Welcome to our platform</h1>'\n * });\n *\n * if (error) {\n * console.error('Failed to send:', error.message);\n * return;\n * }\n * // Email sent successfully - data is {} (empty object)\n *\n * // Send to multiple recipients with CC\n * const { data, error } = await client.emails.send({\n * to: ['user1@example.com', 'user2@example.com'],\n * cc: 'manager@example.com',\n * subject: 'Team Update',\n * html: '<p>Here is the latest update...</p>',\n * replyTo: 'support@example.com'\n * });\n * ```\n */\nexport class Emails {\n private http: HttpClient;\n\n constructor(http: HttpClient) {\n this.http = http;\n }\n\n /**\n * Send a custom HTML email\n * @param options Email options including recipients, subject, and HTML content\n */\n async send(\n options: SendRawEmailRequest\n ): Promise<{ data: SendEmailResponse | null; error: Error | null }> {\n try {\n const data = await this.http.post<SendEmailResponse>(\n '/api/email/send-raw',\n options\n );\n\n return { data, error: null };\n } catch (error: unknown) {\n const normalizedError = error instanceof Error ? error : new Error(String(error));\n return { data: null, error: normalizedError };\n }\n }\n}\n","import { InsForgeConfig } from './types';\nimport { HttpClient } from './lib/http-client';\nimport { TokenManager } from './lib/token-manager';\nimport { Auth } from './modules/auth/auth';\nimport { Database } from './modules/database-postgrest';\nimport { Storage } from './modules/storage';\nimport { AI } from './modules/ai';\nimport { Functions } from './modules/functions';\nimport { Realtime } from './modules/realtime';\nimport { Emails } from './modules/email';\n\n/**\n * Main InsForge SDK Client\n * \n * @example\n * ```typescript\n * import { InsForgeClient } from '@insforge/sdk';\n * \n * const client = new InsForgeClient({\n * baseUrl: 'http://localhost:7130'\n * });\n * \n * // Authentication\n * const { data, error } = await client.auth.signUp({\n * email: 'user@example.com',\n * password: 'password123',\n * name: 'John Doe'\n * });\n * \n * // Database operations\n * const { data, error } = await client.database\n * .from('posts')\n * .select('*')\n * .eq('user_id', session.user.id)\n * .order('created_at', { ascending: false })\n * .limit(10);\n * \n * // Insert data\n * const { data: newPost } = await client.database\n * .from('posts')\n * .insert({ title: 'Hello', content: 'World' })\n * .single();\n * \n * // Invoke edge functions\n * const { data, error } = await client.functions.invoke('my-function', {\n * body: { message: 'Hello from SDK' }\n * });\n * ```\n */\nexport class InsForgeClient {\n private http: HttpClient;\n private tokenManager: TokenManager;\n public readonly auth: Auth;\n public readonly database: Database;\n public readonly storage: Storage;\n public readonly ai: AI;\n public readonly functions: Functions;\n public readonly realtime: Realtime;\n public readonly emails: Emails;\n\n constructor(config: InsForgeConfig = {}) {\n this.http = new HttpClient(config);\n this.tokenManager = new TokenManager(config.storage);\n\n // Check for edge function token\n if (config.edgeFunctionToken) {\n this.http.setAuthToken(config.edgeFunctionToken);\n this.tokenManager.saveSession({\n accessToken: config.edgeFunctionToken,\n user: {} as any,\n });\n }\n\n // Check for existing session\n // In secure mode: try to refresh to get access token\n // In local mode: check localStorage\n const existingSession = this.tokenManager.getSession();\n if (existingSession?.accessToken) {\n this.http.setAuthToken(existingSession.accessToken);\n }\n\n this.auth = new Auth(this.http, this.tokenManager);\n this.database = new Database(this.http, this.tokenManager);\n this.storage = new Storage(this.http);\n this.ai = new AI(this.http);\n this.functions = new Functions(this.http, config.functionsUrl);\n this.realtime = new Realtime(this.http.baseUrl, this.tokenManager, config.anonKey);\n this.emails = new Emails(this.http);\n }\n\n /**\n * Get the underlying HTTP client for custom requests\n * \n * @example\n * ```typescript\n * const httpClient = client.getHttpClient();\n * const customData = await httpClient.get('/api/custom-endpoint');\n * ```\n */\n getHttpClient(): HttpClient {\n return this.http;\n }\n\n /**\n * Future modules will be added here:\n * - database: Database operations\n * - storage: File storage operations\n * - functions: Serverless functions\n * - tables: Table management\n * - metadata: Backend metadata\n */\n}\n"],"mappings":"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","names":["session","response"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/types.ts","../src/lib/http-client.ts","../src/lib/token-manager.ts","../src/modules/auth/helpers.ts","../src/modules/auth/auth.ts","../src/modules/database-postgrest.ts","../src/modules/storage.ts","../src/modules/ai.ts","../src/modules/functions.ts","../src/modules/realtime.ts","../src/modules/email.ts","../src/client.ts"],"sourcesContent":["/**\n * @insforge/sdk - TypeScript SDK for InsForge Backend-as-a-Service\n * \n * @packageDocumentation\n */\n\n// Main client\nexport { InsForgeClient } from './client';\n\n// Types\nexport type {\n InsForgeConfig,\n InsForgeConfig as ClientOptions, // Alias for compatibility\n AuthSession,\n ApiError,\n} from './types';\n\nexport { InsForgeError } from './types';\n\n// Re-export shared schemas that SDK users will need\nexport type {\n UserSchema,\n CreateUserRequest,\n CreateSessionRequest,\n AuthErrorResponse,\n} from '@insforge/shared-schemas';\n\n// Re-export auth module for advanced usage\nexport { Auth } from './modules/auth/auth';\n\n// Re-export database module (using postgrest-js)\nexport { Database } from './modules/database-postgrest';\n// Note: QueryBuilder is no longer exported as we use postgrest-js QueryBuilder internally\n\n// Re-export storage module and types\nexport { Storage, StorageBucket } from './modules/storage';\nexport type { StorageResponse } from './modules/storage';\n\n// Re-export AI module\nexport { AI } from './modules/ai';\n\n// Re-export Functions module\nexport { Functions } from './modules/functions';\nexport type { FunctionInvokeOptions } from './modules/functions';\n\n// Re-export Emails module (Resend-compatible API)\nexport { Emails } from './modules/email';\nexport type { SendEmailOptions, SendEmailResponse } from './modules/email';\n\n// Re-export Realtime module and types\nexport { Realtime } from './modules/realtime';\nexport type {\n RealtimeErrorPayload,\n SubscribeResponse,\n SocketMessage,\n ConnectionState,\n EventCallback,\n} from './modules/realtime';\n\n// Re-export utilities for advanced usage\nexport { HttpClient } from './lib/http-client';\nexport { TokenManager } from './lib/token-manager';\n\n// Factory function for creating clients (Supabase-style)\nimport { InsForgeClient } from './client';\nimport { InsForgeConfig } from './types';\n\nexport function createClient(config: InsForgeConfig): InsForgeClient {\n return new InsForgeClient(config);\n}\n\n// Default export for convenience\nexport default InsForgeClient;\n","/**\n * InsForge SDK Types - only SDK-specific types here\n * Use @insforge/shared-schemas directly for API types\n */\n\nimport type { UserSchema } from '@insforge/shared-schemas';\n\nexport interface InsForgeConfig {\n /**\n * The base URL of the InsForge backend API\n * @default \"http://localhost:7130\"\n */\n baseUrl?: string;\n\n /**\n * Anonymous API key (optional)\n * Used for public/unauthenticated requests when no user token is set\n */\n anonKey?: string;\n\n /**\n * Edge Function Token (optional)\n * Use this when running in edge functions/serverless with a user's JWT token\n * This token will be used for all authenticated requests\n */\n edgeFunctionToken?: string;\n\n /**\n * Direct URL to Deno Subhosting functions (optional)\n * When provided, SDK will try this URL first for function invocations.\n * Falls back to proxy URL if subhosting returns 404.\n * @example \"https://{appKey}.functions.insforge.app\"\n */\n functionsUrl?: string;\n\n /**\n * Custom fetch implementation (useful for Node.js environments)\n */\n fetch?: typeof fetch;\n\n /**\n * Enable server-side auth mode (SSR/Node runtime)\n * In this mode auth endpoints use `client_type=mobile` and refresh_token body flow.\n * @default false\n */\n isServerMode?: boolean;\n\n /**\n * Custom headers to include with every request\n */\n headers?: Record<string, string>;\n}\n\nexport interface AuthSession {\n user: UserSchema;\n accessToken: string;\n expiresAt?: Date;\n}\n\nexport interface ApiError {\n error: string;\n message: string;\n statusCode: number;\n nextActions?: string;\n}\n\nexport class InsForgeError extends Error {\n public statusCode: number;\n public error: string;\n public nextActions?: string;\n\n constructor(message: string, statusCode: number, error: string, nextActions?: string) {\n super(message);\n this.name = 'InsForgeError';\n this.statusCode = statusCode;\n this.error = error;\n this.nextActions = nextActions;\n }\n\n static fromApiError(apiError: ApiError): InsForgeError {\n return new InsForgeError(\n apiError.message,\n apiError.statusCode,\n apiError.error,\n apiError.nextActions\n );\n }\n}\n","import { InsForgeConfig, ApiError, InsForgeError } from '../types';\n\nexport interface RequestOptions extends RequestInit {\n params?: Record<string, string>;\n}\n\nexport class HttpClient {\n public readonly baseUrl: string;\n public readonly fetch: typeof fetch;\n private defaultHeaders: Record<string, string>;\n private anonKey: string | undefined;\n private userToken: string | null = null;\n\n constructor(config: InsForgeConfig) {\n this.baseUrl = config.baseUrl || 'http://localhost:7130';\n // Properly bind fetch to maintain its context\n this.fetch = config.fetch || (globalThis.fetch ? globalThis.fetch.bind(globalThis) : undefined as any);\n this.anonKey = config.anonKey;\n this.defaultHeaders = {\n ...config.headers,\n };\n\n if (!this.fetch) {\n throw new Error(\n 'Fetch is not available. Please provide a fetch implementation in the config.'\n );\n }\n }\n\n private buildUrl(path: string, params?: Record<string, string>): string {\n const url = new URL(path, this.baseUrl);\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n // For select parameter, preserve the exact formatting by normalizing whitespace\n // This ensures PostgREST relationship queries work correctly\n if (key === 'select') {\n // Normalize multiline select strings for PostgREST:\n // 1. Replace all whitespace (including newlines) with single space\n // 2. Remove spaces inside parentheses for proper PostgREST syntax\n // 3. Keep spaces after commas at the top level for readability\n let normalizedValue = value.replace(/\\s+/g, ' ').trim();\n\n // Fix spaces around parentheses and inside them\n normalizedValue = normalizedValue\n .replace(/\\s*\\(\\s*/g, '(') // Remove spaces around opening parens\n .replace(/\\s*\\)\\s*/g, ')') // Remove spaces around closing parens\n .replace(/\\(\\s+/g, '(') // Remove spaces after opening parens\n .replace(/\\s+\\)/g, ')') // Remove spaces before closing parens\n .replace(/,\\s+(?=[^()]*\\))/g, ','); // Remove spaces after commas inside parens\n \n url.searchParams.append(key, normalizedValue);\n } else {\n url.searchParams.append(key, value);\n }\n });\n }\n return url.toString();\n }\n\n async request<T>(\n method: string,\n path: string,\n options: RequestOptions = {}\n ): Promise<T> {\n const { params, headers = {}, body, ...fetchOptions } = options;\n \n const url = this.buildUrl(path, params);\n \n const requestHeaders: Record<string, string> = {\n ...this.defaultHeaders,\n };\n \n // Set Authorization header: prefer user token, fallback to anon key\n const authToken = this.userToken || this.anonKey;\n if (authToken) {\n requestHeaders['Authorization'] = `Bearer ${authToken}`;\n }\n \n // Handle body serialization\n let processedBody: any;\n if (body !== undefined) {\n // Check if body is FormData (for file uploads)\n if (typeof FormData !== 'undefined' && body instanceof FormData) {\n // Don't set Content-Type for FormData, let browser set it with boundary\n processedBody = body;\n } else {\n // JSON body\n if (method !== 'GET') {\n requestHeaders['Content-Type'] = 'application/json;charset=UTF-8';\n }\n processedBody = JSON.stringify(body);\n }\n }\n \n Object.assign(requestHeaders, headers);\n \n const response = await this.fetch(url, {\n method,\n headers: requestHeaders,\n body: processedBody,\n ...fetchOptions,\n });\n\n // Handle 204 No Content\n if (response.status === 204) {\n return undefined as T;\n }\n\n // Try to parse JSON response\n let data: any;\n const contentType = response.headers.get('content-type');\n // Check for any JSON content type (including PostgREST's vnd.pgrst.object+json)\n if (contentType?.includes('json')) {\n data = await response.json();\n } else {\n // For non-JSON responses, return text\n data = await response.text();\n }\n\n // Handle errors\n if (!response.ok) {\n if (data && typeof data === 'object' && 'error' in data) {\n // Add the HTTP status code if not already in the data\n if (!data.statusCode && !data.status) {\n data.statusCode = response.status;\n }\n const error = InsForgeError.fromApiError(data as ApiError);\n // Preserve all additional fields from the error response\n Object.keys(data).forEach(key => {\n if (key !== 'error' && key !== 'message' && key !== 'statusCode') {\n (error as any)[key] = data[key];\n }\n });\n throw error;\n }\n throw new InsForgeError(\n `Request failed: ${response.statusText}`,\n response.status,\n 'REQUEST_FAILED'\n );\n }\n\n return data as T;\n }\n\n get<T>(path: string, options?: RequestOptions): Promise<T> {\n return this.request<T>('GET', path, options);\n }\n\n post<T>(path: string, body?: any, options?: RequestOptions): Promise<T> {\n return this.request<T>('POST', path, { ...options, body });\n }\n\n put<T>(path: string, body?: any, options?: RequestOptions): Promise<T> {\n return this.request<T>('PUT', path, { ...options, body });\n }\n\n patch<T>(path: string, body?: any, options?: RequestOptions): Promise<T> {\n return this.request<T>('PATCH', path, { ...options, body });\n }\n\n delete<T>(path: string, options?: RequestOptions): Promise<T> {\n return this.request<T>('DELETE', path, options);\n }\n\n setAuthToken(token: string | null) {\n this.userToken = token;\n }\n\n getHeaders(): Record<string, string> {\n const headers = { ...this.defaultHeaders };\n \n // Include Authorization header if token is available (same logic as request method)\n const authToken = this.userToken || this.anonKey;\n if (authToken) {\n headers['Authorization'] = `Bearer ${authToken}`;\n }\n \n return headers;\n }\n}","/**\n * Token Manager for InsForge SDK\n *\n * Memory-only token storage.\n */\n\nimport type { UserSchema } from '@insforge/shared-schemas';\nimport type { AuthSession } from '../types';\n\n// CSRF token cookie name\nexport const CSRF_TOKEN_COOKIE = 'insforge_csrf_token';\n\n/**\n * Get CSRF token from cookie\n * Used to include in X-CSRF-Token header for refresh requests\n */\nexport function getCsrfToken(): string | null {\n if (typeof document === 'undefined') return null;\n const match = document.cookie\n .split(';')\n .find(c => c.trim().startsWith(`${CSRF_TOKEN_COOKIE}=`));\n if (!match) return null;\n return match.split('=')[1] || null;\n}\n\n/**\n * Set CSRF token cookie\n * Called after login/register/refresh to store the CSRF token\n */\nexport function setCsrfToken(token: string): void {\n if (typeof document === 'undefined') return;\n const maxAge = 7 * 24 * 60 * 60; // 7 days (same as refresh token)\n const secure = (typeof window !== 'undefined' && window.location.protocol === 'https:') ? '; Secure' : '';\n document.cookie = `${CSRF_TOKEN_COOKIE}=${encodeURIComponent(token)}; path=/; max-age=${maxAge}; SameSite=Lax${secure}`;\n}\n\n/**\n * Clear CSRF token cookie\n * Called on logout\n */\nexport function clearCsrfToken(): void {\n if (typeof document === 'undefined') return;\n const secure = (typeof window !== 'undefined' && window.location.protocol === 'https:') ? '; Secure' : '';\n document.cookie = `${CSRF_TOKEN_COOKIE}=; path=/; max-age=0; SameSite=Lax${secure}`;\n}\n\nexport class TokenManager {\n // In-memory storage\n private accessToken: string | null = null;\n private user: UserSchema | null = null;\n\n // Callback for token changes (used by realtime to reconnect with new token)\n onTokenChange: (() => void) | null = null;\n\n constructor() {}\n\n /**\n * Save session in memory\n */\n saveSession(session: AuthSession): void {\n const tokenChanged = session.accessToken !== this.accessToken;\n this.accessToken = session.accessToken;\n this.user = session.user;\n\n if (tokenChanged && this.onTokenChange) {\n this.onTokenChange();\n }\n }\n\n /**\n * Get current session\n */\n getSession(): AuthSession | null {\n if (!this.accessToken || !this.user) return null;\n return {\n accessToken: this.accessToken,\n user: this.user,\n };\n }\n\n /**\n * Get access token\n */\n getAccessToken(): string | null {\n return this.accessToken;\n }\n\n /**\n * Set access token\n */\n setAccessToken(token: string): void {\n const tokenChanged = token !== this.accessToken;\n this.accessToken = token;\n if (tokenChanged && this.onTokenChange) {\n this.onTokenChange();\n }\n }\n\n /**\n * Get user\n */\n getUser(): UserSchema | null {\n return this.user;\n }\n\n /**\n * Set user\n */\n setUser(user: UserSchema): void {\n this.user = user;\n }\n\n /**\n * Clear in-memory session\n */\n clearSession(): void {\n const hadToken = this.accessToken !== null;\n this.accessToken = null;\n this.user = null;\n\n if (hadToken && this.onTokenChange) {\n this.onTokenChange();\n }\n }\n}\n","/**\n * Auth module helper functions\n */\n\nimport { InsForgeError } from '../../types';\n\n// ============================================================================\n// PKCE (Proof Key for Code Exchange) - RFC 7636\n// ============================================================================\n\nconst PKCE_VERIFIER_KEY = 'insforge_pkce_verifier';\n\n/**\n * Base64 URL encode without padding (per RFC 7636)\n */\nfunction base64UrlEncode(buffer: Uint8Array): string {\n const base64 = btoa(String.fromCharCode(...buffer));\n return base64\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n}\n\n/**\n * Generate a cryptographically random code verifier for PKCE\n */\nexport function generateCodeVerifier(): string {\n const array = new Uint8Array(32);\n crypto.getRandomValues(array);\n return base64UrlEncode(array);\n}\n\n/**\n * Generate code challenge from verifier using SHA-256 (S256 method)\n */\nexport async function generateCodeChallenge(verifier: string): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(verifier);\n const hash = await crypto.subtle.digest('SHA-256', data);\n return base64UrlEncode(new Uint8Array(hash));\n}\n\n/**\n * Store PKCE code verifier in sessionStorage\n */\nexport function storePkceVerifier(verifier: string): void {\n if (typeof sessionStorage !== 'undefined') {\n sessionStorage.setItem(PKCE_VERIFIER_KEY, verifier);\n }\n}\n\n/**\n * Retrieve and clear PKCE code verifier from sessionStorage\n */\nexport function retrievePkceVerifier(): string | null {\n if (typeof sessionStorage === 'undefined') {\n return null;\n }\n const verifier = sessionStorage.getItem(PKCE_VERIFIER_KEY);\n if (verifier) {\n sessionStorage.removeItem(PKCE_VERIFIER_KEY);\n }\n return verifier;\n}\n\n// ============================================================================\n// Error Helpers\n// ============================================================================\n\n/**\n * Wrap an error into the standard { data, error } format\n * Passes through InsForgeError unchanged, wraps other errors\n */\nexport function wrapError<T>(\n error: unknown,\n fallbackMessage: string\n): { data: T | null; error: InsForgeError } {\n if (error instanceof InsForgeError) {\n return { data: null, error };\n }\n\n return {\n data: null,\n error: new InsForgeError(\n error instanceof Error ? error.message : fallbackMessage,\n 500,\n 'UNEXPECTED_ERROR'\n ),\n };\n}\n\n/**\n * Clean up URL parameters (removes sensitive data from URL after OAuth callback)\n */\nexport function cleanUrlParams(...params: string[]): void {\n if (typeof window === 'undefined') {\n return;\n }\n\n const url = new URL(window.location.href);\n params.forEach((p) => url.searchParams.delete(p));\n window.history.replaceState({}, document.title, url.toString());\n}\n","/**\n * Auth module for InsForge SDK\n * Handles authentication, sessions, profiles, and email verification\n */\n\nimport { HttpClient } from '../../lib/http-client';\nimport { TokenManager, getCsrfToken, setCsrfToken, clearCsrfToken } from '../../lib/token-manager';\nimport { AuthSession, InsForgeError } from '../../types';\nimport {\n generateCodeVerifier,\n generateCodeChallenge,\n storePkceVerifier,\n retrievePkceVerifier,\n wrapError,\n cleanUrlParams,\n} from './helpers';\n\nimport type {\n CreateUserRequest,\n CreateUserResponse,\n CreateSessionRequest,\n CreateSessionResponse,\n GetOauthUrlResponse,\n GetPublicAuthConfigResponse,\n OAuthProvidersSchema,\n SendVerificationEmailRequest,\n SendResetPasswordEmailRequest,\n ExchangeResetPasswordTokenRequest,\n VerifyEmailRequest,\n VerifyEmailResponse,\n RefreshSessionResponse,\n UserSchema,\n GetProfileResponse,\n OAuthCodeExchangeRequest,\n} from '@insforge/shared-schemas';\n\ninterface AuthOptions {\n isServerMode?: boolean;\n}\n\nexport class Auth {\n private authCallbackHandled: Promise<void>;\n\n constructor(\n private http: HttpClient,\n private tokenManager: TokenManager,\n private options: AuthOptions = {}\n ) {\n this.authCallbackHandled = this.detectAuthCallback();\n }\n\n private isServerMode(): boolean {\n return !!this.options.isServerMode;\n }\n\n /**\n * Save session from API response\n * Handles token storage, CSRF token, and HTTP auth header\n */\n private saveSessionFromResponse(\n response: CreateUserResponse | CreateSessionResponse | VerifyEmailResponse | RefreshSessionResponse\n ): boolean {\n if (!response.accessToken || !response.user) {\n return false;\n }\n\n const session: AuthSession = {\n accessToken: response.accessToken,\n user: response.user,\n };\n\n // Browser web flow: csrf token is returned for cookie-based refresh\n if (!this.isServerMode() && response.csrfToken) {\n setCsrfToken(response.csrfToken);\n }\n\n if (!this.isServerMode()) {\n this.tokenManager.saveSession(session);\n }\n this.http.setAuthToken(response.accessToken);\n return true;\n }\n\n // ============================================================================\n // OAuth Callback Detection (runs on initialization)\n // ============================================================================\n\n /**\n * Detect and handle OAuth callback parameters in URL\n * Supports PKCE flow (insforge_code) and legacy flow (access_token in URL)\n */\n private async detectAuthCallback(): Promise<void> {\n if (this.isServerMode() || typeof window === 'undefined') return;\n\n try {\n const params = new URLSearchParams(window.location.search);\n\n // Handle error callback\n const error = params.get('error');\n if (error) {\n cleanUrlParams('error');\n console.debug('OAuth callback error:', error);\n return;\n }\n\n // PKCE flow: exchange code for tokens\n const code = params.get('insforge_code');\n if (code) {\n cleanUrlParams('insforge_code');\n const { error: exchangeError } = await this.exchangeOAuthCode(code);\n if (exchangeError) {\n console.debug('OAuth code exchange failed:', exchangeError.message);\n }\n return;\n }\n\n // Legacy flow: tokens directly in URL (backward compatible)\n const accessToken = params.get('access_token');\n const userId = params.get('user_id');\n const email = params.get('email');\n\n if (accessToken && userId && email) {\n const csrfToken = params.get('csrf_token');\n const name = params.get('name');\n\n if (csrfToken) {\n setCsrfToken(csrfToken);\n }\n\n const session: AuthSession = {\n accessToken,\n user: {\n id: userId,\n email,\n profile: { name: name || '' },\n metadata: null,\n emailVerified: false,\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n },\n };\n\n this.tokenManager.saveSession(session);\n this.http.setAuthToken(accessToken);\n cleanUrlParams('access_token', 'user_id', 'email', 'name', 'csrf_token');\n }\n } catch (error) {\n console.debug('OAuth callback detection skipped:', error);\n }\n }\n\n // ============================================================================\n // Sign Up / Sign In / Sign Out\n // ============================================================================\n\n async signUp(request: CreateUserRequest): Promise<{\n data: CreateUserResponse | null;\n error: InsForgeError | null;\n }> {\n try {\n const response = await this.http.post<CreateUserResponse>(\n this.isServerMode() ? '/api/auth/users?client_type=mobile' : '/api/auth/users',\n request,\n { credentials: 'include' }\n );\n\n if (response.accessToken && response.user) {\n this.saveSessionFromResponse(response);\n }\n\n return { data: response, error: null };\n } catch (error) {\n return wrapError(error, 'An unexpected error occurred during sign up');\n }\n }\n\n async signInWithPassword(request: CreateSessionRequest): Promise<{\n data: CreateSessionResponse | null;\n error: InsForgeError | null;\n }> {\n try {\n const response = await this.http.post<CreateSessionResponse>(\n this.isServerMode() ? '/api/auth/sessions?client_type=mobile' : '/api/auth/sessions',\n request,\n { credentials: 'include' }\n );\n\n this.saveSessionFromResponse(response);\n return { data: response, error: null };\n } catch (error) {\n return wrapError(error, 'An unexpected error occurred during sign in');\n }\n }\n\n async signOut(): Promise<{ error: InsForgeError | null }> {\n try {\n // Try backend logout first\n try {\n await this.http.post(\n this.isServerMode() ? '/api/auth/logout?client_type=mobile' : '/api/auth/logout',\n undefined,\n { credentials: 'include' }\n );\n } catch {\n // Ignore backend logout failure so local state is still cleared\n }\n\n this.tokenManager.clearSession();\n this.http.setAuthToken(null);\n if (!this.isServerMode()) {\n clearCsrfToken();\n }\n\n return { error: null };\n } catch {\n return { error: new InsForgeError('Failed to sign out', 500, 'SIGNOUT_ERROR') };\n }\n }\n\n // ============================================================================\n // OAuth Authentication\n // ============================================================================\n\n /**\n * Sign in with OAuth provider using PKCE flow\n */\n async signInWithOAuth(options: {\n provider: OAuthProvidersSchema;\n redirectTo?: string;\n skipBrowserRedirect?: boolean;\n }): Promise<{\n data: { url?: string; provider?: string; codeVerifier?: string };\n error: InsForgeError | null;\n }> {\n try {\n const { provider, redirectTo, skipBrowserRedirect } = options;\n\n const codeVerifier = generateCodeVerifier();\n const codeChallenge = await generateCodeChallenge(codeVerifier);\n storePkceVerifier(codeVerifier);\n\n const params: Record<string, string> = { code_challenge: codeChallenge };\n if (redirectTo) params.redirect_uri = redirectTo;\n\n const response = await this.http.get<GetOauthUrlResponse>(`/api/auth/oauth/${provider}`, { params });\n\n if (!this.isServerMode() && typeof window !== 'undefined' && !skipBrowserRedirect) {\n window.location.href = response.authUrl;\n return { data: {}, error: null };\n }\n\n return {\n data: { url: response.authUrl, provider, codeVerifier },\n error: null,\n };\n } catch (error) {\n if (error instanceof InsForgeError) {\n return { data: {}, error };\n }\n return {\n data: {},\n error: new InsForgeError(\n 'An unexpected error occurred during OAuth initialization',\n 500,\n 'UNEXPECTED_ERROR'\n ),\n };\n }\n }\n\n /**\n * Exchange OAuth authorization code for tokens (PKCE flow)\n * Called automatically on initialization when insforge_code is in URL\n */\n async exchangeOAuthCode(\n code: string,\n codeVerifier?: string\n ): Promise<{\n data: { accessToken: string; refreshToken?: string; user: UserSchema; redirectTo?: string } | null;\n error: InsForgeError | null;\n }> {\n try {\n const verifier = codeVerifier ?? retrievePkceVerifier();\n\n if (!verifier) {\n return {\n data: null,\n error: new InsForgeError(\n 'PKCE code verifier not found. Ensure signInWithOAuth was called in the same browser session.',\n 400,\n 'PKCE_VERIFIER_MISSING'\n ),\n };\n }\n\n const request: OAuthCodeExchangeRequest = { code, code_verifier: verifier };\n const response = await this.http.post<CreateSessionResponse>(\n this.isServerMode()\n ? '/api/auth/oauth/exchange?client_type=mobile'\n : '/api/auth/oauth/exchange',\n request,\n { credentials: 'include' }\n );\n\n this.saveSessionFromResponse(response);\n\n return {\n data: {\n accessToken: response.accessToken,\n refreshToken: response.refreshToken,\n user: response.user,\n redirectTo: response.redirectTo,\n },\n error: null,\n };\n } catch (error) {\n return wrapError(error, 'An unexpected error occurred during OAuth code exchange');\n }\n }\n\n /**\n * Sign in with an ID token from a native SDK (Google One Tap, etc.)\n * Use this for native mobile apps or Google One Tap on web.\n *\n * @param credentials.provider - The identity provider (currently only 'google' is supported)\n * @param credentials.token - The ID token from the native SDK\n */\n async signInWithIdToken(credentials: {\n provider: 'google';\n token: string;\n }): Promise<{\n data: { accessToken: string; refreshToken?: string; user: UserSchema } | null;\n error: InsForgeError | null;\n }> {\n try {\n const { provider, token } = credentials;\n\n const response = await this.http.post<CreateSessionResponse>(\n '/api/auth/id-token?client_type=mobile',\n { provider, token },\n { credentials: 'include' }\n );\n\n this.saveSessionFromResponse(response);\n\n return {\n data: {\n accessToken: response.accessToken,\n refreshToken: response.refreshToken,\n user: response.user,\n },\n error: null,\n };\n } catch (error) {\n return wrapError(error, 'An unexpected error occurred during ID token sign in');\n }\n }\n\n // ============================================================================\n // Session Management\n // ============================================================================\n\n /**\n * Get current user, automatically waits for pending OAuth callback\n */\n async getCurrentUser(): Promise<{\n data: { user: UserSchema | null };\n error: InsForgeError | null;\n }> {\n await this.authCallbackHandled;\n\n try {\n if (this.isServerMode()) {\n const accessToken = this.tokenManager.getAccessToken();\n if (!accessToken) return { data: { user: null }, error: null };\n\n this.http.setAuthToken(accessToken);\n const response = await this.http.get<{ user: UserSchema }>('/api/auth/sessions/current');\n const user = response.user ?? null;\n return { data: { user }, error: null };\n }\n\n // Browser mode: check memory first\n const session = this.tokenManager.getSession();\n if (session) {\n this.http.setAuthToken(session.accessToken);\n return { data: { user: session.user }, error: null };\n }\n\n // Try refresh via httpOnly cookie (browser only)\n if (typeof window !== 'undefined') {\n try {\n const csrfToken = getCsrfToken();\n const response = await this.http.post<RefreshSessionResponse>('/api/auth/refresh', undefined, {\n headers: csrfToken ? { 'X-CSRF-Token': csrfToken } : {},\n credentials: 'include',\n });\n\n if (response.accessToken) {\n this.saveSessionFromResponse(response);\n return { data: { user: response.user ?? null }, error: null };\n }\n } catch (error) {\n if (error instanceof InsForgeError) {\n return { data: { user: null }, error };\n }\n }\n }\n\n return { data: { user: null }, error: null };\n } catch (error) {\n if (error instanceof InsForgeError) {\n return { data: { user: null }, error };\n }\n return {\n data: { user: null },\n error: new InsForgeError(\n 'An unexpected error occurred while getting user',\n 500,\n 'UNEXPECTED_ERROR'\n ),\n };\n }\n }\n\n // ============================================================================\n // Profile Management\n // ============================================================================\n\n async getProfile(userId: string): Promise<{\n data: GetProfileResponse | null;\n error: InsForgeError | null;\n }> {\n try {\n const response = await this.http.get<GetProfileResponse>(`/api/auth/profiles/${userId}`);\n return { data: response, error: null };\n } catch (error) {\n return wrapError(error, 'An unexpected error occurred while fetching user profile');\n }\n }\n\n async setProfile(profile: Record<string, unknown>): Promise<{\n data: GetProfileResponse | null;\n error: InsForgeError | null;\n }> {\n try {\n const response = await this.http.patch<GetProfileResponse>('/api/auth/profiles/current', {\n profile,\n });\n\n const currentUser = this.tokenManager.getUser();\n if (!this.isServerMode() && currentUser && response.profile !== undefined) {\n this.tokenManager.setUser({ ...currentUser, profile: response.profile });\n }\n\n return { data: response, error: null };\n } catch (error) {\n return wrapError(error, 'An unexpected error occurred while updating user profile');\n }\n }\n\n // ============================================================================\n // Email Verification\n // ============================================================================\n\n async resendVerificationEmail(request: SendVerificationEmailRequest): Promise<{\n data: { success: boolean; message: string } | null;\n error: InsForgeError | null;\n }> {\n try {\n const response = await this.http.post<{ success: boolean; message: string }>(\n '/api/auth/email/send-verification',\n request\n );\n return { data: response, error: null };\n } catch (error) {\n return wrapError(error, 'An unexpected error occurred while sending verification code');\n }\n }\n\n /** @deprecated Use `resendVerificationEmail` instead */\n async sendVerificationEmail(request: SendVerificationEmailRequest) {\n return this.resendVerificationEmail(request);\n }\n\n async verifyEmail(request: VerifyEmailRequest): Promise<{\n data: VerifyEmailResponse | null;\n error: InsForgeError | null;\n }> {\n try {\n const response = await this.http.post<VerifyEmailResponse>(\n this.isServerMode()\n ? '/api/auth/email/verify?client_type=mobile'\n : '/api/auth/email/verify',\n request,\n { credentials: 'include' }\n );\n\n this.saveSessionFromResponse(response);\n return { data: response, error: null };\n } catch (error) {\n return wrapError(error, 'An unexpected error occurred while verifying email');\n }\n }\n\n // ============================================================================\n // Password Reset\n // ============================================================================\n\n async sendResetPasswordEmail(request: SendResetPasswordEmailRequest): Promise<{\n data: { success: boolean; message: string } | null;\n error: InsForgeError | null;\n }> {\n try {\n const response = await this.http.post<{ success: boolean; message: string }>(\n '/api/auth/email/send-reset-password',\n request\n );\n return { data: response, error: null };\n } catch (error) {\n return wrapError(error, 'An unexpected error occurred while sending password reset code');\n }\n }\n\n async exchangeResetPasswordToken(request: ExchangeResetPasswordTokenRequest): Promise<{\n data: { token: string; expiresAt: string } | null;\n error: InsForgeError | null;\n }> {\n try {\n const response = await this.http.post<{ token: string; expiresAt: string }>(\n '/api/auth/email/exchange-reset-password-token',\n request\n );\n return { data: response, error: null };\n } catch (error) {\n return wrapError(error, 'An unexpected error occurred while verifying reset code');\n }\n }\n\n async resetPassword(request: { newPassword: string; otp: string }): Promise<{\n data: { message: string; redirectTo?: string } | null;\n error: InsForgeError | null;\n }> {\n try {\n const response = await this.http.post<{ message: string; redirectTo?: string }>(\n '/api/auth/email/reset-password',\n request\n );\n return { data: response, error: null };\n } catch (error) {\n return wrapError(error, 'An unexpected error occurred while resetting password');\n }\n }\n\n // ============================================================================\n // Configuration\n // ============================================================================\n\n async getPublicAuthConfig(): Promise<{\n data: GetPublicAuthConfigResponse | null;\n error: InsForgeError | null;\n }> {\n try {\n const response = await this.http.get<GetPublicAuthConfigResponse>('/api/auth/public-config');\n return { data: response, error: null };\n } catch (error) {\n return wrapError(error, 'An unexpected error occurred while fetching auth configuration');\n }\n }\n}\n","/**\n * Database module using @supabase/postgrest-js\n * Complete replacement for custom QueryBuilder with full PostgREST features\n */\n\nimport { PostgrestClient } from '@supabase/postgrest-js';\nimport { HttpClient } from '../lib/http-client';\nimport { TokenManager } from '../lib/token-manager';\n\n\n/**\n * Custom fetch that transforms URLs and adds auth\n */\nfunction createInsForgePostgrestFetch(\n httpClient: HttpClient,\n tokenManager: TokenManager\n): typeof fetch {\n return async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const url = typeof input === 'string' ? input : input.toString();\n const urlObj = new URL(url);\n\n // Extract pathname (remove leading /)\n // postgrest-js sends: http://dummy/tablename?params for tables\n // postgrest-js sends: http://dummy/rpc/functionname?params for RPC\n const pathname = urlObj.pathname.slice(1);\n\n // Route to appropriate InsForge endpoint\n const rpcMatch = pathname.match(/^rpc\\/(.+)$/);\n const endpoint = rpcMatch\n ? `/api/database/rpc/${rpcMatch[1]}`\n : `/api/database/records/${pathname}`;\n\n const insforgeUrl = `${httpClient.baseUrl}${endpoint}${urlObj.search}`;\n \n // Get auth token from TokenManager or HttpClient\n const token = tokenManager.getAccessToken();\n const httpHeaders = httpClient.getHeaders();\n const authToken = token || httpHeaders['Authorization']?.replace('Bearer ', '');\n \n // Prepare headers\n const headers = new Headers(init?.headers);\n if (authToken && !headers.has('Authorization')) {\n headers.set('Authorization', `Bearer ${authToken}`);\n }\n \n // Make the actual request using native fetch\n const response = await fetch(insforgeUrl, {\n ...init,\n headers\n });\n \n return response;\n };\n}\n\n/**\n * Database client using postgrest-js\n * Drop-in replacement with FULL PostgREST capabilities\n */\nexport class Database {\n private postgrest: PostgrestClient<any, any, any>;\n \n constructor(httpClient: HttpClient, tokenManager: TokenManager) {\n // Create postgrest client with custom fetch\n this.postgrest = new PostgrestClient<any, any, any>('http://dummy', {\n fetch: createInsForgePostgrestFetch(httpClient, tokenManager),\n headers: {}\n });\n }\n \n /**\n * Create a query builder for a table\n * \n * @example\n * // Basic query\n * const { data, error } = await client.database\n * .from('posts')\n * .select('*')\n * .eq('user_id', userId);\n * \n * // With count (Supabase style!)\n * const { data, error, count } = await client.database\n * .from('posts')\n * .select('*', { count: 'exact' })\n * .range(0, 9);\n * \n * // Just get count, no data\n * const { count } = await client.database\n * .from('posts')\n * .select('*', { count: 'exact', head: true });\n * \n * // Complex queries with OR\n * const { data } = await client.database\n * .from('posts')\n * .select('*, users!inner(*)')\n * .or('status.eq.active,status.eq.pending');\n * \n * // All features work:\n * - Nested selects\n * - Foreign key expansion \n * - OR/AND/NOT conditions\n * - Count with head\n * - Range pagination\n * - Upserts\n */\n from(table: string) {\n // Return postgrest query builder with all features\n return this.postgrest.from(table);\n }\n\n /**\n * Call a PostgreSQL function (RPC)\n *\n * @example\n * // Call a function with parameters\n * const { data, error } = await client.database\n * .rpc('get_user_stats', { user_id: 123 });\n *\n * // Call a function with no parameters\n * const { data, error } = await client.database\n * .rpc('get_all_active_users');\n *\n * // With options (head, count, get)\n * const { data, count } = await client.database\n * .rpc('search_posts', { query: 'hello' }, { count: 'exact' });\n */\n rpc(\n fn: string,\n args?: Record<string, unknown>,\n options?: { head?: boolean; get?: boolean; count?: 'exact' | 'planned' | 'estimated' }\n ) {\n return this.postgrest.rpc(fn, args, options);\n }\n}","/**\n * Storage module for InsForge SDK\n * Handles file uploads, downloads, and bucket management\n */\n\nimport { HttpClient } from '../lib/http-client';\nimport { InsForgeError } from '../types';\nimport type { \n StorageFileSchema,\n ListObjectsResponseSchema\n} from '@insforge/shared-schemas';\n\nexport interface StorageResponse<T> {\n data: T | null;\n error: InsForgeError | null;\n}\n\ninterface UploadStrategy {\n method: 'direct' | 'presigned';\n uploadUrl: string;\n fields?: Record<string, string>;\n key: string;\n confirmRequired: boolean;\n confirmUrl?: string;\n expiresAt?: Date;\n}\n\ninterface DownloadStrategy {\n method: 'direct' | 'presigned';\n url: string;\n expiresAt?: Date;\n}\n\n/**\n * Storage bucket operations\n */\nexport class StorageBucket {\n constructor(\n private bucketName: string,\n private http: HttpClient\n ) {}\n\n /**\n * Upload a file with a specific key\n * Uses the upload strategy from backend (direct or presigned)\n * @param path - The object key/path\n * @param file - File or Blob to upload\n */\n async upload(\n path: string,\n file: File | Blob\n ): Promise<StorageResponse<StorageFileSchema>> {\n try {\n // Get upload strategy from backend - this is required\n const strategyResponse = await this.http.post<UploadStrategy>(\n `/api/storage/buckets/${this.bucketName}/upload-strategy`,\n {\n filename: path,\n contentType: file.type || 'application/octet-stream',\n size: file.size\n }\n );\n\n // Use presigned URL if available\n if (strategyResponse.method === 'presigned') {\n return await this.uploadWithPresignedUrl(strategyResponse, file);\n }\n\n // Use direct upload if strategy says so\n if (strategyResponse.method === 'direct') {\n const formData = new FormData();\n formData.append('file', file);\n\n const response = await this.http.request<StorageFileSchema>(\n 'PUT',\n `/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}`,\n {\n body: formData as any,\n headers: {\n // Don't set Content-Type, let browser set multipart boundary\n }\n }\n );\n\n return { data: response, error: null };\n }\n\n throw new InsForgeError(\n `Unsupported upload method: ${strategyResponse.method}`,\n 500,\n 'STORAGE_ERROR'\n );\n } catch (error) {\n return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'Upload failed',\n 500,\n 'STORAGE_ERROR'\n )\n };\n }\n }\n\n /**\n * Upload a file with auto-generated key\n * Uses the upload strategy from backend (direct or presigned)\n * @param file - File or Blob to upload\n */\n async uploadAuto(\n file: File | Blob\n ): Promise<StorageResponse<StorageFileSchema>> {\n try {\n const filename = file instanceof File ? file.name : 'file';\n \n // Get upload strategy from backend - this is required\n const strategyResponse = await this.http.post<UploadStrategy>(\n `/api/storage/buckets/${this.bucketName}/upload-strategy`,\n {\n filename,\n contentType: file.type || 'application/octet-stream',\n size: file.size\n }\n );\n\n // Use presigned URL if available\n if (strategyResponse.method === 'presigned') {\n return await this.uploadWithPresignedUrl(strategyResponse, file);\n }\n\n // Use direct upload if strategy says so\n if (strategyResponse.method === 'direct') {\n const formData = new FormData();\n formData.append('file', file);\n\n const response = await this.http.request<StorageFileSchema>(\n 'POST',\n `/api/storage/buckets/${this.bucketName}/objects`,\n {\n body: formData as any,\n headers: {\n // Don't set Content-Type, let browser set multipart boundary\n }\n }\n );\n\n return { data: response, error: null };\n }\n\n throw new InsForgeError(\n `Unsupported upload method: ${strategyResponse.method}`,\n 500,\n 'STORAGE_ERROR'\n );\n } catch (error) {\n return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'Upload failed',\n 500,\n 'STORAGE_ERROR'\n )\n };\n }\n }\n\n /**\n * Internal method to handle presigned URL uploads\n */\n private async uploadWithPresignedUrl(\n strategy: UploadStrategy,\n file: File | Blob\n ): Promise<StorageResponse<StorageFileSchema>> {\n try {\n // Upload to presigned URL (e.g., S3)\n const formData = new FormData();\n \n // Add all fields from the presigned URL\n if (strategy.fields) {\n Object.entries(strategy.fields).forEach(([key, value]) => {\n formData.append(key, value);\n });\n }\n \n // File must be the last field for S3\n formData.append('file', file);\n\n const uploadResponse = await fetch(strategy.uploadUrl, {\n method: 'POST',\n body: formData\n });\n\n if (!uploadResponse.ok) {\n throw new InsForgeError(\n `Upload to storage failed: ${uploadResponse.statusText}`,\n uploadResponse.status,\n 'STORAGE_ERROR'\n );\n }\n\n // Confirm upload with backend if required\n if (strategy.confirmRequired && strategy.confirmUrl) {\n const confirmResponse = await this.http.post<StorageFileSchema>(\n strategy.confirmUrl,\n {\n size: file.size,\n contentType: file.type || 'application/octet-stream'\n }\n );\n\n return { data: confirmResponse, error: null };\n }\n\n // If no confirmation required, return basic file info\n return {\n data: {\n key: strategy.key,\n bucket: this.bucketName,\n size: file.size,\n mimeType: file.type || 'application/octet-stream',\n uploadedAt: new Date().toISOString(),\n url: this.getPublicUrl(strategy.key)\n } as StorageFileSchema,\n error: null\n };\n } catch (error) {\n throw error instanceof InsForgeError ? error : new InsForgeError(\n 'Presigned upload failed',\n 500,\n 'STORAGE_ERROR'\n );\n }\n }\n\n /**\n * Download a file\n * Uses the download strategy from backend (direct or presigned)\n * @param path - The object key/path\n * Returns the file as a Blob\n */\n async download(path: string): Promise<{ data: Blob | null; error: InsForgeError | null }> {\n try {\n // Get download strategy from backend - this is required\n const strategyResponse = await this.http.post<DownloadStrategy>(\n `/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}/download-strategy`,\n { expiresIn: 3600 }\n );\n\n // Use URL from strategy\n const downloadUrl = strategyResponse.url;\n \n // Download from the URL\n const headers: HeadersInit = {};\n \n // Only add auth header for direct downloads (not presigned URLs)\n if (strategyResponse.method === 'direct') {\n Object.assign(headers, this.http.getHeaders());\n }\n \n const response = await fetch(downloadUrl, {\n method: 'GET',\n headers\n });\n\n if (!response.ok) {\n try {\n const error = await response.json();\n throw InsForgeError.fromApiError(error);\n } catch {\n throw new InsForgeError(\n `Download failed: ${response.statusText}`,\n response.status,\n 'STORAGE_ERROR'\n );\n }\n }\n\n const blob = await response.blob();\n return { data: blob, error: null };\n } catch (error) {\n return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'Download failed',\n 500,\n 'STORAGE_ERROR'\n )\n };\n }\n }\n\n /**\n * Get public URL for a file\n * @param path - The object key/path\n */\n getPublicUrl(path: string): string {\n return `${this.http.baseUrl}/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}`;\n }\n\n /**\n * List objects in the bucket\n * @param prefix - Filter by key prefix\n * @param search - Search in file names\n * @param limit - Maximum number of results (default: 100, max: 1000)\n * @param offset - Number of results to skip\n */\n async list(options?: {\n prefix?: string;\n search?: string;\n limit?: number;\n offset?: number;\n }): Promise<StorageResponse<ListObjectsResponseSchema>> {\n try {\n const params: Record<string, string> = {};\n \n if (options?.prefix) params.prefix = options.prefix;\n if (options?.search) params.search = options.search;\n if (options?.limit) params.limit = options.limit.toString();\n if (options?.offset) params.offset = options.offset.toString();\n\n const response = await this.http.get<ListObjectsResponseSchema>(\n `/api/storage/buckets/${this.bucketName}/objects`,\n { params }\n );\n\n return { data: response, error: null };\n } catch (error) {\n return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'List failed',\n 500,\n 'STORAGE_ERROR'\n )\n };\n }\n }\n\n /**\n * Delete a file\n * @param path - The object key/path\n */\n async remove(path: string): Promise<StorageResponse<{ message: string }>> {\n try {\n const response = await this.http.delete<{ message: string }>(\n `/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}`\n );\n\n return { data: response, error: null };\n } catch (error) {\n return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'Delete failed',\n 500,\n 'STORAGE_ERROR'\n )\n };\n }\n }\n}\n\n/**\n * Storage module for file operations\n */\nexport class Storage {\n constructor(private http: HttpClient) {}\n\n /**\n * Get a bucket instance for operations\n * @param bucketName - Name of the bucket\n */\n from(bucketName: string): StorageBucket {\n return new StorageBucket(bucketName, this.http);\n }\n}","/**\n * AI Module for Insforge SDK\n * Response format roughly matches OpenAI SDK for compatibility\n *\n * The backend handles all the complexity of different AI providers\n * and returns a unified format. This SDK transforms responses to match OpenAI-like format.\n */\n\nimport { HttpClient } from \"../lib/http-client\";\nimport {\n ChatCompletionRequest,\n ChatCompletionResponse,\n ImageGenerationRequest,\n ImageGenerationResponse,\n EmbeddingsRequest,\n EmbeddingsResponse,\n} from \"@insforge/shared-schemas\";\n\nexport class AI {\n public readonly chat: Chat;\n public readonly images: Images;\n public readonly embeddings: Embeddings;\n\n constructor(private http: HttpClient) {\n this.chat = new Chat(http);\n this.images = new Images(http);\n this.embeddings = new Embeddings(http);\n }\n}\n\nclass Chat {\n public readonly completions: ChatCompletions;\n\n constructor(http: HttpClient) {\n this.completions = new ChatCompletions(http);\n }\n}\n\nclass ChatCompletions {\n constructor(private http: HttpClient) {}\n\n /**\n * Create a chat completion - OpenAI-like response format\n *\n * @example\n * ```typescript\n * // Non-streaming\n * const completion = await client.ai.chat.completions.create({\n * model: 'gpt-4',\n * messages: [{ role: 'user', content: 'Hello!' }]\n * });\n * console.log(completion.choices[0].message.content);\n *\n * // With images (OpenAI-compatible format)\n * const response = await client.ai.chat.completions.create({\n * model: 'gpt-4-vision',\n * messages: [{\n * role: 'user',\n * content: [\n * { type: 'text', text: 'What is in this image?' },\n * { type: 'image_url', image_url: { url: 'https://example.com/image.jpg' } }\n * ]\n * }]\n * });\n *\n * // With PDF files\n * const pdfResponse = await client.ai.chat.completions.create({\n * model: 'anthropic/claude-3.5-sonnet',\n * messages: [{\n * role: 'user',\n * content: [\n * { type: 'text', text: 'Summarize this document' },\n * { type: 'file', file: { filename: 'doc.pdf', file_data: 'https://example.com/doc.pdf' } }\n * ]\n * }],\n * fileParser: { enabled: true, pdf: { engine: 'mistral-ocr' } }\n * });\n *\n * // With web search\n * const searchResponse = await client.ai.chat.completions.create({\n * model: 'openai/gpt-4',\n * messages: [{ role: 'user', content: 'What are the latest news about AI?' }],\n * webSearch: { enabled: true, maxResults: 5 }\n * });\n * // Access citations from response.choices[0].message.annotations\n *\n * // With thinking/reasoning mode (Anthropic models)\n * const thinkingResponse = await client.ai.chat.completions.create({\n * model: 'anthropic/claude-3.5-sonnet',\n * messages: [{ role: 'user', content: 'Solve this complex math problem...' }],\n * thinking: true\n * });\n *\n * // Streaming - returns async iterable\n * const stream = await client.ai.chat.completions.create({\n * model: 'gpt-4',\n * messages: [{ role: 'user', content: 'Tell me a story' }],\n * stream: true\n * });\n *\n * for await (const chunk of stream) {\n * if (chunk.choices[0]?.delta?.content) {\n * process.stdout.write(chunk.choices[0].delta.content);\n * }\n * }\n * ```\n */\n async create(params: ChatCompletionRequest): Promise<any> {\n // Backend already expects camelCase, no transformation needed\n const backendParams = {\n model: params.model,\n messages: params.messages,\n temperature: params.temperature,\n maxTokens: params.maxTokens,\n topP: params.topP,\n stream: params.stream,\n // New plugin options\n webSearch: params.webSearch,\n fileParser: params.fileParser,\n thinking: params.thinking,\n // Tool calling options\n tools: params.tools,\n toolChoice: params.toolChoice,\n parallelToolCalls: params.parallelToolCalls,\n };\n\n // For streaming, return an async iterable that yields OpenAI-like chunks\n if (params.stream) {\n const headers = this.http.getHeaders();\n headers[\"Content-Type\"] = \"application/json\";\n\n const response = await this.http.fetch(\n `${this.http.baseUrl}/api/ai/chat/completion`,\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(backendParams),\n }\n );\n\n if (!response.ok) {\n const error = await response.json();\n throw new Error(error.error || \"Stream request failed\");\n }\n\n // Return async iterable that parses SSE and transforms to OpenAI-like format\n return this.parseSSEStream(response, params.model);\n }\n\n // Non-streaming: transform response to OpenAI-like format\n const response: ChatCompletionResponse = await this.http.post(\n \"/api/ai/chat/completion\",\n backendParams\n );\n\n // Transform to OpenAI-like format\n const content = response.text || \"\";\n\n return {\n id: `chatcmpl-${Date.now()}`,\n object: \"chat.completion\",\n created: Math.floor(Date.now() / 1000),\n model: response.metadata?.model,\n choices: [\n {\n index: 0,\n message: {\n role: \"assistant\",\n content,\n // Include tool_calls if present (from tool calling)\n ...(response.tool_calls?.length && { tool_calls: response.tool_calls }),\n // Include annotations if present (from web search or file parsing)\n ...(response.annotations?.length && { annotations: response.annotations }),\n },\n finish_reason: response.tool_calls?.length ? \"tool_calls\" : \"stop\",\n },\n ],\n usage: response.metadata?.usage || {\n prompt_tokens: 0,\n completion_tokens: 0,\n total_tokens: 0,\n },\n };\n }\n\n /**\n * Parse SSE stream into async iterable of OpenAI-like chunks\n */\n private async *parseSSEStream(\n response: Response,\n model: string\n ): AsyncIterableIterator<any> {\n const reader = response.body!.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() || \"\";\n\n for (const line of lines) {\n if (line.startsWith(\"data: \")) {\n const dataStr = line.slice(6).trim();\n if (dataStr) {\n try {\n const data = JSON.parse(dataStr);\n\n // Transform to OpenAI-like streaming format\n if (data.chunk || data.content) {\n yield {\n id: `chatcmpl-${Date.now()}`,\n object: \"chat.completion.chunk\",\n created: Math.floor(Date.now() / 1000),\n model,\n choices: [\n {\n index: 0,\n delta: {\n content: data.chunk || data.content,\n },\n finish_reason: null,\n },\n ],\n };\n }\n\n // Yield tool_calls when received from stream\n if (data.tool_calls?.length) {\n yield {\n id: `chatcmpl-${Date.now()}`,\n object: \"chat.completion.chunk\",\n created: Math.floor(Date.now() / 1000),\n model,\n choices: [\n {\n index: 0,\n delta: {\n tool_calls: data.tool_calls,\n },\n finish_reason: \"tool_calls\",\n },\n ],\n };\n }\n\n // If we received the done signal, we can stop\n if (data.done) {\n reader.releaseLock();\n return;\n }\n } catch (e) {\n // Skip invalid JSON\n console.warn(\"Failed to parse SSE data:\", dataStr);\n }\n }\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n}\n\nclass Embeddings {\n constructor(private http: HttpClient) {}\n\n /**\n * Create embeddings for text input - OpenAI-like response format\n *\n * @example\n * ```typescript\n * // Single text input\n * const response = await client.ai.embeddings.create({\n * model: 'openai/text-embedding-3-small',\n * input: 'Hello world'\n * });\n * console.log(response.data[0].embedding); // number[]\n *\n * // Multiple text inputs\n * const response = await client.ai.embeddings.create({\n * model: 'openai/text-embedding-3-small',\n * input: ['Hello world', 'Goodbye world']\n * });\n * response.data.forEach((item, i) => {\n * console.log(`Embedding ${i}:`, item.embedding.slice(0, 5)); // First 5 dimensions\n * });\n *\n * // With custom dimensions (if supported by model)\n * const response = await client.ai.embeddings.create({\n * model: 'openai/text-embedding-3-small',\n * input: 'Hello world',\n * dimensions: 256\n * });\n *\n * // With base64 encoding format\n * const response = await client.ai.embeddings.create({\n * model: 'openai/text-embedding-3-small',\n * input: 'Hello world',\n * encoding_format: 'base64'\n * });\n * ```\n */\n async create(params: EmbeddingsRequest): Promise<any> {\n const response: EmbeddingsResponse = await this.http.post(\n \"/api/ai/embeddings\",\n params\n );\n\n // Return OpenAI-compatible format\n return {\n object: response.object,\n data: response.data,\n model: response.metadata?.model,\n usage: response.metadata?.usage\n ? {\n prompt_tokens: response.metadata.usage.promptTokens || 0,\n total_tokens: response.metadata.usage.totalTokens || 0,\n }\n : {\n prompt_tokens: 0,\n total_tokens: 0,\n },\n };\n }\n}\n\nclass Images {\n constructor(private http: HttpClient) {}\n\n /**\n * Generate images - OpenAI-like response format\n *\n * @example\n * ```typescript\n * // Text-to-image\n * const response = await client.ai.images.generate({\n * model: 'dall-e-3',\n * prompt: 'A sunset over mountains',\n * });\n * console.log(response.images[0].url);\n *\n * // Image-to-image (with input images)\n * const response = await client.ai.images.generate({\n * model: 'stable-diffusion-xl',\n * prompt: 'Transform this into a watercolor painting',\n * images: [\n * { url: 'https://example.com/input.jpg' },\n * // or base64-encoded Data URI:\n * { url: 'data:image/jpeg;base64,/9j/4AAQ...' }\n * ]\n * });\n * ```\n */\n async generate(params: ImageGenerationRequest): Promise<any> {\n const response: ImageGenerationResponse = await this.http.post(\n \"/api/ai/image/generation\",\n params\n );\n \n // Build data array based on response content\n let data: Array<{ b64_json?: string; content?: string }> = [];\n \n if (response.images && response.images.length > 0) {\n // Has images - extract base64 and include text\n data = response.images.map(img => ({\n b64_json: img.imageUrl.replace(/^data:image\\/\\w+;base64,/, ''),\n content: response.text\n }));\n } else if (response.text) {\n // Text-only response\n data = [{ content: response.text }];\n }\n \n // Return OpenAI-compatible format\n return {\n created: Math.floor(Date.now() / 1000),\n data,\n ...(response.metadata?.usage && {\n usage: {\n total_tokens: response.metadata.usage.totalTokens || 0,\n input_tokens: response.metadata.usage.promptTokens || 0,\n output_tokens: response.metadata.usage.completionTokens || 0,\n }\n })\n };\n }\n}\n","import { HttpClient } from '../lib/http-client';\n\nexport interface FunctionInvokeOptions {\n /**\n * The body of the request\n */\n body?: any;\n\n /**\n * Custom headers to send with the request\n */\n headers?: Record<string, string>;\n\n /**\n * HTTP method (default: POST)\n */\n method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n}\n\n/**\n * Edge Functions client for invoking serverless functions\n *\n * @example\n * ```typescript\n * // Invoke a function with JSON body\n * const { data, error } = await client.functions.invoke('hello-world', {\n * body: { name: 'World' }\n * });\n *\n * // GET request\n * const { data, error } = await client.functions.invoke('get-data', {\n * method: 'GET'\n * });\n * ```\n */\nexport class Functions {\n private http: HttpClient;\n private functionsUrl: string | undefined;\n\n constructor(http: HttpClient, functionsUrl?: string) {\n this.http = http;\n this.functionsUrl = functionsUrl || Functions.deriveSubhostingUrl(http.baseUrl);\n }\n\n /**\n * Derive the subhosting URL from the base URL.\n * Base URL pattern: https://{appKey}.{region}.insforge.app\n * Functions URL: https://{appKey}.functions.insforge.app\n * Only applies to .insforge.app domains.\n */\n private static deriveSubhostingUrl(baseUrl: string): string | undefined {\n try {\n const { hostname } = new URL(baseUrl);\n if (!hostname.endsWith('.insforge.app')) return undefined;\n const appKey = hostname.split('.')[0];\n return `https://${appKey}.functions.insforge.app`;\n } catch {\n return undefined;\n }\n }\n\n /**\n * Invokes an Edge Function\n *\n * If functionsUrl is configured, tries direct subhosting first.\n * Falls back to proxy URL if subhosting returns 404.\n *\n * @param slug The function slug to invoke\n * @param options Request options\n */\n async invoke<T = any>(\n slug: string,\n options: FunctionInvokeOptions = {}\n ): Promise<{ data: T | null; error: Error | null }> {\n const { method = 'POST', body, headers = {} } = options;\n\n // Try direct subhosting URL first if configured\n if (this.functionsUrl) {\n try {\n const data = await this.http.request<T>(method, `${this.functionsUrl}/${slug}`, {\n body,\n headers,\n });\n return { data, error: null };\n } catch (error: any) {\n // If 404, fall through to proxy\n if (error?.statusCode === 404) {\n // Function not found on subhosting, try proxy\n } else {\n // Other errors, return immediately\n return { data: null, error };\n }\n }\n }\n\n // Fall back to proxy URL\n try {\n const path = `/functions/${slug}`;\n const data = await this.http.request<T>(method, path, { body, headers });\n return { data, error: null };\n } catch (error: any) {\n return { data: null, error };\n }\n }\n}","import { io, Socket } from 'socket.io-client';\nimport type { SubscribeResponse, RealtimeErrorPayload, SocketMessage } from '@insforge/shared-schemas';\nimport { TokenManager } from '../lib/token-manager';\n\nexport type { SubscribeResponse, RealtimeErrorPayload, SocketMessage };\n\nexport type ConnectionState = 'disconnected' | 'connecting' | 'connected';\n\nexport type EventCallback<T = unknown> = (payload: T) => void;\n\nconst CONNECT_TIMEOUT = 10000;\n\n/**\n * Realtime module for subscribing to channels and handling real-time events\n *\n * @example\n * ```typescript\n * const { realtime } = client;\n *\n * // Connect to the realtime server\n * await realtime.connect();\n *\n * // Subscribe to a channel\n * const response = await realtime.subscribe('orders:123');\n * if (!response.ok) {\n * console.error('Failed to subscribe:', response.error);\n * }\n *\n * // Listen for specific events\n * realtime.on('order_updated', (payload) => {\n * console.log('Order updated:', payload);\n * });\n *\n * // Listen for connection events\n * realtime.on('connect', () => console.log('Connected!'));\n * realtime.on('connect_error', (err) => console.error('Connection failed:', err));\n * realtime.on('disconnect', (reason) => console.log('Disconnected:', reason));\n * realtime.on('error', (error) => console.error('Realtime error:', error));\n *\n * // Publish a message to a channel\n * await realtime.publish('orders:123', 'status_changed', { status: 'shipped' });\n *\n * // Unsubscribe and disconnect when done\n * realtime.unsubscribe('orders:123');\n * realtime.disconnect();\n * ```\n */\nexport class Realtime {\n private baseUrl: string;\n private tokenManager: TokenManager;\n private socket: Socket | null = null;\n private connectPromise: Promise<void> | null = null;\n private subscribedChannels: Set<string> = new Set();\n private eventListeners: Map<string, Set<EventCallback>> = new Map();\n private anonKey?: string;\n\n constructor(baseUrl: string, tokenManager: TokenManager, anonKey?: string) {\n this.baseUrl = baseUrl;\n this.tokenManager = tokenManager;\n this.anonKey = anonKey;\n\n // Handle token changes (e.g., after refresh)\n this.tokenManager.onTokenChange = () => this.onTokenChange();\n }\n\n private notifyListeners(event: string, payload?: unknown): void {\n const listeners = this.eventListeners.get(event);\n if (!listeners) return;\n for (const cb of listeners) {\n try {\n cb(payload);\n } catch (err) {\n console.error(`Error in ${event} callback:`, err);\n }\n }\n }\n\n /**\n * Connect to the realtime server\n * @returns Promise that resolves when connected\n */\n connect(): Promise<void> {\n // Already connected\n if (this.socket?.connected) {\n return Promise.resolve();\n }\n\n // Connection already in progress, return existing promise\n if (this.connectPromise) {\n return this.connectPromise;\n }\n\n this.connectPromise = new Promise((resolve, reject) => {\n const token = this.tokenManager.getAccessToken() ?? this.anonKey;\n \n\n this.socket = io(this.baseUrl, {\n transports: ['websocket'],\n auth: token ? { token } : undefined,\n });\n\n let initialConnection = true;\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n const cleanup = () => {\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n };\n\n timeoutId = setTimeout(() => {\n if (initialConnection) {\n initialConnection = false;\n this.connectPromise = null;\n this.socket?.disconnect();\n this.socket = null;\n reject(new Error(`Connection timeout after ${CONNECT_TIMEOUT}ms`));\n }\n }, CONNECT_TIMEOUT);\n\n this.socket.on('connect', () => {\n cleanup();\n // Re-subscribe to channels on every connect (initial + reconnects)\n for (const channel of this.subscribedChannels) {\n this.socket!.emit('realtime:subscribe', { channel });\n }\n this.notifyListeners('connect');\n\n if (initialConnection) {\n initialConnection = false;\n this.connectPromise = null;\n resolve();\n }\n });\n\n this.socket.on('connect_error', (error: Error) => {\n cleanup();\n this.notifyListeners('connect_error', error);\n\n if (initialConnection) {\n initialConnection = false;\n this.connectPromise = null;\n reject(error);\n }\n });\n\n this.socket.on('disconnect', (reason: string) => {\n this.notifyListeners('disconnect', reason);\n });\n\n this.socket.on('realtime:error', (error: RealtimeErrorPayload) => {\n this.notifyListeners('error', error);\n });\n\n // Route custom events to listeners (onAny doesn't catch socket reserved events)\n this.socket.onAny((event: string, message: SocketMessage) => {\n if (event === 'realtime:error') return; // Already handled above\n this.notifyListeners(event, message);\n });\n });\n\n return this.connectPromise;\n }\n\n /**\n * Disconnect from the realtime server\n */\n disconnect(): void {\n if (this.socket) {\n this.socket.disconnect();\n this.socket = null;\n }\n this.subscribedChannels.clear();\n }\n\n /**\n * Handle token changes (e.g., after auth refresh)\n * Updates socket auth so reconnects use the new token\n * If connected, triggers reconnect to apply new token immediately\n */\n private onTokenChange(): void {\n const token = this.tokenManager.getAccessToken() ?? this.anonKey;\n\n // Always update auth so socket.io auto-reconnect uses new token\n if (this.socket) {\n this.socket.auth = token ? { token } : {};\n }\n\n // Trigger reconnect if connected OR connecting (to avoid completing with stale token)\n if (this.socket && (this.socket.connected || this.connectPromise)) {\n this.socket.disconnect();\n this.socket.connect();\n // Note: on('connect') handler automatically re-subscribes to channels\n }\n }\n\n /**\n * Check if connected to the realtime server\n */\n get isConnected(): boolean {\n return this.socket?.connected ?? false;\n }\n\n /**\n * Get the current connection state\n */\n get connectionState(): ConnectionState {\n if (!this.socket) return 'disconnected';\n if (this.socket.connected) return 'connected';\n return 'connecting';\n }\n\n /**\n * Get the socket ID (if connected)\n */\n get socketId(): string | undefined {\n return this.socket?.id;\n }\n\n /**\n * Subscribe to a channel\n *\n * Automatically connects if not already connected.\n *\n * @param channel - Channel name (e.g., 'orders:123', 'broadcast')\n * @returns Promise with the subscription response\n */\n async subscribe(channel: string): Promise<SubscribeResponse> {\n // Already subscribed, return success\n if (this.subscribedChannels.has(channel)) {\n return { ok: true, channel };\n }\n\n // Auto-connect if not connected\n if (!this.socket?.connected) {\n try {\n await this.connect();\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Connection failed';\n return { ok: false, channel, error: { code: 'CONNECTION_FAILED', message } };\n }\n }\n\n return new Promise((resolve) => {\n this.socket!.emit('realtime:subscribe', { channel }, (response: SubscribeResponse) => {\n if (response.ok) {\n this.subscribedChannels.add(channel);\n }\n resolve(response);\n });\n });\n }\n\n /**\n * Unsubscribe from a channel (fire-and-forget)\n *\n * @param channel - Channel name to unsubscribe from\n */\n unsubscribe(channel: string): void {\n this.subscribedChannels.delete(channel);\n\n if (this.socket?.connected) {\n this.socket.emit('realtime:unsubscribe', { channel });\n }\n }\n\n /**\n * Publish a message to a channel\n *\n * @param channel - Channel name\n * @param event - Event name\n * @param payload - Message payload\n */\n async publish<T = unknown>(channel: string, event: string, payload: T): Promise<void> {\n if (!this.socket?.connected) {\n throw new Error('Not connected to realtime server. Call connect() first.');\n }\n\n this.socket!.emit('realtime:publish', { channel, event, payload });\n }\n\n /**\n * Listen for events\n *\n * Reserved event names:\n * - 'connect' - Fired when connected to the server\n * - 'connect_error' - Fired when connection fails (payload: Error)\n * - 'disconnect' - Fired when disconnected (payload: reason string)\n * - 'error' - Fired when a realtime error occurs (payload: RealtimeErrorPayload)\n *\n * All other events receive a `SocketMessage` payload with metadata.\n *\n * @param event - Event name to listen for\n * @param callback - Callback function when event is received\n */\n on<T = SocketMessage>(event: string, callback: EventCallback<T>): void {\n if (!this.eventListeners.has(event)) {\n this.eventListeners.set(event, new Set());\n }\n this.eventListeners.get(event)!.add(callback as EventCallback);\n }\n\n /**\n * Remove a listener for a specific event\n *\n * @param event - Event name\n * @param callback - The callback function to remove\n */\n off<T = SocketMessage>(event: string, callback: EventCallback<T>): void {\n const listeners = this.eventListeners.get(event);\n if (listeners) {\n listeners.delete(callback as EventCallback);\n if (listeners.size === 0) {\n this.eventListeners.delete(event);\n }\n }\n }\n\n /**\n * Listen for an event only once, then automatically remove the listener\n *\n * @param event - Event name to listen for\n * @param callback - Callback function when event is received\n */\n once<T = SocketMessage>(event: string, callback: EventCallback<T>): void {\n const wrapper: EventCallback<T> = (payload: T) => {\n this.off(event, wrapper);\n callback(payload);\n };\n this.on(event, wrapper);\n }\n\n /**\n * Get all currently subscribed channels\n *\n * @returns Array of channel names\n */\n getSubscribedChannels(): string[] {\n return Array.from(this.subscribedChannels);\n }\n}\n","import { HttpClient } from '../lib/http-client';\nimport type { SendRawEmailRequest, SendEmailResponse } from '@insforge/shared-schemas';\n\nexport type { SendRawEmailRequest as SendEmailOptions, SendEmailResponse } from '@insforge/shared-schemas';\n\n/**\n * Emails client for sending custom emails\n *\n * @example\n * ```typescript\n * // Send a simple email\n * const { data, error } = await client.emails.send({\n * to: 'user@example.com',\n * subject: 'Welcome!',\n * html: '<h1>Welcome to our platform</h1>'\n * });\n *\n * if (error) {\n * console.error('Failed to send:', error.message);\n * return;\n * }\n * // Email sent successfully - data is {} (empty object)\n *\n * // Send to multiple recipients with CC\n * const { data, error } = await client.emails.send({\n * to: ['user1@example.com', 'user2@example.com'],\n * cc: 'manager@example.com',\n * subject: 'Team Update',\n * html: '<p>Here is the latest update...</p>',\n * replyTo: 'support@example.com'\n * });\n * ```\n */\nexport class Emails {\n private http: HttpClient;\n\n constructor(http: HttpClient) {\n this.http = http;\n }\n\n /**\n * Send a custom HTML email\n * @param options Email options including recipients, subject, and HTML content\n */\n async send(\n options: SendRawEmailRequest\n ): Promise<{ data: SendEmailResponse | null; error: Error | null }> {\n try {\n const data = await this.http.post<SendEmailResponse>(\n '/api/email/send-raw',\n options\n );\n\n return { data, error: null };\n } catch (error: unknown) {\n const normalizedError = error instanceof Error ? error : new Error(String(error));\n return { data: null, error: normalizedError };\n }\n }\n}\n","import { InsForgeConfig } from './types';\nimport { HttpClient } from './lib/http-client';\nimport { TokenManager } from './lib/token-manager';\nimport { Auth } from './modules/auth/auth';\nimport { Database } from './modules/database-postgrest';\nimport { Storage } from './modules/storage';\nimport { AI } from './modules/ai';\nimport { Functions } from './modules/functions';\nimport { Realtime } from './modules/realtime';\nimport { Emails } from './modules/email';\n\n/**\n * Main InsForge SDK Client\n * \n * @example\n * ```typescript\n * import { InsForgeClient } from '@insforge/sdk';\n * \n * const client = new InsForgeClient({\n * baseUrl: 'http://localhost:7130'\n * });\n * \n * // Authentication\n * const { data, error } = await client.auth.signUp({\n * email: 'user@example.com',\n * password: 'password123',\n * name: 'John Doe'\n * });\n * \n * // Database operations\n * const { data, error } = await client.database\n * .from('posts')\n * .select('*')\n * .eq('user_id', session.user.id)\n * .order('created_at', { ascending: false })\n * .limit(10);\n * \n * // Insert data\n * const { data: newPost } = await client.database\n * .from('posts')\n * .insert({ title: 'Hello', content: 'World' })\n * .single();\n * \n * // Invoke edge functions\n * const { data, error } = await client.functions.invoke('my-function', {\n * body: { message: 'Hello from SDK' }\n * });\n * ```\n */\nexport class InsForgeClient {\n private http: HttpClient;\n private tokenManager: TokenManager;\n public readonly auth: Auth;\n public readonly database: Database;\n public readonly storage: Storage;\n public readonly ai: AI;\n public readonly functions: Functions;\n public readonly realtime: Realtime;\n public readonly emails: Emails;\n\n constructor(config: InsForgeConfig = {}) {\n this.http = new HttpClient(config);\n this.tokenManager = new TokenManager();\n\n // Check for edge function token\n if (config.edgeFunctionToken) {\n this.http.setAuthToken(config.edgeFunctionToken);\n this.tokenManager.setAccessToken(config.edgeFunctionToken);\n }\n\n this.auth = new Auth(this.http, this.tokenManager, {\n isServerMode: config.isServerMode ?? false,\n });\n this.database = new Database(this.http, this.tokenManager);\n this.storage = new Storage(this.http);\n this.ai = new AI(this.http);\n this.functions = new Functions(this.http, config.functionsUrl);\n this.realtime = new Realtime(this.http.baseUrl, this.tokenManager, config.anonKey);\n this.emails = new Emails(this.http);\n }\n\n /**\n * Get the underlying HTTP client for custom requests\n * \n * @example\n * ```typescript\n * const httpClient = client.getHttpClient();\n * const customData = await httpClient.get('/api/custom-endpoint');\n * ```\n */\n getHttpClient(): HttpClient {\n return this.http;\n }\n\n /**\n * Future modules will be added here:\n * - database: Database operations\n * - storage: File storage operations\n * - functions: Serverless functions\n * - tables: Table management\n * - metadata: Backend metadata\n */\n}\n"],"mappings":"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","names":["response"]}