@snowtop/ent 0.1.0-alpha99 → 0.1.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.
Files changed (115) hide show
  1. package/action/action.d.ts +8 -1
  2. package/action/executor.d.ts +16 -3
  3. package/action/executor.js +83 -27
  4. package/action/index.d.ts +2 -1
  5. package/action/operations.d.ts +126 -0
  6. package/action/operations.js +686 -0
  7. package/action/orchestrator.d.ts +22 -8
  8. package/action/orchestrator.js +278 -67
  9. package/core/base.d.ts +34 -24
  10. package/core/clause.d.ts +62 -79
  11. package/core/clause.js +77 -5
  12. package/core/config.d.ts +5 -1
  13. package/core/config.js +3 -0
  14. package/core/const.d.ts +3 -0
  15. package/core/const.js +6 -0
  16. package/core/context.d.ts +4 -3
  17. package/core/context.js +2 -1
  18. package/core/db.d.ts +1 -0
  19. package/core/db.js +7 -7
  20. package/core/ent.d.ts +53 -105
  21. package/core/ent.js +104 -599
  22. package/core/global_schema.d.ts +7 -0
  23. package/core/global_schema.js +51 -0
  24. package/core/loaders/assoc_count_loader.d.ts +4 -2
  25. package/core/loaders/assoc_count_loader.js +10 -2
  26. package/core/loaders/assoc_edge_loader.d.ts +2 -3
  27. package/core/loaders/assoc_edge_loader.js +16 -7
  28. package/core/loaders/index.d.ts +0 -1
  29. package/core/loaders/index.js +1 -3
  30. package/core/loaders/loader.d.ts +3 -3
  31. package/core/loaders/loader.js +3 -20
  32. package/core/loaders/object_loader.d.ts +30 -10
  33. package/core/loaders/object_loader.js +179 -40
  34. package/core/loaders/query_loader.d.ts +4 -4
  35. package/core/loaders/query_loader.js +14 -19
  36. package/core/loaders/raw_count_loader.d.ts +1 -0
  37. package/core/loaders/raw_count_loader.js +3 -2
  38. package/core/privacy.d.ts +19 -10
  39. package/core/privacy.js +47 -26
  40. package/core/query/assoc_query.js +1 -1
  41. package/core/query/custom_clause_query.d.ts +6 -3
  42. package/core/query/custom_clause_query.js +36 -9
  43. package/core/query/custom_query.d.ts +3 -1
  44. package/core/query/custom_query.js +29 -6
  45. package/core/query/query.d.ts +12 -2
  46. package/core/query/query.js +67 -38
  47. package/core/query/shared_assoc_test.js +151 -10
  48. package/core/query/shared_test.d.ts +2 -2
  49. package/core/query/shared_test.js +90 -30
  50. package/core/query_impl.d.ts +8 -0
  51. package/core/query_impl.js +28 -0
  52. package/core/viewer.d.ts +2 -0
  53. package/core/viewer.js +2 -0
  54. package/graphql/graphql.d.ts +103 -19
  55. package/graphql/graphql.js +169 -134
  56. package/graphql/graphql_field_helpers.d.ts +9 -3
  57. package/graphql/graphql_field_helpers.js +22 -2
  58. package/graphql/index.d.ts +2 -1
  59. package/graphql/index.js +5 -2
  60. package/graphql/scalars/orderby_direction.d.ts +2 -0
  61. package/graphql/scalars/orderby_direction.js +15 -0
  62. package/imports/dataz/example1/_auth.js +128 -47
  63. package/imports/dataz/example1/_viewer.js +87 -39
  64. package/imports/index.d.ts +1 -1
  65. package/imports/index.js +2 -2
  66. package/index.d.ts +12 -1
  67. package/index.js +18 -6
  68. package/package.json +20 -17
  69. package/parse_schema/parse.d.ts +10 -4
  70. package/parse_schema/parse.js +70 -24
  71. package/schema/base_schema.d.ts +8 -0
  72. package/schema/base_schema.js +11 -0
  73. package/schema/field.d.ts +6 -3
  74. package/schema/field.js +72 -17
  75. package/schema/index.d.ts +1 -1
  76. package/schema/index.js +2 -1
  77. package/schema/json_field.d.ts +3 -3
  78. package/schema/json_field.js +4 -1
  79. package/schema/schema.d.ts +42 -5
  80. package/schema/schema.js +35 -41
  81. package/schema/struct_field.d.ts +8 -6
  82. package/schema/struct_field.js +67 -8
  83. package/schema/union_field.d.ts +1 -1
  84. package/scripts/custom_compiler.js +4 -4
  85. package/scripts/custom_graphql.js +105 -75
  86. package/scripts/move_types.js +4 -1
  87. package/scripts/read_schema.js +2 -2
  88. package/testutils/action/complex_schemas.d.ts +1 -1
  89. package/testutils/action/complex_schemas.js +10 -3
  90. package/testutils/builder.d.ts +3 -0
  91. package/testutils/builder.js +6 -0
  92. package/testutils/db/temp_db.d.ts +9 -1
  93. package/testutils/db/temp_db.js +82 -14
  94. package/testutils/db_mock.js +1 -3
  95. package/testutils/ent-graphql-tests/index.d.ts +1 -1
  96. package/testutils/ent-graphql-tests/index.js +30 -19
  97. package/testutils/fake_comms.js +1 -1
  98. package/testutils/fake_data/fake_contact.d.ts +1 -1
  99. package/testutils/fake_data/fake_tag.d.ts +1 -1
  100. package/testutils/fake_data/fake_user.d.ts +3 -3
  101. package/testutils/fake_data/fake_user.js +15 -4
  102. package/testutils/fake_data/tag_query.js +8 -3
  103. package/testutils/fake_data/test_helpers.d.ts +3 -2
  104. package/testutils/fake_data/test_helpers.js +4 -4
  105. package/testutils/fake_data/user_query.d.ts +5 -2
  106. package/testutils/fake_data/user_query.js +19 -2
  107. package/testutils/fake_log.js +1 -1
  108. package/tsc/ast.js +2 -1
  109. package/tsc/move_generated.js +2 -2
  110. package/tsc/transform.d.ts +2 -2
  111. package/tsc/transform.js +4 -3
  112. package/tsc/transform_ent.js +2 -1
  113. package/tsc/transform_schema.js +4 -3
  114. package/core/loaders/index_loader.d.ts +0 -14
  115. package/core/loaders/index_loader.js +0 -27
@@ -0,0 +1,686 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.ConditionalNodeOperation = exports.ConditionalOperation = exports.EdgeOperation = exports.EditNodeOperation = exports.RawQueryOperation = exports.DeleteNodeOperation = void 0;
27
+ const clause = __importStar(require("../core/clause"));
28
+ const action_1 = require("../action");
29
+ const schema_1 = require("../schema/schema");
30
+ const global_schema_1 = require("../core/global_schema");
31
+ const ent_1 = require("../core/ent");
32
+ class DeleteNodeOperation {
33
+ constructor(id, builder, options) {
34
+ this.id = id;
35
+ this.builder = builder;
36
+ this.options = options;
37
+ }
38
+ async performWrite(queryer, context) {
39
+ let options = {
40
+ ...this.options,
41
+ context,
42
+ };
43
+ return (0, ent_1.deleteRows)(queryer, options, clause.Eq("id", this.id));
44
+ }
45
+ performWriteSync(queryer, context) {
46
+ let options = {
47
+ ...this.options,
48
+ context,
49
+ };
50
+ return (0, ent_1.deleteRowsSync)(queryer, options, clause.Eq("id", this.id));
51
+ }
52
+ }
53
+ exports.DeleteNodeOperation = DeleteNodeOperation;
54
+ class RawQueryOperation {
55
+ constructor(builder, queries) {
56
+ this.builder = builder;
57
+ this.queries = queries;
58
+ }
59
+ async performWrite(queryer, context) {
60
+ for (const q of this.queries) {
61
+ if (typeof q === "string") {
62
+ (0, ent_1.logQuery)(q, []);
63
+ await queryer.query(q);
64
+ }
65
+ else {
66
+ (0, ent_1.logQuery)(q.query, q.logValues || []);
67
+ await queryer.query(q.query, q.values);
68
+ }
69
+ }
70
+ }
71
+ performWriteSync(queryer, context) {
72
+ for (const q of this.queries) {
73
+ if (typeof q === "string") {
74
+ (0, ent_1.logQuery)(q, []);
75
+ queryer.execSync(q);
76
+ }
77
+ else {
78
+ (0, ent_1.logQuery)(q.query, q.logValues || []);
79
+ queryer.execSync(q.query, q.values);
80
+ }
81
+ }
82
+ }
83
+ }
84
+ exports.RawQueryOperation = RawQueryOperation;
85
+ class EditNodeOperation {
86
+ constructor(options, existingEnt = null) {
87
+ this.options = options;
88
+ this.existingEnt = existingEnt;
89
+ this.row = null;
90
+ this.updatedOp = null;
91
+ this.resolved = false;
92
+ this.builder = options.builder;
93
+ this.placeholderID = options.builder.placeholderID;
94
+ }
95
+ resolve(executor) {
96
+ if (!this.options.fieldsToResolve.length) {
97
+ return;
98
+ }
99
+ if (this.resolved) {
100
+ throw new Error(`already resolved ${this.placeholderID}`);
101
+ }
102
+ let fields = this.options.fields;
103
+ this.options.fieldsToResolve.forEach((fieldName) => {
104
+ let value = fields[fieldName];
105
+ if (!value) {
106
+ throw new Error(`trying to resolve field ${fieldName} but not a valid field`);
107
+ }
108
+ let ent = executor.resolveValue(value.placeholderID);
109
+ if (!ent) {
110
+ throw new Error(`couldn't resolve field \`${fieldName}\` with value ${value.placeholderID}`);
111
+ }
112
+ fields[fieldName] = ent.id;
113
+ });
114
+ this.options.fields = fields;
115
+ this.resolved = true;
116
+ }
117
+ hasData(data) {
118
+ for (const _k in data) {
119
+ return true;
120
+ }
121
+ return false;
122
+ }
123
+ buildOnConflictQuery(options) {
124
+ // assumes onConflict has been checked already...
125
+ const clauses = [];
126
+ for (const col of this.options.onConflict.onConflictCols) {
127
+ clauses.push(clause.Eq(col, options.fields[col]));
128
+ }
129
+ const cls = clause.AndOptional(...clauses);
130
+ const query = this.buildReloadQuery(options, cls);
131
+ return { cls, query };
132
+ }
133
+ async performWrite(queryer, context) {
134
+ let options = {
135
+ ...this.options,
136
+ context,
137
+ };
138
+ if (this.existingEnt) {
139
+ if (this.hasData(options.fields)) {
140
+ // even this with returning * may not always work if transformed...
141
+ // we can have a transformed flag to see if it should be returned?
142
+ this.row = await (0, ent_1.editRow)(queryer, options, "RETURNING *");
143
+ }
144
+ else {
145
+ // @ts-ignore
146
+ this.row = this.existingEnt["data"];
147
+ }
148
+ }
149
+ else {
150
+ // TODO: eventually, when we officially support auto-increment ids. need to make sure/test that this works
151
+ // https://github.com/lolopinto/ent/issues/1431
152
+ this.row = await (0, ent_1.createRow)(queryer, options, "RETURNING *");
153
+ const key = this.options.key;
154
+ if (this.row && this.row[key] !== this.options.fields[key]) {
155
+ this.updatedOp = {
156
+ builder: this.options.builder,
157
+ operation: action_1.WriteOperation.Edit,
158
+ };
159
+ }
160
+ if (this.row === null &&
161
+ this.options.onConflict &&
162
+ !this.options.onConflict.updateCols?.length) {
163
+ // no row returned and on conflict, do nothing, have to fetch the conflict row back...
164
+ const { cls, query } = this.buildOnConflictQuery(options);
165
+ (0, ent_1.logQuery)(query, cls.logValues());
166
+ const res = await queryer.query(query, cls.values());
167
+ this.row = res.rows[0];
168
+ this.updatedOp = {
169
+ builder: this.options.builder,
170
+ operation: action_1.WriteOperation.Edit,
171
+ };
172
+ }
173
+ }
174
+ }
175
+ buildReloadQuery(options, cls) {
176
+ // TODO this isn't always an ObjectLoader. should throw or figure out a way to get query
177
+ // and run this on its own...
178
+ const loader = this.options.loadEntOptions.loaderFactory.createLoader(options.context);
179
+ const opts = loader.getOptions();
180
+ if (opts.clause) {
181
+ let optionClause;
182
+ if (typeof opts.clause === "function") {
183
+ optionClause = opts.clause();
184
+ }
185
+ else {
186
+ optionClause = opts.clause;
187
+ }
188
+ if (optionClause) {
189
+ cls = clause.And(cls, optionClause);
190
+ }
191
+ }
192
+ const query = (0, ent_1.buildQuery)({
193
+ fields: opts.fields.length ? opts.fields : ["*"],
194
+ tableName: options.tableName,
195
+ clause: cls,
196
+ });
197
+ return query;
198
+ }
199
+ reloadRow(queryer, id, options) {
200
+ const query = this.buildReloadQuery(options, clause.Eq(options.key, id));
201
+ // special case log here because we're not going through any of the normal
202
+ // methods here because those are async and this is sync
203
+ // this is the only place we're doing this so only handling here
204
+ (0, ent_1.logQuery)(query, [id]);
205
+ const r = queryer.querySync(query, [id]);
206
+ if (r.rows.length === 1) {
207
+ this.row = r.rows[0];
208
+ }
209
+ }
210
+ performWriteSync(queryer, context) {
211
+ let options = {
212
+ ...this.options,
213
+ context,
214
+ };
215
+ if (this.existingEnt) {
216
+ if (this.hasData(this.options.fields)) {
217
+ (0, ent_1.editRowSync)(queryer, options, "RETURNING *");
218
+ this.reloadRow(queryer, this.existingEnt.id, options);
219
+ }
220
+ else {
221
+ // @ts-ignore
222
+ this.row = this.existingEnt["data"];
223
+ }
224
+ }
225
+ else {
226
+ (0, ent_1.createRowSync)(queryer, options, "RETURNING *");
227
+ const id = options.fields[options.key];
228
+ this.reloadRow(queryer, id, options);
229
+ const key = this.options.key;
230
+ if (this.row && this.row[key] !== this.options.fields[key]) {
231
+ this.updatedOp = {
232
+ builder: this.options.builder,
233
+ operation: action_1.WriteOperation.Edit,
234
+ };
235
+ }
236
+ // if we can't find the id, try and load the on conflict row
237
+ // no returning * with sqlite and have to assume the row was created more often than not
238
+ // there's a world in which we combine into one query if on-conflict
239
+ // seems like it's safer not to and sqlite (only sync client we currently have) is fast enough
240
+ // (single-process) that it's fine to do two queries
241
+ // we wanna do this in both on conflict do nothing or on conflict update
242
+ if (this.row === null && this.options.onConflict) {
243
+ const { cls, query } = this.buildOnConflictQuery(options);
244
+ // special case log here because we're not going through any of the normal
245
+ // methods here because those are async and this is sync
246
+ // this is the only place we're doing this so only handling here
247
+ (0, ent_1.logQuery)(query, cls.logValues());
248
+ const r = queryer.querySync(query, cls.values());
249
+ if (r.rows.length === 1) {
250
+ this.row = r.rows[0];
251
+ }
252
+ this.updatedOp = {
253
+ builder: this.options.builder,
254
+ operation: action_1.WriteOperation.Edit,
255
+ };
256
+ }
257
+ }
258
+ }
259
+ returnedRow() {
260
+ return this.row;
261
+ }
262
+ createdEnt(viewer) {
263
+ if (!this.row) {
264
+ return null;
265
+ }
266
+ return new this.options.loadEntOptions.ent(viewer, this.row);
267
+ }
268
+ updatedOperation() {
269
+ return this.updatedOp;
270
+ }
271
+ }
272
+ exports.EditNodeOperation = EditNodeOperation;
273
+ class EdgeOperation {
274
+ constructor(builder, edgeInput, options) {
275
+ this.builder = builder;
276
+ this.edgeInput = edgeInput;
277
+ this.options = options;
278
+ }
279
+ async preFetch(queryer, context) {
280
+ let edgeData = await (0, ent_1.loadEdgeData)(this.edgeInput.edgeType);
281
+ if (!edgeData) {
282
+ throw new Error(`error loading edge data for ${this.edgeInput.edgeType}`);
283
+ }
284
+ this.edgeData = edgeData;
285
+ }
286
+ async performWrite(queryer, context) {
287
+ if (!this.edgeData) {
288
+ throw new Error(`error fetching edgeData for type ${this.edgeInput.edgeType}`);
289
+ }
290
+ switch (this.options.operation) {
291
+ case action_1.WriteOperation.Delete:
292
+ return this.performDeleteWrite(queryer, this.edgeData, this.edgeInput, context);
293
+ case action_1.WriteOperation.Insert:
294
+ case action_1.WriteOperation.Edit:
295
+ return this.performInsertWrite(queryer, this.edgeData, this.edgeInput, context);
296
+ }
297
+ }
298
+ performWriteSync(queryer, context) {
299
+ if (!this.edgeData) {
300
+ throw new Error(`error fetching edgeData for type ${this.edgeInput.edgeType}`);
301
+ }
302
+ switch (this.options.operation) {
303
+ case action_1.WriteOperation.Delete:
304
+ return this.performDeleteWriteSync(queryer, this.edgeData, this.edgeInput, context);
305
+ case action_1.WriteOperation.Insert:
306
+ case action_1.WriteOperation.Edit:
307
+ return this.performInsertWriteSync(queryer, this.edgeData, this.edgeInput, context);
308
+ }
309
+ }
310
+ getDeleteRowParams(edgeData, edge, context) {
311
+ let transformed = null;
312
+ let op = schema_1.SQLStatementOperation.Delete;
313
+ let updateData = null;
314
+ const transformedEdgeWrite = (0, global_schema_1.__getGlobalSchema)()?.transformEdgeWrite;
315
+ if (transformedEdgeWrite && !edge.disableTransformations) {
316
+ transformed = transformedEdgeWrite({
317
+ op: schema_1.SQLStatementOperation.Delete,
318
+ edge,
319
+ });
320
+ if (transformed) {
321
+ op = transformed.op;
322
+ if (transformed.op === schema_1.SQLStatementOperation.Insert) {
323
+ throw new Error(`cannot currently transform a delete into an insert`);
324
+ }
325
+ if (transformed.op === schema_1.SQLStatementOperation.Update) {
326
+ if (!transformed.data) {
327
+ throw new Error(`cannot transform a delete into an update without providing data`);
328
+ }
329
+ updateData = transformed.data;
330
+ }
331
+ }
332
+ }
333
+ return {
334
+ op,
335
+ updateData,
336
+ options: {
337
+ tableName: edgeData.edgeTable,
338
+ context,
339
+ },
340
+ clause: clause.And(clause.Eq("id1", edge.id1), clause.Eq("id2", edge.id2), clause.Eq("edge_type", edge.edgeType)),
341
+ };
342
+ }
343
+ async performDeleteWrite(q, edgeData, edge, context) {
344
+ const params = this.getDeleteRowParams(edgeData, edge, context);
345
+ if (params.op === schema_1.SQLStatementOperation.Delete) {
346
+ return (0, ent_1.deleteRows)(q, params.options, params.clause);
347
+ }
348
+ else {
349
+ if (params.op !== schema_1.SQLStatementOperation.Update) {
350
+ throw new Error(`invalid operation ${params.op}`);
351
+ }
352
+ await (0, ent_1.editRow)(q, {
353
+ tableName: params.options.tableName,
354
+ whereClause: params.clause,
355
+ fields: params.updateData,
356
+ fieldsToLog: params.updateData,
357
+ });
358
+ }
359
+ }
360
+ performDeleteWriteSync(q, edgeData, edge, context) {
361
+ const params = this.getDeleteRowParams(edgeData, edge, context);
362
+ if (params.op === schema_1.SQLStatementOperation.Delete) {
363
+ return (0, ent_1.deleteRowsSync)(q, params.options, params.clause);
364
+ }
365
+ else {
366
+ if (params.op !== schema_1.SQLStatementOperation.Update) {
367
+ throw new Error(`invalid operation ${params.op}`);
368
+ }
369
+ (0, ent_1.editRowSync)(q, {
370
+ tableName: params.options.tableName,
371
+ whereClause: params.clause,
372
+ fields: params.updateData,
373
+ });
374
+ }
375
+ }
376
+ getInsertRowParams(edgeData, edge, context) {
377
+ const fields = {
378
+ id1: edge.id1,
379
+ id2: edge.id2,
380
+ id1_type: edge.id1Type,
381
+ id2_type: edge.id2Type,
382
+ edge_type: edge.edgeType,
383
+ data: edge.data || null,
384
+ };
385
+ if (edge.time) {
386
+ fields["time"] = edge.time.toISOString();
387
+ }
388
+ else {
389
+ // todo make this a schema field like what we do in generated base files...
390
+ // maybe when actions exist?
391
+ fields["time"] = new Date().toISOString();
392
+ }
393
+ const onConflictFields = ["data"];
394
+ const extraEdgeFields = (0, global_schema_1.__getGlobalSchema)()?.extraEdgeFields;
395
+ if (extraEdgeFields) {
396
+ for (const name in extraEdgeFields) {
397
+ const f = extraEdgeFields[name];
398
+ if (f.defaultValueOnCreate) {
399
+ const storageKey = (0, schema_1.getStorageKey)(f, name);
400
+ fields[storageKey] = f.defaultValueOnCreate(this.builder, {});
401
+ // onconflict make sure we override the default values
402
+ // e.g. setting deleted_at = null for soft delete
403
+ onConflictFields.push(storageKey);
404
+ }
405
+ }
406
+ }
407
+ let transformed = null;
408
+ const transformEdgeWrite = (0, global_schema_1.__getGlobalSchema)()?.transformEdgeWrite;
409
+ if (transformEdgeWrite && !edge.disableTransformations) {
410
+ transformed = transformEdgeWrite({
411
+ op: schema_1.SQLStatementOperation.Insert,
412
+ edge,
413
+ });
414
+ if (transformed) {
415
+ throw new Error(`transforming an insert edge not currently supported`);
416
+ }
417
+ }
418
+ return [
419
+ {
420
+ tableName: edgeData.edgeTable,
421
+ fields: fields,
422
+ fieldsToLog: fields,
423
+ context,
424
+ },
425
+ `ON CONFLICT(id1, edge_type, id2) DO UPDATE SET ${onConflictFields
426
+ .map((f) => `${f} = EXCLUDED.${f}`)
427
+ .join(", ")}`,
428
+ ];
429
+ }
430
+ async performInsertWrite(q, edgeData, edge, context) {
431
+ const [options, suffix] = this.getInsertRowParams(edgeData, edge, context);
432
+ await (0, ent_1.createRow)(q, options, suffix);
433
+ }
434
+ performInsertWriteSync(q, edgeData, edge, context) {
435
+ const [options, suffix] = this.getInsertRowParams(edgeData, edge, context);
436
+ (0, ent_1.createRowSync)(q, options, suffix);
437
+ }
438
+ resolveImpl(executor, placeholder, desc) {
439
+ let ent = executor.resolveValue(placeholder);
440
+ if (!ent) {
441
+ throw new Error(`could not resolve placeholder value ${placeholder} for ${desc} for edge ${this.edgeInput.edgeType}`);
442
+ }
443
+ if (ent.id === undefined) {
444
+ throw new Error(`id of resolved ent is not defined`);
445
+ }
446
+ return [ent.id, ent.nodeType];
447
+ }
448
+ resolve(executor) {
449
+ if (this.options.id1Placeholder) {
450
+ [this.edgeInput.id1, this.edgeInput.id1Type] = this.resolveImpl(executor, this.edgeInput.id1, "id1");
451
+ }
452
+ if (this.options.id2Placeholder) {
453
+ [this.edgeInput.id2, this.edgeInput.id2Type] = this.resolveImpl(executor, this.edgeInput.id2, "id2");
454
+ }
455
+ if (this.options.dataPlaceholder) {
456
+ if (!this.edgeInput.data) {
457
+ throw new Error(`data placeholder set but edgeInput data undefined`);
458
+ }
459
+ let [data, _] = this.resolveImpl(executor, this.edgeInput.data.toString(), "data");
460
+ this.edgeInput.data = data.toString();
461
+ }
462
+ }
463
+ symmetricEdge() {
464
+ return new EdgeOperation(this.builder, {
465
+ id1: this.edgeInput.id2,
466
+ id1Type: this.edgeInput.id2Type,
467
+ id2: this.edgeInput.id1,
468
+ id2Type: this.edgeInput.id1Type,
469
+ edgeType: this.edgeInput.edgeType,
470
+ time: this.edgeInput.time,
471
+ data: this.edgeInput.data,
472
+ disableTransformations: this.edgeInput.disableTransformations,
473
+ }, {
474
+ operation: this.options.operation,
475
+ id1Placeholder: this.options.id2Placeholder,
476
+ id2Placeholder: this.options.id1Placeholder,
477
+ dataPlaceholder: this.options.dataPlaceholder,
478
+ });
479
+ }
480
+ inverseEdge(edgeData) {
481
+ return new EdgeOperation(this.builder, {
482
+ id1: this.edgeInput.id2,
483
+ id1Type: this.edgeInput.id2Type,
484
+ id2: this.edgeInput.id1,
485
+ id2Type: this.edgeInput.id1Type,
486
+ edgeType: edgeData.inverseEdgeType,
487
+ time: this.edgeInput.time,
488
+ data: this.edgeInput.data,
489
+ disableTransformations: this.edgeInput.disableTransformations,
490
+ }, {
491
+ operation: this.options.operation,
492
+ id1Placeholder: this.options.id2Placeholder,
493
+ id2Placeholder: this.options.id1Placeholder,
494
+ dataPlaceholder: this.options.dataPlaceholder,
495
+ });
496
+ }
497
+ static resolveIDs(srcBuilder, // id1
498
+ destID) {
499
+ let destIDVal;
500
+ let destPlaceholder = false;
501
+ if (this.isBuilder(destID)) {
502
+ destIDVal = destID.placeholderID;
503
+ destPlaceholder = true;
504
+ }
505
+ else {
506
+ destIDVal = destID;
507
+ }
508
+ let srcIDVal;
509
+ let srcType;
510
+ let srcPlaceholder = false;
511
+ if (srcBuilder.existingEnt) {
512
+ srcIDVal = srcBuilder.existingEnt.id;
513
+ srcType = srcBuilder.existingEnt.nodeType;
514
+ }
515
+ else {
516
+ srcPlaceholder = true;
517
+ // get placeholder.
518
+ srcIDVal = srcBuilder.placeholderID;
519
+ // expected to be filled later
520
+ srcType = "";
521
+ }
522
+ return [srcIDVal, srcType, srcPlaceholder, destIDVal, destPlaceholder];
523
+ }
524
+ static isBuilder(val) {
525
+ return val.placeholderID !== undefined;
526
+ }
527
+ static resolveData(data) {
528
+ if (!data) {
529
+ return [undefined, false];
530
+ }
531
+ if (this.isBuilder(data)) {
532
+ return [data.placeholderID.toString(), true];
533
+ }
534
+ return [data, false];
535
+ }
536
+ static inboundEdge(builder, edgeType, id1, nodeType, options) {
537
+ let [id2Val, id2Type, id2Placeholder, id1Val, id1Placeholder] = EdgeOperation.resolveIDs(builder, id1);
538
+ let [data, dataPlaceholder] = EdgeOperation.resolveData(options?.data);
539
+ const edge = {
540
+ id1: id1Val,
541
+ edgeType: edgeType,
542
+ id2: id2Val,
543
+ id2Type: id2Type,
544
+ id1Type: nodeType,
545
+ ...options,
546
+ };
547
+ if (data) {
548
+ edge.data = data;
549
+ }
550
+ return new EdgeOperation(builder, edge, {
551
+ operation: action_1.WriteOperation.Insert,
552
+ id2Placeholder,
553
+ id1Placeholder,
554
+ dataPlaceholder,
555
+ });
556
+ }
557
+ static outboundEdge(builder, edgeType, id2, nodeType, options) {
558
+ let [id1Val, id1Type, id1Placeholder, id2Val, id2Placeholder] = EdgeOperation.resolveIDs(builder, id2);
559
+ let [data, dataPlaceholder] = EdgeOperation.resolveData(options?.data);
560
+ const edge = {
561
+ id1: id1Val,
562
+ edgeType: edgeType,
563
+ id2: id2Val,
564
+ id2Type: nodeType,
565
+ id1Type: id1Type,
566
+ ...options,
567
+ };
568
+ if (data) {
569
+ edge.data = data;
570
+ }
571
+ return new EdgeOperation(builder, edge, {
572
+ operation: action_1.WriteOperation.Insert,
573
+ id1Placeholder,
574
+ id2Placeholder,
575
+ dataPlaceholder,
576
+ });
577
+ }
578
+ static removeInboundEdge(builder, edgeType, id1, options) {
579
+ if (!builder.existingEnt) {
580
+ throw new Error("cannot remove an edge from a non-existing ent");
581
+ }
582
+ const edge = {
583
+ id1: id1,
584
+ edgeType: edgeType,
585
+ id2: builder.existingEnt.id,
586
+ id2Type: "",
587
+ id1Type: "",
588
+ disableTransformations: options?.disableTransformations,
589
+ };
590
+ return new EdgeOperation(builder, edge, {
591
+ operation: action_1.WriteOperation.Delete,
592
+ });
593
+ }
594
+ static removeOutboundEdge(builder, edgeType, id2, options) {
595
+ if (!builder.existingEnt) {
596
+ throw new Error("cannot remove an edge from a non-existing ent");
597
+ }
598
+ const edge = {
599
+ id2: id2,
600
+ edgeType: edgeType,
601
+ id1: builder.existingEnt.id,
602
+ id2Type: "",
603
+ id1Type: "",
604
+ disableTransformations: options?.disableTransformations,
605
+ };
606
+ return new EdgeOperation(builder, edge, {
607
+ operation: action_1.WriteOperation.Delete,
608
+ });
609
+ }
610
+ }
611
+ exports.EdgeOperation = EdgeOperation;
612
+ class ConditionalOperation {
613
+ constructor(op, conditionalBuilder) {
614
+ this.op = op;
615
+ this.conditionalBuilder = conditionalBuilder;
616
+ this.shortCircuited = false;
617
+ this.builder = op.builder;
618
+ this.placeholderID = op.placeholderID;
619
+ }
620
+ shortCircuit(executor) {
621
+ this.shortCircuited = executor.builderOpChanged(this.conditionalBuilder);
622
+ return this.shortCircuited;
623
+ }
624
+ async preFetch(queryer, context) {
625
+ if (this.op.preFetch) {
626
+ return this.op.preFetch(queryer, context);
627
+ }
628
+ }
629
+ performWriteSync(queryer, context) {
630
+ this.op.performWriteSync(queryer, context);
631
+ }
632
+ performWrite(queryer, context) {
633
+ return this.op.performWrite(queryer, context);
634
+ }
635
+ returnedRow() {
636
+ if (this.op.returnedRow) {
637
+ return this.op.returnedRow();
638
+ }
639
+ return null;
640
+ }
641
+ updatedOperation() {
642
+ if (this.op.updatedOperation) {
643
+ return this.op.updatedOperation();
644
+ }
645
+ return null;
646
+ }
647
+ resolve(executor) {
648
+ if (this.op.resolve) {
649
+ return this.op.resolve(executor);
650
+ }
651
+ }
652
+ async postFetch(queryer, context) {
653
+ if (this.op.postFetch) {
654
+ return this.op.postFetch(queryer, context);
655
+ }
656
+ }
657
+ }
658
+ exports.ConditionalOperation = ConditionalOperation;
659
+ // separate because we need to implement createdEnt and we manually run those before edge/other operations in executors
660
+ class ConditionalNodeOperation extends ConditionalOperation {
661
+ createdEnt(viewer) {
662
+ if (this.op.createdEnt) {
663
+ return this.op.createdEnt(viewer);
664
+ }
665
+ return null;
666
+ }
667
+ updatedOperation() {
668
+ if (!this.op.updatedOperation) {
669
+ return null;
670
+ }
671
+ const ret = this.op.updatedOperation();
672
+ if (ret !== null) {
673
+ return ret;
674
+ }
675
+ if (!this.shortCircuited) {
676
+ return null;
677
+ }
678
+ // hack. if this short circuited, claim that this updated as an edit and it should invalidate other builders
679
+ // this API needs to change or EditNodeOperation needs to be used instead of this...
680
+ return {
681
+ operation: action_1.WriteOperation.Edit,
682
+ builder: this.builder,
683
+ };
684
+ }
685
+ }
686
+ exports.ConditionalNodeOperation = ConditionalNodeOperation;