@insforge/sdk 0.0.3 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -21,9 +21,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  Auth: () => Auth,
24
+ Database: () => Database,
24
25
  HttpClient: () => HttpClient,
25
26
  InsForgeClient: () => InsForgeClient,
26
27
  InsForgeError: () => InsForgeError,
28
+ QueryBuilder: () => QueryBuilder,
27
29
  TokenManager: () => TokenManager,
28
30
  createClient: () => createClient,
29
31
  default: () => index_default
@@ -53,7 +55,7 @@ var InsForgeError = class _InsForgeError extends Error {
53
55
  var HttpClient = class {
54
56
  constructor(config) {
55
57
  this.baseUrl = config.url || "http://localhost:7130";
56
- this.fetch = config.fetch || globalThis.fetch;
58
+ this.fetch = config.fetch || (globalThis.fetch ? globalThis.fetch.bind(globalThis) : void 0);
57
59
  this.defaultHeaders = {
58
60
  "Content-Type": "application/json",
59
61
  ...config.headers
@@ -207,12 +209,15 @@ var Auth = class {
207
209
  error: null
208
210
  };
209
211
  } catch (error) {
212
+ if (error instanceof InsForgeError) {
213
+ return { data: null, error };
214
+ }
210
215
  return {
211
216
  data: null,
212
- error: error instanceof InsForgeError ? error : new InsForgeError(
213
- "Failed to sign up",
217
+ error: new InsForgeError(
218
+ error instanceof Error ? error.message : "An unexpected error occurred during sign up",
214
219
  500,
215
- "SIGNUP_ERROR"
220
+ "UNEXPECTED_ERROR"
216
221
  )
217
222
  };
218
223
  }
@@ -234,12 +239,15 @@ var Auth = class {
234
239
  error: null
235
240
  };
236
241
  } catch (error) {
242
+ if (error instanceof InsForgeError) {
243
+ return { data: null, error };
244
+ }
237
245
  return {
238
246
  data: null,
239
- error: error instanceof InsForgeError ? error : new InsForgeError(
240
- "Invalid login credentials",
241
- 401,
242
- "INVALID_CREDENTIALS"
247
+ error: new InsForgeError(
248
+ "An unexpected error occurred during sign in",
249
+ 500,
250
+ "UNEXPECTED_ERROR"
243
251
  )
244
252
  };
245
253
  }
@@ -265,12 +273,15 @@ var Auth = class {
265
273
  error: null
266
274
  };
267
275
  } catch (error) {
276
+ if (error instanceof InsForgeError) {
277
+ return { data: {}, error };
278
+ }
268
279
  return {
269
280
  data: {},
270
- error: error instanceof InsForgeError ? error : new InsForgeError(
271
- `Failed to initialize OAuth`,
281
+ error: new InsForgeError(
282
+ "An unexpected error occurred during OAuth initialization",
272
283
  500,
273
- "OAUTH_ERROR"
284
+ "UNEXPECTED_ERROR"
274
285
  )
275
286
  };
276
287
  }
@@ -314,12 +325,15 @@ var Auth = class {
314
325
  await this.signOut();
315
326
  return { data: null, error: null };
316
327
  }
328
+ if (error instanceof InsForgeError) {
329
+ return { data: null, error };
330
+ }
317
331
  return {
318
332
  data: null,
319
- error: error instanceof InsForgeError ? error : new InsForgeError(
320
- "Failed to get current user",
333
+ error: new InsForgeError(
334
+ "An unexpected error occurred while fetching user",
321
335
  500,
322
- "GET_USER_ERROR"
336
+ "UNEXPECTED_ERROR"
323
337
  )
324
338
  };
325
339
  }
@@ -336,16 +350,302 @@ var Auth = class {
336
350
  }
337
351
  return { data: { session: null }, error: null };
338
352
  } catch (error) {
353
+ if (error instanceof InsForgeError) {
354
+ return { data: { session: null }, error };
355
+ }
339
356
  return {
340
357
  data: { session: null },
358
+ error: new InsForgeError(
359
+ "An unexpected error occurred while getting session",
360
+ 500,
361
+ "UNEXPECTED_ERROR"
362
+ )
363
+ };
364
+ }
365
+ }
366
+ };
367
+
368
+ // src/modules/database.ts
369
+ var QueryBuilder = class {
370
+ constructor(table, http) {
371
+ this.table = table;
372
+ this.http = http;
373
+ this.method = "GET";
374
+ this.headers = {};
375
+ this.queryParams = {};
376
+ }
377
+ /**
378
+ * Perform a SELECT query
379
+ * @param columns - Columns to select (default: '*')
380
+ * @example
381
+ * .select('*')
382
+ * .select('id, title, content')
383
+ * .select('*, user:user_id(name, email)') // Foreign key expansion
384
+ */
385
+ select(columns = "*") {
386
+ this.method = "GET";
387
+ if (columns !== "*") {
388
+ this.queryParams.select = columns;
389
+ }
390
+ return this;
391
+ }
392
+ /**
393
+ * Perform an INSERT
394
+ * @param values - Single object or array of objects
395
+ * @param options - { upsert: true } for upsert behavior
396
+ * @example
397
+ * .insert({ title: 'Hello', content: 'World' })
398
+ * .insert([{ title: 'Post 1' }, { title: 'Post 2' }])
399
+ */
400
+ insert(values, options) {
401
+ this.method = "POST";
402
+ this.body = Array.isArray(values) ? values : [values];
403
+ if (options?.upsert) {
404
+ this.headers["Prefer"] = "resolution=merge-duplicates,return=representation";
405
+ } else {
406
+ this.headers["Prefer"] = "return=representation";
407
+ }
408
+ return this;
409
+ }
410
+ /**
411
+ * Perform an UPDATE
412
+ * @param values - Object with fields to update
413
+ * @example
414
+ * .update({ title: 'Updated Title' })
415
+ */
416
+ update(values) {
417
+ this.method = "PATCH";
418
+ this.body = values;
419
+ this.headers["Prefer"] = "return=representation";
420
+ return this;
421
+ }
422
+ /**
423
+ * Perform a DELETE
424
+ * @example
425
+ * .delete()
426
+ */
427
+ delete() {
428
+ this.method = "DELETE";
429
+ this.headers["Prefer"] = "return=representation";
430
+ return this;
431
+ }
432
+ /**
433
+ * Perform an UPSERT
434
+ * @param values - Single object or array of objects
435
+ * @example
436
+ * .upsert({ id: 1, title: 'Hello' })
437
+ */
438
+ upsert(values) {
439
+ return this.insert(values, { upsert: true });
440
+ }
441
+ // FILTERS
442
+ /**
443
+ * Filter by column equal to value
444
+ * @example .eq('id', 123)
445
+ */
446
+ eq(column, value) {
447
+ this.queryParams[column] = `eq.${value}`;
448
+ return this;
449
+ }
450
+ /**
451
+ * Filter by column not equal to value
452
+ * @example .neq('status', 'draft')
453
+ */
454
+ neq(column, value) {
455
+ this.queryParams[column] = `neq.${value}`;
456
+ return this;
457
+ }
458
+ /**
459
+ * Filter by column greater than value
460
+ * @example .gt('age', 18)
461
+ */
462
+ gt(column, value) {
463
+ this.queryParams[column] = `gt.${value}`;
464
+ return this;
465
+ }
466
+ /**
467
+ * Filter by column greater than or equal to value
468
+ * @example .gte('price', 100)
469
+ */
470
+ gte(column, value) {
471
+ this.queryParams[column] = `gte.${value}`;
472
+ return this;
473
+ }
474
+ /**
475
+ * Filter by column less than value
476
+ * @example .lt('stock', 10)
477
+ */
478
+ lt(column, value) {
479
+ this.queryParams[column] = `lt.${value}`;
480
+ return this;
481
+ }
482
+ /**
483
+ * Filter by column less than or equal to value
484
+ * @example .lte('discount', 50)
485
+ */
486
+ lte(column, value) {
487
+ this.queryParams[column] = `lte.${value}`;
488
+ return this;
489
+ }
490
+ /**
491
+ * Filter by pattern matching (case-sensitive)
492
+ * @example .like('email', '%@gmail.com')
493
+ */
494
+ like(column, pattern) {
495
+ this.queryParams[column] = `like.${pattern}`;
496
+ return this;
497
+ }
498
+ /**
499
+ * Filter by pattern matching (case-insensitive)
500
+ * @example .ilike('name', '%john%')
501
+ */
502
+ ilike(column, pattern) {
503
+ this.queryParams[column] = `ilike.${pattern}`;
504
+ return this;
505
+ }
506
+ /**
507
+ * Filter by checking if column is a value
508
+ * @example .is('deleted_at', null)
509
+ */
510
+ is(column, value) {
511
+ if (value === null) {
512
+ this.queryParams[column] = "is.null";
513
+ } else {
514
+ this.queryParams[column] = `is.${value}`;
515
+ }
516
+ return this;
517
+ }
518
+ /**
519
+ * Filter by checking if value is in array
520
+ * @example .in('status', ['active', 'pending'])
521
+ */
522
+ in(column, values) {
523
+ this.queryParams[column] = `in.(${values.join(",")})`;
524
+ return this;
525
+ }
526
+ // MODIFIERS
527
+ /**
528
+ * Order by column
529
+ * @example
530
+ * .order('created_at') // ascending
531
+ * .order('created_at', { ascending: false }) // descending
532
+ */
533
+ order(column, options) {
534
+ const ascending = options?.ascending !== false;
535
+ this.queryParams.order = ascending ? column : `${column}.desc`;
536
+ return this;
537
+ }
538
+ /**
539
+ * Limit the number of rows returned
540
+ * @example .limit(10)
541
+ */
542
+ limit(count) {
543
+ this.queryParams.limit = count.toString();
544
+ return this;
545
+ }
546
+ /**
547
+ * Return results from an offset
548
+ * @example .offset(20)
549
+ */
550
+ offset(count) {
551
+ this.queryParams.offset = count.toString();
552
+ return this;
553
+ }
554
+ /**
555
+ * Set a range of rows to return
556
+ * @example .range(0, 9) // First 10 rows
557
+ */
558
+ range(from, to) {
559
+ this.headers["Range"] = `${from}-${to}`;
560
+ return this;
561
+ }
562
+ /**
563
+ * Return a single object instead of array
564
+ * @example .single()
565
+ */
566
+ single() {
567
+ this.headers["Accept"] = "application/vnd.pgrst.object+json";
568
+ return this;
569
+ }
570
+ /**
571
+ * Get the total count (use with select)
572
+ * @example .select('*', { count: 'exact' })
573
+ */
574
+ count(algorithm = "exact") {
575
+ const prefer = this.headers["Prefer"] || "";
576
+ this.headers["Prefer"] = prefer ? `${prefer},count=${algorithm}` : `count=${algorithm}`;
577
+ return this;
578
+ }
579
+ /**
580
+ * Execute the query and return results
581
+ */
582
+ async execute() {
583
+ try {
584
+ const path = `/api/database/records/${this.table}`;
585
+ let response;
586
+ switch (this.method) {
587
+ case "GET":
588
+ response = await this.http.get(path, {
589
+ params: this.queryParams,
590
+ headers: this.headers
591
+ });
592
+ break;
593
+ case "POST":
594
+ response = await this.http.post(path, this.body, {
595
+ params: this.queryParams,
596
+ headers: this.headers
597
+ });
598
+ break;
599
+ case "PATCH":
600
+ response = await this.http.patch(path, this.body, {
601
+ params: this.queryParams,
602
+ headers: this.headers
603
+ });
604
+ break;
605
+ case "DELETE":
606
+ response = await this.http.delete(path, {
607
+ params: this.queryParams,
608
+ headers: this.headers
609
+ });
610
+ break;
611
+ }
612
+ return { data: response, error: null };
613
+ } catch (error) {
614
+ return {
615
+ data: null,
341
616
  error: error instanceof InsForgeError ? error : new InsForgeError(
342
- "Failed to get session",
617
+ "Database operation failed",
343
618
  500,
344
- "GET_SESSION_ERROR"
619
+ "DATABASE_ERROR"
345
620
  )
346
621
  };
347
622
  }
348
623
  }
624
+ /**
625
+ * Make QueryBuilder thenable for async/await
626
+ */
627
+ then(onfulfilled, onrejected) {
628
+ return this.execute().then(onfulfilled, onrejected);
629
+ }
630
+ };
631
+ var Database = class {
632
+ constructor(http) {
633
+ this.http = http;
634
+ }
635
+ /**
636
+ * Create a query builder for a table
637
+ * @param table - The table name
638
+ * @example
639
+ * const { data, error } = await client.database
640
+ * .from('posts')
641
+ * .select('*')
642
+ * .eq('user_id', userId)
643
+ * .order('created_at', { ascending: false })
644
+ * .limit(10);
645
+ */
646
+ from(table) {
647
+ return new QueryBuilder(table, this.http);
648
+ }
349
649
  };
350
650
 
351
651
  // src/client.ts
@@ -357,6 +657,7 @@ var InsForgeClient = class {
357
657
  this.http,
358
658
  this.tokenManager
359
659
  );
660
+ this.database = new Database(this.http);
360
661
  }
361
662
  /**
362
663
  * Set a custom API key for authentication
@@ -402,9 +703,11 @@ var index_default = InsForgeClient;
402
703
  // Annotate the CommonJS export names for ESM import in node:
403
704
  0 && (module.exports = {
404
705
  Auth,
706
+ Database,
405
707
  HttpClient,
406
708
  InsForgeClient,
407
709
  InsForgeError,
710
+ QueryBuilder,
408
711
  TokenManager,
409
712
  createClient
410
713
  });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/types.ts","../src/lib/http-client.ts","../src/lib/token-manager.ts","../src/modules/auth.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 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 URL of the InsForge backend API\n * @default \"http://localhost:7130\"\n */\n url?: string;\n\n /**\n * API key (optional)\n * Can be used for server-side operations or specific use cases\n */\n apiKey?: 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 private baseUrl: string;\n private fetch: typeof fetch;\n private defaultHeaders: Record<string, string>;\n\n constructor(config: InsForgeConfig) {\n this.baseUrl = config.url || 'http://localhost:7130';\n this.fetch = config.fetch || globalThis.fetch;\n this.defaultHeaders = {\n 'Content-Type': 'application/json',\n ...config.headers,\n };\n \n // Add API key if provided\n if (config.apiKey) {\n this.defaultHeaders['Authorization'] = `Bearer ${config.apiKey}`;\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 url.searchParams.append(key, value);\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 response = await this.fetch(url, {\n method,\n headers: {\n ...this.defaultHeaders,\n ...headers,\n },\n body: body ? JSON.stringify(body) : undefined,\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 if (contentType?.includes('application/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 if (token) {\n this.defaultHeaders['Authorization'] = `Bearer ${token}`;\n } else {\n delete this.defaultHeaders['Authorization'];\n }\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 * 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';\n\nimport type {\n UserSchema,\n CreateUserRequest,\n CreateUserResponse,\n CreateSessionRequest,\n CreateSessionResponse,\n GetCurrentSessionResponse,\n GetOauthUrlResponse,\n} from '@insforge/shared-schemas';\n\nexport class Auth {\n constructor(\n private http: HttpClient,\n private tokenManager: TokenManager\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 return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'Failed to sign up',\n 500,\n 'SIGNUP_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 return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'Invalid login credentials',\n 401,\n 'INVALID_CREDENTIALS'\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 return { \n data: {}, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n `Failed to initialize OAuth`,\n 500,\n 'OAUTH_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 from the API\n * Returns exactly what the backend returns: {id, email, role}\n */\n async getCurrentUser(): Promise<{\n data: GetCurrentSessionResponse | null;\n error: InsForgeError | 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\n this.http.setAuthToken(session.accessToken);\n const response = await this.http.get<GetCurrentSessionResponse>('/api/auth/sessions/current');\n \n return {\n data: response,\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 return { \n data: null, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'Failed to get current user',\n 500,\n 'GET_USER_ERROR'\n )\n };\n }\n }\n\n /**\n * Get the stored session (no API call)\n */\n async getSession(): Promise<{\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 return { \n data: { session: null }, \n error: error instanceof InsForgeError ? error : new InsForgeError(\n 'Failed to get session',\n 500,\n 'GET_SESSION_ERROR'\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';\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 * // Register a new user\n * const session = await client.auth.register({\n * email: 'user@example.com',\n * password: 'password123',\n * name: 'John Doe'\n * });\n * \n * // Or login\n * const session = await client.auth.login({\n * email: 'user@example.com',\n * password: 'password123'\n * });\n * \n * // Get current user\n * const user = await client.auth.getCurrentUser();\n * ```\n */\nexport class InsForgeClient {\n private http: HttpClient;\n private tokenManager: TokenManager;\n \n /**\n * Authentication module\n */\n public readonly auth: Auth;\n\n constructor(config: InsForgeConfig = {}) {\n // Initialize HTTP client\n this.http = new HttpClient(config);\n \n // Initialize token manager with storage\n this.tokenManager = new TokenManager(config.storage);\n \n // Initialize auth module\n this.auth = new Auth(\n this.http,\n this.tokenManager\n );\n }\n\n\n /**\n * Set a custom API key for authentication\n * This is useful for server-to-server communication\n * \n * @param apiKey - The API key (should start with 'ik_')\n * \n * @example\n * ```typescript\n * client.setApiKey('ik_your_api_key_here');\n * ```\n */\n setApiKey(apiKey: string): void {\n // API keys can be used as Bearer tokens\n this.http.setAuthToken(apiKey);\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":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/types.ts","../src/lib/http-client.ts","../src/lib/token-manager.ts","../src/modules/auth.ts","../src/modules/database.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 and types\nexport { Database, QueryBuilder } from './modules/database';\nexport type { DatabaseResponse } from './modules/database';\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 URL of the InsForge backend API\n * @default \"http://localhost:7130\"\n */\n url?: string;\n\n /**\n * API key (optional)\n * Can be used for server-side operations or specific use cases\n */\n apiKey?: 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 private baseUrl: string;\n private fetch: typeof fetch;\n private defaultHeaders: Record<string, string>;\n\n constructor(config: InsForgeConfig) {\n this.baseUrl = config.url || '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.defaultHeaders = {\n 'Content-Type': 'application/json',\n ...config.headers,\n };\n \n // Add API key if provided\n if (config.apiKey) {\n this.defaultHeaders['Authorization'] = `Bearer ${config.apiKey}`;\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 url.searchParams.append(key, value);\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 response = await this.fetch(url, {\n method,\n headers: {\n ...this.defaultHeaders,\n ...headers,\n },\n body: body ? JSON.stringify(body) : undefined,\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 if (contentType?.includes('application/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 if (token) {\n this.defaultHeaders['Authorization'] = `Bearer ${token}`;\n } else {\n delete this.defaultHeaders['Authorization'];\n }\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 * 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';\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 constructor(\n private http: HttpClient,\n private tokenManager: TokenManager\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 from the API\n * Returns exactly what the backend returns: {id, email, role}\n */\n async getCurrentUser(): Promise<{\n data: GetCurrentSessionResponse | null;\n error: InsForgeError | 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\n this.http.setAuthToken(session.accessToken);\n const response = await this.http.get<GetCurrentSessionResponse>('/api/auth/sessions/current');\n \n return {\n data: response,\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 the stored session (no API call)\n */\n async getSession(): Promise<{\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 * Database module for InsForge SDK\n * Supabase-style query builder for PostgREST operations\n */\n\nimport { HttpClient } from '../lib/http-client';\nimport { InsForgeError } from '../types';\n\nexport interface DatabaseResponse<T> {\n data: T | null;\n error: InsForgeError | null;\n count?: number;\n}\n\n/**\n * Query builder for database operations\n * Uses method chaining like Supabase\n */\nexport class QueryBuilder<T = any> {\n private method: 'GET' | 'POST' | 'PATCH' | 'DELETE' = 'GET';\n private headers: Record<string, string> = {};\n private queryParams: Record<string, string> = {};\n private body?: any;\n\n constructor(\n private table: string,\n private http: HttpClient\n ) {}\n\n /**\n * Perform a SELECT query\n * @param columns - Columns to select (default: '*')\n * @example\n * .select('*')\n * .select('id, title, content')\n * .select('*, user:user_id(name, email)') // Foreign key expansion\n */\n select(columns: string = '*'): this {\n this.method = 'GET';\n if (columns !== '*') {\n this.queryParams.select = columns;\n }\n return this;\n }\n\n /**\n * Perform an INSERT\n * @param values - Single object or array of objects\n * @param options - { upsert: true } for upsert behavior\n * @example\n * .insert({ title: 'Hello', content: 'World' })\n * .insert([{ title: 'Post 1' }, { title: 'Post 2' }])\n */\n insert(values: Partial<T> | Partial<T>[], options?: { upsert?: boolean }): this {\n this.method = 'POST';\n this.body = Array.isArray(values) ? values : [values];\n \n if (options?.upsert) {\n this.headers['Prefer'] = 'resolution=merge-duplicates,return=representation';\n } else {\n this.headers['Prefer'] = 'return=representation';\n }\n \n return this;\n }\n\n /**\n * Perform an UPDATE\n * @param values - Object with fields to update\n * @example\n * .update({ title: 'Updated Title' })\n */\n update(values: Partial<T>): this {\n this.method = 'PATCH';\n this.body = values;\n this.headers['Prefer'] = 'return=representation';\n return this;\n }\n\n /**\n * Perform a DELETE\n * @example\n * .delete()\n */\n delete(): this {\n this.method = 'DELETE';\n this.headers['Prefer'] = 'return=representation';\n return this;\n }\n\n /**\n * Perform an UPSERT\n * @param values - Single object or array of objects\n * @example\n * .upsert({ id: 1, title: 'Hello' })\n */\n upsert(values: Partial<T> | Partial<T>[]): this {\n return this.insert(values, { upsert: true });\n }\n\n // FILTERS\n\n /**\n * Filter by column equal to value\n * @example .eq('id', 123)\n */\n eq(column: string, value: any): this {\n this.queryParams[column] = `eq.${value}`;\n return this;\n }\n\n /**\n * Filter by column not equal to value\n * @example .neq('status', 'draft')\n */\n neq(column: string, value: any): this {\n this.queryParams[column] = `neq.${value}`;\n return this;\n }\n\n /**\n * Filter by column greater than value\n * @example .gt('age', 18)\n */\n gt(column: string, value: any): this {\n this.queryParams[column] = `gt.${value}`;\n return this;\n }\n\n /**\n * Filter by column greater than or equal to value\n * @example .gte('price', 100)\n */\n gte(column: string, value: any): this {\n this.queryParams[column] = `gte.${value}`;\n return this;\n }\n\n /**\n * Filter by column less than value\n * @example .lt('stock', 10)\n */\n lt(column: string, value: any): this {\n this.queryParams[column] = `lt.${value}`;\n return this;\n }\n\n /**\n * Filter by column less than or equal to value\n * @example .lte('discount', 50)\n */\n lte(column: string, value: any): this {\n this.queryParams[column] = `lte.${value}`;\n return this;\n }\n\n /**\n * Filter by pattern matching (case-sensitive)\n * @example .like('email', '%@gmail.com')\n */\n like(column: string, pattern: string): this {\n this.queryParams[column] = `like.${pattern}`;\n return this;\n }\n\n /**\n * Filter by pattern matching (case-insensitive)\n * @example .ilike('name', '%john%')\n */\n ilike(column: string, pattern: string): this {\n this.queryParams[column] = `ilike.${pattern}`;\n return this;\n }\n\n /**\n * Filter by checking if column is a value\n * @example .is('deleted_at', null)\n */\n is(column: string, value: null | boolean): this {\n if (value === null) {\n this.queryParams[column] = 'is.null';\n } else {\n this.queryParams[column] = `is.${value}`;\n }\n return this;\n }\n\n /**\n * Filter by checking if value is in array\n * @example .in('status', ['active', 'pending'])\n */\n in(column: string, values: any[]): this {\n this.queryParams[column] = `in.(${values.join(',')})`;\n return this;\n }\n\n // MODIFIERS\n\n /**\n * Order by column\n * @example \n * .order('created_at') // ascending\n * .order('created_at', { ascending: false }) // descending\n */\n order(column: string, options?: { ascending?: boolean }): this {\n const ascending = options?.ascending !== false;\n this.queryParams.order = ascending ? column : `${column}.desc`;\n return this;\n }\n\n /**\n * Limit the number of rows returned\n * @example .limit(10)\n */\n limit(count: number): this {\n this.queryParams.limit = count.toString();\n return this;\n }\n\n /**\n * Return results from an offset\n * @example .offset(20)\n */\n offset(count: number): this {\n this.queryParams.offset = count.toString();\n return this;\n }\n\n /**\n * Set a range of rows to return\n * @example .range(0, 9) // First 10 rows\n */\n range(from: number, to: number): this {\n this.headers['Range'] = `${from}-${to}`;\n return this;\n }\n\n /**\n * Return a single object instead of array\n * @example .single()\n */\n single(): this {\n this.headers['Accept'] = 'application/vnd.pgrst.object+json';\n return this;\n }\n\n /**\n * Get the total count (use with select)\n * @example .select('*', { count: 'exact' })\n */\n count(algorithm: 'exact' | 'planned' | 'estimated' = 'exact'): this {\n const prefer = this.headers['Prefer'] || '';\n this.headers['Prefer'] = prefer ? `${prefer},count=${algorithm}` : `count=${algorithm}`;\n return this;\n }\n\n /**\n * Execute the query and return results\n */\n async execute(): Promise<DatabaseResponse<T>> {\n try {\n const path = `/api/database/records/${this.table}`;\n let response: any;\n\n switch (this.method) {\n case 'GET':\n response = await this.http.get<T>(path, {\n params: this.queryParams,\n headers: this.headers\n });\n break;\n \n case 'POST':\n response = await this.http.post<T>(path, this.body, {\n params: this.queryParams,\n headers: this.headers\n });\n break;\n \n case 'PATCH':\n response = await this.http.patch<T>(path, this.body, {\n params: this.queryParams,\n headers: this.headers\n });\n break;\n \n case 'DELETE':\n response = await this.http.delete<T>(path, {\n params: this.queryParams,\n headers: this.headers\n });\n break;\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 'Database operation failed',\n 500,\n 'DATABASE_ERROR'\n )\n };\n }\n }\n\n /**\n * Make QueryBuilder thenable for async/await\n */\n then<TResult1 = DatabaseResponse<T>, TResult2 = never>(\n onfulfilled?: ((value: DatabaseResponse<T>) => TResult1 | PromiseLike<TResult1>) | undefined | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null\n ): Promise<TResult1 | TResult2> {\n return this.execute().then(onfulfilled, onrejected);\n }\n}\n\n/**\n * Database client for InsForge SDK\n * Provides Supabase-style interface\n */\nexport class Database {\n constructor(private http: HttpClient) {}\n\n /**\n * Create a query builder for a table\n * @param table - The table name\n * @example\n * const { data, error } = await client.database\n * .from('posts')\n * .select('*')\n * .eq('user_id', userId)\n * .order('created_at', { ascending: false })\n * .limit(10);\n */\n from<T = any>(table: string): QueryBuilder<T> {\n return new QueryBuilder<T>(table, this.http);\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';\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\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);\n }\n\n\n /**\n * Set a custom API key for authentication\n * This is useful for server-to-server communication\n * \n * @param apiKey - The API key (should start with 'ik_')\n * \n * @example\n * ```typescript\n * client.setApiKey('ik_your_api_key_here');\n * ```\n */\n setApiKey(apiKey: string): void {\n // API keys can be used as Bearer tokens\n this.http.setAuthToken(apiKey);\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":[]}