@snowtop/ent 0.0.2 → 0.0.3-4.alpha

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 (103) hide show
  1. package/action/action.d.ts +6 -6
  2. package/action/action.js +2 -2
  3. package/action/executor.d.ts +7 -12
  4. package/action/executor.js +39 -33
  5. package/action/experimental_action.d.ts +4 -2
  6. package/action/experimental_action.js +27 -2
  7. package/action/index.d.ts +1 -1
  8. package/action/orchestrator.d.ts +14 -6
  9. package/action/orchestrator.js +188 -99
  10. package/action/privacy.js +4 -4
  11. package/auth/auth.js +2 -2
  12. package/core/base.js +12 -9
  13. package/core/clause.d.ts +1 -0
  14. package/core/clause.js +6 -2
  15. package/core/config.d.ts +20 -0
  16. package/core/config.js +2 -2
  17. package/core/context.js +3 -3
  18. package/core/convert.d.ts +4 -0
  19. package/core/convert.js +25 -2
  20. package/core/db.d.ts +18 -1
  21. package/core/db.js +4 -7
  22. package/core/ent.d.ts +17 -10
  23. package/core/ent.js +38 -15
  24. package/core/loaders/assoc_count_loader.js +5 -5
  25. package/core/loaders/assoc_edge_loader.js +10 -10
  26. package/core/loaders/loader.js +3 -3
  27. package/core/loaders/object_loader.js +6 -6
  28. package/core/loaders/query_loader.js +7 -7
  29. package/core/loaders/raw_count_loader.js +4 -4
  30. package/core/logger.js +2 -2
  31. package/core/privacy.d.ts +21 -1
  32. package/core/privacy.js +91 -47
  33. package/core/query/assoc_query.d.ts +12 -12
  34. package/core/query/assoc_query.js +86 -51
  35. package/core/query/custom_query.d.ts +10 -7
  36. package/core/query/custom_query.js +29 -3
  37. package/core/query/query.d.ts +24 -8
  38. package/core/query/query.js +41 -4
  39. package/core/query/shared_assoc_test.js +257 -13
  40. package/core/query/shared_test.d.ts +1 -1
  41. package/core/query/shared_test.js +11 -11
  42. package/core/viewer.js +1 -0
  43. package/graphql/builtins/connection.js +4 -3
  44. package/graphql/builtins/edge.js +3 -2
  45. package/graphql/builtins/node.js +2 -1
  46. package/graphql/graphql.d.ts +2 -0
  47. package/graphql/graphql.js +83 -61
  48. package/graphql/index.d.ts +1 -1
  49. package/graphql/index.js +2 -1
  50. package/graphql/node_resolver.d.ts +1 -0
  51. package/graphql/node_resolver.js +14 -1
  52. package/graphql/query/connection_type.d.ts +5 -4
  53. package/graphql/query/connection_type.js +6 -6
  54. package/graphql/query/edge_connection.d.ts +7 -7
  55. package/graphql/query/page_info.js +5 -4
  56. package/graphql/query/shared_assoc_test.js +9 -9
  57. package/graphql/query/shared_edge_connection.d.ts +1 -1
  58. package/graphql/query/shared_edge_connection.js +4 -4
  59. package/graphql/scalars/time.js +1 -1
  60. package/imports/dataz/example1/_auth.js +8 -8
  61. package/imports/dataz/example1/_viewer.js +4 -4
  62. package/imports/index.d.ts +1 -1
  63. package/imports/index.js +3 -5
  64. package/index.d.ts +2 -1
  65. package/index.js +6 -2
  66. package/package.json +17 -10
  67. package/parse_schema/parse.d.ts +41 -0
  68. package/parse_schema/parse.js +147 -0
  69. package/schema/base_schema.d.ts +2 -0
  70. package/schema/base_schema.js +17 -7
  71. package/schema/field.d.ts +52 -15
  72. package/schema/field.js +252 -47
  73. package/schema/index.d.ts +1 -0
  74. package/schema/index.js +1 -0
  75. package/schema/json_field.d.ts +17 -0
  76. package/schema/json_field.js +48 -0
  77. package/schema/schema.d.ts +39 -4
  78. package/schema/schema.js +2 -0
  79. package/scripts/custom_compiler.js +8 -10
  80. package/scripts/custom_graphql.js +45 -10
  81. package/scripts/read_schema.js +6 -108
  82. package/testutils/builder.d.ts +6 -3
  83. package/testutils/builder.js +31 -15
  84. package/testutils/db/test_db.d.ts +16 -8
  85. package/testutils/db/test_db.js +65 -9
  86. package/testutils/db_mock.js +5 -5
  87. package/testutils/ent-graphql-tests/index.d.ts +1 -0
  88. package/testutils/ent-graphql-tests/index.js +13 -13
  89. package/testutils/fake_comms.d.ts +1 -0
  90. package/testutils/fake_comms.js +4 -0
  91. package/testutils/fake_data/const.d.ts +5 -1
  92. package/testutils/fake_data/const.js +19 -1
  93. package/testutils/fake_data/events_query.d.ts +16 -11
  94. package/testutils/fake_data/events_query.js +15 -0
  95. package/testutils/fake_data/fake_contact.js +9 -9
  96. package/testutils/fake_data/fake_event.js +14 -14
  97. package/testutils/fake_data/fake_user.js +12 -10
  98. package/testutils/fake_data/test_helpers.d.ts +5 -1
  99. package/testutils/fake_data/test_helpers.js +49 -16
  100. package/testutils/fake_data/user_query.d.ts +25 -9
  101. package/testutils/fake_data/user_query.js +52 -5
  102. package/testutils/parse_sql.js +19 -3
  103. package/testutils/write.js +6 -6
package/core/privacy.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AllowIfViewerHasIdentityPrivacyPolicy = exports.AllowIfViewerPrivacyPolicy = exports.AlwaysDenyPrivacyPolicy = exports.AlwaysAllowPrivacyPolicy = exports.applyPrivacyPolicyX = exports.applyPrivacyPolicy = exports.AllowIfSubPolicyAllowsRule = exports.DelayedResultRule = exports.AllowIfConditionAppliesRule = exports.DenyIfViewerOutboundEdgeDoesNotExistRule = exports.DenyIfViewerInboundEdgeDoesNotExistRule = exports.DenyIfEdgeDoesNotExistRule = exports.DenyIfViewerOutboundEdgeExistsRule = exports.DenyIfViewerInboundEdgeExistsRule = exports.DenyIfEdgeExistsRule = exports.AllowIfViewerOutboundEdgeExistsRule = exports.AllowIfViewerInboundEdgeExistsRule = exports.AllowIfEdgeExistsRule = exports.DenyIfEntIsNotVisibleRule = exports.DenyIfEntIsVisibleRule = exports.DenyIfEntIsVisiblePolicy = exports.AllowIfEntIsVisiblePolicy = exports.AllowIfEntIsNotVisibleRule = exports.AllowIfEntIsVisibleRule = exports.AllowIfViewerIsRule = exports.DenyIfFuncRule = exports.AllowIfFuncRule = exports.DenyIfViewerEqualsRule = exports.AllowIfViewerEqualsRule = exports.AllowIfViewerRule = exports.AllowIfHasIdentity = exports.DenyIfLoggedInRule = exports.DenyIfLoggedOutRule = exports.AlwaysDenyRule = exports.AlwaysAllowRule = exports.EntPrivacyError = void 0;
3
+ exports.AllowIfViewerHasIdentityPrivacyPolicy = exports.AllowIfViewerPrivacyPolicy = exports.AlwaysDenyPrivacyPolicy = exports.AlwaysAllowPrivacyPolicy = exports.applyPrivacyPolicyX = exports.applyPrivacyPolicy = exports.AllowIfSubPolicyAllowsRule = exports.DelayedResultRule = exports.AllowIfConditionAppliesRule = exports.DenyIfViewerOutboundEdgeDoesNotExistRule = exports.DenyIfViewerInboundEdgeDoesNotExistRule = exports.DenyIfEdgeDoesNotExistRule = exports.DenyIfViewerOutboundEdgeExistsRule = exports.DenyIfViewerInboundEdgeExistsRule = exports.DenyIfEdgeExistsRule = exports.AllowIfViewerOutboundEdgeExistsRule = exports.AllowIfViewerInboundEdgeExistsRule = exports.AllowIfEdgeExistsRule = exports.DenyIfEntIsNotVisibleRule = exports.DenyIfEntIsVisibleRule = exports.DenyIfEntIsVisiblePolicy = exports.AllowIfEntIsVisiblePolicy = exports.AllowIfEntIsNotVisibleRule = exports.AllowIfEntIsVisibleRule = exports.DenyIfEntPropertyIsRule = exports.AllowIfEntPropertyIsRule = exports.AllowIfViewerIsEntPropertyRule = exports.AllowIfViewerIsRule = exports.DenyIfFuncRule = exports.AllowIfFuncRule = exports.DenyIfViewerEqualsRule = exports.AllowIfViewerEqualsRule = exports.AllowIfViewerRule = exports.AllowIfHasIdentity = exports.DenyIfLoggedInRule = exports.DenyIfLoggedOutRule = exports.AlwaysDenyRule = exports.AlwaysAllowRule = exports.EntPrivacyError = void 0;
4
4
  const base_1 = require("./base");
5
5
  const ent_1 = require("./ent");
6
6
  const logger_1 = require("./logger");
@@ -40,44 +40,44 @@ class EntInvalidPrivacyPolicyError extends Error {
40
40
  }
41
41
  exports.AlwaysAllowRule = {
42
42
  async apply(_v, _ent) {
43
- return base_1.Allow();
43
+ return (0, base_1.Allow)();
44
44
  },
45
45
  };
46
46
  exports.AlwaysDenyRule = {
47
47
  async apply(_v, _ent) {
48
- return base_1.Deny();
48
+ return (0, base_1.Deny)();
49
49
  },
50
50
  };
51
51
  exports.DenyIfLoggedOutRule = {
52
52
  async apply(v, _ent) {
53
53
  if (v.viewerID === null || v.viewerID == undefined) {
54
- return base_1.Deny();
54
+ return (0, base_1.Deny)();
55
55
  }
56
- return base_1.Skip();
56
+ return (0, base_1.Skip)();
57
57
  },
58
58
  };
59
59
  exports.DenyIfLoggedInRule = {
60
60
  async apply(v, _ent) {
61
61
  if (v.viewerID === null || v.viewerID == undefined) {
62
- return base_1.Skip();
62
+ return (0, base_1.Skip)();
63
63
  }
64
- return base_1.Deny();
64
+ return (0, base_1.Deny)();
65
65
  },
66
66
  };
67
67
  exports.AllowIfHasIdentity = {
68
68
  async apply(v, _ent) {
69
69
  if (v.viewerID === null || v.viewerID == undefined) {
70
- return base_1.Skip();
70
+ return (0, base_1.Skip)();
71
71
  }
72
- return base_1.Allow();
72
+ return (0, base_1.Allow)();
73
73
  },
74
74
  };
75
75
  exports.AllowIfViewerRule = {
76
76
  async apply(v, ent) {
77
77
  if (v.viewerID && v.viewerID === ent?.id) {
78
- return base_1.Allow();
78
+ return (0, base_1.Allow)();
79
79
  }
80
- return base_1.Skip();
80
+ return (0, base_1.Skip)();
81
81
  },
82
82
  };
83
83
  class AllowIfViewerEqualsRule {
@@ -85,7 +85,7 @@ class AllowIfViewerEqualsRule {
85
85
  this.id = id;
86
86
  }
87
87
  async apply(v, _ent) {
88
- return v.viewerID === this.id ? base_1.Allow() : base_1.Skip();
88
+ return v.viewerID === this.id ? (0, base_1.Allow)() : (0, base_1.Skip)();
89
89
  }
90
90
  }
91
91
  exports.AllowIfViewerEqualsRule = AllowIfViewerEqualsRule;
@@ -94,7 +94,7 @@ class DenyIfViewerEqualsRule {
94
94
  this.id = id;
95
95
  }
96
96
  async apply(v, _ent) {
97
- return v.viewerID === this.id ? base_1.Deny() : base_1.Skip();
97
+ return v.viewerID === this.id ? (0, base_1.Deny)() : (0, base_1.Skip)();
98
98
  }
99
99
  }
100
100
  exports.DenyIfViewerEqualsRule = DenyIfViewerEqualsRule;
@@ -105,9 +105,9 @@ class AllowIfFuncRule {
105
105
  async apply(v, ent) {
106
106
  const result = await this.fn(v, ent);
107
107
  if (result) {
108
- return base_1.Allow();
108
+ return (0, base_1.Allow)();
109
109
  }
110
- return base_1.Skip();
110
+ return (0, base_1.Skip)();
111
111
  }
112
112
  }
113
113
  exports.AllowIfFuncRule = AllowIfFuncRule;
@@ -118,12 +118,15 @@ class DenyIfFuncRule {
118
118
  async apply(v, ent) {
119
119
  const result = await this.fn(v, ent);
120
120
  if (result) {
121
- return base_1.Deny();
121
+ return (0, base_1.Deny)();
122
122
  }
123
- return base_1.Skip();
123
+ return (0, base_1.Skip)();
124
124
  }
125
125
  }
126
126
  exports.DenyIfFuncRule = DenyIfFuncRule;
127
+ /**
128
+ * @deprecated use AllowIfViewerIsEntPropertyRule
129
+ */
127
130
  class AllowIfViewerIsRule {
128
131
  constructor(property) {
129
132
  this.property = property;
@@ -134,23 +137,64 @@ class AllowIfViewerIsRule {
134
137
  result = ent[this.property];
135
138
  }
136
139
  if (result === v.viewerID) {
137
- return base_1.Allow();
140
+ return (0, base_1.Allow)();
138
141
  }
139
- return base_1.Skip();
142
+ return (0, base_1.Skip)();
140
143
  }
141
144
  }
142
145
  exports.AllowIfViewerIsRule = AllowIfViewerIsRule;
146
+ class AllowIfViewerIsEntPropertyRule {
147
+ constructor(property) {
148
+ this.property = property;
149
+ }
150
+ async apply(v, ent) {
151
+ const result = ent && ent[this.property];
152
+ if (result === v.viewerID) {
153
+ return (0, base_1.Allow)();
154
+ }
155
+ return (0, base_1.Skip)();
156
+ }
157
+ }
158
+ exports.AllowIfViewerIsEntPropertyRule = AllowIfViewerIsEntPropertyRule;
159
+ class AllowIfEntPropertyIsRule {
160
+ constructor(property, val) {
161
+ this.property = property;
162
+ this.val = val;
163
+ }
164
+ async apply(v, ent) {
165
+ const result = ent && ent[this.property];
166
+ if (result === this.val) {
167
+ return (0, base_1.Allow)();
168
+ }
169
+ return (0, base_1.Skip)();
170
+ }
171
+ }
172
+ exports.AllowIfEntPropertyIsRule = AllowIfEntPropertyIsRule;
173
+ class DenyIfEntPropertyIsRule {
174
+ constructor(property, val) {
175
+ this.property = property;
176
+ this.val = val;
177
+ }
178
+ async apply(v, ent) {
179
+ const result = ent && ent[this.property];
180
+ if (result === this.val) {
181
+ return (0, base_1.Deny)();
182
+ }
183
+ return (0, base_1.Skip)();
184
+ }
185
+ }
186
+ exports.DenyIfEntPropertyIsRule = DenyIfEntPropertyIsRule;
143
187
  class AllowIfEntIsVisibleRule {
144
188
  constructor(id, options) {
145
189
  this.id = id;
146
190
  this.options = options;
147
191
  }
148
192
  async apply(v, _ent) {
149
- const visible = await ent_1.loadEnt(v, this.id, this.options);
193
+ const visible = await (0, ent_1.loadEnt)(v, this.id, this.options);
150
194
  if (visible === null) {
151
- return base_1.Skip();
195
+ return (0, base_1.Skip)();
152
196
  }
153
- return base_1.Allow();
197
+ return (0, base_1.Allow)();
154
198
  }
155
199
  }
156
200
  exports.AllowIfEntIsVisibleRule = AllowIfEntIsVisibleRule;
@@ -160,11 +204,11 @@ class AllowIfEntIsNotVisibleRule {
160
204
  this.options = options;
161
205
  }
162
206
  async apply(v, _ent) {
163
- const visible = await ent_1.loadEnt(v, this.id, this.options);
207
+ const visible = await (0, ent_1.loadEnt)(v, this.id, this.options);
164
208
  if (visible === null) {
165
- return base_1.Allow();
209
+ return (0, base_1.Allow)();
166
210
  }
167
- return base_1.Skip();
211
+ return (0, base_1.Skip)();
168
212
  }
169
213
  }
170
214
  exports.AllowIfEntIsNotVisibleRule = AllowIfEntIsNotVisibleRule;
@@ -190,11 +234,11 @@ class DenyIfEntIsVisibleRule {
190
234
  this.options = options;
191
235
  }
192
236
  async apply(v, _ent) {
193
- const visible = await ent_1.loadEnt(v, this.id, this.options);
237
+ const visible = await (0, ent_1.loadEnt)(v, this.id, this.options);
194
238
  if (visible === null) {
195
- return base_1.Skip();
239
+ return (0, base_1.Skip)();
196
240
  }
197
- return base_1.Deny();
241
+ return (0, base_1.Deny)();
198
242
  }
199
243
  }
200
244
  exports.DenyIfEntIsVisibleRule = DenyIfEntIsVisibleRule;
@@ -204,17 +248,17 @@ class DenyIfEntIsNotVisibleRule {
204
248
  this.options = options;
205
249
  }
206
250
  async apply(v, _ent) {
207
- const visible = await ent_1.loadEnt(v, this.id, this.options);
251
+ const visible = await (0, ent_1.loadEnt)(v, this.id, this.options);
208
252
  if (visible === null) {
209
- return base_1.Deny();
253
+ return (0, base_1.Deny)();
210
254
  }
211
- return base_1.Skip();
255
+ return (0, base_1.Skip)();
212
256
  }
213
257
  }
214
258
  exports.DenyIfEntIsNotVisibleRule = DenyIfEntIsNotVisibleRule;
215
259
  async function allowIfEdgeExistsRule(id1, id2, edgeType, context) {
216
260
  if (id1 && id2) {
217
- const edge = await ent_1.loadEdgeForID2({
261
+ const edge = await (0, ent_1.loadEdgeForID2)({
218
262
  id1,
219
263
  edgeType,
220
264
  id2,
@@ -222,10 +266,10 @@ async function allowIfEdgeExistsRule(id1, id2, edgeType, context) {
222
266
  ctr: ent_1.AssocEdge,
223
267
  });
224
268
  if (edge) {
225
- return base_1.Allow();
269
+ return (0, base_1.Allow)();
226
270
  }
227
271
  }
228
- return base_1.Skip();
272
+ return (0, base_1.Skip)();
229
273
  }
230
274
  class AllowIfEdgeExistsRule {
231
275
  constructor(id1, id2, edgeType) {
@@ -259,7 +303,7 @@ exports.AllowIfViewerOutboundEdgeExistsRule = AllowIfViewerOutboundEdgeExistsRul
259
303
  async function denyIfEdgeExistsRule(id1, id2, edgeType, context) {
260
304
  // edge doesn't exist if no viewer
261
305
  if (id1 && id2) {
262
- const edge = await ent_1.loadEdgeForID2({
306
+ const edge = await (0, ent_1.loadEdgeForID2)({
263
307
  id1,
264
308
  edgeType,
265
309
  id2,
@@ -267,17 +311,17 @@ async function denyIfEdgeExistsRule(id1, id2, edgeType, context) {
267
311
  ctr: ent_1.AssocEdge,
268
312
  });
269
313
  if (edge) {
270
- return base_1.Deny();
314
+ return (0, base_1.Deny)();
271
315
  }
272
316
  }
273
- return base_1.Skip();
317
+ return (0, base_1.Skip)();
274
318
  }
275
319
  async function denyIfEdgeDoesNotExistRule(id1, id2, edgeType, context) {
276
320
  // edge doesn't exist if no viewer
277
321
  if (!id1 || !id2) {
278
- return base_1.Deny();
322
+ return (0, base_1.Deny)();
279
323
  }
280
- const edge = await ent_1.loadEdgeForID2({
324
+ const edge = await (0, ent_1.loadEdgeForID2)({
281
325
  id1,
282
326
  edgeType,
283
327
  id2,
@@ -285,9 +329,9 @@ async function denyIfEdgeDoesNotExistRule(id1, id2, edgeType, context) {
285
329
  ctr: ent_1.AssocEdge,
286
330
  });
287
331
  if (!edge) {
288
- return base_1.Deny();
332
+ return (0, base_1.Deny)();
289
333
  }
290
- return base_1.Skip();
334
+ return (0, base_1.Skip)();
291
335
  }
292
336
  class DenyIfEdgeExistsRule {
293
337
  constructor(id1, id2, edgeType) {
@@ -356,10 +400,10 @@ class AllowIfConditionAppliesRule {
356
400
  async apply(v, ent) {
357
401
  const result = await this.fn(v, ent);
358
402
  if (!result) {
359
- return base_1.Skip();
403
+ return (0, base_1.Skip)();
360
404
  }
361
405
  const r = await this.rule.apply(v, ent);
362
- return r.result === privacyResult.Allow ? base_1.Allow() : base_1.Skip();
406
+ return r.result === privacyResult.Allow ? (0, base_1.Allow)() : (0, base_1.Skip)();
363
407
  }
364
408
  }
365
409
  exports.AllowIfConditionAppliesRule = AllowIfConditionAppliesRule;
@@ -371,7 +415,7 @@ class DelayedResultRule {
371
415
  async apply(v, ent) {
372
416
  const rule = await this.fn(v, ent);
373
417
  if (!rule) {
374
- return base_1.Skip();
418
+ return (0, base_1.Skip)();
375
419
  }
376
420
  const res = await rule.apply(v, ent);
377
421
  return res;
@@ -386,9 +430,9 @@ class AllowIfSubPolicyAllowsRule {
386
430
  async apply(v, ent) {
387
431
  const result = await applyPrivacyPolicy(v, this.policy, ent);
388
432
  if (result) {
389
- return base_1.Allow();
433
+ return (0, base_1.Allow)();
390
434
  }
391
- return base_1.Skip();
435
+ return (0, base_1.Skip)();
392
436
  }
393
437
  }
394
438
  exports.AllowIfSubPolicyAllowsRule = AllowIfSubPolicyAllowsRule;
@@ -400,7 +444,7 @@ async function applyPrivacyPolicy(v, policy, ent) {
400
444
  // TODO privacy errors should not throw
401
445
  // but other expected errors should throw...
402
446
  // we shouldn't just hide them
403
- logger_1.log("debug", e);
447
+ (0, logger_1.log)("debug", e);
404
448
  return false;
405
449
  }
406
450
  }
@@ -2,29 +2,29 @@ import { ID, Ent, Viewer, LoadEntOptions, EdgeQueryableDataOptions } from "../ba
2
2
  import { AssocEdge } from "../ent";
3
3
  import { AssocEdgeCountLoaderFactory } from "../loaders/assoc_count_loader";
4
4
  import { AssocEdgeLoaderFactory } from "../loaders/assoc_edge_loader";
5
- import { EdgeQuery, BaseEdgeQuery } from "./query";
6
- export declare type EdgeQuerySource<T extends Ent> = T | T[] | ID | ID[] | EdgeQuery<T, AssocEdge>;
7
- export declare class AssocEdgeQueryBase<TSource extends Ent, TDest extends Ent, TEdge extends AssocEdge> extends BaseEdgeQuery<TDest, TEdge> {
5
+ import { EdgeQuery, BaseEdgeQuery, IDInfo } from "./query";
6
+ export declare type EdgeQuerySource<TSource extends Ent, TDest extends Ent = Ent> = TSource | TSource[] | ID | ID[] | EdgeQuery<TDest, Ent, AssocEdge>;
7
+ declare type loaderOptionsFunc = (type: string) => LoadEntOptions<Ent>;
8
+ export declare abstract class AssocEdgeQueryBase<TSource extends Ent, TDest extends Ent, TEdge extends AssocEdge> extends BaseEdgeQuery<TSource, TDest, TEdge> implements EdgeQuery<TSource, TDest, TEdge> {
8
9
  viewer: Viewer;
9
- src: EdgeQuerySource<TSource>;
10
+ src: EdgeQuerySource<TSource, TDest>;
10
11
  private countLoaderFactory;
11
12
  private dataLoaderFactory;
12
13
  private options;
13
- private idsResolved;
14
- private resolvedIDs;
15
- constructor(viewer: Viewer, src: EdgeQuerySource<TSource>, countLoaderFactory: AssocEdgeCountLoaderFactory, dataLoaderFactory: AssocEdgeLoaderFactory<TEdge>, options: LoadEntOptions<TDest>);
16
- private resolveIDs;
14
+ constructor(viewer: Viewer, src: EdgeQuerySource<TSource, TDest>, countLoaderFactory: AssocEdgeCountLoaderFactory, dataLoaderFactory: AssocEdgeLoaderFactory<TEdge>, options: LoadEntOptions<TDest> | loaderOptionsFunc);
17
15
  private isEdgeQuery;
18
- private addID;
16
+ abstract sourceEnt(id: ID): Promise<Ent | null>;
19
17
  private getSingleID;
20
18
  queryRawCount(): Promise<number>;
21
19
  queryAllRawCount(): Promise<Map<ID, number>>;
22
20
  protected loadEntsFromEdges(id: ID, edges: AssocEdge[]): Promise<TDest[]>;
23
21
  dataToID(edge: AssocEdge): ID;
24
- protected loadRawData(options: EdgeQueryableDataOptions): Promise<void>;
22
+ protected loadRawIDs(addID: (src: ID | TSource) => void): Promise<void>;
23
+ protected loadRawData(infos: IDInfo[], options: EdgeQueryableDataOptions): Promise<void>;
25
24
  queryID2(id2: ID): Promise<TEdge | undefined>;
26
25
  queryAllID2(id2: ID): Promise<Map<ID, TEdge>>;
27
26
  }
28
- export interface EdgeQueryCtr<T extends Ent, TEdge extends AssocEdge> {
29
- new (viewer: Viewer, src: EdgeQuerySource<T>): EdgeQuery<T, TEdge>;
27
+ export interface EdgeQueryCtr<TSource extends Ent, TDest extends Ent, TEdge extends AssocEdge> {
28
+ new (viewer: Viewer, src: EdgeQuerySource<TSource>): EdgeQuery<TSource, TDest, TEdge>;
30
29
  }
30
+ export {};
@@ -4,34 +4,16 @@ exports.AssocEdgeQueryBase = void 0;
4
4
  const ent_1 = require("../ent");
5
5
  const query_1 = require("./query");
6
6
  class AssocEdgeQueryBase extends query_1.BaseEdgeQuery {
7
- constructor(viewer, src, countLoaderFactory, dataLoaderFactory, options) {
7
+ constructor(viewer, src, countLoaderFactory, dataLoaderFactory,
8
+ // if function, it's a polymorphic edge and need to provide
9
+ // a function that goes from edgeType to LoadEntOptions
10
+ options) {
8
11
  super(viewer, "time");
9
12
  this.viewer = viewer;
10
13
  this.src = src;
11
14
  this.countLoaderFactory = countLoaderFactory;
12
15
  this.dataLoaderFactory = dataLoaderFactory;
13
16
  this.options = options;
14
- this.resolvedIDs = [];
15
- }
16
- // TODO memoization...
17
- async resolveIDs() {
18
- if (this.idsResolved) {
19
- return this.resolvedIDs;
20
- }
21
- if (Array.isArray(this.src)) {
22
- this.src.forEach((obj) => this.addID(obj));
23
- }
24
- else if (this.isEdgeQuery(this.src)) {
25
- const idsMap = await this.src.queryAllIDs();
26
- for (const [_, ids] of idsMap) {
27
- ids.forEach((id) => this.resolvedIDs.push(id));
28
- }
29
- }
30
- else {
31
- this.addID(this.src);
32
- }
33
- this.idsResolved = true;
34
- return this.resolvedIDs;
35
17
  }
36
18
  isEdgeQuery(obj) {
37
19
  if (obj.queryIDs !== undefined) {
@@ -39,70 +21,123 @@ class AssocEdgeQueryBase extends query_1.BaseEdgeQuery {
39
21
  }
40
22
  return false;
41
23
  }
42
- addID(obj) {
43
- if (typeof obj === "object") {
44
- this.resolvedIDs.push(obj.id);
45
- }
46
- else {
47
- this.resolvedIDs.push(obj);
48
- }
49
- }
50
24
  async getSingleID() {
51
- const ids = await this.resolveIDs();
52
- if (ids.length !== 1) {
25
+ const infos = await this.genIDInfosToFetch();
26
+ if (infos.length !== 1) {
53
27
  throw new Error("cannot call queryRawCount when more than one id is requested");
54
28
  }
55
- return ids[0];
29
+ return infos[0];
56
30
  }
57
31
  // doesn't work with filters...
58
32
  async queryRawCount() {
59
- const id = await this.getSingleID();
60
- return this.countLoaderFactory.createLoader(this.viewer.context).load(id);
33
+ const info = await this.getSingleID();
34
+ if (info.invalidated) {
35
+ return 0;
36
+ }
37
+ return this.countLoaderFactory
38
+ .createLoader(this.viewer.context)
39
+ .load(info.id);
61
40
  }
62
41
  async queryAllRawCount() {
63
42
  let results = new Map();
64
- const ids = await this.resolveIDs();
43
+ const infos = await this.genIDInfosToFetch();
65
44
  const loader = this.countLoaderFactory.createLoader(this.viewer.context);
66
- await Promise.all(ids.map(async (id) => {
67
- const count = await loader.load(id);
68
- results.set(id, count);
45
+ await Promise.all(infos.map(async (info) => {
46
+ if (info.invalidated) {
47
+ results.set(info.id, 0);
48
+ return;
49
+ }
50
+ const count = await loader.load(info.id);
51
+ results.set(info.id, count);
69
52
  }));
70
53
  return results;
71
54
  }
72
55
  async loadEntsFromEdges(id, edges) {
56
+ if (typeof this.options === "function") {
57
+ const m = new Map();
58
+ for (const edge of edges) {
59
+ const nodeType = edge.id2Type;
60
+ let data = m.get(nodeType);
61
+ if (data === undefined) {
62
+ const opts = this.options(nodeType);
63
+ if (opts === undefined) {
64
+ throw new Error(`getLoaderOptions returned undefined for type ${nodeType}`);
65
+ }
66
+ data = {
67
+ ids: [],
68
+ options: opts,
69
+ };
70
+ }
71
+ data.ids.push(edge.id2);
72
+ m.set(nodeType, data);
73
+ }
74
+ let promises = [];
75
+ for (const [_, value] of m) {
76
+ promises.push((0, ent_1.loadEnts)(this.viewer, value.options, ...value.ids));
77
+ }
78
+ const entss = await Promise.all(promises);
79
+ const r = [];
80
+ for (const ents of entss) {
81
+ r.push(...ents);
82
+ }
83
+ return r;
84
+ }
73
85
  const ids = edges.map((edge) => edge.id2);
74
- return await ent_1.loadEnts(this.viewer, this.options, ...ids);
86
+ return await (0, ent_1.loadEnts)(this.viewer, this.options, ...ids);
75
87
  }
76
88
  dataToID(edge) {
77
89
  return edge.id2;
78
90
  }
79
- async loadRawData(options) {
80
- const ids = await this.resolveIDs();
91
+ async loadRawIDs(addID) {
92
+ if (Array.isArray(this.src)) {
93
+ this.src.forEach((obj) => addID(obj));
94
+ }
95
+ else if (this.isEdgeQuery(this.src)) {
96
+ const idsMap = await this.src.queryAllIDs();
97
+ for (const [_, ids] of idsMap) {
98
+ ids.forEach((id) => addID(id));
99
+ }
100
+ }
101
+ else {
102
+ addID(this.src);
103
+ }
104
+ }
105
+ async loadRawData(infos, options) {
81
106
  const loader = this.dataLoaderFactory.createConfigurableLoader(options, this.viewer.context);
82
- await Promise.all(ids.map(async (id) => {
107
+ await Promise.all(infos.map(async (info) => {
108
+ if (info.invalidated) {
109
+ this.edges.set(info.id, []);
110
+ return;
111
+ }
83
112
  // there'll be filters for special edges here...
84
113
  // and then depending on that, we use this
85
114
  // what happens if you do first(10).id2(XX)
86
115
  // doesn't make sense
87
116
  // so only makes sense if one of these...
88
117
  // Id2 needs to be an option
89
- const edges = await loader.load(id);
90
- this.edges.set(id, edges);
118
+ const edges = await loader.load(info.id);
119
+ this.edges.set(info.id, edges);
91
120
  }));
92
121
  }
93
122
  async queryID2(id2) {
94
- const id = await this.getSingleID();
123
+ const info = await this.getSingleID();
124
+ if (info.invalidated) {
125
+ return;
126
+ }
95
127
  const loader = this.dataLoaderFactory.createLoader(this.viewer.context);
96
- return loader.loadEdgeForID2(id, id2);
128
+ return loader.loadEdgeForID2(info.id, id2);
97
129
  }
98
130
  async queryAllID2(id2) {
99
- const ids = await this.resolveIDs();
131
+ const infos = await this.genIDInfosToFetch();
100
132
  const loader = this.dataLoaderFactory.createLoader(this.viewer.context);
101
133
  const m = new Map();
102
- await Promise.all(ids.map(async (id) => {
103
- const edge = await loader.loadEdgeForID2(id, id2);
134
+ await Promise.all(infos.map(async (info) => {
135
+ if (info.invalidated) {
136
+ return;
137
+ }
138
+ const edge = await loader.loadEdgeForID2(info.id, id2);
104
139
  if (edge) {
105
- m.set(id, edge);
140
+ m.set(info.id, edge);
106
141
  }
107
142
  }));
108
143
  return m;
@@ -1,20 +1,23 @@
1
1
  import { Data, Ent, ID, EdgeQueryableDataOptions, LoadEntOptions, Viewer, LoaderFactory, ConfigurableLoaderFactory } from "../base";
2
- import { BaseEdgeQuery } from "./query";
3
- export interface CustomEdgeQueryOptions<T extends Ent> {
4
- src: Ent | ID;
2
+ import { BaseEdgeQuery, IDInfo, EdgeQuery } from "./query";
3
+ export interface CustomEdgeQueryOptions<TSource extends Ent, TDest extends Ent> {
4
+ src: TSource | ID;
5
5
  countLoaderFactory: LoaderFactory<ID, number>;
6
6
  dataLoaderFactory: ConfigurableLoaderFactory<ID, Data[]>;
7
- options: LoadEntOptions<T>;
7
+ options: LoadEntOptions<TDest>;
8
8
  sortColumn?: string;
9
9
  }
10
- export declare class CustomEdgeQueryBase<TDest extends Ent> extends BaseEdgeQuery<TDest, Data> {
10
+ export declare abstract class CustomEdgeQueryBase<TSource extends Ent, TDest extends Ent> extends BaseEdgeQuery<TSource, TDest, Data> implements EdgeQuery<TSource, TDest, Data> {
11
11
  viewer: Viewer;
12
12
  private options;
13
13
  private id;
14
- constructor(viewer: Viewer, options: CustomEdgeQueryOptions<TDest>);
14
+ constructor(viewer: Viewer, options: CustomEdgeQueryOptions<TSource, TDest>);
15
+ abstract sourceEnt(id: ID): Promise<Ent | null>;
16
+ private idVisible;
15
17
  queryRawCount(): Promise<number>;
16
18
  queryAllRawCount(): Promise<Map<ID, number>>;
17
- protected loadRawData(options: EdgeQueryableDataOptions): Promise<void>;
19
+ protected loadRawIDs(addID: (src: ID | TSource) => void): Promise<void>;
20
+ protected loadRawData(infos: IDInfo[], options: EdgeQueryableDataOptions): Promise<void>;
18
21
  dataToID(edge: Data): ID;
19
22
  protected loadEntsFromEdges(id: ID, rows: Data[]): Promise<TDest[]>;
20
23
  }
@@ -16,16 +16,34 @@ class CustomEdgeQueryBase extends query_1.BaseEdgeQuery {
16
16
  this.id = options.src;
17
17
  }
18
18
  }
19
+ async idVisible() {
20
+ const ids = await this.genIDInfosToFetch();
21
+ if (ids.length !== 1) {
22
+ throw new Error("invalid number of IDInfo");
23
+ }
24
+ return !ids[0].invalidated;
25
+ }
19
26
  async queryRawCount() {
27
+ const idVisible = await this.idVisible();
28
+ if (!idVisible) {
29
+ return 0;
30
+ }
20
31
  return await this.options.countLoaderFactory
21
32
  .createLoader(this.viewer.context)
22
33
  .load(this.id);
23
34
  }
24
35
  async queryAllRawCount() {
25
- const count = await this.queryRawCount();
36
+ let count = 0;
37
+ const idVisible = await this.idVisible();
38
+ if (idVisible) {
39
+ count = await this.queryRawCount();
40
+ }
26
41
  return new Map([[this.id, count]]);
27
42
  }
28
- async loadRawData(options) {
43
+ async loadRawIDs(addID) {
44
+ addID(this.options.src);
45
+ }
46
+ async loadRawData(infos, options) {
29
47
  const loader = this.options.dataLoaderFactory.createConfigurableLoader(options, this.viewer.context);
30
48
  if (!options.orderby) {
31
49
  options.orderby = `${this.options.sortColumn} DESC`;
@@ -33,6 +51,14 @@ class CustomEdgeQueryBase extends query_1.BaseEdgeQuery {
33
51
  if (!options.limit) {
34
52
  options.limit = ent_1.DefaultLimit;
35
53
  }
54
+ if (infos.length !== 1) {
55
+ throw new Error(`expected 1 info passed to loadRawData. ${infos.length} passed`);
56
+ }
57
+ const info = infos[0];
58
+ if (info.invalidated) {
59
+ this.edges.set(this.id, []);
60
+ return;
61
+ }
36
62
  const rows = await loader.load(this.id);
37
63
  this.edges.set(this.id, rows);
38
64
  }
@@ -40,7 +66,7 @@ class CustomEdgeQueryBase extends query_1.BaseEdgeQuery {
40
66
  return edge.id;
41
67
  }
42
68
  async loadEntsFromEdges(id, rows) {
43
- const ents = await ent_1.applyPrivacyPolicyForRows(this.viewer, rows, this.options.options);
69
+ const ents = await (0, ent_1.applyPrivacyPolicyForRows)(this.viewer, rows, this.options.options);
44
70
  return Array.from(ents.values());
45
71
  }
46
72
  }