@snowtop/ent 0.1.0-alpha3 → 0.1.0-alpha30

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 (102) hide show
  1. package/action/action.d.ts +28 -24
  2. package/action/executor.d.ts +4 -4
  3. package/action/executor.js +2 -2
  4. package/action/experimental_action.d.ts +21 -20
  5. package/action/experimental_action.js +11 -5
  6. package/action/orchestrator.d.ts +31 -16
  7. package/action/orchestrator.js +156 -43
  8. package/action/privacy.d.ts +2 -2
  9. package/core/base.d.ts +25 -21
  10. package/core/base.js +16 -0
  11. package/core/clause.d.ts +24 -3
  12. package/core/clause.js +246 -5
  13. package/core/config.d.ts +23 -0
  14. package/core/config.js +17 -0
  15. package/core/context.d.ts +2 -2
  16. package/core/convert.d.ts +1 -1
  17. package/core/db.d.ts +3 -3
  18. package/core/db.js +2 -0
  19. package/core/ent.d.ts +19 -21
  20. package/core/ent.js +76 -25
  21. package/core/loaders/assoc_count_loader.d.ts +2 -2
  22. package/core/loaders/assoc_edge_loader.d.ts +3 -3
  23. package/core/loaders/assoc_edge_loader.js +5 -4
  24. package/core/loaders/index_loader.js +1 -0
  25. package/core/loaders/object_loader.d.ts +10 -5
  26. package/core/loaders/object_loader.js +59 -4
  27. package/core/loaders/query_loader.d.ts +2 -2
  28. package/core/loaders/raw_count_loader.d.ts +2 -2
  29. package/core/privacy.d.ts +25 -25
  30. package/core/privacy.js +3 -0
  31. package/core/query/assoc_query.d.ts +6 -6
  32. package/core/query/custom_query.d.ts +5 -5
  33. package/core/query/query.d.ts +1 -1
  34. package/core/viewer.d.ts +4 -3
  35. package/core/viewer.js +4 -0
  36. package/graphql/builtins/connection.js +3 -3
  37. package/graphql/builtins/edge.js +2 -2
  38. package/graphql/builtins/node.js +1 -1
  39. package/graphql/graphql.d.ts +3 -2
  40. package/graphql/graphql.js +24 -23
  41. package/graphql/index.d.ts +1 -0
  42. package/graphql/index.js +3 -1
  43. package/graphql/mutations/union.d.ts +2 -0
  44. package/graphql/mutations/union.js +35 -0
  45. package/graphql/node_resolver.d.ts +0 -1
  46. package/graphql/query/connection_type.js +6 -6
  47. package/graphql/query/edge_connection.d.ts +9 -9
  48. package/graphql/query/page_info.d.ts +1 -1
  49. package/graphql/query/page_info.js +4 -4
  50. package/graphql/query/shared_assoc_test.js +2 -2
  51. package/graphql/scalars/time.d.ts +1 -1
  52. package/index.d.ts +16 -1
  53. package/index.js +18 -5
  54. package/package.json +3 -3
  55. package/parse_schema/parse.d.ts +18 -5
  56. package/parse_schema/parse.js +55 -6
  57. package/schema/base_schema.d.ts +36 -1
  58. package/schema/base_schema.js +51 -2
  59. package/schema/field.d.ts +1 -1
  60. package/schema/field.js +1 -1
  61. package/schema/index.d.ts +2 -2
  62. package/schema/index.js +8 -1
  63. package/schema/schema.d.ts +61 -1
  64. package/schema/schema.js +126 -5
  65. package/schema/union_field.d.ts +2 -1
  66. package/schema/union_field.js +32 -14
  67. package/scripts/custom_graphql.js +122 -15
  68. package/scripts/{transform_schema.d.ts → migrate_v0.1.d.ts} +0 -0
  69. package/scripts/migrate_v0.1.js +36 -0
  70. package/scripts/read_schema.js +15 -1
  71. package/testutils/builder.d.ts +31 -21
  72. package/testutils/builder.js +98 -13
  73. package/testutils/context/test_context.d.ts +2 -2
  74. package/testutils/context/test_context.js +7 -1
  75. package/testutils/db/test_db.d.ts +2 -1
  76. package/testutils/db/test_db.js +13 -4
  77. package/testutils/ent-graphql-tests/index.d.ts +2 -0
  78. package/testutils/ent-graphql-tests/index.js +26 -17
  79. package/testutils/fake_data/fake_contact.d.ts +4 -8
  80. package/testutils/fake_data/fake_contact.js +15 -19
  81. package/testutils/fake_data/fake_event.d.ts +4 -8
  82. package/testutils/fake_data/fake_event.js +21 -25
  83. package/testutils/fake_data/fake_user.d.ts +5 -9
  84. package/testutils/fake_data/fake_user.js +23 -27
  85. package/testutils/fake_data/test_helpers.js +1 -1
  86. package/testutils/fake_data/user_query.d.ts +2 -2
  87. package/testutils/fake_log.d.ts +3 -3
  88. package/tsc/ast.d.ts +43 -0
  89. package/tsc/ast.js +264 -0
  90. package/tsc/compilerOptions.d.ts +6 -0
  91. package/tsc/compilerOptions.js +40 -1
  92. package/tsc/move_generated.d.ts +1 -0
  93. package/tsc/move_generated.js +160 -0
  94. package/tsc/transform.d.ts +21 -0
  95. package/tsc/transform.js +167 -0
  96. package/tsc/transform_action.d.ts +20 -0
  97. package/tsc/transform_action.js +169 -0
  98. package/tsc/transform_ent.d.ts +17 -0
  99. package/tsc/transform_ent.js +59 -0
  100. package/tsc/transform_schema.d.ts +27 -0
  101. package/tsc/transform_schema.js +354 -0
  102. package/scripts/transform_schema.js +0 -288
package/core/ent.js CHANGED
@@ -22,8 +22,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
22
22
  return (mod && mod.__esModule) ? mod : { "default": mod };
23
23
  };
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
- exports.applyPrivacyPolicyForRows = exports.applyPrivacyPolicyForRowX = exports.applyPrivacyPolicyForRow = exports.loadNodesByEdge = exports.loadEdgeForID2 = exports.loadRawEdgeCountX = exports.loadUniqueNode = exports.loadUniqueEdge = exports.loadCustomEdges = exports.loadEdges = exports.defaultEdgeQueryOptions = exports.DefaultLimit = exports.loadEdgeDatas = exports.loadEdgeData = exports.assocEdgeLoader = exports.AssocEdgeData = exports.getCursor = exports.AssocEdge = exports.DeleteNodeOperation = exports.deleteRowsSync = exports.deleteRows = exports.editRowSync = exports.editRow = exports.buildUpdateQuery = exports.createRowSync = exports.createRow = exports.buildInsertQuery = exports.EdgeOperation = exports.EditNodeOperation = exports.buildGroupQuery = exports.buildQuery = exports.loadRows = exports.performRawQuery = exports.loadRow = exports.loadRowX = exports.applyPrivacyPolicyForEntX = exports.applyPrivacyPolicyForEnt = exports.loadDerivedEntX = exports.loadDerivedEnt = exports.loadCustomData = exports.loadCustomEnts = exports.loadEntsFromClause = exports.loadEntsList = exports.loadEnts = exports.loadEntXFromClause = exports.loadEntFromClause = exports.loadEntXViaKey = exports.loadEntX = exports.loadEntViaKey = exports.loadEnt = void 0;
26
- exports.getEdgeTypeInGroup = void 0;
25
+ exports.getEdgeTypeInGroup = exports.applyPrivacyPolicyForRows = exports.applyPrivacyPolicyForRowX = exports.applyPrivacyPolicyForRow = exports.loadNodesByEdge = exports.loadEdgeForID2 = exports.loadRawEdgeCountX = exports.loadUniqueNode = exports.loadUniqueEdge = exports.loadCustomEdges = exports.loadEdges = exports.defaultEdgeQueryOptions = exports.DefaultLimit = exports.loadEdgeDatas = exports.loadEdgeData = exports.assocEdgeLoader = exports.AssocEdgeData = exports.getCursor = exports.AssocEdge = exports.DeleteNodeOperation = exports.deleteRowsSync = exports.deleteRows = exports.editRowSync = exports.editRow = exports.buildUpdateQuery = exports.createRowSync = exports.createRow = exports.buildInsertQuery = exports.EdgeOperation = exports.EditNodeOperation = exports.buildGroupQuery = exports.buildQuery = exports.loadRows = exports.performRawQuery = exports.loadRow = exports.loadRowX = exports.loadDerivedEntX = exports.loadDerivedEnt = exports.loadCustomData = exports.loadCustomEnts = exports.loadEntsFromClause = exports.loadEntsList = exports.loadEnts = exports.loadEntXFromClause = exports.loadEntFromClause = exports.loadEntXViaKey = exports.loadEntX = exports.loadEntViaKey = exports.loadEnt = void 0;
27
26
  const db_1 = __importStar(require("./db"));
28
27
  const privacy_1 = require("./privacy");
29
28
  const clause = __importStar(require("./clause"));
@@ -62,6 +61,7 @@ function createDataLoader(options) {
62
61
  if ((0, logger_1.logEnabled)("query")) {
63
62
  loaderOptions.cacheMap = new cacheMap(options);
64
63
  }
64
+ // something here brokwn with strict:true
65
65
  return new dataloader_1.default(async (ids) => {
66
66
  if (!ids.length) {
67
67
  return [];
@@ -140,8 +140,7 @@ async function loadEntXFromClause(viewer, options, clause) {
140
140
  context: viewer.context,
141
141
  };
142
142
  const row = await loadRowX(rowOptions);
143
- const ent = new options.ent(viewer, row);
144
- return await applyPrivacyPolicyForEntX(viewer, ent);
143
+ return await applyPrivacyPolicyForRowX(viewer, options, row);
145
144
  }
146
145
  exports.loadEntXFromClause = loadEntXFromClause;
147
146
  async function loadEnts(viewer, options, ...ids) {
@@ -212,7 +211,7 @@ async function loadCustomEnts(viewer, options, query) {
212
211
  const result = new Array(rows.length);
213
212
  await Promise.all(rows.map(async (row, idx) => {
214
213
  const ent = new options.ent(viewer, row);
215
- let privacyEnt = await applyPrivacyPolicyForEnt(viewer, ent);
214
+ let privacyEnt = await applyPrivacyPolicyForEnt(viewer, ent, row, options);
216
215
  if (privacyEnt) {
217
216
  result[idx] = privacyEnt;
218
217
  }
@@ -258,30 +257,60 @@ exports.loadCustomData = loadCustomData;
258
257
  // Derived ents
259
258
  async function loadDerivedEnt(viewer, data, loader) {
260
259
  const ent = new loader(viewer, data);
261
- return await applyPrivacyPolicyForEnt(viewer, ent);
260
+ return await applyPrivacyPolicyForEnt(viewer, ent, data, {
261
+ ent: loader,
262
+ });
262
263
  }
263
264
  exports.loadDerivedEnt = loadDerivedEnt;
264
265
  async function loadDerivedEntX(viewer, data, loader) {
265
266
  const ent = new loader(viewer, data);
266
- return await applyPrivacyPolicyForEntX(viewer, ent);
267
+ return await applyPrivacyPolicyForEntX(viewer, ent, data, { ent: loader });
267
268
  }
268
269
  exports.loadDerivedEntX = loadDerivedEntX;
269
- async function applyPrivacyPolicyForEnt(viewer, ent) {
270
+ // everything calls into this two so should be fine
271
+ // TODO is there a smarter way to not instantiate two objects here?
272
+ async function applyPrivacyPolicyForEnt(viewer, ent, data, fieldPrivacyOptions) {
270
273
  if (ent) {
271
- const visible = await (0, privacy_1.applyPrivacyPolicy)(viewer, ent.privacyPolicy, ent);
272
- if (visible) {
273
- return ent;
274
+ const visible = await (0, privacy_1.applyPrivacyPolicy)(viewer, ent.getPrivacyPolicy(), ent);
275
+ if (!visible) {
276
+ return null;
274
277
  }
278
+ return doFieldPrivacy(viewer, ent, data, fieldPrivacyOptions);
275
279
  }
276
280
  return null;
277
281
  }
278
- exports.applyPrivacyPolicyForEnt = applyPrivacyPolicyForEnt;
279
- async function applyPrivacyPolicyForEntX(viewer, ent) {
282
+ async function applyPrivacyPolicyForEntX(viewer, ent, data, options) {
280
283
  // this will throw
281
- await (0, privacy_1.applyPrivacyPolicyX)(viewer, ent.privacyPolicy, ent);
284
+ await (0, privacy_1.applyPrivacyPolicyX)(viewer, ent.getPrivacyPolicy(), ent);
285
+ return doFieldPrivacy(viewer, ent, data, options);
286
+ }
287
+ async function doFieldPrivacy(viewer, ent, data, options) {
288
+ if (!options.fieldPrivacy) {
289
+ return ent;
290
+ }
291
+ const promises = [];
292
+ let somethingChanged = false;
293
+ for (const [k, policy] of options.fieldPrivacy) {
294
+ promises.push((async () => {
295
+ // don't do anything if key is null or for some reason missing
296
+ const curr = data[k];
297
+ if (curr === null || curr === undefined) {
298
+ return;
299
+ }
300
+ const r = await (0, privacy_1.applyPrivacyPolicy)(viewer, policy, ent);
301
+ if (!r) {
302
+ data[k] = null;
303
+ somethingChanged = true;
304
+ }
305
+ })());
306
+ }
307
+ await Promise.all(promises);
308
+ if (somethingChanged) {
309
+ // have to create new instance
310
+ return new options.ent(viewer, data);
311
+ }
282
312
  return ent;
283
313
  }
284
- exports.applyPrivacyPolicyForEntX = applyPrivacyPolicyForEntX;
285
314
  function logQuery(query, logValues) {
286
315
  (0, logger_1.log)("query", {
287
316
  query: query,
@@ -327,6 +356,8 @@ async function loadRow(options) {
327
356
  return res.rows[0];
328
357
  }
329
358
  catch (e) {
359
+ // an example of an error being suppressed
360
+ // another one. TODO https://github.com/lolopinto/ent/issues/862
330
361
  (0, logger_1.log)("error", e);
331
362
  return null;
332
363
  }
@@ -406,6 +437,7 @@ class EditNodeOperation {
406
437
  constructor(options, existingEnt = null) {
407
438
  this.options = options;
408
439
  this.existingEnt = existingEnt;
440
+ this.row = null;
409
441
  this.placeholderID = options.placeholderID;
410
442
  }
411
443
  resolve(executor) {
@@ -439,9 +471,12 @@ class EditNodeOperation {
439
471
  };
440
472
  if (this.existingEnt) {
441
473
  if (this.hasData(options.fields)) {
474
+ // even this with returning * may not always work if transformed...
475
+ // we can have a transformed flag to see if it should be returned?
442
476
  this.row = await editRow(queryer, options, this.existingEnt.id, "RETURNING *");
443
477
  }
444
478
  else {
479
+ // @ts-ignore
445
480
  this.row = this.existingEnt["data"];
446
481
  }
447
482
  }
@@ -450,20 +485,36 @@ class EditNodeOperation {
450
485
  }
451
486
  }
452
487
  reloadRow(queryer, id, options) {
488
+ // TODO this isn't always an ObjectLoader. should throw or figure out a way to get query
489
+ // and run this on its own...
490
+ const loader = this.options.loadEntOptions.loaderFactory.createLoader(options.context);
491
+ const opts = loader.getOptions();
492
+ let cls = clause.Eq(options.key, id);
493
+ if (opts.clause) {
494
+ let optionClause;
495
+ if (typeof opts.clause === "function") {
496
+ optionClause = opts.clause();
497
+ }
498
+ else {
499
+ optionClause = opts.clause;
500
+ }
501
+ if (optionClause) {
502
+ cls = clause.And(optionClause, cls);
503
+ }
504
+ }
453
505
  const query = buildQuery({
454
- fields: ["*"],
506
+ fields: opts.fields.length ? opts.fields : ["*"],
455
507
  tableName: options.tableName,
456
- clause: clause.Eq(options.key, id),
508
+ clause: cls,
457
509
  });
458
510
  // special case log here because we're not going through any of the normal
459
511
  // methods here because those are async and this is sync
460
512
  // this is the only place we're doing this so only handling here
461
513
  logQuery(query, [id]);
462
514
  const r = queryer.querySync(query, [id]);
463
- if (r.rows.length !== 1) {
464
- throw new Error(`couldn't reload row for ${id}`);
515
+ if (r.rows.length === 1) {
516
+ this.row = r.rows[0];
465
517
  }
466
- this.row = r.rows[0];
467
518
  }
468
519
  performWriteSync(queryer, context) {
469
520
  let options = {
@@ -476,6 +527,7 @@ class EditNodeOperation {
476
527
  this.reloadRow(queryer, this.existingEnt.id, options);
477
528
  }
478
529
  else {
530
+ // @ts-ignore
479
531
  this.row = this.existingEnt["data"];
480
532
  }
481
533
  }
@@ -492,7 +544,7 @@ class EditNodeOperation {
492
544
  if (!this.row) {
493
545
  return null;
494
546
  }
495
- return new this.options.ent(viewer, this.row);
547
+ return new this.options.loadEntOptions.ent(viewer, this.row);
496
548
  }
497
549
  }
498
550
  exports.EditNodeOperation = EditNodeOperation;
@@ -1146,20 +1198,19 @@ async function applyPrivacyPolicyForRow(viewer, options, row) {
1146
1198
  return null;
1147
1199
  }
1148
1200
  const ent = new options.ent(viewer, row);
1149
- return await applyPrivacyPolicyForEnt(viewer, ent);
1201
+ return await applyPrivacyPolicyForEnt(viewer, ent, row, options);
1150
1202
  }
1151
1203
  exports.applyPrivacyPolicyForRow = applyPrivacyPolicyForRow;
1152
1204
  async function applyPrivacyPolicyForRowX(viewer, options, row) {
1153
1205
  const ent = new options.ent(viewer, row);
1154
- return await applyPrivacyPolicyForEntX(viewer, ent);
1206
+ return await applyPrivacyPolicyForEntX(viewer, ent, row, options);
1155
1207
  }
1156
1208
  exports.applyPrivacyPolicyForRowX = applyPrivacyPolicyForRowX;
1157
1209
  async function applyPrivacyPolicyForRows(viewer, rows, options) {
1158
1210
  let m = new Map();
1159
1211
  // apply privacy logic
1160
1212
  await Promise.all(rows.map(async (row) => {
1161
- const ent = new options.ent(viewer, row);
1162
- let privacyEnt = await applyPrivacyPolicyForEnt(viewer, ent);
1213
+ let privacyEnt = await applyPrivacyPolicyForRow(viewer, options, row);
1163
1214
  if (privacyEnt) {
1164
1215
  m.set(privacyEnt.id, privacyEnt);
1165
1216
  }
@@ -1,10 +1,10 @@
1
1
  import { ID, Context, Loader, LoaderFactory } from "../base";
2
2
  export declare class AssocEdgeCountLoader implements Loader<ID, number> {
3
3
  private edgeType;
4
- context?: Context | undefined;
4
+ context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined;
5
5
  private loaderFn;
6
6
  private loader;
7
- constructor(edgeType: string, context?: Context | undefined);
7
+ constructor(edgeType: string, context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined);
8
8
  private getLoader;
9
9
  load(id: ID): Promise<number>;
10
10
  clearAll(): void;
@@ -20,8 +20,8 @@ export declare class AssocDirectEdgeLoader<T extends AssocEdge> implements Loade
20
20
  private edgeType;
21
21
  private edgeCtr;
22
22
  private options?;
23
- context?: Context | undefined;
24
- constructor(edgeType: string, edgeCtr: AssocEdgeConstructor<T>, options?: Partial<Pick<import("../base").QueryableDataOptions, "limit" | "orderby" | "clause">> | undefined, context?: Context | undefined);
23
+ context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined;
24
+ constructor(edgeType: string, edgeCtr: AssocEdgeConstructor<T>, options?: Partial<Pick<import("../base").QueryableDataOptions, "limit" | "orderby" | "clause">> | undefined, context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined);
25
25
  load(id: ID): Promise<T[]>;
26
26
  loadEdgeForID2(id: ID, id2: ID): Promise<T | undefined>;
27
27
  clearAll(): void;
@@ -32,7 +32,7 @@ export declare class AssocEdgeLoaderFactory<T extends AssocEdge> implements Load
32
32
  name: string;
33
33
  constructor(edgeType: string, edgeCtr: AssocEdgeConstructor<T> | (() => AssocEdgeConstructor<T>));
34
34
  createLoader(context?: Context): AssocLoader<T>;
35
- private isFunction;
35
+ private isConstructor;
36
36
  createConfigurableLoader(options: EdgeQueryableDataOptions, context?: Context): AssocLoader<T>;
37
37
  }
38
38
  export {};
@@ -161,16 +161,17 @@ class AssocEdgeLoaderFactory {
161
161
  createLoader(context) {
162
162
  return this.createConfigurableLoader({}, context);
163
163
  }
164
- isFunction(edgeCtr) {
165
- // not constructor
166
- return !(edgeCtr.prototype && edgeCtr.prototype.constructor === edgeCtr);
164
+ isConstructor(edgeCtr) {
165
+ return (edgeCtr.prototype &&
166
+ edgeCtr.prototype.constructor &&
167
+ edgeCtr.prototype.constructor.name.length > 0);
167
168
  }
168
169
  createConfigurableLoader(options, context) {
169
170
  let edgeCtr = this.edgeCtr;
170
171
  // in generated code, the edge is not necessarily defined at the time of loading
171
172
  // so we call this as follows:
172
173
  // const loader = new AssocEdgeLoaderFactory(EdgeType.Foo, ()=>DerivedEdgeClass);
173
- if (this.isFunction(edgeCtr)) {
174
+ if (!this.isConstructor(edgeCtr)) {
174
175
  edgeCtr = edgeCtr();
175
176
  }
176
177
  // rename to make TS happy
@@ -4,6 +4,7 @@ exports.IndexLoaderFactory = void 0;
4
4
  const query_loader_1 = require("./query_loader");
5
5
  // we're keeping this for legacy reasons so as to not break existing callers
6
6
  // and to decouple the change here but all callers can safely be changed here to use QueryLoaderFactory
7
+ // @deprecated use QueryLoaderFactory
7
8
  class IndexLoaderFactory {
8
9
  constructor(options, col, opts) {
9
10
  this.factory = new query_loader_1.QueryLoaderFactory({
@@ -1,23 +1,28 @@
1
- import { Data, SelectDataOptions, Context, Loader, LoaderFactory } from "../base";
1
+ import { ID, Data, SelectDataOptions, Context, Loader, LoaderFactory } from "../base";
2
2
  export declare class ObjectLoader<T> implements Loader<T, Data | null> {
3
3
  private options;
4
- context?: Context | undefined;
4
+ context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined;
5
5
  private toPrime?;
6
6
  private loader;
7
7
  private primedLoaders;
8
8
  private memoizedInitPrime;
9
- constructor(options: SelectDataOptions, context?: Context | undefined, toPrime?: ObjectLoaderFactory<T>[] | undefined);
9
+ constructor(options: SelectDataOptions, context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined, toPrime?: ObjectLoaderFactory<T>[] | undefined);
10
+ getOptions(): SelectDataOptions;
10
11
  private initPrime;
11
12
  load(key: T): Promise<Data | null>;
12
13
  clearAll(): void;
13
14
  loadMany(keys: T[]): Promise<Data[]>;
14
15
  prime(data: Data): void;
15
16
  }
17
+ interface ObjectLoaderOptions extends SelectDataOptions {
18
+ instanceKey?: string;
19
+ }
16
20
  export declare class ObjectLoaderFactory<T> implements LoaderFactory<T, Data | null> {
17
- options: SelectDataOptions;
21
+ options: ObjectLoaderOptions;
18
22
  name: string;
19
23
  private toPrime;
20
- constructor(options: SelectDataOptions);
24
+ constructor(options: ObjectLoaderOptions);
21
25
  createLoader(context?: Context): ObjectLoader<T>;
22
26
  addToPrime(factory: ObjectLoaderFactory<T>): void;
23
27
  }
28
+ export {};
@@ -29,6 +29,9 @@ const clause = __importStar(require("../clause"));
29
29
  const logger_1 = require("../logger");
30
30
  const loader_1 = require("./loader");
31
31
  const memoizee_1 = __importDefault(require("memoizee"));
32
+ // optional clause...
33
+ // so ObjectLoaderFactory and createDataLoader need to take a new optional field which is a clause that's always added here
34
+ // and we need a disableTransform which skips loader completely and uses loadRow...
32
35
  function createDataLoader(options) {
33
36
  const loaderOptions = {};
34
37
  // if query logging is enabled, we should log what's happening with loader
@@ -40,9 +43,22 @@ function createDataLoader(options) {
40
43
  return [];
41
44
  }
42
45
  let col = options.key;
46
+ let cls = clause.In(col, ...ids);
47
+ if (options.clause) {
48
+ let optionClause;
49
+ if (typeof options.clause === "function") {
50
+ optionClause = options.clause();
51
+ }
52
+ else {
53
+ optionClause = options.clause;
54
+ }
55
+ if (optionClause) {
56
+ cls = clause.And(optionClause, cls);
57
+ }
58
+ }
43
59
  const rowOptions = {
44
60
  ...options,
45
- clause: clause.In(col, ...ids),
61
+ clause: cls,
46
62
  };
47
63
  let m = new Map();
48
64
  let result = [];
@@ -77,6 +93,9 @@ class ObjectLoader {
77
93
  }
78
94
  this.memoizedInitPrime = (0, memoizee_1.default)(this.initPrime.bind(this));
79
95
  }
96
+ getOptions() {
97
+ return this.options;
98
+ }
80
99
  initPrime() {
81
100
  if (!this.context || !this.toPrime) {
82
101
  return;
@@ -107,9 +126,22 @@ class ObjectLoader {
107
126
  }
108
127
  return result;
109
128
  }
129
+ let cls = clause.Eq(this.options.key, key);
130
+ if (this.options.clause) {
131
+ let optionClause;
132
+ if (typeof this.options.clause === "function") {
133
+ optionClause = this.options.clause();
134
+ }
135
+ else {
136
+ optionClause = this.options.clause;
137
+ }
138
+ if (optionClause) {
139
+ cls = clause.And(optionClause, cls);
140
+ }
141
+ }
110
142
  const rowOptions = {
111
143
  ...this.options,
112
- clause: clause.Eq(this.options.key, key),
144
+ clause: cls,
113
145
  context: this.context,
114
146
  };
115
147
  return await (0, ent_1.loadRow)(rowOptions);
@@ -121,9 +153,22 @@ class ObjectLoader {
121
153
  if (this.loader) {
122
154
  return await this.loader.loadMany(keys);
123
155
  }
156
+ let cls = clause.In(this.options.key, ...keys);
157
+ if (this.options.clause) {
158
+ let optionClause;
159
+ if (typeof this.options.clause === "function") {
160
+ optionClause = this.options.clause();
161
+ }
162
+ else {
163
+ optionClause = this.options.clause;
164
+ }
165
+ if (optionClause) {
166
+ cls = clause.And(optionClause, cls);
167
+ }
168
+ }
124
169
  const rowOptions = {
125
170
  ...this.options,
126
- clause: clause.In(this.options.key, ...keys),
171
+ clause: cls,
127
172
  context: this.context,
128
173
  };
129
174
  return await (0, ent_1.loadRows)(rowOptions);
@@ -142,7 +187,17 @@ class ObjectLoaderFactory {
142
187
  constructor(options) {
143
188
  this.options = options;
144
189
  this.toPrime = [];
145
- this.name = `${options.tableName}:${options.key}`;
190
+ // we don't wanna do it here because we want it to be delayed
191
+ let instanceKey = "";
192
+ if (typeof this.options.clause === "function") {
193
+ if (!options.instanceKey) {
194
+ throw new Error(`need to pass an instanceKey to ObjectLoader if clause is a function`);
195
+ }
196
+ }
197
+ else if (this.options.clause) {
198
+ instanceKey = this.options.clause.instanceKey();
199
+ }
200
+ this.name = `${options.tableName}:${options.key}:${instanceKey}`;
146
201
  }
147
202
  createLoader(context) {
148
203
  return (0, loader_1.getLoader)(this, () => {
@@ -10,12 +10,12 @@ export declare class QueryDirectLoader<K extends any> implements Loader<K, Data[
10
10
  }
11
11
  export declare class QueryLoader<K extends any> implements Loader<K, Data[]> {
12
12
  private options;
13
- context?: Context | undefined;
13
+ context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined;
14
14
  private queryOptions?;
15
15
  private loader;
16
16
  private primedLoaders;
17
17
  private memoizedInitPrime;
18
- constructor(options: QueryOptions, context?: Context | undefined, queryOptions?: Partial<Pick<import("../base").QueryableDataOptions, "limit" | "orderby" | "clause">> | undefined);
18
+ constructor(options: QueryOptions, context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined, queryOptions?: Partial<Pick<import("../base").QueryableDataOptions, "limit" | "orderby" | "clause">> | undefined);
19
19
  private initPrime;
20
20
  load(id: K): Promise<Data[]>;
21
21
  clearAll(): void;
@@ -9,9 +9,9 @@ interface QueryCountOptions {
9
9
  export declare function createCountDataLoader<K extends any>(options: QueryCountOptions): DataLoader<K, number, K>;
10
10
  export declare class RawCountLoader<K extends any> implements Loader<K, number> {
11
11
  private options;
12
- context?: Context | undefined;
12
+ context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined;
13
13
  private loader;
14
- constructor(options: QueryCountOptions, context?: Context | undefined);
14
+ constructor(options: QueryCountOptions, context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined);
15
15
  load(id: K): Promise<number>;
16
16
  clearAll(): void;
17
17
  }
package/core/privacy.d.ts CHANGED
@@ -6,22 +6,22 @@ export declare class EntPrivacyError extends Error implements PrivacyError {
6
6
  constructor(privacyPolicy: PrivacyPolicy, rule: PrivacyPolicyRule, ent?: Ent);
7
7
  }
8
8
  export declare const AlwaysAllowRule: {
9
- apply(_v: Viewer, _ent?: Ent | undefined): Promise<PrivacyResult>;
9
+ apply(_v: Viewer, _ent?: Ent<Viewer<Ent<any> | null, ID | null>> | undefined): Promise<PrivacyResult>;
10
10
  };
11
11
  export declare const AlwaysDenyRule: {
12
- apply(_v: Viewer, _ent?: Ent | undefined): Promise<PrivacyResult>;
12
+ apply(_v: Viewer, _ent?: Ent<Viewer<Ent<any> | null, ID | null>> | undefined): Promise<PrivacyResult>;
13
13
  };
14
14
  export declare const DenyIfLoggedOutRule: {
15
- apply(v: Viewer, _ent?: Ent | undefined): Promise<PrivacyResult>;
15
+ apply(v: Viewer, _ent?: Ent<Viewer<Ent<any> | null, ID | null>> | undefined): Promise<PrivacyResult>;
16
16
  };
17
17
  export declare const DenyIfLoggedInRule: {
18
- apply(v: Viewer, _ent?: Ent | undefined): Promise<PrivacyResult>;
18
+ apply(v: Viewer, _ent?: Ent<Viewer<Ent<any> | null, ID | null>> | undefined): Promise<PrivacyResult>;
19
19
  };
20
20
  export declare const AllowIfHasIdentity: {
21
- apply(v: Viewer, _ent?: Ent | undefined): Promise<PrivacyResult>;
21
+ apply(v: Viewer, _ent?: Ent<Viewer<Ent<any> | null, ID | null>> | undefined): Promise<PrivacyResult>;
22
22
  };
23
23
  export declare const AllowIfViewerRule: {
24
- apply(v: Viewer, ent?: Ent | undefined): Promise<PrivacyResult>;
24
+ apply(v: Viewer, ent?: Ent<Viewer<Ent<any> | null, ID | null>> | undefined): Promise<PrivacyResult>;
25
25
  };
26
26
  export declare class AllowIfViewerEqualsRule {
27
27
  private id;
@@ -71,45 +71,45 @@ export declare class DenyIfEntPropertyIsRule<T extends Ent> implements PrivacyPo
71
71
  constructor(property: keyof T, val: any);
72
72
  apply(v: Viewer, ent?: T): Promise<PrivacyResult>;
73
73
  }
74
- export declare class AllowIfEntIsVisibleRule<T extends Ent> implements PrivacyPolicyRule {
74
+ export declare class AllowIfEntIsVisibleRule<TEnt extends Ent<TViewer>, TViewer extends Viewer> implements PrivacyPolicyRule {
75
75
  private id;
76
76
  private options;
77
- constructor(id: ID, options: LoadEntOptions<T>);
78
- apply(v: Viewer, _ent?: Ent): Promise<PrivacyResult>;
77
+ constructor(id: ID, options: LoadEntOptions<TEnt, TViewer>);
78
+ apply(v: TViewer, _ent?: Ent): Promise<PrivacyResult>;
79
79
  }
80
- export declare class AllowIfEntIsNotVisibleRule<T extends Ent> implements PrivacyPolicyRule {
80
+ export declare class AllowIfEntIsNotVisibleRule<TEnt extends Ent<TViewer>, TViewer extends Viewer> implements PrivacyPolicyRule {
81
81
  private id;
82
82
  private options;
83
- constructor(id: ID, options: LoadEntOptions<T>);
84
- apply(v: Viewer, _ent?: Ent): Promise<PrivacyResult>;
83
+ constructor(id: ID, options: LoadEntOptions<TEnt, TViewer>);
84
+ apply(v: TViewer, _ent?: Ent): Promise<PrivacyResult>;
85
85
  }
86
- export declare class AllowIfEntIsVisiblePolicy<T extends Ent> implements PrivacyPolicy {
86
+ export declare class AllowIfEntIsVisiblePolicy<TEnt extends Ent<TViewer>, TViewer extends Viewer> implements PrivacyPolicy<TEnt, TViewer> {
87
87
  private id;
88
88
  private options;
89
- constructor(id: ID, options: LoadEntOptions<T>);
89
+ constructor(id: ID, options: LoadEntOptions<TEnt, TViewer>);
90
90
  rules: {
91
- apply(_v: Viewer, _ent?: Ent | undefined): Promise<PrivacyResult>;
91
+ apply(_v: Viewer<Ent<any> | null, ID | null>, _ent?: Ent<Viewer<Ent<any> | null, ID | null>> | undefined): Promise<PrivacyResult>;
92
92
  }[];
93
93
  }
94
- export declare class DenyIfEntIsVisiblePolicy<T extends Ent> implements PrivacyPolicy {
94
+ export declare class DenyIfEntIsVisiblePolicy<TEnt extends Ent<TViewer>, TViewer extends Viewer> implements PrivacyPolicy<TEnt, TViewer> {
95
95
  private id;
96
96
  private options;
97
- constructor(id: ID, options: LoadEntOptions<T>);
97
+ constructor(id: ID, options: LoadEntOptions<TEnt, TViewer>);
98
98
  rules: {
99
- apply(_v: Viewer, _ent?: Ent | undefined): Promise<PrivacyResult>;
99
+ apply(_v: Viewer<Ent<any> | null, ID | null>, _ent?: Ent<Viewer<Ent<any> | null, ID | null>> | undefined): Promise<PrivacyResult>;
100
100
  }[];
101
101
  }
102
- export declare class DenyIfEntIsVisibleRule<T extends Ent> implements PrivacyPolicyRule {
102
+ export declare class DenyIfEntIsVisibleRule<TEnt extends Ent<TViewer>, TViewer extends Viewer> implements PrivacyPolicyRule<TEnt, TViewer> {
103
103
  private id;
104
104
  private options;
105
- constructor(id: ID, options: LoadEntOptions<T>);
106
- apply(v: Viewer, _ent?: Ent): Promise<PrivacyResult>;
105
+ constructor(id: ID, options: LoadEntOptions<TEnt, TViewer>);
106
+ apply(v: TViewer, _ent?: Ent): Promise<PrivacyResult>;
107
107
  }
108
- export declare class DenyIfEntIsNotVisibleRule<T extends Ent> implements PrivacyPolicyRule {
108
+ export declare class DenyIfEntIsNotVisibleRule<TEnt extends Ent<TViewer>, TViewer extends Viewer> implements PrivacyPolicyRule {
109
109
  private id;
110
110
  private options;
111
- constructor(id: ID, options: LoadEntOptions<T>);
112
- apply(v: Viewer, _ent?: Ent): Promise<PrivacyResult>;
111
+ constructor(id: ID, options: LoadEntOptions<TEnt, TViewer>);
112
+ apply(v: TViewer, _ent?: Ent): Promise<PrivacyResult>;
113
113
  }
114
114
  export declare class AllowIfEdgeExistsRule implements PrivacyPolicyRule {
115
115
  private id1;
@@ -121,7 +121,7 @@ export declare class AllowIfEdgeExistsRule implements PrivacyPolicyRule {
121
121
  export declare class AllowIfViewerInboundEdgeExistsRule implements PrivacyPolicyRule {
122
122
  private edgeType;
123
123
  constructor(edgeType: string);
124
- apply(v: Viewer, ent: Ent): Promise<PrivacyResult>;
124
+ apply(v: Viewer, ent?: Ent): Promise<PrivacyResult>;
125
125
  }
126
126
  export declare class AllowIfViewerOutboundEdgeExistsRule implements PrivacyPolicyRule {
127
127
  private edgeType;
package/core/privacy.js CHANGED
@@ -464,6 +464,9 @@ async function applyPrivacyPolicyX(v, policy, ent, throwErr) {
464
464
  if (res.error) {
465
465
  throw res.error;
466
466
  }
467
+ if (res.getError) {
468
+ throw res.getError(policy, rule, ent);
469
+ }
467
470
  if (throwErr) {
468
471
  throw throwErr();
469
472
  }
@@ -3,15 +3,15 @@ import { AssocEdge } from "../ent";
3
3
  import { AssocEdgeCountLoaderFactory } from "../loaders/assoc_count_loader";
4
4
  import { AssocEdgeLoaderFactory } from "../loaders/assoc_edge_loader";
5
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> {
9
- viewer: Viewer;
10
- src: EdgeQuerySource<TSource, TDest>;
6
+ export declare type EdgeQuerySource<TSource extends Ent<TViewer>, TDest extends Ent<TViewer> = Ent<any>, TViewer extends Viewer = Viewer> = TSource | TSource[] | ID | ID[] | EdgeQuery<TDest, Ent, AssocEdge>;
7
+ declare type loaderOptionsFunc<TViewer extends Viewer> = (type: string) => LoadEntOptions<Ent, TViewer>;
8
+ export declare abstract class AssocEdgeQueryBase<TSource extends Ent<TViewer>, TDest extends Ent<TViewer>, TEdge extends AssocEdge, TViewer extends Viewer = Viewer> extends BaseEdgeQuery<TSource, TDest, TEdge> implements EdgeQuery<TSource, TDest, TEdge> {
9
+ viewer: TViewer;
10
+ src: EdgeQuerySource<TSource, TDest, TViewer>;
11
11
  private countLoaderFactory;
12
12
  private dataLoaderFactory;
13
13
  private options;
14
- constructor(viewer: Viewer, src: EdgeQuerySource<TSource, TDest>, countLoaderFactory: AssocEdgeCountLoaderFactory, dataLoaderFactory: AssocEdgeLoaderFactory<TEdge>, options: LoadEntOptions<TDest> | loaderOptionsFunc);
14
+ constructor(viewer: TViewer, src: EdgeQuerySource<TSource, TDest, TViewer>, countLoaderFactory: AssocEdgeCountLoaderFactory, dataLoaderFactory: AssocEdgeLoaderFactory<TEdge>, options: LoadEntOptions<TDest, TViewer> | loaderOptionsFunc<TViewer>);
15
15
  private isEdgeQuery;
16
16
  abstract sourceEnt(id: ID): Promise<Ent | null>;
17
17
  private getSingleID;
@@ -1,17 +1,17 @@
1
1
  import { Data, Ent, ID, EdgeQueryableDataOptions, LoadEntOptions, Viewer, LoaderFactory, ConfigurableLoaderFactory } from "../base";
2
2
  import { BaseEdgeQuery, IDInfo, EdgeQuery } from "./query";
3
- export interface CustomEdgeQueryOptions<TSource extends Ent, TDest extends Ent> {
3
+ export interface CustomEdgeQueryOptions<TSource extends Ent<TViewer>, TDest extends Ent<TViewer>, TViewer extends Viewer = Viewer> {
4
4
  src: TSource | ID;
5
5
  countLoaderFactory: LoaderFactory<ID, number>;
6
6
  dataLoaderFactory: ConfigurableLoaderFactory<ID, Data[]>;
7
- options: LoadEntOptions<TDest>;
7
+ options: LoadEntOptions<TDest, TViewer>;
8
8
  sortColumn?: string;
9
9
  }
10
- export declare abstract class CustomEdgeQueryBase<TSource extends Ent, TDest extends Ent> extends BaseEdgeQuery<TSource, TDest, Data> implements EdgeQuery<TSource, TDest, Data> {
11
- viewer: Viewer;
10
+ export declare abstract class CustomEdgeQueryBase<TSource extends Ent<TViewer>, TDest extends Ent<TViewer>, TViewer extends Viewer = Viewer> extends BaseEdgeQuery<TSource, TDest, Data> implements EdgeQuery<TSource, TDest, Data> {
11
+ viewer: TViewer;
12
12
  private options;
13
13
  private id;
14
- constructor(viewer: Viewer, options: CustomEdgeQueryOptions<TSource, TDest>);
14
+ constructor(viewer: TViewer, options: CustomEdgeQueryOptions<TSource, TDest, TViewer>);
15
15
  abstract sourceEnt(id: ID): Promise<Ent | null>;
16
16
  private idVisible;
17
17
  queryRawCount(): Promise<number>;
@@ -41,7 +41,7 @@ export declare abstract class BaseEdgeQuery<TSource extends Ent, TDest extends E
41
41
  private idMap;
42
42
  private idsToFetch;
43
43
  constructor(viewer: Viewer, sortCol: string);
44
- getPrivacyPolicy(): PrivacyPolicy<Ent>;
44
+ getPrivacyPolicy(): PrivacyPolicy<Ent<Viewer<Ent<any> | null, ID | null>>, Viewer<Ent<any> | null, ID | null>>;
45
45
  abstract sourceEnt(id: ID): Promise<Ent | null>;
46
46
  first(n: number, after?: string): this;
47
47
  last(n: number, before?: string): this;
package/core/viewer.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ID, Ent, Viewer, Context } from "./base";
2
2
  export declare class LoggedOutViewer implements Viewer {
3
- context?: Context | undefined;
4
- constructor(context?: Context | undefined);
3
+ context?: Context<Viewer<Ent<any> | null, ID | null>> | undefined;
4
+ constructor(context?: Context<Viewer<Ent<any> | null, ID | null>> | undefined);
5
5
  viewerID: null;
6
6
  viewer(): Promise<null>;
7
7
  instanceKey(): string;
@@ -17,6 +17,7 @@ export declare class IDViewer implements Viewer {
17
17
  context?: Context;
18
18
  constructor(viewerID: ID, opts?: Partial<IDViewerOptions>);
19
19
  constructor(opts: IDViewerOptions);
20
- viewer(): Promise<Ent | null>;
20
+ setContext(ctx: Context): this;
21
+ viewer(): Promise<Ent<Viewer<Ent<any> | null, ID | null>> | null>;
21
22
  instanceKey(): string;
22
23
  }