@freehour/supabase-core 1.5.3 → 1.5.4

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
@@ -1,809 +1,566 @@
1
- import { assert as l } from "@freehour/assert";
2
- import f from "zod";
3
- import { PostgrestError as j } from "@supabase/supabase-js";
4
- import * as $ from "@supabase/postgrest-js";
5
- import { Mime as _ } from "@freehour/mime";
6
- class E extends Error {
7
- constructor(t, e = {}) {
8
- super(t, e), this.name = this.constructor.name, Error.captureStackTrace(this, this.constructor);
9
- }
10
- }
11
- class x extends E {
12
- /**
13
- * The ID of the file that was not found.
14
- */
15
- fileId;
16
- /**
17
- * The name of the bucket where the file was expected to be found.
18
- */
19
- bucket;
20
- /**
21
- * The path relative to the bucket root where the file was expected to be found.
22
- */
23
- path;
24
- constructor(t, {
25
- fileId: e,
26
- bucket: r,
27
- path: n
28
- } = {}) {
29
- super(t), this.fileId = e, this.bucket = r, this.path = n;
30
- }
31
- }
32
- class S extends E {
33
- /**
34
- * The encountered expression that could not be parsed.
35
- */
36
- expression;
37
- /**
38
- * Additional context about the expected format or structure.
39
- */
40
- format;
41
- constructor(t, {
42
- expression: e,
43
- format: r,
44
- ...n
45
- } = {}) {
46
- super(t, n), this.expression = e, this.format = r;
47
- }
48
- }
49
- class N extends E {
50
- /**
51
- * The schema where the record was expected to be found.
52
- */
53
- schema;
54
- /**
55
- * The table or view where the record was expected to be found.
56
- */
57
- relation;
58
- /**
59
- * The ID of the record that was not found.
60
- */
61
- id;
62
- constructor(t, {
63
- schema: e,
64
- relation: r,
65
- id: n
66
- } = {}) {
67
- super(t), this.schema = e, this.relation = r, this.id = n;
68
- }
69
- }
70
- class P extends Error {
71
- /**
72
- * The MIME type that is unsupported.
73
- */
74
- value;
75
- /**
76
- * The list of supported MIME types.
77
- */
78
- supported;
79
- constructor(t, {
80
- value: e,
81
- supported: r,
82
- ...n
83
- } = {}) {
84
- super(t, n), this.value = e, this.supported = r;
85
- }
86
- }
87
- const D = f.object({
88
- code: f.string(),
89
- details: f.string().nullable(),
90
- hint: f.string().nullable(),
91
- name: f.string().optional(),
92
- message: f.string().optional()
1
+ import { assert as e } from "@freehour/assert";
2
+ import t from "zod";
3
+ import { PostgrestError as n } from "@supabase/supabase-js";
4
+ import * as r from "@supabase/postgrest-js";
5
+ import { Mime as i } from "@freehour/mime";
6
+ //#region lib/errors.ts
7
+ var a = class extends Error {
8
+ constructor(e, t = {}) {
9
+ super(e, t), this.name = this.constructor.name, Error.captureStackTrace(this, this.constructor);
10
+ }
11
+ }, o = class extends a {
12
+ fileId;
13
+ bucket;
14
+ path;
15
+ constructor(e, { fileId: t, bucket: n, path: r } = {}) {
16
+ super(e), this.fileId = t, this.bucket = n, this.path = r;
17
+ }
18
+ }, s = class extends a {
19
+ expression;
20
+ format;
21
+ constructor(e, { expression: t, format: n, ...r } = {}) {
22
+ super(e, r), this.expression = t, this.format = n;
23
+ }
24
+ }, c = class extends a {
25
+ schema;
26
+ relation;
27
+ id;
28
+ constructor(e, { schema: t, relation: n, id: r } = {}) {
29
+ super(e), this.schema = t, this.relation = n, this.id = r;
30
+ }
31
+ }, l = class extends Error {
32
+ value;
33
+ supported;
34
+ constructor(e, { value: t, supported: n, ...r } = {}) {
35
+ super(e, r), this.value = t, this.supported = n;
36
+ }
37
+ }, u = t.object({
38
+ code: t.string(),
39
+ details: t.string().nullable(),
40
+ hint: t.string().nullable(),
41
+ name: t.string().optional(),
42
+ message: t.string().optional()
93
43
  });
94
- function J(s) {
95
- return s instanceof j || D.safeParse(s).success;
96
- }
97
- function L(s, t = "/") {
98
- const e = s.lastIndexOf(t);
99
- return e === -1 ? ["", s] : [s.substring(0, e), s.substring(e + 1)];
100
- }
101
- function F(s) {
102
- return Array.isArray(s) ? s : [s];
103
- }
104
- function M(s, t) {
105
- return s.reduce((e, r) => {
106
- const n = t(r);
107
- return (e[n] ??= []).push(r), e;
108
- }, {});
44
+ function d(e) {
45
+ return e instanceof n || u.safeParse(e).success;
109
46
  }
110
- function A(s, t) {
111
- const e = s.findIndex(t);
112
- return e !== -1 && s.splice(e, 1), s;
47
+ //#endregion
48
+ //#region lib/utils.ts
49
+ function f(e, t = "/") {
50
+ let n = e.lastIndexOf(t);
51
+ return n === -1 ? ["", e] : [e.substring(0, n), e.substring(n + 1)];
113
52
  }
114
- function z(s) {
115
- return Object.entries(s);
53
+ function p(e) {
54
+ return Array.isArray(e) ? e : [e];
116
55
  }
117
- class v {
118
- database;
119
- /**
120
- * The name of the schema containing the view.
121
- */
122
- schema;
123
- /**
124
- * The name of the view or table that this service interacts with.
125
- */
126
- relation;
127
- constructor({
128
- database: t,
129
- schema: e,
130
- relation: r
131
- }) {
132
- this.database = t, this.schema = e, this.relation = r;
133
- }
134
- recordNotFoundError(t) {
135
- return new N(`Record with id ${t} not found in ${this.schema}.${this.relation}`, {
136
- schema: this.schema,
137
- relation: this.relation,
138
- id: t
139
- });
140
- }
141
- /**
142
- * The PostgREST query builder for this relation.
143
- *
144
- * @example
145
- * const { data, error } = await dataService.query.select('*');
146
- */
147
- get query() {
148
- return this.database.schema(this.schema).from(this.relation);
149
- }
150
- /**
151
- * Performs a fuzzy search on the specified column of the relation.
152
- * @returns The rows that match the search criteria in descending order of similarity.
153
- * @throws DatabaseApiError if the query fails.
154
- */
155
- async fuzzySearch({
156
- column: t,
157
- searchTerm: e = "",
158
- minSimilarity: r = 0,
159
- limit: n = 64
160
- }) {
161
- const { data: i } = await this.database.schema("core").rpc("fuzzy_search", {
162
- relation: this.relation,
163
- schema_name: this.schema,
164
- column_name: t,
165
- search_term: e,
166
- min_similarity: r,
167
- limit_results: n
168
- }).throwOnError();
169
- return i;
170
- }
171
- /**
172
- * List all rows in the relation.
173
- * Equivalent to `select('*')` with no filters or pagination.
174
- * @returns Array of rows in the relation.
175
- */
176
- async list() {
177
- const { data: t } = await this.query.select("*").throwOnError();
178
- return t;
179
- }
180
- /**
181
- * Gets a single row by its ID.
182
- * @param id The ID of the row to find.
183
- * @param columns The columns to select from the row. Defaults to all columns.
184
- * @returns The found row or `undefined` if no row with the specified ID exists.
185
- * @throws DatabaseApiError if the query fails.
186
- */
187
- async get(t, e = "*") {
188
- const { data: r } = await this.query.select(e).eq("id", t).throwOnError();
189
- return r[0];
190
- }
191
- /**
192
- * Gets a single row by its ID, throwing an error if no such row exists.
193
- * @param id The ID of the row to find.
194
- * @param columns The columns to select from the row. Defaults to all columns.
195
- * @returns The found row.
196
- * @throws RecordNotFoundError if no row with the specified ID exists.
197
- * @throws DatabaseApiError if the query fails for any other reason.
198
- */
199
- async getOrThrow(t, e = "*") {
200
- const r = await this.get(t, e);
201
- if (r === void 0)
202
- throw this.recordNotFoundError(t);
203
- return r;
204
- }
205
- /**
206
- * Deletes a row from the relation by its ID, i.e. by the `id` column.
207
- * @param id The ID of the row to delete.
208
- * @return The deleted row, or `undefined` if no row with the specified ID existed.
209
- * @throws DatabaseApiError if the deletion fails.
210
- */
211
- async delete(t) {
212
- const { data: e } = await this.query.delete().eq("id", t).select().throwOnError();
213
- return e[0];
214
- }
215
- /**
216
- * Deletes a row from the relation by its ID, throwing an error if no such row exists.
217
- * @param id The ID of the row to delete.
218
- * @returns The deleted row.
219
- * @throws RecordNotFoundError if no row with the specified ID exists.
220
- * @throws DatabaseApiError if the deletion fails for any other reason.
221
- */
222
- async deleteOrThrow(t) {
223
- const e = await this.delete(t);
224
- if (e === void 0)
225
- throw this.recordNotFoundError(t);
226
- return e;
227
- }
228
- /**
229
- * Inserts a new row into the relation.
230
- * @param insert The data to insert into the relation.
231
- * @returns The inserted row.
232
- * @throws DatabaseApiError if the insertion fails.
233
- */
234
- async insert(t) {
235
- const { data: e } = await this.query.insert(t).select().single().throwOnError();
236
- return e;
237
- }
238
- /**
239
- * Inserts or updates a row in the relation.
240
- * @param insert The data to insert or update in the relation.
241
- * @returns The inserted or updated row.
242
- * @throws DatabaseApiError if the upsert operation fails.
243
- */
244
- async upsert(t, {
245
- onConflict: e,
246
- ...r
247
- } = {}) {
248
- const { data: n } = await this.query.upsert(t, {
249
- onConflict: e !== void 0 ? F(e).join(",") : void 0,
250
- ...r
251
- }).select().single().throwOnError();
252
- return n;
253
- }
254
- /**
255
- * Updates an existing row in the relation by its ID.
256
- *
257
- * @param id The ID of the row to update.
258
- * @param update The data to update in the row.
259
- * @returns The updated row.
260
- * @throws DatabaseApiError if the update fails.
261
- */
262
- async update(t, e) {
263
- const { data: r } = await this.query.update(e).eq("id", t).select().single().throwOnError();
264
- return r;
265
- }
56
+ function m(e, t) {
57
+ return e.reduce((e, n) => {
58
+ let r = t(n);
59
+ return (e[r] ??= []).push(n), e;
60
+ }, {});
266
61
  }
267
- class B extends v {
268
- constructor({
269
- database: t,
270
- schema: e,
271
- table: r
272
- }) {
273
- super({
274
- database: t,
275
- schema: e,
276
- relation: r
277
- });
278
- }
62
+ function h(e, t) {
63
+ let n = e.findIndex(t);
64
+ return n !== -1 && e.splice(n, 1), e;
279
65
  }
280
- class C extends v {
281
- constructor({
282
- database: t,
283
- schema: e,
284
- view: r
285
- }) {
286
- super({
287
- database: t,
288
- schema: e,
289
- relation: r
290
- });
291
- }
66
+ function g(e) {
67
+ return Object.entries(e);
292
68
  }
293
- function X(s) {
294
- if (s.error)
295
- throw s.error;
296
- return l(s.count !== null, "Response does not contain a count. Make sure to set the `count` option in the request."), s;
297
- }
298
- const O = ["eq", "neq", "gt", "gte", "lt", "lte", "like", "ilike", "match", "imatch", "in", "is", "isdistinct", "fts", "plfts", "phfts", "wfts", "cs", "cd", "ov", "sl", "sr", "nxr", "nxl", "adj"], Y = ["and", "or"], K = ",", q = "~", tt = (s) => (t = {}) => {
299
- const e = (n) => t[n] ?? n, r = Object.keys(s.shape);
300
- return f.string().transform((n, i) => {
301
- try {
302
- return W(n, r, e);
303
- } catch (a) {
304
- return i.addIssue({
305
- code: "custom",
306
- input: n,
307
- message: a instanceof Error ? a.message : void 0,
308
- params: a instanceof S ? {
309
- expression: a.expression,
310
- format: a.format
311
- } : void 0
312
- }), [];
313
- }
314
- });
69
+ //#endregion
70
+ //#region lib/data-service.ts
71
+ var _ = class {
72
+ database;
73
+ schema;
74
+ relation;
75
+ constructor({ database: e, schema: t, relation: n }) {
76
+ this.database = e, this.schema = t, this.relation = n;
77
+ }
78
+ recordNotFoundError(e) {
79
+ return new c(`Record with id ${e} not found in ${this.schema}.${this.relation}`, {
80
+ schema: this.schema,
81
+ relation: this.relation,
82
+ id: e
83
+ });
84
+ }
85
+ get query() {
86
+ return this.database.schema(this.schema).from(this.relation);
87
+ }
88
+ async fuzzySearch({ column: e, searchTerm: t = "", minSimilarity: n = 0, limit: r = 64 }) {
89
+ let { data: i } = await this.database.schema("core").rpc("fuzzy_search", {
90
+ relation: this.relation,
91
+ schema_name: this.schema,
92
+ column_name: e,
93
+ search_term: t,
94
+ min_similarity: n,
95
+ limit_results: r
96
+ }).throwOnError();
97
+ return i;
98
+ }
99
+ async list() {
100
+ let { data: e } = await this.query.select("*").throwOnError();
101
+ return e;
102
+ }
103
+ async get(e, t = "*") {
104
+ let { data: n } = await this.query.select(t).eq("id", e).throwOnError();
105
+ return n[0];
106
+ }
107
+ async getOrThrow(e, t = "*") {
108
+ let n = await this.get(e, t);
109
+ if (n === void 0) throw this.recordNotFoundError(e);
110
+ return n;
111
+ }
112
+ async delete(e) {
113
+ let { data: t } = await this.query.delete().eq("id", e).select().throwOnError();
114
+ return t[0];
115
+ }
116
+ async deleteOrThrow(e) {
117
+ let t = await this.delete(e);
118
+ if (t === void 0) throw this.recordNotFoundError(e);
119
+ return t;
120
+ }
121
+ async insert(e) {
122
+ let { data: t } = await this.query.insert(e).select().single().throwOnError();
123
+ return t;
124
+ }
125
+ async upsert(e, { onConflict: t, ...n } = {}) {
126
+ let { data: r } = await this.query.upsert(e, {
127
+ onConflict: t === void 0 ? void 0 : p(t).join(","),
128
+ ...n
129
+ }).select().single().throwOnError();
130
+ return r;
131
+ }
132
+ async update(e, t) {
133
+ let { data: n } = await this.query.update(t).eq("id", e).select().single().throwOnError();
134
+ return n;
135
+ }
136
+ }, v = class extends _ {
137
+ constructor({ database: e, schema: t, table: n }) {
138
+ super({
139
+ database: e,
140
+ schema: t,
141
+ relation: n
142
+ });
143
+ }
144
+ }, y = class extends _ {
145
+ constructor({ database: e, schema: t, view: n }) {
146
+ super({
147
+ database: e,
148
+ schema: t,
149
+ relation: n
150
+ });
151
+ }
315
152
  };
316
- function T(s) {
317
- return s.startsWith("not.") ? s.slice(4) : `not.${s}`;
318
- }
319
- function et(s) {
320
- return {
321
- ...s,
322
- op: T(s.op)
323
- };
324
- }
325
- function I(s, t = (e) => e) {
326
- if (s.type === "logical") {
327
- const e = s.args.map((r) => I(r, t));
328
- return `${s.op}(${e})`;
329
- }
330
- return `${t(s.key)}.${s.op}.${s.value}`;
331
- }
332
- function rt(s, t = (r) => r, e = q) {
333
- return s.map((r) => I(r, t)).join(e);
153
+ function b(t) {
154
+ if (t.error) throw t.error;
155
+ return e(t.count !== null, "Response does not contain a count. Make sure to set the `count` option in the request."), t;
334
156
  }
335
- function k(s, t = [], e = (r) => r) {
336
- function r(u) {
337
- const g = [];
338
- let b = 0, w = "", y = !1;
339
- for (const p of u)
340
- p === '"' ? (y = !y, w += p) : p === "(" && !y ? (b++, w += p) : p === ")" && !y ? (b--, w += p) : p === "," && b === 0 && !y ? (g.push(w.trim()), w = "") : w += p;
341
- return g;
342
- }
343
- if (s.endsWith(")")) {
344
- if (s.startsWith("and("))
345
- return {
346
- type: "logical",
347
- op: "and",
348
- args: r(s.slice(4, -1)).map((u) => k(u, t, e))
349
- };
350
- if (s.startsWith("or("))
351
- return {
352
- type: "logical",
353
- op: "or",
354
- args: r(s.slice(3, -1)).map((u) => k(u, t, e))
355
- };
356
- if (s.startsWith("not.and("))
357
- return {
358
- type: "logical",
359
- op: "not.and",
360
- args: r(s.slice(8, -1)).map((u) => k(u, t, e))
361
- };
362
- if (s.startsWith("not.or("))
363
- return {
364
- type: "logical",
365
- op: "not.or",
366
- args: r(s.slice(7, -1)).map((u) => k(u, t, e))
367
- };
368
- }
369
- const i = `^(${t.length === 0 ? "[a-zA-Z_][a-zA-Z0-9_]*" : t.join("|")})\\.((?:not\\.)?(?:${O.join("|")}))\\.(.+)$`, c = new RegExp(i).exec(s);
370
- if (!c)
371
- throw new S(`Invalid filter expression '${s}'`, {
372
- expression: s,
373
- format: {
374
- syntax: "key.(not.)op.value",
375
- keys: t.length === 0 ? "*" : t,
376
- operators: O
377
- }
378
- });
379
- const [, o, d, m] = c;
380
- return {
381
- type: "condition",
382
- key: e(o),
383
- op: d,
384
- value: l.defined(m)
385
- };
386
- }
387
- function W(s, t = [], e = (n) => n, r = q) {
388
- return s.length === 0 ? [] : s.split(r).map((n) => k(n, t, e));
389
- }
390
- class h extends $.PostgrestFilterBuilder {
391
- pagination;
392
- constructor(t) {
393
- super(t);
394
- }
395
- select(t = "*") {
396
- const e = super.select(
397
- F(t).join(",")
398
- );
399
- return new h(e);
400
- }
401
- /**
402
- * Applies a filter to the query.
403
- * A filter is defined as an AST of filter nodes including conditions and logical operators.
404
- * @param filter The filter to apply.
405
- */
406
- where(t) {
407
- if (t.type === "logical") {
408
- const e = t.args.map((r) => I(r)).join(",");
409
- this.url.searchParams.append(t.op, `(${e})`);
410
- } else
411
- this.url.searchParams.append(t.key, `${t.op}.${t.value}`);
412
- return this;
413
- }
414
- /**
415
- * Limits the range of results to a specific page given a page index and limit.
416
- * @param page The page index (0-based).
417
- * @param limit The number of items per page.
418
- * @param count Optional count of total items, if known.
419
- * If provided, it will be used to check if the pagination range is valid and resolve to an empty range if not.
420
- */
421
- paginate(t, e, r) {
422
- l(t >= 0, "Page index must be ≥ 0"), l(e >= 0, "Page limit must be ≥ 0");
423
- const n = t * e, i = n + e - 1;
424
- if (r !== void 0) {
425
- if (n >= r)
426
- return this.limit(0);
427
- if (i >= r)
428
- return this.range(n, r - 1);
429
- }
430
- return this.pagination = {
431
- ...this.pagination,
432
- page: t,
433
- limit: e,
434
- count: r
435
- }, this.range(n, i);
436
- }
437
- /**
438
- * Collects the results of a pagination query.
439
- * **Note:** For collect to work, paginate() must be called before collect() and the selection must include a `count`.
440
- * @returns The paginated list of queried items.
441
- */
442
- collect() {
443
- return this.then(({ data: t, count: e, error: r, ...n }) => {
444
- if (r)
445
- return { data: t, count: e, error: r, ...n };
446
- const { page: i, limit: a, ...c } = l.defined(this.pagination, "Pagination is required for collect(). Make sure to call paginate() before collect()"), o = e ?? c.count;
447
- return l(a > 0, "Page limit must be > 0"), l(Array.isArray(t), "Data must be an array for pagination, make sure to select multiple rows in query"), l(o !== void 0, "Row count is required for pagination, make sure to count in query or pass `count` in paginate()"), {
448
- data: {
449
- items: t,
450
- totalItems: o,
451
- page: i,
452
- totalPages: Math.ceil(o / a),
453
- limit: a
454
- },
455
- error: r,
456
- count: e,
457
- ...n
458
- };
459
- });
460
- }
157
+ //#endregion
158
+ //#region lib/filter.ts
159
+ var x = [
160
+ "eq",
161
+ "neq",
162
+ "gt",
163
+ "gte",
164
+ "lt",
165
+ "lte",
166
+ "like",
167
+ "ilike",
168
+ "match",
169
+ "imatch",
170
+ "in",
171
+ "is",
172
+ "isdistinct",
173
+ "fts",
174
+ "plfts",
175
+ "phfts",
176
+ "wfts",
177
+ "cs",
178
+ "cd",
179
+ "ov",
180
+ "sl",
181
+ "sr",
182
+ "nxr",
183
+ "nxl",
184
+ "adj"
185
+ ], S = ["and", "or"], C = ",", w = "~", T = (e) => (n = {}) => {
186
+ let r = (e) => n[e] ?? e, i = Object.keys(e.shape);
187
+ return t.string().transform((e, t) => {
188
+ try {
189
+ return j(e, i, r);
190
+ } catch (n) {
191
+ return t.addIssue({
192
+ code: "custom",
193
+ input: e,
194
+ message: n instanceof Error ? n.message : void 0,
195
+ params: n instanceof s ? {
196
+ expression: n.expression,
197
+ format: n.format
198
+ } : void 0
199
+ }), [];
200
+ }
201
+ });
202
+ };
203
+ function E(e) {
204
+ return e.startsWith("not.") ? e.slice(4) : `not.${e}`;
461
205
  }
462
- class U extends $.PostgrestQueryBuilder {
463
- constructor(t) {
464
- super(t.url, t);
465
- }
466
- select(t = "*", e) {
467
- const r = super.select(
468
- F(t).join(","),
469
- e
470
- );
471
- return new h(r);
472
- }
473
- /**
474
- * Counts the number of rows in the relation.
475
- * Does not select any columns, only counts the rows.
476
- *
477
- * @param method The counting method to use, defaults to 'exact'.
478
- * @returns The PostgREST filter builder with counting applied and filter extension enabled.
479
- */
480
- count(t = "exact") {
481
- const e = this.select("*", { count: t, head: !0 });
482
- return new h(e);
483
- }
484
- insert(t, e) {
485
- const r = super.insert(t, e);
486
- return new h(r);
487
- }
488
- upsert(t, { onConflict: e, ...r } = {}) {
489
- const n = super.upsert(t, {
490
- onConflict: F(e).join(","),
491
- ...r
492
- });
493
- return new h(n);
494
- }
495
- // @ts-expect-error the signatures are compatible but typescript can't verify it
496
- update(t, e) {
497
- const r = super.update(t, e);
498
- return new h(r);
499
- }
500
- delete() {
501
- const t = super.delete();
502
- return new h(t);
503
- }
206
+ function D(e) {
207
+ return {
208
+ ...e,
209
+ op: E(e.op)
210
+ };
504
211
  }
505
- class Q {
506
- client;
507
- constructor(t) {
508
- this.client = t;
509
- }
510
- from(t) {
511
- const e = this.client.from(t);
512
- return new U(e);
513
- }
514
- rpc(t, e, r) {
515
- const n = this.client.rpc(t, e, r);
516
- return new h(n);
517
- }
212
+ function O(e, t = (e) => e) {
213
+ if (e.type === "logical") {
214
+ let n = e.args.map((e) => O(e, t));
215
+ return `${e.op}(${n})`;
216
+ }
217
+ return `${t(e.key)}.${e.op}.${e.value}`;
518
218
  }
519
- class R {
520
- supabase;
521
- constructor({ supabase: t }) {
522
- this.supabase = t;
523
- }
524
- schema(t) {
525
- const e = this.supabase.schema(t);
526
- return new Q(e);
527
- }
528
- relation(t, e) {
529
- return new v({
530
- database: this,
531
- schema: t,
532
- relation: e
533
- });
534
- }
535
- table(t, e) {
536
- return new B({
537
- database: this,
538
- schema: t,
539
- table: e
540
- });
541
- }
542
- view(t, e) {
543
- return new C({
544
- database: this,
545
- schema: t,
546
- view: e
547
- });
548
- }
219
+ function k(e, t = (e) => e, n = "~") {
220
+ return e.map((e) => O(e, t)).join(n);
549
221
  }
550
- const st = R;
551
- class nt {
552
- preprocesses = [];
553
- storage;
554
- constructor({
555
- storage: t
556
- }) {
557
- this.storage = t;
558
- }
559
- /**
560
- * Retrieves a list of files in the specified bucket that have either no embeddings or embeddings that are outdated.
561
- * Note: The base implementation of this method is expensive to run.
562
- * It is recommended to override it with a more efficient implementation (e.g. using pure SQL) if possible.
563
- *
564
- * @param bucket The name of the bucket to check for outdated embeddings.
565
- * @returns A promise that resolves to an array of file references with outdated embeddings.
566
- */
567
- async getOutdatedEmbeddings(t) {
568
- const e = [];
569
- let r = !0, n;
570
- for (; r; ) {
571
- const { objects: i, ...a } = await this.storage.getFiles(t, { cursor: n }), c = await Promise.all(
572
- i.map(async (o) => {
573
- const d = new Date(o.updated_at), m = await this.storage.getFileStorageLocation({ fileId: o.id }), u = await this.getEmbeddings(m);
574
- return u.length === 0 || u.some((g) => g.createdAt < d);
575
- })
576
- );
577
- e.push(
578
- ...i.filter((o, d) => c[d]).map(({ id: o }) => ({ fileId: o }))
579
- ), { hasNext: r, nextCursor: n } = a;
580
- }
581
- return e;
582
- }
583
- preprocess(t, e) {
584
- return this.preprocesses.forEach((r) => {
585
- t = r.run(t, e);
586
- }), t;
587
- }
588
- addPreprocessingStep(t) {
589
- return this.preprocesses.push(t), this;
590
- }
591
- removePreprocessingStep(t) {
592
- return A(this.preprocesses, (e) => e.name === t), this;
593
- }
594
- async get(t) {
595
- const e = await this.storage.getFileStorageLocation(t);
596
- return this.getEmbeddings(e);
597
- }
598
- async ingest(t, e) {
599
- const { file: r, ...n } = await this.storage.downloadFile(t), i = _.parse(r.type);
600
- if (i.type !== "text")
601
- throw new P(`Unsupported file type: ${i}. Only text files can be embedded.`);
602
- await this.deleteEmbeddings(n);
603
- const a = {
604
- name: r.name,
605
- type: r.type,
606
- size: r.size
607
- }, c = this.preprocess(await r.text(), a);
608
- return this.createEmbeddings(
609
- n,
610
- c,
611
- a,
612
- typeof e == "function" ? e(r, n) : e
613
- );
614
- }
615
- async synchronize(t, e) {
616
- const r = await this.getOutdatedEmbeddings(t);
617
- return (await Promise.all(
618
- r.map(
619
- async (i) => this.ingest(i, e).then(() => ({
620
- file: i,
621
- success: !0,
622
- error: null
623
- })).catch((a) => a instanceof P ? null : {
624
- file: i,
625
- error: a,
626
- success: !1
627
- })
628
- )
629
- )).filter((i) => i !== null);
630
- }
222
+ function A(t, n = [], r = (e) => e) {
223
+ function i(e) {
224
+ let t = [], n = 0, r = "", i = !1;
225
+ for (let a of e) a === "\"" ? (i = !i, r += a) : a === "(" && !i ? (n++, r += a) : a === ")" && !i ? (n--, r += a) : a === "," && n === 0 && !i ? (t.push(r.trim()), r = "") : r += a;
226
+ return t;
227
+ }
228
+ if (t.endsWith(")")) {
229
+ if (t.startsWith("and(")) return {
230
+ type: "logical",
231
+ op: "and",
232
+ args: i(t.slice(4, -1)).map((e) => A(e, n, r))
233
+ };
234
+ if (t.startsWith("or(")) return {
235
+ type: "logical",
236
+ op: "or",
237
+ args: i(t.slice(3, -1)).map((e) => A(e, n, r))
238
+ };
239
+ if (t.startsWith("not.and(")) return {
240
+ type: "logical",
241
+ op: "not.and",
242
+ args: i(t.slice(8, -1)).map((e) => A(e, n, r))
243
+ };
244
+ if (t.startsWith("not.or(")) return {
245
+ type: "logical",
246
+ op: "not.or",
247
+ args: i(t.slice(7, -1)).map((e) => A(e, n, r))
248
+ };
249
+ }
250
+ let a = `^(${n.length === 0 ? "[a-zA-Z_][a-zA-Z0-9_]*" : n.join("|")})\\.((?:not\\.)?(?:${x.join("|")}))\\.(.+)$`, o = new RegExp(a).exec(t);
251
+ if (!o) throw new s(`Invalid filter expression '${t}'`, {
252
+ expression: t,
253
+ format: {
254
+ syntax: "key.(not.)op.value",
255
+ keys: n.length === 0 ? "*" : n,
256
+ operators: x
257
+ }
258
+ });
259
+ let [, c, l, u] = o;
260
+ return {
261
+ type: "condition",
262
+ key: r(c),
263
+ op: l,
264
+ value: e.defined(u)
265
+ };
631
266
  }
632
- const it = {
633
- removeImagesFromMarkdown: {
634
- name: "removeImagesFromMarkdown",
635
- run(s, t) {
636
- if (t.type === "text/markdown") {
637
- const e = /!\[([^\]]*)\]\([^)]*\)/g;
638
- return s.replace(e, (r, n) => `![${n}]()`);
639
- }
640
- return s;
641
- }
642
- },
643
- removeLinksFromMarkdown: {
644
- name: "removeLinksFromMarkdown",
645
- run(s, t) {
646
- if (t.type === "text/markdown") {
647
- const e = /\[([^\]]*)\]\([^)]*\)/g;
648
- return s.replace(e, (r, n) => `[${n}]()`);
649
- }
650
- return s;
651
- }
652
- }
653
- };
654
- class at {
655
- client;
656
- database;
657
- constructor({
658
- client: t,
659
- database: e
660
- }) {
661
- this.client = t, this.database = e;
662
- }
663
- get files() {
664
- return this.database.table("storage", "objects");
665
- }
666
- async getFileObject(t, e) {
667
- const { data: r, error: n } = await this.client.from(t).info(e);
668
- if (n)
669
- throw n;
670
- return r;
671
- }
672
- async getFiles(t, e) {
673
- const { data: r, error: n } = await this.client.from(t).listV2(e);
674
- if (n)
675
- throw n;
676
- return r;
677
- }
678
- async getFileStorageLocation(t) {
679
- if ("fileId" in t) {
680
- const { fileId: i } = t, a = await this.files.get(i, ["bucket_id", "path_tokens"]);
681
- if (!a)
682
- throw new x(`File with ID ${i} not found`, { fileId: i });
683
- return {
684
- fileId: i,
685
- bucket: l.notNull(a.bucket_id, "bucket_id must not be null"),
686
- path: l.notNull(a.path_tokens, "path_tokens must not be null").join("/")
687
- };
688
- }
689
- const { bucket: e, path: r } = t, { id: n } = await this.getFileObject(e, r);
690
- return { fileId: n, bucket: e, path: r };
691
- }
692
- async getFileInfo(t) {
693
- const { fileId: e, bucket: r, path: n } = await this.getFileStorageLocation(t), { id: i, bucketId: a, metadata: c, ...o } = await this.getFileObject(r, n);
694
- return l(i === e, "file ID from storage client must match file ID from database"), l(a === r, "bucketId from storage client must match bucket from database"), {
695
- ...o,
696
- fileId: e,
697
- bucket: r,
698
- path: n,
699
- metadata: c,
700
- properties: c ? {
701
- type: c.mimetype,
702
- lastModified: new Date(c.lastModified).getTime()
703
- } : {}
704
- };
705
- }
706
- async getPublicURL(t, e) {
707
- const { bucket: r, path: n } = await this.getFileStorageLocation(t), { data: { publicUrl: i } } = this.client.from(r).getPublicUrl(n, e);
708
- return i;
709
- }
710
- async existsFile(t) {
711
- const { bucket: e, path: r } = await this.getFileStorageLocation(t), { data: n, error: i } = await this.client.from(e).exists(r);
712
- if (i)
713
- throw i;
714
- return n;
715
- }
716
- async assertExistsFile(t) {
717
- const { bucket: e, path: r } = await this.getFileStorageLocation(t), { data: n, error: i } = await this.client.from(e).exists(r);
718
- if (i)
719
- throw i;
720
- if (!n)
721
- throw new x(`File not found in bucket '${e}' at path '${r}'`, { bucket: e, path: r });
722
- }
723
- async uploadFile(t, { bucket: e, path: r }, { overwriteExisting: n = !1 } = {}) {
724
- const { data: i, error: a } = await this.client.from(e).upload(
725
- `${r}/${t.name}`,
726
- t,
727
- {
728
- upsert: n
729
- }
730
- );
731
- if (a)
732
- throw a;
733
- return {
734
- fileId: i.id,
735
- bucket: e,
736
- path: i.path
737
- };
738
- }
739
- async downloadFile(t) {
740
- const { fileId: e, bucket: r, path: n, properties: i } = await this.getFileInfo(t), { data: a, error: c } = await this.client.from(r).download(n);
741
- if (c)
742
- throw c;
743
- const [, o] = L(n);
744
- return {
745
- fileId: e,
746
- bucket: r,
747
- path: n,
748
- file: new File([a], o, i)
749
- };
750
- }
751
- async deleteFiles(t) {
752
- const e = t.filter((o) => "fileId" in o).map((o) => o.fileId), n = (await this.files.query.select(["bucket_id", "path_tokens"]).containedBy("id", e).throwOnError()).data.map(({ bucket_id: o, path_tokens: d }) => ({
753
- bucket: l.notNull(o, "bucket_id must not be null"),
754
- path: l.notNull(d, "path_tokens must not be null").join("/")
755
- })), i = t.filter((o) => "path" in o).concat(n), a = z(
756
- M(i, (o) => o.bucket)
757
- ).map(([o, d]) => ({
758
- bucket: o,
759
- paths: d.map((m) => m.path)
760
- }));
761
- return (await Promise.all(a.map(
762
- async ({ bucket: o, paths: d }) => this.client.from(o).remove(d).then(({ data: m, error: u }) => {
763
- if (u)
764
- throw u;
765
- return m.map((g, b) => ({
766
- fileId: l.notNull(g.id, "file id must not be null"),
767
- bucket: o,
768
- path: l.defined(d[b], "path must not be null")
769
- }));
770
- })
771
- ))).flat();
772
- }
267
+ function j(e, t = [], n = (e) => e, r = "~") {
268
+ return e.length === 0 ? [] : e.split(r).map((e) => A(e, t, n));
773
269
  }
774
- export {
775
- v as DataService,
776
- st as DatabaseService,
777
- nt as EmbeddingService,
778
- x as FileNotFoundError,
779
- tt as Filter,
780
- q as FilterChainSeparator,
781
- O as FilterOp,
782
- Y as LogicalOp,
783
- K as LogicalOpSeparator,
784
- S as ParseError,
785
- Q as PostgrestClient,
786
- D as PostgrestErrorInterface,
787
- h as PostgrestFilterBuilder,
788
- U as PostgrestQueryBuilder,
789
- N as RecordNotFoundError,
790
- at as StorageService,
791
- B as TableDataService,
792
- E as TracedError,
793
- P as UnsupportedMimeError,
794
- C as ViewDataService,
795
- X as assertCounted,
796
- F as coerceArray,
797
- rt as encodeFilter,
798
- I as encodeFilterNode,
799
- z as entries,
800
- M as groupBy,
801
- J as isDatabaseApiError,
802
- et as negateFilterNode,
803
- T as negateOp,
804
- k as parseFilterExpression,
805
- W as parseFilterExpressionChain,
806
- it as preprocessingSteps,
807
- A as removeElement,
808
- L as splitPath
270
+ //#endregion
271
+ //#region lib/postgrest.ts
272
+ var M = class t extends r.PostgrestFilterBuilder {
273
+ pagination;
274
+ constructor(e) {
275
+ super(e);
276
+ }
277
+ select(e = "*") {
278
+ return new t(super.select(p(e).join(",")));
279
+ }
280
+ where(e) {
281
+ if (e.type === "logical") {
282
+ let t = e.args.map((e) => O(e)).join(",");
283
+ this.url.searchParams.append(e.op, `(${t})`);
284
+ } else this.url.searchParams.append(e.key, `${e.op}.${e.value}`);
285
+ return this;
286
+ }
287
+ paginate(t, n, r) {
288
+ e(t >= 0, "Page index must be ≥ 0"), e(n >= 0, "Page limit must be ≥ 0");
289
+ let i = t * n, a = i + n - 1;
290
+ if (r !== void 0) {
291
+ if (i >= r) return this.limit(0);
292
+ if (a >= r) return this.range(i, r - 1);
293
+ }
294
+ return this.pagination = {
295
+ ...this.pagination,
296
+ page: t,
297
+ limit: n,
298
+ count: r
299
+ }, this.range(i, a);
300
+ }
301
+ collect() {
302
+ return this.then(({ data: t, count: n, error: r, ...i }) => {
303
+ if (r) return {
304
+ data: t,
305
+ count: n,
306
+ error: r,
307
+ ...i
308
+ };
309
+ let { page: a, limit: o, ...s } = e.defined(this.pagination, "Pagination is required for collect(). Make sure to call paginate() before collect()"), c = n ?? s.count;
310
+ return e(o > 0, "Page limit must be > 0"), e(Array.isArray(t), "Data must be an array for pagination, make sure to select multiple rows in query"), e(c !== void 0, "Row count is required for pagination, make sure to count in query or pass `count` in paginate()"), {
311
+ data: {
312
+ items: t,
313
+ totalItems: c,
314
+ page: a,
315
+ totalPages: Math.ceil(c / o),
316
+ limit: o
317
+ },
318
+ error: r,
319
+ count: n,
320
+ ...i
321
+ };
322
+ });
323
+ }
324
+ }, N = class extends r.PostgrestQueryBuilder {
325
+ constructor(e) {
326
+ super(e.url, e);
327
+ }
328
+ select(e = "*", t) {
329
+ return new M(super.select(p(e).join(","), t));
330
+ }
331
+ count(e = "exact") {
332
+ return new M(this.select("*", {
333
+ count: e,
334
+ head: !0
335
+ }));
336
+ }
337
+ insert(e, t) {
338
+ return new M(super.insert(e, t));
339
+ }
340
+ upsert(e, { onConflict: t, ...n } = {}) {
341
+ return new M(super.upsert(e, {
342
+ onConflict: p(t).join(","),
343
+ ...n
344
+ }));
345
+ }
346
+ update(e, t) {
347
+ return new M(super.update(e, t));
348
+ }
349
+ delete() {
350
+ return new M(super.delete());
351
+ }
352
+ }, P = class {
353
+ client;
354
+ constructor(e) {
355
+ this.client = e;
356
+ }
357
+ from(e) {
358
+ return new N(this.client.from(e));
359
+ }
360
+ rpc(e, t, n) {
361
+ return new M(this.client.rpc(e, t, n));
362
+ }
363
+ }, F = class {
364
+ supabase;
365
+ constructor({ supabase: e }) {
366
+ this.supabase = e;
367
+ }
368
+ schema(e) {
369
+ return new P(this.supabase.schema(e));
370
+ }
371
+ relation(e, t) {
372
+ return new _({
373
+ database: this,
374
+ schema: e,
375
+ relation: t
376
+ });
377
+ }
378
+ table(e, t) {
379
+ return new v({
380
+ database: this,
381
+ schema: e,
382
+ table: t
383
+ });
384
+ }
385
+ view(e, t) {
386
+ return new y({
387
+ database: this,
388
+ schema: e,
389
+ view: t
390
+ });
391
+ }
392
+ }, I = {
393
+ removeImagesFromMarkdown: {
394
+ name: "removeImagesFromMarkdown",
395
+ run(e, t) {
396
+ return t.type === "text/markdown" ? e.replace(/!\[([^\]]*)\]\([^)]*\)/g, (e, t) => `![${t}]()`) : e;
397
+ }
398
+ },
399
+ removeLinksFromMarkdown: {
400
+ name: "removeLinksFromMarkdown",
401
+ run(e, t) {
402
+ return t.type === "text/markdown" ? e.replace(/\[([^\]]*)\]\([^)]*\)/g, (e, t) => `[${t}]()`) : e;
403
+ }
404
+ }
405
+ }, L = class {
406
+ preprocesses = [];
407
+ storage;
408
+ constructor({ storage: e }) {
409
+ this.storage = e;
410
+ }
411
+ async getOutdatedEmbeddings(e) {
412
+ let t = [], n = !0, r;
413
+ for (; n;) {
414
+ let { objects: i, ...a } = await this.storage.getFiles(e, { cursor: r }), o = await Promise.all(i.map(async (e) => {
415
+ let t = new Date(e.updated_at), n = await this.storage.getFileStorageLocation({ fileId: e.id }), r = await this.getEmbeddings(n);
416
+ return r.length === 0 || r.some((e) => e.createdAt < t);
417
+ }));
418
+ t.push(...i.filter((e, t) => o[t]).map(({ id: e }) => ({ fileId: e }))), {hasNext: n, nextCursor: r} = a;
419
+ }
420
+ return t;
421
+ }
422
+ preprocess(e, t) {
423
+ return this.preprocesses.forEach((n) => {
424
+ e = n.run(e, t);
425
+ }), e;
426
+ }
427
+ addPreprocessingStep(e) {
428
+ return this.preprocesses.push(e), this;
429
+ }
430
+ removePreprocessingStep(e) {
431
+ return h(this.preprocesses, (t) => t.name === e), this;
432
+ }
433
+ async get(e) {
434
+ let t = await this.storage.getFileStorageLocation(e);
435
+ return this.getEmbeddings(t);
436
+ }
437
+ async ingest(e, t) {
438
+ let { file: n, ...r } = await this.storage.downloadFile(e), a = i.parse(n.type);
439
+ if (a.type !== "text") throw new l(`Unsupported file type: ${a}. Only text files can be embedded.`);
440
+ await this.deleteEmbeddings(r);
441
+ let o = {
442
+ name: n.name,
443
+ type: n.type,
444
+ size: n.size
445
+ }, s = this.preprocess(await n.text(), o);
446
+ return this.createEmbeddings(r, s, o, typeof t == "function" ? t(n, r) : t);
447
+ }
448
+ async synchronize(e, t) {
449
+ let n = await this.getOutdatedEmbeddings(e);
450
+ return (await Promise.all(n.map(async (e) => this.ingest(e, t).then(() => ({
451
+ file: e,
452
+ success: !0,
453
+ error: null
454
+ })).catch((t) => t instanceof l ? null : {
455
+ file: e,
456
+ error: t,
457
+ success: !1
458
+ })))).filter((e) => e !== null);
459
+ }
460
+ }, R = class {
461
+ client;
462
+ database;
463
+ constructor({ client: e, database: t }) {
464
+ this.client = e, this.database = t;
465
+ }
466
+ get files() {
467
+ return this.database.table("storage", "objects");
468
+ }
469
+ async getFileObject(e, t) {
470
+ let { data: n, error: r } = await this.client.from(e).info(t);
471
+ if (r) throw r;
472
+ return n;
473
+ }
474
+ async getFiles(e, t) {
475
+ let { data: n, error: r } = await this.client.from(e).listV2(t);
476
+ if (r) throw r;
477
+ return n;
478
+ }
479
+ async getFileStorageLocation(t) {
480
+ if ("fileId" in t) {
481
+ let { fileId: n } = t, r = await this.files.get(n, ["bucket_id", "path_tokens"]);
482
+ if (!r) throw new o(`File with ID ${n} not found`, { fileId: n });
483
+ return {
484
+ fileId: n,
485
+ bucket: e.notNull(r.bucket_id, "bucket_id must not be null"),
486
+ path: e.notNull(r.path_tokens, "path_tokens must not be null").join("/")
487
+ };
488
+ }
489
+ let { bucket: n, path: r } = t, { id: i } = await this.getFileObject(n, r);
490
+ return {
491
+ fileId: i,
492
+ bucket: n,
493
+ path: r
494
+ };
495
+ }
496
+ async getFileInfo(t) {
497
+ let { fileId: n, bucket: r, path: i } = await this.getFileStorageLocation(t), { id: a, bucketId: o, metadata: s, ...c } = await this.getFileObject(r, i);
498
+ return e(a === n, "file ID from storage client must match file ID from database"), e(o === r, "bucketId from storage client must match bucket from database"), {
499
+ ...c,
500
+ fileId: n,
501
+ bucket: r,
502
+ path: i,
503
+ metadata: s,
504
+ properties: s ? {
505
+ type: s.mimetype,
506
+ lastModified: new Date(s.lastModified).getTime()
507
+ } : {}
508
+ };
509
+ }
510
+ async getPublicURL(e, t) {
511
+ let { bucket: n, path: r } = await this.getFileStorageLocation(e), { data: { publicUrl: i } } = this.client.from(n).getPublicUrl(r, t);
512
+ return i;
513
+ }
514
+ async existsFile(e) {
515
+ let { bucket: t, path: n } = await this.getFileStorageLocation(e), { data: r, error: i } = await this.client.from(t).exists(n);
516
+ if (i) throw i;
517
+ return r;
518
+ }
519
+ async assertExistsFile(e) {
520
+ let { bucket: t, path: n } = await this.getFileStorageLocation(e), { data: r, error: i } = await this.client.from(t).exists(n);
521
+ if (i) throw i;
522
+ if (!r) throw new o(`File not found in bucket '${t}' at path '${n}'`, {
523
+ bucket: t,
524
+ path: n
525
+ });
526
+ }
527
+ async uploadFile(e, { bucket: t, path: n }, { overwriteExisting: r = !1 } = {}) {
528
+ let { data: i, error: a } = await this.client.from(t).upload(`${n}/${e.name}`, e, { upsert: r });
529
+ if (a) throw a;
530
+ return {
531
+ fileId: i.id,
532
+ bucket: t,
533
+ path: i.path
534
+ };
535
+ }
536
+ async downloadFile(e) {
537
+ let { fileId: t, bucket: n, path: r, properties: i } = await this.getFileInfo(e), { data: a, error: o } = await this.client.from(n).download(r);
538
+ if (o) throw o;
539
+ let [, s] = f(r);
540
+ return {
541
+ fileId: t,
542
+ bucket: n,
543
+ path: r,
544
+ file: new File([a], s, i)
545
+ };
546
+ }
547
+ async deleteFiles(t) {
548
+ let n = t.filter((e) => "fileId" in e).map((e) => e.fileId), r = (await this.files.query.select(["bucket_id", "path_tokens"]).containedBy("id", n).throwOnError()).data.map(({ bucket_id: t, path_tokens: n }) => ({
549
+ bucket: e.notNull(t, "bucket_id must not be null"),
550
+ path: e.notNull(n, "path_tokens must not be null").join("/")
551
+ })), i = g(m(t.filter((e) => "path" in e).concat(r), (e) => e.bucket)).map(([e, t]) => ({
552
+ bucket: e,
553
+ paths: t.map((e) => e.path)
554
+ }));
555
+ return (await Promise.all(i.map(async ({ bucket: t, paths: n }) => this.client.from(t).remove(n).then(({ data: r, error: i }) => {
556
+ if (i) throw i;
557
+ return r.map((r, i) => ({
558
+ fileId: e.notNull(r.id, "file id must not be null"),
559
+ bucket: t,
560
+ path: e.defined(n[i], "path must not be null")
561
+ }));
562
+ })))).flat();
563
+ }
809
564
  };
565
+ //#endregion
566
+ export { _ as DataService, F as DatabaseService, L as EmbeddingService, o as FileNotFoundError, T as Filter, w as FilterChainSeparator, x as FilterOp, S as LogicalOp, C as LogicalOpSeparator, s as ParseError, P as PostgrestClient, u as PostgrestErrorInterface, M as PostgrestFilterBuilder, N as PostgrestQueryBuilder, c as RecordNotFoundError, R as StorageService, v as TableDataService, a as TracedError, l as UnsupportedMimeError, y as ViewDataService, b as assertCounted, p as coerceArray, k as encodeFilter, O as encodeFilterNode, g as entries, m as groupBy, d as isDatabaseApiError, D as negateFilterNode, E as negateOp, A as parseFilterExpression, j as parseFilterExpressionChain, I as preprocessingSteps, h as removeElement, f as splitPath };