@pol-studios/db 1.0.54 → 1.0.56
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/{DataLayerContext-C7cJtiO8.d.ts → DataLayerContext-BYZtDD0g.d.ts} +1 -1
- package/dist/auth/context.js +6 -4
- package/dist/auth/hooks.js +7 -5
- package/dist/auth/index.js +7 -5
- package/dist/{chunk-FIAXWEBK.js → chunk-4EO55YV2.js} +10 -7
- package/dist/chunk-4EO55YV2.js.map +1 -0
- package/dist/{chunk-DP3YEVSX.js → chunk-6SDH7M7J.js} +26 -10
- package/dist/chunk-6SDH7M7J.js.map +1 -0
- package/dist/{chunk-UJWETW36.js → chunk-AKIRHA4Q.js} +527 -418
- package/dist/chunk-AKIRHA4Q.js.map +1 -0
- package/dist/{chunk-2XS2PM62.js → chunk-DDL63KLQ.js} +388 -107
- package/dist/chunk-DDL63KLQ.js.map +1 -0
- package/dist/{chunk-YA6MUTA7.js → chunk-FI6JAD5G.js} +3 -3
- package/dist/{chunk-WQLIGVQR.js → chunk-GWYTROSD.js} +98 -1
- package/dist/chunk-GWYTROSD.js.map +1 -0
- package/dist/chunk-JOULSXOI.js +415 -0
- package/dist/chunk-JOULSXOI.js.map +1 -0
- package/dist/{chunk-OKYHI6JG.js → chunk-LF3V3ERS.js} +3 -3
- package/dist/{chunk-FMYXG4VN.js → chunk-MEBT5YHA.js} +2 -2
- package/dist/{chunk-BZSAPFFB.js → chunk-N4KK5G5T.js} +116 -18
- package/dist/chunk-N4KK5G5T.js.map +1 -0
- package/dist/chunk-QYAFI34Q.js +64 -0
- package/dist/chunk-QYAFI34Q.js.map +1 -0
- package/dist/{chunk-3Q74DK5K.js → chunk-VYFAMTHI.js} +2 -2
- package/dist/chunk-W7PERM66.js +215 -0
- package/dist/chunk-W7PERM66.js.map +1 -0
- package/dist/{chunk-ZGQ7Q4ZU.js → chunk-WM25QE7E.js} +2 -2
- package/dist/{chunk-HZIVE5AZ.js → chunk-YRIPM2AN.js} +253 -338
- package/dist/chunk-YRIPM2AN.js.map +1 -0
- package/dist/chunk-YUX6RGLZ.js +1858 -0
- package/dist/chunk-YUX6RGLZ.js.map +1 -0
- package/dist/{chunk-Z3EJX3VG.js → chunk-Z456IHCB.js} +3 -3
- package/dist/core/index.d.ts +24 -1
- package/dist/{executor-YJw4m7Q7.d.ts → executor-D15yjeMo.d.ts} +20 -0
- package/dist/hooks/index.d.ts +3 -3
- package/dist/hooks/index.js +4 -2
- package/dist/{index-jVYdTeWx.d.ts → index-CFUuTzXO.d.ts} +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +16 -14
- package/dist/index.native.d.ts +62 -8
- package/dist/index.native.js +16 -14
- package/dist/index.web.d.ts +10 -9
- package/dist/index.web.js +30 -19
- package/dist/index.web.js.map +1 -1
- package/dist/mutation/index.js +3 -3
- package/dist/parser/index.js +3 -3
- package/dist/powersync-bridge/index.d.ts +1 -1
- package/dist/query/index.d.ts +4 -83
- package/dist/query/index.js +17 -7
- package/dist/realtime/index.d.ts +80 -1
- package/dist/realtime/index.js +14 -12
- package/dist/realtime/index.js.map +1 -1
- package/dist/select-parser-BAV7fOaM.d.ts +144 -0
- package/dist/types/index.d.ts +3 -3
- package/dist/types/index.js +4 -4
- package/dist/{useDbCount-DHLJzmkO.d.ts → useDbCount-Ckb-FhZk.d.ts} +1 -1
- package/dist/{useResolveFeedback-B0UcYWVI.d.ts → useResolveFeedback-CuUkdHoR.d.ts} +13 -29
- package/dist/with-auth/index.js +9 -7
- package/dist/with-auth/index.js.map +1 -1
- package/package.json +9 -4
- package/dist/chunk-2XS2PM62.js.map +0 -1
- package/dist/chunk-BZSAPFFB.js.map +0 -1
- package/dist/chunk-CTRY7JDP.js +0 -4112
- package/dist/chunk-CTRY7JDP.js.map +0 -1
- package/dist/chunk-DP3YEVSX.js.map +0 -1
- package/dist/chunk-FIAXWEBK.js.map +0 -1
- package/dist/chunk-HZIVE5AZ.js.map +0 -1
- package/dist/chunk-INEUG6MC.js +0 -521
- package/dist/chunk-INEUG6MC.js.map +0 -1
- package/dist/chunk-UJWETW36.js.map +0 -1
- package/dist/chunk-WQLIGVQR.js.map +0 -1
- /package/dist/{chunk-YA6MUTA7.js.map → chunk-FI6JAD5G.js.map} +0 -0
- /package/dist/{chunk-OKYHI6JG.js.map → chunk-LF3V3ERS.js.map} +0 -0
- /package/dist/{chunk-FMYXG4VN.js.map → chunk-MEBT5YHA.js.map} +0 -0
- /package/dist/{chunk-3Q74DK5K.js.map → chunk-VYFAMTHI.js.map} +0 -0
- /package/dist/{chunk-ZGQ7Q4ZU.js.map → chunk-WM25QE7E.js.map} +0 -0
- /package/dist/{chunk-Z3EJX3VG.js.map → chunk-Z456IHCB.js.map} +0 -0
|
@@ -1,24 +1,31 @@
|
|
|
1
1
|
import {
|
|
2
2
|
useDbUpsert
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-VYFAMTHI.js";
|
|
4
4
|
import {
|
|
5
5
|
normalizeFilter
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-Z456IHCB.js";
|
|
7
7
|
import {
|
|
8
8
|
OperationLog
|
|
9
9
|
} from "./chunk-7SCJNYTE.js";
|
|
10
10
|
import {
|
|
11
11
|
useDbQuery
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-6SDH7M7J.js";
|
|
13
13
|
import {
|
|
14
14
|
useDataLayerCoreOptional
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-GWYTROSD.js";
|
|
16
|
+
import {
|
|
17
|
+
ResultJoiner
|
|
18
|
+
} from "./chunk-YRIPM2AN.js";
|
|
16
19
|
import {
|
|
17
20
|
getSupabaseUrl
|
|
18
21
|
} from "./chunk-GC3TBUWE.js";
|
|
22
|
+
import {
|
|
23
|
+
parseSelect,
|
|
24
|
+
selectHasExplicitFkSyntax
|
|
25
|
+
} from "./chunk-W7PERM66.js";
|
|
19
26
|
import {
|
|
20
27
|
PostgrestParser
|
|
21
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-JOULSXOI.js";
|
|
22
29
|
import {
|
|
23
30
|
buildNormalizedQuery,
|
|
24
31
|
encode,
|
|
@@ -28,7 +35,7 @@ import {
|
|
|
28
35
|
useQueriesForTableLoader,
|
|
29
36
|
useQuery,
|
|
30
37
|
useUpsertItem
|
|
31
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-YUX6RGLZ.js";
|
|
32
39
|
import {
|
|
33
40
|
UserSessionId,
|
|
34
41
|
useSupabase
|
|
@@ -5094,6 +5101,343 @@ function createAdapterAutoDetector(powerSyncDb, supabase, options) {
|
|
|
5094
5101
|
return new AdapterAutoDetector(powerSyncDb, supabase, options);
|
|
5095
5102
|
}
|
|
5096
5103
|
|
|
5104
|
+
// src/query/supabase-utils.ts
|
|
5105
|
+
var DEFAULT_SCHEMA = "public";
|
|
5106
|
+
function parseTableIdentifier(table) {
|
|
5107
|
+
if (table.includes(".")) {
|
|
5108
|
+
const [schema, ...rest] = table.split(".");
|
|
5109
|
+
return {
|
|
5110
|
+
schema,
|
|
5111
|
+
tableName: rest.join(".")
|
|
5112
|
+
};
|
|
5113
|
+
}
|
|
5114
|
+
return {
|
|
5115
|
+
schema: DEFAULT_SCHEMA,
|
|
5116
|
+
tableName: table
|
|
5117
|
+
};
|
|
5118
|
+
}
|
|
5119
|
+
function applyWhereClause(query, where) {
|
|
5120
|
+
for (const [field, condition] of Object.entries(where)) {
|
|
5121
|
+
if (condition === null) {
|
|
5122
|
+
query = query.is(field, null);
|
|
5123
|
+
} else if (typeof condition === "string" || typeof condition === "number" || typeof condition === "boolean") {
|
|
5124
|
+
query = query.eq(field, condition);
|
|
5125
|
+
} else if (typeof condition === "object") {
|
|
5126
|
+
const operators = condition;
|
|
5127
|
+
if (operators.in !== void 0) {
|
|
5128
|
+
query = query.in(field, operators.in);
|
|
5129
|
+
}
|
|
5130
|
+
if (operators.gt !== void 0) {
|
|
5131
|
+
query = query.gt(field, operators.gt);
|
|
5132
|
+
}
|
|
5133
|
+
if (operators.gte !== void 0) {
|
|
5134
|
+
query = query.gte(field, operators.gte);
|
|
5135
|
+
}
|
|
5136
|
+
if (operators.lt !== void 0) {
|
|
5137
|
+
query = query.lt(field, operators.lt);
|
|
5138
|
+
}
|
|
5139
|
+
if (operators.lte !== void 0) {
|
|
5140
|
+
query = query.lte(field, operators.lte);
|
|
5141
|
+
}
|
|
5142
|
+
if (operators.like !== void 0) {
|
|
5143
|
+
query = query.ilike(field, operators.like);
|
|
5144
|
+
}
|
|
5145
|
+
if (operators.is !== void 0) {
|
|
5146
|
+
query = query.is(field, null);
|
|
5147
|
+
}
|
|
5148
|
+
if (operators.neq !== void 0) {
|
|
5149
|
+
if (operators.neq === null) {
|
|
5150
|
+
query = query.not(field, "is", null);
|
|
5151
|
+
} else {
|
|
5152
|
+
query = query.neq(field, operators.neq);
|
|
5153
|
+
}
|
|
5154
|
+
}
|
|
5155
|
+
if (operators.notIn !== void 0) {
|
|
5156
|
+
query = query.not(field, "in", `(${operators.notIn.join(",")})`);
|
|
5157
|
+
}
|
|
5158
|
+
}
|
|
5159
|
+
}
|
|
5160
|
+
return query;
|
|
5161
|
+
}
|
|
5162
|
+
|
|
5163
|
+
// src/query/supabase-executor.ts
|
|
5164
|
+
var SupabaseQueryExecutor = class {
|
|
5165
|
+
constructor(supabase, schema) {
|
|
5166
|
+
this.supabase = supabase;
|
|
5167
|
+
this.schema = schema;
|
|
5168
|
+
this.joiner = new ResultJoiner();
|
|
5169
|
+
}
|
|
5170
|
+
joiner;
|
|
5171
|
+
/**
|
|
5172
|
+
* Execute a query and return results.
|
|
5173
|
+
*
|
|
5174
|
+
* @param table - The table to query (optionally schema-qualified, e.g., "chat.Message")
|
|
5175
|
+
* @param options - Query options including select, where, orderBy, limit, offset
|
|
5176
|
+
* @returns Object with data array and optional count
|
|
5177
|
+
*/
|
|
5178
|
+
async execute(table, options = {}) {
|
|
5179
|
+
const parsed = parseSelect(options.select ?? "*");
|
|
5180
|
+
const parentSelect = this.buildParentSelect(parsed.columns, parsed.relations);
|
|
5181
|
+
const {
|
|
5182
|
+
schema: schemaName,
|
|
5183
|
+
tableName
|
|
5184
|
+
} = parseTableIdentifier(table);
|
|
5185
|
+
const parentResult = await this.queryTable(schemaName, tableName, parentSelect, options);
|
|
5186
|
+
const parentRecords = parentResult.data;
|
|
5187
|
+
if (parentRecords.length === 0 || parsed.relations.length === 0) {
|
|
5188
|
+
return {
|
|
5189
|
+
data: parentRecords,
|
|
5190
|
+
count: parentResult.count
|
|
5191
|
+
};
|
|
5192
|
+
}
|
|
5193
|
+
const result = await this.queryAndJoinRelations(table, parentRecords, parsed.relations);
|
|
5194
|
+
return {
|
|
5195
|
+
data: result,
|
|
5196
|
+
count: parentResult.count
|
|
5197
|
+
};
|
|
5198
|
+
}
|
|
5199
|
+
/**
|
|
5200
|
+
* Execute a query for a single record by ID.
|
|
5201
|
+
*
|
|
5202
|
+
* @param table - The table to query (optionally schema-qualified)
|
|
5203
|
+
* @param id - The record ID
|
|
5204
|
+
* @param options - Query options (only select is used)
|
|
5205
|
+
* @returns Single record or null
|
|
5206
|
+
*/
|
|
5207
|
+
async executeById(table, id, options = {}) {
|
|
5208
|
+
const result = await this.execute(table, {
|
|
5209
|
+
...options,
|
|
5210
|
+
where: {
|
|
5211
|
+
id
|
|
5212
|
+
},
|
|
5213
|
+
limit: 1
|
|
5214
|
+
});
|
|
5215
|
+
return result.data[0] ?? null;
|
|
5216
|
+
}
|
|
5217
|
+
/**
|
|
5218
|
+
* Build the select string for the parent query.
|
|
5219
|
+
* For relations with explicit FK, we only need the FK column from the parent.
|
|
5220
|
+
* Standard relations are passed through to Supabase's PostgREST.
|
|
5221
|
+
*/
|
|
5222
|
+
buildParentSelect(columns, relations) {
|
|
5223
|
+
const parts = [];
|
|
5224
|
+
if (columns === "*") {
|
|
5225
|
+
parts.push("*");
|
|
5226
|
+
} else {
|
|
5227
|
+
for (const col of columns) {
|
|
5228
|
+
if (col.alias) {
|
|
5229
|
+
parts.push(`${col.alias}:${col.name}`);
|
|
5230
|
+
} else {
|
|
5231
|
+
parts.push(col.name);
|
|
5232
|
+
}
|
|
5233
|
+
}
|
|
5234
|
+
}
|
|
5235
|
+
for (const rel of relations) {
|
|
5236
|
+
if (!rel.explicitFk) {
|
|
5237
|
+
const innerSelect = this.buildNestedSelect(rel);
|
|
5238
|
+
if (rel.alias) {
|
|
5239
|
+
parts.push(`${rel.alias}:${rel.name}(${innerSelect})`);
|
|
5240
|
+
} else {
|
|
5241
|
+
parts.push(`${rel.name}(${innerSelect})`);
|
|
5242
|
+
}
|
|
5243
|
+
}
|
|
5244
|
+
}
|
|
5245
|
+
return parts.join(", ");
|
|
5246
|
+
}
|
|
5247
|
+
/**
|
|
5248
|
+
* Build the select string for a nested relation (recursive).
|
|
5249
|
+
*/
|
|
5250
|
+
buildNestedSelect(rel) {
|
|
5251
|
+
const parts = [];
|
|
5252
|
+
if (rel.columns === "*") {
|
|
5253
|
+
parts.push("*");
|
|
5254
|
+
} else {
|
|
5255
|
+
for (const col of rel.columns) {
|
|
5256
|
+
if (col.alias) {
|
|
5257
|
+
parts.push(`${col.alias}:${col.name}`);
|
|
5258
|
+
} else {
|
|
5259
|
+
parts.push(col.name);
|
|
5260
|
+
}
|
|
5261
|
+
}
|
|
5262
|
+
}
|
|
5263
|
+
for (const nested of rel.relations) {
|
|
5264
|
+
if (!nested.explicitFk) {
|
|
5265
|
+
const innerSelect = this.buildNestedSelect(nested);
|
|
5266
|
+
if (nested.alias) {
|
|
5267
|
+
parts.push(`${nested.alias}:${nested.name}(${innerSelect})`);
|
|
5268
|
+
} else {
|
|
5269
|
+
parts.push(`${nested.name}(${innerSelect})`);
|
|
5270
|
+
}
|
|
5271
|
+
}
|
|
5272
|
+
}
|
|
5273
|
+
return parts.join(", ");
|
|
5274
|
+
}
|
|
5275
|
+
/**
|
|
5276
|
+
* Query a table via Supabase.
|
|
5277
|
+
*/
|
|
5278
|
+
async queryTable(schemaName, tableName, select, options) {
|
|
5279
|
+
let query = this.supabase.schema(schemaName).from(tableName).select(select, {
|
|
5280
|
+
count: "exact"
|
|
5281
|
+
});
|
|
5282
|
+
if (options.where) {
|
|
5283
|
+
query = applyWhereClause(query, options.where);
|
|
5284
|
+
}
|
|
5285
|
+
if (options.orderBy && options.orderBy.length > 0) {
|
|
5286
|
+
for (const order of options.orderBy) {
|
|
5287
|
+
query = query.order(order.field, {
|
|
5288
|
+
ascending: order.direction === "asc"
|
|
5289
|
+
});
|
|
5290
|
+
}
|
|
5291
|
+
}
|
|
5292
|
+
if (options.limit !== void 0 && options.offset !== void 0) {
|
|
5293
|
+
query = query.range(options.offset, options.offset + options.limit - 1);
|
|
5294
|
+
} else if (options.limit !== void 0) {
|
|
5295
|
+
query = query.limit(options.limit);
|
|
5296
|
+
}
|
|
5297
|
+
const {
|
|
5298
|
+
data,
|
|
5299
|
+
error,
|
|
5300
|
+
count
|
|
5301
|
+
} = await query;
|
|
5302
|
+
if (error) {
|
|
5303
|
+
throw new Error(`Supabase query error on ${schemaName}.${tableName}: ${error.message}`);
|
|
5304
|
+
}
|
|
5305
|
+
return {
|
|
5306
|
+
data: data ?? [],
|
|
5307
|
+
count: count ?? void 0
|
|
5308
|
+
};
|
|
5309
|
+
}
|
|
5310
|
+
/**
|
|
5311
|
+
* Query related records using an IN filter.
|
|
5312
|
+
*/
|
|
5313
|
+
async queryRelatedRecords(schemaName, tableName, select, filterColumn, filterValues) {
|
|
5314
|
+
if (filterValues.length === 0) {
|
|
5315
|
+
return [];
|
|
5316
|
+
}
|
|
5317
|
+
const {
|
|
5318
|
+
data,
|
|
5319
|
+
error
|
|
5320
|
+
} = await this.supabase.schema(schemaName).from(tableName).select(select).in(filterColumn, filterValues);
|
|
5321
|
+
if (error) {
|
|
5322
|
+
throw new Error(`Supabase relation query error on ${schemaName}.${tableName}: ${error.message}`);
|
|
5323
|
+
}
|
|
5324
|
+
return data ?? [];
|
|
5325
|
+
}
|
|
5326
|
+
/**
|
|
5327
|
+
* Query and join relations onto parent records.
|
|
5328
|
+
*
|
|
5329
|
+
* @param parentTable - The parent table name
|
|
5330
|
+
* @param parentRecords - Parent records to add relations to
|
|
5331
|
+
* @param relations - Relations to query and join
|
|
5332
|
+
* @returns Parent records with relations attached
|
|
5333
|
+
*/
|
|
5334
|
+
async queryAndJoinRelations(parentTable, parentRecords, relations) {
|
|
5335
|
+
const explicitFkRelations = relations.filter((r) => r.explicitFk);
|
|
5336
|
+
if (explicitFkRelations.length === 0) {
|
|
5337
|
+
return parentRecords;
|
|
5338
|
+
}
|
|
5339
|
+
const idCache = /* @__PURE__ */ new Map();
|
|
5340
|
+
const getIdsForColumn = (column) => {
|
|
5341
|
+
if (!idCache.has(column)) {
|
|
5342
|
+
idCache.set(column, this.joiner.extractUniqueValues(parentRecords, column));
|
|
5343
|
+
}
|
|
5344
|
+
return idCache.get(column);
|
|
5345
|
+
};
|
|
5346
|
+
const relationResults = await Promise.all(explicitFkRelations.map(async (relation) => {
|
|
5347
|
+
const resolved = this.buildExplicitFkRelationship(parentTable, relation);
|
|
5348
|
+
const idColumn = resolved.type === "one-to-many" ? resolved.referencedColumn : resolved.foreignKey;
|
|
5349
|
+
const parentIds = getIdsForColumn(idColumn);
|
|
5350
|
+
if (parentIds.length === 0) {
|
|
5351
|
+
return {
|
|
5352
|
+
relation,
|
|
5353
|
+
resolved,
|
|
5354
|
+
records: []
|
|
5355
|
+
};
|
|
5356
|
+
}
|
|
5357
|
+
const filterColumn = resolved.type === "one-to-many" ? resolved.foreignKey : resolved.referencedColumn;
|
|
5358
|
+
const relSelect = this.buildRelatedSelect(relation);
|
|
5359
|
+
const {
|
|
5360
|
+
schema: targetSchema,
|
|
5361
|
+
tableName: targetTable
|
|
5362
|
+
} = parseTableIdentifier(relation.explicitFk.targetTable);
|
|
5363
|
+
let records = await this.queryRelatedRecords(targetSchema, targetTable, relSelect, filterColumn, parentIds);
|
|
5364
|
+
if (relation.relations.length > 0 && records.length > 0) {
|
|
5365
|
+
const nestedExplicitFk = relation.relations.filter((r) => r.explicitFk);
|
|
5366
|
+
if (nestedExplicitFk.length > 0) {
|
|
5367
|
+
records = await this.queryAndJoinRelations(relation.explicitFk.targetTable, records, relation.relations);
|
|
5368
|
+
}
|
|
5369
|
+
}
|
|
5370
|
+
return {
|
|
5371
|
+
relation,
|
|
5372
|
+
resolved,
|
|
5373
|
+
records
|
|
5374
|
+
};
|
|
5375
|
+
}));
|
|
5376
|
+
let result = [...parentRecords];
|
|
5377
|
+
for (const {
|
|
5378
|
+
relation,
|
|
5379
|
+
resolved,
|
|
5380
|
+
records
|
|
5381
|
+
} of relationResults) {
|
|
5382
|
+
const relationName = relation.alias ?? relation.name;
|
|
5383
|
+
if (records.length === 0) {
|
|
5384
|
+
result = result.map((r) => ({
|
|
5385
|
+
...r,
|
|
5386
|
+
[relationName]: resolved.type === "one-to-many" ? [] : null
|
|
5387
|
+
}));
|
|
5388
|
+
continue;
|
|
5389
|
+
}
|
|
5390
|
+
result = this.joiner.join(result, records, resolved, relationName);
|
|
5391
|
+
}
|
|
5392
|
+
return result;
|
|
5393
|
+
}
|
|
5394
|
+
/**
|
|
5395
|
+
* Build the select string for a related table.
|
|
5396
|
+
*/
|
|
5397
|
+
buildRelatedSelect(relation) {
|
|
5398
|
+
const parts = [];
|
|
5399
|
+
if (relation.columns === "*") {
|
|
5400
|
+
parts.push("*");
|
|
5401
|
+
} else {
|
|
5402
|
+
for (const col of relation.columns) {
|
|
5403
|
+
if (col.alias) {
|
|
5404
|
+
parts.push(`${col.alias}:${col.name}`);
|
|
5405
|
+
} else {
|
|
5406
|
+
parts.push(col.name);
|
|
5407
|
+
}
|
|
5408
|
+
}
|
|
5409
|
+
}
|
|
5410
|
+
for (const nested of relation.relations) {
|
|
5411
|
+
if (!nested.explicitFk) {
|
|
5412
|
+
const innerSelect = this.buildNestedSelect(nested);
|
|
5413
|
+
if (nested.alias) {
|
|
5414
|
+
parts.push(`${nested.alias}:${nested.name}(${innerSelect})`);
|
|
5415
|
+
} else {
|
|
5416
|
+
parts.push(`${nested.name}(${innerSelect})`);
|
|
5417
|
+
}
|
|
5418
|
+
}
|
|
5419
|
+
}
|
|
5420
|
+
return parts.join(", ");
|
|
5421
|
+
}
|
|
5422
|
+
/**
|
|
5423
|
+
* Build a ResolvedRelationship from an explicit FK specification.
|
|
5424
|
+
* This bypasses schema lookup and constructs the relationship directly.
|
|
5425
|
+
*/
|
|
5426
|
+
buildExplicitFkRelationship(parentTable, relation) {
|
|
5427
|
+
const explicitFk = relation.explicitFk;
|
|
5428
|
+
const {
|
|
5429
|
+
tableName: targetTable
|
|
5430
|
+
} = parseTableIdentifier(explicitFk.targetTable);
|
|
5431
|
+
return {
|
|
5432
|
+
type: "many-to-one",
|
|
5433
|
+
fromTable: parentTable,
|
|
5434
|
+
toTable: targetTable,
|
|
5435
|
+
foreignKey: explicitFk.sourceField,
|
|
5436
|
+
referencedColumn: explicitFk.targetColumn ?? "id"
|
|
5437
|
+
};
|
|
5438
|
+
}
|
|
5439
|
+
};
|
|
5440
|
+
|
|
5097
5441
|
// src/adapters/supabase-adapter.ts
|
|
5098
5442
|
var SupabaseAdapter = class {
|
|
5099
5443
|
constructor(supabase, schema) {
|
|
@@ -5107,28 +5451,19 @@ var SupabaseAdapter = class {
|
|
|
5107
5451
|
supportsCache: false,
|
|
5108
5452
|
supportsSync: false
|
|
5109
5453
|
};
|
|
5110
|
-
// ===========================================================================
|
|
5111
|
-
// Private Helper - Table Name Parsing
|
|
5112
|
-
// ===========================================================================
|
|
5113
5454
|
/**
|
|
5114
|
-
*
|
|
5115
|
-
*
|
|
5116
|
-
*
|
|
5117
|
-
* @param table - The table name, optionally schema-qualified (e.g., "users" or "core.Profile")
|
|
5118
|
-
* @returns Object with schema (defaults to "public") and tableName
|
|
5455
|
+
* Query executor for handling explicit FK syntax.
|
|
5456
|
+
* Lazily initialized when needed.
|
|
5119
5457
|
*/
|
|
5120
|
-
|
|
5121
|
-
|
|
5122
|
-
|
|
5123
|
-
|
|
5124
|
-
|
|
5125
|
-
|
|
5126
|
-
|
|
5458
|
+
queryExecutor = null;
|
|
5459
|
+
/**
|
|
5460
|
+
* Get or create the SupabaseQueryExecutor for explicit FK queries.
|
|
5461
|
+
*/
|
|
5462
|
+
getQueryExecutor() {
|
|
5463
|
+
if (!this.queryExecutor) {
|
|
5464
|
+
this.queryExecutor = new SupabaseQueryExecutor(this.supabase, this.schema);
|
|
5127
5465
|
}
|
|
5128
|
-
return
|
|
5129
|
-
schema: "public",
|
|
5130
|
-
tableName: table
|
|
5131
|
-
};
|
|
5466
|
+
return this.queryExecutor;
|
|
5132
5467
|
}
|
|
5133
5468
|
// ===========================================================================
|
|
5134
5469
|
// Query Operations
|
|
@@ -5161,6 +5496,14 @@ var SupabaseAdapter = class {
|
|
|
5161
5496
|
limit,
|
|
5162
5497
|
offset
|
|
5163
5498
|
} = options;
|
|
5499
|
+
if (select && selectHasExplicitFkSyntax(select)) {
|
|
5500
|
+
const executor = this.getQueryExecutor();
|
|
5501
|
+
const result = await executor.execute(table, options);
|
|
5502
|
+
return {
|
|
5503
|
+
data: result.data,
|
|
5504
|
+
count: result.count
|
|
5505
|
+
};
|
|
5506
|
+
}
|
|
5164
5507
|
if (this.hasInvalidUuidFilter(where)) {
|
|
5165
5508
|
console.warn(`[SupabaseAdapter] Query on ${table} has invalid UUID filter (empty string), returning empty results`);
|
|
5166
5509
|
return {
|
|
@@ -5171,12 +5514,12 @@ var SupabaseAdapter = class {
|
|
|
5171
5514
|
const {
|
|
5172
5515
|
schema,
|
|
5173
5516
|
tableName
|
|
5174
|
-
} =
|
|
5517
|
+
} = parseTableIdentifier(table);
|
|
5175
5518
|
let query = this.supabase.schema(schema).from(tableName).select(select, {
|
|
5176
5519
|
count: "exact"
|
|
5177
5520
|
});
|
|
5178
5521
|
if (where) {
|
|
5179
|
-
query =
|
|
5522
|
+
query = applyWhereClause(query, where);
|
|
5180
5523
|
}
|
|
5181
5524
|
if (orderBy && orderBy.length > 0) {
|
|
5182
5525
|
for (const order of orderBy) {
|
|
@@ -5213,10 +5556,14 @@ var SupabaseAdapter = class {
|
|
|
5213
5556
|
*/
|
|
5214
5557
|
async queryById(table, id, options) {
|
|
5215
5558
|
const select = options?.select ?? "*";
|
|
5559
|
+
if (select && selectHasExplicitFkSyntax(select)) {
|
|
5560
|
+
const executor = this.getQueryExecutor();
|
|
5561
|
+
return executor.executeById(table, id, options);
|
|
5562
|
+
}
|
|
5216
5563
|
const {
|
|
5217
5564
|
schema,
|
|
5218
5565
|
tableName
|
|
5219
|
-
} =
|
|
5566
|
+
} = parseTableIdentifier(table);
|
|
5220
5567
|
const {
|
|
5221
5568
|
data,
|
|
5222
5569
|
error
|
|
@@ -5243,7 +5590,7 @@ var SupabaseAdapter = class {
|
|
|
5243
5590
|
const {
|
|
5244
5591
|
schema,
|
|
5245
5592
|
tableName
|
|
5246
|
-
} =
|
|
5593
|
+
} = parseTableIdentifier(table);
|
|
5247
5594
|
const {
|
|
5248
5595
|
data: insertedData,
|
|
5249
5596
|
error
|
|
@@ -5265,7 +5612,7 @@ var SupabaseAdapter = class {
|
|
|
5265
5612
|
const {
|
|
5266
5613
|
schema,
|
|
5267
5614
|
tableName
|
|
5268
|
-
} =
|
|
5615
|
+
} = parseTableIdentifier(table);
|
|
5269
5616
|
const {
|
|
5270
5617
|
data: updatedData,
|
|
5271
5618
|
error
|
|
@@ -5290,7 +5637,7 @@ var SupabaseAdapter = class {
|
|
|
5290
5637
|
const {
|
|
5291
5638
|
schema,
|
|
5292
5639
|
tableName
|
|
5293
|
-
} =
|
|
5640
|
+
} = parseTableIdentifier(table);
|
|
5294
5641
|
const hasId = "id" in data && data.id != null;
|
|
5295
5642
|
if (hasId) {
|
|
5296
5643
|
const id = data.id;
|
|
@@ -5325,7 +5672,7 @@ var SupabaseAdapter = class {
|
|
|
5325
5672
|
const {
|
|
5326
5673
|
schema,
|
|
5327
5674
|
tableName
|
|
5328
|
-
} =
|
|
5675
|
+
} = parseTableIdentifier(table);
|
|
5329
5676
|
const {
|
|
5330
5677
|
error
|
|
5331
5678
|
} = await this.supabase.schema(schema).from(tableName).delete().eq("id", id);
|
|
@@ -5348,7 +5695,7 @@ var SupabaseAdapter = class {
|
|
|
5348
5695
|
const {
|
|
5349
5696
|
schema,
|
|
5350
5697
|
tableName
|
|
5351
|
-
} =
|
|
5698
|
+
} = parseTableIdentifier(table);
|
|
5352
5699
|
const channelName = `v3:${table}:${Date.now()}`;
|
|
5353
5700
|
const channel = this.supabase.channel(channelName).on("postgres_changes", {
|
|
5354
5701
|
event: "*",
|
|
@@ -5368,71 +5715,6 @@ var SupabaseAdapter = class {
|
|
|
5368
5715
|
this.supabase.removeChannel(channel);
|
|
5369
5716
|
};
|
|
5370
5717
|
}
|
|
5371
|
-
// ===========================================================================
|
|
5372
|
-
// Private Helper Methods
|
|
5373
|
-
// ===========================================================================
|
|
5374
|
-
/**
|
|
5375
|
-
* Apply where clause filters to a Supabase query
|
|
5376
|
-
*
|
|
5377
|
-
* Converts WhereClause to Supabase filter methods:
|
|
5378
|
-
* - Direct value: .eq(field, value)
|
|
5379
|
-
* - { in: [...] }: .in(field, values)
|
|
5380
|
-
* - { gt: n }: .gt(field, n)
|
|
5381
|
-
* - { gte: n }: .gte(field, n)
|
|
5382
|
-
* - { lt: n }: .lt(field, n)
|
|
5383
|
-
* - { lte: n }: .lte(field, n)
|
|
5384
|
-
* - { like: s }: .ilike(field, s)
|
|
5385
|
-
* - { is: null }: .is(field, null)
|
|
5386
|
-
* - { neq: v }: .neq(field, v) or .not(field, "is", null)
|
|
5387
|
-
* - { notIn: [...] }: .not().in(field, values)
|
|
5388
|
-
*
|
|
5389
|
-
* @param query - The Supabase query builder
|
|
5390
|
-
* @param where - The where clause to apply
|
|
5391
|
-
* @returns The query with filters applied
|
|
5392
|
-
*/
|
|
5393
|
-
applyWhereClause(query, where) {
|
|
5394
|
-
for (const [field, condition] of Object.entries(where)) {
|
|
5395
|
-
if (condition === null) {
|
|
5396
|
-
query = query.is(field, null);
|
|
5397
|
-
} else if (typeof condition === "string" || typeof condition === "number" || typeof condition === "boolean") {
|
|
5398
|
-
query = query.eq(field, condition);
|
|
5399
|
-
} else if (typeof condition === "object") {
|
|
5400
|
-
const operators = condition;
|
|
5401
|
-
if (operators.in !== void 0) {
|
|
5402
|
-
query = query.in(field, operators.in);
|
|
5403
|
-
}
|
|
5404
|
-
if (operators.gt !== void 0) {
|
|
5405
|
-
query = query.gt(field, operators.gt);
|
|
5406
|
-
}
|
|
5407
|
-
if (operators.gte !== void 0) {
|
|
5408
|
-
query = query.gte(field, operators.gte);
|
|
5409
|
-
}
|
|
5410
|
-
if (operators.lt !== void 0) {
|
|
5411
|
-
query = query.lt(field, operators.lt);
|
|
5412
|
-
}
|
|
5413
|
-
if (operators.lte !== void 0) {
|
|
5414
|
-
query = query.lte(field, operators.lte);
|
|
5415
|
-
}
|
|
5416
|
-
if (operators.like !== void 0) {
|
|
5417
|
-
query = query.ilike(field, operators.like);
|
|
5418
|
-
}
|
|
5419
|
-
if (operators.is !== void 0) {
|
|
5420
|
-
query = query.is(field, null);
|
|
5421
|
-
}
|
|
5422
|
-
if (operators.neq !== void 0) {
|
|
5423
|
-
if (operators.neq === null) {
|
|
5424
|
-
query = query.not(field, "is", null);
|
|
5425
|
-
} else {
|
|
5426
|
-
query = query.neq(field, operators.neq);
|
|
5427
|
-
}
|
|
5428
|
-
}
|
|
5429
|
-
if (operators.notIn !== void 0) {
|
|
5430
|
-
query = query.not(field, "in", `(${operators.notIn.join(",")})`);
|
|
5431
|
-
}
|
|
5432
|
-
}
|
|
5433
|
-
}
|
|
5434
|
-
return query;
|
|
5435
|
-
}
|
|
5436
5718
|
};
|
|
5437
5719
|
function createSupabaseAdapter(supabase, schema) {
|
|
5438
5720
|
return new SupabaseAdapter(supabase, schema);
|
|
@@ -5652,6 +5934,7 @@ function useLiveChangeTracking(tableName, item, action) {
|
|
|
5652
5934
|
let t0;
|
|
5653
5935
|
if ($[0] !== item || $[1] !== oldItem || $[2] !== supabase || $[3] !== tableName) {
|
|
5654
5936
|
t0 = () => {
|
|
5937
|
+
let isMounted = true;
|
|
5655
5938
|
setChangeLog(null);
|
|
5656
5939
|
if (isUsable(item) === false) {
|
|
5657
5940
|
return;
|
|
@@ -5671,6 +5954,9 @@ function useLiveChangeTracking(tableName, item, action) {
|
|
|
5671
5954
|
supabase.schema("core").from("OperationLog").select().filter("tableName", "eq", tableName).filter("recordId", "eq", itemId).order("changeAt", {
|
|
5672
5955
|
ascending: false
|
|
5673
5956
|
}).limit(1).single().then((x) => {
|
|
5957
|
+
if (!isMounted) {
|
|
5958
|
+
return;
|
|
5959
|
+
}
|
|
5674
5960
|
if (isUsable(x.data) === false) {
|
|
5675
5961
|
return;
|
|
5676
5962
|
}
|
|
@@ -5686,6 +5972,9 @@ function useLiveChangeTracking(tableName, item, action) {
|
|
|
5686
5972
|
setChangeLog(changeLog_0);
|
|
5687
5973
|
});
|
|
5688
5974
|
setOldItem(item);
|
|
5975
|
+
return () => {
|
|
5976
|
+
isMounted = false;
|
|
5977
|
+
};
|
|
5689
5978
|
};
|
|
5690
5979
|
$[0] = item;
|
|
5691
5980
|
$[1] = oldItem;
|
|
@@ -6931,14 +7220,6 @@ function useDbRealtime(key, query, table, primaryKeys, options) {
|
|
|
6931
7220
|
if (onChange) {
|
|
6932
7221
|
onChange(payload);
|
|
6933
7222
|
}
|
|
6934
|
-
}).on("postgres_changes", {
|
|
6935
|
-
event: "DELETE",
|
|
6936
|
-
schema: schemaValue,
|
|
6937
|
-
table: tableNameValue
|
|
6938
|
-
}, async (payload_0) => {
|
|
6939
|
-
if (payload_0.eventType === REALTIME_POSTGRES_CHANGES_LISTEN_EVENT.DELETE) {
|
|
6940
|
-
await deleteItem(payload_0.old);
|
|
6941
|
-
}
|
|
6942
7223
|
}).subscribe((status) => {
|
|
6943
7224
|
setRealtimeState(status);
|
|
6944
7225
|
if (status === "SUBSCRIBED") {
|
|
@@ -7984,4 +8265,4 @@ moment/moment.js:
|
|
|
7984
8265
|
(*! license : MIT *)
|
|
7985
8266
|
(*! momentjs.com *)
|
|
7986
8267
|
*/
|
|
7987
|
-
//# sourceMappingURL=chunk-
|
|
8268
|
+
//# sourceMappingURL=chunk-DDL63KLQ.js.map
|