@workglow/supabase 0.2.28

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.
Files changed (33) hide show
  1. package/dist/job-queue/SupabaseQueueStorage.d.ts +196 -0
  2. package/dist/job-queue/SupabaseQueueStorage.d.ts.map +1 -0
  3. package/dist/job-queue/SupabaseRateLimiterStorage.d.ts +54 -0
  4. package/dist/job-queue/SupabaseRateLimiterStorage.d.ts.map +1 -0
  5. package/dist/job-queue/browser.d.ts +7 -0
  6. package/dist/job-queue/browser.d.ts.map +1 -0
  7. package/dist/job-queue/browser.js +765 -0
  8. package/dist/job-queue/browser.js.map +11 -0
  9. package/dist/job-queue/bun.d.ts +7 -0
  10. package/dist/job-queue/bun.d.ts.map +1 -0
  11. package/dist/job-queue/common.d.ts +8 -0
  12. package/dist/job-queue/common.d.ts.map +1 -0
  13. package/dist/job-queue/node.d.ts +7 -0
  14. package/dist/job-queue/node.d.ts.map +1 -0
  15. package/dist/job-queue/node.js +765 -0
  16. package/dist/job-queue/node.js.map +11 -0
  17. package/dist/storage/SupabaseKvStorage.d.ts +32 -0
  18. package/dist/storage/SupabaseKvStorage.d.ts.map +1 -0
  19. package/dist/storage/SupabaseTabularStorage.d.ts +172 -0
  20. package/dist/storage/SupabaseTabularStorage.d.ts.map +1 -0
  21. package/dist/storage/browser.d.ts +7 -0
  22. package/dist/storage/browser.d.ts.map +1 -0
  23. package/dist/storage/browser.js +590 -0
  24. package/dist/storage/browser.js.map +11 -0
  25. package/dist/storage/bun.d.ts +7 -0
  26. package/dist/storage/bun.d.ts.map +1 -0
  27. package/dist/storage/common.d.ts +8 -0
  28. package/dist/storage/common.d.ts.map +1 -0
  29. package/dist/storage/node.d.ts +7 -0
  30. package/dist/storage/node.d.ts.map +1 -0
  31. package/dist/storage/node.js +590 -0
  32. package/dist/storage/node.js.map +11 -0
  33. package/package.json +76 -0
@@ -0,0 +1,590 @@
1
+ // src/storage/SupabaseKvStorage.ts
2
+ import { createServiceToken as createServiceToken2 } from "@workglow/util";
3
+
4
+ // src/storage/SupabaseTabularStorage.ts
5
+ import { createServiceToken } from "@workglow/util";
6
+ import {
7
+ BaseSqlTabularStorage,
8
+ isSearchCondition,
9
+ pickCoveringIndex,
10
+ StorageValidationError
11
+ } from "@workglow/storage";
12
+ var SUPABASE_TABULAR_REPOSITORY = createServiceToken("storage.tabularRepository.supabase");
13
+
14
+ class SupabaseTabularStorage extends BaseSqlTabularStorage {
15
+ client;
16
+ realtimeChannel = null;
17
+ constructor(client, table = "tabular_store", schema, primaryKeyNames, indexes = [], clientProvidedKeys = "if-missing") {
18
+ super(table, schema, primaryKeyNames, indexes, clientProvidedKeys);
19
+ this.client = client;
20
+ }
21
+ async setupDatabase() {
22
+ const sql = `
23
+ CREATE TABLE IF NOT EXISTS "${this.table}" (
24
+ ${this.constructPrimaryKeyColumns('"')} ${this.constructValueColumns('"')},
25
+ PRIMARY KEY (${this.primaryKeyColumnList()})
26
+ )
27
+ `;
28
+ const { error } = await this.client.rpc("exec_sql", { query: sql });
29
+ if (error && !error.message.includes("already exists")) {
30
+ throw error;
31
+ }
32
+ const pkColumns = this.primaryKeyColumns();
33
+ const createdIndexes = new Set;
34
+ for (const columns of this.indexes) {
35
+ if (columns.length <= pkColumns.length) {
36
+ const isPkPrefix = columns.every((col, idx) => col === pkColumns[idx]);
37
+ if (isPkPrefix)
38
+ continue;
39
+ }
40
+ const indexName = `${this.table}_${columns.join("_")}`;
41
+ const columnList = columns.map((col) => `"${String(col)}"`).join(", ");
42
+ const columnKey = columns.join(",");
43
+ if (createdIndexes.has(columnKey))
44
+ continue;
45
+ const isRedundant = Array.from(createdIndexes).some((existing) => {
46
+ const existingCols = existing.split(",");
47
+ return existingCols.length >= columns.length && columns.every((col, idx) => col === existingCols[idx]);
48
+ });
49
+ if (!isRedundant) {
50
+ const indexSql = `CREATE INDEX IF NOT EXISTS "${indexName}" ON "${this.table}" (${columnList})`;
51
+ const { error: indexError } = await this.client.rpc("exec_sql", { query: indexSql });
52
+ if (indexError && !indexError.message.includes("already exists")) {
53
+ console.warn(`Failed to create index ${indexName}:`, indexError);
54
+ }
55
+ createdIndexes.add(columnKey);
56
+ }
57
+ }
58
+ }
59
+ mapTypeToSQL(typeDef) {
60
+ const actualType = this.getNonNullType(typeDef);
61
+ if (typeof actualType === "boolean") {
62
+ return "TEXT /* boolean schema */";
63
+ }
64
+ if (actualType.contentEncoding === "blob")
65
+ return "BYTEA";
66
+ switch (actualType.type) {
67
+ case "string":
68
+ if (actualType.format === "date-time")
69
+ return "TIMESTAMP";
70
+ if (actualType.format === "date")
71
+ return "DATE";
72
+ if (actualType.format === "email")
73
+ return "VARCHAR(255)";
74
+ if (actualType.format === "uri")
75
+ return "VARCHAR(2048)";
76
+ if (actualType.format === "uuid")
77
+ return "UUID";
78
+ if (typeof actualType.maxLength === "number") {
79
+ return `VARCHAR(${actualType.maxLength})`;
80
+ }
81
+ return "TEXT";
82
+ case "number":
83
+ case "integer":
84
+ if (actualType.multipleOf === 1 || actualType.type === "integer") {
85
+ if (typeof actualType.minimum === "number") {
86
+ if (actualType.minimum >= 0) {
87
+ if (typeof actualType.maximum === "number") {
88
+ if (actualType.maximum <= 32767)
89
+ return "SMALLINT";
90
+ if (actualType.maximum <= 2147483647)
91
+ return "INTEGER";
92
+ }
93
+ return "BIGINT";
94
+ }
95
+ }
96
+ return "INTEGER";
97
+ }
98
+ if (actualType.format === "float")
99
+ return "REAL";
100
+ if (actualType.format === "double")
101
+ return "DOUBLE PRECISION";
102
+ if (typeof actualType.multipleOf === "number") {
103
+ const decimalPlaces = String(actualType.multipleOf).split(".")[1]?.length || 0;
104
+ if (decimalPlaces > 0) {
105
+ return `NUMERIC(38, ${decimalPlaces})`;
106
+ }
107
+ }
108
+ return "NUMERIC";
109
+ case "boolean":
110
+ return "BOOLEAN";
111
+ case "array":
112
+ if (actualType.items && typeof actualType.items === "object" && !Array.isArray(actualType.items)) {
113
+ const itemType = this.mapTypeToSQL(actualType.items);
114
+ const supportedArrayElementTypes = [
115
+ "TEXT",
116
+ "VARCHAR",
117
+ "CHAR",
118
+ "INTEGER",
119
+ "SMALLINT",
120
+ "BIGINT",
121
+ "REAL",
122
+ "DOUBLE PRECISION",
123
+ "NUMERIC",
124
+ "BOOLEAN",
125
+ "UUID",
126
+ "DATE",
127
+ "TIMESTAMP"
128
+ ];
129
+ const isSupported = supportedArrayElementTypes.some((type) => itemType === type || itemType.startsWith(type + "(") && type !== "VARCHAR");
130
+ if (isSupported) {
131
+ return `${itemType}[]`;
132
+ } else {
133
+ return "JSONB /* complex array */";
134
+ }
135
+ }
136
+ return "JSONB /* generic array */";
137
+ case "object":
138
+ return "JSONB /* object */";
139
+ default:
140
+ return "TEXT /* unknown type */";
141
+ }
142
+ }
143
+ constructPrimaryKeyColumns($delimiter = "") {
144
+ const cols = Object.entries(this.primaryKeySchema.properties).map(([key, typeDef]) => {
145
+ if (this.isAutoGeneratedKey(key)) {
146
+ if (this.autoGeneratedKeyStrategy === "autoincrement") {
147
+ const sqlType2 = this.mapTypeToSQL(typeDef);
148
+ const isSmallInt = sqlType2.includes("SMALLINT");
149
+ const isBigInt = sqlType2.includes("BIGINT");
150
+ const serialType = isBigInt ? "BIGSERIAL" : isSmallInt ? "SMALLSERIAL" : "SERIAL";
151
+ return `${$delimiter}${key}${$delimiter} ${serialType}`;
152
+ } else if (this.autoGeneratedKeyStrategy === "uuid") {
153
+ return `${$delimiter}${key}${$delimiter} UUID DEFAULT gen_random_uuid()`;
154
+ }
155
+ }
156
+ const sqlType = this.mapTypeToSQL(typeDef);
157
+ let constraints = "NOT NULL";
158
+ if (this.shouldBeUnsigned(typeDef)) {
159
+ constraints += ` CHECK (${$delimiter}${key}${$delimiter} >= 0)`;
160
+ }
161
+ return `${$delimiter}${key}${$delimiter} ${sqlType} ${constraints}`;
162
+ }).join(", ");
163
+ return cols;
164
+ }
165
+ constructValueColumns($delimiter = "") {
166
+ const delimiter = $delimiter || '"';
167
+ const requiredSet = new Set(this.valueSchema.required ?? []);
168
+ const cols = Object.entries(this.valueSchema.properties).map(([key, typeDef]) => {
169
+ const sqlType = this.mapTypeToSQL(typeDef);
170
+ const isRequired = requiredSet.has(key);
171
+ const nullable = !isRequired || this.isNullable(typeDef);
172
+ let constraints = nullable ? "NULL" : "NOT NULL";
173
+ if (this.shouldBeUnsigned(typeDef)) {
174
+ constraints += ` CHECK (${delimiter}${key}${delimiter} >= 0)`;
175
+ }
176
+ return `${delimiter}${key}${delimiter} ${sqlType} ${constraints}`;
177
+ }).join(", ");
178
+ if (cols.length > 0) {
179
+ return `, ${cols}`;
180
+ } else {
181
+ return "";
182
+ }
183
+ }
184
+ sqlToJsValue(column, value) {
185
+ const typeDef = this.schema.properties[column];
186
+ if (typeDef) {
187
+ if (value === null && this.isNullable(typeDef)) {
188
+ return null;
189
+ }
190
+ const actualType = this.getNonNullType(typeDef);
191
+ if (typeof actualType !== "boolean" && (actualType.type === "number" || actualType.type === "integer")) {
192
+ if (typeof value === "number")
193
+ return value;
194
+ if (typeof value === "string") {
195
+ const parsed = Number(value);
196
+ if (!isNaN(parsed))
197
+ return parsed;
198
+ }
199
+ }
200
+ }
201
+ return super.sqlToJsValue(column, value);
202
+ }
203
+ shouldBeUnsigned(typeDef) {
204
+ const actualType = this.getNonNullType(typeDef);
205
+ if (typeof actualType === "boolean") {
206
+ return false;
207
+ }
208
+ if ((actualType.type === "number" || actualType.type === "integer") && typeof actualType.minimum === "number" && actualType.minimum >= 0) {
209
+ return true;
210
+ }
211
+ return false;
212
+ }
213
+ async put(entity) {
214
+ let entityToInsert = { ...entity };
215
+ if (this.hasAutoGeneratedKey() && this.autoGeneratedKeyName) {
216
+ const keyName = String(this.autoGeneratedKeyName);
217
+ const entityRecord = entity;
218
+ const clientProvidedValue = entityRecord[keyName];
219
+ const hasClientValue = clientProvidedValue !== undefined && clientProvidedValue !== null;
220
+ let shouldOmitKey = false;
221
+ if (this.clientProvidedKeys === "never") {
222
+ shouldOmitKey = true;
223
+ } else if (this.clientProvidedKeys === "always") {
224
+ if (!hasClientValue) {
225
+ throw new Error(`Auto-generated key "${keyName}" is required when clientProvidedKeys is "always"`);
226
+ }
227
+ shouldOmitKey = false;
228
+ } else {
229
+ shouldOmitKey = !hasClientValue;
230
+ }
231
+ if (shouldOmitKey) {
232
+ delete entityToInsert[keyName];
233
+ }
234
+ }
235
+ const normalizedEntity = { ...entityToInsert };
236
+ const requiredSet = new Set(this.valueSchema.required ?? []);
237
+ for (const key in this.valueSchema.properties) {
238
+ if (!(key in normalizedEntity) || normalizedEntity[key] === undefined) {
239
+ if (!requiredSet.has(key)) {
240
+ normalizedEntity[key] = null;
241
+ }
242
+ }
243
+ }
244
+ const { data, error } = await this.client.from(this.table).upsert(normalizedEntity, { onConflict: this.primaryKeyColumnList() }).select().single();
245
+ if (error)
246
+ throw error;
247
+ const updatedEntity = data;
248
+ const updatedRecord = updatedEntity;
249
+ for (const key in this.schema.properties) {
250
+ updatedRecord[key] = this.sqlToJsValue(key, updatedRecord[key]);
251
+ }
252
+ this.events.emit("put", updatedEntity);
253
+ return updatedEntity;
254
+ }
255
+ async putBulk(entities) {
256
+ if (entities.length === 0)
257
+ return [];
258
+ return await Promise.all(entities.map((entity) => this.put(entity)));
259
+ }
260
+ async get(key) {
261
+ let query = this.client.from(this.table).select("*");
262
+ const keyRecord = key;
263
+ for (const pkName of this.primaryKeyNames) {
264
+ query = query.eq(String(pkName), keyRecord[String(pkName)]);
265
+ }
266
+ const { data, error } = await query.single();
267
+ if (error) {
268
+ if (error.code === "PGRST116") {
269
+ this.events.emit("get", key, undefined);
270
+ return;
271
+ }
272
+ throw error;
273
+ }
274
+ const val = data;
275
+ if (val) {
276
+ const valRecord = val;
277
+ for (const key2 in this.schema.properties) {
278
+ valRecord[key2] = this.sqlToJsValue(key2, valRecord[key2]);
279
+ }
280
+ }
281
+ this.events.emit("get", key, val);
282
+ return val;
283
+ }
284
+ async delete(value) {
285
+ const { key } = this.separateKeyValueFromCombined(value);
286
+ let query = this.client.from(this.table).delete();
287
+ const deleteKeyRecord = key;
288
+ for (const pkName of this.primaryKeyNames) {
289
+ query = query.eq(String(pkName), deleteKeyRecord[String(pkName)]);
290
+ }
291
+ const { error } = await query;
292
+ if (error)
293
+ throw error;
294
+ this.events.emit("delete", key);
295
+ }
296
+ async getAll(options) {
297
+ this.validateGetAllOptions(options);
298
+ let query = this.client.from(this.table).select("*");
299
+ if (options?.orderBy) {
300
+ for (const { column, direction } of options.orderBy) {
301
+ query = query.order(String(column), { ascending: direction === "ASC" });
302
+ }
303
+ }
304
+ if (options?.offset !== undefined || options?.limit !== undefined) {
305
+ const start = options?.offset ?? 0;
306
+ if (options?.limit !== undefined) {
307
+ query = query.range(start, start + options.limit - 1);
308
+ } else if (options?.offset !== undefined) {
309
+ query = query.range(start, start + 999999);
310
+ }
311
+ }
312
+ const { data, error } = await query;
313
+ if (error)
314
+ throw error;
315
+ if (data && data.length) {
316
+ for (const row of data) {
317
+ const record = row;
318
+ for (const key in this.schema.properties) {
319
+ record[key] = this.sqlToJsValue(key, record[key]);
320
+ }
321
+ }
322
+ return data;
323
+ }
324
+ return;
325
+ }
326
+ async deleteAll() {
327
+ const firstPkColumn = this.primaryKeyNames[0];
328
+ const { error } = await this.client.from(this.table).delete().neq(String(firstPkColumn), null);
329
+ if (error)
330
+ throw error;
331
+ this.events.emit("clearall");
332
+ }
333
+ async size() {
334
+ const { count, error } = await this.client.from(this.table).select("*", { count: "exact", head: true });
335
+ if (error)
336
+ throw error;
337
+ return count ?? 0;
338
+ }
339
+ async getBulk(offset, limit) {
340
+ let query = this.client.from(this.table).select("*");
341
+ for (const pkName of this.primaryKeyNames) {
342
+ query = query.order(String(pkName));
343
+ }
344
+ const { data, error } = await query.range(offset, offset + limit - 1);
345
+ if (error)
346
+ throw error;
347
+ if (!data || data.length === 0) {
348
+ return;
349
+ }
350
+ for (const row of data) {
351
+ const record = row;
352
+ for (const key in this.schema.properties) {
353
+ record[key] = this.sqlToJsValue(key, record[key]);
354
+ }
355
+ }
356
+ return data;
357
+ }
358
+ applyCriteriaToFilter(query, criteria) {
359
+ let q = query;
360
+ for (const column of Object.keys(criteria)) {
361
+ const criterion = criteria[column];
362
+ let operator = "=";
363
+ let value;
364
+ if (isSearchCondition(criterion)) {
365
+ operator = criterion.operator;
366
+ value = criterion.value;
367
+ } else {
368
+ value = criterion;
369
+ }
370
+ switch (operator) {
371
+ case "=":
372
+ q = q.eq(String(column), value);
373
+ break;
374
+ case "<":
375
+ q = q.lt(String(column), value);
376
+ break;
377
+ case "<=":
378
+ q = q.lte(String(column), value);
379
+ break;
380
+ case ">":
381
+ q = q.gt(String(column), value);
382
+ break;
383
+ case ">=":
384
+ q = q.gte(String(column), value);
385
+ break;
386
+ }
387
+ }
388
+ return q;
389
+ }
390
+ async count(criteria) {
391
+ if (!criteria || Object.keys(criteria).length === 0) {
392
+ return await this.size();
393
+ }
394
+ this.validateQueryParams(criteria);
395
+ const query = this.applyCriteriaToFilter(this.client.from(this.table).select("*", { count: "exact", head: true }), criteria);
396
+ const { count, error } = await query;
397
+ if (error)
398
+ throw error;
399
+ return count ?? 0;
400
+ }
401
+ async deleteSearch(criteria) {
402
+ const criteriaKeys = Object.keys(criteria);
403
+ if (criteriaKeys.length === 0) {
404
+ return;
405
+ }
406
+ let query = this.client.from(this.table).delete();
407
+ for (const column of criteriaKeys) {
408
+ if (!(column in this.schema.properties)) {
409
+ throw new Error(`Schema must have a ${String(column)} field to use deleteSearch`);
410
+ }
411
+ const criterion = criteria[column];
412
+ let operator = "=";
413
+ let value;
414
+ if (isSearchCondition(criterion)) {
415
+ operator = criterion.operator;
416
+ value = criterion.value;
417
+ } else {
418
+ value = criterion;
419
+ }
420
+ switch (operator) {
421
+ case "=":
422
+ query = query.eq(String(column), value);
423
+ break;
424
+ case "<":
425
+ query = query.lt(String(column), value);
426
+ break;
427
+ case "<=":
428
+ query = query.lte(String(column), value);
429
+ break;
430
+ case ">":
431
+ query = query.gt(String(column), value);
432
+ break;
433
+ case ">=":
434
+ query = query.gte(String(column), value);
435
+ break;
436
+ }
437
+ }
438
+ const { error } = await query;
439
+ if (error)
440
+ throw error;
441
+ this.events.emit("delete", criteriaKeys[0]);
442
+ }
443
+ async query(criteria, options) {
444
+ this.validateQueryParams(criteria, options);
445
+ let query = this.applyCriteriaToFilter(this.client.from(this.table).select("*"), criteria);
446
+ if (options?.orderBy) {
447
+ for (const { column, direction } of options.orderBy) {
448
+ query = query.order(String(column), { ascending: direction === "ASC" });
449
+ }
450
+ }
451
+ if (options?.offset !== undefined || options?.limit !== undefined) {
452
+ const start = options?.offset ?? 0;
453
+ if (options?.limit !== undefined) {
454
+ query = query.range(start, start + options.limit - 1);
455
+ } else if (options?.offset !== undefined) {
456
+ query = query.range(start, start + 999999);
457
+ }
458
+ } else if (options?.limit !== undefined) {
459
+ query = query.limit(options.limit);
460
+ }
461
+ const { data, error } = await query;
462
+ if (error)
463
+ throw error;
464
+ if (data && data.length > 0) {
465
+ for (const row of data) {
466
+ const record = row;
467
+ for (const key in this.schema.properties) {
468
+ record[key] = this.sqlToJsValue(key, record[key]);
469
+ }
470
+ }
471
+ this.events.emit("query", criteria, data);
472
+ return data;
473
+ }
474
+ this.events.emit("query", criteria, undefined);
475
+ return;
476
+ }
477
+ async queryIndex(criteria, options) {
478
+ this.validateSelect(options);
479
+ this.validateQueryParams(criteria, options);
480
+ const registered = this.indexes.map((cols, i) => {
481
+ const cs = Array.isArray(cols) ? cols : [cols];
482
+ return { name: `idx_${i}`, keyPath: cs };
483
+ });
484
+ pickCoveringIndex({
485
+ table: this.table,
486
+ indexes: registered,
487
+ criteriaColumns: Object.keys(criteria),
488
+ orderByColumns: (options.orderBy ?? []).map((o) => ({
489
+ column: String(o.column),
490
+ direction: o.direction
491
+ })),
492
+ selectColumns: options.select.map(String),
493
+ primaryKeyColumns: this.primaryKeyNames.map(String)
494
+ });
495
+ const colList = options.select.map(String).join(",");
496
+ let q = this.applyCriteriaToFilter(this.client.from(this.table).select(colList), criteria);
497
+ if (options.orderBy) {
498
+ for (const { column, direction } of options.orderBy) {
499
+ q = q.order(String(column), { ascending: direction === "ASC" });
500
+ }
501
+ }
502
+ if (options.offset !== undefined && options.limit === undefined) {
503
+ throw new StorageValidationError("queryIndex with offset requires limit (no implicit cap)");
504
+ }
505
+ if (options.offset !== undefined || options.limit !== undefined) {
506
+ const start = options.offset ?? 0;
507
+ if (options.limit !== undefined) {
508
+ q = q.range(start, start + options.limit - 1);
509
+ }
510
+ }
511
+ const { data, error } = await q;
512
+ if (error)
513
+ throw error;
514
+ if (!data)
515
+ return [];
516
+ const rows = data;
517
+ const sel = new Set(options.select.map(String));
518
+ for (const row of rows) {
519
+ for (const key of Object.keys(row)) {
520
+ if (sel.has(key)) {
521
+ row[key] = this.sqlToJsValue(key, row[key]);
522
+ }
523
+ }
524
+ }
525
+ return rows;
526
+ }
527
+ convertRealtimeRow(row) {
528
+ const entity = { ...row };
529
+ const record = entity;
530
+ for (const key in this.schema.properties) {
531
+ record[key] = this.sqlToJsValue(key, row[key]);
532
+ }
533
+ return entity;
534
+ }
535
+ subscribeToChanges(callback, options) {
536
+ const channelName = `tabular-${this.table}-${Date.now()}`;
537
+ this.realtimeChannel = this.client.channel(channelName).on("postgres_changes", {
538
+ event: "*",
539
+ schema: "public",
540
+ table: this.table
541
+ }, (payload) => {
542
+ const change = {
543
+ type: payload.eventType.toUpperCase(),
544
+ old: payload.old && Object.keys(payload.old).length > 0 ? this.convertRealtimeRow(payload.old) : undefined,
545
+ new: payload.new && Object.keys(payload.new).length > 0 ? this.convertRealtimeRow(payload.new) : undefined
546
+ };
547
+ callback(change);
548
+ }).subscribe();
549
+ return () => {
550
+ if (this.realtimeChannel) {
551
+ this.client.removeChannel(this.realtimeChannel);
552
+ this.realtimeChannel = null;
553
+ }
554
+ };
555
+ }
556
+ destroy() {
557
+ if (this.realtimeChannel) {
558
+ this.client.removeChannel(this.realtimeChannel);
559
+ this.realtimeChannel = null;
560
+ }
561
+ }
562
+ }
563
+
564
+ // src/storage/SupabaseKvStorage.ts
565
+ import {
566
+ DefaultKeyValueKey,
567
+ DefaultKeyValueSchema,
568
+ KvViaTabularStorage
569
+ } from "@workglow/storage";
570
+ var SUPABASE_KV_REPOSITORY = createServiceToken2("storage.kvRepository.supabase");
571
+
572
+ class SupabaseKvStorage extends KvViaTabularStorage {
573
+ client;
574
+ tableName;
575
+ tabularRepository;
576
+ constructor(client, tableName, keySchema = { type: "string" }, valueSchema = {}, tabularRepository) {
577
+ super(keySchema, valueSchema);
578
+ this.client = client;
579
+ this.tableName = tableName;
580
+ this.tabularRepository = tabularRepository ?? new SupabaseTabularStorage(client, tableName, DefaultKeyValueSchema, DefaultKeyValueKey);
581
+ }
582
+ }
583
+ export {
584
+ SupabaseTabularStorage,
585
+ SupabaseKvStorage,
586
+ SUPABASE_TABULAR_REPOSITORY,
587
+ SUPABASE_KV_REPOSITORY
588
+ };
589
+
590
+ //# debugId=B85032AFACA2DABD64756E2164756E21