Sign In

@insforge/sdk

Package Overview
Dependencies
Maintainers
5
Versions
190
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@insforge/sdk - npm Package Compare versions

Comparing version
1.5.0
to
1.5.1
+1089
dist/client-BjhyKtje.d.mts
import { A as AuthSession, I as InsForgeConfig, e as AuthRefreshResponse, d as InsForgeError } from './types-MKmYAYeg.mjs';
import { UserSchema, CreateUserRequest, CreateUserResponse, CreateSessionRequest, CreateSessionResponse, SendOTPRequest, OAuthProvidersSchema, RefreshSessionResponse, GetProfileResponse, SendVerificationEmailRequest, VerifyEmailRequest, VerifyEmailResponse, SendResetPasswordEmailRequest, ExchangeResetPasswordTokenRequest, ExchangeResetPasswordTokenResponse, ResetPasswordResponse, GetPublicAuthConfigResponse, StorageFileSchema, ListObjectsResponseSchema, DeleteObjectsResponse, ChatCompletionRequest, ImageGenerationRequest, EmbeddingsRequest, SubscribeResponse, SocketMessage, PresenceMember, SendRawEmailRequest, SendEmailResponse, StripeEnvironment, CreateCheckoutSessionBody, CreateCheckoutSessionResponse, CreateCustomerPortalSessionBody, CreateCustomerPortalSessionResponse, RazorpayEnvironment, CreateRazorpayOrderBody, CreateRazorpayOrderResponse, VerifyRazorpayOrderBody, VerifyRazorpayOrderResponse, CreateRazorpaySubscriptionBody, CreateRazorpaySubscriptionResponse, VerifyRazorpaySubscriptionBody, VerifyRazorpaySubscriptionResponse, CancelRazorpaySubscriptionBodyInput, CancelRazorpaySubscriptionResponse, PauseRazorpaySubscriptionResponse, ResumeRazorpaySubscriptionResponse } from '@insforge/shared-schemas';
import * as _supabase_postgrest_js from '@supabase/postgrest-js';
import { PostgrestClient } from '@supabase/postgrest-js';
type LogFunction = (message: string, ...args: any[]) => void;
/**
* Debug logger for the InsForge SDK.
* Logs HTTP request/response details with automatic redaction of sensitive data.
*
* @example
* ```typescript
* // Enable via SDK config
* const client = new InsForgeClient({ debug: true });
*
* // Or with a custom log function
* const client = new InsForgeClient({
* debug: (msg) => myLogger.info(msg)
* });
* ```
*/
declare class Logger {
/** Whether debug logging is currently enabled */
enabled: boolean;
private customLog;
/**
* Creates a new Logger instance.
* @param debug - Set to true to enable console logging, or pass a custom log function
*/
constructor(debug?: boolean | LogFunction);
/**
* Logs a debug message at the info level.
* @param message - The message to log
* @param args - Additional arguments to pass to the log function
*/
log(message: string, ...args: any[]): void;
/**
* Logs a debug message at the warning level.
* @param message - The message to log
* @param args - Additional arguments to pass to the log function
*/
warn(message: string, ...args: any[]): void;
/**
* Logs a debug message at the error level.
* @param message - The message to log
* @param args - Additional arguments to pass to the log function
*/
error(message: string, ...args: any[]): void;
/**
* Logs an outgoing HTTP request with method, URL, headers, and body.
* Sensitive headers and body fields are automatically redacted.
* @param method - HTTP method (GET, POST, etc.)
* @param url - The full request URL
* @param headers - Request headers (sensitive values will be redacted)
* @param body - Request body (sensitive fields will be masked)
*/
logRequest(method: string, url: string, headers?: Record<string, string>, body?: any): void;
/**
* Logs an incoming HTTP response with method, URL, status, duration, and body.
* Error responses (4xx/5xx) are logged at the error level.
* @param method - HTTP method (GET, POST, etc.)
* @param url - The full request URL
* @param status - HTTP response status code
* @param durationMs - Request duration in milliseconds
* @param body - Response body (sensitive fields will be masked, large bodies truncated)
*/
logResponse(method: string, url: string, status: number, durationMs: number, body?: any): void;
}
/**
* Token Manager for InsForge SDK
*
* Memory-only token storage.
*/
declare const AuthChangeEvent: {
readonly SIGNED_IN: "signedIn";
readonly SIGNED_OUT: "signedOut";
readonly TOKEN_REFRESHED: "tokenRefreshed";
};
type AuthChangeEvent = (typeof AuthChangeEvent)[keyof typeof AuthChangeEvent];
type AuthStateChangeCallback = (event: AuthChangeEvent) => void;
declare class TokenManager {
private accessToken;
private user;
private authStateChangeCallbacks;
constructor();
/**
* Save session in memory
*/
saveSession(session: AuthSession, event?: AuthChangeEvent): void;
/**
* Get current session
*/
getSession(): AuthSession | null;
/**
* Get access token
*/
getAccessToken(): string | null;
/**
* Set access token
*/
setAccessToken(token: string, event?: AuthChangeEvent): void;
/**
* Get user
*/
getUser(): UserSchema | null;
/**
* Set user
*/
setUser(user: UserSchema): void;
/**
* Clear in-memory session
*/
clearSession(): void;
onAuthStateChange(callback: AuthStateChangeCallback): () => void;
private notifyAuthStateChange;
}
type JsonRequestBody = Record<string, unknown> | unknown[] | null;
interface RequestOptions extends Omit<RequestInit, 'body'> {
params?: Record<string, string>;
body?: RequestInit['body'] | JsonRequestBody;
/** Allow retrying non-idempotent requests (POST, PATCH). Off by default to prevent duplicate writes. */
idempotent?: boolean;
/** Disable automatic access-token refresh for auth/control-flow requests. */
skipAuthRefresh?: boolean;
}
/**
* HTTP client with built-in retry, timeout, and exponential backoff support.
* Handles authentication, request serialization, and error normalization.
*/
declare class HttpClient {
readonly baseUrl: string;
readonly fetch: typeof fetch;
private readonly config;
private defaultHeaders;
private anonKey;
private userToken;
private logger;
private isRefreshing;
private refreshPromise;
private tokenManager;
private refreshToken;
private timeout;
private retryCount;
private retryDelay;
/**
* Creates a new HttpClient instance.
* @param config - SDK configuration including baseUrl, timeout, retry settings, and fetch implementation.
* @param tokenManager - Token manager for session persistence.
* @param logger - Optional logger instance for request/response debugging.
*/
constructor(config: InsForgeConfig, tokenManager?: TokenManager, logger?: Logger);
/**
* Builds a full URL from a path and optional query parameters.
* Normalizes PostgREST select parameters for proper syntax.
*/
private buildUrl;
/** Checks if an HTTP status code is eligible for retry (5xx server errors). */
private isRetryableStatus;
/**
* Computes the delay before the next retry using exponential backoff with jitter.
* @param attempt - The current retry attempt number (1-based).
* @returns Delay in milliseconds.
*/
private computeRetryDelay;
private shouldRefreshAccessToken;
private fetchWithRetry;
/**
* Performs an HTTP request with automatic retry and timeout handling.
* Retries on network errors and 5xx server errors with exponential backoff.
* Client errors (4xx) and timeouts are thrown immediately without retry.
* @param method - HTTP method (GET, POST, PUT, PATCH, DELETE).
* @param path - API path relative to the base URL.
* @param options - Optional request configuration including headers, body, and query params.
* @returns Parsed response data.
* @throws {InsForgeError} On timeout, network failure, or HTTP error responses.
*/
private handleRequest;
request<T>(method: string, path: string, options?: RequestOptions): Promise<T>;
/**
* Performs an SDK-configured fetch and returns the raw Response.
* This is used by clients such as postgrest-js that need to own response
* parsing while still sharing SDK auth and refresh behavior.
*/
rawFetch(input: RequestInfo | URL, init?: RequestInit, options?: {
skipAuthRefresh?: boolean;
}): Promise<Response>;
/** Performs a GET request. */
get<T>(path: string, options?: RequestOptions): Promise<T>;
/** Performs a POST request with an optional JSON body. */
post<T>(path: string, body?: any, options?: RequestOptions): Promise<T>;
/** Performs a PUT request with an optional JSON body. */
put<T>(path: string, body?: any, options?: RequestOptions): Promise<T>;
/** Performs a PATCH request with an optional JSON body. */
patch<T>(path: string, body?: any, options?: RequestOptions): Promise<T>;
/** Performs a DELETE request. */
delete<T>(path: string, options?: RequestOptions): Promise<T>;
/** Sets or clears the user authentication token for subsequent requests. */
setAuthToken(token: string | null): void;
setRefreshToken(token: string | null): void;
/** Returns the current default headers including the authorization header if set. */
getHeaders(): Record<string, string>;
refreshAccessToken(): Promise<AuthRefreshResponse>;
/** Returns a token safe to use for a new connection handshake. */
getValidAccessToken(leewaySeconds?: number): Promise<string | null>;
private refreshAndSaveSession;
private clearAuthSession;
}
/**
* Auth module for InsForge SDK
* Handles authentication, sessions, profiles, and email verification
*/
interface AuthOptions {
isServerMode?: boolean;
detectOAuthCallback?: boolean;
}
type OAuthSignInOptions = {
redirectTo: string;
additionalParams?: Record<string, string>;
skipBrowserRedirect?: boolean;
};
type OAuthSignInLegacyOptions = OAuthSignInOptions & {
provider: OAuthProvidersSchema | string;
};
/** Credentials for the password sign-in flow (excludes the OTP session variant). */
type PasswordSessionRequest = Exclude<CreateSessionRequest, {
method: 'otp';
}>;
/** Payload for {@link Auth.verifyOtp}: the email OTP session variant without the discriminator. */
type VerifyOtpRequest = Omit<Extract<CreateSessionRequest, {
method: 'otp';
}>, 'method'>;
declare class Auth {
private http;
private tokenManager;
private options;
private authCallbackHandled;
constructor(http: HttpClient, tokenManager: TokenManager, options?: AuthOptions);
private isServerMode;
/** Subscribe to SDK authentication state changes. */
onAuthStateChange(callback: AuthStateChangeCallback): () => void;
/**
* Save session from API response
* Handles token storage, CSRF token, and HTTP auth header
*/
private saveSessionFromResponse;
/**
* Detect and handle OAuth callback parameters in URL
* Supports PKCE flow (insforge_code)
*/
private detectAuthCallback;
signUp(request: CreateUserRequest): Promise<{
data: CreateUserResponse | null;
error: InsForgeError | null;
}>;
signInWithPassword(request: PasswordSessionRequest): Promise<{
data: CreateSessionResponse | null;
error: InsForgeError | null;
}>;
/**
* Send a one-time sign-in code to an email address.
*
* The response is intentionally generic whether or not an account exists, to
* avoid account enumeration. Complete the flow with {@link Auth.verifyOtp}.
*/
signInWithOtp(request: SendOTPRequest): Promise<{
data: {
success: boolean;
message: string;
} | null;
error: InsForgeError | null;
}>;
/**
* Verify an email sign-in code and create a session.
*
* If the email is new, a verified passwordless user is created; `name` sets
* the display name only on that first-time creation.
*/
verifyOtp(request: VerifyOtpRequest): Promise<{
data: CreateSessionResponse | null;
error: InsForgeError | null;
}>;
signOut(): Promise<{
error: InsForgeError | null;
}>;
/**
* Sign in with OAuth provider using PKCE flow
*/
signInWithOAuth(provider: OAuthProvidersSchema | string, options: OAuthSignInOptions): Promise<{
data: {
url?: string;
provider?: string;
codeVerifier?: string;
};
error: InsForgeError | null;
}>;
/**
* @deprecated Use signInWithOAuth(provider, { redirectTo, additionalParams, skipBrowserRedirect }).
*/
signInWithOAuth(options: OAuthSignInLegacyOptions): Promise<{
data: {
url?: string;
provider?: string;
codeVerifier?: string;
};
error: InsForgeError | null;
}>;
/**
* Exchange OAuth authorization code for tokens (PKCE flow)
* Called automatically on initialization when insforge_code is in URL
*/
exchangeOAuthCode(code: string, codeVerifier?: string): Promise<{
data: CreateSessionResponse | null;
error: InsForgeError | null;
}>;
/**
* Sign in with an ID token from a native SDK (Google One Tap, etc.)
* Use this for native mobile apps or Google One Tap on web.
*
* @param credentials.provider - The identity provider (currently only 'google' is supported)
* @param credentials.token - The ID token from the native SDK
*/
signInWithIdToken(credentials: {
provider: 'google';
token: string;
}): Promise<{
data: CreateSessionResponse | null;
error: InsForgeError | null;
}>;
/**
* Refresh the current auth session.
*
* Browser mode:
* - Uses httpOnly refresh cookie and optional CSRF header.
*
* Legacy server mode (`isServerMode: true`):
* - Uses mobile auth flow and requires `refreshToken` in request body.
*
* SSR apps should prefer `createRefreshAuthRouter()` / `refreshAuth()` from
* `@insforge/sdk/ssr`.
*/
refreshSession(options?: {
refreshToken?: string;
}): Promise<{
data: RefreshSessionResponse | null;
error: InsForgeError | null;
}>;
/**
* Get current user, automatically waits for pending OAuth callback
*/
getCurrentUser(): Promise<{
data: {
user: UserSchema | null;
};
error: InsForgeError | null;
}>;
getProfile(userId: string): Promise<{
data: GetProfileResponse | null;
error: InsForgeError | null;
}>;
setProfile(profile: Record<string, unknown>): Promise<{
data: GetProfileResponse | null;
error: InsForgeError | null;
}>;
resendVerificationEmail(request: SendVerificationEmailRequest): Promise<{
data: {
success: boolean;
message: string;
} | null;
error: InsForgeError | null;
}>;
verifyEmail(request: VerifyEmailRequest): Promise<{
data: VerifyEmailResponse | null;
error: InsForgeError | null;
}>;
sendResetPasswordEmail(request: SendResetPasswordEmailRequest): Promise<{
data: {
success: boolean;
message: string;
} | null;
error: InsForgeError | null;
}>;
exchangeResetPasswordToken(request: ExchangeResetPasswordTokenRequest): Promise<{
data: ExchangeResetPasswordTokenResponse | null;
error: InsForgeError | null;
}>;
resetPassword(request: {
newPassword: string;
otp: string;
}): Promise<{
data: ResetPasswordResponse | null;
error: InsForgeError | null;
}>;
getPublicAuthConfig(): Promise<{
data: GetPublicAuthConfigResponse | null;
error: InsForgeError | null;
}>;
}
/**
* Database client using postgrest-js
* Drop-in replacement with FULL PostgREST capabilities
*/
declare class Database {
private postgrest;
constructor(httpClient: HttpClient, defaultSchema?: string);
/**
* Select a non-default Postgres schema for the chained query. Maps to
* PostgREST's `Accept-Profile` (reads) / `Content-Profile` (writes) header.
* The schema must be exposed by the backend.
*
* @example
* const { data } = await client.database
* .schema('analytics')
* .from('events')
* .select('*');
*
* @example
* await client.database.schema('analytics').rpc('rollup', { day: '2026-01-01' });
*/
schema(schemaName: string): PostgrestClient<any, any, string, any>;
/**
* Create a query builder for a table
*
* @example
* // Basic query
* const { data, error } = await client.database
* .from('posts')
* .select('*')
* .eq('user_id', userId);
*
* // With count (Supabase style!)
* const { data, error, count } = await client.database
* .from('posts')
* .select('*', { count: 'exact' })
* .range(0, 9);
*
* // Just get count, no data
* const { count } = await client.database
* .from('posts')
* .select('*', { count: 'exact', head: true });
*
* // Complex queries with OR
* const { data } = await client.database
* .from('posts')
* .select('*, users!inner(*)')
* .or('status.eq.active,status.eq.pending');
*
* // All features work:
* - Nested selects
* - Foreign key expansion
* - OR/AND/NOT conditions
* - Count with head
* - Range pagination
* - Upserts
*/
from(table: string): _supabase_postgrest_js.PostgrestQueryBuilder<any, any, any, string, unknown>;
/**
* Call a PostgreSQL function (RPC)
*
* @example
* // Call a function with parameters
* const { data, error } = await client.database
* .rpc('get_user_stats', { user_id: 123 });
*
* // Call a function with no parameters
* const { data, error } = await client.database
* .rpc('get_all_active_users');
*
* // With options (head, count, get)
* const { data, count } = await client.database
* .rpc('search_posts', { query: 'hello' }, { count: 'exact' });
*/
rpc(fn: string, args?: Record<string, unknown>, options?: {
head?: boolean;
get?: boolean;
count?: 'exact' | 'planned' | 'estimated';
}): _supabase_postgrest_js.PostgrestFilterBuilder<any, any, any, any, string, null, "RPC">;
}
/**
* Storage module for InsForge SDK
* Handles file uploads, downloads, and bucket management
*/
interface StorageResponse<T> {
data: T | null;
error: InsForgeError | null;
}
/**
* Storage bucket operations
*/
declare class StorageBucket {
private bucketName;
private http;
constructor(bucketName: string, http: HttpClient);
/**
* Upload a file to a specific key.
* Uses the upload strategy from the backend (direct or presigned).
* Standard PUT semantics: uploading to an existing key replaces the
* current object in place.
* @param path - The object key/path
* @param file - File or Blob to upload
*/
upload(path: string, file: File | Blob): Promise<StorageResponse<StorageFileSchema>>;
/**
* Upload a file under an automatically generated, collision-free key.
* The key is derived client-side from the filename (sanitized base +
* timestamp + random suffix) and uploaded through the standard
* {@link upload} path, so repeated uploads of the same file never
* overwrite each other. Reads the filename structurally to avoid assuming
* a global `File` (which Node 18 does not expose).
* @param file - File or Blob to upload
*/
uploadAuto(file: File | Blob): Promise<StorageResponse<StorageFileSchema>>;
/**
* Internal method to handle presigned URL uploads
*/
private uploadWithPresignedUrl;
/**
* Download a file
* Uses the download strategy from backend (direct or presigned)
* @param path - The object key/path
* Returns the file as a Blob
*/
download(path: string): Promise<{
data: Blob | null;
error: InsForgeError | null;
}>;
/**
* Get the public URL for an object in a public bucket.
*
* Pure string construction — no network call, no auth. The URL only resolves
* if the bucket is public; for private objects use {@link createSignedUrl}.
*
* @param path - The object key/path
* @returns `{ data: { publicUrl }, error }` — matches the external SDK pattern,
* so `const { data } = getPublicUrl(path)` then `data.publicUrl`.
*/
getPublicUrl(path: string): StorageResponse<{
publicUrl: string;
}>;
/**
* Resolve a download strategy (signed or direct URL) for an object with a
* caller-supplied TTL. Prefers the canonical GET route and falls back to the
* legacy POST alias so signed-URL creation still works against older backends
* that predate the GET route (they return 404/405 for it). A genuine
* "object not found" (STORAGE_NOT_FOUND) is not retried.
*/
private requestDownloadStrategy;
/**
* Create a signed URL for an object.
*
* Returns a time-limited, credential-free URL that can be handed directly to
* a browser (`<img src>`), an email, or a third party — no SDK or session is
* needed to fetch it. Authorization is enforced when the URL is minted (the
* caller must be allowed to read the object), so the resulting link is a
* pre-authorized capability scoped to this one object until it expires.
*
* @param path - The object key/path
* @param expiresIn - Lifetime in seconds (default 3600 = 1h, max 604800 = 7d).
* Honored for private buckets; public buckets return their long-lived URL.
*/
createSignedUrl(path: string, expiresIn?: number): Promise<StorageResponse<{
signedUrl: string;
expiresAt: string | null;
}>>;
/**
* Create signed URLs for multiple objects in a single call.
*
* Each entry resolves independently: a failure on one key (not found / not
* permitted) is reported on that entry's `error` without failing the rest.
*
* @param paths - The object keys/paths
* @param expiresIn - Lifetime in seconds (default 3600 = 1h, max 604800 = 7d)
*/
createSignedUrls(paths: string[], expiresIn?: number): Promise<StorageResponse<Array<{
path: string;
signedUrl: string | null;
error: string | null;
}>>>;
/**
* List objects in the bucket
* @param prefix - Filter by key prefix
* @param search - Search in file names
* @param limit - Maximum number of results (default: 100, max: 1000)
* @param offset - Number of results to skip
*/
list(options?: {
prefix?: string;
search?: string;
limit?: number;
offset?: number;
}): Promise<StorageResponse<ListObjectsResponseSchema>>;
/** Delete a single file. */
remove(path: string): Promise<StorageResponse<{
message: string;
}>>;
/** Delete multiple files in a single request. */
remove(paths: string[]): Promise<StorageResponse<DeleteObjectsResponse>>;
/** Delete one or more files when the input type is not narrowed. */
remove(pathOrPaths: string | string[]): Promise<StorageResponse<{
message: string;
} | DeleteObjectsResponse>>;
}
/**
* Storage module for file operations
*/
declare class Storage {
private http;
constructor(http: HttpClient);
/**
* Get a bucket instance for operations
* @param bucketName - Name of the bucket
*/
from(bucketName: string): StorageBucket;
}
/**
* AI Module for Insforge SDK
* Response format roughly matches OpenAI SDK for compatibility
*
* The backend handles all the complexity of different AI providers
* and returns a unified format. This SDK transforms responses to match OpenAI-like format.
*/
declare class AI {
private http;
readonly chat: Chat;
readonly images: Images;
readonly embeddings: Embeddings;
constructor(http: HttpClient);
}
declare class Chat {
readonly completions: ChatCompletions;
constructor(http: HttpClient);
}
declare class ChatCompletions {
private http;
constructor(http: HttpClient);
/**
* Create a chat completion - OpenAI-like response format
*
* @example
* ```typescript
* // Non-streaming
* const completion = await client.ai.chat.completions.create({
* model: 'gpt-4',
* messages: [{ role: 'user', content: 'Hello!' }]
* });
* console.log(completion.choices[0].message.content);
*
* // With images (OpenAI-compatible format)
* const response = await client.ai.chat.completions.create({
* model: 'gpt-4-vision',
* messages: [{
* role: 'user',
* content: [
* { type: 'text', text: 'What is in this image?' },
* { type: 'image_url', image_url: { url: 'https://example.com/image.jpg' } }
* ]
* }]
* });
*
* // With PDF files
* const pdfResponse = await client.ai.chat.completions.create({
* model: 'anthropic/claude-3.5-sonnet',
* messages: [{
* role: 'user',
* content: [
* { type: 'text', text: 'Summarize this document' },
* { type: 'file', file: { filename: 'doc.pdf', file_data: 'https://example.com/doc.pdf' } }
* ]
* }],
* fileParser: { enabled: true, pdf: { engine: 'mistral-ocr' } }
* });
*
* // With web search
* const searchResponse = await client.ai.chat.completions.create({
* model: 'openai/gpt-4',
* messages: [{ role: 'user', content: 'What are the latest news about AI?' }],
* webSearch: { enabled: true, maxResults: 5 }
* });
* // Access citations from response.choices[0].message.annotations
*
* // With thinking/reasoning mode (Anthropic models)
* const thinkingResponse = await client.ai.chat.completions.create({
* model: 'anthropic/claude-3.5-sonnet',
* messages: [{ role: 'user', content: 'Solve this complex math problem...' }],
* thinking: true
* });
*
* // Streaming - returns async iterable
* const stream = await client.ai.chat.completions.create({
* model: 'gpt-4',
* messages: [{ role: 'user', content: 'Tell me a story' }],
* stream: true
* });
*
* for await (const chunk of stream) {
* if (chunk.choices[0]?.delta?.content) {
* process.stdout.write(chunk.choices[0].delta.content);
* }
* }
* ```
*/
create(params: ChatCompletionRequest): Promise<any>;
/**
* Parse SSE stream into async iterable of OpenAI-like chunks
*/
private parseSSEStream;
}
declare class Embeddings {
private http;
constructor(http: HttpClient);
/**
* Create embeddings for text input - OpenAI-like response format
*
* @example
* ```typescript
* // Single text input
* const response = await client.ai.embeddings.create({
* model: 'openai/text-embedding-3-small',
* input: 'Hello world'
* });
* console.log(response.data[0].embedding); // number[]
*
* // Multiple text inputs
* const response = await client.ai.embeddings.create({
* model: 'openai/text-embedding-3-small',
* input: ['Hello world', 'Goodbye world']
* });
* response.data.forEach((item, i) => {
* console.log(`Embedding ${i}:`, item.embedding.slice(0, 5)); // First 5 dimensions
* });
*
* // With custom dimensions (if supported by model)
* const response = await client.ai.embeddings.create({
* model: 'openai/text-embedding-3-small',
* input: 'Hello world',
* dimensions: 256
* });
*
* // With base64 encoding format
* const response = await client.ai.embeddings.create({
* model: 'openai/text-embedding-3-small',
* input: 'Hello world',
* encoding_format: 'base64'
* });
* ```
*/
create(params: EmbeddingsRequest): Promise<any>;
}
declare class Images {
private http;
constructor(http: HttpClient);
/**
* Generate images - OpenAI-like response format
*
* @example
* ```typescript
* // Text-to-image
* const response = await client.ai.images.generate({
* model: 'dall-e-3',
* prompt: 'A sunset over mountains',
* });
* console.log(response.data[0].b64_json);
*
* // Image-to-image (with input images)
* const response = await client.ai.images.generate({
* model: 'stable-diffusion-xl',
* prompt: 'Transform this into a watercolor painting',
* images: [
* { url: 'https://example.com/input.jpg' },
* // or base64-encoded Data URI:
* { url: 'data:image/jpeg;base64,/9j/4AAQ...' }
* ]
* });
* ```
*/
generate(params: ImageGenerationRequest): Promise<any>;
}
interface FunctionInvokeOptions {
/**
* The body of the request
*/
body?: any;
/**
* Custom headers to send with the request
*/
headers?: Record<string, string>;
/**
* HTTP method (default: POST)
*/
method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
}
/**
* Edge Functions client for invoking serverless functions.
*
* @example
* ```typescript
* const { data, error } = await client.functions.invoke('hello-world', {
* body: { name: 'World' }
* });
* ```
*/
declare class Functions {
private http;
private functionsUrl;
constructor(http: HttpClient, functionsUrl?: string);
/**
* Derive the subhosting URL from the base URL.
* Base URL pattern: https://{appKey}.{region}.insforge.app
* Functions URL: https://{appKey}.functions.insforge.app
* Only applies to .insforge.app domains.
*/
private static deriveSubhostingUrl;
/**
* Build a Request for in-process dispatch. The host is a non-routable
* placeholder; the router only reads pathname.
*/
private buildInProcessRequest;
/**
* Invoke an Edge Function.
*
* Dispatch order:
* 1. If `globalThis.__insforge_dispatch__` is present, call it in-process.
* This avoids Deno Subhosting's 508 Loop Detected when one bundled
* function invokes another inside the same deployment.
* 2. Otherwise, try the configured subhosting URL.
* 3. On 404 from subhosting, fall back to the proxy path.
*
* @param slug The function slug to invoke
* @param options Request options
*/
invoke<T = any>(slug: string, options?: FunctionInvokeOptions): Promise<{
data: T | null;
error: InsForgeError | null;
}>;
}
type ConnectionState = 'disconnected' | 'connecting' | 'connected';
type EventCallback<T = unknown> = (payload: T) => void;
/**
* Socket.IO realtime client. Authentication is evaluated for every handshake,
* while an established socket remains authenticated until it disconnects.
*/
declare class Realtime {
private baseUrl;
private tokenManager;
private anonKey?;
private getValidAccessToken;
private socket;
private connectPromise;
private connectionAttempt;
private nextConnectionAttemptId;
private subscriptions;
private eventListeners;
constructor(baseUrl: string, tokenManager: TokenManager, anonKey?: string | undefined, getValidAccessToken?: () => Promise<string | null>);
private notifyListeners;
private getHandshakeToken;
connect(): Promise<void>;
disconnect(): void;
private reconnectForAuthChange;
private handleDisconnect;
private resubscribeChannels;
private requestSubscription;
private settleSubscription;
private applyPresenceEvent;
get isConnected(): boolean;
get connectionState(): ConnectionState;
get socketId(): string | undefined;
subscribe(channel: string): Promise<SubscribeResponse>;
unsubscribe(channel: string): void;
publish<T = unknown>(channel: string, event: string, payload: T): Promise<void>;
on<T = SocketMessage>(event: string, callback: EventCallback<T>): void;
off<T = SocketMessage>(event: string, callback: EventCallback<T>): void;
once<T = SocketMessage>(event: string, callback: EventCallback<T>): void;
getSubscribedChannels(): string[];
getPresenceState(channel: string): PresenceMember[];
}
/**
* Emails client for sending custom emails
*
* @example
* ```typescript
* // Send a simple email
* const { data, error } = await client.emails.send({
* to: 'user@example.com',
* subject: 'Welcome!',
* html: '<h1>Welcome to our platform</h1>'
* });
*
* if (error) {
* console.error('Failed to send:', error.message);
* return;
* }
* // Email sent successfully - data is {} (empty object)
*
* // Send to multiple recipients with CC
* const { data, error } = await client.emails.send({
* to: ['user1@example.com', 'user2@example.com'],
* cc: 'manager@example.com',
* subject: 'Team Update',
* html: '<p>Here is the latest update...</p>',
* replyTo: 'support@example.com'
* });
* ```
*/
declare class Emails {
private http;
constructor(http: HttpClient);
/**
* Send a custom HTML email
* @param options Email options including recipients, subject, and HTML content
*/
send(options: SendRawEmailRequest): Promise<{
data: SendEmailResponse | null;
error: InsForgeError | null;
}>;
}
interface PaymentsResponse<T> {
data: T | null;
error: InsForgeError | null;
}
/**
* Stripe runtime payment flows.
*
* These methods are safe to call from generated app frontends with the current
* user token or anon key. Admin-only Stripe key/catalog APIs are intentionally
* not exposed here.
*/
declare class StripePayments {
private http;
constructor(http: HttpClient);
/**
* Create a Stripe Checkout Session through the InsForge backend.
*
* @example
* ```typescript
* const { data, error } = await client.payments.stripe.createCheckoutSession('test', {
* mode: 'payment',
* lineItems: [{ priceId: 'price_123', quantity: 1 }],
* successUrl: `${window.location.origin}/success`,
* cancelUrl: `${window.location.origin}/pricing`
* });
*
* if (!error && data.checkoutSession.url) {
* window.location.assign(data.checkoutSession.url);
* }
* ```
*/
createCheckoutSession(environment: StripeEnvironment, request: CreateCheckoutSessionBody): Promise<PaymentsResponse<CreateCheckoutSessionResponse>>;
/**
* Create a Stripe Billing Portal Session for a mapped billing subject.
*/
createCustomerPortalSession(environment: StripeEnvironment, request: CreateCustomerPortalSessionBody): Promise<PaymentsResponse<CreateCustomerPortalSessionResponse>>;
}
/**
* Razorpay runtime payment flows.
*
* Razorpay Checkout is client-rendered: create an order or subscription here,
* pass the returned checkoutOptions to Razorpay Checkout.js, then verify the
* signed payment response with the matching verify method.
*/
declare class RazorpayPayments {
private http;
constructor(http: HttpClient);
createOrder(environment: RazorpayEnvironment, request: CreateRazorpayOrderBody): Promise<PaymentsResponse<CreateRazorpayOrderResponse>>;
verifyOrder(environment: RazorpayEnvironment, request: VerifyRazorpayOrderBody): Promise<PaymentsResponse<VerifyRazorpayOrderResponse>>;
createSubscription(environment: RazorpayEnvironment, request: CreateRazorpaySubscriptionBody): Promise<PaymentsResponse<CreateRazorpaySubscriptionResponse>>;
verifySubscription(environment: RazorpayEnvironment, request: VerifyRazorpaySubscriptionBody): Promise<PaymentsResponse<VerifyRazorpaySubscriptionResponse>>;
cancelSubscription(environment: RazorpayEnvironment, subscriptionId: string, request?: CancelRazorpaySubscriptionBodyInput): Promise<PaymentsResponse<CancelRazorpaySubscriptionResponse>>;
pauseSubscription(environment: RazorpayEnvironment, subscriptionId: string): Promise<PaymentsResponse<PauseRazorpaySubscriptionResponse>>;
resumeSubscription(environment: RazorpayEnvironment, subscriptionId: string): Promise<PaymentsResponse<ResumeRazorpaySubscriptionResponse>>;
}
/**
* Provider-scoped payments client.
*/
declare class Payments {
readonly stripe: StripePayments;
readonly razorpay: RazorpayPayments;
constructor(http: HttpClient);
}
type AccessTokenChangeEvent = typeof AuthChangeEvent.SIGNED_IN | typeof AuthChangeEvent.TOKEN_REFRESHED;
/**
* Main InsForge SDK Client
*
* @example
* ```typescript
* import { InsForgeClient } from '@insforge/sdk';
*
* const client = new InsForgeClient({
* baseUrl: 'http://localhost:7130'
* });
*
* // Authentication
* const { data, error } = await client.auth.signUp({
* email: 'user@example.com',
* password: 'password123',
* name: 'John Doe'
* });
*
* // Database operations
* const { data, error } = await client.database
* .from('posts')
* .select('*')
* .eq('user_id', session.user.id)
* .order('created_at', { ascending: false })
* .limit(10);
*
* // Insert data
* const { data: newPost } = await client.database
* .from('posts')
* .insert({ title: 'Hello', content: 'World' })
* .single();
*
* // Invoke edge functions
* const { data, error } = await client.functions.invoke('my-function', {
* body: { message: 'Hello from SDK' }
* });
*
* // Enable debug logging
* const debugClient = new InsForgeClient({
* baseUrl: 'http://localhost:7130',
* debug: true
* });
* ```
*/
declare class InsForgeClient {
private http;
private tokenManager;
readonly auth: Auth;
readonly database: Database;
readonly storage: Storage;
readonly ai: AI;
readonly functions: Functions;
readonly realtime: Realtime;
readonly emails: Emails;
readonly payments: Payments;
constructor(config?: InsForgeConfig);
/**
* Get the underlying HTTP client for custom requests
*
* @example
* ```typescript
* const httpClient = client.getHttpClient();
* const customData = await httpClient.get('/api/custom-endpoint');
* ```
*/
getHttpClient(): HttpClient;
/**
* Set the access token used by every SDK surface. Updates both the HTTP
* client (database / storage / functions / AI / emails) and the realtime
* token manager. Pass `null` to sign out. By default a token replacement is
* treated as a sign-in boundary and reconnects realtime. Pass
* `AuthChangeEvent.TOKEN_REFRESHED` for a same-identity refresh to preserve a live socket; the
* refreshed token is then used at the next handshake.
*
* Use this when an external auth provider (Better Auth, Clerk, Auth0,
* WorkOS, Kinde, Stytch, …) issues the JWT and you need to keep the
* long-lived InsForge client in sync. Without this, you'd have to call
* `client.getHttpClient().setAuthToken(token)` AND reach into the private
* realtime token manager separately.
*
* @example
* ```typescript
* import { AuthChangeEvent } from '@insforge/sdk';
*
* // Refresh a third-party-issued JWT periodically
* const { token } = await fetch('/api/insforge-token').then((r) => r.json());
* client.setAccessToken(token, AuthChangeEvent.TOKEN_REFRESHED);
*
* // Sign-out
* client.setAccessToken(null);
* ```
*/
setAccessToken(token: string | null, event?: AccessTokenChangeEvent): void;
}
export { type AccessTokenChangeEvent as A, type ConnectionState as C, Database as D, Emails as E, Functions as F, HttpClient as H, InsForgeClient as I, Logger as L, type PasswordSessionRequest as P, Realtime as R, Storage as S, type VerifyOtpRequest as V, Auth as a, StorageBucket as b, type StorageResponse as c, AI as d, type FunctionInvokeOptions as e, Payments as f, type PaymentsResponse as g, type EventCallback as h, AuthChangeEvent as i, type AuthStateChangeCallback as j };
import { A as AuthSession, I as InsForgeConfig, e as AuthRefreshResponse, d as InsForgeError } from './types-MKmYAYeg.js';
import { UserSchema, CreateUserRequest, CreateUserResponse, CreateSessionRequest, CreateSessionResponse, SendOTPRequest, OAuthProvidersSchema, RefreshSessionResponse, GetProfileResponse, SendVerificationEmailRequest, VerifyEmailRequest, VerifyEmailResponse, SendResetPasswordEmailRequest, ExchangeResetPasswordTokenRequest, ExchangeResetPasswordTokenResponse, ResetPasswordResponse, GetPublicAuthConfigResponse, StorageFileSchema, ListObjectsResponseSchema, DeleteObjectsResponse, ChatCompletionRequest, ImageGenerationRequest, EmbeddingsRequest, SubscribeResponse, SocketMessage, PresenceMember, SendRawEmailRequest, SendEmailResponse, StripeEnvironment, CreateCheckoutSessionBody, CreateCheckoutSessionResponse, CreateCustomerPortalSessionBody, CreateCustomerPortalSessionResponse, RazorpayEnvironment, CreateRazorpayOrderBody, CreateRazorpayOrderResponse, VerifyRazorpayOrderBody, VerifyRazorpayOrderResponse, CreateRazorpaySubscriptionBody, CreateRazorpaySubscriptionResponse, VerifyRazorpaySubscriptionBody, VerifyRazorpaySubscriptionResponse, CancelRazorpaySubscriptionBodyInput, CancelRazorpaySubscriptionResponse, PauseRazorpaySubscriptionResponse, ResumeRazorpaySubscriptionResponse } from '@insforge/shared-schemas';
import * as _supabase_postgrest_js from '@supabase/postgrest-js';
import { PostgrestClient } from '@supabase/postgrest-js';
type LogFunction = (message: string, ...args: any[]) => void;
/**
* Debug logger for the InsForge SDK.
* Logs HTTP request/response details with automatic redaction of sensitive data.
*
* @example
* ```typescript
* // Enable via SDK config
* const client = new InsForgeClient({ debug: true });
*
* // Or with a custom log function
* const client = new InsForgeClient({
* debug: (msg) => myLogger.info(msg)
* });
* ```
*/
declare class Logger {
/** Whether debug logging is currently enabled */
enabled: boolean;
private customLog;
/**
* Creates a new Logger instance.
* @param debug - Set to true to enable console logging, or pass a custom log function
*/
constructor(debug?: boolean | LogFunction);
/**
* Logs a debug message at the info level.
* @param message - The message to log
* @param args - Additional arguments to pass to the log function
*/
log(message: string, ...args: any[]): void;
/**
* Logs a debug message at the warning level.
* @param message - The message to log
* @param args - Additional arguments to pass to the log function
*/
warn(message: string, ...args: any[]): void;
/**
* Logs a debug message at the error level.
* @param message - The message to log
* @param args - Additional arguments to pass to the log function
*/
error(message: string, ...args: any[]): void;
/**
* Logs an outgoing HTTP request with method, URL, headers, and body.
* Sensitive headers and body fields are automatically redacted.
* @param method - HTTP method (GET, POST, etc.)
* @param url - The full request URL
* @param headers - Request headers (sensitive values will be redacted)
* @param body - Request body (sensitive fields will be masked)
*/
logRequest(method: string, url: string, headers?: Record<string, string>, body?: any): void;
/**
* Logs an incoming HTTP response with method, URL, status, duration, and body.
* Error responses (4xx/5xx) are logged at the error level.
* @param method - HTTP method (GET, POST, etc.)
* @param url - The full request URL
* @param status - HTTP response status code
* @param durationMs - Request duration in milliseconds
* @param body - Response body (sensitive fields will be masked, large bodies truncated)
*/
logResponse(method: string, url: string, status: number, durationMs: number, body?: any): void;
}
/**
* Token Manager for InsForge SDK
*
* Memory-only token storage.
*/
declare const AuthChangeEvent: {
readonly SIGNED_IN: "signedIn";
readonly SIGNED_OUT: "signedOut";
readonly TOKEN_REFRESHED: "tokenRefreshed";
};
type AuthChangeEvent = (typeof AuthChangeEvent)[keyof typeof AuthChangeEvent];
type AuthStateChangeCallback = (event: AuthChangeEvent) => void;
declare class TokenManager {
private accessToken;
private user;
private authStateChangeCallbacks;
constructor();
/**
* Save session in memory
*/
saveSession(session: AuthSession, event?: AuthChangeEvent): void;
/**
* Get current session
*/
getSession(): AuthSession | null;
/**
* Get access token
*/
getAccessToken(): string | null;
/**
* Set access token
*/
setAccessToken(token: string, event?: AuthChangeEvent): void;
/**
* Get user
*/
getUser(): UserSchema | null;
/**
* Set user
*/
setUser(user: UserSchema): void;
/**
* Clear in-memory session
*/
clearSession(): void;
onAuthStateChange(callback: AuthStateChangeCallback): () => void;
private notifyAuthStateChange;
}
type JsonRequestBody = Record<string, unknown> | unknown[] | null;
interface RequestOptions extends Omit<RequestInit, 'body'> {
params?: Record<string, string>;
body?: RequestInit['body'] | JsonRequestBody;
/** Allow retrying non-idempotent requests (POST, PATCH). Off by default to prevent duplicate writes. */
idempotent?: boolean;
/** Disable automatic access-token refresh for auth/control-flow requests. */
skipAuthRefresh?: boolean;
}
/**
* HTTP client with built-in retry, timeout, and exponential backoff support.
* Handles authentication, request serialization, and error normalization.
*/
declare class HttpClient {
readonly baseUrl: string;
readonly fetch: typeof fetch;
private readonly config;
private defaultHeaders;
private anonKey;
private userToken;
private logger;
private isRefreshing;
private refreshPromise;
private tokenManager;
private refreshToken;
private timeout;
private retryCount;
private retryDelay;
/**
* Creates a new HttpClient instance.
* @param config - SDK configuration including baseUrl, timeout, retry settings, and fetch implementation.
* @param tokenManager - Token manager for session persistence.
* @param logger - Optional logger instance for request/response debugging.
*/
constructor(config: InsForgeConfig, tokenManager?: TokenManager, logger?: Logger);
/**
* Builds a full URL from a path and optional query parameters.
* Normalizes PostgREST select parameters for proper syntax.
*/
private buildUrl;
/** Checks if an HTTP status code is eligible for retry (5xx server errors). */
private isRetryableStatus;
/**
* Computes the delay before the next retry using exponential backoff with jitter.
* @param attempt - The current retry attempt number (1-based).
* @returns Delay in milliseconds.
*/
private computeRetryDelay;
private shouldRefreshAccessToken;
private fetchWithRetry;
/**
* Performs an HTTP request with automatic retry and timeout handling.
* Retries on network errors and 5xx server errors with exponential backoff.
* Client errors (4xx) and timeouts are thrown immediately without retry.
* @param method - HTTP method (GET, POST, PUT, PATCH, DELETE).
* @param path - API path relative to the base URL.
* @param options - Optional request configuration including headers, body, and query params.
* @returns Parsed response data.
* @throws {InsForgeError} On timeout, network failure, or HTTP error responses.
*/
private handleRequest;
request<T>(method: string, path: string, options?: RequestOptions): Promise<T>;
/**
* Performs an SDK-configured fetch and returns the raw Response.
* This is used by clients such as postgrest-js that need to own response
* parsing while still sharing SDK auth and refresh behavior.
*/
rawFetch(input: RequestInfo | URL, init?: RequestInit, options?: {
skipAuthRefresh?: boolean;
}): Promise<Response>;
/** Performs a GET request. */
get<T>(path: string, options?: RequestOptions): Promise<T>;
/** Performs a POST request with an optional JSON body. */
post<T>(path: string, body?: any, options?: RequestOptions): Promise<T>;
/** Performs a PUT request with an optional JSON body. */
put<T>(path: string, body?: any, options?: RequestOptions): Promise<T>;
/** Performs a PATCH request with an optional JSON body. */
patch<T>(path: string, body?: any, options?: RequestOptions): Promise<T>;
/** Performs a DELETE request. */
delete<T>(path: string, options?: RequestOptions): Promise<T>;
/** Sets or clears the user authentication token for subsequent requests. */
setAuthToken(token: string | null): void;
setRefreshToken(token: string | null): void;
/** Returns the current default headers including the authorization header if set. */
getHeaders(): Record<string, string>;
refreshAccessToken(): Promise<AuthRefreshResponse>;
/** Returns a token safe to use for a new connection handshake. */
getValidAccessToken(leewaySeconds?: number): Promise<string | null>;
private refreshAndSaveSession;
private clearAuthSession;
}
/**
* Auth module for InsForge SDK
* Handles authentication, sessions, profiles, and email verification
*/
interface AuthOptions {
isServerMode?: boolean;
detectOAuthCallback?: boolean;
}
type OAuthSignInOptions = {
redirectTo: string;
additionalParams?: Record<string, string>;
skipBrowserRedirect?: boolean;
};
type OAuthSignInLegacyOptions = OAuthSignInOptions & {
provider: OAuthProvidersSchema | string;
};
/** Credentials for the password sign-in flow (excludes the OTP session variant). */
type PasswordSessionRequest = Exclude<CreateSessionRequest, {
method: 'otp';
}>;
/** Payload for {@link Auth.verifyOtp}: the email OTP session variant without the discriminator. */
type VerifyOtpRequest = Omit<Extract<CreateSessionRequest, {
method: 'otp';
}>, 'method'>;
declare class Auth {
private http;
private tokenManager;
private options;
private authCallbackHandled;
constructor(http: HttpClient, tokenManager: TokenManager, options?: AuthOptions);
private isServerMode;
/** Subscribe to SDK authentication state changes. */
onAuthStateChange(callback: AuthStateChangeCallback): () => void;
/**
* Save session from API response
* Handles token storage, CSRF token, and HTTP auth header
*/
private saveSessionFromResponse;
/**
* Detect and handle OAuth callback parameters in URL
* Supports PKCE flow (insforge_code)
*/
private detectAuthCallback;
signUp(request: CreateUserRequest): Promise<{
data: CreateUserResponse | null;
error: InsForgeError | null;
}>;
signInWithPassword(request: PasswordSessionRequest): Promise<{
data: CreateSessionResponse | null;
error: InsForgeError | null;
}>;
/**
* Send a one-time sign-in code to an email address.
*
* The response is intentionally generic whether or not an account exists, to
* avoid account enumeration. Complete the flow with {@link Auth.verifyOtp}.
*/
signInWithOtp(request: SendOTPRequest): Promise<{
data: {
success: boolean;
message: string;
} | null;
error: InsForgeError | null;
}>;
/**
* Verify an email sign-in code and create a session.
*
* If the email is new, a verified passwordless user is created; `name` sets
* the display name only on that first-time creation.
*/
verifyOtp(request: VerifyOtpRequest): Promise<{
data: CreateSessionResponse | null;
error: InsForgeError | null;
}>;
signOut(): Promise<{
error: InsForgeError | null;
}>;
/**
* Sign in with OAuth provider using PKCE flow
*/
signInWithOAuth(provider: OAuthProvidersSchema | string, options: OAuthSignInOptions): Promise<{
data: {
url?: string;
provider?: string;
codeVerifier?: string;
};
error: InsForgeError | null;
}>;
/**
* @deprecated Use signInWithOAuth(provider, { redirectTo, additionalParams, skipBrowserRedirect }).
*/
signInWithOAuth(options: OAuthSignInLegacyOptions): Promise<{
data: {
url?: string;
provider?: string;
codeVerifier?: string;
};
error: InsForgeError | null;
}>;
/**
* Exchange OAuth authorization code for tokens (PKCE flow)
* Called automatically on initialization when insforge_code is in URL
*/
exchangeOAuthCode(code: string, codeVerifier?: string): Promise<{
data: CreateSessionResponse | null;
error: InsForgeError | null;
}>;
/**
* Sign in with an ID token from a native SDK (Google One Tap, etc.)
* Use this for native mobile apps or Google One Tap on web.
*
* @param credentials.provider - The identity provider (currently only 'google' is supported)
* @param credentials.token - The ID token from the native SDK
*/
signInWithIdToken(credentials: {
provider: 'google';
token: string;
}): Promise<{
data: CreateSessionResponse | null;
error: InsForgeError | null;
}>;
/**
* Refresh the current auth session.
*
* Browser mode:
* - Uses httpOnly refresh cookie and optional CSRF header.
*
* Legacy server mode (`isServerMode: true`):
* - Uses mobile auth flow and requires `refreshToken` in request body.
*
* SSR apps should prefer `createRefreshAuthRouter()` / `refreshAuth()` from
* `@insforge/sdk/ssr`.
*/
refreshSession(options?: {
refreshToken?: string;
}): Promise<{
data: RefreshSessionResponse | null;
error: InsForgeError | null;
}>;
/**
* Get current user, automatically waits for pending OAuth callback
*/
getCurrentUser(): Promise<{
data: {
user: UserSchema | null;
};
error: InsForgeError | null;
}>;
getProfile(userId: string): Promise<{
data: GetProfileResponse | null;
error: InsForgeError | null;
}>;
setProfile(profile: Record<string, unknown>): Promise<{
data: GetProfileResponse | null;
error: InsForgeError | null;
}>;
resendVerificationEmail(request: SendVerificationEmailRequest): Promise<{
data: {
success: boolean;
message: string;
} | null;
error: InsForgeError | null;
}>;
verifyEmail(request: VerifyEmailRequest): Promise<{
data: VerifyEmailResponse | null;
error: InsForgeError | null;
}>;
sendResetPasswordEmail(request: SendResetPasswordEmailRequest): Promise<{
data: {
success: boolean;
message: string;
} | null;
error: InsForgeError | null;
}>;
exchangeResetPasswordToken(request: ExchangeResetPasswordTokenRequest): Promise<{
data: ExchangeResetPasswordTokenResponse | null;
error: InsForgeError | null;
}>;
resetPassword(request: {
newPassword: string;
otp: string;
}): Promise<{
data: ResetPasswordResponse | null;
error: InsForgeError | null;
}>;
getPublicAuthConfig(): Promise<{
data: GetPublicAuthConfigResponse | null;
error: InsForgeError | null;
}>;
}
/**
* Database client using postgrest-js
* Drop-in replacement with FULL PostgREST capabilities
*/
declare class Database {
private postgrest;
constructor(httpClient: HttpClient, defaultSchema?: string);
/**
* Select a non-default Postgres schema for the chained query. Maps to
* PostgREST's `Accept-Profile` (reads) / `Content-Profile` (writes) header.
* The schema must be exposed by the backend.
*
* @example
* const { data } = await client.database
* .schema('analytics')
* .from('events')
* .select('*');
*
* @example
* await client.database.schema('analytics').rpc('rollup', { day: '2026-01-01' });
*/
schema(schemaName: string): PostgrestClient<any, any, string, any>;
/**
* Create a query builder for a table
*
* @example
* // Basic query
* const { data, error } = await client.database
* .from('posts')
* .select('*')
* .eq('user_id', userId);
*
* // With count (Supabase style!)
* const { data, error, count } = await client.database
* .from('posts')
* .select('*', { count: 'exact' })
* .range(0, 9);
*
* // Just get count, no data
* const { count } = await client.database
* .from('posts')
* .select('*', { count: 'exact', head: true });
*
* // Complex queries with OR
* const { data } = await client.database
* .from('posts')
* .select('*, users!inner(*)')
* .or('status.eq.active,status.eq.pending');
*
* // All features work:
* - Nested selects
* - Foreign key expansion
* - OR/AND/NOT conditions
* - Count with head
* - Range pagination
* - Upserts
*/
from(table: string): _supabase_postgrest_js.PostgrestQueryBuilder<any, any, any, string, unknown>;
/**
* Call a PostgreSQL function (RPC)
*
* @example
* // Call a function with parameters
* const { data, error } = await client.database
* .rpc('get_user_stats', { user_id: 123 });
*
* // Call a function with no parameters
* const { data, error } = await client.database
* .rpc('get_all_active_users');
*
* // With options (head, count, get)
* const { data, count } = await client.database
* .rpc('search_posts', { query: 'hello' }, { count: 'exact' });
*/
rpc(fn: string, args?: Record<string, unknown>, options?: {
head?: boolean;
get?: boolean;
count?: 'exact' | 'planned' | 'estimated';
}): _supabase_postgrest_js.PostgrestFilterBuilder<any, any, any, any, string, null, "RPC">;
}
/**
* Storage module for InsForge SDK
* Handles file uploads, downloads, and bucket management
*/
interface StorageResponse<T> {
data: T | null;
error: InsForgeError | null;
}
/**
* Storage bucket operations
*/
declare class StorageBucket {
private bucketName;
private http;
constructor(bucketName: string, http: HttpClient);
/**
* Upload a file to a specific key.
* Uses the upload strategy from the backend (direct or presigned).
* Standard PUT semantics: uploading to an existing key replaces the
* current object in place.
* @param path - The object key/path
* @param file - File or Blob to upload
*/
upload(path: string, file: File | Blob): Promise<StorageResponse<StorageFileSchema>>;
/**
* Upload a file under an automatically generated, collision-free key.
* The key is derived client-side from the filename (sanitized base +
* timestamp + random suffix) and uploaded through the standard
* {@link upload} path, so repeated uploads of the same file never
* overwrite each other. Reads the filename structurally to avoid assuming
* a global `File` (which Node 18 does not expose).
* @param file - File or Blob to upload
*/
uploadAuto(file: File | Blob): Promise<StorageResponse<StorageFileSchema>>;
/**
* Internal method to handle presigned URL uploads
*/
private uploadWithPresignedUrl;
/**
* Download a file
* Uses the download strategy from backend (direct or presigned)
* @param path - The object key/path
* Returns the file as a Blob
*/
download(path: string): Promise<{
data: Blob | null;
error: InsForgeError | null;
}>;
/**
* Get the public URL for an object in a public bucket.
*
* Pure string construction — no network call, no auth. The URL only resolves
* if the bucket is public; for private objects use {@link createSignedUrl}.
*
* @param path - The object key/path
* @returns `{ data: { publicUrl }, error }` — matches the external SDK pattern,
* so `const { data } = getPublicUrl(path)` then `data.publicUrl`.
*/
getPublicUrl(path: string): StorageResponse<{
publicUrl: string;
}>;
/**
* Resolve a download strategy (signed or direct URL) for an object with a
* caller-supplied TTL. Prefers the canonical GET route and falls back to the
* legacy POST alias so signed-URL creation still works against older backends
* that predate the GET route (they return 404/405 for it). A genuine
* "object not found" (STORAGE_NOT_FOUND) is not retried.
*/
private requestDownloadStrategy;
/**
* Create a signed URL for an object.
*
* Returns a time-limited, credential-free URL that can be handed directly to
* a browser (`<img src>`), an email, or a third party — no SDK or session is
* needed to fetch it. Authorization is enforced when the URL is minted (the
* caller must be allowed to read the object), so the resulting link is a
* pre-authorized capability scoped to this one object until it expires.
*
* @param path - The object key/path
* @param expiresIn - Lifetime in seconds (default 3600 = 1h, max 604800 = 7d).
* Honored for private buckets; public buckets return their long-lived URL.
*/
createSignedUrl(path: string, expiresIn?: number): Promise<StorageResponse<{
signedUrl: string;
expiresAt: string | null;
}>>;
/**
* Create signed URLs for multiple objects in a single call.
*
* Each entry resolves independently: a failure on one key (not found / not
* permitted) is reported on that entry's `error` without failing the rest.
*
* @param paths - The object keys/paths
* @param expiresIn - Lifetime in seconds (default 3600 = 1h, max 604800 = 7d)
*/
createSignedUrls(paths: string[], expiresIn?: number): Promise<StorageResponse<Array<{
path: string;
signedUrl: string | null;
error: string | null;
}>>>;
/**
* List objects in the bucket
* @param prefix - Filter by key prefix
* @param search - Search in file names
* @param limit - Maximum number of results (default: 100, max: 1000)
* @param offset - Number of results to skip
*/
list(options?: {
prefix?: string;
search?: string;
limit?: number;
offset?: number;
}): Promise<StorageResponse<ListObjectsResponseSchema>>;
/** Delete a single file. */
remove(path: string): Promise<StorageResponse<{
message: string;
}>>;
/** Delete multiple files in a single request. */
remove(paths: string[]): Promise<StorageResponse<DeleteObjectsResponse>>;
/** Delete one or more files when the input type is not narrowed. */
remove(pathOrPaths: string | string[]): Promise<StorageResponse<{
message: string;
} | DeleteObjectsResponse>>;
}
/**
* Storage module for file operations
*/
declare class Storage {
private http;
constructor(http: HttpClient);
/**
* Get a bucket instance for operations
* @param bucketName - Name of the bucket
*/
from(bucketName: string): StorageBucket;
}
/**
* AI Module for Insforge SDK
* Response format roughly matches OpenAI SDK for compatibility
*
* The backend handles all the complexity of different AI providers
* and returns a unified format. This SDK transforms responses to match OpenAI-like format.
*/
declare class AI {
private http;
readonly chat: Chat;
readonly images: Images;
readonly embeddings: Embeddings;
constructor(http: HttpClient);
}
declare class Chat {
readonly completions: ChatCompletions;
constructor(http: HttpClient);
}
declare class ChatCompletions {
private http;
constructor(http: HttpClient);
/**
* Create a chat completion - OpenAI-like response format
*
* @example
* ```typescript
* // Non-streaming
* const completion = await client.ai.chat.completions.create({
* model: 'gpt-4',
* messages: [{ role: 'user', content: 'Hello!' }]
* });
* console.log(completion.choices[0].message.content);
*
* // With images (OpenAI-compatible format)
* const response = await client.ai.chat.completions.create({
* model: 'gpt-4-vision',
* messages: [{
* role: 'user',
* content: [
* { type: 'text', text: 'What is in this image?' },
* { type: 'image_url', image_url: { url: 'https://example.com/image.jpg' } }
* ]
* }]
* });
*
* // With PDF files
* const pdfResponse = await client.ai.chat.completions.create({
* model: 'anthropic/claude-3.5-sonnet',
* messages: [{
* role: 'user',
* content: [
* { type: 'text', text: 'Summarize this document' },
* { type: 'file', file: { filename: 'doc.pdf', file_data: 'https://example.com/doc.pdf' } }
* ]
* }],
* fileParser: { enabled: true, pdf: { engine: 'mistral-ocr' } }
* });
*
* // With web search
* const searchResponse = await client.ai.chat.completions.create({
* model: 'openai/gpt-4',
* messages: [{ role: 'user', content: 'What are the latest news about AI?' }],
* webSearch: { enabled: true, maxResults: 5 }
* });
* // Access citations from response.choices[0].message.annotations
*
* // With thinking/reasoning mode (Anthropic models)
* const thinkingResponse = await client.ai.chat.completions.create({
* model: 'anthropic/claude-3.5-sonnet',
* messages: [{ role: 'user', content: 'Solve this complex math problem...' }],
* thinking: true
* });
*
* // Streaming - returns async iterable
* const stream = await client.ai.chat.completions.create({
* model: 'gpt-4',
* messages: [{ role: 'user', content: 'Tell me a story' }],
* stream: true
* });
*
* for await (const chunk of stream) {
* if (chunk.choices[0]?.delta?.content) {
* process.stdout.write(chunk.choices[0].delta.content);
* }
* }
* ```
*/
create(params: ChatCompletionRequest): Promise<any>;
/**
* Parse SSE stream into async iterable of OpenAI-like chunks
*/
private parseSSEStream;
}
declare class Embeddings {
private http;
constructor(http: HttpClient);
/**
* Create embeddings for text input - OpenAI-like response format
*
* @example
* ```typescript
* // Single text input
* const response = await client.ai.embeddings.create({
* model: 'openai/text-embedding-3-small',
* input: 'Hello world'
* });
* console.log(response.data[0].embedding); // number[]
*
* // Multiple text inputs
* const response = await client.ai.embeddings.create({
* model: 'openai/text-embedding-3-small',
* input: ['Hello world', 'Goodbye world']
* });
* response.data.forEach((item, i) => {
* console.log(`Embedding ${i}:`, item.embedding.slice(0, 5)); // First 5 dimensions
* });
*
* // With custom dimensions (if supported by model)
* const response = await client.ai.embeddings.create({
* model: 'openai/text-embedding-3-small',
* input: 'Hello world',
* dimensions: 256
* });
*
* // With base64 encoding format
* const response = await client.ai.embeddings.create({
* model: 'openai/text-embedding-3-small',
* input: 'Hello world',
* encoding_format: 'base64'
* });
* ```
*/
create(params: EmbeddingsRequest): Promise<any>;
}
declare class Images {
private http;
constructor(http: HttpClient);
/**
* Generate images - OpenAI-like response format
*
* @example
* ```typescript
* // Text-to-image
* const response = await client.ai.images.generate({
* model: 'dall-e-3',
* prompt: 'A sunset over mountains',
* });
* console.log(response.data[0].b64_json);
*
* // Image-to-image (with input images)
* const response = await client.ai.images.generate({
* model: 'stable-diffusion-xl',
* prompt: 'Transform this into a watercolor painting',
* images: [
* { url: 'https://example.com/input.jpg' },
* // or base64-encoded Data URI:
* { url: 'data:image/jpeg;base64,/9j/4AAQ...' }
* ]
* });
* ```
*/
generate(params: ImageGenerationRequest): Promise<any>;
}
interface FunctionInvokeOptions {
/**
* The body of the request
*/
body?: any;
/**
* Custom headers to send with the request
*/
headers?: Record<string, string>;
/**
* HTTP method (default: POST)
*/
method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
}
/**
* Edge Functions client for invoking serverless functions.
*
* @example
* ```typescript
* const { data, error } = await client.functions.invoke('hello-world', {
* body: { name: 'World' }
* });
* ```
*/
declare class Functions {
private http;
private functionsUrl;
constructor(http: HttpClient, functionsUrl?: string);
/**
* Derive the subhosting URL from the base URL.
* Base URL pattern: https://{appKey}.{region}.insforge.app
* Functions URL: https://{appKey}.functions.insforge.app
* Only applies to .insforge.app domains.
*/
private static deriveSubhostingUrl;
/**
* Build a Request for in-process dispatch. The host is a non-routable
* placeholder; the router only reads pathname.
*/
private buildInProcessRequest;
/**
* Invoke an Edge Function.
*
* Dispatch order:
* 1. If `globalThis.__insforge_dispatch__` is present, call it in-process.
* This avoids Deno Subhosting's 508 Loop Detected when one bundled
* function invokes another inside the same deployment.
* 2. Otherwise, try the configured subhosting URL.
* 3. On 404 from subhosting, fall back to the proxy path.
*
* @param slug The function slug to invoke
* @param options Request options
*/
invoke<T = any>(slug: string, options?: FunctionInvokeOptions): Promise<{
data: T | null;
error: InsForgeError | null;
}>;
}
type ConnectionState = 'disconnected' | 'connecting' | 'connected';
type EventCallback<T = unknown> = (payload: T) => void;
/**
* Socket.IO realtime client. Authentication is evaluated for every handshake,
* while an established socket remains authenticated until it disconnects.
*/
declare class Realtime {
private baseUrl;
private tokenManager;
private anonKey?;
private getValidAccessToken;
private socket;
private connectPromise;
private connectionAttempt;
private nextConnectionAttemptId;
private subscriptions;
private eventListeners;
constructor(baseUrl: string, tokenManager: TokenManager, anonKey?: string | undefined, getValidAccessToken?: () => Promise<string | null>);
private notifyListeners;
private getHandshakeToken;
connect(): Promise<void>;
disconnect(): void;
private reconnectForAuthChange;
private handleDisconnect;
private resubscribeChannels;
private requestSubscription;
private settleSubscription;
private applyPresenceEvent;
get isConnected(): boolean;
get connectionState(): ConnectionState;
get socketId(): string | undefined;
subscribe(channel: string): Promise<SubscribeResponse>;
unsubscribe(channel: string): void;
publish<T = unknown>(channel: string, event: string, payload: T): Promise<void>;
on<T = SocketMessage>(event: string, callback: EventCallback<T>): void;
off<T = SocketMessage>(event: string, callback: EventCallback<T>): void;
once<T = SocketMessage>(event: string, callback: EventCallback<T>): void;
getSubscribedChannels(): string[];
getPresenceState(channel: string): PresenceMember[];
}
/**
* Emails client for sending custom emails
*
* @example
* ```typescript
* // Send a simple email
* const { data, error } = await client.emails.send({
* to: 'user@example.com',
* subject: 'Welcome!',
* html: '<h1>Welcome to our platform</h1>'
* });
*
* if (error) {
* console.error('Failed to send:', error.message);
* return;
* }
* // Email sent successfully - data is {} (empty object)
*
* // Send to multiple recipients with CC
* const { data, error } = await client.emails.send({
* to: ['user1@example.com', 'user2@example.com'],
* cc: 'manager@example.com',
* subject: 'Team Update',
* html: '<p>Here is the latest update...</p>',
* replyTo: 'support@example.com'
* });
* ```
*/
declare class Emails {
private http;
constructor(http: HttpClient);
/**
* Send a custom HTML email
* @param options Email options including recipients, subject, and HTML content
*/
send(options: SendRawEmailRequest): Promise<{
data: SendEmailResponse | null;
error: InsForgeError | null;
}>;
}
interface PaymentsResponse<T> {
data: T | null;
error: InsForgeError | null;
}
/**
* Stripe runtime payment flows.
*
* These methods are safe to call from generated app frontends with the current
* user token or anon key. Admin-only Stripe key/catalog APIs are intentionally
* not exposed here.
*/
declare class StripePayments {
private http;
constructor(http: HttpClient);
/**
* Create a Stripe Checkout Session through the InsForge backend.
*
* @example
* ```typescript
* const { data, error } = await client.payments.stripe.createCheckoutSession('test', {
* mode: 'payment',
* lineItems: [{ priceId: 'price_123', quantity: 1 }],
* successUrl: `${window.location.origin}/success`,
* cancelUrl: `${window.location.origin}/pricing`
* });
*
* if (!error && data.checkoutSession.url) {
* window.location.assign(data.checkoutSession.url);
* }
* ```
*/
createCheckoutSession(environment: StripeEnvironment, request: CreateCheckoutSessionBody): Promise<PaymentsResponse<CreateCheckoutSessionResponse>>;
/**
* Create a Stripe Billing Portal Session for a mapped billing subject.
*/
createCustomerPortalSession(environment: StripeEnvironment, request: CreateCustomerPortalSessionBody): Promise<PaymentsResponse<CreateCustomerPortalSessionResponse>>;
}
/**
* Razorpay runtime payment flows.
*
* Razorpay Checkout is client-rendered: create an order or subscription here,
* pass the returned checkoutOptions to Razorpay Checkout.js, then verify the
* signed payment response with the matching verify method.
*/
declare class RazorpayPayments {
private http;
constructor(http: HttpClient);
createOrder(environment: RazorpayEnvironment, request: CreateRazorpayOrderBody): Promise<PaymentsResponse<CreateRazorpayOrderResponse>>;
verifyOrder(environment: RazorpayEnvironment, request: VerifyRazorpayOrderBody): Promise<PaymentsResponse<VerifyRazorpayOrderResponse>>;
createSubscription(environment: RazorpayEnvironment, request: CreateRazorpaySubscriptionBody): Promise<PaymentsResponse<CreateRazorpaySubscriptionResponse>>;
verifySubscription(environment: RazorpayEnvironment, request: VerifyRazorpaySubscriptionBody): Promise<PaymentsResponse<VerifyRazorpaySubscriptionResponse>>;
cancelSubscription(environment: RazorpayEnvironment, subscriptionId: string, request?: CancelRazorpaySubscriptionBodyInput): Promise<PaymentsResponse<CancelRazorpaySubscriptionResponse>>;
pauseSubscription(environment: RazorpayEnvironment, subscriptionId: string): Promise<PaymentsResponse<PauseRazorpaySubscriptionResponse>>;
resumeSubscription(environment: RazorpayEnvironment, subscriptionId: string): Promise<PaymentsResponse<ResumeRazorpaySubscriptionResponse>>;
}
/**
* Provider-scoped payments client.
*/
declare class Payments {
readonly stripe: StripePayments;
readonly razorpay: RazorpayPayments;
constructor(http: HttpClient);
}
type AccessTokenChangeEvent = typeof AuthChangeEvent.SIGNED_IN | typeof AuthChangeEvent.TOKEN_REFRESHED;
/**
* Main InsForge SDK Client
*
* @example
* ```typescript
* import { InsForgeClient } from '@insforge/sdk';
*
* const client = new InsForgeClient({
* baseUrl: 'http://localhost:7130'
* });
*
* // Authentication
* const { data, error } = await client.auth.signUp({
* email: 'user@example.com',
* password: 'password123',
* name: 'John Doe'
* });
*
* // Database operations
* const { data, error } = await client.database
* .from('posts')
* .select('*')
* .eq('user_id', session.user.id)
* .order('created_at', { ascending: false })
* .limit(10);
*
* // Insert data
* const { data: newPost } = await client.database
* .from('posts')
* .insert({ title: 'Hello', content: 'World' })
* .single();
*
* // Invoke edge functions
* const { data, error } = await client.functions.invoke('my-function', {
* body: { message: 'Hello from SDK' }
* });
*
* // Enable debug logging
* const debugClient = new InsForgeClient({
* baseUrl: 'http://localhost:7130',
* debug: true
* });
* ```
*/
declare class InsForgeClient {
private http;
private tokenManager;
readonly auth: Auth;
readonly database: Database;
readonly storage: Storage;
readonly ai: AI;
readonly functions: Functions;
readonly realtime: Realtime;
readonly emails: Emails;
readonly payments: Payments;
constructor(config?: InsForgeConfig);
/**
* Get the underlying HTTP client for custom requests
*
* @example
* ```typescript
* const httpClient = client.getHttpClient();
* const customData = await httpClient.get('/api/custom-endpoint');
* ```
*/
getHttpClient(): HttpClient;
/**
* Set the access token used by every SDK surface. Updates both the HTTP
* client (database / storage / functions / AI / emails) and the realtime
* token manager. Pass `null` to sign out. By default a token replacement is
* treated as a sign-in boundary and reconnects realtime. Pass
* `AuthChangeEvent.TOKEN_REFRESHED` for a same-identity refresh to preserve a live socket; the
* refreshed token is then used at the next handshake.
*
* Use this when an external auth provider (Better Auth, Clerk, Auth0,
* WorkOS, Kinde, Stytch, …) issues the JWT and you need to keep the
* long-lived InsForge client in sync. Without this, you'd have to call
* `client.getHttpClient().setAuthToken(token)` AND reach into the private
* realtime token manager separately.
*
* @example
* ```typescript
* import { AuthChangeEvent } from '@insforge/sdk';
*
* // Refresh a third-party-issued JWT periodically
* const { token } = await fetch('/api/insforge-token').then((r) => r.json());
* client.setAccessToken(token, AuthChangeEvent.TOKEN_REFRESHED);
*
* // Sign-out
* client.setAccessToken(null);
* ```
*/
setAccessToken(token: string | null, event?: AccessTokenChangeEvent): void;
}
export { type AccessTokenChangeEvent as A, type ConnectionState as C, Database as D, Emails as E, Functions as F, HttpClient as H, InsForgeClient as I, Logger as L, type PasswordSessionRequest as P, Realtime as R, Storage as S, type VerifyOtpRequest as V, Auth as a, StorageBucket as b, type StorageResponse as c, AI as d, type FunctionInvokeOptions as e, Payments as f, type PaymentsResponse as g, type EventCallback as h, AuthChangeEvent as i, type AuthStateChangeCallback as j };
+3
-3

@@ -1,6 +0,6 @@

import { I as InsForgeClient } from './client-Bi-sr540.mjs';
export { d as AI, A as AccessTokenChangeEvent, a as Auth, h as AuthChangeEvent, i as AuthStateChangeCallback, C as ConnectionState, D as Database, E as Emails, g as EventCallback, e as FunctionInvokeOptions, F as Functions, H as HttpClient, L as Logger, P as Payments, f as PaymentsResponse, R as Realtime, S as Storage, b as StorageBucket, c as StorageResponse } from './client-Bi-sr540.mjs';
import { I as InsForgeClient } from './client-BjhyKtje.mjs';
export { d as AI, A as AccessTokenChangeEvent, a as Auth, i as AuthChangeEvent, j as AuthStateChangeCallback, C as ConnectionState, D as Database, E as Emails, h as EventCallback, e as FunctionInvokeOptions, F as Functions, H as HttpClient, L as Logger, P as PasswordSessionRequest, f as Payments, g as PaymentsResponse, R as Realtime, S as Storage, b as StorageBucket, c as StorageResponse, V as VerifyOtpRequest } from './client-BjhyKtje.mjs';
import { I as InsForgeConfig, a as InsForgeAdminConfig } from './types-MKmYAYeg.mjs';
export { b as ApiError, A as AuthSession, d as InsForgeError, c as InsForgeErrorCode } from './types-MKmYAYeg.mjs';
export { AuthErrorResponse, CreateSessionRequest, CreateUserRequest, RealtimeErrorPayload, SendRawEmailRequest as SendEmailOptions, SendEmailResponse, SocketMessage, SubscribeResponse, UserSchema } from '@insforge/shared-schemas';
export { AuthErrorResponse, CreateSessionRequest, CreateUserRequest, DeleteObjectResult, DeleteObjectsResponse, RealtimeErrorPayload, SendRawEmailRequest as SendEmailOptions, SendEmailResponse, SendOTPRequest, SocketMessage, SubscribeResponse, UserSchema } from '@insforge/shared-schemas';
import '@supabase/postgrest-js';

@@ -7,0 +7,0 @@

@@ -1,6 +0,6 @@

import { I as InsForgeClient } from './client-BauEtpem.js';
export { d as AI, A as AccessTokenChangeEvent, a as Auth, h as AuthChangeEvent, i as AuthStateChangeCallback, C as ConnectionState, D as Database, E as Emails, g as EventCallback, e as FunctionInvokeOptions, F as Functions, H as HttpClient, L as Logger, P as Payments, f as PaymentsResponse, R as Realtime, S as Storage, b as StorageBucket, c as StorageResponse } from './client-BauEtpem.js';
import { I as InsForgeClient } from './client-BS9Xf-qE.js';
export { d as AI, A as AccessTokenChangeEvent, a as Auth, i as AuthChangeEvent, j as AuthStateChangeCallback, C as ConnectionState, D as Database, E as Emails, h as EventCallback, e as FunctionInvokeOptions, F as Functions, H as HttpClient, L as Logger, P as PasswordSessionRequest, f as Payments, g as PaymentsResponse, R as Realtime, S as Storage, b as StorageBucket, c as StorageResponse, V as VerifyOtpRequest } from './client-BS9Xf-qE.js';
import { I as InsForgeConfig, a as InsForgeAdminConfig } from './types-MKmYAYeg.js';
export { b as ApiError, A as AuthSession, d as InsForgeError, c as InsForgeErrorCode } from './types-MKmYAYeg.js';
export { AuthErrorResponse, CreateSessionRequest, CreateUserRequest, RealtimeErrorPayload, SendRawEmailRequest as SendEmailOptions, SendEmailResponse, SocketMessage, SubscribeResponse, UserSchema } from '@insforge/shared-schemas';
export { AuthErrorResponse, CreateSessionRequest, CreateUserRequest, DeleteObjectResult, DeleteObjectsResponse, RealtimeErrorPayload, SendRawEmailRequest as SendEmailOptions, SendEmailResponse, SendOTPRequest, SocketMessage, SubscribeResponse, UserSchema } from '@insforge/shared-schemas';
import '@supabase/postgrest-js';

@@ -7,0 +7,0 @@

@@ -1,2 +0,2 @@

import { I as InsForgeClient } from './client-Bi-sr540.mjs';
import { I as InsForgeClient } from './client-BjhyKtje.mjs';
import { I as InsForgeConfig, e as AuthRefreshResponse, d as InsForgeError } from './types-MKmYAYeg.mjs';

@@ -74,2 +74,4 @@ import { A as AuthCookieSettings, C as CookieStore, a as CookieWriter } from './middleware-o3zPqPvY.mjs';

verifyEmail: SafeAuthAction<InsForgeClient['auth']['verifyEmail']>;
signInWithOtp: InsForgeClient['auth']['signInWithOtp'];
verifyOtp: SafeAuthAction<InsForgeClient['auth']['verifyOtp']>;
signOut: InsForgeClient['auth']['signOut'];

@@ -76,0 +78,0 @@ }

@@ -1,2 +0,2 @@

import { I as InsForgeClient } from './client-BauEtpem.js';
import { I as InsForgeClient } from './client-BS9Xf-qE.js';
import { I as InsForgeConfig, e as AuthRefreshResponse, d as InsForgeError } from './types-MKmYAYeg.js';

@@ -74,2 +74,4 @@ import { A as AuthCookieSettings, C as CookieStore, a as CookieWriter } from './middleware-CicBLgnO.js';

verifyEmail: SafeAuthAction<InsForgeClient['auth']['verifyEmail']>;
signInWithOtp: InsForgeClient['auth']['signInWithOtp'];
verifyOtp: SafeAuthAction<InsForgeClient['auth']['verifyOtp']>;
signOut: InsForgeClient['auth']['signOut'];

@@ -76,0 +78,0 @@ }

{
"name": "@insforge/sdk",
"version": "1.5.0",
"version": "1.5.1",
"description": "Official JavaScript/TypeScript client for InsForge Backend-as-a-Service platform",

@@ -44,3 +44,3 @@ "main": "./dist/index.js",

"format:check": "prettier --check .",
"typecheck": "tsc --noEmit",
"typecheck": "tsc --noEmit && tsc -p tsconfig.type-tests.json",
"publish:dev": "npm version prerelease --preid=dev && npm run build && npm publish --tag dev",

@@ -69,3 +69,3 @@ "publish:stable": "npm run build && npm publish"

"dependencies": {
"@insforge/shared-schemas": "^1.1.58",
"@insforge/shared-schemas": "^1.2.1",
"@supabase/postgrest-js": "^1.21.3",

@@ -72,0 +72,0 @@ "socket.io-client": "^4.8.1"

@@ -215,4 +215,10 @@ # insforge-sdk-js

// Delete a file
const { data, error } = await insforge.storage.from('avatars').remove(['user-avatar.png']);
const { data, error } = await insforge.storage.from('avatars').remove('user-avatar.png');
// Delete multiple files (maximum 1000 keys)
const { data, error } = await insforge.storage
.from('avatars')
.remove(['user-avatar.png', 'old-avatar.png']);
// data: { results: [{ key, status: 'deleted' | 'notFound' | 'failed', message? }] }
// List files

@@ -219,0 +225,0 @@ const { data, error } = await insforge.storage.from('avatars').list();

@@ -746,4 +746,10 @@ # InsForge SDK Reference

```javascript
// Delete one object
await bucket.remove('path/file.jpg');
// Response: { data: { message }, error }
// Delete multiple objects in one request (maximum 1000 keys)
await bucket.remove(['path/a.jpg', 'path/b.txt']);
// Response: { data: { results }, error }
// results: { key, status: 'deleted' | 'notFound' | 'failed', message? }[]
```

@@ -750,0 +756,0 @@

import { A as AuthSession, I as InsForgeConfig, e as AuthRefreshResponse, d as InsForgeError } from './types-MKmYAYeg.js';
import { UserSchema, CreateUserRequest, CreateUserResponse, CreateSessionRequest, CreateSessionResponse, OAuthProvidersSchema, RefreshSessionResponse, GetProfileResponse, SendVerificationEmailRequest, VerifyEmailRequest, VerifyEmailResponse, SendResetPasswordEmailRequest, ExchangeResetPasswordTokenRequest, ExchangeResetPasswordTokenResponse, ResetPasswordResponse, GetPublicAuthConfigResponse, StorageFileSchema, ListObjectsResponseSchema, ChatCompletionRequest, ImageGenerationRequest, EmbeddingsRequest, SubscribeResponse, SocketMessage, PresenceMember, SendRawEmailRequest, SendEmailResponse, StripeEnvironment, CreateCheckoutSessionBody, CreateCheckoutSessionResponse, CreateCustomerPortalSessionBody, CreateCustomerPortalSessionResponse, RazorpayEnvironment, CreateRazorpayOrderBody, CreateRazorpayOrderResponse, VerifyRazorpayOrderBody, VerifyRazorpayOrderResponse, CreateRazorpaySubscriptionBody, CreateRazorpaySubscriptionResponse, VerifyRazorpaySubscriptionBody, VerifyRazorpaySubscriptionResponse, CancelRazorpaySubscriptionBodyInput, CancelRazorpaySubscriptionResponse, PauseRazorpaySubscriptionResponse, ResumeRazorpaySubscriptionResponse } from '@insforge/shared-schemas';
import * as _supabase_postgrest_js from '@supabase/postgrest-js';
import { PostgrestClient } from '@supabase/postgrest-js';
type LogFunction = (message: string, ...args: any[]) => void;
/**
* Debug logger for the InsForge SDK.
* Logs HTTP request/response details with automatic redaction of sensitive data.
*
* @example
* ```typescript
* // Enable via SDK config
* const client = new InsForgeClient({ debug: true });
*
* // Or with a custom log function
* const client = new InsForgeClient({
* debug: (msg) => myLogger.info(msg)
* });
* ```
*/
declare class Logger {
/** Whether debug logging is currently enabled */
enabled: boolean;
private customLog;
/**
* Creates a new Logger instance.
* @param debug - Set to true to enable console logging, or pass a custom log function
*/
constructor(debug?: boolean | LogFunction);
/**
* Logs a debug message at the info level.
* @param message - The message to log
* @param args - Additional arguments to pass to the log function
*/
log(message: string, ...args: any[]): void;
/**
* Logs a debug message at the warning level.
* @param message - The message to log
* @param args - Additional arguments to pass to the log function
*/
warn(message: string, ...args: any[]): void;
/**
* Logs a debug message at the error level.
* @param message - The message to log
* @param args - Additional arguments to pass to the log function
*/
error(message: string, ...args: any[]): void;
/**
* Logs an outgoing HTTP request with method, URL, headers, and body.
* Sensitive headers and body fields are automatically redacted.
* @param method - HTTP method (GET, POST, etc.)
* @param url - The full request URL
* @param headers - Request headers (sensitive values will be redacted)
* @param body - Request body (sensitive fields will be masked)
*/
logRequest(method: string, url: string, headers?: Record<string, string>, body?: any): void;
/**
* Logs an incoming HTTP response with method, URL, status, duration, and body.
* Error responses (4xx/5xx) are logged at the error level.
* @param method - HTTP method (GET, POST, etc.)
* @param url - The full request URL
* @param status - HTTP response status code
* @param durationMs - Request duration in milliseconds
* @param body - Response body (sensitive fields will be masked, large bodies truncated)
*/
logResponse(method: string, url: string, status: number, durationMs: number, body?: any): void;
}
/**
* Token Manager for InsForge SDK
*
* Memory-only token storage.
*/
declare const AuthChangeEvent: {
readonly SIGNED_IN: "signedIn";
readonly SIGNED_OUT: "signedOut";
readonly TOKEN_REFRESHED: "tokenRefreshed";
};
type AuthChangeEvent = (typeof AuthChangeEvent)[keyof typeof AuthChangeEvent];
type AuthStateChangeCallback = (event: AuthChangeEvent) => void;
declare class TokenManager {
private accessToken;
private user;
private authStateChangeCallbacks;
constructor();
/**
* Save session in memory
*/
saveSession(session: AuthSession, event?: AuthChangeEvent): void;
/**
* Get current session
*/
getSession(): AuthSession | null;
/**
* Get access token
*/
getAccessToken(): string | null;
/**
* Set access token
*/
setAccessToken(token: string, event?: AuthChangeEvent): void;
/**
* Get user
*/
getUser(): UserSchema | null;
/**
* Set user
*/
setUser(user: UserSchema): void;
/**
* Clear in-memory session
*/
clearSession(): void;
onAuthStateChange(callback: AuthStateChangeCallback): () => void;
private notifyAuthStateChange;
}
type JsonRequestBody = Record<string, unknown> | unknown[] | null;
interface RequestOptions extends Omit<RequestInit, 'body'> {
params?: Record<string, string>;
body?: RequestInit['body'] | JsonRequestBody;
/** Allow retrying non-idempotent requests (POST, PATCH). Off by default to prevent duplicate writes. */
idempotent?: boolean;
/** Disable automatic access-token refresh for auth/control-flow requests. */
skipAuthRefresh?: boolean;
}
/**
* HTTP client with built-in retry, timeout, and exponential backoff support.
* Handles authentication, request serialization, and error normalization.
*/
declare class HttpClient {
readonly baseUrl: string;
readonly fetch: typeof fetch;
private readonly config;
private defaultHeaders;
private anonKey;
private userToken;
private logger;
private isRefreshing;
private refreshPromise;
private tokenManager;
private refreshToken;
private timeout;
private retryCount;
private retryDelay;
/**
* Creates a new HttpClient instance.
* @param config - SDK configuration including baseUrl, timeout, retry settings, and fetch implementation.
* @param tokenManager - Token manager for session persistence.
* @param logger - Optional logger instance for request/response debugging.
*/
constructor(config: InsForgeConfig, tokenManager?: TokenManager, logger?: Logger);
/**
* Builds a full URL from a path and optional query parameters.
* Normalizes PostgREST select parameters for proper syntax.
*/
private buildUrl;
/** Checks if an HTTP status code is eligible for retry (5xx server errors). */
private isRetryableStatus;
/**
* Computes the delay before the next retry using exponential backoff with jitter.
* @param attempt - The current retry attempt number (1-based).
* @returns Delay in milliseconds.
*/
private computeRetryDelay;
private shouldRefreshAccessToken;
private fetchWithRetry;
/**
* Performs an HTTP request with automatic retry and timeout handling.
* Retries on network errors and 5xx server errors with exponential backoff.
* Client errors (4xx) and timeouts are thrown immediately without retry.
* @param method - HTTP method (GET, POST, PUT, PATCH, DELETE).
* @param path - API path relative to the base URL.
* @param options - Optional request configuration including headers, body, and query params.
* @returns Parsed response data.
* @throws {InsForgeError} On timeout, network failure, or HTTP error responses.
*/
private handleRequest;
request<T>(method: string, path: string, options?: RequestOptions): Promise<T>;
/**
* Performs an SDK-configured fetch and returns the raw Response.
* This is used by clients such as postgrest-js that need to own response
* parsing while still sharing SDK auth and refresh behavior.
*/
rawFetch(input: RequestInfo | URL, init?: RequestInit, options?: {
skipAuthRefresh?: boolean;
}): Promise<Response>;
/** Performs a GET request. */
get<T>(path: string, options?: RequestOptions): Promise<T>;
/** Performs a POST request with an optional JSON body. */
post<T>(path: string, body?: any, options?: RequestOptions): Promise<T>;
/** Performs a PUT request with an optional JSON body. */
put<T>(path: string, body?: any, options?: RequestOptions): Promise<T>;
/** Performs a PATCH request with an optional JSON body. */
patch<T>(path: string, body?: any, options?: RequestOptions): Promise<T>;
/** Performs a DELETE request. */
delete<T>(path: string, options?: RequestOptions): Promise<T>;
/** Sets or clears the user authentication token for subsequent requests. */
setAuthToken(token: string | null): void;
setRefreshToken(token: string | null): void;
/** Returns the current default headers including the authorization header if set. */
getHeaders(): Record<string, string>;
refreshAccessToken(): Promise<AuthRefreshResponse>;
/** Returns a token safe to use for a new connection handshake. */
getValidAccessToken(leewaySeconds?: number): Promise<string | null>;
private refreshAndSaveSession;
private clearAuthSession;
}
/**
* Auth module for InsForge SDK
* Handles authentication, sessions, profiles, and email verification
*/
interface AuthOptions {
isServerMode?: boolean;
detectOAuthCallback?: boolean;
}
type OAuthSignInOptions = {
redirectTo: string;
additionalParams?: Record<string, string>;
skipBrowserRedirect?: boolean;
};
type OAuthSignInLegacyOptions = OAuthSignInOptions & {
provider: OAuthProvidersSchema | string;
};
declare class Auth {
private http;
private tokenManager;
private options;
private authCallbackHandled;
constructor(http: HttpClient, tokenManager: TokenManager, options?: AuthOptions);
private isServerMode;
/** Subscribe to SDK authentication state changes. */
onAuthStateChange(callback: AuthStateChangeCallback): () => void;
/**
* Save session from API response
* Handles token storage, CSRF token, and HTTP auth header
*/
private saveSessionFromResponse;
/**
* Detect and handle OAuth callback parameters in URL
* Supports PKCE flow (insforge_code)
*/
private detectAuthCallback;
signUp(request: CreateUserRequest): Promise<{
data: CreateUserResponse | null;
error: InsForgeError | null;
}>;
signInWithPassword(request: CreateSessionRequest): Promise<{
data: CreateSessionResponse | null;
error: InsForgeError | null;
}>;
signOut(): Promise<{
error: InsForgeError | null;
}>;
/**
* Sign in with OAuth provider using PKCE flow
*/
signInWithOAuth(provider: OAuthProvidersSchema | string, options: OAuthSignInOptions): Promise<{
data: {
url?: string;
provider?: string;
codeVerifier?: string;
};
error: InsForgeError | null;
}>;
/**
* @deprecated Use signInWithOAuth(provider, { redirectTo, additionalParams, skipBrowserRedirect }).
*/
signInWithOAuth(options: OAuthSignInLegacyOptions): Promise<{
data: {
url?: string;
provider?: string;
codeVerifier?: string;
};
error: InsForgeError | null;
}>;
/**
* Exchange OAuth authorization code for tokens (PKCE flow)
* Called automatically on initialization when insforge_code is in URL
*/
exchangeOAuthCode(code: string, codeVerifier?: string): Promise<{
data: CreateSessionResponse | null;
error: InsForgeError | null;
}>;
/**
* Sign in with an ID token from a native SDK (Google One Tap, etc.)
* Use this for native mobile apps or Google One Tap on web.
*
* @param credentials.provider - The identity provider (currently only 'google' is supported)
* @param credentials.token - The ID token from the native SDK
*/
signInWithIdToken(credentials: {
provider: 'google';
token: string;
}): Promise<{
data: CreateSessionResponse | null;
error: InsForgeError | null;
}>;
/**
* Refresh the current auth session.
*
* Browser mode:
* - Uses httpOnly refresh cookie and optional CSRF header.
*
* Legacy server mode (`isServerMode: true`):
* - Uses mobile auth flow and requires `refreshToken` in request body.
*
* SSR apps should prefer `createRefreshAuthRouter()` / `refreshAuth()` from
* `@insforge/sdk/ssr`.
*/
refreshSession(options?: {
refreshToken?: string;
}): Promise<{
data: RefreshSessionResponse | null;
error: InsForgeError | null;
}>;
/**
* Get current user, automatically waits for pending OAuth callback
*/
getCurrentUser(): Promise<{
data: {
user: UserSchema | null;
};
error: InsForgeError | null;
}>;
getProfile(userId: string): Promise<{
data: GetProfileResponse | null;
error: InsForgeError | null;
}>;
setProfile(profile: Record<string, unknown>): Promise<{
data: GetProfileResponse | null;
error: InsForgeError | null;
}>;
resendVerificationEmail(request: SendVerificationEmailRequest): Promise<{
data: {
success: boolean;
message: string;
} | null;
error: InsForgeError | null;
}>;
verifyEmail(request: VerifyEmailRequest): Promise<{
data: VerifyEmailResponse | null;
error: InsForgeError | null;
}>;
sendResetPasswordEmail(request: SendResetPasswordEmailRequest): Promise<{
data: {
success: boolean;
message: string;
} | null;
error: InsForgeError | null;
}>;
exchangeResetPasswordToken(request: ExchangeResetPasswordTokenRequest): Promise<{
data: ExchangeResetPasswordTokenResponse | null;
error: InsForgeError | null;
}>;
resetPassword(request: {
newPassword: string;
otp: string;
}): Promise<{
data: ResetPasswordResponse | null;
error: InsForgeError | null;
}>;
getPublicAuthConfig(): Promise<{
data: GetPublicAuthConfigResponse | null;
error: InsForgeError | null;
}>;
}
/**
* Database client using postgrest-js
* Drop-in replacement with FULL PostgREST capabilities
*/
declare class Database {
private postgrest;
constructor(httpClient: HttpClient, defaultSchema?: string);
/**
* Select a non-default Postgres schema for the chained query. Maps to
* PostgREST's `Accept-Profile` (reads) / `Content-Profile` (writes) header.
* The schema must be exposed by the backend.
*
* @example
* const { data } = await client.database
* .schema('analytics')
* .from('events')
* .select('*');
*
* @example
* await client.database.schema('analytics').rpc('rollup', { day: '2026-01-01' });
*/
schema(schemaName: string): PostgrestClient<any, any, string, any>;
/**
* Create a query builder for a table
*
* @example
* // Basic query
* const { data, error } = await client.database
* .from('posts')
* .select('*')
* .eq('user_id', userId);
*
* // With count (Supabase style!)
* const { data, error, count } = await client.database
* .from('posts')
* .select('*', { count: 'exact' })
* .range(0, 9);
*
* // Just get count, no data
* const { count } = await client.database
* .from('posts')
* .select('*', { count: 'exact', head: true });
*
* // Complex queries with OR
* const { data } = await client.database
* .from('posts')
* .select('*, users!inner(*)')
* .or('status.eq.active,status.eq.pending');
*
* // All features work:
* - Nested selects
* - Foreign key expansion
* - OR/AND/NOT conditions
* - Count with head
* - Range pagination
* - Upserts
*/
from(table: string): _supabase_postgrest_js.PostgrestQueryBuilder<any, any, any, string, unknown>;
/**
* Call a PostgreSQL function (RPC)
*
* @example
* // Call a function with parameters
* const { data, error } = await client.database
* .rpc('get_user_stats', { user_id: 123 });
*
* // Call a function with no parameters
* const { data, error } = await client.database
* .rpc('get_all_active_users');
*
* // With options (head, count, get)
* const { data, count } = await client.database
* .rpc('search_posts', { query: 'hello' }, { count: 'exact' });
*/
rpc(fn: string, args?: Record<string, unknown>, options?: {
head?: boolean;
get?: boolean;
count?: 'exact' | 'planned' | 'estimated';
}): _supabase_postgrest_js.PostgrestFilterBuilder<any, any, any, any, string, null, "RPC">;
}
/**
* Storage module for InsForge SDK
* Handles file uploads, downloads, and bucket management
*/
interface StorageResponse<T> {
data: T | null;
error: InsForgeError | null;
}
/**
* Storage bucket operations
*/
declare class StorageBucket {
private bucketName;
private http;
constructor(bucketName: string, http: HttpClient);
/**
* Upload a file to a specific key.
* Uses the upload strategy from the backend (direct or presigned).
* Standard PUT semantics: uploading to an existing key replaces the
* current object in place.
* @param path - The object key/path
* @param file - File or Blob to upload
*/
upload(path: string, file: File | Blob): Promise<StorageResponse<StorageFileSchema>>;
/**
* Upload a file under an automatically generated, collision-free key.
* The key is derived client-side from the filename (sanitized base +
* timestamp + random suffix) and uploaded through the standard
* {@link upload} path, so repeated uploads of the same file never
* overwrite each other. Reads the filename structurally to avoid assuming
* a global `File` (which Node 18 does not expose).
* @param file - File or Blob to upload
*/
uploadAuto(file: File | Blob): Promise<StorageResponse<StorageFileSchema>>;
/**
* Internal method to handle presigned URL uploads
*/
private uploadWithPresignedUrl;
/**
* Download a file
* Uses the download strategy from backend (direct or presigned)
* @param path - The object key/path
* Returns the file as a Blob
*/
download(path: string): Promise<{
data: Blob | null;
error: InsForgeError | null;
}>;
/**
* Get the public URL for an object in a public bucket.
*
* Pure string construction — no network call, no auth. The URL only resolves
* if the bucket is public; for private objects use {@link createSignedUrl}.
*
* @param path - The object key/path
* @returns `{ data: { publicUrl }, error }` — matches the external SDK pattern,
* so `const { data } = getPublicUrl(path)` then `data.publicUrl`.
*/
getPublicUrl(path: string): StorageResponse<{
publicUrl: string;
}>;
/**
* Resolve a download strategy (signed or direct URL) for an object with a
* caller-supplied TTL. Prefers the canonical GET route and falls back to the
* legacy POST alias so signed-URL creation still works against older backends
* that predate the GET route (they return 404/405 for it). A genuine
* "object not found" (STORAGE_NOT_FOUND) is not retried.
*/
private requestDownloadStrategy;
/**
* Create a signed URL for an object.
*
* Returns a time-limited, credential-free URL that can be handed directly to
* a browser (`<img src>`), an email, or a third party — no SDK or session is
* needed to fetch it. Authorization is enforced when the URL is minted (the
* caller must be allowed to read the object), so the resulting link is a
* pre-authorized capability scoped to this one object until it expires.
*
* @param path - The object key/path
* @param expiresIn - Lifetime in seconds (default 3600 = 1h, max 604800 = 7d).
* Honored for private buckets; public buckets return their long-lived URL.
*/
createSignedUrl(path: string, expiresIn?: number): Promise<StorageResponse<{
signedUrl: string;
expiresAt: string | null;
}>>;
/**
* Create signed URLs for multiple objects in a single call.
*
* Each entry resolves independently: a failure on one key (not found / not
* permitted) is reported on that entry's `error` without failing the rest.
*
* @param paths - The object keys/paths
* @param expiresIn - Lifetime in seconds (default 3600 = 1h, max 604800 = 7d)
*/
createSignedUrls(paths: string[], expiresIn?: number): Promise<StorageResponse<Array<{
path: string;
signedUrl: string | null;
error: string | null;
}>>>;
/**
* List objects in the bucket
* @param prefix - Filter by key prefix
* @param search - Search in file names
* @param limit - Maximum number of results (default: 100, max: 1000)
* @param offset - Number of results to skip
*/
list(options?: {
prefix?: string;
search?: string;
limit?: number;
offset?: number;
}): Promise<StorageResponse<ListObjectsResponseSchema>>;
/**
* Delete a file
* @param path - The object key/path
*/
remove(path: string): Promise<StorageResponse<{
message: string;
}>>;
}
/**
* Storage module for file operations
*/
declare class Storage {
private http;
constructor(http: HttpClient);
/**
* Get a bucket instance for operations
* @param bucketName - Name of the bucket
*/
from(bucketName: string): StorageBucket;
}
/**
* AI Module for Insforge SDK
* Response format roughly matches OpenAI SDK for compatibility
*
* The backend handles all the complexity of different AI providers
* and returns a unified format. This SDK transforms responses to match OpenAI-like format.
*/
declare class AI {
private http;
readonly chat: Chat;
readonly images: Images;
readonly embeddings: Embeddings;
constructor(http: HttpClient);
}
declare class Chat {
readonly completions: ChatCompletions;
constructor(http: HttpClient);
}
declare class ChatCompletions {
private http;
constructor(http: HttpClient);
/**
* Create a chat completion - OpenAI-like response format
*
* @example
* ```typescript
* // Non-streaming
* const completion = await client.ai.chat.completions.create({
* model: 'gpt-4',
* messages: [{ role: 'user', content: 'Hello!' }]
* });
* console.log(completion.choices[0].message.content);
*
* // With images (OpenAI-compatible format)
* const response = await client.ai.chat.completions.create({
* model: 'gpt-4-vision',
* messages: [{
* role: 'user',
* content: [
* { type: 'text', text: 'What is in this image?' },
* { type: 'image_url', image_url: { url: 'https://example.com/image.jpg' } }
* ]
* }]
* });
*
* // With PDF files
* const pdfResponse = await client.ai.chat.completions.create({
* model: 'anthropic/claude-3.5-sonnet',
* messages: [{
* role: 'user',
* content: [
* { type: 'text', text: 'Summarize this document' },
* { type: 'file', file: { filename: 'doc.pdf', file_data: 'https://example.com/doc.pdf' } }
* ]
* }],
* fileParser: { enabled: true, pdf: { engine: 'mistral-ocr' } }
* });
*
* // With web search
* const searchResponse = await client.ai.chat.completions.create({
* model: 'openai/gpt-4',
* messages: [{ role: 'user', content: 'What are the latest news about AI?' }],
* webSearch: { enabled: true, maxResults: 5 }
* });
* // Access citations from response.choices[0].message.annotations
*
* // With thinking/reasoning mode (Anthropic models)
* const thinkingResponse = await client.ai.chat.completions.create({
* model: 'anthropic/claude-3.5-sonnet',
* messages: [{ role: 'user', content: 'Solve this complex math problem...' }],
* thinking: true
* });
*
* // Streaming - returns async iterable
* const stream = await client.ai.chat.completions.create({
* model: 'gpt-4',
* messages: [{ role: 'user', content: 'Tell me a story' }],
* stream: true
* });
*
* for await (const chunk of stream) {
* if (chunk.choices[0]?.delta?.content) {
* process.stdout.write(chunk.choices[0].delta.content);
* }
* }
* ```
*/
create(params: ChatCompletionRequest): Promise<any>;
/**
* Parse SSE stream into async iterable of OpenAI-like chunks
*/
private parseSSEStream;
}
declare class Embeddings {
private http;
constructor(http: HttpClient);
/**
* Create embeddings for text input - OpenAI-like response format
*
* @example
* ```typescript
* // Single text input
* const response = await client.ai.embeddings.create({
* model: 'openai/text-embedding-3-small',
* input: 'Hello world'
* });
* console.log(response.data[0].embedding); // number[]
*
* // Multiple text inputs
* const response = await client.ai.embeddings.create({
* model: 'openai/text-embedding-3-small',
* input: ['Hello world', 'Goodbye world']
* });
* response.data.forEach((item, i) => {
* console.log(`Embedding ${i}:`, item.embedding.slice(0, 5)); // First 5 dimensions
* });
*
* // With custom dimensions (if supported by model)
* const response = await client.ai.embeddings.create({
* model: 'openai/text-embedding-3-small',
* input: 'Hello world',
* dimensions: 256
* });
*
* // With base64 encoding format
* const response = await client.ai.embeddings.create({
* model: 'openai/text-embedding-3-small',
* input: 'Hello world',
* encoding_format: 'base64'
* });
* ```
*/
create(params: EmbeddingsRequest): Promise<any>;
}
declare class Images {
private http;
constructor(http: HttpClient);
/**
* Generate images - OpenAI-like response format
*
* @example
* ```typescript
* // Text-to-image
* const response = await client.ai.images.generate({
* model: 'dall-e-3',
* prompt: 'A sunset over mountains',
* });
* console.log(response.data[0].b64_json);
*
* // Image-to-image (with input images)
* const response = await client.ai.images.generate({
* model: 'stable-diffusion-xl',
* prompt: 'Transform this into a watercolor painting',
* images: [
* { url: 'https://example.com/input.jpg' },
* // or base64-encoded Data URI:
* { url: 'data:image/jpeg;base64,/9j/4AAQ...' }
* ]
* });
* ```
*/
generate(params: ImageGenerationRequest): Promise<any>;
}
interface FunctionInvokeOptions {
/**
* The body of the request
*/
body?: any;
/**
* Custom headers to send with the request
*/
headers?: Record<string, string>;
/**
* HTTP method (default: POST)
*/
method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
}
/**
* Edge Functions client for invoking serverless functions.
*
* @example
* ```typescript
* const { data, error } = await client.functions.invoke('hello-world', {
* body: { name: 'World' }
* });
* ```
*/
declare class Functions {
private http;
private functionsUrl;
constructor(http: HttpClient, functionsUrl?: string);
/**
* Derive the subhosting URL from the base URL.
* Base URL pattern: https://{appKey}.{region}.insforge.app
* Functions URL: https://{appKey}.functions.insforge.app
* Only applies to .insforge.app domains.
*/
private static deriveSubhostingUrl;
/**
* Build a Request for in-process dispatch. The host is a non-routable
* placeholder; the router only reads pathname.
*/
private buildInProcessRequest;
/**
* Invoke an Edge Function.
*
* Dispatch order:
* 1. If `globalThis.__insforge_dispatch__` is present, call it in-process.
* This avoids Deno Subhosting's 508 Loop Detected when one bundled
* function invokes another inside the same deployment.
* 2. Otherwise, try the configured subhosting URL.
* 3. On 404 from subhosting, fall back to the proxy path.
*
* @param slug The function slug to invoke
* @param options Request options
*/
invoke<T = any>(slug: string, options?: FunctionInvokeOptions): Promise<{
data: T | null;
error: InsForgeError | null;
}>;
}
type ConnectionState = 'disconnected' | 'connecting' | 'connected';
type EventCallback<T = unknown> = (payload: T) => void;
/**
* Socket.IO realtime client. Authentication is evaluated for every handshake,
* while an established socket remains authenticated until it disconnects.
*/
declare class Realtime {
private baseUrl;
private tokenManager;
private anonKey?;
private getValidAccessToken;
private socket;
private connectPromise;
private connectionAttempt;
private nextConnectionAttemptId;
private subscriptions;
private eventListeners;
constructor(baseUrl: string, tokenManager: TokenManager, anonKey?: string | undefined, getValidAccessToken?: () => Promise<string | null>);
private notifyListeners;
private getHandshakeToken;
connect(): Promise<void>;
disconnect(): void;
private reconnectForAuthChange;
private handleDisconnect;
private resubscribeChannels;
private requestSubscription;
private settleSubscription;
private applyPresenceEvent;
get isConnected(): boolean;
get connectionState(): ConnectionState;
get socketId(): string | undefined;
subscribe(channel: string): Promise<SubscribeResponse>;
unsubscribe(channel: string): void;
publish<T = unknown>(channel: string, event: string, payload: T): Promise<void>;
on<T = SocketMessage>(event: string, callback: EventCallback<T>): void;
off<T = SocketMessage>(event: string, callback: EventCallback<T>): void;
once<T = SocketMessage>(event: string, callback: EventCallback<T>): void;
getSubscribedChannels(): string[];
getPresenceState(channel: string): PresenceMember[];
}
/**
* Emails client for sending custom emails
*
* @example
* ```typescript
* // Send a simple email
* const { data, error } = await client.emails.send({
* to: 'user@example.com',
* subject: 'Welcome!',
* html: '<h1>Welcome to our platform</h1>'
* });
*
* if (error) {
* console.error('Failed to send:', error.message);
* return;
* }
* // Email sent successfully - data is {} (empty object)
*
* // Send to multiple recipients with CC
* const { data, error } = await client.emails.send({
* to: ['user1@example.com', 'user2@example.com'],
* cc: 'manager@example.com',
* subject: 'Team Update',
* html: '<p>Here is the latest update...</p>',
* replyTo: 'support@example.com'
* });
* ```
*/
declare class Emails {
private http;
constructor(http: HttpClient);
/**
* Send a custom HTML email
* @param options Email options including recipients, subject, and HTML content
*/
send(options: SendRawEmailRequest): Promise<{
data: SendEmailResponse | null;
error: InsForgeError | null;
}>;
}
interface PaymentsResponse<T> {
data: T | null;
error: InsForgeError | null;
}
/**
* Stripe runtime payment flows.
*
* These methods are safe to call from generated app frontends with the current
* user token or anon key. Admin-only Stripe key/catalog APIs are intentionally
* not exposed here.
*/
declare class StripePayments {
private http;
constructor(http: HttpClient);
/**
* Create a Stripe Checkout Session through the InsForge backend.
*
* @example
* ```typescript
* const { data, error } = await client.payments.stripe.createCheckoutSession('test', {
* mode: 'payment',
* lineItems: [{ priceId: 'price_123', quantity: 1 }],
* successUrl: `${window.location.origin}/success`,
* cancelUrl: `${window.location.origin}/pricing`
* });
*
* if (!error && data.checkoutSession.url) {
* window.location.assign(data.checkoutSession.url);
* }
* ```
*/
createCheckoutSession(environment: StripeEnvironment, request: CreateCheckoutSessionBody): Promise<PaymentsResponse<CreateCheckoutSessionResponse>>;
/**
* Create a Stripe Billing Portal Session for a mapped billing subject.
*/
createCustomerPortalSession(environment: StripeEnvironment, request: CreateCustomerPortalSessionBody): Promise<PaymentsResponse<CreateCustomerPortalSessionResponse>>;
}
/**
* Razorpay runtime payment flows.
*
* Razorpay Checkout is client-rendered: create an order or subscription here,
* pass the returned checkoutOptions to Razorpay Checkout.js, then verify the
* signed payment response with the matching verify method.
*/
declare class RazorpayPayments {
private http;
constructor(http: HttpClient);
createOrder(environment: RazorpayEnvironment, request: CreateRazorpayOrderBody): Promise<PaymentsResponse<CreateRazorpayOrderResponse>>;
verifyOrder(environment: RazorpayEnvironment, request: VerifyRazorpayOrderBody): Promise<PaymentsResponse<VerifyRazorpayOrderResponse>>;
createSubscription(environment: RazorpayEnvironment, request: CreateRazorpaySubscriptionBody): Promise<PaymentsResponse<CreateRazorpaySubscriptionResponse>>;
verifySubscription(environment: RazorpayEnvironment, request: VerifyRazorpaySubscriptionBody): Promise<PaymentsResponse<VerifyRazorpaySubscriptionResponse>>;
cancelSubscription(environment: RazorpayEnvironment, subscriptionId: string, request?: CancelRazorpaySubscriptionBodyInput): Promise<PaymentsResponse<CancelRazorpaySubscriptionResponse>>;
pauseSubscription(environment: RazorpayEnvironment, subscriptionId: string): Promise<PaymentsResponse<PauseRazorpaySubscriptionResponse>>;
resumeSubscription(environment: RazorpayEnvironment, subscriptionId: string): Promise<PaymentsResponse<ResumeRazorpaySubscriptionResponse>>;
}
/**
* Provider-scoped payments client.
*/
declare class Payments {
readonly stripe: StripePayments;
readonly razorpay: RazorpayPayments;
constructor(http: HttpClient);
}
type AccessTokenChangeEvent = typeof AuthChangeEvent.SIGNED_IN | typeof AuthChangeEvent.TOKEN_REFRESHED;
/**
* Main InsForge SDK Client
*
* @example
* ```typescript
* import { InsForgeClient } from '@insforge/sdk';
*
* const client = new InsForgeClient({
* baseUrl: 'http://localhost:7130'
* });
*
* // Authentication
* const { data, error } = await client.auth.signUp({
* email: 'user@example.com',
* password: 'password123',
* name: 'John Doe'
* });
*
* // Database operations
* const { data, error } = await client.database
* .from('posts')
* .select('*')
* .eq('user_id', session.user.id)
* .order('created_at', { ascending: false })
* .limit(10);
*
* // Insert data
* const { data: newPost } = await client.database
* .from('posts')
* .insert({ title: 'Hello', content: 'World' })
* .single();
*
* // Invoke edge functions
* const { data, error } = await client.functions.invoke('my-function', {
* body: { message: 'Hello from SDK' }
* });
*
* // Enable debug logging
* const debugClient = new InsForgeClient({
* baseUrl: 'http://localhost:7130',
* debug: true
* });
* ```
*/
declare class InsForgeClient {
private http;
private tokenManager;
readonly auth: Auth;
readonly database: Database;
readonly storage: Storage;
readonly ai: AI;
readonly functions: Functions;
readonly realtime: Realtime;
readonly emails: Emails;
readonly payments: Payments;
constructor(config?: InsForgeConfig);
/**
* Get the underlying HTTP client for custom requests
*
* @example
* ```typescript
* const httpClient = client.getHttpClient();
* const customData = await httpClient.get('/api/custom-endpoint');
* ```
*/
getHttpClient(): HttpClient;
/**
* Set the access token used by every SDK surface. Updates both the HTTP
* client (database / storage / functions / AI / emails) and the realtime
* token manager. Pass `null` to sign out. By default a token replacement is
* treated as a sign-in boundary and reconnects realtime. Pass
* `AuthChangeEvent.TOKEN_REFRESHED` for a same-identity refresh to preserve a live socket; the
* refreshed token is then used at the next handshake.
*
* Use this when an external auth provider (Better Auth, Clerk, Auth0,
* WorkOS, Kinde, Stytch, …) issues the JWT and you need to keep the
* long-lived InsForge client in sync. Without this, you'd have to call
* `client.getHttpClient().setAuthToken(token)` AND reach into the private
* realtime token manager separately.
*
* @example
* ```typescript
* import { AuthChangeEvent } from '@insforge/sdk';
*
* // Refresh a third-party-issued JWT periodically
* const { token } = await fetch('/api/insforge-token').then((r) => r.json());
* client.setAccessToken(token, AuthChangeEvent.TOKEN_REFRESHED);
*
* // Sign-out
* client.setAccessToken(null);
* ```
*/
setAccessToken(token: string | null, event?: AccessTokenChangeEvent): void;
}
export { type AccessTokenChangeEvent as A, type ConnectionState as C, Database as D, Emails as E, Functions as F, HttpClient as H, InsForgeClient as I, Logger as L, Payments as P, Realtime as R, Storage as S, Auth as a, StorageBucket as b, type StorageResponse as c, AI as d, type FunctionInvokeOptions as e, type PaymentsResponse as f, type EventCallback as g, AuthChangeEvent as h, type AuthStateChangeCallback as i };
import { A as AuthSession, I as InsForgeConfig, e as AuthRefreshResponse, d as InsForgeError } from './types-MKmYAYeg.mjs';
import { UserSchema, CreateUserRequest, CreateUserResponse, CreateSessionRequest, CreateSessionResponse, OAuthProvidersSchema, RefreshSessionResponse, GetProfileResponse, SendVerificationEmailRequest, VerifyEmailRequest, VerifyEmailResponse, SendResetPasswordEmailRequest, ExchangeResetPasswordTokenRequest, ExchangeResetPasswordTokenResponse, ResetPasswordResponse, GetPublicAuthConfigResponse, StorageFileSchema, ListObjectsResponseSchema, ChatCompletionRequest, ImageGenerationRequest, EmbeddingsRequest, SubscribeResponse, SocketMessage, PresenceMember, SendRawEmailRequest, SendEmailResponse, StripeEnvironment, CreateCheckoutSessionBody, CreateCheckoutSessionResponse, CreateCustomerPortalSessionBody, CreateCustomerPortalSessionResponse, RazorpayEnvironment, CreateRazorpayOrderBody, CreateRazorpayOrderResponse, VerifyRazorpayOrderBody, VerifyRazorpayOrderResponse, CreateRazorpaySubscriptionBody, CreateRazorpaySubscriptionResponse, VerifyRazorpaySubscriptionBody, VerifyRazorpaySubscriptionResponse, CancelRazorpaySubscriptionBodyInput, CancelRazorpaySubscriptionResponse, PauseRazorpaySubscriptionResponse, ResumeRazorpaySubscriptionResponse } from '@insforge/shared-schemas';
import * as _supabase_postgrest_js from '@supabase/postgrest-js';
import { PostgrestClient } from '@supabase/postgrest-js';
type LogFunction = (message: string, ...args: any[]) => void;
/**
* Debug logger for the InsForge SDK.
* Logs HTTP request/response details with automatic redaction of sensitive data.
*
* @example
* ```typescript
* // Enable via SDK config
* const client = new InsForgeClient({ debug: true });
*
* // Or with a custom log function
* const client = new InsForgeClient({
* debug: (msg) => myLogger.info(msg)
* });
* ```
*/
declare class Logger {
/** Whether debug logging is currently enabled */
enabled: boolean;
private customLog;
/**
* Creates a new Logger instance.
* @param debug - Set to true to enable console logging, or pass a custom log function
*/
constructor(debug?: boolean | LogFunction);
/**
* Logs a debug message at the info level.
* @param message - The message to log
* @param args - Additional arguments to pass to the log function
*/
log(message: string, ...args: any[]): void;
/**
* Logs a debug message at the warning level.
* @param message - The message to log
* @param args - Additional arguments to pass to the log function
*/
warn(message: string, ...args: any[]): void;
/**
* Logs a debug message at the error level.
* @param message - The message to log
* @param args - Additional arguments to pass to the log function
*/
error(message: string, ...args: any[]): void;
/**
* Logs an outgoing HTTP request with method, URL, headers, and body.
* Sensitive headers and body fields are automatically redacted.
* @param method - HTTP method (GET, POST, etc.)
* @param url - The full request URL
* @param headers - Request headers (sensitive values will be redacted)
* @param body - Request body (sensitive fields will be masked)
*/
logRequest(method: string, url: string, headers?: Record<string, string>, body?: any): void;
/**
* Logs an incoming HTTP response with method, URL, status, duration, and body.
* Error responses (4xx/5xx) are logged at the error level.
* @param method - HTTP method (GET, POST, etc.)
* @param url - The full request URL
* @param status - HTTP response status code
* @param durationMs - Request duration in milliseconds
* @param body - Response body (sensitive fields will be masked, large bodies truncated)
*/
logResponse(method: string, url: string, status: number, durationMs: number, body?: any): void;
}
/**
* Token Manager for InsForge SDK
*
* Memory-only token storage.
*/
declare const AuthChangeEvent: {
readonly SIGNED_IN: "signedIn";
readonly SIGNED_OUT: "signedOut";
readonly TOKEN_REFRESHED: "tokenRefreshed";
};
type AuthChangeEvent = (typeof AuthChangeEvent)[keyof typeof AuthChangeEvent];
type AuthStateChangeCallback = (event: AuthChangeEvent) => void;
declare class TokenManager {
private accessToken;
private user;
private authStateChangeCallbacks;
constructor();
/**
* Save session in memory
*/
saveSession(session: AuthSession, event?: AuthChangeEvent): void;
/**
* Get current session
*/
getSession(): AuthSession | null;
/**
* Get access token
*/
getAccessToken(): string | null;
/**
* Set access token
*/
setAccessToken(token: string, event?: AuthChangeEvent): void;
/**
* Get user
*/
getUser(): UserSchema | null;
/**
* Set user
*/
setUser(user: UserSchema): void;
/**
* Clear in-memory session
*/
clearSession(): void;
onAuthStateChange(callback: AuthStateChangeCallback): () => void;
private notifyAuthStateChange;
}
type JsonRequestBody = Record<string, unknown> | unknown[] | null;
interface RequestOptions extends Omit<RequestInit, 'body'> {
params?: Record<string, string>;
body?: RequestInit['body'] | JsonRequestBody;
/** Allow retrying non-idempotent requests (POST, PATCH). Off by default to prevent duplicate writes. */
idempotent?: boolean;
/** Disable automatic access-token refresh for auth/control-flow requests. */
skipAuthRefresh?: boolean;
}
/**
* HTTP client with built-in retry, timeout, and exponential backoff support.
* Handles authentication, request serialization, and error normalization.
*/
declare class HttpClient {
readonly baseUrl: string;
readonly fetch: typeof fetch;
private readonly config;
private defaultHeaders;
private anonKey;
private userToken;
private logger;
private isRefreshing;
private refreshPromise;
private tokenManager;
private refreshToken;
private timeout;
private retryCount;
private retryDelay;
/**
* Creates a new HttpClient instance.
* @param config - SDK configuration including baseUrl, timeout, retry settings, and fetch implementation.
* @param tokenManager - Token manager for session persistence.
* @param logger - Optional logger instance for request/response debugging.
*/
constructor(config: InsForgeConfig, tokenManager?: TokenManager, logger?: Logger);
/**
* Builds a full URL from a path and optional query parameters.
* Normalizes PostgREST select parameters for proper syntax.
*/
private buildUrl;
/** Checks if an HTTP status code is eligible for retry (5xx server errors). */
private isRetryableStatus;
/**
* Computes the delay before the next retry using exponential backoff with jitter.
* @param attempt - The current retry attempt number (1-based).
* @returns Delay in milliseconds.
*/
private computeRetryDelay;
private shouldRefreshAccessToken;
private fetchWithRetry;
/**
* Performs an HTTP request with automatic retry and timeout handling.
* Retries on network errors and 5xx server errors with exponential backoff.
* Client errors (4xx) and timeouts are thrown immediately without retry.
* @param method - HTTP method (GET, POST, PUT, PATCH, DELETE).
* @param path - API path relative to the base URL.
* @param options - Optional request configuration including headers, body, and query params.
* @returns Parsed response data.
* @throws {InsForgeError} On timeout, network failure, or HTTP error responses.
*/
private handleRequest;
request<T>(method: string, path: string, options?: RequestOptions): Promise<T>;
/**
* Performs an SDK-configured fetch and returns the raw Response.
* This is used by clients such as postgrest-js that need to own response
* parsing while still sharing SDK auth and refresh behavior.
*/
rawFetch(input: RequestInfo | URL, init?: RequestInit, options?: {
skipAuthRefresh?: boolean;
}): Promise<Response>;
/** Performs a GET request. */
get<T>(path: string, options?: RequestOptions): Promise<T>;
/** Performs a POST request with an optional JSON body. */
post<T>(path: string, body?: any, options?: RequestOptions): Promise<T>;
/** Performs a PUT request with an optional JSON body. */
put<T>(path: string, body?: any, options?: RequestOptions): Promise<T>;
/** Performs a PATCH request with an optional JSON body. */
patch<T>(path: string, body?: any, options?: RequestOptions): Promise<T>;
/** Performs a DELETE request. */
delete<T>(path: string, options?: RequestOptions): Promise<T>;
/** Sets or clears the user authentication token for subsequent requests. */
setAuthToken(token: string | null): void;
setRefreshToken(token: string | null): void;
/** Returns the current default headers including the authorization header if set. */
getHeaders(): Record<string, string>;
refreshAccessToken(): Promise<AuthRefreshResponse>;
/** Returns a token safe to use for a new connection handshake. */
getValidAccessToken(leewaySeconds?: number): Promise<string | null>;
private refreshAndSaveSession;
private clearAuthSession;
}
/**
* Auth module for InsForge SDK
* Handles authentication, sessions, profiles, and email verification
*/
interface AuthOptions {
isServerMode?: boolean;
detectOAuthCallback?: boolean;
}
type OAuthSignInOptions = {
redirectTo: string;
additionalParams?: Record<string, string>;
skipBrowserRedirect?: boolean;
};
type OAuthSignInLegacyOptions = OAuthSignInOptions & {
provider: OAuthProvidersSchema | string;
};
declare class Auth {
private http;
private tokenManager;
private options;
private authCallbackHandled;
constructor(http: HttpClient, tokenManager: TokenManager, options?: AuthOptions);
private isServerMode;
/** Subscribe to SDK authentication state changes. */
onAuthStateChange(callback: AuthStateChangeCallback): () => void;
/**
* Save session from API response
* Handles token storage, CSRF token, and HTTP auth header
*/
private saveSessionFromResponse;
/**
* Detect and handle OAuth callback parameters in URL
* Supports PKCE flow (insforge_code)
*/
private detectAuthCallback;
signUp(request: CreateUserRequest): Promise<{
data: CreateUserResponse | null;
error: InsForgeError | null;
}>;
signInWithPassword(request: CreateSessionRequest): Promise<{
data: CreateSessionResponse | null;
error: InsForgeError | null;
}>;
signOut(): Promise<{
error: InsForgeError | null;
}>;
/**
* Sign in with OAuth provider using PKCE flow
*/
signInWithOAuth(provider: OAuthProvidersSchema | string, options: OAuthSignInOptions): Promise<{
data: {
url?: string;
provider?: string;
codeVerifier?: string;
};
error: InsForgeError | null;
}>;
/**
* @deprecated Use signInWithOAuth(provider, { redirectTo, additionalParams, skipBrowserRedirect }).
*/
signInWithOAuth(options: OAuthSignInLegacyOptions): Promise<{
data: {
url?: string;
provider?: string;
codeVerifier?: string;
};
error: InsForgeError | null;
}>;
/**
* Exchange OAuth authorization code for tokens (PKCE flow)
* Called automatically on initialization when insforge_code is in URL
*/
exchangeOAuthCode(code: string, codeVerifier?: string): Promise<{
data: CreateSessionResponse | null;
error: InsForgeError | null;
}>;
/**
* Sign in with an ID token from a native SDK (Google One Tap, etc.)
* Use this for native mobile apps or Google One Tap on web.
*
* @param credentials.provider - The identity provider (currently only 'google' is supported)
* @param credentials.token - The ID token from the native SDK
*/
signInWithIdToken(credentials: {
provider: 'google';
token: string;
}): Promise<{
data: CreateSessionResponse | null;
error: InsForgeError | null;
}>;
/**
* Refresh the current auth session.
*
* Browser mode:
* - Uses httpOnly refresh cookie and optional CSRF header.
*
* Legacy server mode (`isServerMode: true`):
* - Uses mobile auth flow and requires `refreshToken` in request body.
*
* SSR apps should prefer `createRefreshAuthRouter()` / `refreshAuth()` from
* `@insforge/sdk/ssr`.
*/
refreshSession(options?: {
refreshToken?: string;
}): Promise<{
data: RefreshSessionResponse | null;
error: InsForgeError | null;
}>;
/**
* Get current user, automatically waits for pending OAuth callback
*/
getCurrentUser(): Promise<{
data: {
user: UserSchema | null;
};
error: InsForgeError | null;
}>;
getProfile(userId: string): Promise<{
data: GetProfileResponse | null;
error: InsForgeError | null;
}>;
setProfile(profile: Record<string, unknown>): Promise<{
data: GetProfileResponse | null;
error: InsForgeError | null;
}>;
resendVerificationEmail(request: SendVerificationEmailRequest): Promise<{
data: {
success: boolean;
message: string;
} | null;
error: InsForgeError | null;
}>;
verifyEmail(request: VerifyEmailRequest): Promise<{
data: VerifyEmailResponse | null;
error: InsForgeError | null;
}>;
sendResetPasswordEmail(request: SendResetPasswordEmailRequest): Promise<{
data: {
success: boolean;
message: string;
} | null;
error: InsForgeError | null;
}>;
exchangeResetPasswordToken(request: ExchangeResetPasswordTokenRequest): Promise<{
data: ExchangeResetPasswordTokenResponse | null;
error: InsForgeError | null;
}>;
resetPassword(request: {
newPassword: string;
otp: string;
}): Promise<{
data: ResetPasswordResponse | null;
error: InsForgeError | null;
}>;
getPublicAuthConfig(): Promise<{
data: GetPublicAuthConfigResponse | null;
error: InsForgeError | null;
}>;
}
/**
* Database client using postgrest-js
* Drop-in replacement with FULL PostgREST capabilities
*/
declare class Database {
private postgrest;
constructor(httpClient: HttpClient, defaultSchema?: string);
/**
* Select a non-default Postgres schema for the chained query. Maps to
* PostgREST's `Accept-Profile` (reads) / `Content-Profile` (writes) header.
* The schema must be exposed by the backend.
*
* @example
* const { data } = await client.database
* .schema('analytics')
* .from('events')
* .select('*');
*
* @example
* await client.database.schema('analytics').rpc('rollup', { day: '2026-01-01' });
*/
schema(schemaName: string): PostgrestClient<any, any, string, any>;
/**
* Create a query builder for a table
*
* @example
* // Basic query
* const { data, error } = await client.database
* .from('posts')
* .select('*')
* .eq('user_id', userId);
*
* // With count (Supabase style!)
* const { data, error, count } = await client.database
* .from('posts')
* .select('*', { count: 'exact' })
* .range(0, 9);
*
* // Just get count, no data
* const { count } = await client.database
* .from('posts')
* .select('*', { count: 'exact', head: true });
*
* // Complex queries with OR
* const { data } = await client.database
* .from('posts')
* .select('*, users!inner(*)')
* .or('status.eq.active,status.eq.pending');
*
* // All features work:
* - Nested selects
* - Foreign key expansion
* - OR/AND/NOT conditions
* - Count with head
* - Range pagination
* - Upserts
*/
from(table: string): _supabase_postgrest_js.PostgrestQueryBuilder<any, any, any, string, unknown>;
/**
* Call a PostgreSQL function (RPC)
*
* @example
* // Call a function with parameters
* const { data, error } = await client.database
* .rpc('get_user_stats', { user_id: 123 });
*
* // Call a function with no parameters
* const { data, error } = await client.database
* .rpc('get_all_active_users');
*
* // With options (head, count, get)
* const { data, count } = await client.database
* .rpc('search_posts', { query: 'hello' }, { count: 'exact' });
*/
rpc(fn: string, args?: Record<string, unknown>, options?: {
head?: boolean;
get?: boolean;
count?: 'exact' | 'planned' | 'estimated';
}): _supabase_postgrest_js.PostgrestFilterBuilder<any, any, any, any, string, null, "RPC">;
}
/**
* Storage module for InsForge SDK
* Handles file uploads, downloads, and bucket management
*/
interface StorageResponse<T> {
data: T | null;
error: InsForgeError | null;
}
/**
* Storage bucket operations
*/
declare class StorageBucket {
private bucketName;
private http;
constructor(bucketName: string, http: HttpClient);
/**
* Upload a file to a specific key.
* Uses the upload strategy from the backend (direct or presigned).
* Standard PUT semantics: uploading to an existing key replaces the
* current object in place.
* @param path - The object key/path
* @param file - File or Blob to upload
*/
upload(path: string, file: File | Blob): Promise<StorageResponse<StorageFileSchema>>;
/**
* Upload a file under an automatically generated, collision-free key.
* The key is derived client-side from the filename (sanitized base +
* timestamp + random suffix) and uploaded through the standard
* {@link upload} path, so repeated uploads of the same file never
* overwrite each other. Reads the filename structurally to avoid assuming
* a global `File` (which Node 18 does not expose).
* @param file - File or Blob to upload
*/
uploadAuto(file: File | Blob): Promise<StorageResponse<StorageFileSchema>>;
/**
* Internal method to handle presigned URL uploads
*/
private uploadWithPresignedUrl;
/**
* Download a file
* Uses the download strategy from backend (direct or presigned)
* @param path - The object key/path
* Returns the file as a Blob
*/
download(path: string): Promise<{
data: Blob | null;
error: InsForgeError | null;
}>;
/**
* Get the public URL for an object in a public bucket.
*
* Pure string construction — no network call, no auth. The URL only resolves
* if the bucket is public; for private objects use {@link createSignedUrl}.
*
* @param path - The object key/path
* @returns `{ data: { publicUrl }, error }` — matches the external SDK pattern,
* so `const { data } = getPublicUrl(path)` then `data.publicUrl`.
*/
getPublicUrl(path: string): StorageResponse<{
publicUrl: string;
}>;
/**
* Resolve a download strategy (signed or direct URL) for an object with a
* caller-supplied TTL. Prefers the canonical GET route and falls back to the
* legacy POST alias so signed-URL creation still works against older backends
* that predate the GET route (they return 404/405 for it). A genuine
* "object not found" (STORAGE_NOT_FOUND) is not retried.
*/
private requestDownloadStrategy;
/**
* Create a signed URL for an object.
*
* Returns a time-limited, credential-free URL that can be handed directly to
* a browser (`<img src>`), an email, or a third party — no SDK or session is
* needed to fetch it. Authorization is enforced when the URL is minted (the
* caller must be allowed to read the object), so the resulting link is a
* pre-authorized capability scoped to this one object until it expires.
*
* @param path - The object key/path
* @param expiresIn - Lifetime in seconds (default 3600 = 1h, max 604800 = 7d).
* Honored for private buckets; public buckets return their long-lived URL.
*/
createSignedUrl(path: string, expiresIn?: number): Promise<StorageResponse<{
signedUrl: string;
expiresAt: string | null;
}>>;
/**
* Create signed URLs for multiple objects in a single call.
*
* Each entry resolves independently: a failure on one key (not found / not
* permitted) is reported on that entry's `error` without failing the rest.
*
* @param paths - The object keys/paths
* @param expiresIn - Lifetime in seconds (default 3600 = 1h, max 604800 = 7d)
*/
createSignedUrls(paths: string[], expiresIn?: number): Promise<StorageResponse<Array<{
path: string;
signedUrl: string | null;
error: string | null;
}>>>;
/**
* List objects in the bucket
* @param prefix - Filter by key prefix
* @param search - Search in file names
* @param limit - Maximum number of results (default: 100, max: 1000)
* @param offset - Number of results to skip
*/
list(options?: {
prefix?: string;
search?: string;
limit?: number;
offset?: number;
}): Promise<StorageResponse<ListObjectsResponseSchema>>;
/**
* Delete a file
* @param path - The object key/path
*/
remove(path: string): Promise<StorageResponse<{
message: string;
}>>;
}
/**
* Storage module for file operations
*/
declare class Storage {
private http;
constructor(http: HttpClient);
/**
* Get a bucket instance for operations
* @param bucketName - Name of the bucket
*/
from(bucketName: string): StorageBucket;
}
/**
* AI Module for Insforge SDK
* Response format roughly matches OpenAI SDK for compatibility
*
* The backend handles all the complexity of different AI providers
* and returns a unified format. This SDK transforms responses to match OpenAI-like format.
*/
declare class AI {
private http;
readonly chat: Chat;
readonly images: Images;
readonly embeddings: Embeddings;
constructor(http: HttpClient);
}
declare class Chat {
readonly completions: ChatCompletions;
constructor(http: HttpClient);
}
declare class ChatCompletions {
private http;
constructor(http: HttpClient);
/**
* Create a chat completion - OpenAI-like response format
*
* @example
* ```typescript
* // Non-streaming
* const completion = await client.ai.chat.completions.create({
* model: 'gpt-4',
* messages: [{ role: 'user', content: 'Hello!' }]
* });
* console.log(completion.choices[0].message.content);
*
* // With images (OpenAI-compatible format)
* const response = await client.ai.chat.completions.create({
* model: 'gpt-4-vision',
* messages: [{
* role: 'user',
* content: [
* { type: 'text', text: 'What is in this image?' },
* { type: 'image_url', image_url: { url: 'https://example.com/image.jpg' } }
* ]
* }]
* });
*
* // With PDF files
* const pdfResponse = await client.ai.chat.completions.create({
* model: 'anthropic/claude-3.5-sonnet',
* messages: [{
* role: 'user',
* content: [
* { type: 'text', text: 'Summarize this document' },
* { type: 'file', file: { filename: 'doc.pdf', file_data: 'https://example.com/doc.pdf' } }
* ]
* }],
* fileParser: { enabled: true, pdf: { engine: 'mistral-ocr' } }
* });
*
* // With web search
* const searchResponse = await client.ai.chat.completions.create({
* model: 'openai/gpt-4',
* messages: [{ role: 'user', content: 'What are the latest news about AI?' }],
* webSearch: { enabled: true, maxResults: 5 }
* });
* // Access citations from response.choices[0].message.annotations
*
* // With thinking/reasoning mode (Anthropic models)
* const thinkingResponse = await client.ai.chat.completions.create({
* model: 'anthropic/claude-3.5-sonnet',
* messages: [{ role: 'user', content: 'Solve this complex math problem...' }],
* thinking: true
* });
*
* // Streaming - returns async iterable
* const stream = await client.ai.chat.completions.create({
* model: 'gpt-4',
* messages: [{ role: 'user', content: 'Tell me a story' }],
* stream: true
* });
*
* for await (const chunk of stream) {
* if (chunk.choices[0]?.delta?.content) {
* process.stdout.write(chunk.choices[0].delta.content);
* }
* }
* ```
*/
create(params: ChatCompletionRequest): Promise<any>;
/**
* Parse SSE stream into async iterable of OpenAI-like chunks
*/
private parseSSEStream;
}
declare class Embeddings {
private http;
constructor(http: HttpClient);
/**
* Create embeddings for text input - OpenAI-like response format
*
* @example
* ```typescript
* // Single text input
* const response = await client.ai.embeddings.create({
* model: 'openai/text-embedding-3-small',
* input: 'Hello world'
* });
* console.log(response.data[0].embedding); // number[]
*
* // Multiple text inputs
* const response = await client.ai.embeddings.create({
* model: 'openai/text-embedding-3-small',
* input: ['Hello world', 'Goodbye world']
* });
* response.data.forEach((item, i) => {
* console.log(`Embedding ${i}:`, item.embedding.slice(0, 5)); // First 5 dimensions
* });
*
* // With custom dimensions (if supported by model)
* const response = await client.ai.embeddings.create({
* model: 'openai/text-embedding-3-small',
* input: 'Hello world',
* dimensions: 256
* });
*
* // With base64 encoding format
* const response = await client.ai.embeddings.create({
* model: 'openai/text-embedding-3-small',
* input: 'Hello world',
* encoding_format: 'base64'
* });
* ```
*/
create(params: EmbeddingsRequest): Promise<any>;
}
declare class Images {
private http;
constructor(http: HttpClient);
/**
* Generate images - OpenAI-like response format
*
* @example
* ```typescript
* // Text-to-image
* const response = await client.ai.images.generate({
* model: 'dall-e-3',
* prompt: 'A sunset over mountains',
* });
* console.log(response.data[0].b64_json);
*
* // Image-to-image (with input images)
* const response = await client.ai.images.generate({
* model: 'stable-diffusion-xl',
* prompt: 'Transform this into a watercolor painting',
* images: [
* { url: 'https://example.com/input.jpg' },
* // or base64-encoded Data URI:
* { url: 'data:image/jpeg;base64,/9j/4AAQ...' }
* ]
* });
* ```
*/
generate(params: ImageGenerationRequest): Promise<any>;
}
interface FunctionInvokeOptions {
/**
* The body of the request
*/
body?: any;
/**
* Custom headers to send with the request
*/
headers?: Record<string, string>;
/**
* HTTP method (default: POST)
*/
method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
}
/**
* Edge Functions client for invoking serverless functions.
*
* @example
* ```typescript
* const { data, error } = await client.functions.invoke('hello-world', {
* body: { name: 'World' }
* });
* ```
*/
declare class Functions {
private http;
private functionsUrl;
constructor(http: HttpClient, functionsUrl?: string);
/**
* Derive the subhosting URL from the base URL.
* Base URL pattern: https://{appKey}.{region}.insforge.app
* Functions URL: https://{appKey}.functions.insforge.app
* Only applies to .insforge.app domains.
*/
private static deriveSubhostingUrl;
/**
* Build a Request for in-process dispatch. The host is a non-routable
* placeholder; the router only reads pathname.
*/
private buildInProcessRequest;
/**
* Invoke an Edge Function.
*
* Dispatch order:
* 1. If `globalThis.__insforge_dispatch__` is present, call it in-process.
* This avoids Deno Subhosting's 508 Loop Detected when one bundled
* function invokes another inside the same deployment.
* 2. Otherwise, try the configured subhosting URL.
* 3. On 404 from subhosting, fall back to the proxy path.
*
* @param slug The function slug to invoke
* @param options Request options
*/
invoke<T = any>(slug: string, options?: FunctionInvokeOptions): Promise<{
data: T | null;
error: InsForgeError | null;
}>;
}
type ConnectionState = 'disconnected' | 'connecting' | 'connected';
type EventCallback<T = unknown> = (payload: T) => void;
/**
* Socket.IO realtime client. Authentication is evaluated for every handshake,
* while an established socket remains authenticated until it disconnects.
*/
declare class Realtime {
private baseUrl;
private tokenManager;
private anonKey?;
private getValidAccessToken;
private socket;
private connectPromise;
private connectionAttempt;
private nextConnectionAttemptId;
private subscriptions;
private eventListeners;
constructor(baseUrl: string, tokenManager: TokenManager, anonKey?: string | undefined, getValidAccessToken?: () => Promise<string | null>);
private notifyListeners;
private getHandshakeToken;
connect(): Promise<void>;
disconnect(): void;
private reconnectForAuthChange;
private handleDisconnect;
private resubscribeChannels;
private requestSubscription;
private settleSubscription;
private applyPresenceEvent;
get isConnected(): boolean;
get connectionState(): ConnectionState;
get socketId(): string | undefined;
subscribe(channel: string): Promise<SubscribeResponse>;
unsubscribe(channel: string): void;
publish<T = unknown>(channel: string, event: string, payload: T): Promise<void>;
on<T = SocketMessage>(event: string, callback: EventCallback<T>): void;
off<T = SocketMessage>(event: string, callback: EventCallback<T>): void;
once<T = SocketMessage>(event: string, callback: EventCallback<T>): void;
getSubscribedChannels(): string[];
getPresenceState(channel: string): PresenceMember[];
}
/**
* Emails client for sending custom emails
*
* @example
* ```typescript
* // Send a simple email
* const { data, error } = await client.emails.send({
* to: 'user@example.com',
* subject: 'Welcome!',
* html: '<h1>Welcome to our platform</h1>'
* });
*
* if (error) {
* console.error('Failed to send:', error.message);
* return;
* }
* // Email sent successfully - data is {} (empty object)
*
* // Send to multiple recipients with CC
* const { data, error } = await client.emails.send({
* to: ['user1@example.com', 'user2@example.com'],
* cc: 'manager@example.com',
* subject: 'Team Update',
* html: '<p>Here is the latest update...</p>',
* replyTo: 'support@example.com'
* });
* ```
*/
declare class Emails {
private http;
constructor(http: HttpClient);
/**
* Send a custom HTML email
* @param options Email options including recipients, subject, and HTML content
*/
send(options: SendRawEmailRequest): Promise<{
data: SendEmailResponse | null;
error: InsForgeError | null;
}>;
}
interface PaymentsResponse<T> {
data: T | null;
error: InsForgeError | null;
}
/**
* Stripe runtime payment flows.
*
* These methods are safe to call from generated app frontends with the current
* user token or anon key. Admin-only Stripe key/catalog APIs are intentionally
* not exposed here.
*/
declare class StripePayments {
private http;
constructor(http: HttpClient);
/**
* Create a Stripe Checkout Session through the InsForge backend.
*
* @example
* ```typescript
* const { data, error } = await client.payments.stripe.createCheckoutSession('test', {
* mode: 'payment',
* lineItems: [{ priceId: 'price_123', quantity: 1 }],
* successUrl: `${window.location.origin}/success`,
* cancelUrl: `${window.location.origin}/pricing`
* });
*
* if (!error && data.checkoutSession.url) {
* window.location.assign(data.checkoutSession.url);
* }
* ```
*/
createCheckoutSession(environment: StripeEnvironment, request: CreateCheckoutSessionBody): Promise<PaymentsResponse<CreateCheckoutSessionResponse>>;
/**
* Create a Stripe Billing Portal Session for a mapped billing subject.
*/
createCustomerPortalSession(environment: StripeEnvironment, request: CreateCustomerPortalSessionBody): Promise<PaymentsResponse<CreateCustomerPortalSessionResponse>>;
}
/**
* Razorpay runtime payment flows.
*
* Razorpay Checkout is client-rendered: create an order or subscription here,
* pass the returned checkoutOptions to Razorpay Checkout.js, then verify the
* signed payment response with the matching verify method.
*/
declare class RazorpayPayments {
private http;
constructor(http: HttpClient);
createOrder(environment: RazorpayEnvironment, request: CreateRazorpayOrderBody): Promise<PaymentsResponse<CreateRazorpayOrderResponse>>;
verifyOrder(environment: RazorpayEnvironment, request: VerifyRazorpayOrderBody): Promise<PaymentsResponse<VerifyRazorpayOrderResponse>>;
createSubscription(environment: RazorpayEnvironment, request: CreateRazorpaySubscriptionBody): Promise<PaymentsResponse<CreateRazorpaySubscriptionResponse>>;
verifySubscription(environment: RazorpayEnvironment, request: VerifyRazorpaySubscriptionBody): Promise<PaymentsResponse<VerifyRazorpaySubscriptionResponse>>;
cancelSubscription(environment: RazorpayEnvironment, subscriptionId: string, request?: CancelRazorpaySubscriptionBodyInput): Promise<PaymentsResponse<CancelRazorpaySubscriptionResponse>>;
pauseSubscription(environment: RazorpayEnvironment, subscriptionId: string): Promise<PaymentsResponse<PauseRazorpaySubscriptionResponse>>;
resumeSubscription(environment: RazorpayEnvironment, subscriptionId: string): Promise<PaymentsResponse<ResumeRazorpaySubscriptionResponse>>;
}
/**
* Provider-scoped payments client.
*/
declare class Payments {
readonly stripe: StripePayments;
readonly razorpay: RazorpayPayments;
constructor(http: HttpClient);
}
type AccessTokenChangeEvent = typeof AuthChangeEvent.SIGNED_IN | typeof AuthChangeEvent.TOKEN_REFRESHED;
/**
* Main InsForge SDK Client
*
* @example
* ```typescript
* import { InsForgeClient } from '@insforge/sdk';
*
* const client = new InsForgeClient({
* baseUrl: 'http://localhost:7130'
* });
*
* // Authentication
* const { data, error } = await client.auth.signUp({
* email: 'user@example.com',
* password: 'password123',
* name: 'John Doe'
* });
*
* // Database operations
* const { data, error } = await client.database
* .from('posts')
* .select('*')
* .eq('user_id', session.user.id)
* .order('created_at', { ascending: false })
* .limit(10);
*
* // Insert data
* const { data: newPost } = await client.database
* .from('posts')
* .insert({ title: 'Hello', content: 'World' })
* .single();
*
* // Invoke edge functions
* const { data, error } = await client.functions.invoke('my-function', {
* body: { message: 'Hello from SDK' }
* });
*
* // Enable debug logging
* const debugClient = new InsForgeClient({
* baseUrl: 'http://localhost:7130',
* debug: true
* });
* ```
*/
declare class InsForgeClient {
private http;
private tokenManager;
readonly auth: Auth;
readonly database: Database;
readonly storage: Storage;
readonly ai: AI;
readonly functions: Functions;
readonly realtime: Realtime;
readonly emails: Emails;
readonly payments: Payments;
constructor(config?: InsForgeConfig);
/**
* Get the underlying HTTP client for custom requests
*
* @example
* ```typescript
* const httpClient = client.getHttpClient();
* const customData = await httpClient.get('/api/custom-endpoint');
* ```
*/
getHttpClient(): HttpClient;
/**
* Set the access token used by every SDK surface. Updates both the HTTP
* client (database / storage / functions / AI / emails) and the realtime
* token manager. Pass `null` to sign out. By default a token replacement is
* treated as a sign-in boundary and reconnects realtime. Pass
* `AuthChangeEvent.TOKEN_REFRESHED` for a same-identity refresh to preserve a live socket; the
* refreshed token is then used at the next handshake.
*
* Use this when an external auth provider (Better Auth, Clerk, Auth0,
* WorkOS, Kinde, Stytch, …) issues the JWT and you need to keep the
* long-lived InsForge client in sync. Without this, you'd have to call
* `client.getHttpClient().setAuthToken(token)` AND reach into the private
* realtime token manager separately.
*
* @example
* ```typescript
* import { AuthChangeEvent } from '@insforge/sdk';
*
* // Refresh a third-party-issued JWT periodically
* const { token } = await fetch('/api/insforge-token').then((r) => r.json());
* client.setAccessToken(token, AuthChangeEvent.TOKEN_REFRESHED);
*
* // Sign-out
* client.setAccessToken(null);
* ```
*/
setAccessToken(token: string | null, event?: AccessTokenChangeEvent): void;
}
export { type AccessTokenChangeEvent as A, type ConnectionState as C, Database as D, Emails as E, Functions as F, HttpClient as H, InsForgeClient as I, Logger as L, Payments as P, Realtime as R, Storage as S, Auth as a, StorageBucket as b, type StorageResponse as c, AI as d, type FunctionInvokeOptions as e, type PaymentsResponse as f, type EventCallback as g, AuthChangeEvent as h, type AuthStateChangeCallback as i };

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display