@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
@@ -5,6 +5,7 @@ const ent_1 = require("../core/ent");
5
5
  const schema_1 = require("../schema/schema");
6
6
  const action_1 = require("../action");
7
7
  const snake_case_1 = require("snake-case");
8
+ const camel_case_1 = require("camel-case");
8
9
  const privacy_1 = require("../core/privacy");
9
10
  const executor_1 = require("./executor");
10
11
  const logger_1 = require("../core/logger");
@@ -58,6 +59,8 @@ class Orchestrator {
58
59
  this.changesets = [];
59
60
  this.dependencies = new Map();
60
61
  this.fieldsToResolve = [];
62
+ this.defaultFieldsByFieldName = {};
63
+ this.defaultFieldsByTSName = {};
61
64
  this.viewer = options.viewer;
62
65
  }
63
66
  addEdge(edge, op) {
@@ -143,6 +146,8 @@ class Orchestrator {
143
146
  tableName: this.options.tableName,
144
147
  fieldsToResolve: this.fieldsToResolve,
145
148
  key: this.options.key,
149
+ ent: this.options.loaderOptions.ent,
150
+ placeholderID: this.options.builder.placeholderID,
146
151
  };
147
152
  if (this.logValues) {
148
153
  opts.fieldsToLog = this.logValues;
@@ -188,7 +193,7 @@ class Orchestrator {
188
193
  throw new Error("could not find an edge operation from the given parameters");
189
194
  }
190
195
  async buildEdgeOps(ops) {
191
- const edgeDatas = await ent_1.loadEdgeDatas(...Array.from(this.edgeSet.values()));
196
+ const edgeDatas = await (0, ent_1.loadEdgeDatas)(...Array.from(this.edgeSet.values()));
192
197
  for (const [edgeType, m] of this.edges) {
193
198
  for (const [op, m2] of m) {
194
199
  for (const [_, edge] of m2) {
@@ -222,53 +227,65 @@ class Orchestrator {
222
227
  }
223
228
  return new EntCannotDeleteEntError(privacyPolicy, action, this.options.builder.existingEnt);
224
229
  }
230
+ getEntForPrivacyPolicy(editedData) {
231
+ if (this.options.operation !== action_1.WriteOperation.Insert) {
232
+ return this.options.builder.existingEnt;
233
+ }
234
+ // we create an unsafe ent to be used for privacy policies
235
+ return new this.options.builder.ent(this.options.builder.viewer, editedData);
236
+ }
225
237
  async validate() {
238
+ // existing ent required for edit or delete operations
239
+ switch (this.options.operation) {
240
+ case action_1.WriteOperation.Delete:
241
+ case action_1.WriteOperation.Edit:
242
+ if (!this.options.builder.existingEnt) {
243
+ throw new Error("existing ent required with operation");
244
+ }
245
+ }
226
246
  const action = this.options.action;
227
- let privacyPolicy = action?.getPrivacyPolicy();
228
247
  const builder = this.options.builder;
229
- let promises = [];
248
+ // future optimization: can get schemaFields to memoize based on different values
249
+ const schemaFields = (0, schema_1.getFields)(this.options.schema);
250
+ let editedData = this.getFieldsWithDefaultValues(builder, schemaFields, action);
251
+ // this runs in following phases:
252
+ // * set default fields and pass to builder so the value can be checked by triggers/observers/validators
253
+ // * privacy policy (use unsafe ent if we have it)
254
+ // * triggers
255
+ // * validators
256
+ let privacyPolicy = action?.getPrivacyPolicy();
230
257
  if (privacyPolicy) {
231
- promises.push(privacy_1.applyPrivacyPolicyX(this.options.viewer, privacyPolicy, builder.existingEnt, this.throwError.bind(this)));
258
+ await (0, privacy_1.applyPrivacyPolicyX)(this.options.viewer, privacyPolicy, this.getEntForPrivacyPolicy(editedData), this.throwError.bind(this));
232
259
  }
233
260
  // have to run triggers which update fields first before field and other validators
234
261
  // so running this first to build things up
235
262
  let triggers = action?.triggers;
236
263
  if (triggers) {
237
- let triggerPromises = [];
238
- triggers.forEach((trigger) => {
239
- let c = trigger.changeset(builder, action.getInput());
240
- if (c) {
241
- triggerPromises.push(c);
242
- }
243
- });
244
- // TODO right now trying to parallelize this with validateFields below
245
- // may need to run triggers first to be deterministic
246
- // TODO: see https://github.com/lolopinto/ent/pull/50
247
- promises.push(this.triggers(triggerPromises));
264
+ await this.triggers(action, builder, triggers);
248
265
  }
249
- promises.push(this.validateFields());
250
266
  let validators = action?.validators || [];
251
- if (validators) {
252
- promises.push(this.validators(validators, action, builder));
253
- }
254
- await Promise.all(promises);
255
- }
256
- async triggers(triggerPromises) {
257
- // keep changesets to use later
258
- let changesets = await Promise.all(triggerPromises.map(async (promise) => {
259
- if (Array.isArray(promise)) {
260
- return await Promise.all(promise);
267
+ await Promise.all([
268
+ this.formatAndValidateFields(schemaFields),
269
+ this.validators(validators, action, builder),
270
+ ]);
271
+ }
272
+ async triggers(action, builder, triggers) {
273
+ await Promise.all(triggers.map(async (trigger) => {
274
+ let ret = await trigger.changeset(builder, action.getInput());
275
+ if (Array.isArray(ret)) {
276
+ ret = await Promise.all(ret);
261
277
  }
262
- return await promise;
263
- }));
264
- changesets.forEach((c) => {
265
- if (Array.isArray(c)) {
266
- this.changesets.push(...c);
278
+ if (Array.isArray(ret)) {
279
+ for (const v of ret) {
280
+ if (typeof v === "object") {
281
+ this.changesets.push(v);
282
+ }
283
+ }
267
284
  }
268
- else if (c) {
269
- this.changesets.push(c);
285
+ else if (ret) {
286
+ this.changesets.push(ret);
270
287
  }
271
- });
288
+ }));
272
289
  }
273
290
  async validators(validators, action, builder) {
274
291
  let promises = [];
@@ -283,88 +300,157 @@ class Orchestrator {
283
300
  isBuilder(val) {
284
301
  return val.placeholderID !== undefined;
285
302
  }
286
- async validateFields() {
287
- // existing ent required for edit or delete operations
288
- switch (this.options.operation) {
289
- case action_1.WriteOperation.Delete:
290
- case action_1.WriteOperation.Edit:
291
- if (!this.options.builder.existingEnt) {
292
- throw new Error("existing ent required with operation");
293
- }
294
- }
295
- if (this.options.operation == action_1.WriteOperation.Delete) {
296
- return;
297
- }
303
+ getFieldsWithDefaultValues(builder, schemaFields, action) {
298
304
  const editedFields = this.options.editedFields();
299
- // build up data to be saved...
300
305
  let data = {};
301
- let logValues = {};
302
- const schemaFields = schema_1.getFields(this.options.schema);
306
+ let defaultData = {};
307
+ let input = action?.getInput() || {};
308
+ let updateInput = false;
303
309
  for (const [fieldName, field] of schemaFields) {
304
310
  let value = editedFields.get(fieldName);
305
- let dbKey = field.storageKey || snake_case_1.snakeCase(field.name);
311
+ let defaultValue = undefined;
312
+ let dbKey = field.storageKey || (0, snake_case_1.snakeCase)(field.name);
306
313
  if (value === undefined) {
307
- if (field.defaultValueOnCreate &&
308
- this.options.operation === action_1.WriteOperation.Insert) {
309
- value = field.defaultValueOnCreate();
314
+ if (this.options.operation === action_1.WriteOperation.Insert) {
315
+ if (field.defaultToViewerOnCreate && field.defaultValueOnCreate) {
316
+ throw new Error(`cannot set both defaultToViewerOnCreate and defaultValueOnCreate`);
317
+ }
318
+ if (field.defaultToViewerOnCreate) {
319
+ defaultValue = builder.viewer.viewerID;
320
+ }
321
+ if (field.defaultValueOnCreate) {
322
+ defaultValue = field.defaultValueOnCreate(builder, input);
323
+ if (defaultValue === undefined) {
324
+ throw new Error(`defaultValueOnCreate() returned undefined for field ${field.name}`);
325
+ }
326
+ }
310
327
  }
311
328
  if (field.defaultValueOnEdit &&
312
329
  this.options.operation === action_1.WriteOperation.Edit) {
313
- value = field.defaultValueOnEdit();
314
- // TODO special case this if this is the onlything changing and don't do the write.
330
+ defaultValue = field.defaultValueOnEdit(builder, input);
315
331
  }
316
332
  }
317
- if (value === null) {
318
- if (!field.nullable) {
319
- throw new Error(`field ${field.name} set to null for non-nullable field`);
320
- }
333
+ if (value !== undefined) {
334
+ data[dbKey] = value;
321
335
  }
322
- else if (value === undefined) {
323
- if (!field.nullable &&
324
- // required field can be skipped if server default set
325
- // not checking defaultValueOnCreate() or defaultValueOnEdit() as that's set above
326
- // not setting server default as we're depending on the database handling that.
327
- // server default allowed
328
- field.serverDefault === undefined &&
329
- this.options.operation === action_1.WriteOperation.Insert) {
330
- throw new Error(`required field ${field.name} not set`);
331
- }
336
+ if (defaultValue !== undefined) {
337
+ updateInput = true;
338
+ defaultData[dbKey] = defaultValue;
339
+ this.defaultFieldsByFieldName[fieldName] = defaultValue;
340
+ // TODO related to #510. we need this logic to be consistent so do this all in TypeScript or get it from go somehow
341
+ this.defaultFieldsByTSName[(0, camel_case_1.camelCase)(fieldName)] = defaultValue;
332
342
  }
333
- else if (this.isBuilder(value)) {
334
- let builder = value;
335
- // keep track of dependencies to resolve
336
- this.dependencies.set(builder.placeholderID, builder);
337
- // keep track of fields to resolve
338
- this.fieldsToResolve.push(dbKey);
343
+ }
344
+ // if there's data changing, add data
345
+ if (this.hasData(data)) {
346
+ data = {
347
+ ...data,
348
+ ...defaultData,
349
+ };
350
+ if (updateInput && this.options.updateInput) {
351
+ // this basically fixes #605. just needs to be exposed correctly
352
+ this.options.updateInput(this.defaultFieldsByTSName);
339
353
  }
340
- else {
341
- if (field.valid) {
342
- // TODO this could be async. handle this better
343
- let valid = await Promise.resolve(field.valid(value));
344
- if (!valid) {
345
- throw new Error(`invalid field ${field.name} with value ${value}`);
346
- }
354
+ }
355
+ return data;
356
+ }
357
+ hasData(data) {
358
+ for (const _k in data) {
359
+ return true;
360
+ }
361
+ return false;
362
+ }
363
+ async transformFieldValue(field, dbKey, value) {
364
+ // now format and validate...
365
+ if (value === null) {
366
+ if (!field.nullable) {
367
+ throw new Error(`field ${field.name} set to null for non-nullable field`);
368
+ }
369
+ }
370
+ else if (value === undefined) {
371
+ if (!field.nullable &&
372
+ // required field can be skipped if server default set
373
+ // not checking defaultValueOnCreate() or defaultValueOnEdit() as that's set above
374
+ // not setting server default as we're depending on the database handling that.
375
+ // server default allowed
376
+ field.serverDefault === undefined &&
377
+ this.options.operation === action_1.WriteOperation.Insert) {
378
+ throw new Error(`required field ${field.name} not set`);
379
+ }
380
+ }
381
+ else if (this.isBuilder(value)) {
382
+ if (field.valid) {
383
+ const valid = await Promise.resolve(field.valid(value));
384
+ if (!valid) {
385
+ throw new Error(`invalid field ${field.name} with value ${value}`);
347
386
  }
348
- if (field.format) {
349
- // TODO this could be async e.g. password. handle this better
350
- value = await Promise.resolve(field.format(value));
387
+ }
388
+ // keep track of dependencies to resolve
389
+ this.dependencies.set(value.placeholderID, value);
390
+ // keep track of fields to resolve
391
+ this.fieldsToResolve.push(dbKey);
392
+ }
393
+ else {
394
+ if (field.valid) {
395
+ // TODO this could be async. handle this better
396
+ const valid = await Promise.resolve(field.valid(value));
397
+ if (!valid) {
398
+ throw new Error(`invalid field ${field.name} with value ${value}`);
351
399
  }
352
400
  }
401
+ if (field.format) {
402
+ // TODO this could be async e.g. password. handle this better
403
+ value = await Promise.resolve(field.format(value));
404
+ }
405
+ }
406
+ return value;
407
+ }
408
+ async formatAndValidateFields(schemaFields) {
409
+ const op = this.options.operation;
410
+ if (op === action_1.WriteOperation.Delete) {
411
+ return;
412
+ }
413
+ const editedFields = this.options.editedFields();
414
+ // build up data to be saved...
415
+ let data = {};
416
+ let logValues = {};
417
+ for (const [fieldName, field] of schemaFields) {
418
+ let value = editedFields.get(fieldName);
419
+ if (value === undefined && op === action_1.WriteOperation.Insert) {
420
+ // null allowed
421
+ value = this.defaultFieldsByFieldName[fieldName];
422
+ }
423
+ let dbKey = field.storageKey || (0, snake_case_1.snakeCase)(field.name);
424
+ value = await this.transformFieldValue(field, dbKey, value);
353
425
  if (value !== undefined) {
354
426
  data[dbKey] = value;
355
427
  logValues[dbKey] = field.logValue(value);
356
428
  }
357
429
  }
430
+ // we ignored default values while editing.
431
+ // if we're editing and there's data, add default values
432
+ if (op === action_1.WriteOperation.Edit && this.hasData(data)) {
433
+ for (const fieldName in this.defaultFieldsByFieldName) {
434
+ const defaultValue = this.defaultFieldsByFieldName[fieldName];
435
+ let field = schemaFields.get(fieldName);
436
+ let dbKey = field.storageKey || (0, snake_case_1.snakeCase)(field.name);
437
+ // no value, let's just default
438
+ if (data[dbKey] === undefined) {
439
+ const value = await this.transformFieldValue(field, dbKey, defaultValue);
440
+ data[dbKey] = value;
441
+ logValues[dbKey] = field.logValue(value);
442
+ }
443
+ }
444
+ }
358
445
  this.validatedFields = data;
359
446
  this.logValues = logValues;
360
- // console.log(this.validatedFields);
361
447
  }
362
448
  async valid() {
363
449
  try {
364
450
  await this.validate();
365
451
  }
366
452
  catch (e) {
367
- logger_1.log("error", e);
453
+ (0, logger_1.log)("error", e);
368
454
  return false;
369
455
  }
370
456
  return true;
@@ -377,7 +463,6 @@ class Orchestrator {
377
463
  await this.validX();
378
464
  let ops = [this.buildMainOp()];
379
465
  await this.buildEdgeOps(ops);
380
- // console.log("post build");
381
466
  return new EntChangeset(this.options.viewer, this.options.builder.placeholderID, this.options.loaderOptions.ent, ops, this.dependencies, this.changesets, this.options);
382
467
  }
383
468
  async viewerForEntLoad(data) {
@@ -385,11 +470,11 @@ class Orchestrator {
385
470
  if (!action || !action.viewerForEntLoad) {
386
471
  return this.options.viewer;
387
472
  }
388
- return await action.viewerForEntLoad(data);
473
+ return action.viewerForEntLoad(data);
389
474
  }
390
475
  async returnedRow() {
391
- if (this.mainOp && this.mainOp.returnedEntRow) {
392
- return this.mainOp.returnedEntRow();
476
+ if (this.mainOp && this.mainOp.returnedRow) {
477
+ return this.mainOp.returnedRow();
393
478
  }
394
479
  return null;
395
480
  }
@@ -399,7 +484,7 @@ class Orchestrator {
399
484
  return null;
400
485
  }
401
486
  const viewer = await this.viewerForEntLoad(row);
402
- return await ent_1.applyPrivacyPolicyForRow(viewer, this.options.loaderOptions, row);
487
+ return (0, ent_1.applyPrivacyPolicyForRow)(viewer, this.options.loaderOptions, row);
403
488
  }
404
489
  async editedEntX() {
405
490
  const row = await this.returnedRow();
@@ -407,7 +492,7 @@ class Orchestrator {
407
492
  throw new Error(`ent was not created`);
408
493
  }
409
494
  const viewer = await this.viewerForEntLoad(row);
410
- const ent = await ent_1.applyPrivacyPolicyForRow(viewer, this.options.loaderOptions, row);
495
+ const ent = await (0, ent_1.applyPrivacyPolicyForRow)(viewer, this.options.loaderOptions, row);
411
496
  if (!ent) {
412
497
  if (this.options.operation == action_1.WriteOperation.Insert) {
413
498
  throw new Error(`was able to create ent but not load it`);
@@ -431,13 +516,17 @@ class EntChangeset {
431
516
  this.options = options;
432
517
  }
433
518
  executor() {
434
- // TODO: write comment here similar to go
435
- // if we have dependencies but no changesets, we just need a simple
436
- // executor and depend on something else in the stack to handle this correctly
437
- if (this.changesets?.length) {
438
- return new executor_1.ComplexExecutor(this.viewer, this.placeholderID, this.ent, this.operations, this.dependencies, this.changesets, this.options);
519
+ if (this._executor) {
520
+ return this._executor;
521
+ }
522
+ if (!this.changesets?.length) {
523
+ // if we have dependencies but no changesets, we just need a simple
524
+ // executor and depend on something else in the stack to handle this correctly
525
+ // ComplexExecutor which could be a parent of this should make sure the dependency
526
+ // is resolved beforehand
527
+ return (this._executor = new executor_1.ListBasedExecutor(this.viewer, this.placeholderID, this.operations, this.options));
439
528
  }
440
- return new executor_1.ListBasedExecutor(this.viewer, this.placeholderID, this.ent, this.operations, this.options);
529
+ return (this._executor = new executor_1.ComplexExecutor(this.viewer, this.placeholderID, this.operations, this.dependencies || new Map(), this.changesets || [], this.options));
441
530
  }
442
531
  }
443
532
  exports.EntChangeset = EntChangeset;
package/action/privacy.js CHANGED
@@ -11,9 +11,9 @@ class DenyIfBuilder {
11
11
  }
12
12
  async apply(_v, _ent) {
13
13
  if (this.id && isBuilder(this.id)) {
14
- return base_1.Deny();
14
+ return (0, base_1.Deny)();
15
15
  }
16
- return base_1.Skip();
16
+ return (0, base_1.Skip)();
17
17
  }
18
18
  }
19
19
  exports.DenyIfBuilder = DenyIfBuilder;
@@ -23,9 +23,9 @@ class AllowIfBuilder {
23
23
  }
24
24
  async apply(_v, _ent) {
25
25
  if (this.id && isBuilder(this.id)) {
26
- return base_1.Allow();
26
+ return (0, base_1.Allow)();
27
27
  }
28
- return base_1.Skip();
28
+ return (0, base_1.Skip)();
29
29
  }
30
30
  }
31
31
  exports.AllowIfBuilder = AllowIfBuilder;
package/auth/auth.js CHANGED
@@ -17,11 +17,11 @@ async function getLoggedInViewer(context) {
17
17
  for (const [name, authHandler] of handlers) {
18
18
  let v = await authHandler.authViewer(context);
19
19
  if (v !== null) {
20
- logger_1.log("info", `auth handler \`${name}\` authenticated user \`${v.viewerID}\``);
20
+ (0, logger_1.log)("info", `auth handler \`${name}\` authenticated user \`${v.viewerID}\``);
21
21
  return v;
22
22
  }
23
23
  }
24
- logger_1.log("info", "no auth handler returned viewer. default to logged out viewer");
24
+ (0, logger_1.log)("info", "no auth handler returned viewer. default to logged out viewer");
25
25
  return null;
26
26
  }
27
27
  exports.getLoggedInViewer = getLoggedInViewer;
package/core/base.js CHANGED
@@ -9,22 +9,25 @@ var privacyResult;
9
9
  privacyResult[privacyResult["Deny"] = 401] = "Deny";
10
10
  privacyResult[privacyResult["Skip"] = 307] = "Skip";
11
11
  })(privacyResult || (privacyResult = {}));
12
+ const allow = {
13
+ result: privacyResult.Allow,
14
+ };
12
15
  function Allow() {
13
- return {
14
- result: privacyResult.Allow,
15
- };
16
+ return allow;
16
17
  }
17
18
  exports.Allow = Allow;
19
+ const skip = {
20
+ result: privacyResult.Skip,
21
+ };
18
22
  function Skip() {
19
- return {
20
- result: privacyResult.Skip,
21
- };
23
+ return skip;
22
24
  }
23
25
  exports.Skip = Skip;
26
+ const deny = {
27
+ result: privacyResult.Deny,
28
+ };
24
29
  function Deny() {
25
- return {
26
- result: privacyResult.Deny,
27
- };
30
+ return deny;
28
31
  }
29
32
  exports.Deny = Deny;
30
33
  function DenyWithReason(e) {
package/core/clause.d.ts CHANGED
@@ -28,6 +28,7 @@ declare class compositeClause implements Clause {
28
28
  instanceKey(): string;
29
29
  }
30
30
  export declare function Eq(col: string, value: any): simpleClause;
31
+ export declare function NotEq(col: string, value: any): simpleClause;
31
32
  export declare function Greater(col: string, value: any): simpleClause;
32
33
  export declare function Less(col: string, value: any): simpleClause;
33
34
  export declare function GreaterEq(col: string, value: any): simpleClause;
package/core/clause.js CHANGED
@@ -19,7 +19,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
19
19
  return result;
20
20
  };
21
21
  Object.defineProperty(exports, "__esModule", { value: true });
22
- exports.sensitiveValue = exports.In = exports.Or = exports.And = exports.LessEq = exports.GreaterEq = exports.Less = exports.Greater = exports.Eq = void 0;
22
+ exports.sensitiveValue = exports.In = exports.Or = exports.And = exports.LessEq = exports.GreaterEq = exports.Less = exports.Greater = exports.NotEq = exports.Eq = void 0;
23
23
  const db_1 = __importStar(require("./db"));
24
24
  function isSensitive(val) {
25
25
  return (typeof val === "object" && val.logValue !== undefined);
@@ -149,6 +149,10 @@ function Eq(col, value) {
149
149
  return new simpleClause(col, value, "=");
150
150
  }
151
151
  exports.Eq = Eq;
152
+ function NotEq(col, value) {
153
+ return new simpleClause(col, value, "!=");
154
+ }
155
+ exports.NotEq = NotEq;
152
156
  function Greater(col, value) {
153
157
  return new simpleClause(col, value, ">");
154
158
  }
@@ -173,7 +177,7 @@ function Or(...args) {
173
177
  return new compositeClause(args, " OR ");
174
178
  }
175
179
  exports.Or = Or;
176
- // todo?
180
+ // TODO this breaks if values.length ===1 and array. todo fix
177
181
  function In(col, ...values) {
178
182
  return new inClause(col, values);
179
183
  }
package/core/config.d.ts CHANGED
@@ -6,6 +6,26 @@ export interface Config {
6
6
  dbFile?: string;
7
7
  db?: Database | DBDict;
8
8
  log?: logType | logType[];
9
+ codegen?: CodegenConfig;
10
+ }
11
+ interface CodegenConfig {
12
+ defaultEntPolicy?: PrivacyConfig;
13
+ defaultActionPolicy?: PrivacyConfig;
14
+ prettier?: PrettierConfig;
15
+ relativeImports?: boolean;
16
+ disableGraphQLRoot?: boolean;
17
+ generatedHeader?: string;
18
+ disableBase64Encoding?: boolean;
19
+ generateRootResolvers?: boolean;
20
+ }
21
+ interface PrettierConfig {
22
+ custom?: boolean;
23
+ glob?: string;
24
+ }
25
+ interface PrivacyConfig {
26
+ path: string;
27
+ policyName: string;
28
+ class?: boolean;
9
29
  }
10
30
  export declare function loadConfig(file?: string | Buffer | Config): void;
11
31
  export {};
package/core/config.js CHANGED
@@ -30,7 +30,7 @@ const path = __importStar(require("path"));
30
30
  const logger_1 = require("./logger");
31
31
  function setConfig(cfg) {
32
32
  if (cfg.log) {
33
- logger_1.setLogLevels(cfg.log);
33
+ (0, logger_1.setLogLevels)(cfg.log);
34
34
  }
35
35
  if (cfg.dbConnectionString || cfg.dbFile || cfg.db) {
36
36
  db_1.default.initDB({
@@ -68,7 +68,7 @@ function loadConfig(file) {
68
68
  }
69
69
  }
70
70
  try {
71
- let yaml = js_yaml_1.load(data);
71
+ let yaml = (0, js_yaml_1.load)(data);
72
72
  if (typeof yaml !== "object") {
73
73
  throw new Error(`invalid yaml passed`);
74
74
  }
package/core/context.js CHANGED
@@ -14,7 +14,7 @@ class ContextCache {
14
14
  if (l) {
15
15
  return l;
16
16
  }
17
- logger_1.log("debug", `new context-aware loader created for ${name}`);
17
+ (0, logger_1.log)("debug", `new context-aware loader created for ${name}`);
18
18
  l = create();
19
19
  this.loaders.set(name, l);
20
20
  return l;
@@ -39,7 +39,7 @@ class ContextCache {
39
39
  const key = this.getkey(options);
40
40
  let rows = m.get(key);
41
41
  if (rows) {
42
- logger_1.log("query", {
42
+ (0, logger_1.log)("query", {
43
43
  "cache-hit": key,
44
44
  "tableName": options.tableName,
45
45
  });
@@ -54,7 +54,7 @@ class ContextCache {
54
54
  const key = this.getkey(options);
55
55
  let row = m.get(key);
56
56
  if (row) {
57
- logger_1.log("query", {
57
+ (0, logger_1.log)("query", {
58
58
  "cache-hit": key,
59
59
  "tableName": options.tableName,
60
60
  });
package/core/convert.d.ts CHANGED
@@ -8,3 +8,7 @@ export declare function convertDateList(val: any): Date[];
8
8
  export declare function convertNullableDateList(val: any): Date[] | null;
9
9
  export declare function convertBoolList(val: any): boolean[];
10
10
  export declare function convertNullableBoolList(val: any): boolean[] | null;
11
+ export declare function convertJSON(val: any): any;
12
+ export declare function convertNullableJSON(val: any): any | null;
13
+ export declare function convertJSONList(val: any): boolean[];
14
+ export declare function convertNullableJSONList(val: any): any[] | null;
package/core/convert.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.convertNullableBoolList = exports.convertBoolList = exports.convertNullableDateList = exports.convertDateList = exports.convertNullableList = exports.convertList = exports.convertNullableBool = exports.convertBool = exports.convertNullableDate = exports.convertDate = void 0;
3
+ exports.convertNullableJSONList = exports.convertJSONList = exports.convertNullableJSON = exports.convertJSON = exports.convertNullableBoolList = exports.convertBoolList = exports.convertNullableDateList = exports.convertDateList = exports.convertNullableList = exports.convertList = exports.convertNullableBool = exports.convertBool = exports.convertNullableDate = exports.convertDate = void 0;
4
4
  const luxon_1 = require("luxon");
5
5
  // these are needed to deal with SQLite having different types stored in the db vs the representation
6
6
  // gotten back from the db/needed in ent land
@@ -59,7 +59,8 @@ function convertList(val, conv) {
59
59
  }
60
60
  exports.convertList = convertList;
61
61
  function convertNullableList(val, conv) {
62
- if (val === null) {
62
+ // undefined can happen with unsafe ents
63
+ if (val === null || val === undefined) {
63
64
  return null;
64
65
  }
65
66
  return convertList(val, conv);
@@ -81,3 +82,25 @@ function convertNullableBoolList(val) {
81
82
  return convertNullableList(val, convertBool);
82
83
  }
83
84
  exports.convertNullableBoolList = convertNullableBoolList;
85
+ function convertJSON(val) {
86
+ if (typeof val === "string") {
87
+ return JSON.parse(val);
88
+ }
89
+ return val;
90
+ }
91
+ exports.convertJSON = convertJSON;
92
+ function convertNullableJSON(val) {
93
+ if (val === null) {
94
+ return val;
95
+ }
96
+ return convertJSON(val);
97
+ }
98
+ exports.convertNullableJSON = convertNullableJSON;
99
+ function convertJSONList(val) {
100
+ return convertList(val, convertJSON);
101
+ }
102
+ exports.convertJSONList = convertJSONList;
103
+ function convertNullableJSONList(val) {
104
+ return convertNullableList(val, convertJSON);
105
+ }
106
+ exports.convertNullableJSONList = convertNullableJSONList;