@ragable/sdk 0.0.3 → 0.4.0
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 +383 -1
- package/dist/index.d.ts +383 -1
- package/dist/index.js +769 -57
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +752 -56
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -223,6 +223,74 @@ function toArrayBuffer(value) {
|
|
|
223
223
|
return copy.buffer;
|
|
224
224
|
}
|
|
225
225
|
|
|
226
|
+
// src/sse.ts
|
|
227
|
+
async function parseMaybeJsonBody(response) {
|
|
228
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
229
|
+
if (contentType.includes("application/json")) {
|
|
230
|
+
try {
|
|
231
|
+
return await response.json();
|
|
232
|
+
} catch {
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
try {
|
|
237
|
+
return await response.text();
|
|
238
|
+
} catch {
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
function parseSseDataLine(line) {
|
|
243
|
+
const dataPrefix = "data: ";
|
|
244
|
+
if (!line.startsWith(dataPrefix)) {
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
const json = line.slice(dataPrefix.length).trim();
|
|
248
|
+
if (json.length === 0 || json === "[DONE]") {
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
try {
|
|
252
|
+
return JSON.parse(json);
|
|
253
|
+
} catch {
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
async function* readSseStream(body) {
|
|
258
|
+
const reader = body.getReader();
|
|
259
|
+
const decoder = new TextDecoder();
|
|
260
|
+
let buffer = "";
|
|
261
|
+
try {
|
|
262
|
+
while (true) {
|
|
263
|
+
const { done, value } = await reader.read();
|
|
264
|
+
if (done) {
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
267
|
+
buffer += decoder.decode(value, { stream: true });
|
|
268
|
+
let boundary = buffer.indexOf("\n\n");
|
|
269
|
+
while (boundary !== -1) {
|
|
270
|
+
const block = buffer.slice(0, boundary);
|
|
271
|
+
buffer = buffer.slice(boundary + 2);
|
|
272
|
+
for (const line of block.split("\n")) {
|
|
273
|
+
const evt = parseSseDataLine(line);
|
|
274
|
+
if (evt) {
|
|
275
|
+
yield evt;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
boundary = buffer.indexOf("\n\n");
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
if (buffer.trim().length > 0) {
|
|
282
|
+
for (const line of buffer.split("\n")) {
|
|
283
|
+
const evt = parseSseDataLine(line);
|
|
284
|
+
if (evt) {
|
|
285
|
+
yield evt;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
} finally {
|
|
290
|
+
reader.releaseLock();
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
226
294
|
// src/agents.ts
|
|
227
295
|
var AgentsClient = class {
|
|
228
296
|
constructor(client) {
|
|
@@ -266,72 +334,655 @@ var AgentsClient = class {
|
|
|
266
334
|
if (!body) {
|
|
267
335
|
return;
|
|
268
336
|
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
337
|
+
yield* readSseStream(body);
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
// src/browser-postgrest.ts
|
|
342
|
+
function assertIdent(name, ctx) {
|
|
343
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) {
|
|
344
|
+
throw new RagableError(
|
|
345
|
+
`Invalid ${ctx} identifier "${name}" (use letters, numbers, underscore)`,
|
|
346
|
+
400,
|
|
347
|
+
null
|
|
348
|
+
);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
function quoteIdent(name) {
|
|
352
|
+
assertIdent(name, "column");
|
|
353
|
+
return `"${name}"`;
|
|
354
|
+
}
|
|
355
|
+
var OP_SQL = {
|
|
356
|
+
eq: "=",
|
|
357
|
+
neq: "<>",
|
|
358
|
+
gt: ">",
|
|
359
|
+
gte: ">=",
|
|
360
|
+
lt: "<",
|
|
361
|
+
lte: "<=",
|
|
362
|
+
like: "LIKE",
|
|
363
|
+
ilike: "ILIKE"
|
|
364
|
+
};
|
|
365
|
+
async function asPostgrestResponse(fn) {
|
|
366
|
+
try {
|
|
367
|
+
const data = await fn();
|
|
368
|
+
return { data, error: null };
|
|
369
|
+
} catch (e) {
|
|
370
|
+
const err = e instanceof RagableError ? e : new RagableError(e.message, 500, null);
|
|
371
|
+
return { data: null, error: err };
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
function buildWhere(filters, params) {
|
|
375
|
+
if (filters.length === 0) return { clause: "", nextIdx: 1 };
|
|
376
|
+
const parts = [];
|
|
377
|
+
let i = params.length;
|
|
378
|
+
for (const f of filters) {
|
|
379
|
+
assertIdent(f.column, "filter");
|
|
380
|
+
i += 1;
|
|
381
|
+
parts.push(`${quoteIdent(f.column)} ${OP_SQL[f.op]} $${i}`);
|
|
382
|
+
params.push(f.value);
|
|
383
|
+
}
|
|
384
|
+
return { clause: ` WHERE ${parts.join(" AND ")}`, nextIdx: i };
|
|
385
|
+
}
|
|
386
|
+
var PostgrestSelectBuilder = class {
|
|
387
|
+
constructor(run, databaseInstanceId, table, columns) {
|
|
388
|
+
this.run = run;
|
|
389
|
+
this.databaseInstanceId = databaseInstanceId;
|
|
390
|
+
this.table = table;
|
|
391
|
+
this.columns = columns;
|
|
392
|
+
__publicField(this, "filters", []);
|
|
393
|
+
__publicField(this, "_limit");
|
|
394
|
+
__publicField(this, "_order");
|
|
395
|
+
assertIdent(table, "table");
|
|
396
|
+
}
|
|
397
|
+
eq(column, value) {
|
|
398
|
+
this.filters.push({ op: "eq", column, value });
|
|
399
|
+
return this;
|
|
400
|
+
}
|
|
401
|
+
neq(column, value) {
|
|
402
|
+
this.filters.push({ op: "neq", column, value });
|
|
403
|
+
return this;
|
|
404
|
+
}
|
|
405
|
+
gt(column, value) {
|
|
406
|
+
this.filters.push({ op: "gt", column, value });
|
|
407
|
+
return this;
|
|
408
|
+
}
|
|
409
|
+
gte(column, value) {
|
|
410
|
+
this.filters.push({ op: "gte", column, value });
|
|
411
|
+
return this;
|
|
412
|
+
}
|
|
413
|
+
lt(column, value) {
|
|
414
|
+
this.filters.push({ op: "lt", column, value });
|
|
415
|
+
return this;
|
|
416
|
+
}
|
|
417
|
+
lte(column, value) {
|
|
418
|
+
this.filters.push({ op: "lte", column, value });
|
|
419
|
+
return this;
|
|
420
|
+
}
|
|
421
|
+
like(column, value) {
|
|
422
|
+
this.filters.push({ op: "like", column, value });
|
|
423
|
+
return this;
|
|
424
|
+
}
|
|
425
|
+
ilike(column, value) {
|
|
426
|
+
this.filters.push({ op: "ilike", column, value });
|
|
427
|
+
return this;
|
|
428
|
+
}
|
|
429
|
+
limit(n) {
|
|
430
|
+
this._limit = n;
|
|
431
|
+
return this;
|
|
432
|
+
}
|
|
433
|
+
order(column, options) {
|
|
434
|
+
this._order = { column, ascending: options?.ascending !== false };
|
|
435
|
+
return this;
|
|
436
|
+
}
|
|
437
|
+
/** @param includeUserLimit when false, omit `.limit()` (for `.single()` / `.maybeSingle()`). */
|
|
438
|
+
buildSelectCore(params, includeUserLimit) {
|
|
439
|
+
const tbl = quoteIdent(this.table);
|
|
440
|
+
const { clause } = buildWhere(this.filters, params);
|
|
441
|
+
let sql = `SELECT ${this.columns} FROM ${tbl}${clause}`;
|
|
442
|
+
if (this._order) {
|
|
443
|
+
sql += ` ORDER BY ${quoteIdent(this._order.column)} ${this._order.ascending ? "ASC" : "DESC"}`;
|
|
444
|
+
}
|
|
445
|
+
if (includeUserLimit && this._limit != null) {
|
|
446
|
+
sql += ` LIMIT ${Math.max(0, Math.floor(this._limit))}`;
|
|
447
|
+
}
|
|
448
|
+
return sql;
|
|
449
|
+
}
|
|
450
|
+
then(onfulfilled, onrejected) {
|
|
451
|
+
return this.executeMany().then(onfulfilled, onrejected);
|
|
452
|
+
}
|
|
453
|
+
async executeMany() {
|
|
454
|
+
return asPostgrestResponse(async () => {
|
|
455
|
+
const params = [];
|
|
456
|
+
const sql = this.buildSelectCore(params, true);
|
|
457
|
+
const res = await this.run({
|
|
458
|
+
databaseInstanceId: this.databaseInstanceId,
|
|
459
|
+
sql,
|
|
460
|
+
params,
|
|
461
|
+
readOnly: true
|
|
462
|
+
});
|
|
463
|
+
return res.rows;
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
async single() {
|
|
467
|
+
return asPostgrestResponse(async () => {
|
|
468
|
+
const params = [];
|
|
469
|
+
const base = this.buildSelectCore(params, false);
|
|
470
|
+
const sql = `${base} LIMIT 2`;
|
|
471
|
+
const res = await this.run({
|
|
472
|
+
databaseInstanceId: this.databaseInstanceId,
|
|
473
|
+
sql,
|
|
474
|
+
params,
|
|
475
|
+
readOnly: true
|
|
476
|
+
});
|
|
477
|
+
if (res.rows.length === 0) {
|
|
478
|
+
throw new RagableError("JSON object requested, multiple (or no) rows returned", 406, {
|
|
479
|
+
code: "PGRST116"
|
|
480
|
+
});
|
|
291
481
|
}
|
|
292
|
-
if (
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
482
|
+
if (res.rows.length > 1) {
|
|
483
|
+
throw new RagableError("JSON object requested, multiple (or no) rows returned", 406, {
|
|
484
|
+
code: "PGRST116"
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
return res.rows[0];
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
async maybeSingle() {
|
|
491
|
+
return asPostgrestResponse(async () => {
|
|
492
|
+
const params = [];
|
|
493
|
+
const base = this.buildSelectCore(params, false);
|
|
494
|
+
const sql = `${base} LIMIT 2`;
|
|
495
|
+
const res = await this.run({
|
|
496
|
+
databaseInstanceId: this.databaseInstanceId,
|
|
497
|
+
sql,
|
|
498
|
+
params,
|
|
499
|
+
readOnly: true
|
|
500
|
+
});
|
|
501
|
+
if (res.rows.length > 1) {
|
|
502
|
+
throw new RagableError("JSON object requested, multiple (or no) rows returned", 406, {
|
|
503
|
+
code: "PGRST116"
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
return res.rows[0] ?? null;
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
};
|
|
510
|
+
var PostgrestInsertBuilder = class {
|
|
511
|
+
constructor(run, databaseInstanceId, table, rows) {
|
|
512
|
+
this.run = run;
|
|
513
|
+
this.databaseInstanceId = databaseInstanceId;
|
|
514
|
+
this.table = table;
|
|
515
|
+
this.rows = rows;
|
|
516
|
+
__publicField(this, "returning", "*");
|
|
517
|
+
assertIdent(table, "table");
|
|
518
|
+
}
|
|
519
|
+
select(columns = "*") {
|
|
520
|
+
this.returning = columns;
|
|
521
|
+
return this;
|
|
522
|
+
}
|
|
523
|
+
then(onfulfilled, onrejected) {
|
|
524
|
+
return this.execute().then(onfulfilled, onrejected);
|
|
525
|
+
}
|
|
526
|
+
async execute() {
|
|
527
|
+
return asPostgrestResponse(async () => {
|
|
528
|
+
if (this.rows.length === 0) return [];
|
|
529
|
+
const keys = Object.keys(this.rows[0]);
|
|
530
|
+
for (const k of keys) assertIdent(k, "column");
|
|
531
|
+
const tbl = quoteIdent(this.table);
|
|
532
|
+
const params = [];
|
|
533
|
+
const valueGroups = [];
|
|
534
|
+
for (const row of this.rows) {
|
|
535
|
+
const placeholders = [];
|
|
536
|
+
for (const k of keys) {
|
|
537
|
+
params.push(row[k]);
|
|
538
|
+
placeholders.push(`$${params.length}`);
|
|
298
539
|
}
|
|
540
|
+
valueGroups.push(`(${placeholders.join(", ")})`);
|
|
299
541
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
542
|
+
const cols = keys.map(quoteIdent).join(", ");
|
|
543
|
+
const sql = `INSERT INTO ${tbl} (${cols}) VALUES ${valueGroups.join(", ")} RETURNING ${this.returning}`;
|
|
544
|
+
const res = await this.run({
|
|
545
|
+
databaseInstanceId: this.databaseInstanceId,
|
|
546
|
+
sql,
|
|
547
|
+
params,
|
|
548
|
+
readOnly: false
|
|
549
|
+
});
|
|
550
|
+
return res.rows;
|
|
551
|
+
});
|
|
303
552
|
}
|
|
304
553
|
};
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
554
|
+
var PostgrestUpdateBuilder = class {
|
|
555
|
+
constructor(run, databaseInstanceId, table, patch) {
|
|
556
|
+
this.run = run;
|
|
557
|
+
this.databaseInstanceId = databaseInstanceId;
|
|
558
|
+
this.table = table;
|
|
559
|
+
this.patch = patch;
|
|
560
|
+
__publicField(this, "filters", []);
|
|
561
|
+
__publicField(this, "returning", "*");
|
|
562
|
+
assertIdent(table, "table");
|
|
313
563
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
564
|
+
eq(column, value) {
|
|
565
|
+
this.filters.push({ op: "eq", column, value });
|
|
566
|
+
return this;
|
|
567
|
+
}
|
|
568
|
+
select(columns = "*") {
|
|
569
|
+
this.returning = columns;
|
|
570
|
+
return this;
|
|
571
|
+
}
|
|
572
|
+
then(onfulfilled, onrejected) {
|
|
573
|
+
return this.execute().then(onfulfilled, onrejected);
|
|
574
|
+
}
|
|
575
|
+
async execute() {
|
|
576
|
+
return asPostgrestResponse(async () => {
|
|
577
|
+
const keys = Object.keys(this.patch);
|
|
578
|
+
if (keys.length === 0) {
|
|
579
|
+
throw new RagableError("Empty update payload", 400, null);
|
|
580
|
+
}
|
|
581
|
+
for (const k of keys) assertIdent(k, "column");
|
|
582
|
+
if (this.filters.length === 0) {
|
|
583
|
+
throw new RagableError(
|
|
584
|
+
"UPDATE requires a filter (e.g. .eq('id', value)) \u2014 refusing unscoped update",
|
|
585
|
+
400,
|
|
586
|
+
null
|
|
587
|
+
);
|
|
588
|
+
}
|
|
589
|
+
const params = [];
|
|
590
|
+
const sets = [];
|
|
591
|
+
for (const k of keys) {
|
|
592
|
+
params.push(this.patch[k]);
|
|
593
|
+
sets.push(`${quoteIdent(k)} = $${params.length}`);
|
|
594
|
+
}
|
|
595
|
+
const { clause } = buildWhere(this.filters, params);
|
|
596
|
+
const tbl = quoteIdent(this.table);
|
|
597
|
+
const sql = `UPDATE ${tbl} SET ${sets.join(", ")}${clause} RETURNING ${this.returning}`;
|
|
598
|
+
const res = await this.run({
|
|
599
|
+
databaseInstanceId: this.databaseInstanceId,
|
|
600
|
+
sql,
|
|
601
|
+
params,
|
|
602
|
+
readOnly: false
|
|
603
|
+
});
|
|
604
|
+
return res.rows;
|
|
605
|
+
});
|
|
606
|
+
}
|
|
607
|
+
};
|
|
608
|
+
var PostgrestDeleteBuilder = class {
|
|
609
|
+
constructor(run, databaseInstanceId, table) {
|
|
610
|
+
this.run = run;
|
|
611
|
+
this.databaseInstanceId = databaseInstanceId;
|
|
612
|
+
this.table = table;
|
|
613
|
+
__publicField(this, "filters", []);
|
|
614
|
+
__publicField(this, "returning", "*");
|
|
615
|
+
assertIdent(table, "table");
|
|
616
|
+
}
|
|
617
|
+
eq(column, value) {
|
|
618
|
+
this.filters.push({ op: "eq", column, value });
|
|
619
|
+
return this;
|
|
620
|
+
}
|
|
621
|
+
select(columns = "*") {
|
|
622
|
+
this.returning = columns;
|
|
623
|
+
return this;
|
|
624
|
+
}
|
|
625
|
+
then(onfulfilled, onrejected) {
|
|
626
|
+
return this.execute().then(onfulfilled, onrejected);
|
|
627
|
+
}
|
|
628
|
+
async execute() {
|
|
629
|
+
return asPostgrestResponse(async () => {
|
|
630
|
+
if (this.filters.length === 0) {
|
|
631
|
+
throw new RagableError(
|
|
632
|
+
"DELETE requires a filter (e.g. .eq('id', value)) \u2014 refusing unscoped delete",
|
|
633
|
+
400,
|
|
634
|
+
null
|
|
635
|
+
);
|
|
636
|
+
}
|
|
637
|
+
const params = [];
|
|
638
|
+
const { clause } = buildWhere(this.filters, params);
|
|
639
|
+
const tbl = quoteIdent(this.table);
|
|
640
|
+
const sql = `DELETE FROM ${tbl}${clause} RETURNING ${this.returning}`;
|
|
641
|
+
const res = await this.run({
|
|
642
|
+
databaseInstanceId: this.databaseInstanceId,
|
|
643
|
+
sql,
|
|
644
|
+
params,
|
|
645
|
+
readOnly: false
|
|
646
|
+
});
|
|
647
|
+
return res.rows;
|
|
648
|
+
});
|
|
649
|
+
}
|
|
650
|
+
};
|
|
651
|
+
var PostgrestTableApi = class {
|
|
652
|
+
constructor(run, databaseInstanceId, table) {
|
|
653
|
+
this.run = run;
|
|
654
|
+
this.databaseInstanceId = databaseInstanceId;
|
|
655
|
+
this.table = table;
|
|
656
|
+
}
|
|
657
|
+
select(columns = "*") {
|
|
658
|
+
return new PostgrestSelectBuilder(
|
|
659
|
+
this.run,
|
|
660
|
+
this.databaseInstanceId,
|
|
661
|
+
this.table,
|
|
662
|
+
columns
|
|
663
|
+
);
|
|
664
|
+
}
|
|
665
|
+
insert(values) {
|
|
666
|
+
const rows = Array.isArray(values) ? values : [values];
|
|
667
|
+
return new PostgrestInsertBuilder(
|
|
668
|
+
this.run,
|
|
669
|
+
this.databaseInstanceId,
|
|
670
|
+
this.table,
|
|
671
|
+
rows
|
|
672
|
+
);
|
|
673
|
+
}
|
|
674
|
+
update(patch) {
|
|
675
|
+
return new PostgrestUpdateBuilder(
|
|
676
|
+
this.run,
|
|
677
|
+
this.databaseInstanceId,
|
|
678
|
+
this.table,
|
|
679
|
+
patch
|
|
680
|
+
);
|
|
681
|
+
}
|
|
682
|
+
delete() {
|
|
683
|
+
return new PostgrestDeleteBuilder(
|
|
684
|
+
this.run,
|
|
685
|
+
this.databaseInstanceId,
|
|
686
|
+
this.table
|
|
687
|
+
);
|
|
318
688
|
}
|
|
689
|
+
};
|
|
690
|
+
|
|
691
|
+
// src/browser.ts
|
|
692
|
+
function normalizeBrowserApiBase(baseUrl) {
|
|
693
|
+
return (baseUrl ?? "http://localhost:8080/api").replace(/\/+$/, "");
|
|
319
694
|
}
|
|
320
|
-
function
|
|
321
|
-
const
|
|
322
|
-
if (!
|
|
323
|
-
|
|
695
|
+
function requireAuthGroupId(options) {
|
|
696
|
+
const id = options.authGroupId?.trim();
|
|
697
|
+
if (!id) {
|
|
698
|
+
throw new Error(
|
|
699
|
+
"authGroupId is required for auth and database methods on the browser client"
|
|
700
|
+
);
|
|
324
701
|
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
702
|
+
return id;
|
|
703
|
+
}
|
|
704
|
+
async function requireAccessToken(options) {
|
|
705
|
+
const getter = options.getAccessToken;
|
|
706
|
+
if (!getter) {
|
|
707
|
+
throw new Error(
|
|
708
|
+
"getAccessToken is required for this call (return the end-user access JWT)"
|
|
709
|
+
);
|
|
328
710
|
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
711
|
+
const token = await getter();
|
|
712
|
+
if (!token?.trim()) {
|
|
713
|
+
throw new Error("getAccessToken returned no token");
|
|
714
|
+
}
|
|
715
|
+
return token.trim();
|
|
716
|
+
}
|
|
717
|
+
async function parseJsonOrThrow(response) {
|
|
718
|
+
const payload = await parseMaybeJsonBody(response);
|
|
719
|
+
if (!response.ok) {
|
|
720
|
+
const message = extractErrorMessage(payload, response.statusText);
|
|
721
|
+
throw new RagableError(message, response.status, payload);
|
|
722
|
+
}
|
|
723
|
+
return payload;
|
|
724
|
+
}
|
|
725
|
+
function parseExpiresInSeconds(expiresIn) {
|
|
726
|
+
const s = expiresIn.trim().toLowerCase();
|
|
727
|
+
const m = /^(\d+)([smhd])?$/.exec(s);
|
|
728
|
+
if (m) {
|
|
729
|
+
const n = Number(m[1]);
|
|
730
|
+
const u = m[2] ?? "s";
|
|
731
|
+
const mult = u === "s" ? 1 : u === "m" ? 60 : u === "h" ? 3600 : u === "d" ? 86400 : 1;
|
|
732
|
+
return n * mult;
|
|
733
|
+
}
|
|
734
|
+
const asNum = Number(s);
|
|
735
|
+
return Number.isFinite(asNum) ? asNum : 0;
|
|
736
|
+
}
|
|
737
|
+
function toSupabaseSession(s) {
|
|
738
|
+
return {
|
|
739
|
+
access_token: s.accessToken,
|
|
740
|
+
refresh_token: s.refreshToken,
|
|
741
|
+
expires_in: parseExpiresInSeconds(s.expiresIn),
|
|
742
|
+
token_type: "bearer",
|
|
743
|
+
user: s.user
|
|
744
|
+
};
|
|
745
|
+
}
|
|
746
|
+
var RagableBrowserAuthClient = class {
|
|
747
|
+
constructor(options) {
|
|
748
|
+
this.options = options;
|
|
749
|
+
}
|
|
750
|
+
get fetchImpl() {
|
|
751
|
+
return this.options.fetch ?? fetch;
|
|
752
|
+
}
|
|
753
|
+
toUrl(path) {
|
|
754
|
+
return `${normalizeBrowserApiBase(this.options.baseUrl)}${path.startsWith("/") ? path : `/${path}`}`;
|
|
755
|
+
}
|
|
756
|
+
baseHeaders(json) {
|
|
757
|
+
const h = new Headers(this.options.headers);
|
|
758
|
+
if (json) {
|
|
759
|
+
h.set("Content-Type", "application/json");
|
|
760
|
+
}
|
|
761
|
+
return h;
|
|
762
|
+
}
|
|
763
|
+
authPrefix() {
|
|
764
|
+
const gid = requireAuthGroupId(this.options);
|
|
765
|
+
return `/auth-groups/${gid}/auth`;
|
|
766
|
+
}
|
|
767
|
+
/** Supabase: `signUp` → `{ data: { user, session }, error }` */
|
|
768
|
+
async signUp(credentials) {
|
|
769
|
+
return asPostgrestResponse(async () => {
|
|
770
|
+
const name = typeof credentials.options?.data?.name === "string" ? credentials.options.data.name : void 0;
|
|
771
|
+
const session = await this.register({
|
|
772
|
+
email: credentials.email,
|
|
773
|
+
password: credentials.password,
|
|
774
|
+
name
|
|
775
|
+
});
|
|
776
|
+
return { user: session.user, session: toSupabaseSession(session) };
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
/** Supabase: `signInWithPassword` */
|
|
780
|
+
async signInWithPassword(credentials) {
|
|
781
|
+
return asPostgrestResponse(async () => {
|
|
782
|
+
const session = await this.login(credentials);
|
|
783
|
+
return { user: session.user, session: toSupabaseSession(session) };
|
|
784
|
+
});
|
|
785
|
+
}
|
|
786
|
+
/** Supabase: `refreshSession` */
|
|
787
|
+
async refreshSession(refreshToken) {
|
|
788
|
+
return asPostgrestResponse(async () => {
|
|
789
|
+
const tokens = await this.refresh({ refreshToken });
|
|
790
|
+
const me = await this.getUserFromToken(tokens.accessToken);
|
|
791
|
+
const session = {
|
|
792
|
+
access_token: tokens.accessToken,
|
|
793
|
+
refresh_token: tokens.refreshToken,
|
|
794
|
+
expires_in: parseExpiresInSeconds(tokens.expiresIn),
|
|
795
|
+
token_type: "bearer",
|
|
796
|
+
user: me.user
|
|
797
|
+
};
|
|
798
|
+
return { session, user: me.user };
|
|
799
|
+
});
|
|
800
|
+
}
|
|
801
|
+
/** Supabase: `getUser()` — needs `getAccessToken` on the client */
|
|
802
|
+
async getUser() {
|
|
803
|
+
return asPostgrestResponse(() => this.getMe());
|
|
804
|
+
}
|
|
805
|
+
/** Supabase: `updateUser` */
|
|
806
|
+
async updateUser(attributes) {
|
|
807
|
+
return asPostgrestResponse(
|
|
808
|
+
() => this.updateMe({
|
|
809
|
+
password: attributes.password,
|
|
810
|
+
name: attributes.data?.name
|
|
811
|
+
})
|
|
812
|
+
);
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* Supabase/Firebase: no server call — clear tokens in your app.
|
|
816
|
+
* Returns `{ error: null }` for API compatibility.
|
|
817
|
+
*/
|
|
818
|
+
async signOut(_options) {
|
|
819
|
+
return { error: null };
|
|
820
|
+
}
|
|
821
|
+
async getUserFromToken(accessToken) {
|
|
822
|
+
const headers = this.baseHeaders(false);
|
|
823
|
+
headers.set("Authorization", `Bearer ${accessToken}`);
|
|
824
|
+
const response = await this.fetchImpl(`${this.toUrl(this.authPrefix())}/me`, {
|
|
825
|
+
method: "GET",
|
|
826
|
+
headers
|
|
827
|
+
});
|
|
828
|
+
return parseJsonOrThrow(response);
|
|
829
|
+
}
|
|
830
|
+
async register(body) {
|
|
831
|
+
const response = await this.fetchImpl(`${this.toUrl(this.authPrefix())}/register`, {
|
|
832
|
+
method: "POST",
|
|
833
|
+
headers: this.baseHeaders(true),
|
|
834
|
+
body: JSON.stringify(body)
|
|
835
|
+
});
|
|
836
|
+
return parseJsonOrThrow(response);
|
|
333
837
|
}
|
|
838
|
+
async login(body) {
|
|
839
|
+
const response = await this.fetchImpl(`${this.toUrl(this.authPrefix())}/login`, {
|
|
840
|
+
method: "POST",
|
|
841
|
+
headers: this.baseHeaders(true),
|
|
842
|
+
body: JSON.stringify(body)
|
|
843
|
+
});
|
|
844
|
+
return parseJsonOrThrow(response);
|
|
845
|
+
}
|
|
846
|
+
async refresh(body) {
|
|
847
|
+
const response = await this.fetchImpl(`${this.toUrl(this.authPrefix())}/refresh`, {
|
|
848
|
+
method: "POST",
|
|
849
|
+
headers: this.baseHeaders(true),
|
|
850
|
+
body: JSON.stringify(body)
|
|
851
|
+
});
|
|
852
|
+
return parseJsonOrThrow(response);
|
|
853
|
+
}
|
|
854
|
+
async getMe() {
|
|
855
|
+
const token = await requireAccessToken(this.options);
|
|
856
|
+
const headers = this.baseHeaders(false);
|
|
857
|
+
headers.set("Authorization", `Bearer ${token}`);
|
|
858
|
+
const response = await this.fetchImpl(`${this.toUrl(this.authPrefix())}/me`, {
|
|
859
|
+
method: "GET",
|
|
860
|
+
headers
|
|
861
|
+
});
|
|
862
|
+
return parseJsonOrThrow(response);
|
|
863
|
+
}
|
|
864
|
+
async updateMe(body) {
|
|
865
|
+
const token = await requireAccessToken(this.options);
|
|
866
|
+
const headers = this.baseHeaders(true);
|
|
867
|
+
headers.set("Authorization", `Bearer ${token}`);
|
|
868
|
+
const response = await this.fetchImpl(`${this.toUrl(this.authPrefix())}/me`, {
|
|
869
|
+
method: "PATCH",
|
|
870
|
+
headers,
|
|
871
|
+
body: JSON.stringify(body)
|
|
872
|
+
});
|
|
873
|
+
return parseJsonOrThrow(response);
|
|
874
|
+
}
|
|
875
|
+
};
|
|
876
|
+
var RagableBrowserDatabaseClient = class {
|
|
877
|
+
constructor(options) {
|
|
878
|
+
this.options = options;
|
|
879
|
+
}
|
|
880
|
+
get fetchImpl() {
|
|
881
|
+
return this.options.fetch ?? fetch;
|
|
882
|
+
}
|
|
883
|
+
toUrl(path) {
|
|
884
|
+
return `${normalizeBrowserApiBase(this.options.baseUrl)}${path.startsWith("/") ? path : `/${path}`}`;
|
|
885
|
+
}
|
|
886
|
+
async query(params) {
|
|
887
|
+
const gid = requireAuthGroupId(this.options);
|
|
888
|
+
const token = await requireAccessToken(this.options);
|
|
889
|
+
const headers = this.baseHeaders();
|
|
890
|
+
headers.set("Authorization", `Bearer ${token}`);
|
|
891
|
+
headers.set("Content-Type", "application/json");
|
|
892
|
+
const response = await this.fetchImpl(
|
|
893
|
+
this.toUrl(`/auth-groups/${gid}/data/query`),
|
|
894
|
+
{
|
|
895
|
+
method: "POST",
|
|
896
|
+
headers,
|
|
897
|
+
body: JSON.stringify({
|
|
898
|
+
databaseInstanceId: params.databaseInstanceId,
|
|
899
|
+
sql: params.sql,
|
|
900
|
+
...params.params !== void 0 ? { params: params.params } : {},
|
|
901
|
+
...params.readOnly === false ? { readOnly: false } : {},
|
|
902
|
+
...params.timeoutMs !== void 0 ? { timeoutMs: params.timeoutMs } : {},
|
|
903
|
+
...params.rowLimit !== void 0 ? { rowLimit: params.rowLimit } : {}
|
|
904
|
+
})
|
|
905
|
+
}
|
|
906
|
+
);
|
|
907
|
+
return parseJsonOrThrow(response);
|
|
908
|
+
}
|
|
909
|
+
baseHeaders() {
|
|
910
|
+
return new Headers(this.options.headers);
|
|
911
|
+
}
|
|
912
|
+
};
|
|
913
|
+
var RagableBrowserAgentsClient = class {
|
|
914
|
+
constructor(options) {
|
|
915
|
+
this.options = options;
|
|
916
|
+
}
|
|
917
|
+
get fetchImpl() {
|
|
918
|
+
return this.options.fetch ?? fetch;
|
|
919
|
+
}
|
|
920
|
+
toUrl(path) {
|
|
921
|
+
return `${normalizeBrowserApiBase(this.options.baseUrl)}${path.startsWith("/") ? path : `/${path}`}`;
|
|
922
|
+
}
|
|
923
|
+
/**
|
|
924
|
+
* Stream agent execution as SSE (`POST /public/organizations/:orgId/agents/:agentId/chat/stream`).
|
|
925
|
+
*/
|
|
926
|
+
async *chatStream(agentId, params) {
|
|
927
|
+
const orgId = this.options.organizationId;
|
|
928
|
+
const body = {
|
|
929
|
+
message: params.message,
|
|
930
|
+
...params.history !== void 0 ? { history: params.history } : {},
|
|
931
|
+
...params.triggerSubtype !== void 0 ? { triggerSubtype: params.triggerSubtype } : {},
|
|
932
|
+
...params.triggerNodeId !== void 0 ? { triggerNodeId: params.triggerNodeId } : {}
|
|
933
|
+
};
|
|
934
|
+
const headers = new Headers(this.options.headers);
|
|
935
|
+
headers.set("Content-Type", "application/json");
|
|
936
|
+
const response = await this.fetchImpl(
|
|
937
|
+
this.toUrl(`/public/organizations/${orgId}/agents/${agentId}/chat/stream`),
|
|
938
|
+
{
|
|
939
|
+
method: "POST",
|
|
940
|
+
headers,
|
|
941
|
+
body: JSON.stringify(body)
|
|
942
|
+
}
|
|
943
|
+
);
|
|
944
|
+
if (!response.ok) {
|
|
945
|
+
const payload = await parseMaybeJsonBody(response);
|
|
946
|
+
const message = extractErrorMessage(payload, response.statusText);
|
|
947
|
+
throw new RagableError(message, response.status, payload);
|
|
948
|
+
}
|
|
949
|
+
const streamBody = response.body;
|
|
950
|
+
if (!streamBody) {
|
|
951
|
+
return;
|
|
952
|
+
}
|
|
953
|
+
yield* readSseStream(streamBody);
|
|
954
|
+
}
|
|
955
|
+
};
|
|
956
|
+
var RagableBrowser = class {
|
|
957
|
+
constructor(options) {
|
|
958
|
+
__publicField(this, "agents");
|
|
959
|
+
__publicField(this, "auth");
|
|
960
|
+
__publicField(this, "database");
|
|
961
|
+
__publicField(this, "options");
|
|
962
|
+
this.options = options;
|
|
963
|
+
this.agents = new RagableBrowserAgentsClient(options);
|
|
964
|
+
this.auth = new RagableBrowserAuthClient(options);
|
|
965
|
+
this.database = new RagableBrowserDatabaseClient(options);
|
|
966
|
+
}
|
|
967
|
+
/**
|
|
968
|
+
* Supabase-style table API: `.from('items').select().eq('id', 1).single()`.
|
|
969
|
+
* Pass `databaseInstanceId` here or set `databaseInstanceId` on the client options.
|
|
970
|
+
*/
|
|
971
|
+
from(table, databaseInstanceId) {
|
|
972
|
+
const id = databaseInstanceId?.trim() || this.options.databaseInstanceId?.trim();
|
|
973
|
+
if (!id) {
|
|
974
|
+
throw new Error(
|
|
975
|
+
"RagableBrowser.from() requires databaseInstanceId in client options or as the second argument"
|
|
976
|
+
);
|
|
977
|
+
}
|
|
978
|
+
const run = (p) => this.database.query(p);
|
|
979
|
+
return new PostgrestTableApi(run, id, table);
|
|
980
|
+
}
|
|
981
|
+
};
|
|
982
|
+
function createBrowserClient(options) {
|
|
983
|
+
return new RagableBrowser(options);
|
|
334
984
|
}
|
|
985
|
+
var createRagableBrowserClient = createBrowserClient;
|
|
335
986
|
|
|
336
987
|
// src/rag.ts
|
|
337
988
|
function formatRetrievalContext(results, options = {}) {
|
|
@@ -389,18 +1040,63 @@ var Ragable = class {
|
|
|
389
1040
|
};
|
|
390
1041
|
}
|
|
391
1042
|
};
|
|
392
|
-
function
|
|
1043
|
+
function isServerClientOptions(o) {
|
|
1044
|
+
return typeof o === "object" && o !== null && "apiKey" in o && typeof o.apiKey === "string" && o.apiKey.length > 0;
|
|
1045
|
+
}
|
|
1046
|
+
function createClient(urlOrOptions, browserOptions) {
|
|
1047
|
+
if (typeof urlOrOptions === "string") {
|
|
1048
|
+
if (!browserOptions) {
|
|
1049
|
+
throw new Error(
|
|
1050
|
+
"createClient(url, options) requires options with at least organizationId"
|
|
1051
|
+
);
|
|
1052
|
+
}
|
|
1053
|
+
const raw = urlOrOptions.trim().replace(/\/+$/, "");
|
|
1054
|
+
const baseUrl = raw.endsWith("/api") ? raw : `${raw}/api`;
|
|
1055
|
+
return createBrowserClient({
|
|
1056
|
+
...browserOptions,
|
|
1057
|
+
baseUrl: normalizeBrowserApiBase(baseUrl)
|
|
1058
|
+
});
|
|
1059
|
+
}
|
|
1060
|
+
if (isServerClientOptions(urlOrOptions)) {
|
|
1061
|
+
return new Ragable(urlOrOptions);
|
|
1062
|
+
}
|
|
1063
|
+
if (typeof urlOrOptions === "object" && urlOrOptions !== null && "organizationId" in urlOrOptions && typeof urlOrOptions.organizationId === "string") {
|
|
1064
|
+
return createBrowserClient(
|
|
1065
|
+
urlOrOptions
|
|
1066
|
+
);
|
|
1067
|
+
}
|
|
1068
|
+
throw new Error(
|
|
1069
|
+
"createClient(options) requires apiKey (server) or organizationId (browser)"
|
|
1070
|
+
);
|
|
1071
|
+
}
|
|
1072
|
+
function createRagableServerClient(options) {
|
|
393
1073
|
return new Ragable(options);
|
|
394
1074
|
}
|
|
395
1075
|
export {
|
|
396
1076
|
AgentsClient,
|
|
1077
|
+
PostgrestDeleteBuilder,
|
|
1078
|
+
PostgrestInsertBuilder,
|
|
1079
|
+
PostgrestSelectBuilder,
|
|
1080
|
+
PostgrestTableApi,
|
|
1081
|
+
PostgrestUpdateBuilder,
|
|
397
1082
|
Ragable,
|
|
1083
|
+
RagableBrowser,
|
|
1084
|
+
RagableBrowserAgentsClient,
|
|
1085
|
+
RagableBrowserAuthClient,
|
|
1086
|
+
RagableBrowserDatabaseClient,
|
|
398
1087
|
RagableError,
|
|
399
1088
|
RagableRequestClient,
|
|
400
1089
|
ShiftClient,
|
|
1090
|
+
asPostgrestResponse,
|
|
1091
|
+
createBrowserClient,
|
|
401
1092
|
createClient,
|
|
402
1093
|
createRagPipeline,
|
|
1094
|
+
createRagableBrowserClient,
|
|
1095
|
+
createRagableServerClient,
|
|
403
1096
|
extractErrorMessage,
|
|
404
|
-
formatRetrievalContext
|
|
1097
|
+
formatRetrievalContext,
|
|
1098
|
+
normalizeBrowserApiBase,
|
|
1099
|
+
parseSseDataLine,
|
|
1100
|
+
readSseStream
|
|
405
1101
|
};
|
|
406
1102
|
//# sourceMappingURL=index.mjs.map
|