@snowtop/ent 0.0.39-alpha8 → 0.0.40-alpha5

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.
@@ -12,7 +12,7 @@ export interface OrchestratorOptions<T extends Ent, TData extends Data> {
12
12
  builder: Builder<T>;
13
13
  action?: Action<T>;
14
14
  schema: SchemaInputType;
15
- editedFields(): Map<string, any>;
15
+ editedFields(): Map<string, any> | Promise<Map<string, any>>;
16
16
  updateInput?: (data: TData) => void;
17
17
  }
18
18
  interface edgeInputDataOpts {
@@ -4,7 +4,6 @@ exports.EntChangeset = exports.Orchestrator = exports.edgeDirection = void 0;
4
4
  const ent_1 = require("../core/ent");
5
5
  const schema_1 = require("../schema/schema");
6
6
  const action_1 = require("../action");
7
- const snake_case_1 = require("snake-case");
8
7
  const camel_case_1 = require("camel-case");
9
8
  const privacy_1 = require("../core/privacy");
10
9
  const executor_1 = require("./executor");
@@ -277,7 +276,8 @@ class Orchestrator {
277
276
  const builder = this.options.builder;
278
277
  // future optimization: can get schemaFields to memoize based on different values
279
278
  const schemaFields = (0, schema_1.getFields)(this.options.schema);
280
- let editedData = await this.getFieldsWithDefaultValues(builder, schemaFields, action);
279
+ const editedFields = await this.options.editedFields();
280
+ let editedData = await this.getFieldsWithDefaultValues(builder, schemaFields, editedFields, action);
281
281
  // this runs in following phases:
282
282
  // * set default fields and pass to builder so the value can be checked by triggers/observers/validators
283
283
  // * privacy policy (use unsafe ent if we have it)
@@ -294,8 +294,11 @@ class Orchestrator {
294
294
  await this.triggers(action, builder, triggers);
295
295
  }
296
296
  let validators = action?.validators || [];
297
+ // not ideal we're calling this twice. fix...
298
+ // needed for now. may need to write somet of this?
299
+ const editedFields2 = await this.options.editedFields();
297
300
  await Promise.all([
298
- this.formatAndValidateFields(schemaFields),
301
+ this.formatAndValidateFields(schemaFields, editedFields2),
299
302
  this.validators(validators, action, builder),
300
303
  ]);
301
304
  }
@@ -330,8 +333,7 @@ class Orchestrator {
330
333
  isBuilder(val) {
331
334
  return val.placeholderID !== undefined;
332
335
  }
333
- async getFieldsWithDefaultValues(builder, schemaFields, action) {
334
- const editedFields = this.options.editedFields();
336
+ async getFieldsWithDefaultValues(builder, schemaFields, editedFields, action) {
335
337
  let data = {};
336
338
  let defaultData = {};
337
339
  let input = action?.getInput() || {};
@@ -369,12 +371,12 @@ class Orchestrator {
369
371
  if (field.format) {
370
372
  val = field.format(transformed.data[k]);
371
373
  }
372
- let dbKey = field.storageKey || (0, snake_case_1.snakeCase)(field.name);
374
+ let dbKey = (0, schema_1.getStorageKey)(field);
373
375
  data[dbKey] = val;
374
376
  this.defaultFieldsByTSName[(0, camel_case_1.camelCase)(k)] = val;
375
377
  // hmm do we need this?
376
378
  // TODO how to do this for local tests?
377
- // this.defaultFieldsByFieldName[k] = val;
379
+ // this.defaultFieldsByFieldName[k] = val;
378
380
  }
379
381
  }
380
382
  this.actualOperation = this.getWriteOpForSQLStamentOp(transformed.op);
@@ -387,7 +389,7 @@ class Orchestrator {
387
389
  for (const [fieldName, field] of schemaFields) {
388
390
  let value = editedFields.get(fieldName);
389
391
  let defaultValue = undefined;
390
- let dbKey = field.storageKey || (0, snake_case_1.snakeCase)(field.name);
392
+ let dbKey = (0, schema_1.getStorageKey)(field);
391
393
  if (value === undefined) {
392
394
  if (this.actualOperation === action_1.WriteOperation.Insert) {
393
395
  if (field.defaultToViewerOnCreate && field.defaultValueOnCreate) {
@@ -483,12 +485,11 @@ class Orchestrator {
483
485
  }
484
486
  return value;
485
487
  }
486
- async formatAndValidateFields(schemaFields) {
488
+ async formatAndValidateFields(schemaFields, editedFields) {
487
489
  const op = this.actualOperation;
488
490
  if (op === action_1.WriteOperation.Delete) {
489
491
  return;
490
492
  }
491
- const editedFields = this.options.editedFields();
492
493
  // build up data to be saved...
493
494
  let data = {};
494
495
  let logValues = {};
@@ -498,7 +499,7 @@ class Orchestrator {
498
499
  // null allowed
499
500
  value = this.defaultFieldsByFieldName[fieldName];
500
501
  }
501
- let dbKey = field.storageKey || (0, snake_case_1.snakeCase)(field.name);
502
+ let dbKey = (0, schema_1.getStorageKey)(field);
502
503
  value = await this.transformFieldValue(field, dbKey, value);
503
504
  if (value !== undefined) {
504
505
  data[dbKey] = value;
@@ -511,7 +512,7 @@ class Orchestrator {
511
512
  for (const fieldName in this.defaultFieldsByFieldName) {
512
513
  const defaultValue = this.defaultFieldsByFieldName[fieldName];
513
514
  let field = schemaFields.get(fieldName);
514
- let dbKey = field.storageKey || (0, snake_case_1.snakeCase)(field.name);
515
+ let dbKey = (0, schema_1.getStorageKey)(field);
515
516
  // no value, let's just default
516
517
  if (data[dbKey] === undefined) {
517
518
  const value = await this.transformFieldValue(field, dbKey, defaultValue);
package/core/base.d.ts CHANGED
@@ -62,7 +62,7 @@ export interface SelectBaseDataOptions extends DataOptions {
62
62
  }
63
63
  export interface SelectDataOptions extends SelectBaseDataOptions {
64
64
  key: string;
65
- clause?: clause.Clause;
65
+ clause?: clause.Clause | (() => clause.Clause | undefined);
66
66
  }
67
67
  export interface QueryableDataOptions extends SelectBaseDataOptions, QueryDataOptions {
68
68
  }
@@ -89,9 +89,11 @@ interface LoadableEntOptions<T extends Ent> {
89
89
  ent: EntConstructor<T>;
90
90
  }
91
91
  export interface LoadEntOptions<T extends Ent> extends LoadableEntOptions<T>, SelectBaseDataOptions {
92
+ fieldPrivacy?: Map<string, PrivacyPolicy>;
92
93
  }
93
94
  export interface LoadCustomEntOptions<T extends Ent> extends SelectBaseDataOptions {
94
95
  ent: EntConstructor<T>;
96
+ fieldPrivacy?: Map<string, PrivacyPolicy>;
95
97
  }
96
98
  export interface LoaderInfo {
97
99
  tableName: string;
package/core/clause.d.ts CHANGED
@@ -53,5 +53,9 @@ export declare function TsQuery(col: string, val: string | TsQuery): Clause;
53
53
  export declare function PlainToTsQuery(col: string, val: string | TsQuery): Clause;
54
54
  export declare function PhraseToTsQuery(col: string, val: string | TsQuery): Clause;
55
55
  export declare function WebsearchToTsQuery(col: string, val: string | TsQuery): Clause;
56
+ export declare function TsVectorColTsQuery(col: string, val: string | TsQuery): Clause;
57
+ export declare function TsVectorPlainToTsQuery(col: string, val: string | TsQuery): Clause;
58
+ export declare function TsVectorPhraseToTsQuery(col: string, val: string | TsQuery): Clause;
59
+ export declare function TsVectorWebsearchToTsQuery(col: string, val: string | TsQuery): Clause;
56
60
  export declare function sensitiveValue(val: any): SensitiveValue;
57
61
  export {};
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.WebsearchToTsQuery = exports.PhraseToTsQuery = exports.PlainToTsQuery = exports.TsQuery = exports.In = exports.Or = exports.AndOptional = exports.And = exports.LessEq = exports.GreaterEq = exports.Less = exports.Greater = exports.NotEq = exports.Eq = exports.ArrayLessEq = exports.ArrayGreaterEq = exports.ArrayLess = exports.ArrayGreater = exports.ArrayNotEq = exports.ArrayEq = void 0;
22
+ exports.sensitiveValue = exports.TsVectorWebsearchToTsQuery = exports.TsVectorPhraseToTsQuery = exports.TsVectorPlainToTsQuery = exports.TsVectorColTsQuery = exports.WebsearchToTsQuery = exports.PhraseToTsQuery = exports.PlainToTsQuery = exports.TsQuery = exports.In = exports.Or = exports.AndOptional = exports.And = exports.LessEq = exports.GreaterEq = exports.Less = exports.Greater = exports.NotEq = exports.Eq = exports.ArrayLessEq = exports.ArrayGreaterEq = exports.ArrayLess = exports.ArrayGreater = exports.ArrayNotEq = exports.ArrayEq = void 0;
23
23
  const db_1 = __importStar(require("./db"));
24
24
  function isSensitive(val) {
25
25
  return (val !== null &&
@@ -236,9 +236,10 @@ class compositeClause {
236
236
  }
237
237
  }
238
238
  class tsQueryClause {
239
- constructor(col, val) {
239
+ constructor(col, val, tsVectorCol) {
240
240
  this.col = col;
241
241
  this.val = val;
242
+ this.tsVectorCol = tsVectorCol;
242
243
  }
243
244
  isTsQuery(val) {
244
245
  return typeof val !== "string";
@@ -253,8 +254,15 @@ class tsQueryClause {
253
254
  };
254
255
  }
255
256
  clause(idx) {
256
- const { language, value } = this.getInfo();
257
- return `${this.col} @@ ${this.getFunction()}('${language}', '${value}')`;
257
+ const { language } = this.getInfo();
258
+ if (db_1.Dialect.Postgres === db_1.default.getDialect()) {
259
+ if (this.tsVectorCol) {
260
+ return `to_tsvector(${this.col}) @@ ${this.getFunction()}('${language}', $${idx})`;
261
+ }
262
+ return `${this.col} @@ ${this.getFunction()}('${language}', $${idx})`;
263
+ }
264
+ // FYI this doesn't actually work for sqlite since different
265
+ return `${this.col} @@ ${this.getFunction()}('${language}', ?)`;
258
266
  }
259
267
  values() {
260
268
  const { value } = this.getInfo();
@@ -269,7 +277,10 @@ class tsQueryClause {
269
277
  }
270
278
  instanceKey() {
271
279
  const { language, value } = this.getInfo();
272
- return `${this.col} @@${this.getFunction()}:${language}:${value}`;
280
+ if (this.tsVectorCol) {
281
+ return `to_tsvector(${this.col})@@${this.getFunction()}:${language}:${value}`;
282
+ }
283
+ return `${this.col}@@${this.getFunction()}:${language}:${value}`;
273
284
  }
274
285
  }
275
286
  class plainToTsQueryClause extends tsQueryClause {
@@ -380,6 +391,32 @@ function WebsearchToTsQuery(col, val) {
380
391
  return new websearchTosQueryClause(col, val);
381
392
  }
382
393
  exports.WebsearchToTsQuery = WebsearchToTsQuery;
394
+ // TsVectorColTsQuery is used when the column is not a tsvector field e.g.
395
+ // when there's an index just on the field and is not a combination of multiple fields
396
+ function TsVectorColTsQuery(col, val) {
397
+ return new tsQueryClause(col, val, true);
398
+ }
399
+ exports.TsVectorColTsQuery = TsVectorColTsQuery;
400
+ // TsVectorPlainToTsQuery is used when the column is not a tsvector field e.g.
401
+ // when there's an index just on the field and is not a combination of multiple fields
402
+ // TODO do these 4 need TsQuery because would be nice to have language?
403
+ // it seems to default to the config of the column
404
+ function TsVectorPlainToTsQuery(col, val) {
405
+ return new plainToTsQueryClause(col, val, true);
406
+ }
407
+ exports.TsVectorPlainToTsQuery = TsVectorPlainToTsQuery;
408
+ // TsVectorPhraseToTsQuery is used when the column is not a tsvector field e.g.
409
+ // when there's an index just on the field and is not a combination of multiple fields
410
+ function TsVectorPhraseToTsQuery(col, val) {
411
+ return new phraseToTsQueryClause(col, val, true);
412
+ }
413
+ exports.TsVectorPhraseToTsQuery = TsVectorPhraseToTsQuery;
414
+ // TsVectorWebsearchToTsQuery is used when the column is not a tsvector field e.g.
415
+ // when there's an index just on the field and is not a combination of multiple fields
416
+ function TsVectorWebsearchToTsQuery(col, val) {
417
+ return new websearchTosQueryClause(col, val, true);
418
+ }
419
+ exports.TsVectorWebsearchToTsQuery = TsVectorWebsearchToTsQuery;
383
420
  // TODO would be nice to support this with building blocks but not supporting for now
384
421
  // AND: foo & bar,
385
422
  // OR: foo | bar
package/core/config.d.ts CHANGED
@@ -9,6 +9,10 @@ declare enum graphQLFieldFormat {
9
9
  LOWER_CAMEL = "lowerCamel",
10
10
  SNAKE_CASE = "snake_case"
11
11
  }
12
+ declare enum fieldPrivacyEvaluated {
13
+ AT_ENT_LOAD = "at_ent_load",
14
+ ON_DEMAND = "on_demand"
15
+ }
12
16
  export interface Config {
13
17
  dbConnectionString?: string;
14
18
  dbFile?: string;
@@ -29,6 +33,8 @@ interface CodegenConfig {
29
33
  defaultGraphQLMutationName?: graphqlMutationName;
30
34
  defaultGraphQLFieldFormat?: graphQLFieldFormat;
31
35
  schemaSQLFilePath?: boolean;
36
+ databaseToCompareTo?: string;
37
+ fieldPrivacyEvaluated?: fieldPrivacyEvaluated;
32
38
  }
33
39
  interface PrettierConfig {
34
40
  custom?: boolean;
package/core/config.js CHANGED
@@ -40,6 +40,11 @@ var graphQLFieldFormat;
40
40
  graphQLFieldFormat["LOWER_CAMEL"] = "lowerCamel";
41
41
  graphQLFieldFormat["SNAKE_CASE"] = "snake_case";
42
42
  })(graphQLFieldFormat || (graphQLFieldFormat = {}));
43
+ var fieldPrivacyEvaluated;
44
+ (function (fieldPrivacyEvaluated) {
45
+ fieldPrivacyEvaluated["AT_ENT_LOAD"] = "at_ent_load";
46
+ fieldPrivacyEvaluated["ON_DEMAND"] = "on_demand";
47
+ })(fieldPrivacyEvaluated || (fieldPrivacyEvaluated = {}));
43
48
  function setConfig(cfg) {
44
49
  if (cfg.log) {
45
50
  (0, logger_1.setLogLevels)(cfg.log);
package/core/db.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { Pool, ClientConfig, PoolClient } from "pg";
2
- export interface Database {
1
+ import { Pool, PoolClient, PoolConfig } from "pg";
2
+ export interface Database extends PoolConfig {
3
3
  database?: string;
4
4
  user?: string;
5
5
  password?: string;
@@ -16,7 +16,7 @@ export declare enum Dialect {
16
16
  }
17
17
  interface DatabaseInfo {
18
18
  dialect: Dialect;
19
- config: ClientConfig;
19
+ config: PoolConfig;
20
20
  filePath?: string;
21
21
  }
22
22
  export default class DB {
package/core/db.js CHANGED
@@ -109,6 +109,8 @@ function getClientConfig(args) {
109
109
  host: cfg.host,
110
110
  port: cfg.port,
111
111
  ssl: cfg.sslmode == "enable",
112
+ // max, min, etc
113
+ ...cfg,
112
114
  },
113
115
  };
114
116
  }
package/core/ent.d.ts CHANGED
@@ -22,8 +22,6 @@ export declare type CustomQuery = string | rawQueryOptions | clause.Clause | Que
22
22
  export declare function loadCustomData(options: SelectBaseDataOptions, query: CustomQuery, context: Context | undefined): Promise<Data[]>;
23
23
  export declare function loadDerivedEnt<T extends Ent>(viewer: Viewer, data: Data, loader: new (viewer: Viewer, data: Data) => T): Promise<T | null>;
24
24
  export declare function loadDerivedEntX<T extends Ent>(viewer: Viewer, data: Data, loader: new (viewer: Viewer, data: Data) => T): Promise<T>;
25
- export declare function applyPrivacyPolicyForEnt<T extends Ent>(viewer: Viewer, ent: T | null): Promise<T | null>;
26
- export declare function applyPrivacyPolicyForEntX<T extends Ent>(viewer: Viewer, ent: T): Promise<T>;
27
25
  export declare function loadRowX(options: LoadRowOptions): Promise<Data>;
28
26
  export declare function loadRow(options: LoadRowOptions): Promise<Data | null>;
29
27
  export declare function performRawQuery(query: string, values: any[], logValues?: any[]): Promise<Data[]>;
package/core/ent.js CHANGED
@@ -22,7 +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.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.applyPrivacyPolicyForEntX = exports.applyPrivacyPolicyForEnt = exports.loadDerivedEntX = exports.loadDerivedEnt = exports.loadCustomData = exports.loadCustomEnts = exports.loadEntsFromClause = exports.loadEnts = exports.loadEntXFromClause = exports.loadEntFromClause = exports.loadEntXViaKey = exports.loadEntX = exports.loadEntViaKey = exports.loadEnt = 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.loadEnts = exports.loadEntXFromClause = exports.loadEntFromClause = exports.loadEntXViaKey = exports.loadEntX = exports.loadEntViaKey = exports.loadEnt = void 0;
26
26
  const db_1 = __importStar(require("./db"));
27
27
  const privacy_1 = require("./privacy");
28
28
  const clause = __importStar(require("./clause"));
@@ -139,8 +139,7 @@ async function loadEntXFromClause(viewer, options, clause) {
139
139
  context: viewer.context,
140
140
  };
141
141
  const row = await loadRowX(rowOptions);
142
- const ent = new options.ent(viewer, row);
143
- return await applyPrivacyPolicyForEntX(viewer, ent);
142
+ return await applyPrivacyPolicyForRowX(viewer, options, row);
144
143
  }
145
144
  exports.loadEntXFromClause = loadEntXFromClause;
146
145
  async function loadEnts(viewer, options, ...ids) {
@@ -207,7 +206,7 @@ async function loadCustomEnts(viewer, options, query) {
207
206
  const result = new Array(rows.length);
208
207
  await Promise.all(rows.map(async (row, idx) => {
209
208
  const ent = new options.ent(viewer, row);
210
- let privacyEnt = await applyPrivacyPolicyForEnt(viewer, ent);
209
+ let privacyEnt = await applyPrivacyPolicyForEnt(viewer, ent, row, options);
211
210
  if (privacyEnt) {
212
211
  result[idx] = privacyEnt;
213
212
  }
@@ -253,30 +252,55 @@ exports.loadCustomData = loadCustomData;
253
252
  // Derived ents
254
253
  async function loadDerivedEnt(viewer, data, loader) {
255
254
  const ent = new loader(viewer, data);
256
- return await applyPrivacyPolicyForEnt(viewer, ent);
255
+ return await applyPrivacyPolicyForEnt(viewer, ent, data, {
256
+ ent: loader,
257
+ });
257
258
  }
258
259
  exports.loadDerivedEnt = loadDerivedEnt;
259
260
  async function loadDerivedEntX(viewer, data, loader) {
260
261
  const ent = new loader(viewer, data);
261
- return await applyPrivacyPolicyForEntX(viewer, ent);
262
+ return await applyPrivacyPolicyForEntX(viewer, ent, data, { ent: loader });
262
263
  }
263
264
  exports.loadDerivedEntX = loadDerivedEntX;
264
- async function applyPrivacyPolicyForEnt(viewer, ent) {
265
+ // everything calls into this two so should be fine
266
+ // TODO is there a smarter way to not instantiate two objects here?
267
+ async function applyPrivacyPolicyForEnt(viewer, ent, data, fieldPrivacyOptions) {
265
268
  if (ent) {
266
269
  const visible = await (0, privacy_1.applyPrivacyPolicy)(viewer, ent.privacyPolicy, ent);
267
- if (visible) {
268
- return ent;
270
+ if (!visible) {
271
+ return null;
269
272
  }
273
+ return doFieldPrivacy(viewer, ent, data, fieldPrivacyOptions);
270
274
  }
271
275
  return null;
272
276
  }
273
- exports.applyPrivacyPolicyForEnt = applyPrivacyPolicyForEnt;
274
- async function applyPrivacyPolicyForEntX(viewer, ent) {
277
+ async function applyPrivacyPolicyForEntX(viewer, ent, data, options) {
275
278
  // this will throw
276
279
  await (0, privacy_1.applyPrivacyPolicyX)(viewer, ent.privacyPolicy, ent);
280
+ return doFieldPrivacy(viewer, ent, data, options);
281
+ }
282
+ async function doFieldPrivacy(viewer, ent, data, options) {
283
+ if (!options.fieldPrivacy) {
284
+ return ent;
285
+ }
286
+ const promises = [];
287
+ let somethingChanged = false;
288
+ for (const [k, policy] of options.fieldPrivacy) {
289
+ promises.push((async () => {
290
+ const r = await (0, privacy_1.applyPrivacyPolicy)(viewer, policy, ent);
291
+ if (!r) {
292
+ data[k] = null;
293
+ somethingChanged = true;
294
+ }
295
+ })());
296
+ }
297
+ await Promise.all(promises);
298
+ if (somethingChanged) {
299
+ // have to create new instance
300
+ return new options.ent(viewer, data);
301
+ }
277
302
  return ent;
278
303
  }
279
- exports.applyPrivacyPolicyForEntX = applyPrivacyPolicyForEntX;
280
304
  function logQuery(query, logValues) {
281
305
  (0, logger_1.log)("query", {
282
306
  query: query,
@@ -322,6 +346,8 @@ async function loadRow(options) {
322
346
  return res.rows[0];
323
347
  }
324
348
  catch (e) {
349
+ // an example of an error being suppressed
350
+ // another one. TODO https://github.com/lolopinto/ent/issues/862
325
351
  (0, logger_1.log)("error", e);
326
352
  return null;
327
353
  }
@@ -453,7 +479,16 @@ class EditNodeOperation {
453
479
  const opts = loader.getOptions();
454
480
  let cls = clause.Eq(options.key, id);
455
481
  if (opts.clause) {
456
- cls = clause.And(opts.clause, cls);
482
+ let optionClause;
483
+ if (typeof opts.clause === "function") {
484
+ optionClause = opts.clause();
485
+ }
486
+ else {
487
+ optionClause = opts.clause;
488
+ }
489
+ if (optionClause) {
490
+ cls = clause.And(optionClause, cls);
491
+ }
457
492
  }
458
493
  const query = buildQuery({
459
494
  fields: opts.fields.length ? opts.fields : ["*"],
@@ -1150,20 +1185,19 @@ async function applyPrivacyPolicyForRow(viewer, options, row) {
1150
1185
  return null;
1151
1186
  }
1152
1187
  const ent = new options.ent(viewer, row);
1153
- return await applyPrivacyPolicyForEnt(viewer, ent);
1188
+ return await applyPrivacyPolicyForEnt(viewer, ent, row, options);
1154
1189
  }
1155
1190
  exports.applyPrivacyPolicyForRow = applyPrivacyPolicyForRow;
1156
1191
  async function applyPrivacyPolicyForRowX(viewer, options, row) {
1157
1192
  const ent = new options.ent(viewer, row);
1158
- return await applyPrivacyPolicyForEntX(viewer, ent);
1193
+ return await applyPrivacyPolicyForEntX(viewer, ent, row, options);
1159
1194
  }
1160
1195
  exports.applyPrivacyPolicyForRowX = applyPrivacyPolicyForRowX;
1161
1196
  async function applyPrivacyPolicyForRows(viewer, rows, options) {
1162
1197
  let m = new Map();
1163
1198
  // apply privacy logic
1164
1199
  await Promise.all(rows.map(async (row) => {
1165
- const ent = new options.ent(viewer, row);
1166
- let privacyEnt = await applyPrivacyPolicyForEnt(viewer, ent);
1200
+ let privacyEnt = await applyPrivacyPolicyForRow(viewer, options, row);
1167
1201
  if (privacyEnt) {
1168
1202
  m.set(privacyEnt.id, privacyEnt);
1169
1203
  }
@@ -14,11 +14,15 @@ export declare class ObjectLoader<T> implements Loader<T, Data | null> {
14
14
  loadMany(keys: T[]): Promise<Data[]>;
15
15
  prime(data: Data): void;
16
16
  }
17
+ interface ObjectLoaderOptions extends SelectDataOptions {
18
+ instanceKey?: string;
19
+ }
17
20
  export declare class ObjectLoaderFactory<T> implements LoaderFactory<T, Data | null> {
18
- options: SelectDataOptions;
21
+ options: ObjectLoaderOptions;
19
22
  name: string;
20
23
  private toPrime;
21
- constructor(options: SelectDataOptions);
24
+ constructor(options: ObjectLoaderOptions);
22
25
  createLoader(context?: Context): ObjectLoader<T>;
23
26
  addToPrime(factory: ObjectLoaderFactory<T>): void;
24
27
  }
28
+ export {};
@@ -45,7 +45,16 @@ function createDataLoader(options) {
45
45
  let col = options.key;
46
46
  let cls = clause.In(col, ...ids);
47
47
  if (options.clause) {
48
- cls = clause.And(options.clause, cls);
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
+ }
49
58
  }
50
59
  const rowOptions = {
51
60
  ...options,
@@ -119,7 +128,16 @@ class ObjectLoader {
119
128
  }
120
129
  let cls = clause.Eq(this.options.key, key);
121
130
  if (this.options.clause) {
122
- cls = clause.And(this.options.clause, cls);
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
+ }
123
141
  }
124
142
  const rowOptions = {
125
143
  ...this.options,
@@ -137,7 +155,16 @@ class ObjectLoader {
137
155
  }
138
156
  let cls = clause.In(this.options.key, ...keys);
139
157
  if (this.options.clause) {
140
- cls = clause.And(this.options.clause, cls);
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
+ }
141
168
  }
142
169
  const rowOptions = {
143
170
  ...this.options,
@@ -160,7 +187,17 @@ class ObjectLoaderFactory {
160
187
  constructor(options) {
161
188
  this.options = options;
162
189
  this.toPrime = [];
163
- this.name = `${options.tableName}:${options.key}:${options.clause?.instanceKey() || ""}`;
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}`;
164
201
  }
165
202
  createLoader(context) {
166
203
  return (0, loader_1.getLoader)(this, () => {
package/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export * from "./core/base";
2
- export { loadEnt, loadCustomData, loadCustomEnts, loadEntX, loadEnts, CustomQuery, loadDerivedEnt, loadDerivedEntX, loadEntViaKey, loadEntXViaKey, applyPrivacyPolicyForEnt, applyPrivacyPolicyForEntX, performRawQuery, loadRowX, loadRow, loadRows, DataOperation, EditNodeOptions, EditNodeOperation, EdgeOperation, DeleteNodeOperation, AssocEdge, AssocEdgeInputOptions, AssocEdgeInput, AssocEdgeData, loadEdgeData, loadEdgeDatas, loadEdges, loadUniqueEdge, loadUniqueNode, loadRawEdgeCountX, loadEdgeForID2, loadNodesByEdge, getEdgeTypeInGroup, } from "./core/ent";
2
+ export { loadEnt, loadCustomData, loadCustomEnts, loadEntX, loadEnts, CustomQuery, loadDerivedEnt, loadDerivedEntX, loadEntViaKey, loadEntXViaKey, performRawQuery, loadRowX, loadRow, loadRows, DataOperation, EditNodeOptions, EditNodeOperation, EdgeOperation, DeleteNodeOperation, AssocEdge, AssocEdgeInputOptions, AssocEdgeInput, AssocEdgeData, loadEdgeData, loadEdgeDatas, loadEdges, loadUniqueEdge, loadUniqueNode, loadRawEdgeCountX, loadEdgeForID2, loadNodesByEdge, getEdgeTypeInGroup, } from "./core/ent";
3
3
  import DB from "./core/db";
4
4
  export * from "./core/loaders";
5
5
  export { DB };
@@ -24,6 +24,14 @@ declare const query: {
24
24
  ArrayLess: typeof q.ArrayLess;
25
25
  ArrayGreaterEq: typeof q.ArrayGreaterEq;
26
26
  ArrayLessEq: typeof q.ArrayLessEq;
27
+ TsQuery: typeof q.TsQuery;
28
+ PlainToTsQuery: typeof q.PlainToTsQuery;
29
+ PhraseToTsQuery: typeof q.PhraseToTsQuery;
30
+ WebsearchToTsQuery: typeof q.WebsearchToTsQuery;
31
+ TsVectorColTsQuery: typeof q.TsVectorColTsQuery;
32
+ TsVectorPlainToTsQuery: typeof q.TsVectorPlainToTsQuery;
33
+ TsVectorPhraseToTsQuery: typeof q.TsVectorPhraseToTsQuery;
34
+ TsVectorWebsearchToTsQuery: typeof q.TsVectorWebsearchToTsQuery;
27
35
  };
28
36
  export { query };
29
37
  export { RequestContext, ContextCache } from "./core/context";
package/index.js CHANGED
@@ -25,8 +25,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
25
25
  return (mod && mod.__esModule) ? mod : { "default": mod };
26
26
  };
27
27
  Object.defineProperty(exports, "__esModule", { value: true });
28
- exports.DenyIfViewerOutboundEdgeExistsRule = exports.DenyIfViewerInboundEdgeExistsRule = exports.DenyIfEdgeExistsRule = exports.AllowIfViewerOutboundEdgeExistsRule = exports.AllowIfViewerInboundEdgeExistsRule = exports.AllowIfEdgeExistsRule = exports.DenyIfViewerEqualsRule = exports.AllowIfViewerEqualsRule = exports.DenyIfEntPropertyIsRule = exports.AllowIfEntPropertyIsRule = exports.AllowIfViewerIsEntPropertyRule = exports.AllowIfViewerIsRule = exports.AllowIfFuncRule = exports.AllowIfViewerRule = exports.AllowIfHasIdentity = exports.DenyIfLoggedOutRule = exports.DenyIfLoggedInRule = exports.AlwaysDenyRule = exports.AlwaysAllowRule = exports.EntPrivacyError = exports.DB = exports.getEdgeTypeInGroup = exports.loadNodesByEdge = exports.loadEdgeForID2 = exports.loadRawEdgeCountX = exports.loadUniqueNode = exports.loadUniqueEdge = exports.loadEdges = exports.loadEdgeDatas = exports.loadEdgeData = exports.AssocEdgeData = exports.AssocEdge = exports.DeleteNodeOperation = exports.EdgeOperation = exports.EditNodeOperation = exports.loadRows = exports.loadRow = exports.loadRowX = exports.performRawQuery = exports.applyPrivacyPolicyForEntX = exports.applyPrivacyPolicyForEnt = exports.loadEntXViaKey = exports.loadEntViaKey = exports.loadDerivedEntX = exports.loadDerivedEnt = exports.loadEnts = exports.loadEntX = exports.loadCustomEnts = exports.loadCustomData = exports.loadEnt = void 0;
29
- exports.setLogLevels = exports.loadConfig = exports.LoggedOutViewer = exports.IDViewer = exports.ContextCache = exports.query = exports.AllowIfViewerHasIdentityPrivacyPolicy = exports.AllowIfViewerPrivacyPolicy = exports.AllowIfSubPolicyAllowsRule = exports.AllowIfConditionAppliesRule = exports.AlwaysDenyPrivacyPolicy = exports.AlwaysAllowPrivacyPolicy = exports.applyPrivacyPolicyX = exports.applyPrivacyPolicy = exports.DelayedResultRule = exports.DenyIfEntIsVisiblePolicy = exports.AllowIfEntIsVisiblePolicy = exports.DenyIfEntIsNotVisibleRule = exports.DenyIfEntIsVisibleRule = exports.AllowIfEntIsNotVisibleRule = exports.AllowIfEntIsVisibleRule = exports.DenyIfViewerOutboundEdgeDoesNotExistRule = exports.DenyIfViewerInboundEdgeDoesNotExistRule = exports.DenyIfEdgeDoesNotExistRule = void 0;
28
+ exports.DenyIfViewerInboundEdgeDoesNotExistRule = exports.DenyIfEdgeDoesNotExistRule = exports.DenyIfViewerOutboundEdgeExistsRule = exports.DenyIfViewerInboundEdgeExistsRule = exports.DenyIfEdgeExistsRule = exports.AllowIfViewerOutboundEdgeExistsRule = exports.AllowIfViewerInboundEdgeExistsRule = exports.AllowIfEdgeExistsRule = exports.DenyIfViewerEqualsRule = exports.AllowIfViewerEqualsRule = exports.DenyIfEntPropertyIsRule = exports.AllowIfEntPropertyIsRule = exports.AllowIfViewerIsEntPropertyRule = exports.AllowIfViewerIsRule = exports.AllowIfFuncRule = exports.AllowIfViewerRule = exports.AllowIfHasIdentity = exports.DenyIfLoggedOutRule = exports.DenyIfLoggedInRule = exports.AlwaysDenyRule = exports.AlwaysAllowRule = exports.EntPrivacyError = exports.DB = exports.getEdgeTypeInGroup = exports.loadNodesByEdge = exports.loadEdgeForID2 = exports.loadRawEdgeCountX = exports.loadUniqueNode = exports.loadUniqueEdge = exports.loadEdges = exports.loadEdgeDatas = exports.loadEdgeData = exports.AssocEdgeData = exports.AssocEdge = exports.DeleteNodeOperation = exports.EdgeOperation = exports.EditNodeOperation = exports.loadRows = exports.loadRow = exports.loadRowX = exports.performRawQuery = exports.loadEntXViaKey = exports.loadEntViaKey = exports.loadDerivedEntX = exports.loadDerivedEnt = exports.loadEnts = exports.loadEntX = exports.loadCustomEnts = exports.loadCustomData = exports.loadEnt = void 0;
29
+ exports.setLogLevels = exports.loadConfig = exports.LoggedOutViewer = exports.IDViewer = exports.ContextCache = exports.query = exports.AllowIfViewerHasIdentityPrivacyPolicy = exports.AllowIfViewerPrivacyPolicy = exports.AllowIfSubPolicyAllowsRule = exports.AllowIfConditionAppliesRule = exports.AlwaysDenyPrivacyPolicy = exports.AlwaysAllowPrivacyPolicy = exports.applyPrivacyPolicyX = exports.applyPrivacyPolicy = exports.DelayedResultRule = exports.DenyIfEntIsVisiblePolicy = exports.AllowIfEntIsVisiblePolicy = exports.DenyIfEntIsNotVisibleRule = exports.DenyIfEntIsVisibleRule = exports.AllowIfEntIsNotVisibleRule = exports.AllowIfEntIsVisibleRule = exports.DenyIfViewerOutboundEdgeDoesNotExistRule = void 0;
30
30
  __exportStar(require("./core/base"), exports);
31
31
  var ent_1 = require("./core/ent");
32
32
  Object.defineProperty(exports, "loadEnt", { enumerable: true, get: function () { return ent_1.loadEnt; } });
@@ -38,8 +38,6 @@ Object.defineProperty(exports, "loadDerivedEnt", { enumerable: true, get: functi
38
38
  Object.defineProperty(exports, "loadDerivedEntX", { enumerable: true, get: function () { return ent_1.loadDerivedEntX; } });
39
39
  Object.defineProperty(exports, "loadEntViaKey", { enumerable: true, get: function () { return ent_1.loadEntViaKey; } });
40
40
  Object.defineProperty(exports, "loadEntXViaKey", { enumerable: true, get: function () { return ent_1.loadEntXViaKey; } });
41
- Object.defineProperty(exports, "applyPrivacyPolicyForEnt", { enumerable: true, get: function () { return ent_1.applyPrivacyPolicyForEnt; } });
42
- Object.defineProperty(exports, "applyPrivacyPolicyForEntX", { enumerable: true, get: function () { return ent_1.applyPrivacyPolicyForEntX; } });
43
41
  Object.defineProperty(exports, "performRawQuery", { enumerable: true, get: function () { return ent_1.performRawQuery; } });
44
42
  // even these 3 need to change...
45
43
  Object.defineProperty(exports, "loadRowX", { enumerable: true, get: function () { return ent_1.loadRowX; } });
@@ -62,7 +60,7 @@ Object.defineProperty(exports, "getEdgeTypeInGroup", { enumerable: true, get: fu
62
60
  const db_1 = __importDefault(require("./core/db"));
63
61
  exports.DB = db_1.default;
64
62
  __exportStar(require("./core/loaders"), exports);
65
- // TODO figure out if this should be its own
63
+ // TODO figure out if this should be its own import path e.g. @snowtop/ent/privacy
66
64
  var privacy_1 = require("./core/privacy");
67
65
  Object.defineProperty(exports, "EntPrivacyError", { enumerable: true, get: function () { return privacy_1.EntPrivacyError; } });
68
66
  Object.defineProperty(exports, "AlwaysAllowRule", { enumerable: true, get: function () { return privacy_1.AlwaysAllowRule; } });
@@ -122,6 +120,14 @@ const query = {
122
120
  ArrayLess: q.ArrayLess,
123
121
  ArrayGreaterEq: q.ArrayGreaterEq,
124
122
  ArrayLessEq: q.ArrayLessEq,
123
+ TsQuery: q.TsQuery,
124
+ PlainToTsQuery: q.PlainToTsQuery,
125
+ PhraseToTsQuery: q.PhraseToTsQuery,
126
+ WebsearchToTsQuery: q.WebsearchToTsQuery,
127
+ TsVectorColTsQuery: q.TsVectorColTsQuery,
128
+ TsVectorPlainToTsQuery: q.TsVectorPlainToTsQuery,
129
+ TsVectorPhraseToTsQuery: q.TsVectorPhraseToTsQuery,
130
+ TsVectorWebsearchToTsQuery: q.TsVectorWebsearchToTsQuery,
125
131
  };
126
132
  exports.query = query;
127
133
  var context_1 = require("./core/context");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@snowtop/ent",
3
- "version": "0.0.39-alpha8",
3
+ "version": "0.0.40-alpha5",
4
4
  "description": "snowtop ent framework",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -38,10 +38,11 @@ interface ProcessedPattern {
38
38
  assocEdges: ProcessedAssocEdge[];
39
39
  fields: ProcessedField[];
40
40
  }
41
- declare type ProcessedField = Omit<Field, "defaultValueOnEdit" | "defaultValueOnCreate"> & {
41
+ declare type ProcessedField = Omit<Field, "defaultValueOnEdit" | "defaultValueOnCreate" | "privacyPolicy"> & {
42
42
  hasDefaultValueOnCreate?: boolean;
43
43
  hasDefaultValueOnEdit?: boolean;
44
44
  patternName?: string;
45
+ hasFieldPrivacy?: boolean;
45
46
  };
46
47
  interface patternsDict {
47
48
  [key: string]: ProcessedPattern;
@@ -7,6 +7,7 @@ function processFields(src, patternName) {
7
7
  let f = { ...field };
8
8
  f.hasDefaultValueOnCreate = field.defaultValueOnCreate != undefined;
9
9
  f.hasDefaultValueOnEdit = field.defaultValueOnEdit != undefined;
10
+ f.hasFieldPrivacy = field.privacyPolicy !== undefined;
10
11
  if (field.polymorphic) {
11
12
  // convert boolean into object
12
13
  // we keep boolean as an option to keep API simple
package/schema/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import Schema from "./schema";
2
2
  export { Schema };
3
- export { Field, AssocEdge, AssocEdgeGroup, InverseAssocEdge, Edge, Pattern, DBType, Type, FieldOptions, SchemaConstructor, SchemaInputType, getFields, ActionOperation, Action, EdgeAction, NoFields, Constraint, Index, ConstraintType, ForeignKeyInfo, requiredField, optionalField, UpdateOperation, TransformedUpdateOperation, SQLStatementOperation, getTransformedReadClause, } from "./schema";
3
+ export { Field, AssocEdge, AssocEdgeGroup, InverseAssocEdge, Edge, Pattern, DBType, Type, FieldOptions, SchemaConstructor, SchemaInputType, getFields, getFieldsWithPrivacy, ActionOperation, Action, EdgeAction, NoFields, Constraint, Index, ConstraintType, ForeignKeyInfo, requiredField, optionalField, UpdateOperation, TransformedUpdateOperation, SQLStatementOperation, getTransformedReadClause, getObjectLoaderProperties, } from "./schema";
4
4
  export { Timestamps, Node, BaseEntSchema, BaseEntSchemaWithTZ, } from "./base_schema";
5
5
  export * from "./field";
6
6
  export * from "./json_field";
package/schema/index.js CHANGED
@@ -10,10 +10,11 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
10
10
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
11
11
  };
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
- exports.BaseEntSchemaWithTZ = exports.BaseEntSchema = exports.Node = exports.Timestamps = exports.getTransformedReadClause = exports.SQLStatementOperation = exports.optionalField = exports.requiredField = exports.ConstraintType = exports.NoFields = exports.ActionOperation = exports.getFields = exports.DBType = void 0;
13
+ exports.BaseEntSchemaWithTZ = exports.BaseEntSchema = exports.Node = exports.Timestamps = exports.getObjectLoaderProperties = exports.getTransformedReadClause = exports.SQLStatementOperation = exports.optionalField = exports.requiredField = exports.ConstraintType = exports.NoFields = exports.ActionOperation = exports.getFieldsWithPrivacy = exports.getFields = exports.DBType = void 0;
14
14
  var schema_1 = require("./schema");
15
15
  Object.defineProperty(exports, "DBType", { enumerable: true, get: function () { return schema_1.DBType; } });
16
16
  Object.defineProperty(exports, "getFields", { enumerable: true, get: function () { return schema_1.getFields; } });
17
+ Object.defineProperty(exports, "getFieldsWithPrivacy", { enumerable: true, get: function () { return schema_1.getFieldsWithPrivacy; } });
17
18
  Object.defineProperty(exports, "ActionOperation", { enumerable: true, get: function () { return schema_1.ActionOperation; } });
18
19
  Object.defineProperty(exports, "NoFields", { enumerable: true, get: function () { return schema_1.NoFields; } });
19
20
  Object.defineProperty(exports, "ConstraintType", { enumerable: true, get: function () { return schema_1.ConstraintType; } });
@@ -21,6 +22,7 @@ Object.defineProperty(exports, "requiredField", { enumerable: true, get: functio
21
22
  Object.defineProperty(exports, "optionalField", { enumerable: true, get: function () { return schema_1.optionalField; } });
22
23
  Object.defineProperty(exports, "SQLStatementOperation", { enumerable: true, get: function () { return schema_1.SQLStatementOperation; } });
23
24
  Object.defineProperty(exports, "getTransformedReadClause", { enumerable: true, get: function () { return schema_1.getTransformedReadClause; } });
25
+ Object.defineProperty(exports, "getObjectLoaderProperties", { enumerable: true, get: function () { return schema_1.getObjectLoaderProperties; } });
24
26
  var base_schema_1 = require("./base_schema");
25
27
  Object.defineProperty(exports, "Timestamps", { enumerable: true, get: function () { return base_schema_1.Timestamps; } });
26
28
  Object.defineProperty(exports, "Node", { enumerable: true, get: function () { return base_schema_1.Node; } });
@@ -1,4 +1,4 @@
1
- import { Data, Ent, LoaderInfo, Viewer } from "../core/base";
1
+ import { Data, Ent, LoaderInfo, PrivacyPolicy, Viewer } from "../core/base";
2
2
  import { Builder } from "../action/action";
3
3
  import { Clause } from "../core/clause";
4
4
  export default interface Schema {
@@ -161,6 +161,7 @@ export interface FieldOptions {
161
161
  derivedWhenEmbedded?: boolean;
162
162
  polymorphic?: boolean | PolymorphicOptions;
163
163
  derivedFields?: Field[];
164
+ privacyPolicy?: PrivacyPolicy | (() => PrivacyPolicy);
164
165
  }
165
166
  export interface PolymorphicOptions {
166
167
  types?: string[];
@@ -179,7 +180,14 @@ export interface SchemaConstructor {
179
180
  export declare type SchemaInputType = Schema | SchemaConstructor;
180
181
  export declare function getSchema(value: SchemaInputType): Schema;
181
182
  export declare function getFields(value: SchemaInputType): Map<string, Field>;
183
+ export declare function getStorageKey(field: Field): string;
184
+ export declare function getFieldsWithPrivacy(value: SchemaInputType): Map<string, PrivacyPolicy>;
182
185
  export declare function getTransformedReadClause(value: SchemaInputType): Clause | undefined;
186
+ interface objectLoaderOptions {
187
+ clause?: () => Clause | undefined;
188
+ instanceKey?: string;
189
+ }
190
+ export declare function getObjectLoaderProperties(value: SchemaInputType, tableName: string): objectLoaderOptions | undefined;
183
191
  export declare function getTransformedUpdateOp<T extends Ent>(value: SchemaInputType, stmt: UpdateOperation<T>): TransformedUpdateOperation<T> | undefined;
184
192
  export declare enum ActionOperation {
185
193
  Create = 1,
@@ -223,12 +231,18 @@ export interface Constraint {
223
231
  fkey?: ForeignKeyInfo;
224
232
  condition?: string;
225
233
  }
234
+ export interface FullTextWeight {
235
+ A?: string[];
236
+ B?: string[];
237
+ C?: string[];
238
+ D?: string[];
239
+ }
226
240
  export interface FullText {
227
241
  generatedColumnName?: string;
228
242
  language?: "english" | "french" | "german" | "simple";
229
243
  languageColumn?: string;
230
244
  indexType?: "gin" | "gist";
231
- weights?: string[];
245
+ weights?: FullTextWeight;
232
246
  }
233
247
  export interface Index {
234
248
  name: string;
package/schema/schema.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ConstraintType = exports.optionalField = exports.requiredField = exports.NoFields = exports.ActionOperation = exports.getTransformedUpdateOp = exports.getTransformedReadClause = exports.getFields = exports.getSchema = exports.DBType = exports.SQLStatementOperation = void 0;
3
+ exports.ConstraintType = exports.optionalField = exports.requiredField = exports.NoFields = exports.ActionOperation = exports.getTransformedUpdateOp = exports.getObjectLoaderProperties = exports.getTransformedReadClause = exports.getFieldsWithPrivacy = exports.getStorageKey = exports.getFields = exports.getSchema = exports.DBType = exports.SQLStatementOperation = void 0;
4
+ const snake_case_1 = require("snake-case");
4
5
  // we also want this transformation to exist on a per-action basis
5
6
  // if it exists on an action, we don't do the global schema transformation
6
7
  var SQLStatementOperation;
@@ -72,6 +73,41 @@ function getFields(value) {
72
73
  return m;
73
74
  }
74
75
  exports.getFields = getFields;
76
+ function getStorageKey(field) {
77
+ return field.storageKey || (0, snake_case_1.snakeCase)(field.name);
78
+ }
79
+ exports.getStorageKey = getStorageKey;
80
+ // returns a mapping of storage key to field privacy
81
+ function getFieldsWithPrivacy(value) {
82
+ const schema = getSchema(value);
83
+ function addFields(fields) {
84
+ for (const field of fields) {
85
+ const derivedFields = field.derivedFields;
86
+ if (derivedFields !== undefined) {
87
+ addFields(derivedFields);
88
+ }
89
+ if (field.privacyPolicy) {
90
+ let privacyPolicy;
91
+ if (typeof field.privacyPolicy === "function") {
92
+ privacyPolicy = field.privacyPolicy();
93
+ }
94
+ else {
95
+ privacyPolicy = field.privacyPolicy;
96
+ }
97
+ m.set(getStorageKey(field), privacyPolicy);
98
+ }
99
+ }
100
+ }
101
+ let m = new Map();
102
+ if (schema.patterns) {
103
+ for (const pattern of schema.patterns) {
104
+ addFields(pattern.fields);
105
+ }
106
+ }
107
+ addFields(schema.fields);
108
+ return m;
109
+ }
110
+ exports.getFieldsWithPrivacy = getFieldsWithPrivacy;
75
111
  function getTransformedReadClause(value) {
76
112
  const schema = getSchema(value);
77
113
  if (!schema.patterns) {
@@ -87,6 +123,13 @@ function getTransformedReadClause(value) {
87
123
  return;
88
124
  }
89
125
  exports.getTransformedReadClause = getTransformedReadClause;
126
+ function getObjectLoaderProperties(value, tableName) {
127
+ return {
128
+ clause: () => getTransformedReadClause(value),
129
+ instanceKey: `${tableName}:transformedReadClause`,
130
+ };
131
+ }
132
+ exports.getObjectLoaderProperties = getObjectLoaderProperties;
90
133
  function getTransformedUpdateOp(value, stmt) {
91
134
  const schema = getSchema(value);
92
135
  if (!schema.patterns) {
@@ -147,11 +147,27 @@ class SimpleBuilder {
147
147
  action: action,
148
148
  schema: this.schema,
149
149
  editedFields: () => {
150
- return this.fields;
150
+ // to simulate what we do in generated builders where we return a new Map
151
+ const m = new Map();
152
+ for (const [k, v] of this.fields) {
153
+ m.set(k, v);
154
+ }
155
+ return m;
151
156
  },
152
157
  updateInput: (input) => {
158
+ const knownFields = (0, schema_1.getFields)(this.schema);
153
159
  for (const k in input) {
154
- this.fields.set(k, input[k]);
160
+ if (knownFields.has(k)) {
161
+ this.fields.set(k, input[k]);
162
+ }
163
+ else {
164
+ // related to #510. we do camelCase to pass fields in here but fields may be snakeCase and we want that to pass in tests
165
+ // we do camelCase in
166
+ const sc = (0, snake_case_1.snakeCase)(k);
167
+ if (knownFields.has(sc)) {
168
+ this.fields.set(sc, input[k]);
169
+ }
170
+ }
155
171
  }
156
172
  },
157
173
  });
@@ -71,10 +71,11 @@ export declare class TempDB {
71
71
  constructor(tables: CoreConcept[]);
72
72
  getDialect(): Dialect;
73
73
  getTables(): Map<string, CoreConcept>;
74
- beforeAll(): Promise<void>;
74
+ beforeAll(setupConnString?: boolean): Promise<void>;
75
75
  getSqliteClient(): SqliteDatabase;
76
76
  getPostgresClient(): PGClient;
77
77
  afterAll(): Promise<void>;
78
+ getDB(): string;
78
79
  dropAll(): Promise<void>;
79
80
  drop(...tables: string[]): Promise<void>;
80
81
  create(...tables: CoreConcept[]): Promise<void>;
@@ -336,7 +336,7 @@ class TempDB {
336
336
  getTables() {
337
337
  return this.tables;
338
338
  }
339
- async beforeAll() {
339
+ async beforeAll(setupConnString = true) {
340
340
  if (this.dialect === db_1.Dialect.Postgres) {
341
341
  const user = process.env.POSTGRES_USER || "";
342
342
  const password = process.env.POSTGRES_PASSWORD || "";
@@ -348,11 +348,17 @@ class TempDB {
348
348
  await this.client.connect();
349
349
  this.db = randomDB();
350
350
  await this.client.query(`CREATE DATABASE ${this.db}`);
351
- if (user && password) {
352
- process.env.DB_CONNECTION_STRING = `postgres://${user}:${password}@localhost:5432/${this.db}`;
351
+ if (setupConnString) {
352
+ if (user && password) {
353
+ process.env.DB_CONNECTION_STRING = `postgres://${user}:${password}@localhost:5432/${this.db}`;
354
+ }
355
+ else {
356
+ process.env.DB_CONNECTION_STRING = `postgres://localhost/${this.db}?`;
357
+ }
353
358
  }
354
359
  else {
355
- process.env.DB_CONNECTION_STRING = `postgres://localhost/${this.db}?`;
360
+ // will probably be setup via loadConfig
361
+ delete process.env.DB_CONNECTION_STRING;
356
362
  }
357
363
  this.dbClient = new pg_1.Client({
358
364
  host: "localhost",
@@ -397,6 +403,9 @@ class TempDB {
397
403
  await this.client.query(`DROP DATABASE ${this.db}`);
398
404
  await this.client.end();
399
405
  }
406
+ getDB() {
407
+ return this.db;
408
+ }
400
409
  async dropAll() {
401
410
  for (const [t, _] of this.tables) {
402
411
  await this.drop(t);