@insforge/sdk 0.0.21 → 0.0.23
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 +39 -184
- package/dist/index.d.ts +39 -184
- package/dist/index.js +60 -302
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +60 -301
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -26,7 +26,6 @@ __export(index_exports, {
|
|
|
26
26
|
HttpClient: () => HttpClient,
|
|
27
27
|
InsForgeClient: () => InsForgeClient,
|
|
28
28
|
InsForgeError: () => InsForgeError,
|
|
29
|
-
QueryBuilder: () => QueryBuilder,
|
|
30
29
|
Storage: () => Storage,
|
|
31
30
|
StorageBucket: () => StorageBucket,
|
|
32
31
|
TokenManager: () => TokenManager,
|
|
@@ -62,9 +61,6 @@ var HttpClient = class {
|
|
|
62
61
|
this.defaultHeaders = {
|
|
63
62
|
...config.headers
|
|
64
63
|
};
|
|
65
|
-
if (config.apiKey) {
|
|
66
|
-
this.defaultHeaders["Authorization"] = `Bearer ${config.apiKey}`;
|
|
67
|
-
}
|
|
68
64
|
if (!this.fetch) {
|
|
69
65
|
throw new Error(
|
|
70
66
|
"Fetch is not available. Please provide a fetch implementation in the config."
|
|
@@ -209,294 +205,70 @@ var TokenManager = class {
|
|
|
209
205
|
}
|
|
210
206
|
};
|
|
211
207
|
|
|
212
|
-
// src/modules/database.ts
|
|
213
|
-
var
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
select(columns = "*") {
|
|
233
|
-
if (this.method !== "GET") {
|
|
234
|
-
const existingPrefer = this.headers["Prefer"] || "";
|
|
235
|
-
const preferParts = existingPrefer ? [existingPrefer] : [];
|
|
236
|
-
if (!preferParts.some((p) => p.includes("return="))) {
|
|
237
|
-
preferParts.push("return=representation");
|
|
238
|
-
}
|
|
239
|
-
this.headers["Prefer"] = preferParts.join(",");
|
|
240
|
-
}
|
|
241
|
-
if (this.method === "GET" && columns) {
|
|
242
|
-
this.queryParams.select = columns;
|
|
243
|
-
} else if (columns !== "*") {
|
|
244
|
-
this.queryParams.select = columns;
|
|
245
|
-
}
|
|
246
|
-
return this;
|
|
247
|
-
}
|
|
248
|
-
/**
|
|
249
|
-
* Perform an INSERT
|
|
250
|
-
* @param values - Single object or array of objects
|
|
251
|
-
* @param options - { upsert: true } for upsert behavior
|
|
252
|
-
* @example
|
|
253
|
-
* .insert({ title: 'Hello', content: 'World' }).select()
|
|
254
|
-
* .insert([{ title: 'Post 1' }, { title: 'Post 2' }]).select()
|
|
255
|
-
*/
|
|
256
|
-
insert(values, options) {
|
|
257
|
-
this.method = "POST";
|
|
258
|
-
this.body = Array.isArray(values) ? values : [values];
|
|
259
|
-
if (options?.upsert) {
|
|
260
|
-
this.headers["Prefer"] = "resolution=merge-duplicates";
|
|
261
|
-
}
|
|
262
|
-
return this;
|
|
263
|
-
}
|
|
264
|
-
/**
|
|
265
|
-
* Perform an UPDATE
|
|
266
|
-
* @param values - Object with fields to update
|
|
267
|
-
* @example
|
|
268
|
-
* .update({ title: 'Updated Title' }).select()
|
|
269
|
-
*/
|
|
270
|
-
update(values) {
|
|
271
|
-
this.method = "PATCH";
|
|
272
|
-
this.body = values;
|
|
273
|
-
return this;
|
|
274
|
-
}
|
|
275
|
-
/**
|
|
276
|
-
* Perform a DELETE
|
|
277
|
-
* @example
|
|
278
|
-
* .delete().select()
|
|
279
|
-
*/
|
|
280
|
-
delete() {
|
|
281
|
-
this.method = "DELETE";
|
|
282
|
-
return this;
|
|
283
|
-
}
|
|
284
|
-
/**
|
|
285
|
-
* Perform an UPSERT
|
|
286
|
-
* @param values - Single object or array of objects
|
|
287
|
-
* @example
|
|
288
|
-
* .upsert({ id: 1, title: 'Hello' })
|
|
289
|
-
*/
|
|
290
|
-
upsert(values) {
|
|
291
|
-
return this.insert(values, { upsert: true });
|
|
292
|
-
}
|
|
293
|
-
// FILTERS
|
|
294
|
-
/**
|
|
295
|
-
* Filter by column equal to value
|
|
296
|
-
* @example .eq('id', 123)
|
|
297
|
-
*/
|
|
298
|
-
eq(column, value) {
|
|
299
|
-
this.queryParams[column] = `eq.${value}`;
|
|
300
|
-
return this;
|
|
301
|
-
}
|
|
302
|
-
/**
|
|
303
|
-
* Filter by column not equal to value
|
|
304
|
-
* @example .neq('status', 'draft')
|
|
305
|
-
*/
|
|
306
|
-
neq(column, value) {
|
|
307
|
-
this.queryParams[column] = `neq.${value}`;
|
|
308
|
-
return this;
|
|
309
|
-
}
|
|
310
|
-
/**
|
|
311
|
-
* Filter by column greater than value
|
|
312
|
-
* @example .gt('age', 18)
|
|
313
|
-
*/
|
|
314
|
-
gt(column, value) {
|
|
315
|
-
this.queryParams[column] = `gt.${value}`;
|
|
316
|
-
return this;
|
|
317
|
-
}
|
|
318
|
-
/**
|
|
319
|
-
* Filter by column greater than or equal to value
|
|
320
|
-
* @example .gte('price', 100)
|
|
321
|
-
*/
|
|
322
|
-
gte(column, value) {
|
|
323
|
-
this.queryParams[column] = `gte.${value}`;
|
|
324
|
-
return this;
|
|
325
|
-
}
|
|
326
|
-
/**
|
|
327
|
-
* Filter by column less than value
|
|
328
|
-
* @example .lt('stock', 10)
|
|
329
|
-
*/
|
|
330
|
-
lt(column, value) {
|
|
331
|
-
this.queryParams[column] = `lt.${value}`;
|
|
332
|
-
return this;
|
|
333
|
-
}
|
|
334
|
-
/**
|
|
335
|
-
* Filter by column less than or equal to value
|
|
336
|
-
* @example .lte('discount', 50)
|
|
337
|
-
*/
|
|
338
|
-
lte(column, value) {
|
|
339
|
-
this.queryParams[column] = `lte.${value}`;
|
|
340
|
-
return this;
|
|
341
|
-
}
|
|
342
|
-
/**
|
|
343
|
-
* Filter by pattern matching (case-sensitive)
|
|
344
|
-
* @example .like('email', '%@gmail.com')
|
|
345
|
-
*/
|
|
346
|
-
like(column, pattern) {
|
|
347
|
-
this.queryParams[column] = `like.${pattern}`;
|
|
348
|
-
return this;
|
|
349
|
-
}
|
|
350
|
-
/**
|
|
351
|
-
* Filter by pattern matching (case-insensitive)
|
|
352
|
-
* @example .ilike('name', '%john%')
|
|
353
|
-
*/
|
|
354
|
-
ilike(column, pattern) {
|
|
355
|
-
this.queryParams[column] = `ilike.${pattern}`;
|
|
356
|
-
return this;
|
|
357
|
-
}
|
|
358
|
-
/**
|
|
359
|
-
* Filter by checking if column is a value
|
|
360
|
-
* @example .is('deleted_at', null)
|
|
361
|
-
*/
|
|
362
|
-
is(column, value) {
|
|
363
|
-
if (value === null) {
|
|
364
|
-
this.queryParams[column] = "is.null";
|
|
365
|
-
} else {
|
|
366
|
-
this.queryParams[column] = `is.${value}`;
|
|
367
|
-
}
|
|
368
|
-
return this;
|
|
369
|
-
}
|
|
370
|
-
/**
|
|
371
|
-
* Filter by checking if value is in array
|
|
372
|
-
* @example .in('status', ['active', 'pending'])
|
|
373
|
-
*/
|
|
374
|
-
in(column, values) {
|
|
375
|
-
this.queryParams[column] = `in.(${values.join(",")})`;
|
|
376
|
-
return this;
|
|
377
|
-
}
|
|
378
|
-
// MODIFIERS
|
|
379
|
-
/**
|
|
380
|
-
* Order by column
|
|
381
|
-
* @example
|
|
382
|
-
* .order('created_at') // ascending
|
|
383
|
-
* .order('created_at', { ascending: false }) // descending
|
|
384
|
-
*/
|
|
385
|
-
order(column, options) {
|
|
386
|
-
const ascending = options?.ascending !== false;
|
|
387
|
-
this.queryParams.order = ascending ? column : `${column}.desc`;
|
|
388
|
-
return this;
|
|
389
|
-
}
|
|
390
|
-
/**
|
|
391
|
-
* Limit the number of rows returned
|
|
392
|
-
* @example .limit(10)
|
|
393
|
-
*/
|
|
394
|
-
limit(count) {
|
|
395
|
-
this.queryParams.limit = count.toString();
|
|
396
|
-
return this;
|
|
397
|
-
}
|
|
398
|
-
/**
|
|
399
|
-
* Return results from an offset
|
|
400
|
-
* @example .offset(20)
|
|
401
|
-
*/
|
|
402
|
-
offset(count) {
|
|
403
|
-
this.queryParams.offset = count.toString();
|
|
404
|
-
return this;
|
|
405
|
-
}
|
|
406
|
-
/**
|
|
407
|
-
* Set a range of rows to return
|
|
408
|
-
* @example .range(0, 9) // First 10 rows
|
|
409
|
-
*/
|
|
410
|
-
range(from, to) {
|
|
411
|
-
this.headers["Range"] = `${from}-${to}`;
|
|
412
|
-
return this;
|
|
413
|
-
}
|
|
414
|
-
/**
|
|
415
|
-
* Return a single object instead of array
|
|
416
|
-
* @example .single()
|
|
417
|
-
*/
|
|
418
|
-
single() {
|
|
419
|
-
this.headers["Accept"] = "application/vnd.pgrst.object+json";
|
|
420
|
-
return this;
|
|
421
|
-
}
|
|
422
|
-
/**
|
|
423
|
-
* Get the total count (use with select)
|
|
424
|
-
* @example .select('*', { count: 'exact' })
|
|
425
|
-
*/
|
|
426
|
-
count(algorithm = "exact") {
|
|
427
|
-
const prefer = this.headers["Prefer"] || "";
|
|
428
|
-
this.headers["Prefer"] = prefer ? `${prefer},count=${algorithm}` : `count=${algorithm}`;
|
|
429
|
-
return this;
|
|
430
|
-
}
|
|
431
|
-
/**
|
|
432
|
-
* Execute the query and return results
|
|
433
|
-
*/
|
|
434
|
-
async execute() {
|
|
435
|
-
try {
|
|
436
|
-
const path = `/api/database/records/${this.table}`;
|
|
437
|
-
let response;
|
|
438
|
-
switch (this.method) {
|
|
439
|
-
case "GET":
|
|
440
|
-
response = await this.http.get(path, {
|
|
441
|
-
params: this.queryParams,
|
|
442
|
-
headers: this.headers
|
|
443
|
-
});
|
|
444
|
-
break;
|
|
445
|
-
case "POST":
|
|
446
|
-
response = await this.http.post(path, this.body, {
|
|
447
|
-
params: this.queryParams,
|
|
448
|
-
headers: this.headers
|
|
449
|
-
});
|
|
450
|
-
break;
|
|
451
|
-
case "PATCH":
|
|
452
|
-
response = await this.http.patch(path, this.body, {
|
|
453
|
-
params: this.queryParams,
|
|
454
|
-
headers: this.headers
|
|
455
|
-
});
|
|
456
|
-
break;
|
|
457
|
-
case "DELETE":
|
|
458
|
-
response = await this.http.delete(path, {
|
|
459
|
-
params: this.queryParams,
|
|
460
|
-
headers: this.headers
|
|
461
|
-
});
|
|
462
|
-
break;
|
|
463
|
-
}
|
|
464
|
-
return { data: response, error: null };
|
|
465
|
-
} catch (error) {
|
|
466
|
-
return {
|
|
467
|
-
data: null,
|
|
468
|
-
error: error instanceof InsForgeError ? error : new InsForgeError(
|
|
469
|
-
"Database operation failed",
|
|
470
|
-
500,
|
|
471
|
-
"DATABASE_ERROR"
|
|
472
|
-
)
|
|
473
|
-
};
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
/**
|
|
477
|
-
* Make QueryBuilder thenable for async/await
|
|
478
|
-
*/
|
|
479
|
-
then(onfulfilled, onrejected) {
|
|
480
|
-
return this.execute().then(onfulfilled, onrejected);
|
|
481
|
-
}
|
|
482
|
-
};
|
|
208
|
+
// src/modules/database-postgrest.ts
|
|
209
|
+
var import_postgrest_js = require("@supabase/postgrest-js");
|
|
210
|
+
function createInsForgePostgrestFetch(httpClient, tokenManager) {
|
|
211
|
+
return async (input, init) => {
|
|
212
|
+
const url = typeof input === "string" ? input : input.toString();
|
|
213
|
+
const urlObj = new URL(url);
|
|
214
|
+
const tableName = urlObj.pathname.slice(1);
|
|
215
|
+
const insforgeUrl = `${httpClient.baseUrl}/api/database/records/${tableName}${urlObj.search}`;
|
|
216
|
+
const token = tokenManager.getAccessToken();
|
|
217
|
+
const headers = new Headers(init?.headers);
|
|
218
|
+
if (token && !headers.has("Authorization")) {
|
|
219
|
+
headers.set("Authorization", `Bearer ${token}`);
|
|
220
|
+
}
|
|
221
|
+
const response = await fetch(insforgeUrl, {
|
|
222
|
+
...init,
|
|
223
|
+
headers
|
|
224
|
+
});
|
|
225
|
+
return response;
|
|
226
|
+
};
|
|
227
|
+
}
|
|
483
228
|
var Database = class {
|
|
484
|
-
constructor(
|
|
485
|
-
this.
|
|
229
|
+
constructor(httpClient, tokenManager) {
|
|
230
|
+
this.postgrest = new import_postgrest_js.PostgrestClient("http://dummy", {
|
|
231
|
+
fetch: createInsForgePostgrestFetch(httpClient, tokenManager),
|
|
232
|
+
headers: {}
|
|
233
|
+
});
|
|
486
234
|
}
|
|
487
235
|
/**
|
|
488
236
|
* Create a query builder for a table
|
|
489
|
-
*
|
|
237
|
+
*
|
|
490
238
|
* @example
|
|
239
|
+
* // Basic query
|
|
491
240
|
* const { data, error } = await client.database
|
|
492
241
|
* .from('posts')
|
|
493
242
|
* .select('*')
|
|
494
|
-
* .eq('user_id', userId)
|
|
495
|
-
*
|
|
496
|
-
*
|
|
243
|
+
* .eq('user_id', userId);
|
|
244
|
+
*
|
|
245
|
+
* // With count (Supabase style!)
|
|
246
|
+
* const { data, error, count } = await client.database
|
|
247
|
+
* .from('posts')
|
|
248
|
+
* .select('*', { count: 'exact' })
|
|
249
|
+
* .range(0, 9);
|
|
250
|
+
*
|
|
251
|
+
* // Just get count, no data
|
|
252
|
+
* const { count } = await client.database
|
|
253
|
+
* .from('posts')
|
|
254
|
+
* .select('*', { count: 'exact', head: true });
|
|
255
|
+
*
|
|
256
|
+
* // Complex queries with OR
|
|
257
|
+
* const { data } = await client.database
|
|
258
|
+
* .from('posts')
|
|
259
|
+
* .select('*, users!inner(*)')
|
|
260
|
+
* .or('status.eq.active,status.eq.pending');
|
|
261
|
+
*
|
|
262
|
+
* // All features work:
|
|
263
|
+
* - Nested selects
|
|
264
|
+
* - Foreign key expansion
|
|
265
|
+
* - OR/AND/NOT conditions
|
|
266
|
+
* - Count with head
|
|
267
|
+
* - Range pagination
|
|
268
|
+
* - Upserts
|
|
497
269
|
*/
|
|
498
270
|
from(table) {
|
|
499
|
-
return
|
|
271
|
+
return this.postgrest.from(table);
|
|
500
272
|
}
|
|
501
273
|
};
|
|
502
274
|
|
|
@@ -505,7 +277,7 @@ var Auth = class {
|
|
|
505
277
|
constructor(http, tokenManager) {
|
|
506
278
|
this.http = http;
|
|
507
279
|
this.tokenManager = tokenManager;
|
|
508
|
-
this.database = new Database(http);
|
|
280
|
+
this.database = new Database(http, tokenManager);
|
|
509
281
|
this.detectOAuthCallback();
|
|
510
282
|
}
|
|
511
283
|
/**
|
|
@@ -676,7 +448,7 @@ var Auth = class {
|
|
|
676
448
|
this.http.setAuthToken(session.accessToken);
|
|
677
449
|
const authResponse = await this.http.get("/api/auth/sessions/current");
|
|
678
450
|
const { data: profile, error: profileError } = await this.database.from("users").select("*").eq("id", authResponse.user.id).single();
|
|
679
|
-
if (profileError && profileError.
|
|
451
|
+
if (profileError && profileError.code !== "PGRST116") {
|
|
680
452
|
return { data: null, error: profileError };
|
|
681
453
|
}
|
|
682
454
|
return {
|
|
@@ -710,7 +482,7 @@ var Auth = class {
|
|
|
710
482
|
*/
|
|
711
483
|
async getProfile(userId) {
|
|
712
484
|
const { data, error } = await this.database.from("users").select("*").eq("id", userId).single();
|
|
713
|
-
if (error && error.
|
|
485
|
+
if (error && error.code === "PGRST116") {
|
|
714
486
|
return { data: null, error: null };
|
|
715
487
|
}
|
|
716
488
|
return { data, error };
|
|
@@ -757,7 +529,8 @@ var Auth = class {
|
|
|
757
529
|
)
|
|
758
530
|
};
|
|
759
531
|
}
|
|
760
|
-
|
|
532
|
+
const { data, error } = await this.database.from("users").update(profile).eq("id", session.user.id).select().single();
|
|
533
|
+
return { data, error };
|
|
761
534
|
}
|
|
762
535
|
};
|
|
763
536
|
|
|
@@ -1073,24 +846,10 @@ var InsForgeClient = class {
|
|
|
1073
846
|
this.http,
|
|
1074
847
|
this.tokenManager
|
|
1075
848
|
);
|
|
1076
|
-
this.database = new Database(this.http);
|
|
849
|
+
this.database = new Database(this.http, this.tokenManager);
|
|
1077
850
|
this.storage = new Storage(this.http);
|
|
1078
851
|
this.ai = new AI(this.http);
|
|
1079
852
|
}
|
|
1080
|
-
/**
|
|
1081
|
-
* Set a custom API key for authentication
|
|
1082
|
-
* This is useful for server-to-server communication
|
|
1083
|
-
*
|
|
1084
|
-
* @param apiKey - The API key (should start with 'ik_')
|
|
1085
|
-
*
|
|
1086
|
-
* @example
|
|
1087
|
-
* ```typescript
|
|
1088
|
-
* client.setApiKey('ik_your_api_key_here');
|
|
1089
|
-
* ```
|
|
1090
|
-
*/
|
|
1091
|
-
setApiKey(apiKey) {
|
|
1092
|
-
this.http.setAuthToken(apiKey);
|
|
1093
|
-
}
|
|
1094
853
|
/**
|
|
1095
854
|
* Get the underlying HTTP client for custom requests
|
|
1096
855
|
*
|
|
@@ -1126,7 +885,6 @@ var index_default = InsForgeClient;
|
|
|
1126
885
|
HttpClient,
|
|
1127
886
|
InsForgeClient,
|
|
1128
887
|
InsForgeError,
|
|
1129
|
-
QueryBuilder,
|
|
1130
888
|
Storage,
|
|
1131
889
|
StorageBucket,
|
|
1132
890
|
TokenManager,
|