@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.mjs
CHANGED
|
@@ -25,9 +25,6 @@ var HttpClient = class {
|
|
|
25
25
|
this.defaultHeaders = {
|
|
26
26
|
...config.headers
|
|
27
27
|
};
|
|
28
|
-
if (config.apiKey) {
|
|
29
|
-
this.defaultHeaders["Authorization"] = `Bearer ${config.apiKey}`;
|
|
30
|
-
}
|
|
31
28
|
if (!this.fetch) {
|
|
32
29
|
throw new Error(
|
|
33
30
|
"Fetch is not available. Please provide a fetch implementation in the config."
|
|
@@ -172,294 +169,70 @@ var TokenManager = class {
|
|
|
172
169
|
}
|
|
173
170
|
};
|
|
174
171
|
|
|
175
|
-
// src/modules/database.ts
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
select(columns = "*") {
|
|
196
|
-
if (this.method !== "GET") {
|
|
197
|
-
const existingPrefer = this.headers["Prefer"] || "";
|
|
198
|
-
const preferParts = existingPrefer ? [existingPrefer] : [];
|
|
199
|
-
if (!preferParts.some((p) => p.includes("return="))) {
|
|
200
|
-
preferParts.push("return=representation");
|
|
201
|
-
}
|
|
202
|
-
this.headers["Prefer"] = preferParts.join(",");
|
|
203
|
-
}
|
|
204
|
-
if (this.method === "GET" && columns) {
|
|
205
|
-
this.queryParams.select = columns;
|
|
206
|
-
} else if (columns !== "*") {
|
|
207
|
-
this.queryParams.select = columns;
|
|
208
|
-
}
|
|
209
|
-
return this;
|
|
210
|
-
}
|
|
211
|
-
/**
|
|
212
|
-
* Perform an INSERT
|
|
213
|
-
* @param values - Single object or array of objects
|
|
214
|
-
* @param options - { upsert: true } for upsert behavior
|
|
215
|
-
* @example
|
|
216
|
-
* .insert({ title: 'Hello', content: 'World' }).select()
|
|
217
|
-
* .insert([{ title: 'Post 1' }, { title: 'Post 2' }]).select()
|
|
218
|
-
*/
|
|
219
|
-
insert(values, options) {
|
|
220
|
-
this.method = "POST";
|
|
221
|
-
this.body = Array.isArray(values) ? values : [values];
|
|
222
|
-
if (options?.upsert) {
|
|
223
|
-
this.headers["Prefer"] = "resolution=merge-duplicates";
|
|
224
|
-
}
|
|
225
|
-
return this;
|
|
226
|
-
}
|
|
227
|
-
/**
|
|
228
|
-
* Perform an UPDATE
|
|
229
|
-
* @param values - Object with fields to update
|
|
230
|
-
* @example
|
|
231
|
-
* .update({ title: 'Updated Title' }).select()
|
|
232
|
-
*/
|
|
233
|
-
update(values) {
|
|
234
|
-
this.method = "PATCH";
|
|
235
|
-
this.body = values;
|
|
236
|
-
return this;
|
|
237
|
-
}
|
|
238
|
-
/**
|
|
239
|
-
* Perform a DELETE
|
|
240
|
-
* @example
|
|
241
|
-
* .delete().select()
|
|
242
|
-
*/
|
|
243
|
-
delete() {
|
|
244
|
-
this.method = "DELETE";
|
|
245
|
-
return this;
|
|
246
|
-
}
|
|
247
|
-
/**
|
|
248
|
-
* Perform an UPSERT
|
|
249
|
-
* @param values - Single object or array of objects
|
|
250
|
-
* @example
|
|
251
|
-
* .upsert({ id: 1, title: 'Hello' })
|
|
252
|
-
*/
|
|
253
|
-
upsert(values) {
|
|
254
|
-
return this.insert(values, { upsert: true });
|
|
255
|
-
}
|
|
256
|
-
// FILTERS
|
|
257
|
-
/**
|
|
258
|
-
* Filter by column equal to value
|
|
259
|
-
* @example .eq('id', 123)
|
|
260
|
-
*/
|
|
261
|
-
eq(column, value) {
|
|
262
|
-
this.queryParams[column] = `eq.${value}`;
|
|
263
|
-
return this;
|
|
264
|
-
}
|
|
265
|
-
/**
|
|
266
|
-
* Filter by column not equal to value
|
|
267
|
-
* @example .neq('status', 'draft')
|
|
268
|
-
*/
|
|
269
|
-
neq(column, value) {
|
|
270
|
-
this.queryParams[column] = `neq.${value}`;
|
|
271
|
-
return this;
|
|
272
|
-
}
|
|
273
|
-
/**
|
|
274
|
-
* Filter by column greater than value
|
|
275
|
-
* @example .gt('age', 18)
|
|
276
|
-
*/
|
|
277
|
-
gt(column, value) {
|
|
278
|
-
this.queryParams[column] = `gt.${value}`;
|
|
279
|
-
return this;
|
|
280
|
-
}
|
|
281
|
-
/**
|
|
282
|
-
* Filter by column greater than or equal to value
|
|
283
|
-
* @example .gte('price', 100)
|
|
284
|
-
*/
|
|
285
|
-
gte(column, value) {
|
|
286
|
-
this.queryParams[column] = `gte.${value}`;
|
|
287
|
-
return this;
|
|
288
|
-
}
|
|
289
|
-
/**
|
|
290
|
-
* Filter by column less than value
|
|
291
|
-
* @example .lt('stock', 10)
|
|
292
|
-
*/
|
|
293
|
-
lt(column, value) {
|
|
294
|
-
this.queryParams[column] = `lt.${value}`;
|
|
295
|
-
return this;
|
|
296
|
-
}
|
|
297
|
-
/**
|
|
298
|
-
* Filter by column less than or equal to value
|
|
299
|
-
* @example .lte('discount', 50)
|
|
300
|
-
*/
|
|
301
|
-
lte(column, value) {
|
|
302
|
-
this.queryParams[column] = `lte.${value}`;
|
|
303
|
-
return this;
|
|
304
|
-
}
|
|
305
|
-
/**
|
|
306
|
-
* Filter by pattern matching (case-sensitive)
|
|
307
|
-
* @example .like('email', '%@gmail.com')
|
|
308
|
-
*/
|
|
309
|
-
like(column, pattern) {
|
|
310
|
-
this.queryParams[column] = `like.${pattern}`;
|
|
311
|
-
return this;
|
|
312
|
-
}
|
|
313
|
-
/**
|
|
314
|
-
* Filter by pattern matching (case-insensitive)
|
|
315
|
-
* @example .ilike('name', '%john%')
|
|
316
|
-
*/
|
|
317
|
-
ilike(column, pattern) {
|
|
318
|
-
this.queryParams[column] = `ilike.${pattern}`;
|
|
319
|
-
return this;
|
|
320
|
-
}
|
|
321
|
-
/**
|
|
322
|
-
* Filter by checking if column is a value
|
|
323
|
-
* @example .is('deleted_at', null)
|
|
324
|
-
*/
|
|
325
|
-
is(column, value) {
|
|
326
|
-
if (value === null) {
|
|
327
|
-
this.queryParams[column] = "is.null";
|
|
328
|
-
} else {
|
|
329
|
-
this.queryParams[column] = `is.${value}`;
|
|
330
|
-
}
|
|
331
|
-
return this;
|
|
332
|
-
}
|
|
333
|
-
/**
|
|
334
|
-
* Filter by checking if value is in array
|
|
335
|
-
* @example .in('status', ['active', 'pending'])
|
|
336
|
-
*/
|
|
337
|
-
in(column, values) {
|
|
338
|
-
this.queryParams[column] = `in.(${values.join(",")})`;
|
|
339
|
-
return this;
|
|
340
|
-
}
|
|
341
|
-
// MODIFIERS
|
|
342
|
-
/**
|
|
343
|
-
* Order by column
|
|
344
|
-
* @example
|
|
345
|
-
* .order('created_at') // ascending
|
|
346
|
-
* .order('created_at', { ascending: false }) // descending
|
|
347
|
-
*/
|
|
348
|
-
order(column, options) {
|
|
349
|
-
const ascending = options?.ascending !== false;
|
|
350
|
-
this.queryParams.order = ascending ? column : `${column}.desc`;
|
|
351
|
-
return this;
|
|
352
|
-
}
|
|
353
|
-
/**
|
|
354
|
-
* Limit the number of rows returned
|
|
355
|
-
* @example .limit(10)
|
|
356
|
-
*/
|
|
357
|
-
limit(count) {
|
|
358
|
-
this.queryParams.limit = count.toString();
|
|
359
|
-
return this;
|
|
360
|
-
}
|
|
361
|
-
/**
|
|
362
|
-
* Return results from an offset
|
|
363
|
-
* @example .offset(20)
|
|
364
|
-
*/
|
|
365
|
-
offset(count) {
|
|
366
|
-
this.queryParams.offset = count.toString();
|
|
367
|
-
return this;
|
|
368
|
-
}
|
|
369
|
-
/**
|
|
370
|
-
* Set a range of rows to return
|
|
371
|
-
* @example .range(0, 9) // First 10 rows
|
|
372
|
-
*/
|
|
373
|
-
range(from, to) {
|
|
374
|
-
this.headers["Range"] = `${from}-${to}`;
|
|
375
|
-
return this;
|
|
376
|
-
}
|
|
377
|
-
/**
|
|
378
|
-
* Return a single object instead of array
|
|
379
|
-
* @example .single()
|
|
380
|
-
*/
|
|
381
|
-
single() {
|
|
382
|
-
this.headers["Accept"] = "application/vnd.pgrst.object+json";
|
|
383
|
-
return this;
|
|
384
|
-
}
|
|
385
|
-
/**
|
|
386
|
-
* Get the total count (use with select)
|
|
387
|
-
* @example .select('*', { count: 'exact' })
|
|
388
|
-
*/
|
|
389
|
-
count(algorithm = "exact") {
|
|
390
|
-
const prefer = this.headers["Prefer"] || "";
|
|
391
|
-
this.headers["Prefer"] = prefer ? `${prefer},count=${algorithm}` : `count=${algorithm}`;
|
|
392
|
-
return this;
|
|
393
|
-
}
|
|
394
|
-
/**
|
|
395
|
-
* Execute the query and return results
|
|
396
|
-
*/
|
|
397
|
-
async execute() {
|
|
398
|
-
try {
|
|
399
|
-
const path = `/api/database/records/${this.table}`;
|
|
400
|
-
let response;
|
|
401
|
-
switch (this.method) {
|
|
402
|
-
case "GET":
|
|
403
|
-
response = await this.http.get(path, {
|
|
404
|
-
params: this.queryParams,
|
|
405
|
-
headers: this.headers
|
|
406
|
-
});
|
|
407
|
-
break;
|
|
408
|
-
case "POST":
|
|
409
|
-
response = await this.http.post(path, this.body, {
|
|
410
|
-
params: this.queryParams,
|
|
411
|
-
headers: this.headers
|
|
412
|
-
});
|
|
413
|
-
break;
|
|
414
|
-
case "PATCH":
|
|
415
|
-
response = await this.http.patch(path, this.body, {
|
|
416
|
-
params: this.queryParams,
|
|
417
|
-
headers: this.headers
|
|
418
|
-
});
|
|
419
|
-
break;
|
|
420
|
-
case "DELETE":
|
|
421
|
-
response = await this.http.delete(path, {
|
|
422
|
-
params: this.queryParams,
|
|
423
|
-
headers: this.headers
|
|
424
|
-
});
|
|
425
|
-
break;
|
|
426
|
-
}
|
|
427
|
-
return { data: response, error: null };
|
|
428
|
-
} catch (error) {
|
|
429
|
-
return {
|
|
430
|
-
data: null,
|
|
431
|
-
error: error instanceof InsForgeError ? error : new InsForgeError(
|
|
432
|
-
"Database operation failed",
|
|
433
|
-
500,
|
|
434
|
-
"DATABASE_ERROR"
|
|
435
|
-
)
|
|
436
|
-
};
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
/**
|
|
440
|
-
* Make QueryBuilder thenable for async/await
|
|
441
|
-
*/
|
|
442
|
-
then(onfulfilled, onrejected) {
|
|
443
|
-
return this.execute().then(onfulfilled, onrejected);
|
|
444
|
-
}
|
|
445
|
-
};
|
|
172
|
+
// src/modules/database-postgrest.ts
|
|
173
|
+
import { PostgrestClient } from "@supabase/postgrest-js";
|
|
174
|
+
function createInsForgePostgrestFetch(httpClient, tokenManager) {
|
|
175
|
+
return async (input, init) => {
|
|
176
|
+
const url = typeof input === "string" ? input : input.toString();
|
|
177
|
+
const urlObj = new URL(url);
|
|
178
|
+
const tableName = urlObj.pathname.slice(1);
|
|
179
|
+
const insforgeUrl = `${httpClient.baseUrl}/api/database/records/${tableName}${urlObj.search}`;
|
|
180
|
+
const token = tokenManager.getAccessToken();
|
|
181
|
+
const headers = new Headers(init?.headers);
|
|
182
|
+
if (token && !headers.has("Authorization")) {
|
|
183
|
+
headers.set("Authorization", `Bearer ${token}`);
|
|
184
|
+
}
|
|
185
|
+
const response = await fetch(insforgeUrl, {
|
|
186
|
+
...init,
|
|
187
|
+
headers
|
|
188
|
+
});
|
|
189
|
+
return response;
|
|
190
|
+
};
|
|
191
|
+
}
|
|
446
192
|
var Database = class {
|
|
447
|
-
constructor(
|
|
448
|
-
this.
|
|
193
|
+
constructor(httpClient, tokenManager) {
|
|
194
|
+
this.postgrest = new PostgrestClient("http://dummy", {
|
|
195
|
+
fetch: createInsForgePostgrestFetch(httpClient, tokenManager),
|
|
196
|
+
headers: {}
|
|
197
|
+
});
|
|
449
198
|
}
|
|
450
199
|
/**
|
|
451
200
|
* Create a query builder for a table
|
|
452
|
-
*
|
|
201
|
+
*
|
|
453
202
|
* @example
|
|
203
|
+
* // Basic query
|
|
454
204
|
* const { data, error } = await client.database
|
|
455
205
|
* .from('posts')
|
|
456
206
|
* .select('*')
|
|
457
|
-
* .eq('user_id', userId)
|
|
458
|
-
*
|
|
459
|
-
*
|
|
207
|
+
* .eq('user_id', userId);
|
|
208
|
+
*
|
|
209
|
+
* // With count (Supabase style!)
|
|
210
|
+
* const { data, error, count } = await client.database
|
|
211
|
+
* .from('posts')
|
|
212
|
+
* .select('*', { count: 'exact' })
|
|
213
|
+
* .range(0, 9);
|
|
214
|
+
*
|
|
215
|
+
* // Just get count, no data
|
|
216
|
+
* const { count } = await client.database
|
|
217
|
+
* .from('posts')
|
|
218
|
+
* .select('*', { count: 'exact', head: true });
|
|
219
|
+
*
|
|
220
|
+
* // Complex queries with OR
|
|
221
|
+
* const { data } = await client.database
|
|
222
|
+
* .from('posts')
|
|
223
|
+
* .select('*, users!inner(*)')
|
|
224
|
+
* .or('status.eq.active,status.eq.pending');
|
|
225
|
+
*
|
|
226
|
+
* // All features work:
|
|
227
|
+
* - Nested selects
|
|
228
|
+
* - Foreign key expansion
|
|
229
|
+
* - OR/AND/NOT conditions
|
|
230
|
+
* - Count with head
|
|
231
|
+
* - Range pagination
|
|
232
|
+
* - Upserts
|
|
460
233
|
*/
|
|
461
234
|
from(table) {
|
|
462
|
-
return
|
|
235
|
+
return this.postgrest.from(table);
|
|
463
236
|
}
|
|
464
237
|
};
|
|
465
238
|
|
|
@@ -468,7 +241,7 @@ var Auth = class {
|
|
|
468
241
|
constructor(http, tokenManager) {
|
|
469
242
|
this.http = http;
|
|
470
243
|
this.tokenManager = tokenManager;
|
|
471
|
-
this.database = new Database(http);
|
|
244
|
+
this.database = new Database(http, tokenManager);
|
|
472
245
|
this.detectOAuthCallback();
|
|
473
246
|
}
|
|
474
247
|
/**
|
|
@@ -639,7 +412,7 @@ var Auth = class {
|
|
|
639
412
|
this.http.setAuthToken(session.accessToken);
|
|
640
413
|
const authResponse = await this.http.get("/api/auth/sessions/current");
|
|
641
414
|
const { data: profile, error: profileError } = await this.database.from("users").select("*").eq("id", authResponse.user.id).single();
|
|
642
|
-
if (profileError && profileError.
|
|
415
|
+
if (profileError && profileError.code !== "PGRST116") {
|
|
643
416
|
return { data: null, error: profileError };
|
|
644
417
|
}
|
|
645
418
|
return {
|
|
@@ -673,7 +446,7 @@ var Auth = class {
|
|
|
673
446
|
*/
|
|
674
447
|
async getProfile(userId) {
|
|
675
448
|
const { data, error } = await this.database.from("users").select("*").eq("id", userId).single();
|
|
676
|
-
if (error && error.
|
|
449
|
+
if (error && error.code === "PGRST116") {
|
|
677
450
|
return { data: null, error: null };
|
|
678
451
|
}
|
|
679
452
|
return { data, error };
|
|
@@ -720,7 +493,8 @@ var Auth = class {
|
|
|
720
493
|
)
|
|
721
494
|
};
|
|
722
495
|
}
|
|
723
|
-
|
|
496
|
+
const { data, error } = await this.database.from("users").update(profile).eq("id", session.user.id).select().single();
|
|
497
|
+
return { data, error };
|
|
724
498
|
}
|
|
725
499
|
};
|
|
726
500
|
|
|
@@ -1036,24 +810,10 @@ var InsForgeClient = class {
|
|
|
1036
810
|
this.http,
|
|
1037
811
|
this.tokenManager
|
|
1038
812
|
);
|
|
1039
|
-
this.database = new Database(this.http);
|
|
813
|
+
this.database = new Database(this.http, this.tokenManager);
|
|
1040
814
|
this.storage = new Storage(this.http);
|
|
1041
815
|
this.ai = new AI(this.http);
|
|
1042
816
|
}
|
|
1043
|
-
/**
|
|
1044
|
-
* Set a custom API key for authentication
|
|
1045
|
-
* This is useful for server-to-server communication
|
|
1046
|
-
*
|
|
1047
|
-
* @param apiKey - The API key (should start with 'ik_')
|
|
1048
|
-
*
|
|
1049
|
-
* @example
|
|
1050
|
-
* ```typescript
|
|
1051
|
-
* client.setApiKey('ik_your_api_key_here');
|
|
1052
|
-
* ```
|
|
1053
|
-
*/
|
|
1054
|
-
setApiKey(apiKey) {
|
|
1055
|
-
this.http.setAuthToken(apiKey);
|
|
1056
|
-
}
|
|
1057
817
|
/**
|
|
1058
818
|
* Get the underlying HTTP client for custom requests
|
|
1059
819
|
*
|
|
@@ -1088,7 +848,6 @@ export {
|
|
|
1088
848
|
HttpClient,
|
|
1089
849
|
InsForgeClient,
|
|
1090
850
|
InsForgeError,
|
|
1091
|
-
QueryBuilder,
|
|
1092
851
|
Storage,
|
|
1093
852
|
StorageBucket,
|
|
1094
853
|
TokenManager,
|