@typicalday/firegraph 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -3
- package/dist/{backend-DuvHGgK1.d.cts → backend-BpYLdwCW.d.cts} +1 -1
- package/dist/{backend-DuvHGgK1.d.ts → backend-BpYLdwCW.d.ts} +1 -1
- package/dist/backend-CvImIwTY.d.cts +137 -0
- package/dist/backend-YH5HtawN.d.ts +137 -0
- package/dist/backend.cjs +2 -3
- package/dist/backend.cjs.map +1 -1
- package/dist/backend.d.cts +2 -2
- package/dist/backend.d.ts +2 -2
- package/dist/backend.js +1 -1
- package/dist/{chunk-WRTFC5NG.js → chunk-5HIRYV2S.js} +13 -36
- package/dist/chunk-5HIRYV2S.js.map +1 -0
- package/dist/{chunk-PAD7WFFU.js → chunk-7IEZ6IYY.js} +36 -10
- package/dist/chunk-7IEZ6IYY.js.map +1 -0
- package/dist/chunk-FODIMIWY.js +721 -0
- package/dist/chunk-FODIMIWY.js.map +1 -0
- package/dist/chunk-NGAJCALM.js +34 -0
- package/dist/chunk-NGAJCALM.js.map +1 -0
- package/dist/{chunk-TK64DNVK.js → chunk-SIHE4UY4.js} +3 -4
- package/dist/chunk-SIHE4UY4.js.map +1 -0
- package/dist/chunk-ULRDQ6HZ.js +862 -0
- package/dist/chunk-ULRDQ6HZ.js.map +1 -0
- package/dist/{client-BKi3vk0Q.d.ts → client-B5o39X79.d.ts} +1 -1
- package/dist/{client-BrsaXtDV.d.cts → client-BGHwxwPg.d.cts} +1 -1
- package/dist/{client-Bk2Cm6xv.d.cts → client-DoyEdJ5w.d.cts} +1 -1
- package/dist/{client-Bk2Cm6xv.d.ts → client-DoyEdJ5w.d.ts} +1 -1
- package/dist/cloudflare/index.cjs +155 -165
- package/dist/cloudflare/index.cjs.map +1 -1
- package/dist/cloudflare/index.d.cts +73 -70
- package/dist/cloudflare/index.d.ts +73 -70
- package/dist/cloudflare/index.js +54 -589
- package/dist/cloudflare/index.js.map +1 -1
- package/dist/codegen/index.d.cts +1 -1
- package/dist/codegen/index.d.ts +1 -1
- package/dist/firestore-enterprise/index.cjs +42 -40
- package/dist/firestore-enterprise/index.cjs.map +1 -1
- package/dist/firestore-enterprise/index.d.cts +3 -3
- package/dist/firestore-enterprise/index.d.ts +3 -3
- package/dist/firestore-enterprise/index.js +19 -35
- package/dist/firestore-enterprise/index.js.map +1 -1
- package/dist/firestore-standard/index.cjs +34 -37
- package/dist/firestore-standard/index.cjs.map +1 -1
- package/dist/firestore-standard/index.d.cts +3 -3
- package/dist/firestore-standard/index.d.ts +3 -3
- package/dist/firestore-standard/index.js +10 -34
- package/dist/firestore-standard/index.js.map +1 -1
- package/dist/index.cjs +2 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +7 -5
- package/dist/index.js.map +1 -1
- package/dist/query-client/index.d.cts +2 -2
- package/dist/query-client/index.d.ts +2 -2
- package/dist/{registry-Bc7h6WTM.d.cts → registry-BGh7Jqpb.d.cts} +2 -2
- package/dist/{registry-C2KUPVZj.d.ts → registry-tKTb5Kx1.d.ts} +2 -2
- package/dist/sqlite/index.cjs +585 -378
- package/dist/sqlite/index.cjs.map +1 -1
- package/dist/sqlite/index.d.cts +4 -110
- package/dist/sqlite/index.d.ts +4 -110
- package/dist/sqlite/index.js +7 -1144
- package/dist/sqlite/index.js.map +1 -1
- package/dist/sqlite/local.cjs +1835 -0
- package/dist/sqlite/local.cjs.map +1 -0
- package/dist/sqlite/local.d.cts +83 -0
- package/dist/sqlite/local.d.ts +83 -0
- package/dist/sqlite/local.js +121 -0
- package/dist/sqlite/local.js.map +1 -0
- package/package.json +15 -1
- package/dist/chunk-4MMQ5W74.js +0 -288
- package/dist/chunk-4MMQ5W74.js.map +0 -1
- package/dist/chunk-PAD7WFFU.js.map +0 -1
- package/dist/chunk-TK64DNVK.js.map +0 -1
- package/dist/chunk-WRTFC5NG.js.map +0 -1
package/dist/cloudflare/index.js
CHANGED
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
import {
|
|
2
2
|
GraphTimestampImpl,
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
3
|
+
buildSchemaStatements,
|
|
4
|
+
compileAggregate,
|
|
5
|
+
compileBulkDelete,
|
|
6
|
+
compileBulkUpdate,
|
|
7
|
+
compileDelete,
|
|
8
|
+
compileDeleteAll,
|
|
9
|
+
compileExpand,
|
|
10
|
+
compileExpandHydrate,
|
|
11
|
+
compileFindEdgesProjected,
|
|
12
|
+
compileSelect,
|
|
13
|
+
compileSelectByDocId,
|
|
14
|
+
compileSet,
|
|
15
|
+
compileUpdate,
|
|
16
|
+
decodeProjectedRow,
|
|
17
|
+
rowTimestampToMillis,
|
|
18
|
+
validateTableName
|
|
19
|
+
} from "../chunk-ULRDQ6HZ.js";
|
|
20
|
+
import "../chunk-2DHMNTV6.js";
|
|
13
21
|
import {
|
|
14
22
|
createCapabilities,
|
|
15
23
|
intersectCapabilities
|
|
@@ -17,561 +25,30 @@ import {
|
|
|
17
25
|
import {
|
|
18
26
|
META_EDGE_TYPE,
|
|
19
27
|
META_NODE_TYPE,
|
|
20
|
-
NODE_RELATION,
|
|
21
28
|
buildEdgeQueryPlan,
|
|
22
|
-
computeEdgeDocId,
|
|
23
|
-
computeNodeDocId,
|
|
24
29
|
createGraphClientFromBackend,
|
|
25
30
|
createMergedRegistry,
|
|
26
31
|
createRegistry,
|
|
27
32
|
generateId
|
|
28
|
-
} from "../chunk-
|
|
33
|
+
} from "../chunk-5HIRYV2S.js";
|
|
34
|
+
import {
|
|
35
|
+
NODE_RELATION,
|
|
36
|
+
computeEdgeDocId,
|
|
37
|
+
computeNodeDocId
|
|
38
|
+
} from "../chunk-NGAJCALM.js";
|
|
29
39
|
import {
|
|
30
40
|
CapabilityNotSupportedError,
|
|
31
41
|
FiregraphError,
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
flattenPatch
|
|
35
|
-
} from "../chunk-TK64DNVK.js";
|
|
42
|
+
deleteField
|
|
43
|
+
} from "../chunk-SIHE4UY4.js";
|
|
36
44
|
import "../chunk-EQJUUVFG.js";
|
|
37
45
|
|
|
38
|
-
// src/cloudflare/schema.ts
|
|
39
|
-
var DO_FIELD_TO_COLUMN = {
|
|
40
|
-
aType: "a_type",
|
|
41
|
-
aUid: "a_uid",
|
|
42
|
-
axbType: "axb_type",
|
|
43
|
-
bType: "b_type",
|
|
44
|
-
bUid: "b_uid",
|
|
45
|
-
v: "v",
|
|
46
|
-
createdAt: "created_at",
|
|
47
|
-
updatedAt: "updated_at"
|
|
48
|
-
};
|
|
49
|
-
var IDENT_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
50
|
-
function validateDOTableName(name) {
|
|
51
|
-
if (!IDENT_RE.test(name)) {
|
|
52
|
-
throw new Error(`Invalid SQL identifier: ${name}. Must match /^[A-Za-z_][A-Za-z0-9_]*$/.`);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
function quoteDOIdent(name) {
|
|
56
|
-
validateDOTableName(name);
|
|
57
|
-
return `"${name}"`;
|
|
58
|
-
}
|
|
59
|
-
function quoteDOColumnAlias(label) {
|
|
60
|
-
return `"${label.replace(/"/g, '""')}"`;
|
|
61
|
-
}
|
|
62
|
-
function buildDOSchemaStatements(table, options = {}) {
|
|
63
|
-
const t = quoteDOIdent(table);
|
|
64
|
-
const statements = [
|
|
65
|
-
`CREATE TABLE IF NOT EXISTS ${t} (
|
|
66
|
-
doc_id TEXT NOT NULL PRIMARY KEY,
|
|
67
|
-
a_type TEXT NOT NULL,
|
|
68
|
-
a_uid TEXT NOT NULL,
|
|
69
|
-
axb_type TEXT NOT NULL,
|
|
70
|
-
b_type TEXT NOT NULL,
|
|
71
|
-
b_uid TEXT NOT NULL,
|
|
72
|
-
data TEXT NOT NULL,
|
|
73
|
-
v INTEGER,
|
|
74
|
-
created_at INTEGER NOT NULL,
|
|
75
|
-
updated_at INTEGER NOT NULL
|
|
76
|
-
)`
|
|
77
|
-
];
|
|
78
|
-
const core = options.coreIndexes ?? [...DEFAULT_CORE_INDEXES];
|
|
79
|
-
const fromRegistry = options.registry?.entries().flatMap((e) => e.indexes ?? []) ?? [];
|
|
80
|
-
const deduped = dedupeIndexSpecs([...core, ...fromRegistry]);
|
|
81
|
-
for (const spec of deduped) {
|
|
82
|
-
statements.push(buildIndexDDL(spec, { table, fieldToColumn: DO_FIELD_TO_COLUMN }));
|
|
83
|
-
}
|
|
84
|
-
return statements;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
46
|
// src/cloudflare/sql.ts
|
|
88
|
-
var DO_BACKEND_LABEL = "DO SQLite";
|
|
89
|
-
var DO_BACKEND_ERR_LABEL = "DO SQLite backend";
|
|
90
|
-
function compileFieldRef(field) {
|
|
91
|
-
const column = DO_FIELD_TO_COLUMN[field];
|
|
92
|
-
if (column) {
|
|
93
|
-
return { expr: quoteDOIdent(column) };
|
|
94
|
-
}
|
|
95
|
-
if (field.startsWith("data.")) {
|
|
96
|
-
const suffix = field.slice(5);
|
|
97
|
-
for (const part of suffix.split(".")) {
|
|
98
|
-
validateJsonPathKey(part, DO_BACKEND_ERR_LABEL);
|
|
99
|
-
}
|
|
100
|
-
return { expr: `json_extract("data", '$.${suffix}')` };
|
|
101
|
-
}
|
|
102
|
-
if (field === "data") {
|
|
103
|
-
return { expr: `json_extract("data", '$')` };
|
|
104
|
-
}
|
|
105
|
-
throw new FiregraphError(
|
|
106
|
-
`DO SQLite backend cannot resolve filter field: ${field}`,
|
|
107
|
-
"INVALID_QUERY"
|
|
108
|
-
);
|
|
109
|
-
}
|
|
110
|
-
function bindValue(value) {
|
|
111
|
-
if (value === null || value === void 0) return null;
|
|
112
|
-
if (typeof value === "string" || typeof value === "number" || typeof value === "bigint" || typeof value === "boolean") {
|
|
113
|
-
return value;
|
|
114
|
-
}
|
|
115
|
-
if (value instanceof Date) return value.getTime();
|
|
116
|
-
if (typeof value === "object") {
|
|
117
|
-
const firestoreType = isFirestoreSpecialType(value);
|
|
118
|
-
if (firestoreType) {
|
|
119
|
-
throw new FiregraphError(
|
|
120
|
-
`DO SQLite backend cannot bind a Firestore ${firestoreType} value \u2014 JSON serialization would silently drop fields and the resulting bind would never match a stored row. Convert to a primitive (e.g. \`ts.toMillis()\` for Timestamp) before filtering or updating.`,
|
|
121
|
-
"INVALID_QUERY"
|
|
122
|
-
);
|
|
123
|
-
}
|
|
124
|
-
return JSON.stringify(value);
|
|
125
|
-
}
|
|
126
|
-
return String(value);
|
|
127
|
-
}
|
|
128
|
-
function compileFilter(filter, params) {
|
|
129
|
-
const { expr } = compileFieldRef(filter.field);
|
|
130
|
-
switch (filter.op) {
|
|
131
|
-
case "==":
|
|
132
|
-
params.push(bindValue(filter.value));
|
|
133
|
-
return `${expr} = ?`;
|
|
134
|
-
case "!=":
|
|
135
|
-
params.push(bindValue(filter.value));
|
|
136
|
-
return `${expr} != ?`;
|
|
137
|
-
case "<":
|
|
138
|
-
params.push(bindValue(filter.value));
|
|
139
|
-
return `${expr} < ?`;
|
|
140
|
-
case "<=":
|
|
141
|
-
params.push(bindValue(filter.value));
|
|
142
|
-
return `${expr} <= ?`;
|
|
143
|
-
case ">":
|
|
144
|
-
params.push(bindValue(filter.value));
|
|
145
|
-
return `${expr} > ?`;
|
|
146
|
-
case ">=":
|
|
147
|
-
params.push(bindValue(filter.value));
|
|
148
|
-
return `${expr} >= ?`;
|
|
149
|
-
case "in": {
|
|
150
|
-
const values = asArray(filter.value, "in");
|
|
151
|
-
const placeholders = values.map(() => "?").join(", ");
|
|
152
|
-
for (const v of values) params.push(bindValue(v));
|
|
153
|
-
return `${expr} IN (${placeholders})`;
|
|
154
|
-
}
|
|
155
|
-
case "not-in": {
|
|
156
|
-
const values = asArray(filter.value, "not-in");
|
|
157
|
-
const placeholders = values.map(() => "?").join(", ");
|
|
158
|
-
for (const v of values) params.push(bindValue(v));
|
|
159
|
-
return `${expr} NOT IN (${placeholders})`;
|
|
160
|
-
}
|
|
161
|
-
case "array-contains": {
|
|
162
|
-
params.push(bindValue(filter.value));
|
|
163
|
-
return `EXISTS (SELECT 1 FROM json_each(${expr}) WHERE value = ?)`;
|
|
164
|
-
}
|
|
165
|
-
case "array-contains-any": {
|
|
166
|
-
const values = asArray(filter.value, "array-contains-any");
|
|
167
|
-
const placeholders = values.map(() => "?").join(", ");
|
|
168
|
-
for (const v of values) params.push(bindValue(v));
|
|
169
|
-
return `EXISTS (SELECT 1 FROM json_each(${expr}) WHERE value IN (${placeholders}))`;
|
|
170
|
-
}
|
|
171
|
-
default:
|
|
172
|
-
throw new FiregraphError(
|
|
173
|
-
`DO SQLite backend does not support filter operator: ${String(filter.op)}`,
|
|
174
|
-
"INVALID_QUERY"
|
|
175
|
-
);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
function asArray(value, op) {
|
|
179
|
-
if (!Array.isArray(value) || value.length === 0) {
|
|
180
|
-
throw new FiregraphError(`Operator "${op}" requires a non-empty array value`, "INVALID_QUERY");
|
|
181
|
-
}
|
|
182
|
-
return value;
|
|
183
|
-
}
|
|
184
|
-
function compileOrderBy(options, _params) {
|
|
185
|
-
if (!options?.orderBy) return "";
|
|
186
|
-
const { field, direction } = options.orderBy;
|
|
187
|
-
const { expr } = compileFieldRef(field);
|
|
188
|
-
const dir = direction === "desc" ? "DESC" : "ASC";
|
|
189
|
-
return ` ORDER BY ${expr} ${dir}`;
|
|
190
|
-
}
|
|
191
|
-
function compileLimit(options, params) {
|
|
192
|
-
if (options?.limit === void 0) return "";
|
|
193
|
-
params.push(options.limit);
|
|
194
|
-
return ` LIMIT ?`;
|
|
195
|
-
}
|
|
196
|
-
function compileDOSelect(table, filters, options) {
|
|
197
|
-
const params = [];
|
|
198
|
-
const conditions = [];
|
|
199
|
-
for (const f of filters) {
|
|
200
|
-
conditions.push(compileFilter(f, params));
|
|
201
|
-
}
|
|
202
|
-
const where = conditions.length > 0 ? ` WHERE ${conditions.join(" AND ")}` : "";
|
|
203
|
-
let sql = `SELECT * FROM ${quoteDOIdent(table)}${where}`;
|
|
204
|
-
sql += compileOrderBy(options, params);
|
|
205
|
-
sql += compileLimit(options, params);
|
|
206
|
-
return { sql, params };
|
|
207
|
-
}
|
|
208
|
-
function compileDOExpand(table, params) {
|
|
209
|
-
if (params.sources.length === 0) {
|
|
210
|
-
throw new FiregraphError(
|
|
211
|
-
"compileDOExpand requires a non-empty sources list \u2014 empty IN () is invalid SQL.",
|
|
212
|
-
"INVALID_QUERY"
|
|
213
|
-
);
|
|
214
|
-
}
|
|
215
|
-
const direction = params.direction ?? "forward";
|
|
216
|
-
const aUidCol = compileFieldRef("aUid").expr;
|
|
217
|
-
const bUidCol = compileFieldRef("bUid").expr;
|
|
218
|
-
const aTypeCol = compileFieldRef("aType").expr;
|
|
219
|
-
const bTypeCol = compileFieldRef("bType").expr;
|
|
220
|
-
const axbTypeCol = compileFieldRef("axbType").expr;
|
|
221
|
-
const sourceColumn = direction === "forward" ? aUidCol : bUidCol;
|
|
222
|
-
const sqlParams = [params.axbType];
|
|
223
|
-
const conditions = [`${axbTypeCol} = ?`];
|
|
224
|
-
const placeholders = params.sources.map(() => "?").join(", ");
|
|
225
|
-
conditions.push(`${sourceColumn} IN (${placeholders})`);
|
|
226
|
-
for (const uid of params.sources) sqlParams.push(uid);
|
|
227
|
-
if (params.aType !== void 0) {
|
|
228
|
-
conditions.push(`${aTypeCol} = ?`);
|
|
229
|
-
sqlParams.push(params.aType);
|
|
230
|
-
}
|
|
231
|
-
if (params.bType !== void 0) {
|
|
232
|
-
conditions.push(`${bTypeCol} = ?`);
|
|
233
|
-
sqlParams.push(params.bType);
|
|
234
|
-
}
|
|
235
|
-
if (params.axbType === NODE_RELATION) {
|
|
236
|
-
conditions.push(`${aUidCol} != ${bUidCol}`);
|
|
237
|
-
}
|
|
238
|
-
let sql = `SELECT * FROM ${quoteDOIdent(table)} WHERE ${conditions.join(" AND ")}`;
|
|
239
|
-
if (params.orderBy) {
|
|
240
|
-
sql += compileOrderBy({ orderBy: params.orderBy }, sqlParams);
|
|
241
|
-
}
|
|
242
|
-
if (params.limitPerSource !== void 0) {
|
|
243
|
-
const totalLimit = params.sources.length * params.limitPerSource;
|
|
244
|
-
sql += ` LIMIT ?`;
|
|
245
|
-
sqlParams.push(totalLimit);
|
|
246
|
-
}
|
|
247
|
-
return { sql, params: sqlParams };
|
|
248
|
-
}
|
|
249
|
-
function compileDOExpandHydrate(table, targetUids) {
|
|
250
|
-
if (targetUids.length === 0) {
|
|
251
|
-
throw new FiregraphError(
|
|
252
|
-
"compileDOExpandHydrate requires a non-empty target list \u2014 empty IN () is invalid SQL.",
|
|
253
|
-
"INVALID_QUERY"
|
|
254
|
-
);
|
|
255
|
-
}
|
|
256
|
-
const placeholders = targetUids.map(() => "?").join(", ");
|
|
257
|
-
const sqlParams = [NODE_RELATION];
|
|
258
|
-
for (const uid of targetUids) sqlParams.push(uid);
|
|
259
|
-
const aUidCol = compileFieldRef("aUid").expr;
|
|
260
|
-
const bUidCol = compileFieldRef("bUid").expr;
|
|
261
|
-
const axbTypeCol = compileFieldRef("axbType").expr;
|
|
262
|
-
return {
|
|
263
|
-
sql: `SELECT * FROM ${quoteDOIdent(table)} WHERE ${axbTypeCol} = ? AND ${aUidCol} = ${bUidCol} AND ${bUidCol} IN (${placeholders})`,
|
|
264
|
-
params: sqlParams
|
|
265
|
-
};
|
|
266
|
-
}
|
|
267
|
-
function compileDOSelectByDocId(table, docId) {
|
|
268
|
-
return {
|
|
269
|
-
sql: `SELECT * FROM ${quoteDOIdent(table)} WHERE "doc_id" = ? LIMIT 1`,
|
|
270
|
-
params: [docId]
|
|
271
|
-
};
|
|
272
|
-
}
|
|
273
|
-
function normalizeDOProjectionField(field) {
|
|
274
|
-
if (field in DO_FIELD_TO_COLUMN) return field;
|
|
275
|
-
if (field === "data" || field.startsWith("data.")) return field;
|
|
276
|
-
return `data.${field}`;
|
|
277
|
-
}
|
|
278
|
-
function compileDOFindEdgesProjected(table, select, filters, options) {
|
|
279
|
-
if (select.length === 0) {
|
|
280
|
-
throw new FiregraphError(
|
|
281
|
-
"compileDOFindEdgesProjected requires a non-empty select list \u2014 an empty projection has no SQL representation distinct from `findEdges`.",
|
|
282
|
-
"INVALID_QUERY"
|
|
283
|
-
);
|
|
284
|
-
}
|
|
285
|
-
const seen = /* @__PURE__ */ new Set();
|
|
286
|
-
const uniqueFields = [];
|
|
287
|
-
for (const f of select) {
|
|
288
|
-
if (!seen.has(f)) {
|
|
289
|
-
seen.add(f);
|
|
290
|
-
uniqueFields.push(f);
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
const projections = [];
|
|
294
|
-
const columns = [];
|
|
295
|
-
for (let idx = 0; idx < uniqueFields.length; idx++) {
|
|
296
|
-
const field = uniqueFields[idx];
|
|
297
|
-
const canonical = normalizeDOProjectionField(field);
|
|
298
|
-
const { expr } = compileFieldRef(canonical);
|
|
299
|
-
const alias = quoteDOColumnAlias(field);
|
|
300
|
-
projections.push(`${expr} AS ${alias}`);
|
|
301
|
-
let kind;
|
|
302
|
-
let typeAliasName;
|
|
303
|
-
if (canonical === "data") {
|
|
304
|
-
kind = "data";
|
|
305
|
-
} else if (canonical.startsWith("data.")) {
|
|
306
|
-
kind = "json";
|
|
307
|
-
typeAliasName = `__fg_t_${idx}`;
|
|
308
|
-
const typeAlias = quoteDOColumnAlias(typeAliasName);
|
|
309
|
-
projections.push(`json_type("data", '$.${canonical.slice(5)}') AS ${typeAlias}`);
|
|
310
|
-
} else {
|
|
311
|
-
if (canonical === "v") kind = "builtin-int";
|
|
312
|
-
else if (canonical === "createdAt" || canonical === "updatedAt") kind = "builtin-timestamp";
|
|
313
|
-
else kind = "builtin-text";
|
|
314
|
-
}
|
|
315
|
-
columns.push({ field, kind, typeAlias: typeAliasName });
|
|
316
|
-
}
|
|
317
|
-
const params = [];
|
|
318
|
-
const conditions = [];
|
|
319
|
-
for (const f of filters) {
|
|
320
|
-
conditions.push(compileFilter(f, params));
|
|
321
|
-
}
|
|
322
|
-
const where = conditions.length > 0 ? ` WHERE ${conditions.join(" AND ")}` : "";
|
|
323
|
-
let sql = `SELECT ${projections.join(", ")} FROM ${quoteDOIdent(table)}${where}`;
|
|
324
|
-
sql += compileOrderBy(options, params);
|
|
325
|
-
sql += compileLimit(options, params);
|
|
326
|
-
return { stmt: { sql, params }, columns };
|
|
327
|
-
}
|
|
328
|
-
function decodeDOProjectedRow(row, columns) {
|
|
329
|
-
const out = {};
|
|
330
|
-
for (const c of columns) {
|
|
331
|
-
const raw = row[c.field];
|
|
332
|
-
switch (c.kind) {
|
|
333
|
-
case "builtin-text":
|
|
334
|
-
out[c.field] = raw === null || raw === void 0 ? null : String(raw);
|
|
335
|
-
break;
|
|
336
|
-
case "builtin-int":
|
|
337
|
-
if (raw === null || raw === void 0) {
|
|
338
|
-
out[c.field] = null;
|
|
339
|
-
} else if (typeof raw === "bigint") {
|
|
340
|
-
out[c.field] = Number(raw);
|
|
341
|
-
} else if (typeof raw === "number") {
|
|
342
|
-
out[c.field] = raw;
|
|
343
|
-
} else {
|
|
344
|
-
out[c.field] = Number(raw);
|
|
345
|
-
}
|
|
346
|
-
break;
|
|
347
|
-
case "builtin-timestamp": {
|
|
348
|
-
const ms = toMillis(raw);
|
|
349
|
-
out[c.field] = GraphTimestampImpl.fromMillis(ms);
|
|
350
|
-
break;
|
|
351
|
-
}
|
|
352
|
-
case "data":
|
|
353
|
-
if (raw === null || raw === void 0 || raw === "") {
|
|
354
|
-
out[c.field] = {};
|
|
355
|
-
} else {
|
|
356
|
-
out[c.field] = JSON.parse(raw);
|
|
357
|
-
}
|
|
358
|
-
break;
|
|
359
|
-
case "json": {
|
|
360
|
-
const t = row[c.typeAlias];
|
|
361
|
-
if (raw === null || raw === void 0) {
|
|
362
|
-
out[c.field] = null;
|
|
363
|
-
} else if (t === "object" || t === "array") {
|
|
364
|
-
out[c.field] = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
365
|
-
} else if (t === "integer" && typeof raw === "bigint") {
|
|
366
|
-
out[c.field] = Number(raw);
|
|
367
|
-
} else {
|
|
368
|
-
out[c.field] = raw;
|
|
369
|
-
}
|
|
370
|
-
break;
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
return out;
|
|
375
|
-
}
|
|
376
|
-
function compileDOAggregate(table, spec, filters) {
|
|
377
|
-
const aliases = Object.keys(spec);
|
|
378
|
-
if (aliases.length === 0) {
|
|
379
|
-
throw new FiregraphError(
|
|
380
|
-
"aggregate() requires at least one aggregation in the `aggregates` map.",
|
|
381
|
-
"INVALID_QUERY"
|
|
382
|
-
);
|
|
383
|
-
}
|
|
384
|
-
const projections = [];
|
|
385
|
-
for (const alias of aliases) {
|
|
386
|
-
const { op, field } = spec[alias];
|
|
387
|
-
validateJsonPathKey(alias, DO_BACKEND_ERR_LABEL);
|
|
388
|
-
if (op === "count") {
|
|
389
|
-
if (field !== void 0) {
|
|
390
|
-
throw new FiregraphError(
|
|
391
|
-
`Aggregate '${alias}' op 'count' must not specify a field \u2014 count operates on rows, not a column expression.`,
|
|
392
|
-
"INVALID_QUERY"
|
|
393
|
-
);
|
|
394
|
-
}
|
|
395
|
-
projections.push(`COUNT(*) AS ${quoteDOIdent(alias)}`);
|
|
396
|
-
continue;
|
|
397
|
-
}
|
|
398
|
-
if (!field) {
|
|
399
|
-
throw new FiregraphError(
|
|
400
|
-
`Aggregate '${alias}' op '${op}' requires a field.`,
|
|
401
|
-
"INVALID_QUERY"
|
|
402
|
-
);
|
|
403
|
-
}
|
|
404
|
-
const { expr } = compileFieldRef(field);
|
|
405
|
-
const numeric = `CAST(${expr} AS REAL)`;
|
|
406
|
-
if (op === "sum") projections.push(`SUM(${numeric}) AS ${quoteDOIdent(alias)}`);
|
|
407
|
-
else if (op === "avg") projections.push(`AVG(${numeric}) AS ${quoteDOIdent(alias)}`);
|
|
408
|
-
else if (op === "min") projections.push(`MIN(${numeric}) AS ${quoteDOIdent(alias)}`);
|
|
409
|
-
else if (op === "max") projections.push(`MAX(${numeric}) AS ${quoteDOIdent(alias)}`);
|
|
410
|
-
else
|
|
411
|
-
throw new FiregraphError(
|
|
412
|
-
`DO SQLite backend does not support aggregate op: ${String(op)}`,
|
|
413
|
-
"INVALID_QUERY"
|
|
414
|
-
);
|
|
415
|
-
}
|
|
416
|
-
const params = [];
|
|
417
|
-
const conditions = [];
|
|
418
|
-
for (const f of filters) {
|
|
419
|
-
conditions.push(compileFilter(f, params));
|
|
420
|
-
}
|
|
421
|
-
const where = conditions.length > 0 ? ` WHERE ${conditions.join(" AND ")}` : "";
|
|
422
|
-
const sql = `SELECT ${projections.join(", ")} FROM ${quoteDOIdent(table)}${where}`;
|
|
423
|
-
return { stmt: { sql, params }, aliases };
|
|
424
|
-
}
|
|
425
|
-
function compileDOSet(table, docId, record, nowMillis, mode) {
|
|
426
|
-
assertJsonSafePayload(record.data, DO_BACKEND_LABEL);
|
|
427
|
-
if (mode === "replace") {
|
|
428
|
-
const sql2 = `INSERT OR REPLACE INTO ${quoteDOIdent(table)} (
|
|
429
|
-
doc_id, a_type, a_uid, axb_type, b_type, b_uid, data, v, created_at, updated_at
|
|
430
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;
|
|
431
|
-
const params = [
|
|
432
|
-
docId,
|
|
433
|
-
record.aType,
|
|
434
|
-
record.aUid,
|
|
435
|
-
record.axbType,
|
|
436
|
-
record.bType,
|
|
437
|
-
record.bUid,
|
|
438
|
-
JSON.stringify(record.data ?? {}),
|
|
439
|
-
record.v ?? null,
|
|
440
|
-
nowMillis,
|
|
441
|
-
nowMillis
|
|
442
|
-
];
|
|
443
|
-
return { sql: sql2, params };
|
|
444
|
-
}
|
|
445
|
-
const insertParams = [
|
|
446
|
-
docId,
|
|
447
|
-
record.aType,
|
|
448
|
-
record.aUid,
|
|
449
|
-
record.axbType,
|
|
450
|
-
record.bType,
|
|
451
|
-
record.bUid,
|
|
452
|
-
JSON.stringify(record.data ?? {}),
|
|
453
|
-
record.v ?? null,
|
|
454
|
-
nowMillis,
|
|
455
|
-
nowMillis
|
|
456
|
-
];
|
|
457
|
-
const ops = flattenPatch(record.data ?? {});
|
|
458
|
-
const updateParams = [];
|
|
459
|
-
const dataExpr = compileDataOpsExpr(ops, `COALESCE("data", '{}')`, updateParams, DO_BACKEND_ERR_LABEL) ?? `COALESCE("data", '{}')`;
|
|
460
|
-
const sql = `INSERT INTO ${quoteDOIdent(table)} (
|
|
461
|
-
doc_id, a_type, a_uid, axb_type, b_type, b_uid, data, v, created_at, updated_at
|
|
462
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
463
|
-
ON CONFLICT(doc_id) DO UPDATE SET
|
|
464
|
-
"a_type" = excluded."a_type",
|
|
465
|
-
"a_uid" = excluded."a_uid",
|
|
466
|
-
"axb_type" = excluded."axb_type",
|
|
467
|
-
"b_type" = excluded."b_type",
|
|
468
|
-
"b_uid" = excluded."b_uid",
|
|
469
|
-
"data" = ${dataExpr},
|
|
470
|
-
"v" = COALESCE(excluded."v", "v"),
|
|
471
|
-
"created_at" = excluded."created_at",
|
|
472
|
-
"updated_at" = excluded."updated_at"`;
|
|
473
|
-
return { sql, params: [...insertParams, ...updateParams] };
|
|
474
|
-
}
|
|
475
|
-
function compileDOUpdate(table, docId, update, nowMillis) {
|
|
476
|
-
assertUpdatePayloadExclusive(update);
|
|
477
|
-
const setClauses = [];
|
|
478
|
-
const params = [];
|
|
479
|
-
if (update.replaceData) {
|
|
480
|
-
assertJsonSafePayload(update.replaceData, DO_BACKEND_LABEL);
|
|
481
|
-
setClauses.push(`"data" = ?`);
|
|
482
|
-
params.push(JSON.stringify(update.replaceData));
|
|
483
|
-
} else if (update.dataOps && update.dataOps.length > 0) {
|
|
484
|
-
for (const op of update.dataOps) {
|
|
485
|
-
if (!op.delete) assertJsonSafePayload(op.value, DO_BACKEND_LABEL);
|
|
486
|
-
}
|
|
487
|
-
const expr = compileDataOpsExpr(
|
|
488
|
-
update.dataOps,
|
|
489
|
-
`COALESCE("data", '{}')`,
|
|
490
|
-
params,
|
|
491
|
-
DO_BACKEND_ERR_LABEL
|
|
492
|
-
);
|
|
493
|
-
if (expr !== null) {
|
|
494
|
-
setClauses.push(`"data" = ${expr}`);
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
if (update.v !== void 0) {
|
|
498
|
-
setClauses.push(`"v" = ?`);
|
|
499
|
-
params.push(update.v);
|
|
500
|
-
}
|
|
501
|
-
setClauses.push(`"updated_at" = ?`);
|
|
502
|
-
params.push(nowMillis);
|
|
503
|
-
params.push(docId);
|
|
504
|
-
return {
|
|
505
|
-
sql: `UPDATE ${quoteDOIdent(table)} SET ${setClauses.join(", ")} WHERE "doc_id" = ?`,
|
|
506
|
-
params
|
|
507
|
-
};
|
|
508
|
-
}
|
|
509
|
-
function compileDODelete(table, docId) {
|
|
510
|
-
return {
|
|
511
|
-
sql: `DELETE FROM ${quoteDOIdent(table)} WHERE "doc_id" = ?`,
|
|
512
|
-
params: [docId]
|
|
513
|
-
};
|
|
514
|
-
}
|
|
515
|
-
function compileDOBulkDelete(table, filters) {
|
|
516
|
-
const params = [];
|
|
517
|
-
const conditions = [];
|
|
518
|
-
for (const f of filters) {
|
|
519
|
-
conditions.push(compileFilter(f, params));
|
|
520
|
-
}
|
|
521
|
-
const where = conditions.length > 0 ? ` WHERE ${conditions.join(" AND ")}` : "";
|
|
522
|
-
return {
|
|
523
|
-
sql: `DELETE FROM ${quoteDOIdent(table)}${where}`,
|
|
524
|
-
params
|
|
525
|
-
};
|
|
526
|
-
}
|
|
527
|
-
function compileDOBulkUpdate(table, filters, patchData, nowMillis) {
|
|
528
|
-
const dataOps = flattenPatch(patchData);
|
|
529
|
-
if (dataOps.length === 0) {
|
|
530
|
-
throw new FiregraphError(
|
|
531
|
-
"bulkUpdate() patch.data must contain at least one leaf \u2014 an empty patch would only rewrite `updated_at`, which is almost certainly a bug. Use `setDoc` with merge mode if you want to stamp without editing data.",
|
|
532
|
-
"INVALID_QUERY"
|
|
533
|
-
);
|
|
534
|
-
}
|
|
535
|
-
for (const op of dataOps) {
|
|
536
|
-
if (!op.delete) assertJsonSafePayload(op.value, DO_BACKEND_LABEL);
|
|
537
|
-
}
|
|
538
|
-
const setParams = [];
|
|
539
|
-
const expr = compileDataOpsExpr(
|
|
540
|
-
dataOps,
|
|
541
|
-
`COALESCE("data", '{}')`,
|
|
542
|
-
setParams,
|
|
543
|
-
DO_BACKEND_ERR_LABEL
|
|
544
|
-
);
|
|
545
|
-
if (expr === null) {
|
|
546
|
-
throw new FiregraphError(
|
|
547
|
-
"bulkUpdate() patch produced no SQL operations \u2014 internal invariant violated.",
|
|
548
|
-
"INVALID_ARGUMENT"
|
|
549
|
-
);
|
|
550
|
-
}
|
|
551
|
-
const setClauses = [`"data" = ${expr}`, `"updated_at" = ?`];
|
|
552
|
-
setParams.push(nowMillis);
|
|
553
|
-
const whereParams = [];
|
|
554
|
-
const conditions = [];
|
|
555
|
-
for (const f of filters) {
|
|
556
|
-
conditions.push(compileFilter(f, whereParams));
|
|
557
|
-
}
|
|
558
|
-
const where = conditions.length > 0 ? ` WHERE ${conditions.join(" AND ")}` : "";
|
|
559
|
-
return {
|
|
560
|
-
sql: `UPDATE ${quoteDOIdent(table)} SET ${setClauses.join(", ")}${where}`,
|
|
561
|
-
params: [...setParams, ...whereParams]
|
|
562
|
-
};
|
|
563
|
-
}
|
|
564
|
-
function compileDODeleteAll(table) {
|
|
565
|
-
return {
|
|
566
|
-
sql: `DELETE FROM ${quoteDOIdent(table)}`,
|
|
567
|
-
params: []
|
|
568
|
-
};
|
|
569
|
-
}
|
|
570
47
|
function rowToDORecord(row) {
|
|
571
48
|
const dataString = row.data;
|
|
572
49
|
const data = dataString ? JSON.parse(dataString) : {};
|
|
573
|
-
const createdAtMs =
|
|
574
|
-
const updatedAtMs =
|
|
50
|
+
const createdAtMs = rowTimestampToMillis(row.created_at);
|
|
51
|
+
const updatedAtMs = rowTimestampToMillis(row.updated_at);
|
|
575
52
|
const record = {
|
|
576
53
|
aType: row.a_type,
|
|
577
54
|
aUid: row.a_uid,
|
|
@@ -603,18 +80,6 @@ function hydrateDORecord(wire) {
|
|
|
603
80
|
}
|
|
604
81
|
return record;
|
|
605
82
|
}
|
|
606
|
-
function toMillis(value) {
|
|
607
|
-
if (typeof value === "number") return value;
|
|
608
|
-
if (typeof value === "bigint") return Number(value);
|
|
609
|
-
if (typeof value === "string") {
|
|
610
|
-
const n = Number(value);
|
|
611
|
-
if (Number.isFinite(n)) return n;
|
|
612
|
-
}
|
|
613
|
-
throw new FiregraphError(
|
|
614
|
-
`DO SQLite row has non-numeric timestamp column: ${typeof value} (${String(value)})`,
|
|
615
|
-
"INVALID_QUERY"
|
|
616
|
-
);
|
|
617
|
-
}
|
|
618
83
|
|
|
619
84
|
// src/cloudflare/backend.ts
|
|
620
85
|
function validateSegment(value, label) {
|
|
@@ -878,7 +343,7 @@ var DORPCBackend = class _DORPCBackend {
|
|
|
878
343
|
);
|
|
879
344
|
}
|
|
880
345
|
const { rows, columns } = await stub._fgFindEdgesProjected(select, filters, options);
|
|
881
|
-
return rows.map((row) =>
|
|
346
|
+
return rows.map((row) => decodeProjectedRow(row, columns));
|
|
882
347
|
}
|
|
883
348
|
// --- Cross-scope queries ---
|
|
884
349
|
//
|
|
@@ -1045,7 +510,7 @@ var FiregraphDO = class extends DurableObject {
|
|
|
1045
510
|
super(ctx, env);
|
|
1046
511
|
this.state = ctx;
|
|
1047
512
|
const table = options.table ?? DEFAULT_OPTIONS.table;
|
|
1048
|
-
|
|
513
|
+
validateTableName(table);
|
|
1049
514
|
this.table = table;
|
|
1050
515
|
this.registry = options.registry;
|
|
1051
516
|
this.coreIndexes = options.coreIndexes;
|
|
@@ -1064,12 +529,12 @@ var FiregraphDO = class extends DurableObject {
|
|
|
1064
529
|
// `src/cloudflare/backend.ts` calls these directly on the DO stub.
|
|
1065
530
|
// ---------------------------------------------------------------------------
|
|
1066
531
|
async _fgGetDoc(docId) {
|
|
1067
|
-
const stmt =
|
|
532
|
+
const stmt = compileSelectByDocId(this.table, docId);
|
|
1068
533
|
const rows = this.execAll(stmt);
|
|
1069
534
|
return rows.length === 0 ? null : rowToDORecord(rows[0]);
|
|
1070
535
|
}
|
|
1071
536
|
async _fgQuery(filters, options) {
|
|
1072
|
-
const stmt =
|
|
537
|
+
const stmt = compileSelect(this.table, filters, options);
|
|
1073
538
|
const rows = this.execAll(stmt);
|
|
1074
539
|
return rows.map(rowToDORecord);
|
|
1075
540
|
}
|
|
@@ -1081,7 +546,7 @@ var FiregraphDO = class extends DurableObject {
|
|
|
1081
546
|
* the wire payload stays a plain row of (alias → number | null).
|
|
1082
547
|
*/
|
|
1083
548
|
async _fgAggregate(spec, filters) {
|
|
1084
|
-
const { stmt, aliases } =
|
|
549
|
+
const { stmt, aliases } = compileAggregate(this.table, spec, filters);
|
|
1085
550
|
const rows = this.execAll(stmt);
|
|
1086
551
|
const row = rows[0] ?? {};
|
|
1087
552
|
const out = {};
|
|
@@ -1098,11 +563,11 @@ var FiregraphDO = class extends DurableObject {
|
|
|
1098
563
|
// RPC: writes
|
|
1099
564
|
// ---------------------------------------------------------------------------
|
|
1100
565
|
async _fgSetDoc(docId, record, mode) {
|
|
1101
|
-
const stmt =
|
|
566
|
+
const stmt = compileSet(this.table, docId, record, Date.now(), mode);
|
|
1102
567
|
this.execRun(stmt);
|
|
1103
568
|
}
|
|
1104
569
|
async _fgUpdateDoc(docId, update) {
|
|
1105
|
-
const stmt =
|
|
570
|
+
const stmt = compileUpdate(this.table, docId, update, Date.now());
|
|
1106
571
|
const sqlWithReturning = `${stmt.sql} RETURNING "doc_id"`;
|
|
1107
572
|
const rows = this.state.storage.sql.exec(sqlWithReturning, ...stmt.params).toArray();
|
|
1108
573
|
if (rows.length === 0) {
|
|
@@ -1110,7 +575,7 @@ var FiregraphDO = class extends DurableObject {
|
|
|
1110
575
|
}
|
|
1111
576
|
}
|
|
1112
577
|
async _fgDeleteDoc(docId) {
|
|
1113
|
-
const stmt =
|
|
578
|
+
const stmt = compileDelete(this.table, docId);
|
|
1114
579
|
this.execRun(stmt);
|
|
1115
580
|
}
|
|
1116
581
|
// ---------------------------------------------------------------------------
|
|
@@ -1128,11 +593,11 @@ var FiregraphDO = class extends DurableObject {
|
|
|
1128
593
|
const statements = ops.map((op) => {
|
|
1129
594
|
switch (op.kind) {
|
|
1130
595
|
case "set":
|
|
1131
|
-
return
|
|
596
|
+
return compileSet(this.table, op.docId, op.record, now, op.mode);
|
|
1132
597
|
case "update":
|
|
1133
|
-
return
|
|
598
|
+
return compileUpdate(this.table, op.docId, op.update, now);
|
|
1134
599
|
case "delete":
|
|
1135
|
-
return
|
|
600
|
+
return compileDelete(this.table, op.docId);
|
|
1136
601
|
}
|
|
1137
602
|
});
|
|
1138
603
|
this.state.storage.transactionSync(() => {
|
|
@@ -1151,8 +616,8 @@ var FiregraphDO = class extends DurableObject {
|
|
|
1151
616
|
// Without that topology the DO has no way to enumerate its children.
|
|
1152
617
|
// ---------------------------------------------------------------------------
|
|
1153
618
|
async _fgRemoveNodeCascade(uid) {
|
|
1154
|
-
const outgoingStmt =
|
|
1155
|
-
const incomingStmt =
|
|
619
|
+
const outgoingStmt = compileSelect(this.table, [{ field: "aUid", op: "==", value: uid }]);
|
|
620
|
+
const incomingStmt = compileSelect(this.table, [{ field: "bUid", op: "==", value: uid }]);
|
|
1156
621
|
const outgoingRows = this.execAll(outgoingStmt);
|
|
1157
622
|
const incomingRows = this.execAll(incomingStmt);
|
|
1158
623
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -1172,9 +637,9 @@ var FiregraphDO = class extends DurableObject {
|
|
|
1172
637
|
edgeDocIds.push(docId);
|
|
1173
638
|
}
|
|
1174
639
|
}
|
|
1175
|
-
const statements = edgeDocIds.map((id) =>
|
|
640
|
+
const statements = edgeDocIds.map((id) => compileDelete(this.table, id));
|
|
1176
641
|
if (nodeExists) {
|
|
1177
|
-
statements.push(
|
|
642
|
+
statements.push(compileDelete(this.table, computeNodeDocId(uid)));
|
|
1178
643
|
}
|
|
1179
644
|
if (statements.length === 0) {
|
|
1180
645
|
return {
|
|
@@ -1213,11 +678,11 @@ var FiregraphDO = class extends DurableObject {
|
|
|
1213
678
|
const plan = buildEdgeQueryPlan(params);
|
|
1214
679
|
let docIds;
|
|
1215
680
|
if (plan.strategy === "get") {
|
|
1216
|
-
const existsStmt =
|
|
681
|
+
const existsStmt = compileSelectByDocId(this.table, plan.docId);
|
|
1217
682
|
const rows = this.execAll(existsStmt);
|
|
1218
683
|
docIds = rows.length > 0 ? [plan.docId] : [];
|
|
1219
684
|
} else {
|
|
1220
|
-
const selectStmt =
|
|
685
|
+
const selectStmt = compileSelect(this.table, plan.filters, plan.options);
|
|
1221
686
|
const rows = this.execAll(selectStmt);
|
|
1222
687
|
docIds = rows.map(
|
|
1223
688
|
(row) => computeEdgeDocId(row.a_uid, row.axb_type, row.b_uid)
|
|
@@ -1226,7 +691,7 @@ var FiregraphDO = class extends DurableObject {
|
|
|
1226
691
|
if (docIds.length === 0) {
|
|
1227
692
|
return { deleted: 0, batches: 0, errors: [] };
|
|
1228
693
|
}
|
|
1229
|
-
const deleteStmts = docIds.map((id) =>
|
|
694
|
+
const deleteStmts = docIds.map((id) => compileDelete(this.table, id));
|
|
1230
695
|
try {
|
|
1231
696
|
this.state.storage.transactionSync(() => {
|
|
1232
697
|
for (const stmt of deleteStmts) {
|
|
@@ -1271,12 +736,12 @@ var FiregraphDO = class extends DurableObject {
|
|
|
1271
736
|
"INVALID_ARGUMENT"
|
|
1272
737
|
);
|
|
1273
738
|
}
|
|
1274
|
-
const stmt =
|
|
739
|
+
const stmt = compileBulkDelete(this.table, filters);
|
|
1275
740
|
return this.execDmlWithReturning(stmt);
|
|
1276
741
|
}
|
|
1277
742
|
async _fgBulkUpdate(filters, patch, _options) {
|
|
1278
743
|
void _options;
|
|
1279
|
-
const stmt =
|
|
744
|
+
const stmt = compileBulkUpdate(this.table, filters, patch.data, Date.now());
|
|
1280
745
|
return this.execDmlWithReturning(stmt);
|
|
1281
746
|
}
|
|
1282
747
|
// ---------------------------------------------------------------------------
|
|
@@ -1293,7 +758,7 @@ var FiregraphDO = class extends DurableObject {
|
|
|
1293
758
|
if (params.sources.length === 0) {
|
|
1294
759
|
return params.hydrate ? { edges: [], targets: [] } : { edges: [] };
|
|
1295
760
|
}
|
|
1296
|
-
const stmt =
|
|
761
|
+
const stmt = compileExpand(this.table, params);
|
|
1297
762
|
const rows = this.state.storage.sql.exec(stmt.sql, ...stmt.params).toArray();
|
|
1298
763
|
const edges = rows.map((row) => rowToDORecord(row));
|
|
1299
764
|
if (!params.hydrate) {
|
|
@@ -1305,7 +770,7 @@ var FiregraphDO = class extends DurableObject {
|
|
|
1305
770
|
if (uniqueTargets.length === 0) {
|
|
1306
771
|
return { edges, targets: [] };
|
|
1307
772
|
}
|
|
1308
|
-
const hydrateStmt =
|
|
773
|
+
const hydrateStmt = compileExpandHydrate(this.table, uniqueTargets);
|
|
1309
774
|
const hydrateRows = this.state.storage.sql.exec(hydrateStmt.sql, ...hydrateStmt.params).toArray();
|
|
1310
775
|
const byUid = /* @__PURE__ */ new Map();
|
|
1311
776
|
for (const row of hydrateRows) {
|
|
@@ -1327,7 +792,7 @@ var FiregraphDO = class extends DurableObject {
|
|
|
1327
792
|
// a typical projection); structured clone copes happily.
|
|
1328
793
|
// ---------------------------------------------------------------------------
|
|
1329
794
|
async _fgFindEdgesProjected(select, filters, options) {
|
|
1330
|
-
const { stmt, columns } =
|
|
795
|
+
const { stmt, columns } = compileFindEdgesProjected(this.table, select, filters, options);
|
|
1331
796
|
const rows = this.state.storage.sql.exec(stmt.sql, ...stmt.params).toArray();
|
|
1332
797
|
return { rows, columns };
|
|
1333
798
|
}
|
|
@@ -1365,14 +830,14 @@ var FiregraphDO = class extends DurableObject {
|
|
|
1365
830
|
* forever), but its storage can be emptied.
|
|
1366
831
|
*/
|
|
1367
832
|
async _fgDestroy() {
|
|
1368
|
-
const stmt =
|
|
833
|
+
const stmt = compileDeleteAll(this.table);
|
|
1369
834
|
this.execRun(stmt);
|
|
1370
835
|
}
|
|
1371
836
|
// ---------------------------------------------------------------------------
|
|
1372
837
|
// Internals
|
|
1373
838
|
// ---------------------------------------------------------------------------
|
|
1374
839
|
runSchema() {
|
|
1375
|
-
const statements =
|
|
840
|
+
const statements = buildSchemaStatements(this.table, {
|
|
1376
841
|
coreIndexes: this.coreIndexes,
|
|
1377
842
|
registry: this.registry
|
|
1378
843
|
});
|
|
@@ -1393,7 +858,7 @@ export {
|
|
|
1393
858
|
FiregraphDO,
|
|
1394
859
|
META_EDGE_TYPE,
|
|
1395
860
|
META_NODE_TYPE,
|
|
1396
|
-
buildDOSchemaStatements,
|
|
861
|
+
buildSchemaStatements as buildDOSchemaStatements,
|
|
1397
862
|
createCapabilities,
|
|
1398
863
|
createDOClient,
|
|
1399
864
|
createMergedRegistry,
|