convex-ents 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/deletion.d.ts +41 -0
- package/dist/deletion.js +1264 -0
- package/dist/deletion.js.map +1 -0
- package/dist/functions.d.ts +5 -303
- package/dist/functions.js +373 -253
- package/dist/functions.js.map +1 -1
- package/dist/index--8O_7LM9.d.ts +368 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +594 -260
- package/dist/index.js.map +1 -1
- package/dist/schema.d.ts +40 -1
- package/dist/schema.js +39 -5
- package/dist/schema.js.map +1 -1
- package/dist/writer.d.ts +5 -30
- package/dist/writer.js +333 -221
- package/dist/writer.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -24,7 +24,8 @@ __export(src_exports, {
|
|
|
24
24
|
defineEnt: () => defineEnt,
|
|
25
25
|
defineEntSchema: () => defineEntSchema,
|
|
26
26
|
entsTableFactory: () => entsTableFactory,
|
|
27
|
-
getEntDefinitions: () => getEntDefinitions
|
|
27
|
+
getEntDefinitions: () => getEntDefinitions,
|
|
28
|
+
scheduledDeleteFactory: () => scheduledDeleteFactory
|
|
28
29
|
});
|
|
29
30
|
module.exports = __toCommonJS(src_exports);
|
|
30
31
|
|
|
@@ -35,7 +36,7 @@ function defineEntSchema(schema, options) {
|
|
|
35
36
|
const tableNames = Object.keys(schema);
|
|
36
37
|
for (const tableName of tableNames) {
|
|
37
38
|
const table = schema[tableName];
|
|
38
|
-
for (const edge of
|
|
39
|
+
for (const edge of edgeConfigsBeforeDefineSchema(table)) {
|
|
39
40
|
if (
|
|
40
41
|
// Skip inverse edges, we process their forward edges
|
|
41
42
|
edge.cardinality === "multiple" && edge.type === "ref" && edge.inverse !== void 0 || // symmetric is only set by defineEntSchema,
|
|
@@ -52,7 +53,7 @@ function defineEntSchema(schema, options) {
|
|
|
52
53
|
);
|
|
53
54
|
}
|
|
54
55
|
const isSelfDirected = edge.to === tableName;
|
|
55
|
-
const inverseEdgeCandidates =
|
|
56
|
+
const inverseEdgeCandidates = edgeConfigsBeforeDefineSchema(
|
|
56
57
|
otherTable
|
|
57
58
|
).filter(canBeInverseEdge(tableName, edge, isSelfDirected));
|
|
58
59
|
if (inverseEdgeCandidates.length > 1) {
|
|
@@ -61,6 +62,11 @@ function defineEntSchema(schema, options) {
|
|
|
61
62
|
);
|
|
62
63
|
}
|
|
63
64
|
const inverseEdge = inverseEdgeCandidates[0];
|
|
65
|
+
if (edge.cardinality === "single" && edge.type === "field" && inverseEdge === void 0) {
|
|
66
|
+
throw new Error(
|
|
67
|
+
`Missing inverse edge in table "${otherTableName}" for edge "${edge.name}" in table "${tableName}"`
|
|
68
|
+
);
|
|
69
|
+
}
|
|
64
70
|
if (edge.cardinality === "single" && edge.type === "ref") {
|
|
65
71
|
if (inverseEdge === void 0) {
|
|
66
72
|
throw new Error(
|
|
@@ -82,6 +88,13 @@ function defineEntSchema(schema, options) {
|
|
|
82
88
|
}
|
|
83
89
|
inverseEdge.unique = true;
|
|
84
90
|
}
|
|
91
|
+
if (edge.cardinality === "single" && edge.type === "ref" || edge.cardinality === "multiple" && edge.type === "field") {
|
|
92
|
+
if (edge.deletion !== void 0 && deletionConfigFromEntDefinition(otherTable) === void 0) {
|
|
93
|
+
throw new Error(
|
|
94
|
+
`Cannot specify soft deletion behavior for edge "${edge.name}" in table "${tableName}" because the target table "${otherTableName}" does not have a "soft" or "scheduled" deletion behavior configured.`
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
85
98
|
if (edge.cardinality === "multiple") {
|
|
86
99
|
if (!isSelfDirected && inverseEdge === void 0) {
|
|
87
100
|
throw new Error(
|
|
@@ -165,11 +178,14 @@ function canBeInverseEdge(tableName, edge, isSelfDirected) {
|
|
|
165
178
|
return true;
|
|
166
179
|
};
|
|
167
180
|
}
|
|
168
|
-
function
|
|
181
|
+
function edgeConfigsBeforeDefineSchema(table) {
|
|
169
182
|
return Object.values(
|
|
170
183
|
table.edgeConfigs
|
|
171
184
|
);
|
|
172
185
|
}
|
|
186
|
+
function deletionConfigFromEntDefinition(table) {
|
|
187
|
+
return table.deletionConfig;
|
|
188
|
+
}
|
|
173
189
|
function defineEnt(documentSchema) {
|
|
174
190
|
return new EntDefinitionImpl(documentSchema);
|
|
175
191
|
}
|
|
@@ -187,6 +203,7 @@ var EntDefinitionImpl = class {
|
|
|
187
203
|
edgeConfigs = {};
|
|
188
204
|
fieldConfigs = {};
|
|
189
205
|
defaults = {};
|
|
206
|
+
deletionConfig;
|
|
190
207
|
constructor(documentSchema) {
|
|
191
208
|
this.documentSchema = documentSchema;
|
|
192
209
|
}
|
|
@@ -292,7 +309,8 @@ var EntDefinitionImpl = class {
|
|
|
292
309
|
);
|
|
293
310
|
}
|
|
294
311
|
const inverseName = options?.inverse;
|
|
295
|
-
|
|
312
|
+
const deletion = options?.deletion;
|
|
313
|
+
this.edgeConfigs[name] = ref !== void 0 ? { name, to, cardinality, type: "field", ref, deletion } : { name, to, cardinality, type: "ref", table, field, inverseField };
|
|
296
314
|
if (inverseName !== void 0) {
|
|
297
315
|
this.edgeConfigs[inverseName] = {
|
|
298
316
|
name: inverseName,
|
|
@@ -305,6 +323,22 @@ var EntDefinitionImpl = class {
|
|
|
305
323
|
}
|
|
306
324
|
return this;
|
|
307
325
|
}
|
|
326
|
+
deletion(type, options) {
|
|
327
|
+
if (this.documentSchema.deletionTime !== void 0) {
|
|
328
|
+
throw new Error(
|
|
329
|
+
`Cannot enable "${type}" deletion because "deletionTime" field was already defined.`
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
if (this.deletionConfig !== void 0) {
|
|
333
|
+
throw new Error(`Deletion behavior can only be specified once.`);
|
|
334
|
+
}
|
|
335
|
+
this.documentSchema = {
|
|
336
|
+
...this.documentSchema,
|
|
337
|
+
deletionTime: import_values.v.optional(import_values.v.number())
|
|
338
|
+
};
|
|
339
|
+
this.deletionConfig = { type, ...options };
|
|
340
|
+
return this;
|
|
341
|
+
}
|
|
308
342
|
};
|
|
309
343
|
function getEntDefinitions(schema) {
|
|
310
344
|
const tables = schema.tables;
|
|
@@ -314,7 +348,8 @@ function getEntDefinitions(schema) {
|
|
|
314
348
|
[tableName]: {
|
|
315
349
|
defaults: tables[tableName].defaults,
|
|
316
350
|
edges: tables[tableName].edgeConfigs,
|
|
317
|
-
fields: tables[tableName].fieldConfigs
|
|
351
|
+
fields: tables[tableName].fieldConfigs,
|
|
352
|
+
deletionConfig: tables[tableName].deletionConfig
|
|
318
353
|
}
|
|
319
354
|
}),
|
|
320
355
|
{}
|
|
@@ -322,79 +357,119 @@ function getEntDefinitions(schema) {
|
|
|
322
357
|
}
|
|
323
358
|
|
|
324
359
|
// src/writer.ts
|
|
325
|
-
var
|
|
326
|
-
|
|
327
|
-
|
|
360
|
+
var import_server2 = require("convex/server");
|
|
361
|
+
var WriterImplBase = class _WriterImplBase {
|
|
362
|
+
constructor(ctx, entDefinitions, table) {
|
|
363
|
+
this.ctx = ctx;
|
|
328
364
|
this.entDefinitions = entDefinitions;
|
|
329
365
|
this.table = table;
|
|
330
366
|
}
|
|
331
|
-
async
|
|
367
|
+
async deleteId(id, behavior) {
|
|
368
|
+
await this.checkReadAndWriteRule("delete", id, void 0);
|
|
369
|
+
const deletionConfig = getDeletionConfig(this.entDefinitions, this.table);
|
|
370
|
+
const isDeletingSoftly = behavior !== "hard" && deletionConfig !== void 0 && (deletionConfig.type === "soft" || deletionConfig.type === "scheduled");
|
|
371
|
+
if (behavior === "soft" && !isDeletingSoftly) {
|
|
372
|
+
throw new Error(
|
|
373
|
+
`Cannot soft delete document with ID "${id}" in table "${this.table}" because it does not have an "allowSoft", "soft" or "scheduled" deletion behavior configured.`
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
const edges = {};
|
|
332
377
|
await Promise.all(
|
|
333
|
-
Object.values(
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
await this.db.delete(idOrIds.remove);
|
|
378
|
+
Object.values(getEdgeDefinitions(this.entDefinitions, this.table)).map(
|
|
379
|
+
async (edgeDefinition) => {
|
|
380
|
+
const key = edgeDefinition.name;
|
|
381
|
+
if (edgeDefinition.cardinality === "single" && edgeDefinition.type === "ref" || edgeDefinition.cardinality === "multiple" && edgeDefinition.type === "field") {
|
|
382
|
+
if (!isDeletingSoftly || edgeDefinition.deletion === "soft") {
|
|
383
|
+
const remove = (await this.ctx.db.query(edgeDefinition.to).withIndex(
|
|
384
|
+
edgeDefinition.ref,
|
|
385
|
+
(q) => q.eq(edgeDefinition.ref, id)
|
|
386
|
+
).collect()).map((doc) => doc._id);
|
|
387
|
+
edges[key] = { remove };
|
|
344
388
|
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
389
|
+
} else if (edgeDefinition.cardinality === "multiple") {
|
|
390
|
+
if (!isDeletingSoftly) {
|
|
391
|
+
const removeEdges = (await this.ctx.db.query(edgeDefinition.table).withIndex(
|
|
392
|
+
edgeDefinition.field,
|
|
393
|
+
(q) => q.eq(edgeDefinition.field, id)
|
|
394
|
+
).collect()).concat(
|
|
395
|
+
edgeDefinition.symmetric ? await this.ctx.db.query(edgeDefinition.table).withIndex(
|
|
396
|
+
edgeDefinition.ref,
|
|
397
|
+
(q) => q.eq(edgeDefinition.ref, id)
|
|
398
|
+
).collect() : []
|
|
399
|
+
).map((doc) => doc._id);
|
|
400
|
+
edges[key] = { removeEdges };
|
|
350
401
|
}
|
|
351
402
|
}
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
|
|
403
|
+
}
|
|
404
|
+
)
|
|
405
|
+
);
|
|
406
|
+
const deletionTime = +/* @__PURE__ */ new Date();
|
|
407
|
+
if (isDeletingSoftly) {
|
|
408
|
+
await this.ctx.db.patch(id, { deletionTime });
|
|
409
|
+
} else {
|
|
410
|
+
try {
|
|
411
|
+
await this.ctx.db.delete(id);
|
|
412
|
+
} catch (e) {
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
await this.writeEdges(id, edges, isDeletingSoftly);
|
|
416
|
+
if (deletionConfig !== void 0 && deletionConfig.type === "scheduled") {
|
|
417
|
+
const fnRef = this.ctx.scheduledDelete ?? (0, import_server2.makeFunctionReference)(
|
|
418
|
+
"functions:scheduledDelete"
|
|
419
|
+
);
|
|
420
|
+
await this.ctx.scheduler.runAfter(deletionConfig.delayMs ?? 0, fnRef, {
|
|
421
|
+
origin: {
|
|
422
|
+
id,
|
|
423
|
+
table: this.table,
|
|
424
|
+
deletionTime
|
|
425
|
+
},
|
|
426
|
+
inProgress: false,
|
|
427
|
+
stack: []
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
return id;
|
|
431
|
+
}
|
|
432
|
+
async deletedIdIn(id, table, cascadingSoft) {
|
|
433
|
+
await new _WriterImplBase(this.ctx, this.entDefinitions, table).deleteId(
|
|
434
|
+
id,
|
|
435
|
+
cascadingSoft ? "soft" : "hard"
|
|
436
|
+
);
|
|
437
|
+
}
|
|
438
|
+
async writeEdges(docId, changes, deleteSoftly) {
|
|
439
|
+
await Promise.all(
|
|
440
|
+
Object.values(getEdgeDefinitions(this.entDefinitions, this.table)).map(
|
|
441
|
+
async (edgeDefinition) => {
|
|
442
|
+
const idOrIds = changes[edgeDefinition.name];
|
|
443
|
+
if (idOrIds === void 0) {
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
if (edgeDefinition.cardinality === "single" && edgeDefinition.type === "ref" || edgeDefinition.cardinality === "multiple" && edgeDefinition.type === "field") {
|
|
447
|
+
if (idOrIds.remove !== void 0 && idOrIds.remove.length > 0) {
|
|
355
448
|
await Promise.all(
|
|
356
449
|
idOrIds.remove.map(
|
|
357
|
-
(id) => this.
|
|
450
|
+
(id) => this.deletedIdIn(
|
|
451
|
+
id,
|
|
452
|
+
edgeDefinition.to,
|
|
453
|
+
(deleteSoftly ?? false) && edgeDefinition.deletion === "soft"
|
|
454
|
+
)
|
|
358
455
|
)
|
|
359
456
|
);
|
|
360
457
|
}
|
|
361
|
-
if (idOrIds.add !== void 0) {
|
|
458
|
+
if (idOrIds.add !== void 0 && idOrIds.add.length > 0) {
|
|
362
459
|
await Promise.all(
|
|
363
460
|
idOrIds.add.map(
|
|
364
|
-
async (id) => this.db.patch(id, {
|
|
461
|
+
async (id) => this.ctx.db.patch(id, {
|
|
365
462
|
[edgeDefinition.ref]: docId
|
|
366
463
|
})
|
|
367
464
|
)
|
|
368
465
|
);
|
|
369
466
|
}
|
|
370
|
-
} else {
|
|
371
|
-
|
|
372
|
-
if (idOrIds.remove !== void 0) {
|
|
373
|
-
removeEdges = (await Promise.all(
|
|
374
|
-
idOrIds.remove.map(
|
|
375
|
-
async (id) => (await this.db.query(edgeDefinition.table).withIndex(
|
|
376
|
-
edgeDefinition.field,
|
|
377
|
-
(q) => q.eq(edgeDefinition.field, docId).eq(
|
|
378
|
-
edgeDefinition.ref,
|
|
379
|
-
id
|
|
380
|
-
)
|
|
381
|
-
).collect()).concat(
|
|
382
|
-
edgeDefinition.symmetric ? await this.db.query(edgeDefinition.table).withIndex(
|
|
383
|
-
edgeDefinition.ref,
|
|
384
|
-
(q) => q.eq(edgeDefinition.ref, docId).eq(edgeDefinition.field, id)
|
|
385
|
-
).collect() : []
|
|
386
|
-
)
|
|
387
|
-
)
|
|
388
|
-
)).map((doc) => doc._id);
|
|
389
|
-
}
|
|
390
|
-
if (idOrIds.removeEdges !== void 0) {
|
|
391
|
-
removeEdges = idOrIds.removeEdges;
|
|
392
|
-
}
|
|
393
|
-
if (removeEdges.length > 0) {
|
|
467
|
+
} else if (edgeDefinition.cardinality === "multiple") {
|
|
468
|
+
if ((idOrIds.removeEdges ?? []).length > 0) {
|
|
394
469
|
await Promise.all(
|
|
395
|
-
removeEdges.map(async (id) => {
|
|
470
|
+
idOrIds.removeEdges.map(async (id) => {
|
|
396
471
|
try {
|
|
397
|
-
await this.db.delete(id);
|
|
472
|
+
await this.ctx.db.delete(id);
|
|
398
473
|
} catch (e) {
|
|
399
474
|
}
|
|
400
475
|
})
|
|
@@ -403,12 +478,12 @@ var WriterImplBase = class {
|
|
|
403
478
|
if (idOrIds.add !== void 0) {
|
|
404
479
|
await Promise.all(
|
|
405
480
|
idOrIds.add.map(async (id) => {
|
|
406
|
-
await this.db.insert(edgeDefinition.table, {
|
|
481
|
+
await this.ctx.db.insert(edgeDefinition.table, {
|
|
407
482
|
[edgeDefinition.field]: docId,
|
|
408
483
|
[edgeDefinition.ref]: id
|
|
409
484
|
});
|
|
410
485
|
if (edgeDefinition.symmetric) {
|
|
411
|
-
await this.db.insert(edgeDefinition.table, {
|
|
486
|
+
await this.ctx.db.insert(edgeDefinition.table, {
|
|
412
487
|
[edgeDefinition.field]: id,
|
|
413
488
|
[edgeDefinition.ref]: docId
|
|
414
489
|
});
|
|
@@ -418,7 +493,7 @@ var WriterImplBase = class {
|
|
|
418
493
|
}
|
|
419
494
|
}
|
|
420
495
|
}
|
|
421
|
-
|
|
496
|
+
)
|
|
422
497
|
);
|
|
423
498
|
}
|
|
424
499
|
async checkUniqueness(value, id) {
|
|
@@ -429,7 +504,7 @@ var WriterImplBase = class {
|
|
|
429
504
|
if (fieldDefinition.unique) {
|
|
430
505
|
const key = fieldDefinition.name;
|
|
431
506
|
const fieldValue = value[key];
|
|
432
|
-
const existing = await this.db.query(this.table).withIndex(key, (q) => q.eq(key, value[key])).unique();
|
|
507
|
+
const existing = await this.ctx.db.query(this.table).withIndex(key, (q) => q.eq(key, value[key])).unique();
|
|
433
508
|
if (existing !== null && (id === void 0 || existing._id !== id)) {
|
|
434
509
|
throw new Error(
|
|
435
510
|
`In table "${this.table}" cannot create a duplicate document with field "${key}" of value \`${fieldValue}\`, existing document with ID "${existing._id}" already has it.`
|
|
@@ -439,28 +514,31 @@ var WriterImplBase = class {
|
|
|
439
514
|
})
|
|
440
515
|
);
|
|
441
516
|
await Promise.all(
|
|
442
|
-
Object.values(
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
517
|
+
Object.values(getEdgeDefinitions(this.entDefinitions, this.table)).map(
|
|
518
|
+
async (edgeDefinition) => {
|
|
519
|
+
if (edgeDefinition.cardinality === "single" && edgeDefinition.type === "field" && edgeDefinition.unique) {
|
|
520
|
+
const key = edgeDefinition.field;
|
|
521
|
+
if (value[key] === void 0) {
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
const existing = await this.ctx.db.query(this.table).withIndex(key, (q) => q.eq(key, value[key])).unique();
|
|
525
|
+
if (existing !== null && (id === void 0 || existing._id !== id)) {
|
|
526
|
+
throw new Error(
|
|
527
|
+
`In table "${this.table}" cannot create a duplicate 1:1 edge "${edgeDefinition.name}" to ID "${value[key]}", existing document with ID "${existing._id}" already has it.`
|
|
528
|
+
);
|
|
529
|
+
}
|
|
455
530
|
}
|
|
456
531
|
}
|
|
457
|
-
|
|
532
|
+
)
|
|
458
533
|
);
|
|
459
534
|
}
|
|
460
535
|
fieldsOnly(value) {
|
|
461
536
|
const fields = {};
|
|
462
537
|
Object.keys(value).forEach((key) => {
|
|
463
|
-
const edgeDefinition =
|
|
538
|
+
const edgeDefinition = getEdgeDefinitions(
|
|
539
|
+
this.entDefinitions,
|
|
540
|
+
this.table
|
|
541
|
+
)[key];
|
|
464
542
|
if (edgeDefinition === void 0) {
|
|
465
543
|
fields[key] = value[key];
|
|
466
544
|
}
|
|
@@ -471,7 +549,7 @@ var WriterImplBase = class {
|
|
|
471
549
|
if (id !== void 0) {
|
|
472
550
|
const readPolicy = getReadRule(this.entDefinitions, this.table);
|
|
473
551
|
if (readPolicy !== void 0) {
|
|
474
|
-
const doc = await this.db.get(id);
|
|
552
|
+
const doc = await this.ctx.db.get(id);
|
|
475
553
|
if (doc === null) {
|
|
476
554
|
throw new Error(
|
|
477
555
|
`Cannot update document with ID "${id}" in table "${this.table} because it does not exist"`
|
|
@@ -490,8 +568,8 @@ var WriterImplBase = class {
|
|
|
490
568
|
return;
|
|
491
569
|
}
|
|
492
570
|
const ent = id === void 0 ? void 0 : entWrapper(
|
|
493
|
-
await this.db.get(id),
|
|
494
|
-
this.
|
|
571
|
+
await this.ctx.db.get(id),
|
|
572
|
+
this.ctx,
|
|
495
573
|
this.entDefinitions,
|
|
496
574
|
this.table
|
|
497
575
|
);
|
|
@@ -523,17 +601,17 @@ var WriterImplBase = class {
|
|
|
523
601
|
|
|
524
602
|
// src/functions.ts
|
|
525
603
|
var PromiseQueryOrNullImpl = class _PromiseQueryOrNullImpl extends Promise {
|
|
526
|
-
constructor(
|
|
604
|
+
constructor(ctx, entDefinitions, table, retrieve) {
|
|
527
605
|
super(() => {
|
|
528
606
|
});
|
|
529
|
-
this.
|
|
607
|
+
this.ctx = ctx;
|
|
530
608
|
this.entDefinitions = entDefinitions;
|
|
531
609
|
this.table = table;
|
|
532
610
|
this.retrieve = retrieve;
|
|
533
611
|
}
|
|
534
612
|
filter(predicate) {
|
|
535
613
|
return new _PromiseQueryOrNullImpl(
|
|
536
|
-
this.
|
|
614
|
+
this.ctx,
|
|
537
615
|
this.entDefinitions,
|
|
538
616
|
this.table,
|
|
539
617
|
async () => {
|
|
@@ -545,16 +623,18 @@ var PromiseQueryOrNullImpl = class _PromiseQueryOrNullImpl extends Promise {
|
|
|
545
623
|
}
|
|
546
624
|
);
|
|
547
625
|
}
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
626
|
+
map(callbackFn) {
|
|
627
|
+
return new PromiseArrayImpl(async () => {
|
|
628
|
+
const array = await this;
|
|
629
|
+
if (array === null) {
|
|
630
|
+
return null;
|
|
631
|
+
}
|
|
632
|
+
return await Promise.all(array.map(callbackFn));
|
|
633
|
+
});
|
|
554
634
|
}
|
|
555
635
|
order(order, indexName) {
|
|
556
636
|
return new _PromiseQueryOrNullImpl(
|
|
557
|
-
this.
|
|
637
|
+
this.ctx,
|
|
558
638
|
this.entDefinitions,
|
|
559
639
|
this.table,
|
|
560
640
|
async () => {
|
|
@@ -569,17 +649,18 @@ var PromiseQueryOrNullImpl = class _PromiseQueryOrNullImpl extends Promise {
|
|
|
569
649
|
}
|
|
570
650
|
);
|
|
571
651
|
}
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
652
|
+
paginate(paginationOpts) {
|
|
653
|
+
return new PromisePaginationResultOrNullImpl(
|
|
654
|
+
this.ctx,
|
|
655
|
+
this.entDefinitions,
|
|
656
|
+
this.table,
|
|
657
|
+
this.retrieve,
|
|
658
|
+
paginationOpts
|
|
659
|
+
);
|
|
579
660
|
}
|
|
580
661
|
take(n) {
|
|
581
662
|
return new PromiseEntsOrNullImpl(
|
|
582
|
-
this.
|
|
663
|
+
this.ctx,
|
|
583
664
|
this.entDefinitions,
|
|
584
665
|
this.table,
|
|
585
666
|
async () => {
|
|
@@ -590,7 +671,7 @@ var PromiseQueryOrNullImpl = class _PromiseQueryOrNullImpl extends Promise {
|
|
|
590
671
|
}
|
|
591
672
|
first() {
|
|
592
673
|
return new PromiseEntOrNullImpl(
|
|
593
|
-
this.
|
|
674
|
+
this.ctx,
|
|
594
675
|
this.entDefinitions,
|
|
595
676
|
this.table,
|
|
596
677
|
async () => {
|
|
@@ -606,7 +687,7 @@ var PromiseQueryOrNullImpl = class _PromiseQueryOrNullImpl extends Promise {
|
|
|
606
687
|
}
|
|
607
688
|
firstX() {
|
|
608
689
|
return new PromiseEntWriterImpl(
|
|
609
|
-
this.
|
|
690
|
+
this.ctx,
|
|
610
691
|
this.entDefinitions,
|
|
611
692
|
this.table,
|
|
612
693
|
async () => {
|
|
@@ -625,7 +706,7 @@ var PromiseQueryOrNullImpl = class _PromiseQueryOrNullImpl extends Promise {
|
|
|
625
706
|
}
|
|
626
707
|
unique() {
|
|
627
708
|
return new PromiseEntOrNullImpl(
|
|
628
|
-
this.
|
|
709
|
+
this.ctx,
|
|
629
710
|
this.entDefinitions,
|
|
630
711
|
this.table,
|
|
631
712
|
async () => {
|
|
@@ -647,7 +728,7 @@ var PromiseQueryOrNullImpl = class _PromiseQueryOrNullImpl extends Promise {
|
|
|
647
728
|
}
|
|
648
729
|
uniqueX() {
|
|
649
730
|
return new PromiseEntWriterImpl(
|
|
650
|
-
this.
|
|
731
|
+
this.ctx,
|
|
651
732
|
this.entDefinitions,
|
|
652
733
|
this.table,
|
|
653
734
|
async () => {
|
|
@@ -674,7 +755,7 @@ var PromiseQueryOrNullImpl = class _PromiseQueryOrNullImpl extends Promise {
|
|
|
674
755
|
}
|
|
675
756
|
const docs = await query.collect();
|
|
676
757
|
return filterByReadRule(
|
|
677
|
-
this.
|
|
758
|
+
this.ctx,
|
|
678
759
|
this.entDefinitions,
|
|
679
760
|
this.table,
|
|
680
761
|
docs,
|
|
@@ -684,7 +765,7 @@ var PromiseQueryOrNullImpl = class _PromiseQueryOrNullImpl extends Promise {
|
|
|
684
765
|
then(onfulfilled, onrejected) {
|
|
685
766
|
return this.docs().then(
|
|
686
767
|
(documents) => documents === null ? null : documents.map(
|
|
687
|
-
(doc) => entWrapper(doc, this.
|
|
768
|
+
(doc) => entWrapper(doc, this.ctx, this.entDefinitions, this.table)
|
|
688
769
|
)
|
|
689
770
|
).then(onfulfilled, onrejected);
|
|
690
771
|
}
|
|
@@ -713,7 +794,7 @@ var PromiseQueryOrNullImpl = class _PromiseQueryOrNullImpl extends Promise {
|
|
|
713
794
|
}
|
|
714
795
|
docs.push(
|
|
715
796
|
...(await filterByReadRule(
|
|
716
|
-
this.
|
|
797
|
+
this.ctx,
|
|
717
798
|
this.entDefinitions,
|
|
718
799
|
this.table,
|
|
719
800
|
page,
|
|
@@ -725,9 +806,57 @@ var PromiseQueryOrNullImpl = class _PromiseQueryOrNullImpl extends Promise {
|
|
|
725
806
|
return docs;
|
|
726
807
|
}
|
|
727
808
|
};
|
|
809
|
+
var PromisePaginationResultOrNullImpl = class extends Promise {
|
|
810
|
+
constructor(ctx, entDefinitions, table, retrieve, paginationOpts) {
|
|
811
|
+
super(() => {
|
|
812
|
+
});
|
|
813
|
+
this.ctx = ctx;
|
|
814
|
+
this.entDefinitions = entDefinitions;
|
|
815
|
+
this.table = table;
|
|
816
|
+
this.retrieve = retrieve;
|
|
817
|
+
this.paginationOpts = paginationOpts;
|
|
818
|
+
}
|
|
819
|
+
async map(callbackFn) {
|
|
820
|
+
const result = await this;
|
|
821
|
+
if (result === null) {
|
|
822
|
+
return null;
|
|
823
|
+
}
|
|
824
|
+
return {
|
|
825
|
+
...result,
|
|
826
|
+
page: await Promise.all(result.page.map(callbackFn))
|
|
827
|
+
};
|
|
828
|
+
}
|
|
829
|
+
async docs() {
|
|
830
|
+
const query = await this.retrieve();
|
|
831
|
+
if (query === null) {
|
|
832
|
+
return null;
|
|
833
|
+
}
|
|
834
|
+
const result = await query.paginate(this.paginationOpts);
|
|
835
|
+
return {
|
|
836
|
+
...result,
|
|
837
|
+
page: await filterByReadRule(
|
|
838
|
+
this.ctx,
|
|
839
|
+
this.entDefinitions,
|
|
840
|
+
this.table,
|
|
841
|
+
result.page,
|
|
842
|
+
false
|
|
843
|
+
)
|
|
844
|
+
};
|
|
845
|
+
}
|
|
846
|
+
then(onfulfilled, onrejected) {
|
|
847
|
+
return this.docs().then(
|
|
848
|
+
(result) => result === null ? null : {
|
|
849
|
+
...result,
|
|
850
|
+
page: result.page.map(
|
|
851
|
+
(doc) => entWrapper(doc, this.ctx, this.entDefinitions, this.table)
|
|
852
|
+
)
|
|
853
|
+
}
|
|
854
|
+
).then(onfulfilled, onrejected);
|
|
855
|
+
}
|
|
856
|
+
};
|
|
728
857
|
var PromiseTableImpl = class extends PromiseQueryOrNullImpl {
|
|
729
|
-
constructor(
|
|
730
|
-
super(
|
|
858
|
+
constructor(ctx, entDefinitions, table) {
|
|
859
|
+
super(ctx, entDefinitions, table, async () => ctx.db.query(table));
|
|
731
860
|
}
|
|
732
861
|
get(...args) {
|
|
733
862
|
return this.getImpl(args);
|
|
@@ -743,18 +872,18 @@ var PromiseTableImpl = class extends PromiseQueryOrNullImpl {
|
|
|
743
872
|
}
|
|
744
873
|
getImpl(args, throwIfNull = false) {
|
|
745
874
|
return new PromiseEntWriterImpl(
|
|
746
|
-
this.
|
|
875
|
+
this.ctx,
|
|
747
876
|
this.entDefinitions,
|
|
748
877
|
this.table,
|
|
749
878
|
args.length === 1 ? async () => {
|
|
750
879
|
const id = args[0];
|
|
751
|
-
if (this.db.normalizeId(this.table, id) === null) {
|
|
880
|
+
if (this.ctx.db.normalizeId(this.table, id) === null) {
|
|
752
881
|
throw new Error(`Invalid id \`${id}\` for table "${this.table}"`);
|
|
753
882
|
}
|
|
754
883
|
return {
|
|
755
884
|
id,
|
|
756
885
|
doc: async () => {
|
|
757
|
-
const doc = await this.db.get(id);
|
|
886
|
+
const doc = await this.ctx.db.get(id);
|
|
758
887
|
if (throwIfNull && doc === null) {
|
|
759
888
|
throw new Error(
|
|
760
889
|
`Document not found with id \`${id}\` in table "${this.table}"`
|
|
@@ -765,7 +894,7 @@ var PromiseTableImpl = class extends PromiseQueryOrNullImpl {
|
|
|
765
894
|
};
|
|
766
895
|
} : async () => {
|
|
767
896
|
const [indexName, value] = args;
|
|
768
|
-
const doc = await this.db.query(this.table).withIndex(indexName, (q) => q.eq(indexName, value)).unique();
|
|
897
|
+
const doc = await this.ctx.db.query(this.table).withIndex(indexName, (q) => q.eq(indexName, value)).unique();
|
|
769
898
|
if (throwIfNull && doc === null) {
|
|
770
899
|
throw new Error(
|
|
771
900
|
`Table "${this.table}" does not contain document with field "${indexName}" = \`${value}\``
|
|
@@ -778,13 +907,13 @@ var PromiseTableImpl = class extends PromiseQueryOrNullImpl {
|
|
|
778
907
|
}
|
|
779
908
|
getManyImpl(args, throwIfNull = false) {
|
|
780
909
|
return new PromiseEntsOrNullImpl(
|
|
781
|
-
this.
|
|
910
|
+
this.ctx,
|
|
782
911
|
this.entDefinitions,
|
|
783
912
|
this.table,
|
|
784
913
|
args.length === 1 ? async () => {
|
|
785
914
|
const ids = args[0];
|
|
786
915
|
ids.forEach((id) => {
|
|
787
|
-
if (this.db.normalizeId(this.table, id) === null) {
|
|
916
|
+
if (this.ctx.db.normalizeId(this.table, id) === null) {
|
|
788
917
|
throw new Error(
|
|
789
918
|
`Invalid id \`${id}\` for table "${this.table}"`
|
|
790
919
|
);
|
|
@@ -792,7 +921,7 @@ var PromiseTableImpl = class extends PromiseQueryOrNullImpl {
|
|
|
792
921
|
});
|
|
793
922
|
return await Promise.all(
|
|
794
923
|
ids.map(async (id) => {
|
|
795
|
-
const doc = await this.db.get(id);
|
|
924
|
+
const doc = await this.ctx.db.get(id);
|
|
796
925
|
if (doc === null) {
|
|
797
926
|
throw new Error(
|
|
798
927
|
`Document not found with id \`${id}\` in table "${this.table}"`
|
|
@@ -805,7 +934,7 @@ var PromiseTableImpl = class extends PromiseQueryOrNullImpl {
|
|
|
805
934
|
const [indexName, values] = args;
|
|
806
935
|
return await Promise.all(
|
|
807
936
|
values.map(async (value) => {
|
|
808
|
-
const doc = await this.db.query(this.table).withIndex(indexName, (q) => q.eq(indexName, value)).unique();
|
|
937
|
+
const doc = await this.ctx.db.query(this.table).withIndex(indexName, (q) => q.eq(indexName, value)).unique();
|
|
809
938
|
if (throwIfNull && doc === null) {
|
|
810
939
|
throw new Error(
|
|
811
940
|
`Table "${this.table}" does not contain document with field "${indexName}" = \`${value}\``
|
|
@@ -819,7 +948,7 @@ var PromiseTableImpl = class extends PromiseQueryOrNullImpl {
|
|
|
819
948
|
);
|
|
820
949
|
}
|
|
821
950
|
normalizeId(id) {
|
|
822
|
-
return this.db.normalizeId(this.table, id);
|
|
951
|
+
return this.ctx.db.normalizeId(this.table, id);
|
|
823
952
|
}
|
|
824
953
|
// normalizeId or throw
|
|
825
954
|
normalizeIdX(id) {
|
|
@@ -831,7 +960,7 @@ var PromiseTableImpl = class extends PromiseQueryOrNullImpl {
|
|
|
831
960
|
}
|
|
832
961
|
withIndex(indexName, indexRange) {
|
|
833
962
|
return new PromiseQueryOrNullImpl(
|
|
834
|
-
this.
|
|
963
|
+
this.ctx,
|
|
835
964
|
this.entDefinitions,
|
|
836
965
|
this.table,
|
|
837
966
|
async () => {
|
|
@@ -842,7 +971,7 @@ var PromiseTableImpl = class extends PromiseQueryOrNullImpl {
|
|
|
842
971
|
}
|
|
843
972
|
search(indexName, searchFilter) {
|
|
844
973
|
return new PromiseQueryOrNullImpl(
|
|
845
|
-
this.
|
|
974
|
+
this.ctx,
|
|
846
975
|
this.entDefinitions,
|
|
847
976
|
this.table,
|
|
848
977
|
async () => {
|
|
@@ -853,25 +982,27 @@ var PromiseTableImpl = class extends PromiseQueryOrNullImpl {
|
|
|
853
982
|
}
|
|
854
983
|
};
|
|
855
984
|
var PromiseEntsOrNullImpl = class extends Promise {
|
|
856
|
-
constructor(
|
|
985
|
+
constructor(ctx, entDefinitions, table, retrieve, throwIfNull) {
|
|
857
986
|
super(() => {
|
|
858
987
|
});
|
|
859
|
-
this.
|
|
988
|
+
this.ctx = ctx;
|
|
860
989
|
this.entDefinitions = entDefinitions;
|
|
861
990
|
this.table = table;
|
|
862
991
|
this.retrieve = retrieve;
|
|
863
992
|
this.throwIfNull = throwIfNull;
|
|
864
993
|
}
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
994
|
+
map(callbackFn) {
|
|
995
|
+
return new PromiseArrayImpl(async () => {
|
|
996
|
+
const array = await this;
|
|
997
|
+
if (array === null) {
|
|
998
|
+
return null;
|
|
999
|
+
}
|
|
1000
|
+
return await Promise.all(array.map(callbackFn));
|
|
1001
|
+
});
|
|
871
1002
|
}
|
|
872
1003
|
first() {
|
|
873
1004
|
return new PromiseEntOrNullImpl(
|
|
874
|
-
this.
|
|
1005
|
+
this.ctx,
|
|
875
1006
|
this.entDefinitions,
|
|
876
1007
|
this.table,
|
|
877
1008
|
async () => {
|
|
@@ -886,7 +1017,7 @@ var PromiseEntsOrNullImpl = class extends Promise {
|
|
|
886
1017
|
}
|
|
887
1018
|
firstX() {
|
|
888
1019
|
return new PromiseEntOrNullImpl(
|
|
889
|
-
this.
|
|
1020
|
+
this.ctx,
|
|
890
1021
|
this.entDefinitions,
|
|
891
1022
|
this.table,
|
|
892
1023
|
async () => {
|
|
@@ -905,7 +1036,7 @@ var PromiseEntsOrNullImpl = class extends Promise {
|
|
|
905
1036
|
}
|
|
906
1037
|
unique() {
|
|
907
1038
|
return new PromiseEntOrNullImpl(
|
|
908
|
-
this.
|
|
1039
|
+
this.ctx,
|
|
909
1040
|
this.entDefinitions,
|
|
910
1041
|
this.table,
|
|
911
1042
|
async () => {
|
|
@@ -923,7 +1054,7 @@ var PromiseEntsOrNullImpl = class extends Promise {
|
|
|
923
1054
|
}
|
|
924
1055
|
uniqueX() {
|
|
925
1056
|
return new PromiseEntOrNullImpl(
|
|
926
|
-
this.
|
|
1057
|
+
this.ctx,
|
|
927
1058
|
this.entDefinitions,
|
|
928
1059
|
this.table,
|
|
929
1060
|
async () => {
|
|
@@ -945,7 +1076,7 @@ var PromiseEntsOrNullImpl = class extends Promise {
|
|
|
945
1076
|
async docs() {
|
|
946
1077
|
const docs = await this.retrieve();
|
|
947
1078
|
return filterByReadRule(
|
|
948
|
-
this.
|
|
1079
|
+
this.ctx,
|
|
949
1080
|
this.entDefinitions,
|
|
950
1081
|
this.table,
|
|
951
1082
|
docs,
|
|
@@ -955,14 +1086,14 @@ var PromiseEntsOrNullImpl = class extends Promise {
|
|
|
955
1086
|
then(onfulfilled, onrejected) {
|
|
956
1087
|
return this.docs().then(
|
|
957
1088
|
(docs) => docs === null ? null : docs.map(
|
|
958
|
-
(doc) => entWrapper(doc, this.
|
|
1089
|
+
(doc) => entWrapper(doc, this.ctx, this.entDefinitions, this.table)
|
|
959
1090
|
)
|
|
960
1091
|
).then(onfulfilled, onrejected);
|
|
961
1092
|
}
|
|
962
1093
|
};
|
|
963
1094
|
var PromiseEdgeOrNullImpl = class extends PromiseEntsOrNullImpl {
|
|
964
|
-
constructor(
|
|
965
|
-
super(
|
|
1095
|
+
constructor(ctx, entDefinitions, table, field, retrieveRange) {
|
|
1096
|
+
super(ctx, entDefinitions, table, () => retrieveRange((q) => q), false);
|
|
966
1097
|
this.field = field;
|
|
967
1098
|
this.retrieveRange = retrieveRange;
|
|
968
1099
|
}
|
|
@@ -972,10 +1103,10 @@ var PromiseEdgeOrNullImpl = class extends PromiseEntsOrNullImpl {
|
|
|
972
1103
|
}
|
|
973
1104
|
};
|
|
974
1105
|
var PromiseEntOrNullImpl = class _PromiseEntOrNullImpl extends Promise {
|
|
975
|
-
constructor(
|
|
1106
|
+
constructor(ctx, entDefinitions, table, retrieve, throwIfNull) {
|
|
976
1107
|
super(() => {
|
|
977
1108
|
});
|
|
978
|
-
this.
|
|
1109
|
+
this.ctx = ctx;
|
|
979
1110
|
this.entDefinitions = entDefinitions;
|
|
980
1111
|
this.table = table;
|
|
981
1112
|
this.retrieve = retrieve;
|
|
@@ -993,7 +1124,7 @@ var PromiseEntOrNullImpl = class _PromiseEntOrNullImpl extends Promise {
|
|
|
993
1124
|
const readPolicy = getReadRule(this.entDefinitions, this.table);
|
|
994
1125
|
if (readPolicy !== void 0) {
|
|
995
1126
|
const decision = await readPolicy(
|
|
996
|
-
entWrapper(doc, this.
|
|
1127
|
+
entWrapper(doc, this.ctx, this.entDefinitions, this.table)
|
|
997
1128
|
);
|
|
998
1129
|
if (this.throwIfNull && !decision) {
|
|
999
1130
|
throw new Error(
|
|
@@ -1006,7 +1137,7 @@ var PromiseEntOrNullImpl = class _PromiseEntOrNullImpl extends Promise {
|
|
|
1006
1137
|
}
|
|
1007
1138
|
then(onfulfilled, onrejected) {
|
|
1008
1139
|
return this.doc().then(
|
|
1009
|
-
(doc) => doc === null ? null : entWrapper(doc, this.
|
|
1140
|
+
(doc) => doc === null ? null : entWrapper(doc, this.ctx, this.entDefinitions, this.table)
|
|
1010
1141
|
).then(onfulfilled, onrejected);
|
|
1011
1142
|
}
|
|
1012
1143
|
edge(edge) {
|
|
@@ -1016,11 +1147,11 @@ var PromiseEntOrNullImpl = class _PromiseEntOrNullImpl extends Promise {
|
|
|
1016
1147
|
return this.edgeImpl(edge, true);
|
|
1017
1148
|
}
|
|
1018
1149
|
edgeImpl(edge, throwIfNull = false) {
|
|
1019
|
-
const edgeDefinition = this.entDefinitions
|
|
1150
|
+
const edgeDefinition = getEdgeDefinitions(this.entDefinitions, this.table)[edge];
|
|
1020
1151
|
if (edgeDefinition.cardinality === "multiple") {
|
|
1021
1152
|
if (edgeDefinition.type === "ref") {
|
|
1022
1153
|
return new PromiseEdgeOrNullImpl(
|
|
1023
|
-
this.
|
|
1154
|
+
this.ctx,
|
|
1024
1155
|
this.entDefinitions,
|
|
1025
1156
|
edgeDefinition.to,
|
|
1026
1157
|
edgeDefinition.ref,
|
|
@@ -1029,13 +1160,13 @@ var PromiseEntOrNullImpl = class _PromiseEntOrNullImpl extends Promise {
|
|
|
1029
1160
|
if (id === null) {
|
|
1030
1161
|
return null;
|
|
1031
1162
|
}
|
|
1032
|
-
const edgeDocs = await this.db.query(edgeDefinition.table).withIndex(
|
|
1163
|
+
const edgeDocs = await this.ctx.db.query(edgeDefinition.table).withIndex(
|
|
1033
1164
|
edgeDefinition.field,
|
|
1034
1165
|
(q) => indexRange(q.eq(edgeDefinition.field, id))
|
|
1035
1166
|
).collect();
|
|
1036
1167
|
return (await Promise.all(
|
|
1037
1168
|
edgeDocs.map(
|
|
1038
|
-
(edgeDoc) => this.db.get(edgeDoc[edgeDefinition.ref])
|
|
1169
|
+
(edgeDoc) => this.ctx.db.get(edgeDoc[edgeDefinition.ref])
|
|
1039
1170
|
)
|
|
1040
1171
|
)).filter((doc, i) => {
|
|
1041
1172
|
if (doc === null) {
|
|
@@ -1049,7 +1180,7 @@ var PromiseEntOrNullImpl = class _PromiseEntOrNullImpl extends Promise {
|
|
|
1049
1180
|
);
|
|
1050
1181
|
}
|
|
1051
1182
|
return new PromiseQueryOrNullImpl(
|
|
1052
|
-
this.
|
|
1183
|
+
this.ctx,
|
|
1053
1184
|
this.entDefinitions,
|
|
1054
1185
|
edgeDefinition.to,
|
|
1055
1186
|
async () => {
|
|
@@ -1057,7 +1188,7 @@ var PromiseEntOrNullImpl = class _PromiseEntOrNullImpl extends Promise {
|
|
|
1057
1188
|
if (id === null) {
|
|
1058
1189
|
return null;
|
|
1059
1190
|
}
|
|
1060
|
-
return this.db.query(edgeDefinition.to).withIndex(
|
|
1191
|
+
return this.ctx.db.query(edgeDefinition.to).withIndex(
|
|
1061
1192
|
edgeDefinition.ref,
|
|
1062
1193
|
(q) => q.eq(edgeDefinition.ref, id)
|
|
1063
1194
|
);
|
|
@@ -1065,7 +1196,7 @@ var PromiseEntOrNullImpl = class _PromiseEntOrNullImpl extends Promise {
|
|
|
1065
1196
|
);
|
|
1066
1197
|
}
|
|
1067
1198
|
return new _PromiseEntOrNullImpl(
|
|
1068
|
-
this.
|
|
1199
|
+
this.ctx,
|
|
1069
1200
|
this.entDefinitions,
|
|
1070
1201
|
edgeDefinition.to,
|
|
1071
1202
|
async () => {
|
|
@@ -1074,7 +1205,7 @@ var PromiseEntOrNullImpl = class _PromiseEntOrNullImpl extends Promise {
|
|
|
1074
1205
|
return nullRetriever;
|
|
1075
1206
|
}
|
|
1076
1207
|
if (edgeDefinition.type === "ref") {
|
|
1077
|
-
const otherDoc = await this.db.query(edgeDefinition.to).withIndex(
|
|
1208
|
+
const otherDoc = await this.ctx.db.query(edgeDefinition.to).withIndex(
|
|
1078
1209
|
edgeDefinition.ref,
|
|
1079
1210
|
(q) => q.eq(edgeDefinition.ref, id)
|
|
1080
1211
|
).unique();
|
|
@@ -1090,7 +1221,7 @@ var PromiseEntOrNullImpl = class _PromiseEntOrNullImpl extends Promise {
|
|
|
1090
1221
|
return {
|
|
1091
1222
|
id: otherId,
|
|
1092
1223
|
doc: async () => {
|
|
1093
|
-
const otherDoc = await this.db.get(otherId);
|
|
1224
|
+
const otherDoc = await this.ctx.db.get(otherId);
|
|
1094
1225
|
if (otherDoc === null) {
|
|
1095
1226
|
throw new Error(
|
|
1096
1227
|
`Dangling reference for edge "${edgeDefinition.name}" in table "${this.table}" for document with ID "${id}": Could not find a document with ID "${otherId}" in table "${edgeDefinition.to}".`
|
|
@@ -1104,10 +1235,27 @@ var PromiseEntOrNullImpl = class _PromiseEntOrNullImpl extends Promise {
|
|
|
1104
1235
|
);
|
|
1105
1236
|
}
|
|
1106
1237
|
};
|
|
1107
|
-
|
|
1238
|
+
var PromiseArrayImpl = class extends Promise {
|
|
1239
|
+
constructor(retrieve) {
|
|
1240
|
+
super(() => {
|
|
1241
|
+
});
|
|
1242
|
+
this.retrieve = retrieve;
|
|
1243
|
+
}
|
|
1244
|
+
async filter(predicate) {
|
|
1245
|
+
const array = await this.retrieve();
|
|
1246
|
+
if (array === null) {
|
|
1247
|
+
return null;
|
|
1248
|
+
}
|
|
1249
|
+
return array.filter(predicate);
|
|
1250
|
+
}
|
|
1251
|
+
then(onfulfilled, onrejected) {
|
|
1252
|
+
return this.retrieve().then(onfulfilled, onrejected);
|
|
1253
|
+
}
|
|
1254
|
+
};
|
|
1255
|
+
function entWrapper(fields, ctx, entDefinitions, table) {
|
|
1108
1256
|
const doc = { ...fields };
|
|
1109
1257
|
const queryInterface = new PromiseEntWriterImpl(
|
|
1110
|
-
|
|
1258
|
+
ctx,
|
|
1111
1259
|
entDefinitions,
|
|
1112
1260
|
table,
|
|
1113
1261
|
async () => ({ id: doc._id, doc: async () => doc }),
|
|
@@ -1130,6 +1278,14 @@ function entWrapper(fields, db, entDefinitions, table) {
|
|
|
1130
1278
|
writable: false,
|
|
1131
1279
|
configurable: false
|
|
1132
1280
|
});
|
|
1281
|
+
Object.defineProperty(doc, "doc", {
|
|
1282
|
+
value: () => {
|
|
1283
|
+
return doc;
|
|
1284
|
+
},
|
|
1285
|
+
enumerable: false,
|
|
1286
|
+
writable: false,
|
|
1287
|
+
configurable: false
|
|
1288
|
+
});
|
|
1133
1289
|
Object.defineProperty(doc, "patch", {
|
|
1134
1290
|
value: (value) => {
|
|
1135
1291
|
return queryInterface.patch(value);
|
|
@@ -1163,54 +1319,58 @@ function entWrapper(fields, db, entDefinitions, table) {
|
|
|
1163
1319
|
);
|
|
1164
1320
|
return doc;
|
|
1165
1321
|
}
|
|
1166
|
-
function entsTableFactory(
|
|
1322
|
+
function entsTableFactory(ctx, entDefinitions, options) {
|
|
1323
|
+
const enrichedCtx = options !== void 0 ? { ...ctx, ...options } : ctx;
|
|
1167
1324
|
return (table, indexName, indexRange) => {
|
|
1168
1325
|
if (typeof table !== "string") {
|
|
1169
1326
|
throw new Error(`Expected table name, got \`${table}\``);
|
|
1170
1327
|
}
|
|
1171
1328
|
if (indexName !== void 0) {
|
|
1172
|
-
return new PromiseTableImpl(
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1329
|
+
return new PromiseTableImpl(
|
|
1330
|
+
enrichedCtx,
|
|
1331
|
+
entDefinitions,
|
|
1332
|
+
table
|
|
1333
|
+
).withIndex(indexName, indexRange);
|
|
1176
1334
|
}
|
|
1177
|
-
if (db.insert !== void 0) {
|
|
1335
|
+
if (ctx.db.insert !== void 0) {
|
|
1178
1336
|
return new PromiseTableWriterImpl(
|
|
1179
|
-
|
|
1337
|
+
enrichedCtx,
|
|
1180
1338
|
entDefinitions,
|
|
1181
1339
|
table
|
|
1182
1340
|
);
|
|
1183
1341
|
}
|
|
1184
|
-
return new PromiseTableImpl(
|
|
1342
|
+
return new PromiseTableImpl(enrichedCtx, entDefinitions, table);
|
|
1185
1343
|
};
|
|
1186
1344
|
}
|
|
1187
1345
|
var PromiseTableWriterImpl = class extends PromiseTableImpl {
|
|
1188
|
-
constructor(
|
|
1189
|
-
super(
|
|
1190
|
-
this.
|
|
1191
|
-
this.base = new WriterImplBase(
|
|
1346
|
+
constructor(ctx, entDefinitions, table) {
|
|
1347
|
+
super(ctx, entDefinitions, table);
|
|
1348
|
+
this.ctx = ctx;
|
|
1349
|
+
this.base = new WriterImplBase(ctx, entDefinitions, table);
|
|
1192
1350
|
}
|
|
1193
1351
|
base;
|
|
1194
1352
|
insert(value) {
|
|
1195
1353
|
return new PromiseEntIdImpl(
|
|
1196
|
-
this.
|
|
1354
|
+
this.ctx,
|
|
1197
1355
|
this.entDefinitions,
|
|
1198
1356
|
this.table,
|
|
1199
1357
|
async () => {
|
|
1200
1358
|
await this.base.checkReadAndWriteRule("create", void 0, value);
|
|
1201
1359
|
await this.base.checkUniqueness(value);
|
|
1202
1360
|
const fields = this.base.fieldsOnly(value);
|
|
1203
|
-
const docId = await this.db.insert(this.table, fields);
|
|
1361
|
+
const docId = await this.ctx.db.insert(this.table, fields);
|
|
1204
1362
|
const edges = {};
|
|
1205
1363
|
Object.keys(value).forEach((key) => {
|
|
1206
|
-
const edgeDefinition =
|
|
1364
|
+
const edgeDefinition = getEdgeDefinitions(
|
|
1365
|
+
this.entDefinitions,
|
|
1366
|
+
this.table
|
|
1367
|
+
)[key];
|
|
1207
1368
|
if (edgeDefinition === void 0 || edgeDefinition.cardinality === "single" && edgeDefinition.type === "field") {
|
|
1208
1369
|
return;
|
|
1209
1370
|
}
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
}
|
|
1213
|
-
edges[key] = { add: value[key] };
|
|
1371
|
+
edges[key] = {
|
|
1372
|
+
add: edgeDefinition.cardinality === "single" ? [value[key]] : value[key]
|
|
1373
|
+
};
|
|
1214
1374
|
});
|
|
1215
1375
|
await this.base.writeEdges(docId, edges);
|
|
1216
1376
|
return docId;
|
|
@@ -1223,19 +1383,19 @@ var PromiseTableWriterImpl = class extends PromiseTableImpl {
|
|
|
1223
1383
|
}
|
|
1224
1384
|
};
|
|
1225
1385
|
var PromiseEntWriterImpl = class extends PromiseEntOrNullImpl {
|
|
1226
|
-
constructor(
|
|
1227
|
-
super(
|
|
1228
|
-
this.
|
|
1386
|
+
constructor(ctx, entDefinitions, table, retrieve, throwIfNull) {
|
|
1387
|
+
super(ctx, entDefinitions, table, retrieve, throwIfNull);
|
|
1388
|
+
this.ctx = ctx;
|
|
1229
1389
|
this.entDefinitions = entDefinitions;
|
|
1230
1390
|
this.table = table;
|
|
1231
1391
|
this.retrieve = retrieve;
|
|
1232
1392
|
this.throwIfNull = throwIfNull;
|
|
1233
|
-
this.base = new WriterImplBase(
|
|
1393
|
+
this.base = new WriterImplBase(ctx, entDefinitions, table);
|
|
1234
1394
|
}
|
|
1235
1395
|
base;
|
|
1236
1396
|
patch(value) {
|
|
1237
1397
|
return new PromiseEntIdImpl(
|
|
1238
|
-
this.
|
|
1398
|
+
this.ctx,
|
|
1239
1399
|
this.entDefinitions,
|
|
1240
1400
|
this.table,
|
|
1241
1401
|
async () => {
|
|
@@ -1244,18 +1404,52 @@ var PromiseEntWriterImpl = class extends PromiseEntOrNullImpl {
|
|
|
1244
1404
|
await this.base.checkReadAndWriteRule("update", id, value);
|
|
1245
1405
|
await this.base.checkUniqueness(value, id);
|
|
1246
1406
|
const fields = this.base.fieldsOnly(value);
|
|
1247
|
-
await this.db.patch(id, fields);
|
|
1407
|
+
await this.ctx.db.patch(id, fields);
|
|
1248
1408
|
const edges = {};
|
|
1249
1409
|
await Promise.all(
|
|
1250
1410
|
Object.keys(value).map(async (key) => {
|
|
1251
|
-
const edgeDefinition =
|
|
1411
|
+
const edgeDefinition = getEdgeDefinitions(
|
|
1412
|
+
this.entDefinitions,
|
|
1413
|
+
this.table
|
|
1414
|
+
)[key];
|
|
1252
1415
|
if (edgeDefinition === void 0 || edgeDefinition.cardinality === "single" && edgeDefinition.type === "field") {
|
|
1253
1416
|
return;
|
|
1254
1417
|
}
|
|
1255
1418
|
if (edgeDefinition.cardinality === "single") {
|
|
1256
|
-
throw new Error(
|
|
1419
|
+
throw new Error(
|
|
1420
|
+
`Cannot set 1:1 edge "${edgeDefinition.name}" on ent in table "${this.table}", update the ent in "${edgeDefinition.to}" table instead.`
|
|
1421
|
+
);
|
|
1257
1422
|
} else {
|
|
1258
|
-
|
|
1423
|
+
if (edgeDefinition.type === "field") {
|
|
1424
|
+
throw new Error(
|
|
1425
|
+
`Cannot set 1:many edges "${edgeDefinition.name}" on ent in table "${this.table}", update the ents in "${edgeDefinition.to}" table instead.`
|
|
1426
|
+
);
|
|
1427
|
+
} else {
|
|
1428
|
+
const { add, remove } = value[key];
|
|
1429
|
+
const removeEdges = (await Promise.all(
|
|
1430
|
+
(remove ?? []).map(
|
|
1431
|
+
async (edgeId) => (await this.ctx.db.query(edgeDefinition.table).withIndex(
|
|
1432
|
+
edgeDefinition.field,
|
|
1433
|
+
(q) => q.eq(edgeDefinition.field, id).eq(
|
|
1434
|
+
edgeDefinition.ref,
|
|
1435
|
+
edgeId
|
|
1436
|
+
)
|
|
1437
|
+
).collect()).concat(
|
|
1438
|
+
edgeDefinition.symmetric ? await this.ctx.db.query(edgeDefinition.table).withIndex(
|
|
1439
|
+
edgeDefinition.ref,
|
|
1440
|
+
(q) => q.eq(edgeDefinition.ref, id).eq(
|
|
1441
|
+
edgeDefinition.field,
|
|
1442
|
+
edgeId
|
|
1443
|
+
)
|
|
1444
|
+
).collect() : []
|
|
1445
|
+
)
|
|
1446
|
+
)
|
|
1447
|
+
)).map((edgeDoc) => edgeDoc._id);
|
|
1448
|
+
edges[key] = {
|
|
1449
|
+
add,
|
|
1450
|
+
removeEdges
|
|
1451
|
+
};
|
|
1452
|
+
}
|
|
1259
1453
|
}
|
|
1260
1454
|
})
|
|
1261
1455
|
);
|
|
@@ -1266,7 +1460,7 @@ var PromiseEntWriterImpl = class extends PromiseEntOrNullImpl {
|
|
|
1266
1460
|
}
|
|
1267
1461
|
replace(value) {
|
|
1268
1462
|
return new PromiseEntIdImpl(
|
|
1269
|
-
this.
|
|
1463
|
+
this.ctx,
|
|
1270
1464
|
this.entDefinitions,
|
|
1271
1465
|
this.table,
|
|
1272
1466
|
async () => {
|
|
@@ -1275,38 +1469,33 @@ var PromiseEntWriterImpl = class extends PromiseEntOrNullImpl {
|
|
|
1275
1469
|
await this.base.checkReadAndWriteRule("update", docId, value);
|
|
1276
1470
|
await this.base.checkUniqueness(value, docId);
|
|
1277
1471
|
const fields = this.base.fieldsOnly(value);
|
|
1278
|
-
await this.db.replace(docId, fields);
|
|
1472
|
+
await this.ctx.db.replace(docId, fields);
|
|
1279
1473
|
const edges = {};
|
|
1280
1474
|
await Promise.all(
|
|
1281
1475
|
Object.values(
|
|
1282
|
-
this.entDefinitions
|
|
1476
|
+
getEdgeDefinitions(this.entDefinitions, this.table)
|
|
1283
1477
|
).map(async (edgeDefinition) => {
|
|
1284
1478
|
const key = edgeDefinition.name;
|
|
1285
1479
|
const idOrIds = value[key];
|
|
1286
1480
|
if (edgeDefinition.cardinality === "single") {
|
|
1287
1481
|
if (edgeDefinition.type === "ref") {
|
|
1288
|
-
const oldDoc = await this.db.get(docId);
|
|
1482
|
+
const oldDoc = await this.ctx.db.get(docId);
|
|
1289
1483
|
if (oldDoc[key] !== void 0 && oldDoc[key] !== idOrIds) {
|
|
1290
1484
|
throw new Error("Cannot set 1:1 edge from optional end.");
|
|
1291
1485
|
}
|
|
1292
1486
|
}
|
|
1293
1487
|
} else {
|
|
1294
1488
|
if (edgeDefinition.type === "field") {
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
).collect()).map((doc) => doc._id);
|
|
1299
|
-
edges[key] = {
|
|
1300
|
-
add: idOrIds,
|
|
1301
|
-
remove: existing
|
|
1302
|
-
};
|
|
1489
|
+
if (idOrIds !== void 0) {
|
|
1490
|
+
throw new Error("Cannot set 1:many edge from many end.");
|
|
1491
|
+
}
|
|
1303
1492
|
} else {
|
|
1304
1493
|
const requested = new Set(idOrIds ?? []);
|
|
1305
|
-
const
|
|
1494
|
+
const removeEdges = (await this.ctx.db.query(edgeDefinition.table).withIndex(
|
|
1306
1495
|
edgeDefinition.field,
|
|
1307
1496
|
(q) => q.eq(edgeDefinition.field, docId)
|
|
1308
1497
|
).collect()).map((doc) => [doc._id, doc[edgeDefinition.ref]]).concat(
|
|
1309
|
-
edgeDefinition.symmetric ? (await this.db.query(edgeDefinition.table).withIndex(
|
|
1498
|
+
edgeDefinition.symmetric ? (await this.ctx.db.query(edgeDefinition.table).withIndex(
|
|
1310
1499
|
edgeDefinition.ref,
|
|
1311
1500
|
(q) => q.eq(edgeDefinition.ref, docId)
|
|
1312
1501
|
).collect()).map(
|
|
@@ -1320,8 +1509,8 @@ var PromiseEntWriterImpl = class extends PromiseEntOrNullImpl {
|
|
|
1320
1509
|
return true;
|
|
1321
1510
|
}).map(([edgeId]) => edgeId);
|
|
1322
1511
|
edges[key] = {
|
|
1323
|
-
add:
|
|
1324
|
-
removeEdges
|
|
1512
|
+
add: idOrIds ?? [],
|
|
1513
|
+
removeEdges
|
|
1325
1514
|
};
|
|
1326
1515
|
}
|
|
1327
1516
|
}
|
|
@@ -1335,70 +1524,26 @@ var PromiseEntWriterImpl = class extends PromiseEntOrNullImpl {
|
|
|
1335
1524
|
async delete() {
|
|
1336
1525
|
const { id: docId } = await this.retrieve();
|
|
1337
1526
|
const id = docId;
|
|
1338
|
-
|
|
1339
|
-
let memoized = void 0;
|
|
1340
|
-
const oldDoc = async () => {
|
|
1341
|
-
if (memoized !== void 0) {
|
|
1342
|
-
return memoized;
|
|
1343
|
-
}
|
|
1344
|
-
return memoized = await this.db.get(id);
|
|
1345
|
-
};
|
|
1346
|
-
const edges = {};
|
|
1347
|
-
await Promise.all(
|
|
1348
|
-
Object.values(
|
|
1349
|
-
this.entDefinitions[this.table].edges
|
|
1350
|
-
).map(async (edgeDefinition) => {
|
|
1351
|
-
const key = edgeDefinition.name;
|
|
1352
|
-
if (edgeDefinition.cardinality === "single") {
|
|
1353
|
-
if (edgeDefinition.type === "ref") {
|
|
1354
|
-
edges[key] = {
|
|
1355
|
-
remove: (await oldDoc())[key]
|
|
1356
|
-
};
|
|
1357
|
-
}
|
|
1358
|
-
} else {
|
|
1359
|
-
if (edgeDefinition.type === "field") {
|
|
1360
|
-
const existing = (await this.db.query(edgeDefinition.to).withIndex(
|
|
1361
|
-
edgeDefinition.ref,
|
|
1362
|
-
(q) => q.eq(edgeDefinition.ref, id)
|
|
1363
|
-
).collect()).map((doc) => doc._id);
|
|
1364
|
-
edges[key] = { remove: existing };
|
|
1365
|
-
} else {
|
|
1366
|
-
const existing = (await this.db.query(edgeDefinition.table).withIndex(
|
|
1367
|
-
edgeDefinition.field,
|
|
1368
|
-
(q) => q.eq(edgeDefinition.field, id)
|
|
1369
|
-
).collect()).concat(
|
|
1370
|
-
edgeDefinition.symmetric ? await this.db.query(edgeDefinition.table).withIndex(
|
|
1371
|
-
edgeDefinition.ref,
|
|
1372
|
-
(q) => q.eq(edgeDefinition.ref, id)
|
|
1373
|
-
).collect() : []
|
|
1374
|
-
).map((doc) => doc._id);
|
|
1375
|
-
edges[key] = { removeEdges: existing };
|
|
1376
|
-
}
|
|
1377
|
-
}
|
|
1378
|
-
})
|
|
1379
|
-
);
|
|
1380
|
-
await this.db.delete(id);
|
|
1381
|
-
await this.base.writeEdges(id, edges);
|
|
1382
|
-
return id;
|
|
1527
|
+
return this.base.deleteId(id, "default");
|
|
1383
1528
|
}
|
|
1384
1529
|
};
|
|
1385
1530
|
var PromiseEntIdImpl = class extends Promise {
|
|
1386
|
-
constructor(
|
|
1531
|
+
constructor(ctx, entDefinitions, table, retrieve) {
|
|
1387
1532
|
super(() => {
|
|
1388
1533
|
});
|
|
1389
|
-
this.
|
|
1534
|
+
this.ctx = ctx;
|
|
1390
1535
|
this.entDefinitions = entDefinitions;
|
|
1391
1536
|
this.table = table;
|
|
1392
1537
|
this.retrieve = retrieve;
|
|
1393
1538
|
}
|
|
1394
1539
|
get() {
|
|
1395
1540
|
return new PromiseEntOrNullImpl(
|
|
1396
|
-
this.
|
|
1541
|
+
this.ctx,
|
|
1397
1542
|
this.entDefinitions,
|
|
1398
1543
|
this.table,
|
|
1399
1544
|
async () => {
|
|
1400
1545
|
const id = await this.retrieve();
|
|
1401
|
-
return { id, doc: async () => this.db.get(id) };
|
|
1546
|
+
return { id, doc: async () => this.ctx.db.get(id) };
|
|
1402
1547
|
},
|
|
1403
1548
|
true
|
|
1404
1549
|
);
|
|
@@ -1420,28 +1565,28 @@ function loadedRetriever(doc) {
|
|
|
1420
1565
|
function addEntRules(entDefinitions, rules) {
|
|
1421
1566
|
return { ...entDefinitions, rules };
|
|
1422
1567
|
}
|
|
1423
|
-
async function filterByReadRule(
|
|
1568
|
+
async function filterByReadRule(ctx, entDefinitions, table, docs, throwIfNull) {
|
|
1424
1569
|
if (docs === null) {
|
|
1425
1570
|
return null;
|
|
1426
1571
|
}
|
|
1427
1572
|
const readPolicy = getReadRule(entDefinitions, table);
|
|
1428
|
-
if (readPolicy
|
|
1429
|
-
|
|
1430
|
-
docs.map(async (doc) => {
|
|
1431
|
-
const decision = await readPolicy(
|
|
1432
|
-
entWrapper(doc, db, entDefinitions, table)
|
|
1433
|
-
);
|
|
1434
|
-
if (throwIfNull && !decision) {
|
|
1435
|
-
throw new Error(
|
|
1436
|
-
`Document cannot be read with id \`${doc._id}\` in table "${table}"`
|
|
1437
|
-
);
|
|
1438
|
-
}
|
|
1439
|
-
return decision;
|
|
1440
|
-
})
|
|
1441
|
-
);
|
|
1442
|
-
return docs.filter((_, i) => decisions[i]);
|
|
1573
|
+
if (readPolicy === void 0) {
|
|
1574
|
+
return docs;
|
|
1443
1575
|
}
|
|
1444
|
-
|
|
1576
|
+
const decisions = await Promise.all(
|
|
1577
|
+
docs.map(async (doc) => {
|
|
1578
|
+
const decision = await readPolicy(
|
|
1579
|
+
entWrapper(doc, ctx, entDefinitions, table)
|
|
1580
|
+
);
|
|
1581
|
+
if (throwIfNull && !decision) {
|
|
1582
|
+
throw new Error(
|
|
1583
|
+
`Document cannot be read with id \`${doc._id}\` in table "${table}"`
|
|
1584
|
+
);
|
|
1585
|
+
}
|
|
1586
|
+
return decision;
|
|
1587
|
+
})
|
|
1588
|
+
);
|
|
1589
|
+
return docs.filter((_, i) => decisions[i]);
|
|
1445
1590
|
}
|
|
1446
1591
|
function getReadRule(entDefinitions, table) {
|
|
1447
1592
|
return entDefinitions.rules?.[table]?.read;
|
|
@@ -1449,12 +1594,201 @@ function getReadRule(entDefinitions, table) {
|
|
|
1449
1594
|
function getWriteRule(entDefinitions, table) {
|
|
1450
1595
|
return entDefinitions.rules?.[table]?.write;
|
|
1451
1596
|
}
|
|
1597
|
+
function getEdgeDefinitions(entDefinitions, table) {
|
|
1598
|
+
return entDefinitions[table].edges;
|
|
1599
|
+
}
|
|
1600
|
+
function getDeletionConfig(entDefinitions, table) {
|
|
1601
|
+
return entDefinitions[table].deletionConfig;
|
|
1602
|
+
}
|
|
1603
|
+
|
|
1604
|
+
// src/deletion.ts
|
|
1605
|
+
var import_server3 = require("convex/server");
|
|
1606
|
+
var import_values2 = require("convex/values");
|
|
1607
|
+
var vApproach = import_values2.v.union(
|
|
1608
|
+
import_values2.v.literal("schedule"),
|
|
1609
|
+
import_values2.v.literal("deleteOne"),
|
|
1610
|
+
import_values2.v.literal("paginate")
|
|
1611
|
+
);
|
|
1612
|
+
function scheduledDeleteFactory(entDefinitions, options) {
|
|
1613
|
+
const selfRef = options?.scheduledDelete ?? (0, import_server3.makeFunctionReference)(
|
|
1614
|
+
"functions:scheduledDelete"
|
|
1615
|
+
);
|
|
1616
|
+
return (0, import_server3.internalMutationGeneric)({
|
|
1617
|
+
args: {
|
|
1618
|
+
origin: import_values2.v.object({
|
|
1619
|
+
id: import_values2.v.string(),
|
|
1620
|
+
table: import_values2.v.string(),
|
|
1621
|
+
deletionTime: import_values2.v.number()
|
|
1622
|
+
}),
|
|
1623
|
+
stack: import_values2.v.array(
|
|
1624
|
+
import_values2.v.union(
|
|
1625
|
+
import_values2.v.object({
|
|
1626
|
+
id: import_values2.v.string(),
|
|
1627
|
+
table: import_values2.v.string(),
|
|
1628
|
+
edges: import_values2.v.array(
|
|
1629
|
+
import_values2.v.object({
|
|
1630
|
+
approach: vApproach,
|
|
1631
|
+
table: import_values2.v.string(),
|
|
1632
|
+
indexName: import_values2.v.string()
|
|
1633
|
+
})
|
|
1634
|
+
)
|
|
1635
|
+
}),
|
|
1636
|
+
import_values2.v.object({
|
|
1637
|
+
approach: vApproach,
|
|
1638
|
+
cursor: import_values2.v.union(import_values2.v.string(), import_values2.v.null()),
|
|
1639
|
+
table: import_values2.v.string(),
|
|
1640
|
+
indexName: import_values2.v.string(),
|
|
1641
|
+
fieldValue: import_values2.v.any()
|
|
1642
|
+
})
|
|
1643
|
+
)
|
|
1644
|
+
),
|
|
1645
|
+
inProgress: import_values2.v.boolean()
|
|
1646
|
+
},
|
|
1647
|
+
handler: async (ctx, { origin, stack, inProgress }) => {
|
|
1648
|
+
const originId = ctx.db.normalizeId(origin.table, origin.id);
|
|
1649
|
+
if (originId === null) {
|
|
1650
|
+
throw new Error(`Invalid ID "${origin.id}" for table ${origin.table}`);
|
|
1651
|
+
}
|
|
1652
|
+
const doc = await ctx.db.get(originId);
|
|
1653
|
+
if (doc.deletionTime !== origin.deletionTime) {
|
|
1654
|
+
if (inProgress) {
|
|
1655
|
+
console.error(
|
|
1656
|
+
`[Ents] Already in-progress scheduled deletion for "${origin.id}" was cancelled!`
|
|
1657
|
+
);
|
|
1658
|
+
} else {
|
|
1659
|
+
console.log(
|
|
1660
|
+
`[Ents] Scheduled deletion for "${origin.id}" was cancelled`
|
|
1661
|
+
);
|
|
1662
|
+
}
|
|
1663
|
+
return;
|
|
1664
|
+
}
|
|
1665
|
+
await progressScheduledDeletion(
|
|
1666
|
+
ctx,
|
|
1667
|
+
entDefinitions,
|
|
1668
|
+
selfRef,
|
|
1669
|
+
origin,
|
|
1670
|
+
inProgress ? stack : [
|
|
1671
|
+
{
|
|
1672
|
+
id: originId,
|
|
1673
|
+
table: origin.table,
|
|
1674
|
+
edges: getEdgeArgs(entDefinitions, origin.table)
|
|
1675
|
+
}
|
|
1676
|
+
]
|
|
1677
|
+
);
|
|
1678
|
+
}
|
|
1679
|
+
});
|
|
1680
|
+
}
|
|
1681
|
+
function getEdgeArgs(entDefinitions, table) {
|
|
1682
|
+
const edges = getEdgeDefinitions(entDefinitions, table);
|
|
1683
|
+
return Object.values(edges).flatMap((edgeDefinition) => {
|
|
1684
|
+
if (edgeDefinition.cardinality === "single" && edgeDefinition.type === "ref" || edgeDefinition.cardinality === "multiple" && edgeDefinition.type === "field") {
|
|
1685
|
+
const table2 = edgeDefinition.to;
|
|
1686
|
+
const targetDeletionConfig = getDeletionConfig(entDefinitions, table2);
|
|
1687
|
+
const targetEdges = getEdgeDefinitions(entDefinitions, table2);
|
|
1688
|
+
const hasCascadingEdges = Object.values(targetEdges).some(
|
|
1689
|
+
(edgeDefinition2) => edgeDefinition2.cardinality === "single" && edgeDefinition2.type === "ref" || edgeDefinition2.cardinality === "multiple"
|
|
1690
|
+
);
|
|
1691
|
+
const approach = targetDeletionConfig !== void 0 && hasCascadingEdges ? "schedule" : hasCascadingEdges ? "deleteOne" : "paginate";
|
|
1692
|
+
const indexName = edgeDefinition.ref;
|
|
1693
|
+
return [{ table: table2, indexName, approach }];
|
|
1694
|
+
} else if (edgeDefinition.cardinality === "multiple") {
|
|
1695
|
+
const table2 = edgeDefinition.table;
|
|
1696
|
+
return [
|
|
1697
|
+
{
|
|
1698
|
+
table: table2,
|
|
1699
|
+
indexName: edgeDefinition.field,
|
|
1700
|
+
approach: "paginate"
|
|
1701
|
+
},
|
|
1702
|
+
...edgeDefinition.symmetric ? [
|
|
1703
|
+
{
|
|
1704
|
+
table: table2,
|
|
1705
|
+
indexName: edgeDefinition.ref,
|
|
1706
|
+
approach: "paginate"
|
|
1707
|
+
}
|
|
1708
|
+
] : []
|
|
1709
|
+
];
|
|
1710
|
+
} else {
|
|
1711
|
+
return [];
|
|
1712
|
+
}
|
|
1713
|
+
});
|
|
1714
|
+
}
|
|
1715
|
+
async function progressScheduledDeletion(ctx, entDefinitions, selfRef, origin, stack) {
|
|
1716
|
+
const last = stack[stack.length - 1];
|
|
1717
|
+
if ("id" in last) {
|
|
1718
|
+
const edgeArgs = last.edges[0];
|
|
1719
|
+
if (edgeArgs === void 0) {
|
|
1720
|
+
await ctx.db.delete(last.id);
|
|
1721
|
+
if (stack.length > 1) {
|
|
1722
|
+
await ctx.scheduler.runAfter(0, selfRef, {
|
|
1723
|
+
origin,
|
|
1724
|
+
stack: stack.slice(0, -1),
|
|
1725
|
+
inProgress: true
|
|
1726
|
+
});
|
|
1727
|
+
}
|
|
1728
|
+
} else {
|
|
1729
|
+
const updated = { ...last, edges: last.edges.slice(1) };
|
|
1730
|
+
await paginate(
|
|
1731
|
+
ctx,
|
|
1732
|
+
entDefinitions,
|
|
1733
|
+
selfRef,
|
|
1734
|
+
origin,
|
|
1735
|
+
stack.slice(0, -1).concat(updated),
|
|
1736
|
+
{ cursor: null, fieldValue: last.id, ...edgeArgs }
|
|
1737
|
+
);
|
|
1738
|
+
}
|
|
1739
|
+
} else {
|
|
1740
|
+
await paginate(ctx, entDefinitions, selfRef, origin, stack, last);
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
async function paginate(ctx, entDefinitions, selfRef, origin, stack, { table, approach, indexName, fieldValue, cursor }) {
|
|
1744
|
+
const { page, continueCursor, isDone } = await ctx.db.query(table).withIndex(indexName, (q) => q.eq(indexName, fieldValue)).paginate({
|
|
1745
|
+
cursor,
|
|
1746
|
+
...approach === "paginate" ? { numItems: 8192 / 4, maximumBytesRead: 2 ** 18 } : { numItems: 1 }
|
|
1747
|
+
});
|
|
1748
|
+
const updated = {
|
|
1749
|
+
approach,
|
|
1750
|
+
table,
|
|
1751
|
+
cursor: continueCursor,
|
|
1752
|
+
indexName,
|
|
1753
|
+
fieldValue
|
|
1754
|
+
};
|
|
1755
|
+
const relevantStack = cursor === null ? stack : stack.slice(0, -1);
|
|
1756
|
+
if (approach === "schedule") {
|
|
1757
|
+
await ctx.scheduler.runAfter(0, selfRef, {
|
|
1758
|
+
origin,
|
|
1759
|
+
stack: isDone ? relevantStack : relevantStack.concat([
|
|
1760
|
+
updated,
|
|
1761
|
+
{
|
|
1762
|
+
id: page[0]._id,
|
|
1763
|
+
table,
|
|
1764
|
+
edges: getEdgeArgs(entDefinitions, table)
|
|
1765
|
+
}
|
|
1766
|
+
]),
|
|
1767
|
+
inProgress: true
|
|
1768
|
+
});
|
|
1769
|
+
} else {
|
|
1770
|
+
if (approach === "deleteOne") {
|
|
1771
|
+
await new WriterImplBase(ctx, entDefinitions, origin.table).deleteId(
|
|
1772
|
+
page[0].id,
|
|
1773
|
+
"hard"
|
|
1774
|
+
);
|
|
1775
|
+
} else {
|
|
1776
|
+
await Promise.all(page.map((doc) => ctx.db.delete(doc._id)));
|
|
1777
|
+
}
|
|
1778
|
+
await ctx.scheduler.runAfter(0, selfRef, {
|
|
1779
|
+
origin,
|
|
1780
|
+
stack: isDone ? relevantStack : relevantStack.concat([updated]),
|
|
1781
|
+
inProgress: true
|
|
1782
|
+
});
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1452
1785
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1453
1786
|
0 && (module.exports = {
|
|
1454
1787
|
addEntRules,
|
|
1455
1788
|
defineEnt,
|
|
1456
1789
|
defineEntSchema,
|
|
1457
1790
|
entsTableFactory,
|
|
1458
|
-
getEntDefinitions
|
|
1791
|
+
getEntDefinitions,
|
|
1792
|
+
scheduledDeleteFactory
|
|
1459
1793
|
});
|
|
1460
1794
|
//# sourceMappingURL=index.js.map
|