@snowtop/ent 0.1.0-alpha88 → 0.1.0-alpha89-16dc3410-33c4-11ed-9fc4-5d4a927887be

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.
@@ -46,7 +46,7 @@ export interface Observer<TEnt extends Ent<TViewer>, TBuilder extends Builder<TE
46
46
  observe(builder: TBuilder, input: TInput): void | Promise<void>;
47
47
  }
48
48
  export interface Validator<TEnt extends Ent<TViewer>, TBuilder extends Builder<TEnt, TViewer, TExistingEnt>, TViewer extends Viewer = Viewer, TInput extends Data = Data, TExistingEnt extends TMaybleNullableEnt<TEnt> = MaybeNull<TEnt>> {
49
- validate(builder: TBuilder, input: TInput): Promise<void> | void;
49
+ validate(builder: TBuilder, input: TInput): Promise<void | undefined | Error> | void | Error | undefined;
50
50
  }
51
51
  export interface Action<TEnt extends Ent<TViewer>, TBuilder extends Builder<TEnt, TViewer, TExistingEnt>, TViewer extends Viewer = Viewer, TInput extends Data = Data, TExistingEnt extends TMaybleNullableEnt<TEnt> = MaybeNull<TEnt>> {
52
52
  readonly viewer: Viewer;
@@ -368,13 +368,14 @@ class Orchestrator {
368
368
  // not ideal we're calling this twice. fix...
369
369
  // needed for now. may need to rewrite some of this?
370
370
  const editedFields2 = await this.options.editedFields();
371
- const [errors, _] = await Promise.all([
371
+ const [errors, errs2] = await Promise.all([
372
372
  this.formatAndValidateFields(schemaFields, editedFields2),
373
373
  this.validators(validators, action, builder),
374
374
  ]);
375
375
  if (privacyError !== null) {
376
376
  errors.unshift(privacyError);
377
377
  }
378
+ errors.push(...errs2);
378
379
  return errors;
379
380
  }
380
381
  async triggers(action, builder, triggers) {
@@ -420,16 +421,19 @@ class Orchestrator {
420
421
  }
421
422
  }
422
423
  async validators(validators, action, builder) {
423
- // TODO need to catch errors and return it...
424
- // don't need it initially since what we need this for doesn't have the errors
425
- let promises = [];
426
- validators.forEach((validator) => {
427
- let res = validator.validate(builder, action.getInput());
428
- if (res) {
429
- promises.push(res);
430
- }
431
- });
432
- await Promise.all(promises);
424
+ const errors = [];
425
+ await Promise.all(validators.map(async (v) => {
426
+ try {
427
+ const r = await v.validate(builder, action.getInput());
428
+ if (r instanceof Error) {
429
+ errors.push(r);
430
+ }
431
+ }
432
+ catch (err) {
433
+ errors.push(err);
434
+ }
435
+ }));
436
+ return errors;
433
437
  }
434
438
  isBuilder(val) {
435
439
  return val.placeholderID !== undefined;
package/core/clause.d.ts CHANGED
@@ -4,6 +4,7 @@ export interface Clause {
4
4
  values(): any[];
5
5
  instanceKey(): string;
6
6
  logValues(): any[];
7
+ compositeOp?: string;
7
8
  }
8
9
  export interface SensitiveValue {
9
10
  value(): any;
@@ -37,6 +38,7 @@ export declare class inClause implements Clause {
37
38
  declare class compositeClause implements Clause {
38
39
  private clauses;
39
40
  private sep;
41
+ compositeOp: string;
40
42
  constructor(clauses: Clause[], sep: string);
41
43
  clause(idx: number): string;
42
44
  columns(): string[];
@@ -97,6 +99,7 @@ export declare function LessEq(col: string, value: any): simpleClause;
97
99
  export declare function And(...args: Clause[]): compositeClause;
98
100
  export declare function AndOptional(...args: (Clause | undefined)[]): Clause;
99
101
  export declare function Or(...args: Clause[]): compositeClause;
102
+ export declare function OrOptional(...args: (Clause | undefined)[]): Clause;
100
103
  export declare function In(col: string, ...values: any): Clause;
101
104
  export declare function In(col: string, values: any[], type?: string): Clause;
102
105
  interface TsQuery {
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.JSONPathValuePredicate = exports.JSONObjectFieldKeyAsText = exports.JSONObjectFieldKeyASJSON = 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.ArrayNotEq = exports.ArrayEq = exports.PostgresArrayNotOverlaps = exports.PostgresArrayOverlaps = exports.PostgresArrayNotContains = exports.PostgresArrayNotContainsValue = exports.PostgresArrayContains = exports.PostgresArrayContainsValue = exports.inClause = void 0;
22
+ exports.JSONPathValuePredicate = exports.JSONObjectFieldKeyAsText = exports.JSONObjectFieldKeyASJSON = exports.sensitiveValue = exports.TsVectorWebsearchToTsQuery = exports.TsVectorPhraseToTsQuery = exports.TsVectorPlainToTsQuery = exports.TsVectorColTsQuery = exports.WebsearchToTsQuery = exports.PhraseToTsQuery = exports.PlainToTsQuery = exports.TsQuery = exports.In = exports.OrOptional = exports.Or = exports.AndOptional = exports.And = exports.LessEq = exports.GreaterEq = exports.Less = exports.Greater = exports.NotEq = exports.Eq = exports.ArrayNotEq = exports.ArrayEq = exports.PostgresArrayNotOverlaps = exports.PostgresArrayOverlaps = exports.PostgresArrayNotContains = exports.PostgresArrayNotContainsValue = exports.PostgresArrayContains = exports.PostgresArrayContainsValue = exports.inClause = void 0;
23
23
  const db_1 = __importStar(require("./db"));
24
24
  function isSensitive(val) {
25
25
  return (val !== null &&
@@ -59,9 +59,9 @@ class simpleClause {
59
59
  return [this.col];
60
60
  }
61
61
  values() {
62
- const sqliteClause = this.nullClause();
63
- if (sqliteClause) {
64
- return sqliteClause.values();
62
+ const nullClause = this.nullClause();
63
+ if (nullClause) {
64
+ return nullClause.values();
65
65
  }
66
66
  if (isSensitive(this.value)) {
67
67
  return [this.value.value()];
@@ -69,9 +69,9 @@ class simpleClause {
69
69
  return [this.value];
70
70
  }
71
71
  logValues() {
72
- const sqliteClause = this.nullClause();
73
- if (sqliteClause) {
74
- return sqliteClause.logValues();
72
+ const nullClause = this.nullClause();
73
+ if (nullClause) {
74
+ return nullClause.logValues();
75
75
  }
76
76
  if (isSensitive(this.value)) {
77
77
  return [this.value.logValue()];
@@ -79,9 +79,9 @@ class simpleClause {
79
79
  return [this.value];
80
80
  }
81
81
  instanceKey() {
82
- const sqliteClause = this.nullClause();
83
- if (sqliteClause) {
84
- return sqliteClause.instanceKey();
82
+ const nullClause = this.nullClause();
83
+ if (nullClause) {
84
+ return nullClause.instanceKey();
85
85
  }
86
86
  return `${this.col}${this.op}${rawValue(this.value)}`;
87
87
  }
@@ -300,11 +300,17 @@ class compositeClause {
300
300
  constructor(clauses, sep) {
301
301
  this.clauses = clauses;
302
302
  this.sep = sep;
303
+ this.compositeOp = this.sep;
303
304
  }
304
305
  clause(idx) {
305
306
  let clauses = [];
306
307
  for (const clause of this.clauses) {
307
- clauses.push(clause.clause(idx));
308
+ let cls = clause.clause(idx);
309
+ // if composite clause and a different op, add parens so that we enforce order of precedence
310
+ if (clause.compositeOp && clause.compositeOp !== this.sep) {
311
+ cls = `(${cls})`;
312
+ }
313
+ clauses.push(cls);
308
314
  idx = idx + clause.values().length;
309
315
  }
310
316
  return clauses.join(this.sep);
@@ -332,7 +338,14 @@ class compositeClause {
332
338
  }
333
339
  instanceKey() {
334
340
  let keys = [];
335
- this.clauses.forEach((clause) => keys.push(clause.instanceKey()));
341
+ this.clauses.forEach((clause) => {
342
+ if (clause.compositeOp && clause.compositeOp != this.sep) {
343
+ keys.push(`(${clause.instanceKey()})`);
344
+ }
345
+ else {
346
+ keys.push(clause.instanceKey());
347
+ }
348
+ });
336
349
  return keys.join(this.sep);
337
350
  }
338
351
  }
@@ -513,6 +526,15 @@ function Or(...args) {
513
526
  return new compositeClause(args, " OR ");
514
527
  }
515
528
  exports.Or = Or;
529
+ function OrOptional(...args) {
530
+ // @ts-ignore
531
+ let filtered = args.filter((v) => v !== undefined);
532
+ if (filtered.length === 1) {
533
+ return filtered[0];
534
+ }
535
+ return Or(...filtered);
536
+ }
537
+ exports.OrOptional = OrOptional;
516
538
  function In(...args) {
517
539
  if (args.length < 2) {
518
540
  throw new Error(`invalid args passed to In`);
package/core/db.d.ts CHANGED
@@ -77,6 +77,7 @@ interface SqliteRunResult {
77
77
  }
78
78
  interface SqliteDatabase {
79
79
  memory: boolean;
80
+ exec(query: string): SqliteStatement;
80
81
  prepare(query: string): SqliteStatement;
81
82
  close(): void;
82
83
  transaction(fn: (...params: any[]) => any): SqliteTransaction;
package/core/ent.d.ts CHANGED
@@ -229,6 +229,6 @@ interface loadEdgeForIDOptions<T extends AssocEdge> extends loadCustomEdgesOptio
229
229
  export declare function loadEdgeForID2<T extends AssocEdge>(options: loadEdgeForIDOptions<T>): Promise<T | undefined>;
230
230
  export declare function loadNodesByEdge<T extends Ent>(viewer: Viewer, id1: ID, edgeType: string, options: LoadEntOptions<T>): Promise<T[]>;
231
231
  export declare function applyPrivacyPolicyForRow<TEnt extends Ent<TViewer>, TViewer extends Viewer>(viewer: TViewer, options: LoadEntOptions<TEnt, TViewer>, row: Data): Promise<TEnt | null>;
232
- export declare function applyPrivacyPolicyForRows<TEnt extends Ent<TViewer>, TViewer extends Viewer>(viewer: TViewer, rows: Data[], options: LoadEntOptions<TEnt, TViewer>): Promise<Map<ID, TEnt>>;
232
+ export declare function applyPrivacyPolicyForRows<TEnt extends Ent<TViewer>, TViewer extends Viewer>(viewer: TViewer, rows: Data[], options: LoadEntOptions<TEnt, TViewer>): Promise<TEnt[]>;
233
233
  export declare function getEdgeTypeInGroup<T extends string>(viewer: Viewer, id1: ID, id2: ID, m: Map<T, string>): Promise<[T, AssocEdge] | undefined>;
234
234
  export {};
package/core/ent.js CHANGED
@@ -196,6 +196,11 @@ function getEntKey(viewer, id, options) {
196
196
  }
197
197
  exports.getEntKey = getEntKey;
198
198
  async function loadEnt(viewer, id, options) {
199
+ if (typeof id !== "string" &&
200
+ typeof id !== "number" &&
201
+ typeof id !== "bigint") {
202
+ throw new Error(`invalid id ${id} passed to loadEnt`);
203
+ }
199
204
  const r = await getEntLoader(viewer, options).load(id);
200
205
  return r instanceof ErrorWrapper ? null : r;
201
206
  }
@@ -239,6 +244,11 @@ async function loadEntViaKey(viewer, key, options) {
239
244
  }
240
245
  exports.loadEntViaKey = loadEntViaKey;
241
246
  async function loadEntX(viewer, id, options) {
247
+ if (typeof id !== "string" &&
248
+ typeof id !== "number" &&
249
+ typeof id !== "bigint") {
250
+ throw new Error(`invalid id ${id} passed to loadEntX`);
251
+ }
242
252
  const r = await getEntLoader(viewer, options).load(id);
243
253
  if (r instanceof ErrorWrapper) {
244
254
  throw r.error;
@@ -338,25 +348,12 @@ async function loadEntsFromClause(viewer, clause, options) {
338
348
  context: viewer.context,
339
349
  };
340
350
  const rows = await loadRows(rowOptions);
341
- return await applyPrivacyPolicyForRows(viewer, rows, options);
351
+ return applyPrivacyPolicyForRowsDeprecated(viewer, rows, options);
342
352
  }
343
353
  exports.loadEntsFromClause = loadEntsFromClause;
344
354
  async function loadCustomEnts(viewer, options, query) {
345
355
  const rows = await loadCustomData(options, query, viewer.context);
346
- const result = new Array(rows.length);
347
- if (!rows.length) {
348
- return [];
349
- }
350
- const entLoader = getEntLoader(viewer, options);
351
- await Promise.all(rows.map(async (row, idx) => {
352
- const r = await applyPrivacyPolicyForRowAndStoreInEntLoader(viewer, row, options, entLoader);
353
- if (r instanceof ErrorWrapper) {
354
- return;
355
- }
356
- result[idx] = r;
357
- }));
358
- // filter ents that aren't visible because of privacy
359
- return result.filter((r) => r !== undefined);
356
+ return applyPrivacyPolicyForRows(viewer, rows, options);
360
357
  }
361
358
  exports.loadCustomEnts = loadCustomEnts;
362
359
  function isClause(opts) {
@@ -1540,10 +1537,8 @@ async function applyPrivacyPolicyForRowX(viewer, options, row) {
1540
1537
  const ent = new options.ent(viewer, row);
1541
1538
  return await applyPrivacyPolicyForEntX(viewer, ent, row, options);
1542
1539
  }
1543
- // TODO this needs to be changed to use ent cache as needed...
1544
- // most current callsites fine not using it
1545
- // custom_query is one that should be updated
1546
- async function applyPrivacyPolicyForRows(viewer, rows, options) {
1540
+ // deprecated. doesn't use entcache
1541
+ async function applyPrivacyPolicyForRowsDeprecated(viewer, rows, options) {
1547
1542
  let m = new Map();
1548
1543
  // apply privacy logic
1549
1544
  await Promise.all(rows.map(async (row) => {
@@ -1554,6 +1549,22 @@ async function applyPrivacyPolicyForRows(viewer, rows, options) {
1554
1549
  }));
1555
1550
  return m;
1556
1551
  }
1552
+ async function applyPrivacyPolicyForRows(viewer, rows, options) {
1553
+ const result = new Array(rows.length);
1554
+ if (!rows.length) {
1555
+ return [];
1556
+ }
1557
+ const entLoader = getEntLoader(viewer, options);
1558
+ await Promise.all(rows.map(async (row, idx) => {
1559
+ const r = await applyPrivacyPolicyForRowAndStoreInEntLoader(viewer, row, options, entLoader);
1560
+ if (r instanceof ErrorWrapper) {
1561
+ return;
1562
+ }
1563
+ result[idx] = r;
1564
+ }));
1565
+ // filter ents that aren't visible because of privacy
1566
+ return result.filter((r) => r !== undefined);
1567
+ }
1557
1568
  exports.applyPrivacyPolicyForRows = applyPrivacyPolicyForRows;
1558
1569
  async function loadEdgeWithConst(viewer, id1, id2, edgeEnum, edgeType) {
1559
1570
  const edge = await loadEdgeForID2({
@@ -3,4 +3,4 @@ export { RawCountLoader, RawCountLoaderFactory } from "./raw_count_loader";
3
3
  export { AssocEdgeCountLoader, AssocEdgeCountLoaderFactory, } from "./assoc_count_loader";
4
4
  export { AssocDirectEdgeLoader, AssocEdgeLoader, AssocEdgeLoaderFactory, } from "./assoc_edge_loader";
5
5
  export { IndexLoaderFactory } from "./index_loader";
6
- export { QueryLoader, QueryDirectLoader, QueryLoaderFactory, } from "./query_loader";
6
+ export { QueryLoaderFactory } from "./query_loader";
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.QueryLoaderFactory = exports.QueryDirectLoader = exports.QueryLoader = exports.IndexLoaderFactory = exports.AssocEdgeLoaderFactory = exports.AssocEdgeLoader = exports.AssocDirectEdgeLoader = exports.AssocEdgeCountLoaderFactory = exports.AssocEdgeCountLoader = exports.RawCountLoaderFactory = exports.RawCountLoader = exports.ObjectLoaderFactory = exports.ObjectLoader = void 0;
3
+ exports.QueryLoaderFactory = exports.IndexLoaderFactory = exports.AssocEdgeLoaderFactory = exports.AssocEdgeLoader = exports.AssocDirectEdgeLoader = exports.AssocEdgeCountLoaderFactory = exports.AssocEdgeCountLoader = exports.RawCountLoaderFactory = exports.RawCountLoader = exports.ObjectLoaderFactory = exports.ObjectLoader = void 0;
4
4
  var object_loader_1 = require("./object_loader");
5
5
  Object.defineProperty(exports, "ObjectLoader", { enumerable: true, get: function () { return object_loader_1.ObjectLoader; } });
6
6
  Object.defineProperty(exports, "ObjectLoaderFactory", { enumerable: true, get: function () { return object_loader_1.ObjectLoaderFactory; } });
@@ -17,6 +17,4 @@ Object.defineProperty(exports, "AssocEdgeLoaderFactory", { enumerable: true, get
17
17
  var index_loader_1 = require("./index_loader");
18
18
  Object.defineProperty(exports, "IndexLoaderFactory", { enumerable: true, get: function () { return index_loader_1.IndexLoaderFactory; } });
19
19
  var query_loader_1 = require("./query_loader");
20
- Object.defineProperty(exports, "QueryLoader", { enumerable: true, get: function () { return query_loader_1.QueryLoader; } });
21
- Object.defineProperty(exports, "QueryDirectLoader", { enumerable: true, get: function () { return query_loader_1.QueryDirectLoader; } });
22
20
  Object.defineProperty(exports, "QueryLoaderFactory", { enumerable: true, get: function () { return query_loader_1.QueryLoaderFactory; } });
@@ -1,4 +1,4 @@
1
- import { ID, SelectBaseDataOptions, Context, Data, LoaderFactory, EdgeQueryableDataOptions } from "../base";
1
+ import { ID, SelectBaseDataOptions, Context, Data, LoaderFactory, EdgeQueryableDataOptions, Loader } from "../base";
2
2
  import * as clause from "../clause";
3
3
  import { ObjectLoaderFactory } from "./object_loader";
4
4
  export declare class IndexLoaderFactory implements LoaderFactory<ID, Data[]> {
@@ -10,5 +10,5 @@ export declare class IndexLoaderFactory implements LoaderFactory<ID, Data[]> {
10
10
  toPrime?: ObjectLoaderFactory<ID>[];
11
11
  });
12
12
  createLoader(context?: Context): any;
13
- createConfigurableLoader(options: EdgeQueryableDataOptions, context?: Context): import("../base").Loader<unknown, Data[]> | import("./query_loader").QueryDirectLoader<unknown>;
13
+ createConfigurableLoader(options: EdgeQueryableDataOptions, context?: Context): Loader<ID, Data[]>;
14
14
  }
@@ -1,21 +1,14 @@
1
1
  import { Context, ID, EdgeQueryableDataOptions, Loader, LoaderFactory, Data } from "../base";
2
2
  import * as clause from "../clause";
3
3
  import { ObjectLoaderFactory } from "./object_loader";
4
- export declare class QueryDirectLoader<K extends any> implements Loader<K, Data[]> {
4
+ export declare function getOrderBy(sortCol: string, orderby?: string): string;
5
+ declare class QueryDirectLoader<K extends any> implements Loader<K, Data[]> {
5
6
  private options;
6
7
  private queryOptions?;
7
- constructor(options: QueryOptions, queryOptions?: Partial<Pick<import("../base").QueryableDataOptions, "limit" | "orderby" | "clause">> | undefined);
8
- load(id: K): Promise<Data[]>;
9
- clearAll(): void;
10
- }
11
- export declare class QueryLoader<K extends any> implements Loader<K, Data[]> {
12
- private options;
13
8
  context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined;
14
- private queryOptions?;
15
- private loader;
16
- private primedLoaders;
17
9
  private memoizedInitPrime;
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);
10
+ private primedLoaders;
11
+ constructor(options: QueryOptions, queryOptions?: Partial<Pick<import("../base").QueryableDataOptions, "limit" | "orderby" | "clause">> | undefined, context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined);
19
12
  private initPrime;
20
13
  load(id: K): Promise<Data[]>;
21
14
  clearAll(): void;
@@ -34,5 +27,6 @@ export declare class QueryLoaderFactory<K extends any> implements LoaderFactory<
34
27
  constructor(options: QueryOptions);
35
28
  createLoader(context?: Context): any;
36
29
  createConfigurableLoader(options: EdgeQueryableDataOptions, context?: Context): Loader<unknown, Data[]> | QueryDirectLoader<unknown>;
30
+ static createConfigurableLoader(name: string, queryOptions: QueryOptions, options: EdgeQueryableDataOptions, context?: Context): Loader<unknown, Data[]> | QueryDirectLoader<unknown>;
37
31
  }
38
32
  export {};
@@ -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.QueryLoaderFactory = exports.QueryLoader = exports.QueryDirectLoader = void 0;
25
+ exports.QueryLoaderFactory = exports.getOrderBy = void 0;
26
26
  const dataloader_1 = __importDefault(require("dataloader"));
27
27
  const ent_1 = require("../ent");
28
28
  const clause = __importStar(require("../clause"));
@@ -30,13 +30,17 @@ const logger_1 = require("../logger");
30
30
  const loader_1 = require("./loader");
31
31
  const memoizee_1 = __importDefault(require("memoizee"));
32
32
  function getOrderBy(sortCol, orderby) {
33
+ if (orderby) {
34
+ return orderby;
35
+ }
33
36
  let sortColLower = sortCol.toLowerCase();
34
37
  let orderbyDirection = " DESC";
35
38
  if (sortColLower.endsWith("asc") || sortCol.endsWith("desc")) {
36
39
  orderbyDirection = "";
37
40
  }
38
- return orderby || `${sortCol}${orderbyDirection}`;
41
+ return `${sortCol}${orderbyDirection}`;
39
42
  }
43
+ exports.getOrderBy = getOrderBy;
40
44
  async function simpleCase(options, id, queryOptions) {
41
45
  let cls;
42
46
  if (options.groupCol) {
@@ -120,16 +124,47 @@ function createLoader(options, queryOptions) {
120
124
  }, loaderOptions);
121
125
  }
122
126
  class QueryDirectLoader {
123
- constructor(options, queryOptions) {
127
+ constructor(options, queryOptions, context) {
124
128
  this.options = options;
125
129
  this.queryOptions = queryOptions;
130
+ this.context = context;
131
+ this.memoizedInitPrime = (0, memoizee_1.default)(this.initPrime.bind(this));
132
+ }
133
+ initPrime() {
134
+ if (!this.context || !this.options?.toPrime) {
135
+ return;
136
+ }
137
+ let primedLoaders = new Map();
138
+ this.options.toPrime.forEach((prime) => {
139
+ const l2 = prime.createLoader(this.context);
140
+ if (l2.prime === undefined) {
141
+ return;
142
+ }
143
+ primedLoaders.set(prime.options.key, l2);
144
+ });
145
+ this.primedLoaders = primedLoaders;
126
146
  }
127
147
  async load(id) {
128
- return simpleCase(this.options, id, this.queryOptions);
148
+ const rows = await simpleCase(this.options, id, this.queryOptions);
149
+ if (this.context) {
150
+ this.memoizedInitPrime();
151
+ if (this.primedLoaders) {
152
+ for (const row of rows) {
153
+ for (const [key, loader] of this.primedLoaders) {
154
+ const value = row[key];
155
+ if (value !== undefined) {
156
+ loader.prime(row);
157
+ }
158
+ }
159
+ }
160
+ }
161
+ }
162
+ return rows;
129
163
  }
130
164
  clearAll() { }
131
165
  }
132
- exports.QueryDirectLoader = QueryDirectLoader;
166
+ // note, you should never call this directly
167
+ // there's scenarios where QueryDirectLoader is needed instead of this...
133
168
  class QueryLoader {
134
169
  constructor(options, context, queryOptions) {
135
170
  this.options = options;
@@ -176,7 +211,6 @@ class QueryLoader {
176
211
  this.loader && this.loader.clearAll();
177
212
  }
178
213
  }
179
- exports.QueryLoader = QueryLoader;
180
214
  class QueryLoaderFactory {
181
215
  constructor(options) {
182
216
  this.options = options;
@@ -194,11 +228,14 @@ class QueryLoaderFactory {
194
228
  return (0, loader_1.getLoader)(this, () => new QueryLoader(this.options, context), context);
195
229
  }
196
230
  createConfigurableLoader(options, context) {
197
- if (options?.clause || !context) {
198
- return new QueryDirectLoader(this.options, options);
231
+ return QueryLoaderFactory.createConfigurableLoader(this.name, this.options, options, context);
232
+ }
233
+ static createConfigurableLoader(name, queryOptions, options, context) {
234
+ if (options.clause || !context) {
235
+ return new QueryDirectLoader(queryOptions, options, context);
199
236
  }
200
- const key = `${this.name}:limit:${options.limit}:orderby:${options.orderby}`;
201
- return (0, loader_1.getCustomLoader)(key, () => new QueryLoader(this.options, context, options), context);
237
+ const key = `${name}:limit:${options.limit}:orderby:${options.orderby}`;
238
+ return (0, loader_1.getCustomLoader)(key, () => new QueryLoader(queryOptions, context, options), context);
202
239
  }
203
240
  }
204
241
  exports.QueryLoaderFactory = QueryLoaderFactory;
@@ -0,0 +1,24 @@
1
+ import { Data, EdgeQueryableDataOptions, Ent, ID, LoadEntOptions, Viewer } from "../base";
2
+ import { Clause } from "../clause";
3
+ import { BaseEdgeQuery, IDInfo } from "./query";
4
+ interface CustomClauseQueryOptions<TDest extends Ent<TViewer>, TViewer extends Viewer = Viewer> {
5
+ loadEntOptions: LoadEntOptions<TDest, TViewer>;
6
+ clause: Clause;
7
+ name: string;
8
+ sortColumn?: string;
9
+ disableTransformations?: boolean;
10
+ }
11
+ export declare class CustomClauseQuery<TDest extends Ent<TViewer>, TViewer extends Viewer = Viewer> extends BaseEdgeQuery<any, TDest, Data> {
12
+ viewer: TViewer;
13
+ private options;
14
+ private clause;
15
+ constructor(viewer: TViewer, options: CustomClauseQueryOptions<TDest, TViewer>);
16
+ sourceEnt(_id: ID): Promise<null>;
17
+ queryRawCount(): Promise<number>;
18
+ queryAllRawCount(): Promise<Map<ID, number>>;
19
+ protected loadRawIDs(_addID: (src: ID) => void): Promise<void>;
20
+ protected loadRawData(_infos: IDInfo[], options: EdgeQueryableDataOptions): Promise<void>;
21
+ dataToID(edge: Data): ID;
22
+ protected loadEntsFromEdges(id: ID, rows: Data[]): Promise<TDest[]>;
23
+ }
24
+ export {};
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CustomClauseQuery = void 0;
4
+ const clause_1 = require("../clause");
5
+ const ent_1 = require("../ent");
6
+ const query_loader_1 = require("../loaders/query_loader");
7
+ const query_1 = require("./query");
8
+ function getClause(opts) {
9
+ let cls = opts.clause;
10
+ if (opts.disableTransformations) {
11
+ return cls;
12
+ }
13
+ let optClause = opts.loadEntOptions.loaderFactory?.options?.clause;
14
+ if (typeof optClause === "function") {
15
+ optClause = optClause();
16
+ }
17
+ if (!optClause) {
18
+ return cls;
19
+ }
20
+ return (0, clause_1.AndOptional)(cls, optClause);
21
+ }
22
+ class CustomClauseQuery extends query_1.BaseEdgeQuery {
23
+ constructor(viewer, options) {
24
+ super(viewer, options.sortColumn || "created_at");
25
+ this.viewer = viewer;
26
+ this.options = options;
27
+ this.clause = getClause(options);
28
+ }
29
+ async sourceEnt(_id) {
30
+ return null;
31
+ }
32
+ async queryRawCount() {
33
+ const row = await (0, ent_1.loadRow)({
34
+ tableName: this.options.loadEntOptions.tableName,
35
+ // sqlite needs as count otherwise it returns count(1)
36
+ fields: ["count(1) as count"],
37
+ clause: this.clause,
38
+ context: this.viewer.context,
39
+ });
40
+ return parseInt(row?.count, 10) || 0;
41
+ }
42
+ async queryAllRawCount() {
43
+ throw new Error(`queryAllRawCount doesn't make sense in CustomClauseQuery`);
44
+ }
45
+ // nothing to do here
46
+ async loadRawIDs(_addID) { }
47
+ async loadRawData(_infos, options) {
48
+ if (!options.orderby) {
49
+ options.orderby = `${this.options.sortColumn} DESC`;
50
+ }
51
+ if (!options.limit) {
52
+ options.limit = ent_1.DefaultLimit;
53
+ }
54
+ let sortCol = this.options.sortColumn || "created_at";
55
+ const rows = await (0, ent_1.loadRows)({
56
+ tableName: this.options.loadEntOptions.tableName,
57
+ fields: this.options.loadEntOptions.fields,
58
+ clause: (0, clause_1.AndOptional)(this.clause, options.clause),
59
+ orderby: (0, query_loader_1.getOrderBy)(sortCol, options?.orderby),
60
+ limit: options?.limit || ent_1.DefaultLimit,
61
+ context: this.viewer.context,
62
+ });
63
+ this.edges.set(1, rows);
64
+ }
65
+ dataToID(edge) {
66
+ return edge.id;
67
+ }
68
+ async loadEntsFromEdges(id, rows) {
69
+ return (0, ent_1.applyPrivacyPolicyForRows)(this.viewer, rows, this.options.loadEntOptions);
70
+ }
71
+ }
72
+ exports.CustomClauseQuery = CustomClauseQuery;
@@ -1,22 +1,37 @@
1
1
  import { Data, Ent, ID, EdgeQueryableDataOptions, LoadEntOptions, Viewer, LoaderFactory, ConfigurableLoaderFactory } from "../base";
2
+ import { Clause } from "../clause";
2
3
  import { BaseEdgeQuery, IDInfo, EdgeQuery } from "./query";
3
- export interface CustomEdgeQueryOptions<TSource extends Ent<TViewer>, TDest extends Ent<TViewer>, TViewer extends Viewer = Viewer> {
4
+ export interface CustomEdgeQueryOptionsDeprecated<TSource extends Ent<TViewer>, TDest extends Ent<TViewer>, TViewer extends Viewer = Viewer> {
4
5
  src: TSource | ID;
5
6
  countLoaderFactory: LoaderFactory<ID, number>;
6
7
  dataLoaderFactory: ConfigurableLoaderFactory<ID, Data[]>;
7
8
  options: LoadEntOptions<TDest, TViewer>;
8
9
  sortColumn?: string;
9
10
  }
11
+ export interface CustomEdgeQueryOptions<TSource extends Ent<TViewer>, TDest extends Ent<TViewer>, TViewer extends Viewer = Viewer> {
12
+ src: TSource | ID;
13
+ loadEntOptions: LoadEntOptions<TDest, TViewer>;
14
+ groupCol?: string;
15
+ clause?: Clause;
16
+ name: string;
17
+ sortColumn?: string;
18
+ disableTransformations?: boolean;
19
+ }
10
20
  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
21
  viewer: TViewer;
12
22
  private options;
13
23
  private id;
14
- constructor(viewer: TViewer, options: CustomEdgeQueryOptions<TSource, TDest, TViewer>);
24
+ private opts;
25
+ constructor(viewer: TViewer, options: CustomEdgeQueryOptionsDeprecated<TSource, TDest, TViewer> | CustomEdgeQueryOptions<TSource, TDest, TViewer>);
15
26
  abstract sourceEnt(id: ID): Promise<Ent | null>;
16
27
  private idVisible;
28
+ private isDeprecatedOptions;
29
+ private getCountLoader;
30
+ private getQueryLoader;
17
31
  queryRawCount(): Promise<number>;
18
32
  queryAllRawCount(): Promise<Map<ID, number>>;
19
33
  protected loadRawIDs(addID: (src: ID | TSource) => void): Promise<void>;
34
+ private getLoadEntOptions;
20
35
  protected loadRawData(infos: IDInfo[], options: EdgeQueryableDataOptions): Promise<void>;
21
36
  dataToID(edge: Data): ID;
22
37
  protected loadEntsFromEdges(id: ID, rows: Data[]): Promise<TDest[]>;