@insforge/sdk 0.0.32 → 0.0.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -253,17 +253,24 @@ declare class StorageBucket {
253
253
  constructor(bucketName: string, http: HttpClient);
254
254
  /**
255
255
  * Upload a file with a specific key
256
+ * Uses the upload strategy from backend (direct or presigned)
256
257
  * @param path - The object key/path
257
258
  * @param file - File or Blob to upload
258
259
  */
259
260
  upload(path: string, file: File | Blob): Promise<StorageResponse<StorageFileSchema>>;
260
261
  /**
261
262
  * Upload a file with auto-generated key
263
+ * Uses the upload strategy from backend (direct or presigned)
262
264
  * @param file - File or Blob to upload
263
265
  */
264
266
  uploadAuto(file: File | Blob): Promise<StorageResponse<StorageFileSchema>>;
267
+ /**
268
+ * Internal method to handle presigned URL uploads
269
+ */
270
+ private uploadWithPresignedUrl;
265
271
  /**
266
272
  * Download a file
273
+ * Uses the download strategy from backend (direct or presigned)
267
274
  * @param path - The object key/path
268
275
  * Returns the file as a Blob
269
276
  */
package/dist/index.d.ts CHANGED
@@ -253,17 +253,24 @@ declare class StorageBucket {
253
253
  constructor(bucketName: string, http: HttpClient);
254
254
  /**
255
255
  * Upload a file with a specific key
256
+ * Uses the upload strategy from backend (direct or presigned)
256
257
  * @param path - The object key/path
257
258
  * @param file - File or Blob to upload
258
259
  */
259
260
  upload(path: string, file: File | Blob): Promise<StorageResponse<StorageFileSchema>>;
260
261
  /**
261
262
  * Upload a file with auto-generated key
263
+ * Uses the upload strategy from backend (direct or presigned)
262
264
  * @param file - File or Blob to upload
263
265
  */
264
266
  uploadAuto(file: File | Blob): Promise<StorageResponse<StorageFileSchema>>;
267
+ /**
268
+ * Internal method to handle presigned URL uploads
269
+ */
270
+ private uploadWithPresignedUrl;
265
271
  /**
266
272
  * Download a file
273
+ * Uses the download strategy from backend (direct or presigned)
267
274
  * @param path - The object key/path
268
275
  * Returns the file as a Blob
269
276
  */
package/dist/index.js CHANGED
@@ -544,24 +544,43 @@ var StorageBucket = class {
544
544
  }
545
545
  /**
546
546
  * Upload a file with a specific key
547
+ * Uses the upload strategy from backend (direct or presigned)
547
548
  * @param path - The object key/path
548
549
  * @param file - File or Blob to upload
549
550
  */
550
551
  async upload(path, file) {
551
552
  try {
552
- const formData = new FormData();
553
- formData.append("file", file);
554
- const response = await this.http.request(
555
- "PUT",
556
- `/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}`,
553
+ const strategyResponse = await this.http.post(
554
+ `/api/storage/buckets/${this.bucketName}/upload-strategy`,
557
555
  {
558
- body: formData,
559
- headers: {
560
- // Don't set Content-Type, let browser set multipart boundary
561
- }
556
+ filename: path,
557
+ contentType: file.type || "application/octet-stream",
558
+ size: file.size
562
559
  }
563
560
  );
564
- return { data: response, error: null };
561
+ if (strategyResponse.method === "presigned") {
562
+ return await this.uploadWithPresignedUrl(strategyResponse, file);
563
+ }
564
+ if (strategyResponse.method === "direct") {
565
+ const formData = new FormData();
566
+ formData.append("file", file);
567
+ const response = await this.http.request(
568
+ "PUT",
569
+ `/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}`,
570
+ {
571
+ body: formData,
572
+ headers: {
573
+ // Don't set Content-Type, let browser set multipart boundary
574
+ }
575
+ }
576
+ );
577
+ return { data: response, error: null };
578
+ }
579
+ throw new InsForgeError(
580
+ `Unsupported upload method: ${strategyResponse.method}`,
581
+ 500,
582
+ "STORAGE_ERROR"
583
+ );
565
584
  } catch (error) {
566
585
  return {
567
586
  data: null,
@@ -575,23 +594,43 @@ var StorageBucket = class {
575
594
  }
576
595
  /**
577
596
  * Upload a file with auto-generated key
597
+ * Uses the upload strategy from backend (direct or presigned)
578
598
  * @param file - File or Blob to upload
579
599
  */
580
600
  async uploadAuto(file) {
581
601
  try {
582
- const formData = new FormData();
583
- formData.append("file", file);
584
- const response = await this.http.request(
585
- "POST",
586
- `/api/storage/buckets/${this.bucketName}/objects`,
602
+ const filename = file instanceof File ? file.name : "file";
603
+ const strategyResponse = await this.http.post(
604
+ `/api/storage/buckets/${this.bucketName}/upload-strategy`,
587
605
  {
588
- body: formData,
589
- headers: {
590
- // Don't set Content-Type, let browser set multipart boundary
591
- }
606
+ filename,
607
+ contentType: file.type || "application/octet-stream",
608
+ size: file.size
592
609
  }
593
610
  );
594
- return { data: response, error: null };
611
+ if (strategyResponse.method === "presigned") {
612
+ return await this.uploadWithPresignedUrl(strategyResponse, file);
613
+ }
614
+ if (strategyResponse.method === "direct") {
615
+ const formData = new FormData();
616
+ formData.append("file", file);
617
+ const response = await this.http.request(
618
+ "POST",
619
+ `/api/storage/buckets/${this.bucketName}/objects`,
620
+ {
621
+ body: formData,
622
+ headers: {
623
+ // Don't set Content-Type, let browser set multipart boundary
624
+ }
625
+ }
626
+ );
627
+ return { data: response, error: null };
628
+ }
629
+ throw new InsForgeError(
630
+ `Unsupported upload method: ${strategyResponse.method}`,
631
+ 500,
632
+ "STORAGE_ERROR"
633
+ );
595
634
  } catch (error) {
596
635
  return {
597
636
  data: null,
@@ -603,17 +642,78 @@ var StorageBucket = class {
603
642
  };
604
643
  }
605
644
  }
645
+ /**
646
+ * Internal method to handle presigned URL uploads
647
+ */
648
+ async uploadWithPresignedUrl(strategy, file) {
649
+ try {
650
+ const formData = new FormData();
651
+ if (strategy.fields) {
652
+ Object.entries(strategy.fields).forEach(([key, value]) => {
653
+ formData.append(key, value);
654
+ });
655
+ }
656
+ formData.append("file", file);
657
+ const uploadResponse = await fetch(strategy.uploadUrl, {
658
+ method: "POST",
659
+ body: formData
660
+ });
661
+ if (!uploadResponse.ok) {
662
+ throw new InsForgeError(
663
+ `Upload to storage failed: ${uploadResponse.statusText}`,
664
+ uploadResponse.status,
665
+ "STORAGE_ERROR"
666
+ );
667
+ }
668
+ if (strategy.confirmRequired && strategy.confirmUrl) {
669
+ const confirmResponse = await this.http.post(
670
+ strategy.confirmUrl,
671
+ {
672
+ size: file.size,
673
+ contentType: file.type || "application/octet-stream"
674
+ }
675
+ );
676
+ return { data: confirmResponse, error: null };
677
+ }
678
+ return {
679
+ data: {
680
+ key: strategy.key,
681
+ bucket: this.bucketName,
682
+ size: file.size,
683
+ mimeType: file.type || "application/octet-stream",
684
+ uploadedAt: (/* @__PURE__ */ new Date()).toISOString(),
685
+ url: this.getPublicUrl(strategy.key)
686
+ },
687
+ error: null
688
+ };
689
+ } catch (error) {
690
+ throw error instanceof InsForgeError ? error : new InsForgeError(
691
+ "Presigned upload failed",
692
+ 500,
693
+ "STORAGE_ERROR"
694
+ );
695
+ }
696
+ }
606
697
  /**
607
698
  * Download a file
699
+ * Uses the download strategy from backend (direct or presigned)
608
700
  * @param path - The object key/path
609
701
  * Returns the file as a Blob
610
702
  */
611
703
  async download(path) {
612
704
  try {
613
- const url = `${this.http.baseUrl}/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}`;
614
- const response = await this.http.fetch(url, {
705
+ const strategyResponse = await this.http.post(
706
+ `/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}/download-strategy`,
707
+ { expiresIn: 3600 }
708
+ );
709
+ const downloadUrl = strategyResponse.url;
710
+ const headers = {};
711
+ if (strategyResponse.method === "direct") {
712
+ Object.assign(headers, this.http.getHeaders());
713
+ }
714
+ const response = await fetch(downloadUrl, {
615
715
  method: "GET",
616
- headers: this.http.getHeaders()
716
+ headers
617
717
  });
618
718
  if (!response.ok) {
619
719
  try {
@@ -904,33 +1004,18 @@ var Images = class {
904
1004
  "/api/ai/image/generation",
905
1005
  params
906
1006
  );
907
- console.log("response", response);
908
- if (!response.images || response.images.length === 0) {
909
- console.warn("No images in response:", response);
910
- return {
911
- created: Math.floor(Date.now() / 1e3),
912
- data: [],
913
- output_format: "png",
914
- ...response.metadata?.usage && {
915
- usage: {
916
- total_tokens: response.metadata.usage.totalTokens || 0,
917
- input_tokens: response.metadata.usage.promptTokens || 0,
918
- output_tokens: response.metadata.usage.completionTokens || 0
919
- }
920
- }
921
- };
1007
+ let data = [];
1008
+ if (response.images && response.images.length > 0) {
1009
+ data = response.images.map((img) => ({
1010
+ b64_json: img.imageUrl.replace(/^data:image\/\w+;base64,/, ""),
1011
+ content: response.text
1012
+ }));
1013
+ } else if (response.text) {
1014
+ data = [{ content: response.text }];
922
1015
  }
923
1016
  return {
924
1017
  created: Math.floor(Date.now() / 1e3),
925
- data: response.images.map((img) => {
926
- const b64_json = img.imageUrl.replace(/^data:image\/\w+;base64,/, "");
927
- return {
928
- b64_json,
929
- content: response.text
930
- // this field is not in openai sdk, but is in openrouter
931
- };
932
- }),
933
- output_format: "png",
1018
+ data,
934
1019
  ...response.metadata?.usage && {
935
1020
  usage: {
936
1021
  total_tokens: response.metadata.usage.totalTokens || 0,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/types.ts","../src/lib/http-client.ts","../src/lib/token-manager.ts","../src/modules/database-postgrest.ts","../src/modules/auth.ts","../src/modules/storage.ts","../src/modules/ai.ts","../src/client.ts"],"sourcesContent":["/**\n * @insforge/sdk - TypeScript SDK for InsForge Backend-as-a-Service\n * \n * @packageDocumentation\n */\n\n// Main client\nexport { InsForgeClient } from './client';\n\n// Types\nexport type {\n InsForgeConfig,\n InsForgeConfig as ClientOptions, // Alias for compatibility\n TokenStorage,\n AuthSession,\n ApiError,\n} from './types';\n\nexport { InsForgeError } from './types';\n\n// Re-export shared schemas that SDK users will need\nexport type {\n UserSchema,\n CreateUserRequest,\n CreateSessionRequest,\n AuthErrorResponse,\n} from '@insforge/shared-schemas';\n\n// Re-export auth module for advanced usage\nexport { Auth } from './modules/auth';\n\n// Re-export database module (using postgrest-js)\nexport { Database } from './modules/database-postgrest';\n// Note: QueryBuilder is no longer exported as we use postgrest-js QueryBuilder internally\n\n// Re-export storage module and types\nexport { Storage, StorageBucket } from './modules/storage';\nexport type { StorageResponse } from './modules/storage';\n\n// Re-export AI module\nexport { AI } from './modules/ai';\n\n// Re-export utilities for advanced usage\nexport { HttpClient } from './lib/http-client';\nexport { TokenManager } from './lib/token-manager';\n\n// Factory function for creating clients (Supabase-style)\nimport { InsForgeClient } from './client';\nimport { InsForgeConfig } from './types';\n\nexport function createClient(config: InsForgeConfig): InsForgeClient {\n return new InsForgeClient(config);\n}\n\n// Default export for convenience\nexport default InsForgeClient;","/**\n * InsForge SDK Types - only SDK-specific types here\n * Use @insforge/shared-schemas directly for API types\n */\n\nimport type { UserSchema } from '@insforge/shared-schemas';\n\nexport interface InsForgeConfig {\n /**\n * The base URL of the InsForge backend API\n * @default \"http://localhost:7130\"\n */\n baseUrl?: string;\n\n /**\n * Anonymous API key (optional)\n * Used for public/unauthenticated requests when no user token is set\n */\n anonKey?: string;\n\n /**\n * Custom fetch implementation (useful for Node.js environments)\n */\n fetch?: typeof fetch;\n\n /**\n * Storage adapter for persisting tokens\n */\n storage?: TokenStorage;\n\n /**\n * Whether to automatically refresh tokens before they expire\n * @default true\n */\n autoRefreshToken?: boolean;\n\n /**\n * Whether to persist session in storage\n * @default true\n */\n persistSession?: boolean;\n\n /**\n * Custom headers to include with every request\n */\n headers?: Record<string, string>;\n}\n\nexport interface TokenStorage {\n getItem(key: string): string | null | Promise<string | null>;\n setItem(key: string, value: string): void | Promise<void>;\n removeItem(key: string): void | Promise<void>;\n}\n\nexport interface AuthSession {\n user: UserSchema;\n accessToken: string;\n expiresAt?: Date;\n}\n\nexport interface ApiError {\n error: string;\n message: string;\n statusCode: number;\n nextActions?: string;\n}\n\nexport class InsForgeError extends Error {\n public statusCode: number;\n public error: string;\n public nextActions?: string;\n\n constructor(message: string, statusCode: number, error: string, nextActions?: string) {\n super(message);\n this.name = 'InsForgeError';\n this.statusCode = statusCode;\n this.error = error;\n this.nextActions = nextActions;\n }\n\n static fromApiError(apiError: ApiError): InsForgeError {\n return new InsForgeError(\n apiError.message,\n apiError.statusCode,\n apiError.error,\n apiError.nextActions\n );\n }\n}","import { InsForgeConfig, ApiError, InsForgeError } from '../types';\n\nexport interface RequestOptions extends RequestInit {\n params?: Record<string, string>;\n}\n\nexport class HttpClient {\n public readonly baseUrl: string;\n public readonly fetch: typeof fetch;\n private defaultHeaders: Record<string, string>;\n private anonKey: string | undefined;\n private userToken: string | null = null;\n\n constructor(config: InsForgeConfig) {\n this.baseUrl = config.baseUrl || 'http://localhost:7130';\n // Properly bind fetch to maintain its context\n this.fetch = config.fetch || (globalThis.fetch ? globalThis.fetch.bind(globalThis) : undefined as any);\n this.anonKey = config.anonKey;\n this.defaultHeaders = {\n ...config.headers,\n };\n\n if (!this.fetch) {\n throw new Error(\n 'Fetch is not available. Please provide a fetch implementation in the config.'\n );\n }\n }\n\n private buildUrl(path: string, params?: Record<string, string>): string {\n const url = new URL(path, this.baseUrl);\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n // For select parameter, preserve the exact formatting by normalizing whitespace\n // This ensures PostgREST relationship queries work correctly\n if (key === 'select') {\n // Normalize multiline select strings for PostgREST:\n // 1. Replace all whitespace (including newlines) with single space\n // 2. Remove spaces inside parentheses for proper PostgREST syntax\n // 3. Keep spaces after commas at the top level for readability\n let normalizedValue = value.replace(/\\s+/g, ' ').trim();\n \n // Fix spaces around parentheses and inside them\n normalizedValue = normalizedValue\n .replace(/\\s*\\(\\s*/g, '(') // Remove spaces around opening parens\n .replace(/\\s*\\)\\s*/g, ')') // Remove spaces around closing parens\n .replace(/\\(\\s+/g, '(') // Remove spaces after opening parens\n .replace(/\\s+\\)/g, ')') // Remove spaces before closing parens\n .replace(/,\\s+(?=[^()]*\\))/g, ','); // Remove spaces after commas inside parens\n \n url.searchParams.append(key, normalizedValue);\n } else {\n url.searchParams.append(key, value);\n }\n });\n }\n return url.toString();\n }\n\n async request<T>(\n method: string,\n path: string,\n options: RequestOptions = {}\n ): Promise<T> {\n const { params, headers = {}, body, ...fetchOptions } = options;\n \n const url = this.buildUrl(path, params);\n \n const requestHeaders: Record<string, string> = {\n ...this.defaultHeaders,\n };\n \n // Set Authorization header: prefer user token, fallback to anon key\n const authToken = this.userToken || this.anonKey;\n if (authToken) {\n requestHeaders['Authorization'] = `Bearer ${authToken}`;\n }\n \n // Handle body serialization\n let processedBody: any;\n if (body !== undefined) {\n // Check if body is FormData (for file uploads)\n if (typeof FormData !== 'undefined' && body instanceof FormData) {\n // Don't set Content-Type for FormData, let browser set it with boundary\n processedBody = body;\n } else {\n // JSON body\n if (method !== 'GET') {\n requestHeaders['Content-Type'] = 'application/json;charset=UTF-8';\n }\n processedBody = JSON.stringify(body);\n }\n }\n \n Object.assign(requestHeaders, headers);\n \n const response = await this.fetch(url, {\n method,\n headers: requestHeaders,\n body: processedBody,\n ...fetchOptions,\n });\n\n // Handle 204 No Content\n if (response.status === 204) {\n return undefined as T;\n }\n\n // Try to parse JSON response\n let data: any;\n const contentType = response.headers.get('content-type');\n // Check for any JSON content type (including PostgREST's vnd.pgrst.object+json)\n if (contentType?.includes('json')) {\n data = await response.json();\n } else {\n // For non-JSON responses, return text\n data = await response.text();\n }\n\n // Handle errors\n if (!response.ok) {\n if (data && typeof data === 'object' && 'error' in data) {\n throw InsForgeError.fromApiError(data as ApiError);\n }\n throw new InsForgeError(\n `Request failed: ${response.statusText}`,\n response.status,\n 'REQUEST_FAILED'\n );\n }\n\n return data as T;\n }\n\n get<T>(path: string, options?: RequestOptions): Promise<T> {\n return this.request<T>('GET', path, options);\n }\n\n post<T>(path: string, body?: any, options?: RequestOptions): Promise<T> {\n return this.request<T>('POST', path, { ...options, body });\n }\n\n put<T>(path: string, body?: any, options?: RequestOptions): Promise<T> {\n return this.request<T>('PUT', path, { ...options, body });\n }\n\n patch<T>(path: string, body?: any, options?: RequestOptions): Promise<T> {\n return this.request<T>('PATCH', path, { ...options, body });\n }\n\n delete<T>(path: string, options?: RequestOptions): Promise<T> {\n return this.request<T>('DELETE', path, options);\n }\n\n setAuthToken(token: string | null) {\n this.userToken = token;\n }\n\n getHeaders(): Record<string, string> {\n return { ...this.defaultHeaders };\n }\n}","import { TokenStorage, AuthSession } from '../types';\n\nconst TOKEN_KEY = 'insforge-auth-token';\nconst USER_KEY = 'insforge-auth-user';\n\nexport class TokenManager {\n private storage: TokenStorage;\n\n constructor(storage?: TokenStorage) {\n if (storage) {\n // Use provided storage\n this.storage = storage;\n } else if (typeof window !== 'undefined' && window.localStorage) {\n // Browser: use localStorage\n this.storage = window.localStorage;\n } else {\n // Node.js: use in-memory storage\n const store = new Map<string, string>();\n this.storage = {\n getItem: (key: string) => store.get(key) || null,\n setItem: (key: string, value: string) => { store.set(key, value); },\n removeItem: (key: string) => { store.delete(key); }\n };\n }\n }\n\n saveSession(session: AuthSession): void {\n this.storage.setItem(TOKEN_KEY, session.accessToken);\n this.storage.setItem(USER_KEY, JSON.stringify(session.user));\n }\n\n getSession(): AuthSession | null {\n const token = this.storage.getItem(TOKEN_KEY);\n const userStr = this.storage.getItem(USER_KEY);\n\n if (!token || !userStr) {\n return null;\n }\n\n try {\n const user = JSON.parse(userStr as string);\n return { accessToken: token as string, user };\n } catch {\n this.clearSession();\n return null;\n }\n }\n\n getAccessToken(): string | null {\n const token = this.storage.getItem(TOKEN_KEY);\n return typeof token === 'string' ? token : null;\n }\n\n clearSession(): void {\n this.storage.removeItem(TOKEN_KEY);\n this.storage.removeItem(USER_KEY);\n }\n}","/**\n * Database module using @supabase/postgrest-js\n * Complete replacement for custom QueryBuilder with full PostgREST features\n */\n\nimport { PostgrestClient } from '@supabase/postgrest-js';\nimport { HttpClient } from '../lib/http-client';\nimport { TokenManager } from '../lib/token-manager';\n\n\n/**\n * Custom fetch that transforms URLs and adds auth\n */\nfunction createInsForgePostgrestFetch(\n httpClient: HttpClient,\n tokenManager: TokenManager\n): typeof fetch {\n return async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const url = typeof input === 'string' ? input : input.toString();\n const urlObj = new URL(url);\n \n // Extract table name from pathname\n // postgrest-js sends: http://dummy/tablename?params\n // We need: http://localhost:7130/api/database/records/tablename?params\n const tableName = urlObj.pathname.slice(1); // Remove leading /\n \n // Build InsForge URL\n const insforgeUrl = `${httpClient.baseUrl}/api/database/records/${tableName}${urlObj.search}`;\n \n // Get auth token from TokenManager\n const token = tokenManager.getAccessToken();\n \n // Prepare headers\n const headers = new Headers(init?.headers);\n if (token && !headers.has('Authorization')) {\n headers.set('Authorization', `Bearer ${token}`);\n }\n \n // Make the actual request using native fetch\n // This returns a proper Response object with headers\n const response = await fetch(insforgeUrl, {\n ...init,\n headers\n });\n \n return response;\n };\n}\n\n/**\n * Database client using postgrest-js\n * Drop-in replacement with FULL PostgREST capabilities\n */\nexport class Database {\n private postgrest: PostgrestClient<any, any, any>;\n \n constructor(httpClient: HttpClient, tokenManager: TokenManager) {\n // Create postgrest client with custom fetch\n this.postgrest = new PostgrestClient<any, any, any>('http://dummy', {\n fetch: createInsForgePostgrestFetch(httpClient, tokenManager),\n headers: {}\n });\n }\n \n /**\n * Create a query builder for a table\n * \n * @example\n * // Basic query\n * const { data, error } = await client.database\n * .from('posts')\n * .select('*')\n * .eq('user_id', userId);\n * \n * // With count (Supabase style!)\n * const { data, error, count } = await client.database\n * .from('posts')\n * .select('*', { count: 'exact' })\n * .range(0, 9);\n * \n * // Just get count, no data\n * const { count } = await client.database\n * .from('posts')\n * .select('*', { count: 'exact', head: true });\n * \n * // Complex queries with OR\n * const { data } = await client.database\n * .from('posts')\n * .select('*, users!inner(*)')\n * .or('status.eq.active,status.eq.pending');\n * \n * // All features work:\n * - Nested selects\n * - Foreign key expansion \n * - OR/AND/NOT conditions\n * - Count with head\n * - Range pagination\n * - Upserts\n */\n from(table: string) {\n // Return postgrest query builder with all features\n return this.postgrest.from(table);\n }\n}","/**\n * Auth module for InsForge SDK\n * Uses shared schemas for type safety\n */\n\nimport { HttpClient } from '../lib/http-client';\nimport { TokenManager } from '../lib/token-manager';\nimport { AuthSession, InsForgeError } from '../types';\nimport { Database } from './database-postgrest';\n\nimport type {\n CreateUserRequest,\n CreateUserResponse,\n CreateSessionRequest,\n CreateSessionResponse,\n GetCurrentSessionResponse,\n GetOauthUrlResponse,\n} from '@insforge/shared-schemas';\n\nexport class Auth {\n private database: Database;\n \n constructor(\n private http: HttpClient,\n private tokenManager: TokenManager\n ) {\n this.database = new Database(http, tokenManager);\n \n // Auto-detect OAuth callback parameters in the URL\n this.detectOAuthCallback();\n }\n\n /**\n * Automatically detect and handle OAuth callback parameters in the URL\n * This runs on initialization to seamlessly complete the OAuth flow\n * Matches the backend's OAuth callback response (backend/src/api/routes/auth.ts:540-544)\n */\n private detectOAuthCallback(): void {\n // Only run in browser environment\n if (typeof window === 'undefined') return;\n \n try {\n const params = new URLSearchParams(window.location.search);\n \n // Backend returns: access_token, user_id, email, name (optional)\n const accessToken = params.get('access_token');\n const userId = params.get('user_id');\n const email = params.get('email');\n const name = params.get('name');\n \n // Check if we have OAuth callback parameters\n if (accessToken && userId && email) {\n // Create session with the data from backend\n const session: AuthSession = {\n accessToken,\n user: {\n id: userId,\n email: email,\n name: name || '',\n // These fields are not provided by backend OAuth callback\n // They'll be populated when calling getCurrentUser()\n emailVerified: false,\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n } as any,\n };\n \n // Save session and set auth token\n this.tokenManager.saveSession(session);\n this.http.setAuthToken(accessToken);\n \n // Clean up the URL to remove sensitive parameters\n const url = new URL(window.location.href);\n url.searchParams.delete('access_token');\n url.searchParams.delete('user_id');\n url.searchParams.delete('email');\n url.searchParams.delete('name');\n \n // Also handle error case from backend (line 581)\n if (params.has('error')) {\n url.searchParams.delete('error');\n }\n \n // Replace URL without adding to browser history\n window.history.replaceState({}, document.title, url.toString());\n }\n } catch (error) {\n // Silently continue - don't break initialization\n console.debug('OAuth callback detection skipped:', error);\n }\n }\n\n /**\n * Sign up a new user\n */\n async signUp(request: CreateUserRequest): Promise<{\n data: CreateUserResponse | null;\n error: InsForgeError | null;\n }> {\n try {\n const response = await this.http.post<CreateUserResponse>('/api/auth/users', request);\n \n // Save session internally\n const session: AuthSession = {\n accessToken: response.accessToken,\n user: response.user,\n };\n this.tokenManager.saveSession(session);\n this.http.setAuthToken(response.accessToken);\n\n return { \n data: response,\n error: null \n };\n } catch (error) {\n // Pass through API errors unchanged\n if (error instanceof InsForgeError) {\n return { data: null, error };\n }\n \n // Generic fallback for unexpected errors\n return { \n data: null, \n error: new InsForgeError(\n error instanceof Error ? error.message : 'An unexpected error occurred during sign up',\n 500,\n 'UNEXPECTED_ERROR'\n )\n };\n }\n }\n\n /**\n * Sign in with email and password\n */\n async signInWithPassword(request: CreateSessionRequest): Promise<{\n data: CreateSessionResponse | null;\n error: InsForgeError | null;\n }> {\n try {\n const response = await this.http.post<CreateSessionResponse>('/api/auth/sessions', request);\n \n // Save session internally\n const session: AuthSession = {\n accessToken: response.accessToken,\n user: response.user,\n };\n this.tokenManager.saveSession(session);\n this.http.setAuthToken(response.accessToken);\n\n return { \n data: response,\n error: null \n };\n } catch (error) {\n // Pass through API errors unchanged\n if (error instanceof InsForgeError) {\n return { data: null, error };\n }\n \n // Generic fallback for unexpected errors\n return { \n data: null, \n error: new InsForgeError(\n 'An unexpected error occurred during sign in',\n 500,\n 'UNEXPECTED_ERROR'\n )\n };\n }\n }\n\n /**\n * Sign in with OAuth provider\n */\n async signInWithOAuth(options: {\n provider: 'google' | 'github';\n redirectTo?: string;\n skipBrowserRedirect?: boolean;\n }): Promise<{\n data: { url?: string; provider?: string };\n error: InsForgeError | null;\n }> {\n try {\n const { provider, redirectTo, skipBrowserRedirect } = options;\n \n const params = redirectTo \n ? { redirect_uri: redirectTo } \n : undefined;\n \n const endpoint = `/api/auth/oauth/${provider}`;\n const response = await this.http.get<GetOauthUrlResponse>(endpoint, { params });\n \n // Automatically redirect in browser unless told not to\n if (typeof window !== 'undefined' && !skipBrowserRedirect) {\n window.location.href = response.authUrl;\n return { data: {}, error: null };\n }\n\n return { \n data: { \n url: response.authUrl,\n provider \n }, \n error: null \n };\n } catch (error) {\n // Pass through API errors unchanged\n if (error instanceof InsForgeError) {\n return { data: {}, error };\n }\n \n // Generic fallback for unexpected errors\n return { \n data: {}, \n error: new InsForgeError(\n 'An unexpected error occurred during OAuth initialization',\n 500,\n 'UNEXPECTED_ERROR'\n )\n };\n }\n }\n\n /**\n * Sign out the current user\n */\n async signOut(): Promise<{ error: InsForgeError | null }> {\n try {\n this.tokenManager.clearSession();\n this.http.setAuthToken(null);\n return { error: null };\n } catch (error) {\n return { \n error: new InsForgeError(\n 'Failed to sign out',\n 500,\n 'SIGNOUT_ERROR'\n )\n };\n }\n }\n\n /**\n * Get the current user with full profile information\n * Returns both auth info (id, email, role) and profile data (nickname, avatar_url, bio, etc.)\n */\n async getCurrentUser(): Promise<{\n data: { user: any; profile: any } | null;\n error: any | null;\n }> {\n try {\n // Check if we have a token\n const session = this.tokenManager.getSession();\n if (!session?.accessToken) {\n return { data: null, error: null };\n }\n\n // Call the API for auth info\n this.http.setAuthToken(session.accessToken);\n const authResponse = await this.http.get<GetCurrentSessionResponse>('/api/auth/sessions/current');\n \n // Get the user's profile using query builder\n const { data: profile, error: profileError } = await this.database\n .from('users')\n .select('*')\n .eq('id', authResponse.user.id)\n .single();\n \n // For database errors, return PostgrestError directly\n if (profileError && (profileError as any).code !== 'PGRST116') { // PGRST116 = not found\n return { data: null, error: profileError };\n }\n \n return {\n data: {\n user: authResponse.user,\n profile: profile\n },\n error: null\n };\n } catch (error) {\n // If unauthorized, clear session\n if (error instanceof InsForgeError && error.statusCode === 401) {\n await this.signOut();\n return { data: null, error: null };\n }\n \n // Pass through all other errors unchanged\n if (error instanceof InsForgeError) {\n return { data: null, error };\n }\n \n // Generic fallback for unexpected errors\n return { \n data: null, \n error: new InsForgeError(\n 'An unexpected error occurred while fetching user',\n 500,\n 'UNEXPECTED_ERROR'\n )\n };\n }\n }\n\n /**\n * Get any user's profile by ID\n * Returns profile information from the users table (nickname, avatar_url, bio, etc.)\n */\n async getProfile(userId: string): Promise<{\n data: any | null;\n error: any | null;\n }> {\n const { data, error } = await this.database\n .from('users')\n .select('*')\n .eq('id', userId)\n .single();\n \n // Handle not found as null, not error\n if (error && (error as any).code === 'PGRST116') {\n return { data: null, error: null };\n }\n \n // Return PostgrestError directly for database operations\n return { data, error };\n }\n\n /**\n * Get the current session (only session data, no API call)\n * Returns the stored JWT token and basic user info from local storage\n */\n getCurrentSession(): {\n data: { session: AuthSession | null };\n error: InsForgeError | null;\n } {\n try {\n const session = this.tokenManager.getSession();\n \n if (session?.accessToken) {\n this.http.setAuthToken(session.accessToken);\n return { data: { session }, error: null };\n }\n\n return { data: { session: null }, error: null };\n } catch (error) {\n // Pass through API errors unchanged\n if (error instanceof InsForgeError) {\n return { data: { session: null }, error };\n }\n \n // Generic fallback for unexpected errors\n return { \n data: { session: null }, \n error: new InsForgeError(\n 'An unexpected error occurred while getting session',\n 500,\n 'UNEXPECTED_ERROR'\n )\n };\n }\n }\n\n /**\n * Set/Update the current user's profile\n * Updates profile information in the users table (nickname, avatar_url, bio, etc.)\n */\n async setProfile(profile: {\n nickname?: string;\n avatar_url?: string;\n bio?: string;\n birthday?: string;\n [key: string]: any;\n }): Promise<{\n data: any | null;\n error: any | null;\n }> {\n // Get current session to get user ID\n const session = this.tokenManager.getSession();\n if (!session?.user?.id) {\n return { \n data: null, \n error: new InsForgeError(\n 'No authenticated user found',\n 401,\n 'UNAUTHENTICATED'\n )\n };\n }\n\n // Update the profile using query builder\n const { data, error } = await this.database\n .from('users')\n .update(profile)\n .eq('id', session.user.id)\n .select()\n .single();\n \n // Return PostgrestError directly for database operations\n return { data, error };\n }\n\n\n}","/**\n * Storage module for InsForge SDK\n * Handles file uploads, downloads, and bucket management\n */\n\nimport { HttpClient } from '../lib/http-client';\nimport { InsForgeError } from '../types';\nimport type { \n StorageFileSchema,\n ListObjectsResponseSchema\n} from '@insforge/shared-schemas';\n\nexport interface StorageResponse<T> {\n data: T | null;\n error: InsForgeError | null;\n}\n\n/**\n * Storage bucket operations\n */\nexport class StorageBucket {\n constructor(\n private bucketName: string,\n private http: HttpClient\n ) {}\n\n /**\n * Upload a file with a specific key\n * @param path - The object key/path\n * @param file - File or Blob to upload\n */\n async upload(\n path: string,\n file: File | Blob\n ): Promise<StorageResponse<StorageFileSchema>> {\n try {\n const formData = new FormData();\n formData.append('file', file);\n\n // Use PUT for specific path\n const response = await this.http.request<StorageFileSchema>(\n 'PUT',\n `/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}`,\n {\n body: formData as any,\n headers: {\n // Don't set Content-Type, let browser set multipart boundary\n }\n }\n );\n\n return { data: response, error: null };\n } catch (error) {\n return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'Upload failed',\n 500,\n 'STORAGE_ERROR'\n )\n };\n }\n }\n\n /**\n * Upload a file with auto-generated key\n * @param file - File or Blob to upload\n */\n async uploadAuto(\n file: File | Blob\n ): Promise<StorageResponse<StorageFileSchema>> {\n try {\n const formData = new FormData();\n formData.append('file', file);\n\n // Use POST for auto-generated key\n const response = await this.http.request<StorageFileSchema>(\n 'POST',\n `/api/storage/buckets/${this.bucketName}/objects`,\n {\n body: formData as any,\n headers: {\n // Don't set Content-Type, let browser set multipart boundary\n }\n }\n );\n\n return { data: response, error: null };\n } catch (error) {\n return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'Upload failed',\n 500,\n 'STORAGE_ERROR'\n )\n };\n }\n }\n\n /**\n * Download a file\n * @param path - The object key/path\n * Returns the file as a Blob\n */\n async download(path: string): Promise<{ data: Blob | null; error: InsForgeError | null }> {\n try {\n // For binary data, we need to use fetch directly with proper response handling\n // The http.request method expects JSON responses, so we can't use it for blobs\n const url = `${this.http.baseUrl}/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}`;\n \n const response = await this.http.fetch(url, {\n method: 'GET',\n headers: this.http.getHeaders()\n });\n\n if (!response.ok) {\n try {\n const error = await response.json();\n throw InsForgeError.fromApiError(error);\n } catch {\n throw new InsForgeError(\n `Download failed: ${response.statusText}`,\n response.status,\n 'STORAGE_ERROR'\n );\n }\n }\n\n const blob = await response.blob();\n return { data: blob, error: null };\n } catch (error) {\n return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'Download failed',\n 500,\n 'STORAGE_ERROR'\n )\n };\n }\n }\n\n /**\n * Get public URL for a file\n * @param path - The object key/path\n */\n getPublicUrl(path: string): string {\n return `${this.http.baseUrl}/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}`;\n }\n\n /**\n * List objects in the bucket\n * @param prefix - Filter by key prefix\n * @param search - Search in file names\n * @param limit - Maximum number of results (default: 100, max: 1000)\n * @param offset - Number of results to skip\n */\n async list(options?: {\n prefix?: string;\n search?: string;\n limit?: number;\n offset?: number;\n }): Promise<StorageResponse<ListObjectsResponseSchema>> {\n try {\n const params: Record<string, string> = {};\n \n if (options?.prefix) params.prefix = options.prefix;\n if (options?.search) params.search = options.search;\n if (options?.limit) params.limit = options.limit.toString();\n if (options?.offset) params.offset = options.offset.toString();\n\n const response = await this.http.get<ListObjectsResponseSchema>(\n `/api/storage/buckets/${this.bucketName}/objects`,\n { params }\n );\n\n return { data: response, error: null };\n } catch (error) {\n return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'List failed',\n 500,\n 'STORAGE_ERROR'\n )\n };\n }\n }\n\n /**\n * Delete a file\n * @param path - The object key/path\n */\n async remove(path: string): Promise<StorageResponse<{ message: string }>> {\n try {\n const response = await this.http.delete<{ message: string }>(\n `/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}`\n );\n\n return { data: response, error: null };\n } catch (error) {\n return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'Delete failed',\n 500,\n 'STORAGE_ERROR'\n )\n };\n }\n }\n}\n\n/**\n * Storage module for file operations\n */\nexport class Storage {\n constructor(private http: HttpClient) {}\n\n /**\n * Get a bucket instance for operations\n * @param bucketName - Name of the bucket\n */\n from(bucketName: string): StorageBucket {\n return new StorageBucket(bucketName, this.http);\n }\n}","/**\n * AI Module for Insforge SDK\n * Response format roughly matches OpenAI SDK for compatibility\n *\n * The backend handles all the complexity of different AI providers\n * and returns a unified format. This SDK transforms responses to match OpenAI-like format.\n */\n\nimport { HttpClient } from \"../lib/http-client\";\nimport {\n ChatCompletionRequest,\n ChatCompletionResponse,\n ImageGenerationRequest,\n ImageGenerationResponse,\n} from \"@insforge/shared-schemas\";\n\nexport class AI {\n public readonly chat: Chat;\n public readonly images: Images;\n\n constructor(private http: HttpClient) {\n this.chat = new Chat(http);\n this.images = new Images(http);\n }\n}\n\nclass Chat {\n public readonly completions: ChatCompletions;\n\n constructor(http: HttpClient) {\n this.completions = new ChatCompletions(http);\n }\n}\n\nclass ChatCompletions {\n constructor(private http: HttpClient) {}\n\n /**\n * Create a chat completion - OpenAI-like response format\n *\n * @example\n * ```typescript\n * // Non-streaming\n * const completion = await client.ai.chat.completions.create({\n * model: 'gpt-4',\n * messages: [{ role: 'user', content: 'Hello!' }]\n * });\n * console.log(completion.choices[0].message.content);\n *\n * // With images\n * const response = await client.ai.chat.completions.create({\n * model: 'gpt-4-vision',\n * messages: [{\n * role: 'user',\n * content: 'What is in this image?',\n * images: [{ url: 'https://example.com/image.jpg' }]\n * }]\n * });\n *\n * // Streaming - returns async iterable\n * const stream = await client.ai.chat.completions.create({\n * model: 'gpt-4',\n * messages: [{ role: 'user', content: 'Tell me a story' }],\n * stream: true\n * });\n *\n * for await (const chunk of stream) {\n * if (chunk.choices[0]?.delta?.content) {\n * process.stdout.write(chunk.choices[0].delta.content);\n * }\n * }\n * ```\n */\n async create(params: ChatCompletionRequest): Promise<any> {\n // Backend already expects camelCase, no transformation needed\n const backendParams = {\n model: params.model,\n messages: params.messages,\n temperature: params.temperature,\n maxTokens: params.maxTokens,\n topP: params.topP,\n stream: params.stream,\n };\n\n // For streaming, return an async iterable that yields OpenAI-like chunks\n if (params.stream) {\n const headers = this.http.getHeaders();\n headers[\"Content-Type\"] = \"application/json\";\n\n const response = await this.http.fetch(\n `${this.http.baseUrl}/api/ai/chat/completion`,\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(backendParams),\n }\n );\n\n if (!response.ok) {\n const error = await response.json();\n throw new Error(error.error || \"Stream request failed\");\n }\n\n // Return async iterable that parses SSE and transforms to OpenAI-like format\n return this.parseSSEStream(response, params.model);\n }\n\n // Non-streaming: transform response to OpenAI-like format\n const response: ChatCompletionResponse = await this.http.post(\n \"/api/ai/chat/completion\",\n backendParams\n );\n\n // Transform to OpenAI-like format\n const content = response.text || \"\";\n\n return {\n id: `chatcmpl-${Date.now()}`,\n object: \"chat.completion\",\n created: Math.floor(Date.now() / 1000),\n model: response.metadata?.model,\n choices: [\n {\n index: 0,\n message: {\n role: \"assistant\",\n content,\n },\n finish_reason: \"stop\",\n },\n ],\n usage: response.metadata?.usage || {\n prompt_tokens: 0,\n completion_tokens: 0,\n total_tokens: 0,\n },\n };\n }\n\n /**\n * Parse SSE stream into async iterable of OpenAI-like chunks\n */\n private async *parseSSEStream(\n response: Response,\n model: string\n ): AsyncIterableIterator<any> {\n const reader = response.body!.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() || \"\";\n\n for (const line of lines) {\n if (line.startsWith(\"data: \")) {\n const dataStr = line.slice(6).trim();\n if (dataStr) {\n try {\n const data = JSON.parse(dataStr);\n\n // Transform to OpenAI-like streaming format\n if (data.chunk || data.content) {\n yield {\n id: `chatcmpl-${Date.now()}`,\n object: \"chat.completion.chunk\",\n created: Math.floor(Date.now() / 1000),\n model,\n choices: [\n {\n index: 0,\n delta: {\n content: data.chunk || data.content,\n },\n finish_reason: data.done ? \"stop\" : null,\n },\n ],\n };\n }\n\n // If we received the done signal, we can stop\n if (data.done) {\n reader.releaseLock();\n return;\n }\n } catch (e) {\n // Skip invalid JSON\n console.warn(\"Failed to parse SSE data:\", dataStr);\n }\n }\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n}\n\nclass Images {\n constructor(private http: HttpClient) {}\n\n /**\n * Generate images - OpenAI-like response format\n *\n * @example\n * ```typescript\n * // Text-to-image\n * const response = await client.ai.images.generate({\n * model: 'dall-e-3',\n * prompt: 'A sunset over mountains',\n * });\n * console.log(response.images[0].url);\n *\n * // Image-to-image (with input images)\n * const response = await client.ai.images.generate({\n * model: 'stable-diffusion-xl',\n * prompt: 'Transform this into a watercolor painting',\n * images: [\n * { url: 'https://example.com/input.jpg' },\n * // or base64-encoded Data URI:\n * { url: 'data:image/jpeg;base64,/9j/4AAQ...' }\n * ]\n * });\n * ```\n */\n async generate(params: ImageGenerationRequest): Promise<any> {\n const response: ImageGenerationResponse = await this.http.post(\n \"/api/ai/image/generation\",\n params\n );\n console.log('response', response);\n // Check if response has images array, handle gracefully if empty/missing\n if (!response.images || response.images.length === 0) {\n console.warn('No images in response:', response);\n return {\n created: Math.floor(Date.now() / 1000),\n data: [],\n output_format: \"png\",\n ...(response.metadata?.usage && {\n usage: {\n total_tokens: response.metadata.usage.totalTokens || 0,\n input_tokens: response.metadata.usage.promptTokens || 0,\n output_tokens: response.metadata.usage.completionTokens || 0,\n }\n })\n };\n }\n\n // Transform to OpenAI SDK format with b64_json\n return {\n created: Math.floor(Date.now() / 1000),\n data: response.images.map(img => {\n // OpenRouter returns data URLs (data:image/png;base64,...)\n // Extract the base64 portion for OpenAI compatibility\n const b64_json = img.imageUrl.replace(/^data:image\\/\\w+;base64,/, '');\n \n return {\n b64_json: b64_json,\n content: response.text, // this field is not in openai sdk, but is in openrouter\n };\n }),\n output_format: \"png\",\n ...(response.metadata?.usage && {\n usage: {\n total_tokens: response.metadata.usage.totalTokens || 0,\n input_tokens: response.metadata.usage.promptTokens || 0,\n output_tokens: response.metadata.usage.completionTokens || 0,\n }\n })\n };\n }\n}\n","import { InsForgeConfig } from './types';\nimport { HttpClient } from './lib/http-client';\nimport { TokenManager } from './lib/token-manager';\nimport { Auth } from './modules/auth';\nimport { Database } from './modules/database-postgrest';\nimport { Storage } from './modules/storage';\nimport { AI } from './modules/ai';\n\n/**\n * Main InsForge SDK Client\n * \n * @example\n * ```typescript\n * import { InsForgeClient } from '@insforge/sdk';\n * \n * const client = new InsForgeClient({\n * baseUrl: 'http://localhost:7130'\n * });\n * \n * // Authentication\n * const session = await client.auth.register({\n * email: 'user@example.com',\n * password: 'password123',\n * name: 'John Doe'\n * });\n * \n * // Database operations\n * const { data, error } = await client.database\n * .from('posts')\n * .select('*')\n * .eq('user_id', session.user.id)\n * .order('created_at', { ascending: false })\n * .limit(10);\n * \n * // Insert data\n * const { data: newPost } = await client.database\n * .from('posts')\n * .insert({ title: 'Hello', content: 'World' })\n * .single();\n * ```\n */\nexport class InsForgeClient {\n private http: HttpClient;\n private tokenManager: TokenManager;\n \n public readonly auth: Auth;\n public readonly database: Database;\n public readonly storage: Storage;\n public readonly ai: AI;\n\n constructor(config: InsForgeConfig = {}) {\n this.http = new HttpClient(config);\n this.tokenManager = new TokenManager(config.storage);\n \n this.auth = new Auth(\n this.http,\n this.tokenManager\n );\n \n this.database = new Database(this.http, this.tokenManager);\n this.storage = new Storage(this.http);\n this.ai = new AI(this.http);\n }\n\n /**\n * Get the underlying HTTP client for custom requests\n * \n * @example\n * ```typescript\n * const httpClient = client.getHttpClient();\n * const customData = await httpClient.get('/api/custom-endpoint');\n * ```\n */\n getHttpClient(): HttpClient {\n return this.http;\n }\n\n /**\n * Future modules will be added here:\n * - database: Database operations\n * - storage: File storage operations\n * - functions: Serverless functions\n * - tables: Table management\n * - metadata: Backend metadata\n */\n}"],"mappings":"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","names":["response"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/types.ts","../src/lib/http-client.ts","../src/lib/token-manager.ts","../src/modules/database-postgrest.ts","../src/modules/auth.ts","../src/modules/storage.ts","../src/modules/ai.ts","../src/client.ts"],"sourcesContent":["/**\n * @insforge/sdk - TypeScript SDK for InsForge Backend-as-a-Service\n * \n * @packageDocumentation\n */\n\n// Main client\nexport { InsForgeClient } from './client';\n\n// Types\nexport type {\n InsForgeConfig,\n InsForgeConfig as ClientOptions, // Alias for compatibility\n TokenStorage,\n AuthSession,\n ApiError,\n} from './types';\n\nexport { InsForgeError } from './types';\n\n// Re-export shared schemas that SDK users will need\nexport type {\n UserSchema,\n CreateUserRequest,\n CreateSessionRequest,\n AuthErrorResponse,\n} from '@insforge/shared-schemas';\n\n// Re-export auth module for advanced usage\nexport { Auth } from './modules/auth';\n\n// Re-export database module (using postgrest-js)\nexport { Database } from './modules/database-postgrest';\n// Note: QueryBuilder is no longer exported as we use postgrest-js QueryBuilder internally\n\n// Re-export storage module and types\nexport { Storage, StorageBucket } from './modules/storage';\nexport type { StorageResponse } from './modules/storage';\n\n// Re-export AI module\nexport { AI } from './modules/ai';\n\n// Re-export utilities for advanced usage\nexport { HttpClient } from './lib/http-client';\nexport { TokenManager } from './lib/token-manager';\n\n// Factory function for creating clients (Supabase-style)\nimport { InsForgeClient } from './client';\nimport { InsForgeConfig } from './types';\n\nexport function createClient(config: InsForgeConfig): InsForgeClient {\n return new InsForgeClient(config);\n}\n\n// Default export for convenience\nexport default InsForgeClient;","/**\n * InsForge SDK Types - only SDK-specific types here\n * Use @insforge/shared-schemas directly for API types\n */\n\nimport type { UserSchema } from '@insforge/shared-schemas';\n\nexport interface InsForgeConfig {\n /**\n * The base URL of the InsForge backend API\n * @default \"http://localhost:7130\"\n */\n baseUrl?: string;\n\n /**\n * Anonymous API key (optional)\n * Used for public/unauthenticated requests when no user token is set\n */\n anonKey?: string;\n\n /**\n * Custom fetch implementation (useful for Node.js environments)\n */\n fetch?: typeof fetch;\n\n /**\n * Storage adapter for persisting tokens\n */\n storage?: TokenStorage;\n\n /**\n * Whether to automatically refresh tokens before they expire\n * @default true\n */\n autoRefreshToken?: boolean;\n\n /**\n * Whether to persist session in storage\n * @default true\n */\n persistSession?: boolean;\n\n /**\n * Custom headers to include with every request\n */\n headers?: Record<string, string>;\n}\n\nexport interface TokenStorage {\n getItem(key: string): string | null | Promise<string | null>;\n setItem(key: string, value: string): void | Promise<void>;\n removeItem(key: string): void | Promise<void>;\n}\n\nexport interface AuthSession {\n user: UserSchema;\n accessToken: string;\n expiresAt?: Date;\n}\n\nexport interface ApiError {\n error: string;\n message: string;\n statusCode: number;\n nextActions?: string;\n}\n\nexport class InsForgeError extends Error {\n public statusCode: number;\n public error: string;\n public nextActions?: string;\n\n constructor(message: string, statusCode: number, error: string, nextActions?: string) {\n super(message);\n this.name = 'InsForgeError';\n this.statusCode = statusCode;\n this.error = error;\n this.nextActions = nextActions;\n }\n\n static fromApiError(apiError: ApiError): InsForgeError {\n return new InsForgeError(\n apiError.message,\n apiError.statusCode,\n apiError.error,\n apiError.nextActions\n );\n }\n}","import { InsForgeConfig, ApiError, InsForgeError } from '../types';\n\nexport interface RequestOptions extends RequestInit {\n params?: Record<string, string>;\n}\n\nexport class HttpClient {\n public readonly baseUrl: string;\n public readonly fetch: typeof fetch;\n private defaultHeaders: Record<string, string>;\n private anonKey: string | undefined;\n private userToken: string | null = null;\n\n constructor(config: InsForgeConfig) {\n this.baseUrl = config.baseUrl || 'http://localhost:7130';\n // Properly bind fetch to maintain its context\n this.fetch = config.fetch || (globalThis.fetch ? globalThis.fetch.bind(globalThis) : undefined as any);\n this.anonKey = config.anonKey;\n this.defaultHeaders = {\n ...config.headers,\n };\n\n if (!this.fetch) {\n throw new Error(\n 'Fetch is not available. Please provide a fetch implementation in the config.'\n );\n }\n }\n\n private buildUrl(path: string, params?: Record<string, string>): string {\n const url = new URL(path, this.baseUrl);\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n // For select parameter, preserve the exact formatting by normalizing whitespace\n // This ensures PostgREST relationship queries work correctly\n if (key === 'select') {\n // Normalize multiline select strings for PostgREST:\n // 1. Replace all whitespace (including newlines) with single space\n // 2. Remove spaces inside parentheses for proper PostgREST syntax\n // 3. Keep spaces after commas at the top level for readability\n let normalizedValue = value.replace(/\\s+/g, ' ').trim();\n \n // Fix spaces around parentheses and inside them\n normalizedValue = normalizedValue\n .replace(/\\s*\\(\\s*/g, '(') // Remove spaces around opening parens\n .replace(/\\s*\\)\\s*/g, ')') // Remove spaces around closing parens\n .replace(/\\(\\s+/g, '(') // Remove spaces after opening parens\n .replace(/\\s+\\)/g, ')') // Remove spaces before closing parens\n .replace(/,\\s+(?=[^()]*\\))/g, ','); // Remove spaces after commas inside parens\n \n url.searchParams.append(key, normalizedValue);\n } else {\n url.searchParams.append(key, value);\n }\n });\n }\n return url.toString();\n }\n\n async request<T>(\n method: string,\n path: string,\n options: RequestOptions = {}\n ): Promise<T> {\n const { params, headers = {}, body, ...fetchOptions } = options;\n \n const url = this.buildUrl(path, params);\n \n const requestHeaders: Record<string, string> = {\n ...this.defaultHeaders,\n };\n \n // Set Authorization header: prefer user token, fallback to anon key\n const authToken = this.userToken || this.anonKey;\n if (authToken) {\n requestHeaders['Authorization'] = `Bearer ${authToken}`;\n }\n \n // Handle body serialization\n let processedBody: any;\n if (body !== undefined) {\n // Check if body is FormData (for file uploads)\n if (typeof FormData !== 'undefined' && body instanceof FormData) {\n // Don't set Content-Type for FormData, let browser set it with boundary\n processedBody = body;\n } else {\n // JSON body\n if (method !== 'GET') {\n requestHeaders['Content-Type'] = 'application/json;charset=UTF-8';\n }\n processedBody = JSON.stringify(body);\n }\n }\n \n Object.assign(requestHeaders, headers);\n \n const response = await this.fetch(url, {\n method,\n headers: requestHeaders,\n body: processedBody,\n ...fetchOptions,\n });\n\n // Handle 204 No Content\n if (response.status === 204) {\n return undefined as T;\n }\n\n // Try to parse JSON response\n let data: any;\n const contentType = response.headers.get('content-type');\n // Check for any JSON content type (including PostgREST's vnd.pgrst.object+json)\n if (contentType?.includes('json')) {\n data = await response.json();\n } else {\n // For non-JSON responses, return text\n data = await response.text();\n }\n\n // Handle errors\n if (!response.ok) {\n if (data && typeof data === 'object' && 'error' in data) {\n throw InsForgeError.fromApiError(data as ApiError);\n }\n throw new InsForgeError(\n `Request failed: ${response.statusText}`,\n response.status,\n 'REQUEST_FAILED'\n );\n }\n\n return data as T;\n }\n\n get<T>(path: string, options?: RequestOptions): Promise<T> {\n return this.request<T>('GET', path, options);\n }\n\n post<T>(path: string, body?: any, options?: RequestOptions): Promise<T> {\n return this.request<T>('POST', path, { ...options, body });\n }\n\n put<T>(path: string, body?: any, options?: RequestOptions): Promise<T> {\n return this.request<T>('PUT', path, { ...options, body });\n }\n\n patch<T>(path: string, body?: any, options?: RequestOptions): Promise<T> {\n return this.request<T>('PATCH', path, { ...options, body });\n }\n\n delete<T>(path: string, options?: RequestOptions): Promise<T> {\n return this.request<T>('DELETE', path, options);\n }\n\n setAuthToken(token: string | null) {\n this.userToken = token;\n }\n\n getHeaders(): Record<string, string> {\n return { ...this.defaultHeaders };\n }\n}","import { TokenStorage, AuthSession } from '../types';\n\nconst TOKEN_KEY = 'insforge-auth-token';\nconst USER_KEY = 'insforge-auth-user';\n\nexport class TokenManager {\n private storage: TokenStorage;\n\n constructor(storage?: TokenStorage) {\n if (storage) {\n // Use provided storage\n this.storage = storage;\n } else if (typeof window !== 'undefined' && window.localStorage) {\n // Browser: use localStorage\n this.storage = window.localStorage;\n } else {\n // Node.js: use in-memory storage\n const store = new Map<string, string>();\n this.storage = {\n getItem: (key: string) => store.get(key) || null,\n setItem: (key: string, value: string) => { store.set(key, value); },\n removeItem: (key: string) => { store.delete(key); }\n };\n }\n }\n\n saveSession(session: AuthSession): void {\n this.storage.setItem(TOKEN_KEY, session.accessToken);\n this.storage.setItem(USER_KEY, JSON.stringify(session.user));\n }\n\n getSession(): AuthSession | null {\n const token = this.storage.getItem(TOKEN_KEY);\n const userStr = this.storage.getItem(USER_KEY);\n\n if (!token || !userStr) {\n return null;\n }\n\n try {\n const user = JSON.parse(userStr as string);\n return { accessToken: token as string, user };\n } catch {\n this.clearSession();\n return null;\n }\n }\n\n getAccessToken(): string | null {\n const token = this.storage.getItem(TOKEN_KEY);\n return typeof token === 'string' ? token : null;\n }\n\n clearSession(): void {\n this.storage.removeItem(TOKEN_KEY);\n this.storage.removeItem(USER_KEY);\n }\n}","/**\n * Database module using @supabase/postgrest-js\n * Complete replacement for custom QueryBuilder with full PostgREST features\n */\n\nimport { PostgrestClient } from '@supabase/postgrest-js';\nimport { HttpClient } from '../lib/http-client';\nimport { TokenManager } from '../lib/token-manager';\n\n\n/**\n * Custom fetch that transforms URLs and adds auth\n */\nfunction createInsForgePostgrestFetch(\n httpClient: HttpClient,\n tokenManager: TokenManager\n): typeof fetch {\n return async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const url = typeof input === 'string' ? input : input.toString();\n const urlObj = new URL(url);\n \n // Extract table name from pathname\n // postgrest-js sends: http://dummy/tablename?params\n // We need: http://localhost:7130/api/database/records/tablename?params\n const tableName = urlObj.pathname.slice(1); // Remove leading /\n \n // Build InsForge URL\n const insforgeUrl = `${httpClient.baseUrl}/api/database/records/${tableName}${urlObj.search}`;\n \n // Get auth token from TokenManager\n const token = tokenManager.getAccessToken();\n \n // Prepare headers\n const headers = new Headers(init?.headers);\n if (token && !headers.has('Authorization')) {\n headers.set('Authorization', `Bearer ${token}`);\n }\n \n // Make the actual request using native fetch\n // This returns a proper Response object with headers\n const response = await fetch(insforgeUrl, {\n ...init,\n headers\n });\n \n return response;\n };\n}\n\n/**\n * Database client using postgrest-js\n * Drop-in replacement with FULL PostgREST capabilities\n */\nexport class Database {\n private postgrest: PostgrestClient<any, any, any>;\n \n constructor(httpClient: HttpClient, tokenManager: TokenManager) {\n // Create postgrest client with custom fetch\n this.postgrest = new PostgrestClient<any, any, any>('http://dummy', {\n fetch: createInsForgePostgrestFetch(httpClient, tokenManager),\n headers: {}\n });\n }\n \n /**\n * Create a query builder for a table\n * \n * @example\n * // Basic query\n * const { data, error } = await client.database\n * .from('posts')\n * .select('*')\n * .eq('user_id', userId);\n * \n * // With count (Supabase style!)\n * const { data, error, count } = await client.database\n * .from('posts')\n * .select('*', { count: 'exact' })\n * .range(0, 9);\n * \n * // Just get count, no data\n * const { count } = await client.database\n * .from('posts')\n * .select('*', { count: 'exact', head: true });\n * \n * // Complex queries with OR\n * const { data } = await client.database\n * .from('posts')\n * .select('*, users!inner(*)')\n * .or('status.eq.active,status.eq.pending');\n * \n * // All features work:\n * - Nested selects\n * - Foreign key expansion \n * - OR/AND/NOT conditions\n * - Count with head\n * - Range pagination\n * - Upserts\n */\n from(table: string) {\n // Return postgrest query builder with all features\n return this.postgrest.from(table);\n }\n}","/**\n * Auth module for InsForge SDK\n * Uses shared schemas for type safety\n */\n\nimport { HttpClient } from '../lib/http-client';\nimport { TokenManager } from '../lib/token-manager';\nimport { AuthSession, InsForgeError } from '../types';\nimport { Database } from './database-postgrest';\n\nimport type {\n CreateUserRequest,\n CreateUserResponse,\n CreateSessionRequest,\n CreateSessionResponse,\n GetCurrentSessionResponse,\n GetOauthUrlResponse,\n} from '@insforge/shared-schemas';\n\nexport class Auth {\n private database: Database;\n \n constructor(\n private http: HttpClient,\n private tokenManager: TokenManager\n ) {\n this.database = new Database(http, tokenManager);\n \n // Auto-detect OAuth callback parameters in the URL\n this.detectOAuthCallback();\n }\n\n /**\n * Automatically detect and handle OAuth callback parameters in the URL\n * This runs on initialization to seamlessly complete the OAuth flow\n * Matches the backend's OAuth callback response (backend/src/api/routes/auth.ts:540-544)\n */\n private detectOAuthCallback(): void {\n // Only run in browser environment\n if (typeof window === 'undefined') return;\n \n try {\n const params = new URLSearchParams(window.location.search);\n \n // Backend returns: access_token, user_id, email, name (optional)\n const accessToken = params.get('access_token');\n const userId = params.get('user_id');\n const email = params.get('email');\n const name = params.get('name');\n \n // Check if we have OAuth callback parameters\n if (accessToken && userId && email) {\n // Create session with the data from backend\n const session: AuthSession = {\n accessToken,\n user: {\n id: userId,\n email: email,\n name: name || '',\n // These fields are not provided by backend OAuth callback\n // They'll be populated when calling getCurrentUser()\n emailVerified: false,\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n } as any,\n };\n \n // Save session and set auth token\n this.tokenManager.saveSession(session);\n this.http.setAuthToken(accessToken);\n \n // Clean up the URL to remove sensitive parameters\n const url = new URL(window.location.href);\n url.searchParams.delete('access_token');\n url.searchParams.delete('user_id');\n url.searchParams.delete('email');\n url.searchParams.delete('name');\n \n // Also handle error case from backend (line 581)\n if (params.has('error')) {\n url.searchParams.delete('error');\n }\n \n // Replace URL without adding to browser history\n window.history.replaceState({}, document.title, url.toString());\n }\n } catch (error) {\n // Silently continue - don't break initialization\n console.debug('OAuth callback detection skipped:', error);\n }\n }\n\n /**\n * Sign up a new user\n */\n async signUp(request: CreateUserRequest): Promise<{\n data: CreateUserResponse | null;\n error: InsForgeError | null;\n }> {\n try {\n const response = await this.http.post<CreateUserResponse>('/api/auth/users', request);\n \n // Save session internally\n const session: AuthSession = {\n accessToken: response.accessToken,\n user: response.user,\n };\n this.tokenManager.saveSession(session);\n this.http.setAuthToken(response.accessToken);\n\n return { \n data: response,\n error: null \n };\n } catch (error) {\n // Pass through API errors unchanged\n if (error instanceof InsForgeError) {\n return { data: null, error };\n }\n \n // Generic fallback for unexpected errors\n return { \n data: null, \n error: new InsForgeError(\n error instanceof Error ? error.message : 'An unexpected error occurred during sign up',\n 500,\n 'UNEXPECTED_ERROR'\n )\n };\n }\n }\n\n /**\n * Sign in with email and password\n */\n async signInWithPassword(request: CreateSessionRequest): Promise<{\n data: CreateSessionResponse | null;\n error: InsForgeError | null;\n }> {\n try {\n const response = await this.http.post<CreateSessionResponse>('/api/auth/sessions', request);\n \n // Save session internally\n const session: AuthSession = {\n accessToken: response.accessToken,\n user: response.user,\n };\n this.tokenManager.saveSession(session);\n this.http.setAuthToken(response.accessToken);\n\n return { \n data: response,\n error: null \n };\n } catch (error) {\n // Pass through API errors unchanged\n if (error instanceof InsForgeError) {\n return { data: null, error };\n }\n \n // Generic fallback for unexpected errors\n return { \n data: null, \n error: new InsForgeError(\n 'An unexpected error occurred during sign in',\n 500,\n 'UNEXPECTED_ERROR'\n )\n };\n }\n }\n\n /**\n * Sign in with OAuth provider\n */\n async signInWithOAuth(options: {\n provider: 'google' | 'github';\n redirectTo?: string;\n skipBrowserRedirect?: boolean;\n }): Promise<{\n data: { url?: string; provider?: string };\n error: InsForgeError | null;\n }> {\n try {\n const { provider, redirectTo, skipBrowserRedirect } = options;\n \n const params = redirectTo \n ? { redirect_uri: redirectTo } \n : undefined;\n \n const endpoint = `/api/auth/oauth/${provider}`;\n const response = await this.http.get<GetOauthUrlResponse>(endpoint, { params });\n \n // Automatically redirect in browser unless told not to\n if (typeof window !== 'undefined' && !skipBrowserRedirect) {\n window.location.href = response.authUrl;\n return { data: {}, error: null };\n }\n\n return { \n data: { \n url: response.authUrl,\n provider \n }, \n error: null \n };\n } catch (error) {\n // Pass through API errors unchanged\n if (error instanceof InsForgeError) {\n return { data: {}, error };\n }\n \n // Generic fallback for unexpected errors\n return { \n data: {}, \n error: new InsForgeError(\n 'An unexpected error occurred during OAuth initialization',\n 500,\n 'UNEXPECTED_ERROR'\n )\n };\n }\n }\n\n /**\n * Sign out the current user\n */\n async signOut(): Promise<{ error: InsForgeError | null }> {\n try {\n this.tokenManager.clearSession();\n this.http.setAuthToken(null);\n return { error: null };\n } catch (error) {\n return { \n error: new InsForgeError(\n 'Failed to sign out',\n 500,\n 'SIGNOUT_ERROR'\n )\n };\n }\n }\n\n /**\n * Get the current user with full profile information\n * Returns both auth info (id, email, role) and profile data (nickname, avatar_url, bio, etc.)\n */\n async getCurrentUser(): Promise<{\n data: { user: any; profile: any } | null;\n error: any | null;\n }> {\n try {\n // Check if we have a token\n const session = this.tokenManager.getSession();\n if (!session?.accessToken) {\n return { data: null, error: null };\n }\n\n // Call the API for auth info\n this.http.setAuthToken(session.accessToken);\n const authResponse = await this.http.get<GetCurrentSessionResponse>('/api/auth/sessions/current');\n \n // Get the user's profile using query builder\n const { data: profile, error: profileError } = await this.database\n .from('users')\n .select('*')\n .eq('id', authResponse.user.id)\n .single();\n \n // For database errors, return PostgrestError directly\n if (profileError && (profileError as any).code !== 'PGRST116') { // PGRST116 = not found\n return { data: null, error: profileError };\n }\n \n return {\n data: {\n user: authResponse.user,\n profile: profile\n },\n error: null\n };\n } catch (error) {\n // If unauthorized, clear session\n if (error instanceof InsForgeError && error.statusCode === 401) {\n await this.signOut();\n return { data: null, error: null };\n }\n \n // Pass through all other errors unchanged\n if (error instanceof InsForgeError) {\n return { data: null, error };\n }\n \n // Generic fallback for unexpected errors\n return { \n data: null, \n error: new InsForgeError(\n 'An unexpected error occurred while fetching user',\n 500,\n 'UNEXPECTED_ERROR'\n )\n };\n }\n }\n\n /**\n * Get any user's profile by ID\n * Returns profile information from the users table (nickname, avatar_url, bio, etc.)\n */\n async getProfile(userId: string): Promise<{\n data: any | null;\n error: any | null;\n }> {\n const { data, error } = await this.database\n .from('users')\n .select('*')\n .eq('id', userId)\n .single();\n \n // Handle not found as null, not error\n if (error && (error as any).code === 'PGRST116') {\n return { data: null, error: null };\n }\n \n // Return PostgrestError directly for database operations\n return { data, error };\n }\n\n /**\n * Get the current session (only session data, no API call)\n * Returns the stored JWT token and basic user info from local storage\n */\n getCurrentSession(): {\n data: { session: AuthSession | null };\n error: InsForgeError | null;\n } {\n try {\n const session = this.tokenManager.getSession();\n \n if (session?.accessToken) {\n this.http.setAuthToken(session.accessToken);\n return { data: { session }, error: null };\n }\n\n return { data: { session: null }, error: null };\n } catch (error) {\n // Pass through API errors unchanged\n if (error instanceof InsForgeError) {\n return { data: { session: null }, error };\n }\n \n // Generic fallback for unexpected errors\n return { \n data: { session: null }, \n error: new InsForgeError(\n 'An unexpected error occurred while getting session',\n 500,\n 'UNEXPECTED_ERROR'\n )\n };\n }\n }\n\n /**\n * Set/Update the current user's profile\n * Updates profile information in the users table (nickname, avatar_url, bio, etc.)\n */\n async setProfile(profile: {\n nickname?: string;\n avatar_url?: string;\n bio?: string;\n birthday?: string;\n [key: string]: any;\n }): Promise<{\n data: any | null;\n error: any | null;\n }> {\n // Get current session to get user ID\n const session = this.tokenManager.getSession();\n if (!session?.user?.id) {\n return { \n data: null, \n error: new InsForgeError(\n 'No authenticated user found',\n 401,\n 'UNAUTHENTICATED'\n )\n };\n }\n\n // Update the profile using query builder\n const { data, error } = await this.database\n .from('users')\n .update(profile)\n .eq('id', session.user.id)\n .select()\n .single();\n \n // Return PostgrestError directly for database operations\n return { data, error };\n }\n\n\n}","/**\n * Storage module for InsForge SDK\n * Handles file uploads, downloads, and bucket management\n */\n\nimport { HttpClient } from '../lib/http-client';\nimport { InsForgeError } from '../types';\nimport type { \n StorageFileSchema,\n ListObjectsResponseSchema\n} from '@insforge/shared-schemas';\n\nexport interface StorageResponse<T> {\n data: T | null;\n error: InsForgeError | null;\n}\n\ninterface UploadStrategy {\n method: 'direct' | 'presigned';\n uploadUrl: string;\n fields?: Record<string, string>;\n key: string;\n confirmRequired: boolean;\n confirmUrl?: string;\n expiresAt?: Date;\n}\n\ninterface DownloadStrategy {\n method: 'direct' | 'presigned';\n url: string;\n expiresAt?: Date;\n}\n\n/**\n * Storage bucket operations\n */\nexport class StorageBucket {\n constructor(\n private bucketName: string,\n private http: HttpClient\n ) {}\n\n /**\n * Upload a file with a specific key\n * Uses the upload strategy from backend (direct or presigned)\n * @param path - The object key/path\n * @param file - File or Blob to upload\n */\n async upload(\n path: string,\n file: File | Blob\n ): Promise<StorageResponse<StorageFileSchema>> {\n try {\n // Get upload strategy from backend - this is required\n const strategyResponse = await this.http.post<UploadStrategy>(\n `/api/storage/buckets/${this.bucketName}/upload-strategy`,\n {\n filename: path,\n contentType: file.type || 'application/octet-stream',\n size: file.size\n }\n );\n\n // Use presigned URL if available\n if (strategyResponse.method === 'presigned') {\n return await this.uploadWithPresignedUrl(strategyResponse, file);\n }\n\n // Use direct upload if strategy says so\n if (strategyResponse.method === 'direct') {\n const formData = new FormData();\n formData.append('file', file);\n\n const response = await this.http.request<StorageFileSchema>(\n 'PUT',\n `/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}`,\n {\n body: formData as any,\n headers: {\n // Don't set Content-Type, let browser set multipart boundary\n }\n }\n );\n\n return { data: response, error: null };\n }\n\n throw new InsForgeError(\n `Unsupported upload method: ${strategyResponse.method}`,\n 500,\n 'STORAGE_ERROR'\n );\n } catch (error) {\n return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'Upload failed',\n 500,\n 'STORAGE_ERROR'\n )\n };\n }\n }\n\n /**\n * Upload a file with auto-generated key\n * Uses the upload strategy from backend (direct or presigned)\n * @param file - File or Blob to upload\n */\n async uploadAuto(\n file: File | Blob\n ): Promise<StorageResponse<StorageFileSchema>> {\n try {\n const filename = file instanceof File ? file.name : 'file';\n \n // Get upload strategy from backend - this is required\n const strategyResponse = await this.http.post<UploadStrategy>(\n `/api/storage/buckets/${this.bucketName}/upload-strategy`,\n {\n filename,\n contentType: file.type || 'application/octet-stream',\n size: file.size\n }\n );\n\n // Use presigned URL if available\n if (strategyResponse.method === 'presigned') {\n return await this.uploadWithPresignedUrl(strategyResponse, file);\n }\n\n // Use direct upload if strategy says so\n if (strategyResponse.method === 'direct') {\n const formData = new FormData();\n formData.append('file', file);\n\n const response = await this.http.request<StorageFileSchema>(\n 'POST',\n `/api/storage/buckets/${this.bucketName}/objects`,\n {\n body: formData as any,\n headers: {\n // Don't set Content-Type, let browser set multipart boundary\n }\n }\n );\n\n return { data: response, error: null };\n }\n\n throw new InsForgeError(\n `Unsupported upload method: ${strategyResponse.method}`,\n 500,\n 'STORAGE_ERROR'\n );\n } catch (error) {\n return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'Upload failed',\n 500,\n 'STORAGE_ERROR'\n )\n };\n }\n }\n\n /**\n * Internal method to handle presigned URL uploads\n */\n private async uploadWithPresignedUrl(\n strategy: UploadStrategy,\n file: File | Blob\n ): Promise<StorageResponse<StorageFileSchema>> {\n try {\n // Upload to presigned URL (e.g., S3)\n const formData = new FormData();\n \n // Add all fields from the presigned URL\n if (strategy.fields) {\n Object.entries(strategy.fields).forEach(([key, value]) => {\n formData.append(key, value);\n });\n }\n \n // File must be the last field for S3\n formData.append('file', file);\n\n const uploadResponse = await fetch(strategy.uploadUrl, {\n method: 'POST',\n body: formData\n });\n\n if (!uploadResponse.ok) {\n throw new InsForgeError(\n `Upload to storage failed: ${uploadResponse.statusText}`,\n uploadResponse.status,\n 'STORAGE_ERROR'\n );\n }\n\n // Confirm upload with backend if required\n if (strategy.confirmRequired && strategy.confirmUrl) {\n const confirmResponse = await this.http.post<StorageFileSchema>(\n strategy.confirmUrl,\n {\n size: file.size,\n contentType: file.type || 'application/octet-stream'\n }\n );\n\n return { data: confirmResponse, error: null };\n }\n\n // If no confirmation required, return basic file info\n return {\n data: {\n key: strategy.key,\n bucket: this.bucketName,\n size: file.size,\n mimeType: file.type || 'application/octet-stream',\n uploadedAt: new Date().toISOString(),\n url: this.getPublicUrl(strategy.key)\n } as StorageFileSchema,\n error: null\n };\n } catch (error) {\n throw error instanceof InsForgeError ? error : new InsForgeError(\n 'Presigned upload failed',\n 500,\n 'STORAGE_ERROR'\n );\n }\n }\n\n /**\n * Download a file\n * Uses the download strategy from backend (direct or presigned)\n * @param path - The object key/path\n * Returns the file as a Blob\n */\n async download(path: string): Promise<{ data: Blob | null; error: InsForgeError | null }> {\n try {\n // Get download strategy from backend - this is required\n const strategyResponse = await this.http.post<DownloadStrategy>(\n `/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}/download-strategy`,\n { expiresIn: 3600 }\n );\n\n // Use URL from strategy\n const downloadUrl = strategyResponse.url;\n \n // Download from the URL\n const headers: HeadersInit = {};\n \n // Only add auth header for direct downloads (not presigned URLs)\n if (strategyResponse.method === 'direct') {\n Object.assign(headers, this.http.getHeaders());\n }\n \n const response = await fetch(downloadUrl, {\n method: 'GET',\n headers\n });\n\n if (!response.ok) {\n try {\n const error = await response.json();\n throw InsForgeError.fromApiError(error);\n } catch {\n throw new InsForgeError(\n `Download failed: ${response.statusText}`,\n response.status,\n 'STORAGE_ERROR'\n );\n }\n }\n\n const blob = await response.blob();\n return { data: blob, error: null };\n } catch (error) {\n return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'Download failed',\n 500,\n 'STORAGE_ERROR'\n )\n };\n }\n }\n\n /**\n * Get public URL for a file\n * @param path - The object key/path\n */\n getPublicUrl(path: string): string {\n return `${this.http.baseUrl}/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}`;\n }\n\n /**\n * List objects in the bucket\n * @param prefix - Filter by key prefix\n * @param search - Search in file names\n * @param limit - Maximum number of results (default: 100, max: 1000)\n * @param offset - Number of results to skip\n */\n async list(options?: {\n prefix?: string;\n search?: string;\n limit?: number;\n offset?: number;\n }): Promise<StorageResponse<ListObjectsResponseSchema>> {\n try {\n const params: Record<string, string> = {};\n \n if (options?.prefix) params.prefix = options.prefix;\n if (options?.search) params.search = options.search;\n if (options?.limit) params.limit = options.limit.toString();\n if (options?.offset) params.offset = options.offset.toString();\n\n const response = await this.http.get<ListObjectsResponseSchema>(\n `/api/storage/buckets/${this.bucketName}/objects`,\n { params }\n );\n\n return { data: response, error: null };\n } catch (error) {\n return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'List failed',\n 500,\n 'STORAGE_ERROR'\n )\n };\n }\n }\n\n /**\n * Delete a file\n * @param path - The object key/path\n */\n async remove(path: string): Promise<StorageResponse<{ message: string }>> {\n try {\n const response = await this.http.delete<{ message: string }>(\n `/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}`\n );\n\n return { data: response, error: null };\n } catch (error) {\n return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'Delete failed',\n 500,\n 'STORAGE_ERROR'\n )\n };\n }\n }\n}\n\n/**\n * Storage module for file operations\n */\nexport class Storage {\n constructor(private http: HttpClient) {}\n\n /**\n * Get a bucket instance for operations\n * @param bucketName - Name of the bucket\n */\n from(bucketName: string): StorageBucket {\n return new StorageBucket(bucketName, this.http);\n }\n}","/**\n * AI Module for Insforge SDK\n * Response format roughly matches OpenAI SDK for compatibility\n *\n * The backend handles all the complexity of different AI providers\n * and returns a unified format. This SDK transforms responses to match OpenAI-like format.\n */\n\nimport { HttpClient } from \"../lib/http-client\";\nimport {\n ChatCompletionRequest,\n ChatCompletionResponse,\n ImageGenerationRequest,\n ImageGenerationResponse,\n} from \"@insforge/shared-schemas\";\n\nexport class AI {\n public readonly chat: Chat;\n public readonly images: Images;\n\n constructor(private http: HttpClient) {\n this.chat = new Chat(http);\n this.images = new Images(http);\n }\n}\n\nclass Chat {\n public readonly completions: ChatCompletions;\n\n constructor(http: HttpClient) {\n this.completions = new ChatCompletions(http);\n }\n}\n\nclass ChatCompletions {\n constructor(private http: HttpClient) {}\n\n /**\n * Create a chat completion - OpenAI-like response format\n *\n * @example\n * ```typescript\n * // Non-streaming\n * const completion = await client.ai.chat.completions.create({\n * model: 'gpt-4',\n * messages: [{ role: 'user', content: 'Hello!' }]\n * });\n * console.log(completion.choices[0].message.content);\n *\n * // With images\n * const response = await client.ai.chat.completions.create({\n * model: 'gpt-4-vision',\n * messages: [{\n * role: 'user',\n * content: 'What is in this image?',\n * images: [{ url: 'https://example.com/image.jpg' }]\n * }]\n * });\n *\n * // Streaming - returns async iterable\n * const stream = await client.ai.chat.completions.create({\n * model: 'gpt-4',\n * messages: [{ role: 'user', content: 'Tell me a story' }],\n * stream: true\n * });\n *\n * for await (const chunk of stream) {\n * if (chunk.choices[0]?.delta?.content) {\n * process.stdout.write(chunk.choices[0].delta.content);\n * }\n * }\n * ```\n */\n async create(params: ChatCompletionRequest): Promise<any> {\n // Backend already expects camelCase, no transformation needed\n const backendParams = {\n model: params.model,\n messages: params.messages,\n temperature: params.temperature,\n maxTokens: params.maxTokens,\n topP: params.topP,\n stream: params.stream,\n };\n\n // For streaming, return an async iterable that yields OpenAI-like chunks\n if (params.stream) {\n const headers = this.http.getHeaders();\n headers[\"Content-Type\"] = \"application/json\";\n\n const response = await this.http.fetch(\n `${this.http.baseUrl}/api/ai/chat/completion`,\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(backendParams),\n }\n );\n\n if (!response.ok) {\n const error = await response.json();\n throw new Error(error.error || \"Stream request failed\");\n }\n\n // Return async iterable that parses SSE and transforms to OpenAI-like format\n return this.parseSSEStream(response, params.model);\n }\n\n // Non-streaming: transform response to OpenAI-like format\n const response: ChatCompletionResponse = await this.http.post(\n \"/api/ai/chat/completion\",\n backendParams\n );\n\n // Transform to OpenAI-like format\n const content = response.text || \"\";\n\n return {\n id: `chatcmpl-${Date.now()}`,\n object: \"chat.completion\",\n created: Math.floor(Date.now() / 1000),\n model: response.metadata?.model,\n choices: [\n {\n index: 0,\n message: {\n role: \"assistant\",\n content,\n },\n finish_reason: \"stop\",\n },\n ],\n usage: response.metadata?.usage || {\n prompt_tokens: 0,\n completion_tokens: 0,\n total_tokens: 0,\n },\n };\n }\n\n /**\n * Parse SSE stream into async iterable of OpenAI-like chunks\n */\n private async *parseSSEStream(\n response: Response,\n model: string\n ): AsyncIterableIterator<any> {\n const reader = response.body!.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() || \"\";\n\n for (const line of lines) {\n if (line.startsWith(\"data: \")) {\n const dataStr = line.slice(6).trim();\n if (dataStr) {\n try {\n const data = JSON.parse(dataStr);\n\n // Transform to OpenAI-like streaming format\n if (data.chunk || data.content) {\n yield {\n id: `chatcmpl-${Date.now()}`,\n object: \"chat.completion.chunk\",\n created: Math.floor(Date.now() / 1000),\n model,\n choices: [\n {\n index: 0,\n delta: {\n content: data.chunk || data.content,\n },\n finish_reason: data.done ? \"stop\" : null,\n },\n ],\n };\n }\n\n // If we received the done signal, we can stop\n if (data.done) {\n reader.releaseLock();\n return;\n }\n } catch (e) {\n // Skip invalid JSON\n console.warn(\"Failed to parse SSE data:\", dataStr);\n }\n }\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n}\n\nclass Images {\n constructor(private http: HttpClient) {}\n\n /**\n * Generate images - OpenAI-like response format\n *\n * @example\n * ```typescript\n * // Text-to-image\n * const response = await client.ai.images.generate({\n * model: 'dall-e-3',\n * prompt: 'A sunset over mountains',\n * });\n * console.log(response.images[0].url);\n *\n * // Image-to-image (with input images)\n * const response = await client.ai.images.generate({\n * model: 'stable-diffusion-xl',\n * prompt: 'Transform this into a watercolor painting',\n * images: [\n * { url: 'https://example.com/input.jpg' },\n * // or base64-encoded Data URI:\n * { url: 'data:image/jpeg;base64,/9j/4AAQ...' }\n * ]\n * });\n * ```\n */\n async generate(params: ImageGenerationRequest): Promise<any> {\n const response: ImageGenerationResponse = await this.http.post(\n \"/api/ai/image/generation\",\n params\n );\n \n // Build data array based on response content\n let data: Array<{ b64_json?: string; content?: string }> = [];\n \n if (response.images && response.images.length > 0) {\n // Has images - extract base64 and include text\n data = response.images.map(img => ({\n b64_json: img.imageUrl.replace(/^data:image\\/\\w+;base64,/, ''),\n content: response.text\n }));\n } else if (response.text) {\n // Text-only response\n data = [{ content: response.text }];\n }\n \n // Return OpenAI-compatible format\n return {\n created: Math.floor(Date.now() / 1000),\n data,\n ...(response.metadata?.usage && {\n usage: {\n total_tokens: response.metadata.usage.totalTokens || 0,\n input_tokens: response.metadata.usage.promptTokens || 0,\n output_tokens: response.metadata.usage.completionTokens || 0,\n }\n })\n };\n }\n}\n","import { InsForgeConfig } from './types';\nimport { HttpClient } from './lib/http-client';\nimport { TokenManager } from './lib/token-manager';\nimport { Auth } from './modules/auth';\nimport { Database } from './modules/database-postgrest';\nimport { Storage } from './modules/storage';\nimport { AI } from './modules/ai';\n\n/**\n * Main InsForge SDK Client\n * \n * @example\n * ```typescript\n * import { InsForgeClient } from '@insforge/sdk';\n * \n * const client = new InsForgeClient({\n * baseUrl: 'http://localhost:7130'\n * });\n * \n * // Authentication\n * const session = await client.auth.register({\n * email: 'user@example.com',\n * password: 'password123',\n * name: 'John Doe'\n * });\n * \n * // Database operations\n * const { data, error } = await client.database\n * .from('posts')\n * .select('*')\n * .eq('user_id', session.user.id)\n * .order('created_at', { ascending: false })\n * .limit(10);\n * \n * // Insert data\n * const { data: newPost } = await client.database\n * .from('posts')\n * .insert({ title: 'Hello', content: 'World' })\n * .single();\n * ```\n */\nexport class InsForgeClient {\n private http: HttpClient;\n private tokenManager: TokenManager;\n \n public readonly auth: Auth;\n public readonly database: Database;\n public readonly storage: Storage;\n public readonly ai: AI;\n\n constructor(config: InsForgeConfig = {}) {\n this.http = new HttpClient(config);\n this.tokenManager = new TokenManager(config.storage);\n \n this.auth = new Auth(\n this.http,\n this.tokenManager\n );\n \n this.database = new Database(this.http, this.tokenManager);\n this.storage = new Storage(this.http);\n this.ai = new AI(this.http);\n }\n\n /**\n * Get the underlying HTTP client for custom requests\n * \n * @example\n * ```typescript\n * const httpClient = client.getHttpClient();\n * const customData = await httpClient.get('/api/custom-endpoint');\n * ```\n */\n getHttpClient(): HttpClient {\n return this.http;\n }\n\n /**\n * Future modules will be added here:\n * - database: Database operations\n * - storage: File storage operations\n * - functions: Serverless functions\n * - tables: Table management\n * - metadata: Backend metadata\n */\n}"],"mappings":"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","names":["response"]}
package/dist/index.mjs CHANGED
@@ -508,24 +508,43 @@ var StorageBucket = class {
508
508
  }
509
509
  /**
510
510
  * Upload a file with a specific key
511
+ * Uses the upload strategy from backend (direct or presigned)
511
512
  * @param path - The object key/path
512
513
  * @param file - File or Blob to upload
513
514
  */
514
515
  async upload(path, file) {
515
516
  try {
516
- const formData = new FormData();
517
- formData.append("file", file);
518
- const response = await this.http.request(
519
- "PUT",
520
- `/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}`,
517
+ const strategyResponse = await this.http.post(
518
+ `/api/storage/buckets/${this.bucketName}/upload-strategy`,
521
519
  {
522
- body: formData,
523
- headers: {
524
- // Don't set Content-Type, let browser set multipart boundary
525
- }
520
+ filename: path,
521
+ contentType: file.type || "application/octet-stream",
522
+ size: file.size
526
523
  }
527
524
  );
528
- return { data: response, error: null };
525
+ if (strategyResponse.method === "presigned") {
526
+ return await this.uploadWithPresignedUrl(strategyResponse, file);
527
+ }
528
+ if (strategyResponse.method === "direct") {
529
+ const formData = new FormData();
530
+ formData.append("file", file);
531
+ const response = await this.http.request(
532
+ "PUT",
533
+ `/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}`,
534
+ {
535
+ body: formData,
536
+ headers: {
537
+ // Don't set Content-Type, let browser set multipart boundary
538
+ }
539
+ }
540
+ );
541
+ return { data: response, error: null };
542
+ }
543
+ throw new InsForgeError(
544
+ `Unsupported upload method: ${strategyResponse.method}`,
545
+ 500,
546
+ "STORAGE_ERROR"
547
+ );
529
548
  } catch (error) {
530
549
  return {
531
550
  data: null,
@@ -539,23 +558,43 @@ var StorageBucket = class {
539
558
  }
540
559
  /**
541
560
  * Upload a file with auto-generated key
561
+ * Uses the upload strategy from backend (direct or presigned)
542
562
  * @param file - File or Blob to upload
543
563
  */
544
564
  async uploadAuto(file) {
545
565
  try {
546
- const formData = new FormData();
547
- formData.append("file", file);
548
- const response = await this.http.request(
549
- "POST",
550
- `/api/storage/buckets/${this.bucketName}/objects`,
566
+ const filename = file instanceof File ? file.name : "file";
567
+ const strategyResponse = await this.http.post(
568
+ `/api/storage/buckets/${this.bucketName}/upload-strategy`,
551
569
  {
552
- body: formData,
553
- headers: {
554
- // Don't set Content-Type, let browser set multipart boundary
555
- }
570
+ filename,
571
+ contentType: file.type || "application/octet-stream",
572
+ size: file.size
556
573
  }
557
574
  );
558
- return { data: response, error: null };
575
+ if (strategyResponse.method === "presigned") {
576
+ return await this.uploadWithPresignedUrl(strategyResponse, file);
577
+ }
578
+ if (strategyResponse.method === "direct") {
579
+ const formData = new FormData();
580
+ formData.append("file", file);
581
+ const response = await this.http.request(
582
+ "POST",
583
+ `/api/storage/buckets/${this.bucketName}/objects`,
584
+ {
585
+ body: formData,
586
+ headers: {
587
+ // Don't set Content-Type, let browser set multipart boundary
588
+ }
589
+ }
590
+ );
591
+ return { data: response, error: null };
592
+ }
593
+ throw new InsForgeError(
594
+ `Unsupported upload method: ${strategyResponse.method}`,
595
+ 500,
596
+ "STORAGE_ERROR"
597
+ );
559
598
  } catch (error) {
560
599
  return {
561
600
  data: null,
@@ -567,17 +606,78 @@ var StorageBucket = class {
567
606
  };
568
607
  }
569
608
  }
609
+ /**
610
+ * Internal method to handle presigned URL uploads
611
+ */
612
+ async uploadWithPresignedUrl(strategy, file) {
613
+ try {
614
+ const formData = new FormData();
615
+ if (strategy.fields) {
616
+ Object.entries(strategy.fields).forEach(([key, value]) => {
617
+ formData.append(key, value);
618
+ });
619
+ }
620
+ formData.append("file", file);
621
+ const uploadResponse = await fetch(strategy.uploadUrl, {
622
+ method: "POST",
623
+ body: formData
624
+ });
625
+ if (!uploadResponse.ok) {
626
+ throw new InsForgeError(
627
+ `Upload to storage failed: ${uploadResponse.statusText}`,
628
+ uploadResponse.status,
629
+ "STORAGE_ERROR"
630
+ );
631
+ }
632
+ if (strategy.confirmRequired && strategy.confirmUrl) {
633
+ const confirmResponse = await this.http.post(
634
+ strategy.confirmUrl,
635
+ {
636
+ size: file.size,
637
+ contentType: file.type || "application/octet-stream"
638
+ }
639
+ );
640
+ return { data: confirmResponse, error: null };
641
+ }
642
+ return {
643
+ data: {
644
+ key: strategy.key,
645
+ bucket: this.bucketName,
646
+ size: file.size,
647
+ mimeType: file.type || "application/octet-stream",
648
+ uploadedAt: (/* @__PURE__ */ new Date()).toISOString(),
649
+ url: this.getPublicUrl(strategy.key)
650
+ },
651
+ error: null
652
+ };
653
+ } catch (error) {
654
+ throw error instanceof InsForgeError ? error : new InsForgeError(
655
+ "Presigned upload failed",
656
+ 500,
657
+ "STORAGE_ERROR"
658
+ );
659
+ }
660
+ }
570
661
  /**
571
662
  * Download a file
663
+ * Uses the download strategy from backend (direct or presigned)
572
664
  * @param path - The object key/path
573
665
  * Returns the file as a Blob
574
666
  */
575
667
  async download(path) {
576
668
  try {
577
- const url = `${this.http.baseUrl}/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}`;
578
- const response = await this.http.fetch(url, {
669
+ const strategyResponse = await this.http.post(
670
+ `/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}/download-strategy`,
671
+ { expiresIn: 3600 }
672
+ );
673
+ const downloadUrl = strategyResponse.url;
674
+ const headers = {};
675
+ if (strategyResponse.method === "direct") {
676
+ Object.assign(headers, this.http.getHeaders());
677
+ }
678
+ const response = await fetch(downloadUrl, {
579
679
  method: "GET",
580
- headers: this.http.getHeaders()
680
+ headers
581
681
  });
582
682
  if (!response.ok) {
583
683
  try {
@@ -868,33 +968,18 @@ var Images = class {
868
968
  "/api/ai/image/generation",
869
969
  params
870
970
  );
871
- console.log("response", response);
872
- if (!response.images || response.images.length === 0) {
873
- console.warn("No images in response:", response);
874
- return {
875
- created: Math.floor(Date.now() / 1e3),
876
- data: [],
877
- output_format: "png",
878
- ...response.metadata?.usage && {
879
- usage: {
880
- total_tokens: response.metadata.usage.totalTokens || 0,
881
- input_tokens: response.metadata.usage.promptTokens || 0,
882
- output_tokens: response.metadata.usage.completionTokens || 0
883
- }
884
- }
885
- };
971
+ let data = [];
972
+ if (response.images && response.images.length > 0) {
973
+ data = response.images.map((img) => ({
974
+ b64_json: img.imageUrl.replace(/^data:image\/\w+;base64,/, ""),
975
+ content: response.text
976
+ }));
977
+ } else if (response.text) {
978
+ data = [{ content: response.text }];
886
979
  }
887
980
  return {
888
981
  created: Math.floor(Date.now() / 1e3),
889
- data: response.images.map((img) => {
890
- const b64_json = img.imageUrl.replace(/^data:image\/\w+;base64,/, "");
891
- return {
892
- b64_json,
893
- content: response.text
894
- // this field is not in openai sdk, but is in openrouter
895
- };
896
- }),
897
- output_format: "png",
982
+ data,
898
983
  ...response.metadata?.usage && {
899
984
  usage: {
900
985
  total_tokens: response.metadata.usage.totalTokens || 0,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts","../src/lib/http-client.ts","../src/lib/token-manager.ts","../src/modules/database-postgrest.ts","../src/modules/auth.ts","../src/modules/storage.ts","../src/modules/ai.ts","../src/client.ts","../src/index.ts"],"sourcesContent":["/**\n * InsForge SDK Types - only SDK-specific types here\n * Use @insforge/shared-schemas directly for API types\n */\n\nimport type { UserSchema } from '@insforge/shared-schemas';\n\nexport interface InsForgeConfig {\n /**\n * The base URL of the InsForge backend API\n * @default \"http://localhost:7130\"\n */\n baseUrl?: string;\n\n /**\n * Anonymous API key (optional)\n * Used for public/unauthenticated requests when no user token is set\n */\n anonKey?: string;\n\n /**\n * Custom fetch implementation (useful for Node.js environments)\n */\n fetch?: typeof fetch;\n\n /**\n * Storage adapter for persisting tokens\n */\n storage?: TokenStorage;\n\n /**\n * Whether to automatically refresh tokens before they expire\n * @default true\n */\n autoRefreshToken?: boolean;\n\n /**\n * Whether to persist session in storage\n * @default true\n */\n persistSession?: boolean;\n\n /**\n * Custom headers to include with every request\n */\n headers?: Record<string, string>;\n}\n\nexport interface TokenStorage {\n getItem(key: string): string | null | Promise<string | null>;\n setItem(key: string, value: string): void | Promise<void>;\n removeItem(key: string): void | Promise<void>;\n}\n\nexport interface AuthSession {\n user: UserSchema;\n accessToken: string;\n expiresAt?: Date;\n}\n\nexport interface ApiError {\n error: string;\n message: string;\n statusCode: number;\n nextActions?: string;\n}\n\nexport class InsForgeError extends Error {\n public statusCode: number;\n public error: string;\n public nextActions?: string;\n\n constructor(message: string, statusCode: number, error: string, nextActions?: string) {\n super(message);\n this.name = 'InsForgeError';\n this.statusCode = statusCode;\n this.error = error;\n this.nextActions = nextActions;\n }\n\n static fromApiError(apiError: ApiError): InsForgeError {\n return new InsForgeError(\n apiError.message,\n apiError.statusCode,\n apiError.error,\n apiError.nextActions\n );\n }\n}","import { InsForgeConfig, ApiError, InsForgeError } from '../types';\n\nexport interface RequestOptions extends RequestInit {\n params?: Record<string, string>;\n}\n\nexport class HttpClient {\n public readonly baseUrl: string;\n public readonly fetch: typeof fetch;\n private defaultHeaders: Record<string, string>;\n private anonKey: string | undefined;\n private userToken: string | null = null;\n\n constructor(config: InsForgeConfig) {\n this.baseUrl = config.baseUrl || 'http://localhost:7130';\n // Properly bind fetch to maintain its context\n this.fetch = config.fetch || (globalThis.fetch ? globalThis.fetch.bind(globalThis) : undefined as any);\n this.anonKey = config.anonKey;\n this.defaultHeaders = {\n ...config.headers,\n };\n\n if (!this.fetch) {\n throw new Error(\n 'Fetch is not available. Please provide a fetch implementation in the config.'\n );\n }\n }\n\n private buildUrl(path: string, params?: Record<string, string>): string {\n const url = new URL(path, this.baseUrl);\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n // For select parameter, preserve the exact formatting by normalizing whitespace\n // This ensures PostgREST relationship queries work correctly\n if (key === 'select') {\n // Normalize multiline select strings for PostgREST:\n // 1. Replace all whitespace (including newlines) with single space\n // 2. Remove spaces inside parentheses for proper PostgREST syntax\n // 3. Keep spaces after commas at the top level for readability\n let normalizedValue = value.replace(/\\s+/g, ' ').trim();\n \n // Fix spaces around parentheses and inside them\n normalizedValue = normalizedValue\n .replace(/\\s*\\(\\s*/g, '(') // Remove spaces around opening parens\n .replace(/\\s*\\)\\s*/g, ')') // Remove spaces around closing parens\n .replace(/\\(\\s+/g, '(') // Remove spaces after opening parens\n .replace(/\\s+\\)/g, ')') // Remove spaces before closing parens\n .replace(/,\\s+(?=[^()]*\\))/g, ','); // Remove spaces after commas inside parens\n \n url.searchParams.append(key, normalizedValue);\n } else {\n url.searchParams.append(key, value);\n }\n });\n }\n return url.toString();\n }\n\n async request<T>(\n method: string,\n path: string,\n options: RequestOptions = {}\n ): Promise<T> {\n const { params, headers = {}, body, ...fetchOptions } = options;\n \n const url = this.buildUrl(path, params);\n \n const requestHeaders: Record<string, string> = {\n ...this.defaultHeaders,\n };\n \n // Set Authorization header: prefer user token, fallback to anon key\n const authToken = this.userToken || this.anonKey;\n if (authToken) {\n requestHeaders['Authorization'] = `Bearer ${authToken}`;\n }\n \n // Handle body serialization\n let processedBody: any;\n if (body !== undefined) {\n // Check if body is FormData (for file uploads)\n if (typeof FormData !== 'undefined' && body instanceof FormData) {\n // Don't set Content-Type for FormData, let browser set it with boundary\n processedBody = body;\n } else {\n // JSON body\n if (method !== 'GET') {\n requestHeaders['Content-Type'] = 'application/json;charset=UTF-8';\n }\n processedBody = JSON.stringify(body);\n }\n }\n \n Object.assign(requestHeaders, headers);\n \n const response = await this.fetch(url, {\n method,\n headers: requestHeaders,\n body: processedBody,\n ...fetchOptions,\n });\n\n // Handle 204 No Content\n if (response.status === 204) {\n return undefined as T;\n }\n\n // Try to parse JSON response\n let data: any;\n const contentType = response.headers.get('content-type');\n // Check for any JSON content type (including PostgREST's vnd.pgrst.object+json)\n if (contentType?.includes('json')) {\n data = await response.json();\n } else {\n // For non-JSON responses, return text\n data = await response.text();\n }\n\n // Handle errors\n if (!response.ok) {\n if (data && typeof data === 'object' && 'error' in data) {\n throw InsForgeError.fromApiError(data as ApiError);\n }\n throw new InsForgeError(\n `Request failed: ${response.statusText}`,\n response.status,\n 'REQUEST_FAILED'\n );\n }\n\n return data as T;\n }\n\n get<T>(path: string, options?: RequestOptions): Promise<T> {\n return this.request<T>('GET', path, options);\n }\n\n post<T>(path: string, body?: any, options?: RequestOptions): Promise<T> {\n return this.request<T>('POST', path, { ...options, body });\n }\n\n put<T>(path: string, body?: any, options?: RequestOptions): Promise<T> {\n return this.request<T>('PUT', path, { ...options, body });\n }\n\n patch<T>(path: string, body?: any, options?: RequestOptions): Promise<T> {\n return this.request<T>('PATCH', path, { ...options, body });\n }\n\n delete<T>(path: string, options?: RequestOptions): Promise<T> {\n return this.request<T>('DELETE', path, options);\n }\n\n setAuthToken(token: string | null) {\n this.userToken = token;\n }\n\n getHeaders(): Record<string, string> {\n return { ...this.defaultHeaders };\n }\n}","import { TokenStorage, AuthSession } from '../types';\n\nconst TOKEN_KEY = 'insforge-auth-token';\nconst USER_KEY = 'insforge-auth-user';\n\nexport class TokenManager {\n private storage: TokenStorage;\n\n constructor(storage?: TokenStorage) {\n if (storage) {\n // Use provided storage\n this.storage = storage;\n } else if (typeof window !== 'undefined' && window.localStorage) {\n // Browser: use localStorage\n this.storage = window.localStorage;\n } else {\n // Node.js: use in-memory storage\n const store = new Map<string, string>();\n this.storage = {\n getItem: (key: string) => store.get(key) || null,\n setItem: (key: string, value: string) => { store.set(key, value); },\n removeItem: (key: string) => { store.delete(key); }\n };\n }\n }\n\n saveSession(session: AuthSession): void {\n this.storage.setItem(TOKEN_KEY, session.accessToken);\n this.storage.setItem(USER_KEY, JSON.stringify(session.user));\n }\n\n getSession(): AuthSession | null {\n const token = this.storage.getItem(TOKEN_KEY);\n const userStr = this.storage.getItem(USER_KEY);\n\n if (!token || !userStr) {\n return null;\n }\n\n try {\n const user = JSON.parse(userStr as string);\n return { accessToken: token as string, user };\n } catch {\n this.clearSession();\n return null;\n }\n }\n\n getAccessToken(): string | null {\n const token = this.storage.getItem(TOKEN_KEY);\n return typeof token === 'string' ? token : null;\n }\n\n clearSession(): void {\n this.storage.removeItem(TOKEN_KEY);\n this.storage.removeItem(USER_KEY);\n }\n}","/**\n * Database module using @supabase/postgrest-js\n * Complete replacement for custom QueryBuilder with full PostgREST features\n */\n\nimport { PostgrestClient } from '@supabase/postgrest-js';\nimport { HttpClient } from '../lib/http-client';\nimport { TokenManager } from '../lib/token-manager';\n\n\n/**\n * Custom fetch that transforms URLs and adds auth\n */\nfunction createInsForgePostgrestFetch(\n httpClient: HttpClient,\n tokenManager: TokenManager\n): typeof fetch {\n return async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const url = typeof input === 'string' ? input : input.toString();\n const urlObj = new URL(url);\n \n // Extract table name from pathname\n // postgrest-js sends: http://dummy/tablename?params\n // We need: http://localhost:7130/api/database/records/tablename?params\n const tableName = urlObj.pathname.slice(1); // Remove leading /\n \n // Build InsForge URL\n const insforgeUrl = `${httpClient.baseUrl}/api/database/records/${tableName}${urlObj.search}`;\n \n // Get auth token from TokenManager\n const token = tokenManager.getAccessToken();\n \n // Prepare headers\n const headers = new Headers(init?.headers);\n if (token && !headers.has('Authorization')) {\n headers.set('Authorization', `Bearer ${token}`);\n }\n \n // Make the actual request using native fetch\n // This returns a proper Response object with headers\n const response = await fetch(insforgeUrl, {\n ...init,\n headers\n });\n \n return response;\n };\n}\n\n/**\n * Database client using postgrest-js\n * Drop-in replacement with FULL PostgREST capabilities\n */\nexport class Database {\n private postgrest: PostgrestClient<any, any, any>;\n \n constructor(httpClient: HttpClient, tokenManager: TokenManager) {\n // Create postgrest client with custom fetch\n this.postgrest = new PostgrestClient<any, any, any>('http://dummy', {\n fetch: createInsForgePostgrestFetch(httpClient, tokenManager),\n headers: {}\n });\n }\n \n /**\n * Create a query builder for a table\n * \n * @example\n * // Basic query\n * const { data, error } = await client.database\n * .from('posts')\n * .select('*')\n * .eq('user_id', userId);\n * \n * // With count (Supabase style!)\n * const { data, error, count } = await client.database\n * .from('posts')\n * .select('*', { count: 'exact' })\n * .range(0, 9);\n * \n * // Just get count, no data\n * const { count } = await client.database\n * .from('posts')\n * .select('*', { count: 'exact', head: true });\n * \n * // Complex queries with OR\n * const { data } = await client.database\n * .from('posts')\n * .select('*, users!inner(*)')\n * .or('status.eq.active,status.eq.pending');\n * \n * // All features work:\n * - Nested selects\n * - Foreign key expansion \n * - OR/AND/NOT conditions\n * - Count with head\n * - Range pagination\n * - Upserts\n */\n from(table: string) {\n // Return postgrest query builder with all features\n return this.postgrest.from(table);\n }\n}","/**\n * Auth module for InsForge SDK\n * Uses shared schemas for type safety\n */\n\nimport { HttpClient } from '../lib/http-client';\nimport { TokenManager } from '../lib/token-manager';\nimport { AuthSession, InsForgeError } from '../types';\nimport { Database } from './database-postgrest';\n\nimport type {\n CreateUserRequest,\n CreateUserResponse,\n CreateSessionRequest,\n CreateSessionResponse,\n GetCurrentSessionResponse,\n GetOauthUrlResponse,\n} from '@insforge/shared-schemas';\n\nexport class Auth {\n private database: Database;\n \n constructor(\n private http: HttpClient,\n private tokenManager: TokenManager\n ) {\n this.database = new Database(http, tokenManager);\n \n // Auto-detect OAuth callback parameters in the URL\n this.detectOAuthCallback();\n }\n\n /**\n * Automatically detect and handle OAuth callback parameters in the URL\n * This runs on initialization to seamlessly complete the OAuth flow\n * Matches the backend's OAuth callback response (backend/src/api/routes/auth.ts:540-544)\n */\n private detectOAuthCallback(): void {\n // Only run in browser environment\n if (typeof window === 'undefined') return;\n \n try {\n const params = new URLSearchParams(window.location.search);\n \n // Backend returns: access_token, user_id, email, name (optional)\n const accessToken = params.get('access_token');\n const userId = params.get('user_id');\n const email = params.get('email');\n const name = params.get('name');\n \n // Check if we have OAuth callback parameters\n if (accessToken && userId && email) {\n // Create session with the data from backend\n const session: AuthSession = {\n accessToken,\n user: {\n id: userId,\n email: email,\n name: name || '',\n // These fields are not provided by backend OAuth callback\n // They'll be populated when calling getCurrentUser()\n emailVerified: false,\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n } as any,\n };\n \n // Save session and set auth token\n this.tokenManager.saveSession(session);\n this.http.setAuthToken(accessToken);\n \n // Clean up the URL to remove sensitive parameters\n const url = new URL(window.location.href);\n url.searchParams.delete('access_token');\n url.searchParams.delete('user_id');\n url.searchParams.delete('email');\n url.searchParams.delete('name');\n \n // Also handle error case from backend (line 581)\n if (params.has('error')) {\n url.searchParams.delete('error');\n }\n \n // Replace URL without adding to browser history\n window.history.replaceState({}, document.title, url.toString());\n }\n } catch (error) {\n // Silently continue - don't break initialization\n console.debug('OAuth callback detection skipped:', error);\n }\n }\n\n /**\n * Sign up a new user\n */\n async signUp(request: CreateUserRequest): Promise<{\n data: CreateUserResponse | null;\n error: InsForgeError | null;\n }> {\n try {\n const response = await this.http.post<CreateUserResponse>('/api/auth/users', request);\n \n // Save session internally\n const session: AuthSession = {\n accessToken: response.accessToken,\n user: response.user,\n };\n this.tokenManager.saveSession(session);\n this.http.setAuthToken(response.accessToken);\n\n return { \n data: response,\n error: null \n };\n } catch (error) {\n // Pass through API errors unchanged\n if (error instanceof InsForgeError) {\n return { data: null, error };\n }\n \n // Generic fallback for unexpected errors\n return { \n data: null, \n error: new InsForgeError(\n error instanceof Error ? error.message : 'An unexpected error occurred during sign up',\n 500,\n 'UNEXPECTED_ERROR'\n )\n };\n }\n }\n\n /**\n * Sign in with email and password\n */\n async signInWithPassword(request: CreateSessionRequest): Promise<{\n data: CreateSessionResponse | null;\n error: InsForgeError | null;\n }> {\n try {\n const response = await this.http.post<CreateSessionResponse>('/api/auth/sessions', request);\n \n // Save session internally\n const session: AuthSession = {\n accessToken: response.accessToken,\n user: response.user,\n };\n this.tokenManager.saveSession(session);\n this.http.setAuthToken(response.accessToken);\n\n return { \n data: response,\n error: null \n };\n } catch (error) {\n // Pass through API errors unchanged\n if (error instanceof InsForgeError) {\n return { data: null, error };\n }\n \n // Generic fallback for unexpected errors\n return { \n data: null, \n error: new InsForgeError(\n 'An unexpected error occurred during sign in',\n 500,\n 'UNEXPECTED_ERROR'\n )\n };\n }\n }\n\n /**\n * Sign in with OAuth provider\n */\n async signInWithOAuth(options: {\n provider: 'google' | 'github';\n redirectTo?: string;\n skipBrowserRedirect?: boolean;\n }): Promise<{\n data: { url?: string; provider?: string };\n error: InsForgeError | null;\n }> {\n try {\n const { provider, redirectTo, skipBrowserRedirect } = options;\n \n const params = redirectTo \n ? { redirect_uri: redirectTo } \n : undefined;\n \n const endpoint = `/api/auth/oauth/${provider}`;\n const response = await this.http.get<GetOauthUrlResponse>(endpoint, { params });\n \n // Automatically redirect in browser unless told not to\n if (typeof window !== 'undefined' && !skipBrowserRedirect) {\n window.location.href = response.authUrl;\n return { data: {}, error: null };\n }\n\n return { \n data: { \n url: response.authUrl,\n provider \n }, \n error: null \n };\n } catch (error) {\n // Pass through API errors unchanged\n if (error instanceof InsForgeError) {\n return { data: {}, error };\n }\n \n // Generic fallback for unexpected errors\n return { \n data: {}, \n error: new InsForgeError(\n 'An unexpected error occurred during OAuth initialization',\n 500,\n 'UNEXPECTED_ERROR'\n )\n };\n }\n }\n\n /**\n * Sign out the current user\n */\n async signOut(): Promise<{ error: InsForgeError | null }> {\n try {\n this.tokenManager.clearSession();\n this.http.setAuthToken(null);\n return { error: null };\n } catch (error) {\n return { \n error: new InsForgeError(\n 'Failed to sign out',\n 500,\n 'SIGNOUT_ERROR'\n )\n };\n }\n }\n\n /**\n * Get the current user with full profile information\n * Returns both auth info (id, email, role) and profile data (nickname, avatar_url, bio, etc.)\n */\n async getCurrentUser(): Promise<{\n data: { user: any; profile: any } | null;\n error: any | null;\n }> {\n try {\n // Check if we have a token\n const session = this.tokenManager.getSession();\n if (!session?.accessToken) {\n return { data: null, error: null };\n }\n\n // Call the API for auth info\n this.http.setAuthToken(session.accessToken);\n const authResponse = await this.http.get<GetCurrentSessionResponse>('/api/auth/sessions/current');\n \n // Get the user's profile using query builder\n const { data: profile, error: profileError } = await this.database\n .from('users')\n .select('*')\n .eq('id', authResponse.user.id)\n .single();\n \n // For database errors, return PostgrestError directly\n if (profileError && (profileError as any).code !== 'PGRST116') { // PGRST116 = not found\n return { data: null, error: profileError };\n }\n \n return {\n data: {\n user: authResponse.user,\n profile: profile\n },\n error: null\n };\n } catch (error) {\n // If unauthorized, clear session\n if (error instanceof InsForgeError && error.statusCode === 401) {\n await this.signOut();\n return { data: null, error: null };\n }\n \n // Pass through all other errors unchanged\n if (error instanceof InsForgeError) {\n return { data: null, error };\n }\n \n // Generic fallback for unexpected errors\n return { \n data: null, \n error: new InsForgeError(\n 'An unexpected error occurred while fetching user',\n 500,\n 'UNEXPECTED_ERROR'\n )\n };\n }\n }\n\n /**\n * Get any user's profile by ID\n * Returns profile information from the users table (nickname, avatar_url, bio, etc.)\n */\n async getProfile(userId: string): Promise<{\n data: any | null;\n error: any | null;\n }> {\n const { data, error } = await this.database\n .from('users')\n .select('*')\n .eq('id', userId)\n .single();\n \n // Handle not found as null, not error\n if (error && (error as any).code === 'PGRST116') {\n return { data: null, error: null };\n }\n \n // Return PostgrestError directly for database operations\n return { data, error };\n }\n\n /**\n * Get the current session (only session data, no API call)\n * Returns the stored JWT token and basic user info from local storage\n */\n getCurrentSession(): {\n data: { session: AuthSession | null };\n error: InsForgeError | null;\n } {\n try {\n const session = this.tokenManager.getSession();\n \n if (session?.accessToken) {\n this.http.setAuthToken(session.accessToken);\n return { data: { session }, error: null };\n }\n\n return { data: { session: null }, error: null };\n } catch (error) {\n // Pass through API errors unchanged\n if (error instanceof InsForgeError) {\n return { data: { session: null }, error };\n }\n \n // Generic fallback for unexpected errors\n return { \n data: { session: null }, \n error: new InsForgeError(\n 'An unexpected error occurred while getting session',\n 500,\n 'UNEXPECTED_ERROR'\n )\n };\n }\n }\n\n /**\n * Set/Update the current user's profile\n * Updates profile information in the users table (nickname, avatar_url, bio, etc.)\n */\n async setProfile(profile: {\n nickname?: string;\n avatar_url?: string;\n bio?: string;\n birthday?: string;\n [key: string]: any;\n }): Promise<{\n data: any | null;\n error: any | null;\n }> {\n // Get current session to get user ID\n const session = this.tokenManager.getSession();\n if (!session?.user?.id) {\n return { \n data: null, \n error: new InsForgeError(\n 'No authenticated user found',\n 401,\n 'UNAUTHENTICATED'\n )\n };\n }\n\n // Update the profile using query builder\n const { data, error } = await this.database\n .from('users')\n .update(profile)\n .eq('id', session.user.id)\n .select()\n .single();\n \n // Return PostgrestError directly for database operations\n return { data, error };\n }\n\n\n}","/**\n * Storage module for InsForge SDK\n * Handles file uploads, downloads, and bucket management\n */\n\nimport { HttpClient } from '../lib/http-client';\nimport { InsForgeError } from '../types';\nimport type { \n StorageFileSchema,\n ListObjectsResponseSchema\n} from '@insforge/shared-schemas';\n\nexport interface StorageResponse<T> {\n data: T | null;\n error: InsForgeError | null;\n}\n\n/**\n * Storage bucket operations\n */\nexport class StorageBucket {\n constructor(\n private bucketName: string,\n private http: HttpClient\n ) {}\n\n /**\n * Upload a file with a specific key\n * @param path - The object key/path\n * @param file - File or Blob to upload\n */\n async upload(\n path: string,\n file: File | Blob\n ): Promise<StorageResponse<StorageFileSchema>> {\n try {\n const formData = new FormData();\n formData.append('file', file);\n\n // Use PUT for specific path\n const response = await this.http.request<StorageFileSchema>(\n 'PUT',\n `/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}`,\n {\n body: formData as any,\n headers: {\n // Don't set Content-Type, let browser set multipart boundary\n }\n }\n );\n\n return { data: response, error: null };\n } catch (error) {\n return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'Upload failed',\n 500,\n 'STORAGE_ERROR'\n )\n };\n }\n }\n\n /**\n * Upload a file with auto-generated key\n * @param file - File or Blob to upload\n */\n async uploadAuto(\n file: File | Blob\n ): Promise<StorageResponse<StorageFileSchema>> {\n try {\n const formData = new FormData();\n formData.append('file', file);\n\n // Use POST for auto-generated key\n const response = await this.http.request<StorageFileSchema>(\n 'POST',\n `/api/storage/buckets/${this.bucketName}/objects`,\n {\n body: formData as any,\n headers: {\n // Don't set Content-Type, let browser set multipart boundary\n }\n }\n );\n\n return { data: response, error: null };\n } catch (error) {\n return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'Upload failed',\n 500,\n 'STORAGE_ERROR'\n )\n };\n }\n }\n\n /**\n * Download a file\n * @param path - The object key/path\n * Returns the file as a Blob\n */\n async download(path: string): Promise<{ data: Blob | null; error: InsForgeError | null }> {\n try {\n // For binary data, we need to use fetch directly with proper response handling\n // The http.request method expects JSON responses, so we can't use it for blobs\n const url = `${this.http.baseUrl}/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}`;\n \n const response = await this.http.fetch(url, {\n method: 'GET',\n headers: this.http.getHeaders()\n });\n\n if (!response.ok) {\n try {\n const error = await response.json();\n throw InsForgeError.fromApiError(error);\n } catch {\n throw new InsForgeError(\n `Download failed: ${response.statusText}`,\n response.status,\n 'STORAGE_ERROR'\n );\n }\n }\n\n const blob = await response.blob();\n return { data: blob, error: null };\n } catch (error) {\n return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'Download failed',\n 500,\n 'STORAGE_ERROR'\n )\n };\n }\n }\n\n /**\n * Get public URL for a file\n * @param path - The object key/path\n */\n getPublicUrl(path: string): string {\n return `${this.http.baseUrl}/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}`;\n }\n\n /**\n * List objects in the bucket\n * @param prefix - Filter by key prefix\n * @param search - Search in file names\n * @param limit - Maximum number of results (default: 100, max: 1000)\n * @param offset - Number of results to skip\n */\n async list(options?: {\n prefix?: string;\n search?: string;\n limit?: number;\n offset?: number;\n }): Promise<StorageResponse<ListObjectsResponseSchema>> {\n try {\n const params: Record<string, string> = {};\n \n if (options?.prefix) params.prefix = options.prefix;\n if (options?.search) params.search = options.search;\n if (options?.limit) params.limit = options.limit.toString();\n if (options?.offset) params.offset = options.offset.toString();\n\n const response = await this.http.get<ListObjectsResponseSchema>(\n `/api/storage/buckets/${this.bucketName}/objects`,\n { params }\n );\n\n return { data: response, error: null };\n } catch (error) {\n return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'List failed',\n 500,\n 'STORAGE_ERROR'\n )\n };\n }\n }\n\n /**\n * Delete a file\n * @param path - The object key/path\n */\n async remove(path: string): Promise<StorageResponse<{ message: string }>> {\n try {\n const response = await this.http.delete<{ message: string }>(\n `/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}`\n );\n\n return { data: response, error: null };\n } catch (error) {\n return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'Delete failed',\n 500,\n 'STORAGE_ERROR'\n )\n };\n }\n }\n}\n\n/**\n * Storage module for file operations\n */\nexport class Storage {\n constructor(private http: HttpClient) {}\n\n /**\n * Get a bucket instance for operations\n * @param bucketName - Name of the bucket\n */\n from(bucketName: string): StorageBucket {\n return new StorageBucket(bucketName, this.http);\n }\n}","/**\n * AI Module for Insforge SDK\n * Response format roughly matches OpenAI SDK for compatibility\n *\n * The backend handles all the complexity of different AI providers\n * and returns a unified format. This SDK transforms responses to match OpenAI-like format.\n */\n\nimport { HttpClient } from \"../lib/http-client\";\nimport {\n ChatCompletionRequest,\n ChatCompletionResponse,\n ImageGenerationRequest,\n ImageGenerationResponse,\n} from \"@insforge/shared-schemas\";\n\nexport class AI {\n public readonly chat: Chat;\n public readonly images: Images;\n\n constructor(private http: HttpClient) {\n this.chat = new Chat(http);\n this.images = new Images(http);\n }\n}\n\nclass Chat {\n public readonly completions: ChatCompletions;\n\n constructor(http: HttpClient) {\n this.completions = new ChatCompletions(http);\n }\n}\n\nclass ChatCompletions {\n constructor(private http: HttpClient) {}\n\n /**\n * Create a chat completion - OpenAI-like response format\n *\n * @example\n * ```typescript\n * // Non-streaming\n * const completion = await client.ai.chat.completions.create({\n * model: 'gpt-4',\n * messages: [{ role: 'user', content: 'Hello!' }]\n * });\n * console.log(completion.choices[0].message.content);\n *\n * // With images\n * const response = await client.ai.chat.completions.create({\n * model: 'gpt-4-vision',\n * messages: [{\n * role: 'user',\n * content: 'What is in this image?',\n * images: [{ url: 'https://example.com/image.jpg' }]\n * }]\n * });\n *\n * // Streaming - returns async iterable\n * const stream = await client.ai.chat.completions.create({\n * model: 'gpt-4',\n * messages: [{ role: 'user', content: 'Tell me a story' }],\n * stream: true\n * });\n *\n * for await (const chunk of stream) {\n * if (chunk.choices[0]?.delta?.content) {\n * process.stdout.write(chunk.choices[0].delta.content);\n * }\n * }\n * ```\n */\n async create(params: ChatCompletionRequest): Promise<any> {\n // Backend already expects camelCase, no transformation needed\n const backendParams = {\n model: params.model,\n messages: params.messages,\n temperature: params.temperature,\n maxTokens: params.maxTokens,\n topP: params.topP,\n stream: params.stream,\n };\n\n // For streaming, return an async iterable that yields OpenAI-like chunks\n if (params.stream) {\n const headers = this.http.getHeaders();\n headers[\"Content-Type\"] = \"application/json\";\n\n const response = await this.http.fetch(\n `${this.http.baseUrl}/api/ai/chat/completion`,\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(backendParams),\n }\n );\n\n if (!response.ok) {\n const error = await response.json();\n throw new Error(error.error || \"Stream request failed\");\n }\n\n // Return async iterable that parses SSE and transforms to OpenAI-like format\n return this.parseSSEStream(response, params.model);\n }\n\n // Non-streaming: transform response to OpenAI-like format\n const response: ChatCompletionResponse = await this.http.post(\n \"/api/ai/chat/completion\",\n backendParams\n );\n\n // Transform to OpenAI-like format\n const content = response.text || \"\";\n\n return {\n id: `chatcmpl-${Date.now()}`,\n object: \"chat.completion\",\n created: Math.floor(Date.now() / 1000),\n model: response.metadata?.model,\n choices: [\n {\n index: 0,\n message: {\n role: \"assistant\",\n content,\n },\n finish_reason: \"stop\",\n },\n ],\n usage: response.metadata?.usage || {\n prompt_tokens: 0,\n completion_tokens: 0,\n total_tokens: 0,\n },\n };\n }\n\n /**\n * Parse SSE stream into async iterable of OpenAI-like chunks\n */\n private async *parseSSEStream(\n response: Response,\n model: string\n ): AsyncIterableIterator<any> {\n const reader = response.body!.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() || \"\";\n\n for (const line of lines) {\n if (line.startsWith(\"data: \")) {\n const dataStr = line.slice(6).trim();\n if (dataStr) {\n try {\n const data = JSON.parse(dataStr);\n\n // Transform to OpenAI-like streaming format\n if (data.chunk || data.content) {\n yield {\n id: `chatcmpl-${Date.now()}`,\n object: \"chat.completion.chunk\",\n created: Math.floor(Date.now() / 1000),\n model,\n choices: [\n {\n index: 0,\n delta: {\n content: data.chunk || data.content,\n },\n finish_reason: data.done ? \"stop\" : null,\n },\n ],\n };\n }\n\n // If we received the done signal, we can stop\n if (data.done) {\n reader.releaseLock();\n return;\n }\n } catch (e) {\n // Skip invalid JSON\n console.warn(\"Failed to parse SSE data:\", dataStr);\n }\n }\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n}\n\nclass Images {\n constructor(private http: HttpClient) {}\n\n /**\n * Generate images - OpenAI-like response format\n *\n * @example\n * ```typescript\n * // Text-to-image\n * const response = await client.ai.images.generate({\n * model: 'dall-e-3',\n * prompt: 'A sunset over mountains',\n * });\n * console.log(response.images[0].url);\n *\n * // Image-to-image (with input images)\n * const response = await client.ai.images.generate({\n * model: 'stable-diffusion-xl',\n * prompt: 'Transform this into a watercolor painting',\n * images: [\n * { url: 'https://example.com/input.jpg' },\n * // or base64-encoded Data URI:\n * { url: 'data:image/jpeg;base64,/9j/4AAQ...' }\n * ]\n * });\n * ```\n */\n async generate(params: ImageGenerationRequest): Promise<any> {\n const response: ImageGenerationResponse = await this.http.post(\n \"/api/ai/image/generation\",\n params\n );\n console.log('response', response);\n // Check if response has images array, handle gracefully if empty/missing\n if (!response.images || response.images.length === 0) {\n console.warn('No images in response:', response);\n return {\n created: Math.floor(Date.now() / 1000),\n data: [],\n output_format: \"png\",\n ...(response.metadata?.usage && {\n usage: {\n total_tokens: response.metadata.usage.totalTokens || 0,\n input_tokens: response.metadata.usage.promptTokens || 0,\n output_tokens: response.metadata.usage.completionTokens || 0,\n }\n })\n };\n }\n\n // Transform to OpenAI SDK format with b64_json\n return {\n created: Math.floor(Date.now() / 1000),\n data: response.images.map(img => {\n // OpenRouter returns data URLs (data:image/png;base64,...)\n // Extract the base64 portion for OpenAI compatibility\n const b64_json = img.imageUrl.replace(/^data:image\\/\\w+;base64,/, '');\n \n return {\n b64_json: b64_json,\n content: response.text, // this field is not in openai sdk, but is in openrouter\n };\n }),\n output_format: \"png\",\n ...(response.metadata?.usage && {\n usage: {\n total_tokens: response.metadata.usage.totalTokens || 0,\n input_tokens: response.metadata.usage.promptTokens || 0,\n output_tokens: response.metadata.usage.completionTokens || 0,\n }\n })\n };\n }\n}\n","import { InsForgeConfig } from './types';\nimport { HttpClient } from './lib/http-client';\nimport { TokenManager } from './lib/token-manager';\nimport { Auth } from './modules/auth';\nimport { Database } from './modules/database-postgrest';\nimport { Storage } from './modules/storage';\nimport { AI } from './modules/ai';\n\n/**\n * Main InsForge SDK Client\n * \n * @example\n * ```typescript\n * import { InsForgeClient } from '@insforge/sdk';\n * \n * const client = new InsForgeClient({\n * baseUrl: 'http://localhost:7130'\n * });\n * \n * // Authentication\n * const session = await client.auth.register({\n * email: 'user@example.com',\n * password: 'password123',\n * name: 'John Doe'\n * });\n * \n * // Database operations\n * const { data, error } = await client.database\n * .from('posts')\n * .select('*')\n * .eq('user_id', session.user.id)\n * .order('created_at', { ascending: false })\n * .limit(10);\n * \n * // Insert data\n * const { data: newPost } = await client.database\n * .from('posts')\n * .insert({ title: 'Hello', content: 'World' })\n * .single();\n * ```\n */\nexport class InsForgeClient {\n private http: HttpClient;\n private tokenManager: TokenManager;\n \n public readonly auth: Auth;\n public readonly database: Database;\n public readonly storage: Storage;\n public readonly ai: AI;\n\n constructor(config: InsForgeConfig = {}) {\n this.http = new HttpClient(config);\n this.tokenManager = new TokenManager(config.storage);\n \n this.auth = new Auth(\n this.http,\n this.tokenManager\n );\n \n this.database = new Database(this.http, this.tokenManager);\n this.storage = new Storage(this.http);\n this.ai = new AI(this.http);\n }\n\n /**\n * Get the underlying HTTP client for custom requests\n * \n * @example\n * ```typescript\n * const httpClient = client.getHttpClient();\n * const customData = await httpClient.get('/api/custom-endpoint');\n * ```\n */\n getHttpClient(): HttpClient {\n return this.http;\n }\n\n /**\n * Future modules will be added here:\n * - database: Database operations\n * - storage: File storage operations\n * - functions: Serverless functions\n * - tables: Table management\n * - metadata: Backend metadata\n */\n}","/**\n * @insforge/sdk - TypeScript SDK for InsForge Backend-as-a-Service\n * \n * @packageDocumentation\n */\n\n// Main client\nexport { InsForgeClient } from './client';\n\n// Types\nexport type {\n InsForgeConfig,\n InsForgeConfig as ClientOptions, // Alias for compatibility\n TokenStorage,\n AuthSession,\n ApiError,\n} from './types';\n\nexport { InsForgeError } from './types';\n\n// Re-export shared schemas that SDK users will need\nexport type {\n UserSchema,\n CreateUserRequest,\n CreateSessionRequest,\n AuthErrorResponse,\n} from '@insforge/shared-schemas';\n\n// Re-export auth module for advanced usage\nexport { Auth } from './modules/auth';\n\n// Re-export database module (using postgrest-js)\nexport { Database } from './modules/database-postgrest';\n// Note: QueryBuilder is no longer exported as we use postgrest-js QueryBuilder internally\n\n// Re-export storage module and types\nexport { Storage, StorageBucket } from './modules/storage';\nexport type { StorageResponse } from './modules/storage';\n\n// Re-export AI module\nexport { AI } from './modules/ai';\n\n// Re-export utilities for advanced usage\nexport { HttpClient } from './lib/http-client';\nexport { TokenManager } from './lib/token-manager';\n\n// Factory function for creating clients (Supabase-style)\nimport { InsForgeClient } from './client';\nimport { InsForgeConfig } from './types';\n\nexport function createClient(config: InsForgeConfig): InsForgeClient {\n return new InsForgeClient(config);\n}\n\n// Default export for convenience\nexport default InsForgeClient;"],"mappings":"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","names":["response"]}
1
+ {"version":3,"sources":["../src/types.ts","../src/lib/http-client.ts","../src/lib/token-manager.ts","../src/modules/database-postgrest.ts","../src/modules/auth.ts","../src/modules/storage.ts","../src/modules/ai.ts","../src/client.ts","../src/index.ts"],"sourcesContent":["/**\n * InsForge SDK Types - only SDK-specific types here\n * Use @insforge/shared-schemas directly for API types\n */\n\nimport type { UserSchema } from '@insforge/shared-schemas';\n\nexport interface InsForgeConfig {\n /**\n * The base URL of the InsForge backend API\n * @default \"http://localhost:7130\"\n */\n baseUrl?: string;\n\n /**\n * Anonymous API key (optional)\n * Used for public/unauthenticated requests when no user token is set\n */\n anonKey?: string;\n\n /**\n * Custom fetch implementation (useful for Node.js environments)\n */\n fetch?: typeof fetch;\n\n /**\n * Storage adapter for persisting tokens\n */\n storage?: TokenStorage;\n\n /**\n * Whether to automatically refresh tokens before they expire\n * @default true\n */\n autoRefreshToken?: boolean;\n\n /**\n * Whether to persist session in storage\n * @default true\n */\n persistSession?: boolean;\n\n /**\n * Custom headers to include with every request\n */\n headers?: Record<string, string>;\n}\n\nexport interface TokenStorage {\n getItem(key: string): string | null | Promise<string | null>;\n setItem(key: string, value: string): void | Promise<void>;\n removeItem(key: string): void | Promise<void>;\n}\n\nexport interface AuthSession {\n user: UserSchema;\n accessToken: string;\n expiresAt?: Date;\n}\n\nexport interface ApiError {\n error: string;\n message: string;\n statusCode: number;\n nextActions?: string;\n}\n\nexport class InsForgeError extends Error {\n public statusCode: number;\n public error: string;\n public nextActions?: string;\n\n constructor(message: string, statusCode: number, error: string, nextActions?: string) {\n super(message);\n this.name = 'InsForgeError';\n this.statusCode = statusCode;\n this.error = error;\n this.nextActions = nextActions;\n }\n\n static fromApiError(apiError: ApiError): InsForgeError {\n return new InsForgeError(\n apiError.message,\n apiError.statusCode,\n apiError.error,\n apiError.nextActions\n );\n }\n}","import { InsForgeConfig, ApiError, InsForgeError } from '../types';\n\nexport interface RequestOptions extends RequestInit {\n params?: Record<string, string>;\n}\n\nexport class HttpClient {\n public readonly baseUrl: string;\n public readonly fetch: typeof fetch;\n private defaultHeaders: Record<string, string>;\n private anonKey: string | undefined;\n private userToken: string | null = null;\n\n constructor(config: InsForgeConfig) {\n this.baseUrl = config.baseUrl || 'http://localhost:7130';\n // Properly bind fetch to maintain its context\n this.fetch = config.fetch || (globalThis.fetch ? globalThis.fetch.bind(globalThis) : undefined as any);\n this.anonKey = config.anonKey;\n this.defaultHeaders = {\n ...config.headers,\n };\n\n if (!this.fetch) {\n throw new Error(\n 'Fetch is not available. Please provide a fetch implementation in the config.'\n );\n }\n }\n\n private buildUrl(path: string, params?: Record<string, string>): string {\n const url = new URL(path, this.baseUrl);\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n // For select parameter, preserve the exact formatting by normalizing whitespace\n // This ensures PostgREST relationship queries work correctly\n if (key === 'select') {\n // Normalize multiline select strings for PostgREST:\n // 1. Replace all whitespace (including newlines) with single space\n // 2. Remove spaces inside parentheses for proper PostgREST syntax\n // 3. Keep spaces after commas at the top level for readability\n let normalizedValue = value.replace(/\\s+/g, ' ').trim();\n \n // Fix spaces around parentheses and inside them\n normalizedValue = normalizedValue\n .replace(/\\s*\\(\\s*/g, '(') // Remove spaces around opening parens\n .replace(/\\s*\\)\\s*/g, ')') // Remove spaces around closing parens\n .replace(/\\(\\s+/g, '(') // Remove spaces after opening parens\n .replace(/\\s+\\)/g, ')') // Remove spaces before closing parens\n .replace(/,\\s+(?=[^()]*\\))/g, ','); // Remove spaces after commas inside parens\n \n url.searchParams.append(key, normalizedValue);\n } else {\n url.searchParams.append(key, value);\n }\n });\n }\n return url.toString();\n }\n\n async request<T>(\n method: string,\n path: string,\n options: RequestOptions = {}\n ): Promise<T> {\n const { params, headers = {}, body, ...fetchOptions } = options;\n \n const url = this.buildUrl(path, params);\n \n const requestHeaders: Record<string, string> = {\n ...this.defaultHeaders,\n };\n \n // Set Authorization header: prefer user token, fallback to anon key\n const authToken = this.userToken || this.anonKey;\n if (authToken) {\n requestHeaders['Authorization'] = `Bearer ${authToken}`;\n }\n \n // Handle body serialization\n let processedBody: any;\n if (body !== undefined) {\n // Check if body is FormData (for file uploads)\n if (typeof FormData !== 'undefined' && body instanceof FormData) {\n // Don't set Content-Type for FormData, let browser set it with boundary\n processedBody = body;\n } else {\n // JSON body\n if (method !== 'GET') {\n requestHeaders['Content-Type'] = 'application/json;charset=UTF-8';\n }\n processedBody = JSON.stringify(body);\n }\n }\n \n Object.assign(requestHeaders, headers);\n \n const response = await this.fetch(url, {\n method,\n headers: requestHeaders,\n body: processedBody,\n ...fetchOptions,\n });\n\n // Handle 204 No Content\n if (response.status === 204) {\n return undefined as T;\n }\n\n // Try to parse JSON response\n let data: any;\n const contentType = response.headers.get('content-type');\n // Check for any JSON content type (including PostgREST's vnd.pgrst.object+json)\n if (contentType?.includes('json')) {\n data = await response.json();\n } else {\n // For non-JSON responses, return text\n data = await response.text();\n }\n\n // Handle errors\n if (!response.ok) {\n if (data && typeof data === 'object' && 'error' in data) {\n throw InsForgeError.fromApiError(data as ApiError);\n }\n throw new InsForgeError(\n `Request failed: ${response.statusText}`,\n response.status,\n 'REQUEST_FAILED'\n );\n }\n\n return data as T;\n }\n\n get<T>(path: string, options?: RequestOptions): Promise<T> {\n return this.request<T>('GET', path, options);\n }\n\n post<T>(path: string, body?: any, options?: RequestOptions): Promise<T> {\n return this.request<T>('POST', path, { ...options, body });\n }\n\n put<T>(path: string, body?: any, options?: RequestOptions): Promise<T> {\n return this.request<T>('PUT', path, { ...options, body });\n }\n\n patch<T>(path: string, body?: any, options?: RequestOptions): Promise<T> {\n return this.request<T>('PATCH', path, { ...options, body });\n }\n\n delete<T>(path: string, options?: RequestOptions): Promise<T> {\n return this.request<T>('DELETE', path, options);\n }\n\n setAuthToken(token: string | null) {\n this.userToken = token;\n }\n\n getHeaders(): Record<string, string> {\n return { ...this.defaultHeaders };\n }\n}","import { TokenStorage, AuthSession } from '../types';\n\nconst TOKEN_KEY = 'insforge-auth-token';\nconst USER_KEY = 'insforge-auth-user';\n\nexport class TokenManager {\n private storage: TokenStorage;\n\n constructor(storage?: TokenStorage) {\n if (storage) {\n // Use provided storage\n this.storage = storage;\n } else if (typeof window !== 'undefined' && window.localStorage) {\n // Browser: use localStorage\n this.storage = window.localStorage;\n } else {\n // Node.js: use in-memory storage\n const store = new Map<string, string>();\n this.storage = {\n getItem: (key: string) => store.get(key) || null,\n setItem: (key: string, value: string) => { store.set(key, value); },\n removeItem: (key: string) => { store.delete(key); }\n };\n }\n }\n\n saveSession(session: AuthSession): void {\n this.storage.setItem(TOKEN_KEY, session.accessToken);\n this.storage.setItem(USER_KEY, JSON.stringify(session.user));\n }\n\n getSession(): AuthSession | null {\n const token = this.storage.getItem(TOKEN_KEY);\n const userStr = this.storage.getItem(USER_KEY);\n\n if (!token || !userStr) {\n return null;\n }\n\n try {\n const user = JSON.parse(userStr as string);\n return { accessToken: token as string, user };\n } catch {\n this.clearSession();\n return null;\n }\n }\n\n getAccessToken(): string | null {\n const token = this.storage.getItem(TOKEN_KEY);\n return typeof token === 'string' ? token : null;\n }\n\n clearSession(): void {\n this.storage.removeItem(TOKEN_KEY);\n this.storage.removeItem(USER_KEY);\n }\n}","/**\n * Database module using @supabase/postgrest-js\n * Complete replacement for custom QueryBuilder with full PostgREST features\n */\n\nimport { PostgrestClient } from '@supabase/postgrest-js';\nimport { HttpClient } from '../lib/http-client';\nimport { TokenManager } from '../lib/token-manager';\n\n\n/**\n * Custom fetch that transforms URLs and adds auth\n */\nfunction createInsForgePostgrestFetch(\n httpClient: HttpClient,\n tokenManager: TokenManager\n): typeof fetch {\n return async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const url = typeof input === 'string' ? input : input.toString();\n const urlObj = new URL(url);\n \n // Extract table name from pathname\n // postgrest-js sends: http://dummy/tablename?params\n // We need: http://localhost:7130/api/database/records/tablename?params\n const tableName = urlObj.pathname.slice(1); // Remove leading /\n \n // Build InsForge URL\n const insforgeUrl = `${httpClient.baseUrl}/api/database/records/${tableName}${urlObj.search}`;\n \n // Get auth token from TokenManager\n const token = tokenManager.getAccessToken();\n \n // Prepare headers\n const headers = new Headers(init?.headers);\n if (token && !headers.has('Authorization')) {\n headers.set('Authorization', `Bearer ${token}`);\n }\n \n // Make the actual request using native fetch\n // This returns a proper Response object with headers\n const response = await fetch(insforgeUrl, {\n ...init,\n headers\n });\n \n return response;\n };\n}\n\n/**\n * Database client using postgrest-js\n * Drop-in replacement with FULL PostgREST capabilities\n */\nexport class Database {\n private postgrest: PostgrestClient<any, any, any>;\n \n constructor(httpClient: HttpClient, tokenManager: TokenManager) {\n // Create postgrest client with custom fetch\n this.postgrest = new PostgrestClient<any, any, any>('http://dummy', {\n fetch: createInsForgePostgrestFetch(httpClient, tokenManager),\n headers: {}\n });\n }\n \n /**\n * Create a query builder for a table\n * \n * @example\n * // Basic query\n * const { data, error } = await client.database\n * .from('posts')\n * .select('*')\n * .eq('user_id', userId);\n * \n * // With count (Supabase style!)\n * const { data, error, count } = await client.database\n * .from('posts')\n * .select('*', { count: 'exact' })\n * .range(0, 9);\n * \n * // Just get count, no data\n * const { count } = await client.database\n * .from('posts')\n * .select('*', { count: 'exact', head: true });\n * \n * // Complex queries with OR\n * const { data } = await client.database\n * .from('posts')\n * .select('*, users!inner(*)')\n * .or('status.eq.active,status.eq.pending');\n * \n * // All features work:\n * - Nested selects\n * - Foreign key expansion \n * - OR/AND/NOT conditions\n * - Count with head\n * - Range pagination\n * - Upserts\n */\n from(table: string) {\n // Return postgrest query builder with all features\n return this.postgrest.from(table);\n }\n}","/**\n * Auth module for InsForge SDK\n * Uses shared schemas for type safety\n */\n\nimport { HttpClient } from '../lib/http-client';\nimport { TokenManager } from '../lib/token-manager';\nimport { AuthSession, InsForgeError } from '../types';\nimport { Database } from './database-postgrest';\n\nimport type {\n CreateUserRequest,\n CreateUserResponse,\n CreateSessionRequest,\n CreateSessionResponse,\n GetCurrentSessionResponse,\n GetOauthUrlResponse,\n} from '@insforge/shared-schemas';\n\nexport class Auth {\n private database: Database;\n \n constructor(\n private http: HttpClient,\n private tokenManager: TokenManager\n ) {\n this.database = new Database(http, tokenManager);\n \n // Auto-detect OAuth callback parameters in the URL\n this.detectOAuthCallback();\n }\n\n /**\n * Automatically detect and handle OAuth callback parameters in the URL\n * This runs on initialization to seamlessly complete the OAuth flow\n * Matches the backend's OAuth callback response (backend/src/api/routes/auth.ts:540-544)\n */\n private detectOAuthCallback(): void {\n // Only run in browser environment\n if (typeof window === 'undefined') return;\n \n try {\n const params = new URLSearchParams(window.location.search);\n \n // Backend returns: access_token, user_id, email, name (optional)\n const accessToken = params.get('access_token');\n const userId = params.get('user_id');\n const email = params.get('email');\n const name = params.get('name');\n \n // Check if we have OAuth callback parameters\n if (accessToken && userId && email) {\n // Create session with the data from backend\n const session: AuthSession = {\n accessToken,\n user: {\n id: userId,\n email: email,\n name: name || '',\n // These fields are not provided by backend OAuth callback\n // They'll be populated when calling getCurrentUser()\n emailVerified: false,\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n } as any,\n };\n \n // Save session and set auth token\n this.tokenManager.saveSession(session);\n this.http.setAuthToken(accessToken);\n \n // Clean up the URL to remove sensitive parameters\n const url = new URL(window.location.href);\n url.searchParams.delete('access_token');\n url.searchParams.delete('user_id');\n url.searchParams.delete('email');\n url.searchParams.delete('name');\n \n // Also handle error case from backend (line 581)\n if (params.has('error')) {\n url.searchParams.delete('error');\n }\n \n // Replace URL without adding to browser history\n window.history.replaceState({}, document.title, url.toString());\n }\n } catch (error) {\n // Silently continue - don't break initialization\n console.debug('OAuth callback detection skipped:', error);\n }\n }\n\n /**\n * Sign up a new user\n */\n async signUp(request: CreateUserRequest): Promise<{\n data: CreateUserResponse | null;\n error: InsForgeError | null;\n }> {\n try {\n const response = await this.http.post<CreateUserResponse>('/api/auth/users', request);\n \n // Save session internally\n const session: AuthSession = {\n accessToken: response.accessToken,\n user: response.user,\n };\n this.tokenManager.saveSession(session);\n this.http.setAuthToken(response.accessToken);\n\n return { \n data: response,\n error: null \n };\n } catch (error) {\n // Pass through API errors unchanged\n if (error instanceof InsForgeError) {\n return { data: null, error };\n }\n \n // Generic fallback for unexpected errors\n return { \n data: null, \n error: new InsForgeError(\n error instanceof Error ? error.message : 'An unexpected error occurred during sign up',\n 500,\n 'UNEXPECTED_ERROR'\n )\n };\n }\n }\n\n /**\n * Sign in with email and password\n */\n async signInWithPassword(request: CreateSessionRequest): Promise<{\n data: CreateSessionResponse | null;\n error: InsForgeError | null;\n }> {\n try {\n const response = await this.http.post<CreateSessionResponse>('/api/auth/sessions', request);\n \n // Save session internally\n const session: AuthSession = {\n accessToken: response.accessToken,\n user: response.user,\n };\n this.tokenManager.saveSession(session);\n this.http.setAuthToken(response.accessToken);\n\n return { \n data: response,\n error: null \n };\n } catch (error) {\n // Pass through API errors unchanged\n if (error instanceof InsForgeError) {\n return { data: null, error };\n }\n \n // Generic fallback for unexpected errors\n return { \n data: null, \n error: new InsForgeError(\n 'An unexpected error occurred during sign in',\n 500,\n 'UNEXPECTED_ERROR'\n )\n };\n }\n }\n\n /**\n * Sign in with OAuth provider\n */\n async signInWithOAuth(options: {\n provider: 'google' | 'github';\n redirectTo?: string;\n skipBrowserRedirect?: boolean;\n }): Promise<{\n data: { url?: string; provider?: string };\n error: InsForgeError | null;\n }> {\n try {\n const { provider, redirectTo, skipBrowserRedirect } = options;\n \n const params = redirectTo \n ? { redirect_uri: redirectTo } \n : undefined;\n \n const endpoint = `/api/auth/oauth/${provider}`;\n const response = await this.http.get<GetOauthUrlResponse>(endpoint, { params });\n \n // Automatically redirect in browser unless told not to\n if (typeof window !== 'undefined' && !skipBrowserRedirect) {\n window.location.href = response.authUrl;\n return { data: {}, error: null };\n }\n\n return { \n data: { \n url: response.authUrl,\n provider \n }, \n error: null \n };\n } catch (error) {\n // Pass through API errors unchanged\n if (error instanceof InsForgeError) {\n return { data: {}, error };\n }\n \n // Generic fallback for unexpected errors\n return { \n data: {}, \n error: new InsForgeError(\n 'An unexpected error occurred during OAuth initialization',\n 500,\n 'UNEXPECTED_ERROR'\n )\n };\n }\n }\n\n /**\n * Sign out the current user\n */\n async signOut(): Promise<{ error: InsForgeError | null }> {\n try {\n this.tokenManager.clearSession();\n this.http.setAuthToken(null);\n return { error: null };\n } catch (error) {\n return { \n error: new InsForgeError(\n 'Failed to sign out',\n 500,\n 'SIGNOUT_ERROR'\n )\n };\n }\n }\n\n /**\n * Get the current user with full profile information\n * Returns both auth info (id, email, role) and profile data (nickname, avatar_url, bio, etc.)\n */\n async getCurrentUser(): Promise<{\n data: { user: any; profile: any } | null;\n error: any | null;\n }> {\n try {\n // Check if we have a token\n const session = this.tokenManager.getSession();\n if (!session?.accessToken) {\n return { data: null, error: null };\n }\n\n // Call the API for auth info\n this.http.setAuthToken(session.accessToken);\n const authResponse = await this.http.get<GetCurrentSessionResponse>('/api/auth/sessions/current');\n \n // Get the user's profile using query builder\n const { data: profile, error: profileError } = await this.database\n .from('users')\n .select('*')\n .eq('id', authResponse.user.id)\n .single();\n \n // For database errors, return PostgrestError directly\n if (profileError && (profileError as any).code !== 'PGRST116') { // PGRST116 = not found\n return { data: null, error: profileError };\n }\n \n return {\n data: {\n user: authResponse.user,\n profile: profile\n },\n error: null\n };\n } catch (error) {\n // If unauthorized, clear session\n if (error instanceof InsForgeError && error.statusCode === 401) {\n await this.signOut();\n return { data: null, error: null };\n }\n \n // Pass through all other errors unchanged\n if (error instanceof InsForgeError) {\n return { data: null, error };\n }\n \n // Generic fallback for unexpected errors\n return { \n data: null, \n error: new InsForgeError(\n 'An unexpected error occurred while fetching user',\n 500,\n 'UNEXPECTED_ERROR'\n )\n };\n }\n }\n\n /**\n * Get any user's profile by ID\n * Returns profile information from the users table (nickname, avatar_url, bio, etc.)\n */\n async getProfile(userId: string): Promise<{\n data: any | null;\n error: any | null;\n }> {\n const { data, error } = await this.database\n .from('users')\n .select('*')\n .eq('id', userId)\n .single();\n \n // Handle not found as null, not error\n if (error && (error as any).code === 'PGRST116') {\n return { data: null, error: null };\n }\n \n // Return PostgrestError directly for database operations\n return { data, error };\n }\n\n /**\n * Get the current session (only session data, no API call)\n * Returns the stored JWT token and basic user info from local storage\n */\n getCurrentSession(): {\n data: { session: AuthSession | null };\n error: InsForgeError | null;\n } {\n try {\n const session = this.tokenManager.getSession();\n \n if (session?.accessToken) {\n this.http.setAuthToken(session.accessToken);\n return { data: { session }, error: null };\n }\n\n return { data: { session: null }, error: null };\n } catch (error) {\n // Pass through API errors unchanged\n if (error instanceof InsForgeError) {\n return { data: { session: null }, error };\n }\n \n // Generic fallback for unexpected errors\n return { \n data: { session: null }, \n error: new InsForgeError(\n 'An unexpected error occurred while getting session',\n 500,\n 'UNEXPECTED_ERROR'\n )\n };\n }\n }\n\n /**\n * Set/Update the current user's profile\n * Updates profile information in the users table (nickname, avatar_url, bio, etc.)\n */\n async setProfile(profile: {\n nickname?: string;\n avatar_url?: string;\n bio?: string;\n birthday?: string;\n [key: string]: any;\n }): Promise<{\n data: any | null;\n error: any | null;\n }> {\n // Get current session to get user ID\n const session = this.tokenManager.getSession();\n if (!session?.user?.id) {\n return { \n data: null, \n error: new InsForgeError(\n 'No authenticated user found',\n 401,\n 'UNAUTHENTICATED'\n )\n };\n }\n\n // Update the profile using query builder\n const { data, error } = await this.database\n .from('users')\n .update(profile)\n .eq('id', session.user.id)\n .select()\n .single();\n \n // Return PostgrestError directly for database operations\n return { data, error };\n }\n\n\n}","/**\n * Storage module for InsForge SDK\n * Handles file uploads, downloads, and bucket management\n */\n\nimport { HttpClient } from '../lib/http-client';\nimport { InsForgeError } from '../types';\nimport type { \n StorageFileSchema,\n ListObjectsResponseSchema\n} from '@insforge/shared-schemas';\n\nexport interface StorageResponse<T> {\n data: T | null;\n error: InsForgeError | null;\n}\n\ninterface UploadStrategy {\n method: 'direct' | 'presigned';\n uploadUrl: string;\n fields?: Record<string, string>;\n key: string;\n confirmRequired: boolean;\n confirmUrl?: string;\n expiresAt?: Date;\n}\n\ninterface DownloadStrategy {\n method: 'direct' | 'presigned';\n url: string;\n expiresAt?: Date;\n}\n\n/**\n * Storage bucket operations\n */\nexport class StorageBucket {\n constructor(\n private bucketName: string,\n private http: HttpClient\n ) {}\n\n /**\n * Upload a file with a specific key\n * Uses the upload strategy from backend (direct or presigned)\n * @param path - The object key/path\n * @param file - File or Blob to upload\n */\n async upload(\n path: string,\n file: File | Blob\n ): Promise<StorageResponse<StorageFileSchema>> {\n try {\n // Get upload strategy from backend - this is required\n const strategyResponse = await this.http.post<UploadStrategy>(\n `/api/storage/buckets/${this.bucketName}/upload-strategy`,\n {\n filename: path,\n contentType: file.type || 'application/octet-stream',\n size: file.size\n }\n );\n\n // Use presigned URL if available\n if (strategyResponse.method === 'presigned') {\n return await this.uploadWithPresignedUrl(strategyResponse, file);\n }\n\n // Use direct upload if strategy says so\n if (strategyResponse.method === 'direct') {\n const formData = new FormData();\n formData.append('file', file);\n\n const response = await this.http.request<StorageFileSchema>(\n 'PUT',\n `/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}`,\n {\n body: formData as any,\n headers: {\n // Don't set Content-Type, let browser set multipart boundary\n }\n }\n );\n\n return { data: response, error: null };\n }\n\n throw new InsForgeError(\n `Unsupported upload method: ${strategyResponse.method}`,\n 500,\n 'STORAGE_ERROR'\n );\n } catch (error) {\n return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'Upload failed',\n 500,\n 'STORAGE_ERROR'\n )\n };\n }\n }\n\n /**\n * Upload a file with auto-generated key\n * Uses the upload strategy from backend (direct or presigned)\n * @param file - File or Blob to upload\n */\n async uploadAuto(\n file: File | Blob\n ): Promise<StorageResponse<StorageFileSchema>> {\n try {\n const filename = file instanceof File ? file.name : 'file';\n \n // Get upload strategy from backend - this is required\n const strategyResponse = await this.http.post<UploadStrategy>(\n `/api/storage/buckets/${this.bucketName}/upload-strategy`,\n {\n filename,\n contentType: file.type || 'application/octet-stream',\n size: file.size\n }\n );\n\n // Use presigned URL if available\n if (strategyResponse.method === 'presigned') {\n return await this.uploadWithPresignedUrl(strategyResponse, file);\n }\n\n // Use direct upload if strategy says so\n if (strategyResponse.method === 'direct') {\n const formData = new FormData();\n formData.append('file', file);\n\n const response = await this.http.request<StorageFileSchema>(\n 'POST',\n `/api/storage/buckets/${this.bucketName}/objects`,\n {\n body: formData as any,\n headers: {\n // Don't set Content-Type, let browser set multipart boundary\n }\n }\n );\n\n return { data: response, error: null };\n }\n\n throw new InsForgeError(\n `Unsupported upload method: ${strategyResponse.method}`,\n 500,\n 'STORAGE_ERROR'\n );\n } catch (error) {\n return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'Upload failed',\n 500,\n 'STORAGE_ERROR'\n )\n };\n }\n }\n\n /**\n * Internal method to handle presigned URL uploads\n */\n private async uploadWithPresignedUrl(\n strategy: UploadStrategy,\n file: File | Blob\n ): Promise<StorageResponse<StorageFileSchema>> {\n try {\n // Upload to presigned URL (e.g., S3)\n const formData = new FormData();\n \n // Add all fields from the presigned URL\n if (strategy.fields) {\n Object.entries(strategy.fields).forEach(([key, value]) => {\n formData.append(key, value);\n });\n }\n \n // File must be the last field for S3\n formData.append('file', file);\n\n const uploadResponse = await fetch(strategy.uploadUrl, {\n method: 'POST',\n body: formData\n });\n\n if (!uploadResponse.ok) {\n throw new InsForgeError(\n `Upload to storage failed: ${uploadResponse.statusText}`,\n uploadResponse.status,\n 'STORAGE_ERROR'\n );\n }\n\n // Confirm upload with backend if required\n if (strategy.confirmRequired && strategy.confirmUrl) {\n const confirmResponse = await this.http.post<StorageFileSchema>(\n strategy.confirmUrl,\n {\n size: file.size,\n contentType: file.type || 'application/octet-stream'\n }\n );\n\n return { data: confirmResponse, error: null };\n }\n\n // If no confirmation required, return basic file info\n return {\n data: {\n key: strategy.key,\n bucket: this.bucketName,\n size: file.size,\n mimeType: file.type || 'application/octet-stream',\n uploadedAt: new Date().toISOString(),\n url: this.getPublicUrl(strategy.key)\n } as StorageFileSchema,\n error: null\n };\n } catch (error) {\n throw error instanceof InsForgeError ? error : new InsForgeError(\n 'Presigned upload failed',\n 500,\n 'STORAGE_ERROR'\n );\n }\n }\n\n /**\n * Download a file\n * Uses the download strategy from backend (direct or presigned)\n * @param path - The object key/path\n * Returns the file as a Blob\n */\n async download(path: string): Promise<{ data: Blob | null; error: InsForgeError | null }> {\n try {\n // Get download strategy from backend - this is required\n const strategyResponse = await this.http.post<DownloadStrategy>(\n `/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}/download-strategy`,\n { expiresIn: 3600 }\n );\n\n // Use URL from strategy\n const downloadUrl = strategyResponse.url;\n \n // Download from the URL\n const headers: HeadersInit = {};\n \n // Only add auth header for direct downloads (not presigned URLs)\n if (strategyResponse.method === 'direct') {\n Object.assign(headers, this.http.getHeaders());\n }\n \n const response = await fetch(downloadUrl, {\n method: 'GET',\n headers\n });\n\n if (!response.ok) {\n try {\n const error = await response.json();\n throw InsForgeError.fromApiError(error);\n } catch {\n throw new InsForgeError(\n `Download failed: ${response.statusText}`,\n response.status,\n 'STORAGE_ERROR'\n );\n }\n }\n\n const blob = await response.blob();\n return { data: blob, error: null };\n } catch (error) {\n return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'Download failed',\n 500,\n 'STORAGE_ERROR'\n )\n };\n }\n }\n\n /**\n * Get public URL for a file\n * @param path - The object key/path\n */\n getPublicUrl(path: string): string {\n return `${this.http.baseUrl}/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}`;\n }\n\n /**\n * List objects in the bucket\n * @param prefix - Filter by key prefix\n * @param search - Search in file names\n * @param limit - Maximum number of results (default: 100, max: 1000)\n * @param offset - Number of results to skip\n */\n async list(options?: {\n prefix?: string;\n search?: string;\n limit?: number;\n offset?: number;\n }): Promise<StorageResponse<ListObjectsResponseSchema>> {\n try {\n const params: Record<string, string> = {};\n \n if (options?.prefix) params.prefix = options.prefix;\n if (options?.search) params.search = options.search;\n if (options?.limit) params.limit = options.limit.toString();\n if (options?.offset) params.offset = options.offset.toString();\n\n const response = await this.http.get<ListObjectsResponseSchema>(\n `/api/storage/buckets/${this.bucketName}/objects`,\n { params }\n );\n\n return { data: response, error: null };\n } catch (error) {\n return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'List failed',\n 500,\n 'STORAGE_ERROR'\n )\n };\n }\n }\n\n /**\n * Delete a file\n * @param path - The object key/path\n */\n async remove(path: string): Promise<StorageResponse<{ message: string }>> {\n try {\n const response = await this.http.delete<{ message: string }>(\n `/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}`\n );\n\n return { data: response, error: null };\n } catch (error) {\n return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'Delete failed',\n 500,\n 'STORAGE_ERROR'\n )\n };\n }\n }\n}\n\n/**\n * Storage module for file operations\n */\nexport class Storage {\n constructor(private http: HttpClient) {}\n\n /**\n * Get a bucket instance for operations\n * @param bucketName - Name of the bucket\n */\n from(bucketName: string): StorageBucket {\n return new StorageBucket(bucketName, this.http);\n }\n}","/**\n * AI Module for Insforge SDK\n * Response format roughly matches OpenAI SDK for compatibility\n *\n * The backend handles all the complexity of different AI providers\n * and returns a unified format. This SDK transforms responses to match OpenAI-like format.\n */\n\nimport { HttpClient } from \"../lib/http-client\";\nimport {\n ChatCompletionRequest,\n ChatCompletionResponse,\n ImageGenerationRequest,\n ImageGenerationResponse,\n} from \"@insforge/shared-schemas\";\n\nexport class AI {\n public readonly chat: Chat;\n public readonly images: Images;\n\n constructor(private http: HttpClient) {\n this.chat = new Chat(http);\n this.images = new Images(http);\n }\n}\n\nclass Chat {\n public readonly completions: ChatCompletions;\n\n constructor(http: HttpClient) {\n this.completions = new ChatCompletions(http);\n }\n}\n\nclass ChatCompletions {\n constructor(private http: HttpClient) {}\n\n /**\n * Create a chat completion - OpenAI-like response format\n *\n * @example\n * ```typescript\n * // Non-streaming\n * const completion = await client.ai.chat.completions.create({\n * model: 'gpt-4',\n * messages: [{ role: 'user', content: 'Hello!' }]\n * });\n * console.log(completion.choices[0].message.content);\n *\n * // With images\n * const response = await client.ai.chat.completions.create({\n * model: 'gpt-4-vision',\n * messages: [{\n * role: 'user',\n * content: 'What is in this image?',\n * images: [{ url: 'https://example.com/image.jpg' }]\n * }]\n * });\n *\n * // Streaming - returns async iterable\n * const stream = await client.ai.chat.completions.create({\n * model: 'gpt-4',\n * messages: [{ role: 'user', content: 'Tell me a story' }],\n * stream: true\n * });\n *\n * for await (const chunk of stream) {\n * if (chunk.choices[0]?.delta?.content) {\n * process.stdout.write(chunk.choices[0].delta.content);\n * }\n * }\n * ```\n */\n async create(params: ChatCompletionRequest): Promise<any> {\n // Backend already expects camelCase, no transformation needed\n const backendParams = {\n model: params.model,\n messages: params.messages,\n temperature: params.temperature,\n maxTokens: params.maxTokens,\n topP: params.topP,\n stream: params.stream,\n };\n\n // For streaming, return an async iterable that yields OpenAI-like chunks\n if (params.stream) {\n const headers = this.http.getHeaders();\n headers[\"Content-Type\"] = \"application/json\";\n\n const response = await this.http.fetch(\n `${this.http.baseUrl}/api/ai/chat/completion`,\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(backendParams),\n }\n );\n\n if (!response.ok) {\n const error = await response.json();\n throw new Error(error.error || \"Stream request failed\");\n }\n\n // Return async iterable that parses SSE and transforms to OpenAI-like format\n return this.parseSSEStream(response, params.model);\n }\n\n // Non-streaming: transform response to OpenAI-like format\n const response: ChatCompletionResponse = await this.http.post(\n \"/api/ai/chat/completion\",\n backendParams\n );\n\n // Transform to OpenAI-like format\n const content = response.text || \"\";\n\n return {\n id: `chatcmpl-${Date.now()}`,\n object: \"chat.completion\",\n created: Math.floor(Date.now() / 1000),\n model: response.metadata?.model,\n choices: [\n {\n index: 0,\n message: {\n role: \"assistant\",\n content,\n },\n finish_reason: \"stop\",\n },\n ],\n usage: response.metadata?.usage || {\n prompt_tokens: 0,\n completion_tokens: 0,\n total_tokens: 0,\n },\n };\n }\n\n /**\n * Parse SSE stream into async iterable of OpenAI-like chunks\n */\n private async *parseSSEStream(\n response: Response,\n model: string\n ): AsyncIterableIterator<any> {\n const reader = response.body!.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() || \"\";\n\n for (const line of lines) {\n if (line.startsWith(\"data: \")) {\n const dataStr = line.slice(6).trim();\n if (dataStr) {\n try {\n const data = JSON.parse(dataStr);\n\n // Transform to OpenAI-like streaming format\n if (data.chunk || data.content) {\n yield {\n id: `chatcmpl-${Date.now()}`,\n object: \"chat.completion.chunk\",\n created: Math.floor(Date.now() / 1000),\n model,\n choices: [\n {\n index: 0,\n delta: {\n content: data.chunk || data.content,\n },\n finish_reason: data.done ? \"stop\" : null,\n },\n ],\n };\n }\n\n // If we received the done signal, we can stop\n if (data.done) {\n reader.releaseLock();\n return;\n }\n } catch (e) {\n // Skip invalid JSON\n console.warn(\"Failed to parse SSE data:\", dataStr);\n }\n }\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n}\n\nclass Images {\n constructor(private http: HttpClient) {}\n\n /**\n * Generate images - OpenAI-like response format\n *\n * @example\n * ```typescript\n * // Text-to-image\n * const response = await client.ai.images.generate({\n * model: 'dall-e-3',\n * prompt: 'A sunset over mountains',\n * });\n * console.log(response.images[0].url);\n *\n * // Image-to-image (with input images)\n * const response = await client.ai.images.generate({\n * model: 'stable-diffusion-xl',\n * prompt: 'Transform this into a watercolor painting',\n * images: [\n * { url: 'https://example.com/input.jpg' },\n * // or base64-encoded Data URI:\n * { url: 'data:image/jpeg;base64,/9j/4AAQ...' }\n * ]\n * });\n * ```\n */\n async generate(params: ImageGenerationRequest): Promise<any> {\n const response: ImageGenerationResponse = await this.http.post(\n \"/api/ai/image/generation\",\n params\n );\n \n // Build data array based on response content\n let data: Array<{ b64_json?: string; content?: string }> = [];\n \n if (response.images && response.images.length > 0) {\n // Has images - extract base64 and include text\n data = response.images.map(img => ({\n b64_json: img.imageUrl.replace(/^data:image\\/\\w+;base64,/, ''),\n content: response.text\n }));\n } else if (response.text) {\n // Text-only response\n data = [{ content: response.text }];\n }\n \n // Return OpenAI-compatible format\n return {\n created: Math.floor(Date.now() / 1000),\n data,\n ...(response.metadata?.usage && {\n usage: {\n total_tokens: response.metadata.usage.totalTokens || 0,\n input_tokens: response.metadata.usage.promptTokens || 0,\n output_tokens: response.metadata.usage.completionTokens || 0,\n }\n })\n };\n }\n}\n","import { InsForgeConfig } from './types';\nimport { HttpClient } from './lib/http-client';\nimport { TokenManager } from './lib/token-manager';\nimport { Auth } from './modules/auth';\nimport { Database } from './modules/database-postgrest';\nimport { Storage } from './modules/storage';\nimport { AI } from './modules/ai';\n\n/**\n * Main InsForge SDK Client\n * \n * @example\n * ```typescript\n * import { InsForgeClient } from '@insforge/sdk';\n * \n * const client = new InsForgeClient({\n * baseUrl: 'http://localhost:7130'\n * });\n * \n * // Authentication\n * const session = await client.auth.register({\n * email: 'user@example.com',\n * password: 'password123',\n * name: 'John Doe'\n * });\n * \n * // Database operations\n * const { data, error } = await client.database\n * .from('posts')\n * .select('*')\n * .eq('user_id', session.user.id)\n * .order('created_at', { ascending: false })\n * .limit(10);\n * \n * // Insert data\n * const { data: newPost } = await client.database\n * .from('posts')\n * .insert({ title: 'Hello', content: 'World' })\n * .single();\n * ```\n */\nexport class InsForgeClient {\n private http: HttpClient;\n private tokenManager: TokenManager;\n \n public readonly auth: Auth;\n public readonly database: Database;\n public readonly storage: Storage;\n public readonly ai: AI;\n\n constructor(config: InsForgeConfig = {}) {\n this.http = new HttpClient(config);\n this.tokenManager = new TokenManager(config.storage);\n \n this.auth = new Auth(\n this.http,\n this.tokenManager\n );\n \n this.database = new Database(this.http, this.tokenManager);\n this.storage = new Storage(this.http);\n this.ai = new AI(this.http);\n }\n\n /**\n * Get the underlying HTTP client for custom requests\n * \n * @example\n * ```typescript\n * const httpClient = client.getHttpClient();\n * const customData = await httpClient.get('/api/custom-endpoint');\n * ```\n */\n getHttpClient(): HttpClient {\n return this.http;\n }\n\n /**\n * Future modules will be added here:\n * - database: Database operations\n * - storage: File storage operations\n * - functions: Serverless functions\n * - tables: Table management\n * - metadata: Backend metadata\n */\n}","/**\n * @insforge/sdk - TypeScript SDK for InsForge Backend-as-a-Service\n * \n * @packageDocumentation\n */\n\n// Main client\nexport { InsForgeClient } from './client';\n\n// Types\nexport type {\n InsForgeConfig,\n InsForgeConfig as ClientOptions, // Alias for compatibility\n TokenStorage,\n AuthSession,\n ApiError,\n} from './types';\n\nexport { InsForgeError } from './types';\n\n// Re-export shared schemas that SDK users will need\nexport type {\n UserSchema,\n CreateUserRequest,\n CreateSessionRequest,\n AuthErrorResponse,\n} from '@insforge/shared-schemas';\n\n// Re-export auth module for advanced usage\nexport { Auth } from './modules/auth';\n\n// Re-export database module (using postgrest-js)\nexport { Database } from './modules/database-postgrest';\n// Note: QueryBuilder is no longer exported as we use postgrest-js QueryBuilder internally\n\n// Re-export storage module and types\nexport { Storage, StorageBucket } from './modules/storage';\nexport type { StorageResponse } from './modules/storage';\n\n// Re-export AI module\nexport { AI } from './modules/ai';\n\n// Re-export utilities for advanced usage\nexport { HttpClient } from './lib/http-client';\nexport { TokenManager } from './lib/token-manager';\n\n// Factory function for creating clients (Supabase-style)\nimport { InsForgeClient } from './client';\nimport { InsForgeConfig } from './types';\n\nexport function createClient(config: InsForgeConfig): InsForgeClient {\n return new InsForgeClient(config);\n}\n\n// Default export for convenience\nexport default InsForgeClient;"],"mappings":"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","names":["response"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@insforge/sdk",
3
- "version": "0.0.32",
3
+ "version": "0.0.34",
4
4
  "description": "TypeScript SDK for InsForge Backend-as-a-Service platform",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",