@snowtop/ent 0.1.0-alpha152 → 0.1.0-alpha154

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 (46) hide show
  1. package/action/index.d.ts +1 -0
  2. package/action/operations.d.ts +3 -2
  3. package/action/operations.js +8 -6
  4. package/action/orchestrator.d.ts +5 -0
  5. package/action/orchestrator.js +37 -5
  6. package/core/base.d.ts +5 -3
  7. package/core/context.d.ts +2 -1
  8. package/core/context.js +2 -1
  9. package/core/ent.d.ts +3 -3
  10. package/core/ent.js +10 -4
  11. package/core/loaders/assoc_count_loader.d.ts +4 -2
  12. package/core/loaders/assoc_count_loader.js +10 -2
  13. package/core/loaders/assoc_edge_loader.d.ts +2 -3
  14. package/core/loaders/assoc_edge_loader.js +14 -4
  15. package/core/loaders/index_loader.d.ts +2 -1
  16. package/core/loaders/index_loader.js +1 -1
  17. package/core/loaders/query_loader.d.ts +3 -3
  18. package/core/loaders/query_loader.js +11 -16
  19. package/core/privacy.d.ts +19 -10
  20. package/core/privacy.js +33 -21
  21. package/core/query/assoc_query.js +1 -1
  22. package/core/query/custom_clause_query.d.ts +4 -2
  23. package/core/query/custom_clause_query.js +32 -15
  24. package/core/query/custom_query.d.ts +3 -1
  25. package/core/query/custom_query.js +28 -5
  26. package/core/query/query.d.ts +6 -4
  27. package/core/query/query.js +51 -46
  28. package/core/query/shared_assoc_test.js +142 -1
  29. package/core/query/shared_test.d.ts +2 -2
  30. package/core/query/shared_test.js +26 -29
  31. package/core/query_impl.d.ts +8 -0
  32. package/core/query_impl.js +28 -0
  33. package/graphql/index.d.ts +1 -1
  34. package/graphql/index.js +3 -1
  35. package/graphql/scalars/orderby_direction.js +2 -2
  36. package/index.d.ts +1 -0
  37. package/index.js +1 -0
  38. package/package.json +1 -1
  39. package/parse_schema/parse.d.ts +1 -0
  40. package/parse_schema/parse.js +1 -0
  41. package/testutils/fake_data/fake_user.js +15 -4
  42. package/testutils/fake_data/tag_query.js +8 -3
  43. package/testutils/fake_data/test_helpers.d.ts +3 -2
  44. package/testutils/fake_data/test_helpers.js +3 -3
  45. package/testutils/fake_data/user_query.d.ts +5 -2
  46. package/testutils/fake_data/user_query.js +19 -2
package/action/index.d.ts CHANGED
@@ -3,3 +3,4 @@ export { OrchestratorOptions, Orchestrator, EntChangeset, EdgeInputData, } from
3
3
  export { DenyIfBuilder, AllowIfBuilder } from "./privacy";
4
4
  export { RelativeFieldValue, RelativeNumberValue, NumberOps, convertRelativeInput, maybeConvertRelativeInputPlusExpressions, } from "./relative_value";
5
5
  export { Transaction } from "./transaction";
6
+ export { AssocEdgeOptions } from "./operations";
@@ -68,6 +68,7 @@ export interface AssocEdgeInputOptions extends AssocEdgeOptions {
68
68
  }
69
69
  export interface AssocEdgeOptions {
70
70
  conditional?: boolean;
71
+ disableTransformations?: boolean;
71
72
  }
72
73
  export interface AssocEdgeInput extends AssocEdgeInputOptions {
73
74
  id1: ID;
@@ -100,8 +101,8 @@ export declare class EdgeOperation implements DataOperation {
100
101
  private static resolveData;
101
102
  static inboundEdge<T extends Ent, T2 extends Ent>(builder: Builder<T>, edgeType: string, id1: Builder<T2> | ID, nodeType: string, options?: AssocEdgeInputOptions): EdgeOperation;
102
103
  static outboundEdge<T extends Ent, T2 extends Ent>(builder: Builder<T>, edgeType: string, id2: Builder<T2> | ID, nodeType: string, options?: AssocEdgeInputOptions): EdgeOperation;
103
- static removeInboundEdge<T extends Ent>(builder: Builder<T>, edgeType: string, id1: ID): EdgeOperation;
104
- static removeOutboundEdge<T extends Ent>(builder: Builder<T>, edgeType: string, id2: ID): EdgeOperation;
104
+ static removeInboundEdge<T extends Ent>(builder: Builder<T>, edgeType: string, id1: ID, options?: AssocEdgeInputOptions): EdgeOperation;
105
+ static removeOutboundEdge<T extends Ent>(builder: Builder<T>, edgeType: string, id2: ID, options?: AssocEdgeInputOptions): EdgeOperation;
105
106
  }
106
107
  export declare class ConditionalOperation<T extends Ent = Ent> implements DataOperation<T> {
107
108
  protected op: DataOperation<T>;
@@ -311,9 +311,8 @@ class EdgeOperation {
311
311
  let transformed = null;
312
312
  let op = schema_1.SQLStatementOperation.Delete;
313
313
  let updateData = null;
314
- // TODO respect disableTransformations
315
314
  const transformedEdgeWrite = (0, global_schema_1.__getGlobalSchema)()?.transformEdgeWrite;
316
- if (transformedEdgeWrite) {
315
+ if (transformedEdgeWrite && !edge.disableTransformations) {
317
316
  transformed = transformedEdgeWrite({
318
317
  op: schema_1.SQLStatementOperation.Delete,
319
318
  edge,
@@ -405,10 +404,9 @@ class EdgeOperation {
405
404
  }
406
405
  }
407
406
  }
408
- // TODO respect disableTransformations
409
407
  let transformed = null;
410
408
  const transformEdgeWrite = (0, global_schema_1.__getGlobalSchema)()?.transformEdgeWrite;
411
- if (transformEdgeWrite) {
409
+ if (transformEdgeWrite && !edge.disableTransformations) {
412
410
  transformed = transformEdgeWrite({
413
411
  op: schema_1.SQLStatementOperation.Insert,
414
412
  edge,
@@ -471,6 +469,7 @@ class EdgeOperation {
471
469
  edgeType: this.edgeInput.edgeType,
472
470
  time: this.edgeInput.time,
473
471
  data: this.edgeInput.data,
472
+ disableTransformations: this.edgeInput.disableTransformations,
474
473
  }, {
475
474
  operation: this.options.operation,
476
475
  id1Placeholder: this.options.id2Placeholder,
@@ -487,6 +486,7 @@ class EdgeOperation {
487
486
  edgeType: edgeData.inverseEdgeType,
488
487
  time: this.edgeInput.time,
489
488
  data: this.edgeInput.data,
489
+ disableTransformations: this.edgeInput.disableTransformations,
490
490
  }, {
491
491
  operation: this.options.operation,
492
492
  id1Placeholder: this.options.id2Placeholder,
@@ -575,7 +575,7 @@ class EdgeOperation {
575
575
  dataPlaceholder,
576
576
  });
577
577
  }
578
- static removeInboundEdge(builder, edgeType, id1) {
578
+ static removeInboundEdge(builder, edgeType, id1, options) {
579
579
  if (!builder.existingEnt) {
580
580
  throw new Error("cannot remove an edge from a non-existing ent");
581
581
  }
@@ -585,12 +585,13 @@ class EdgeOperation {
585
585
  id2: builder.existingEnt.id,
586
586
  id2Type: "",
587
587
  id1Type: "",
588
+ disableTransformations: options?.disableTransformations,
588
589
  };
589
590
  return new EdgeOperation(builder, edge, {
590
591
  operation: action_1.WriteOperation.Delete,
591
592
  });
592
593
  }
593
- static removeOutboundEdge(builder, edgeType, id2) {
594
+ static removeOutboundEdge(builder, edgeType, id2, options) {
594
595
  if (!builder.existingEnt) {
595
596
  throw new Error("cannot remove an edge from a non-existing ent");
596
597
  }
@@ -600,6 +601,7 @@ class EdgeOperation {
600
601
  id1: builder.existingEnt.id,
601
602
  id2Type: "",
602
603
  id1Type: "",
604
+ disableTransformations: options?.disableTransformations,
603
605
  };
604
606
  return new EdgeOperation(builder, edge, {
605
607
  operation: action_1.WriteOperation.Delete,
@@ -121,6 +121,11 @@ export declare class EntChangeset<T extends Ent> implements Changeset {
121
121
  constructor(viewer: Viewer, builder: Builder<T>, placeholderID: ID, conditionalOverride: boolean, operations: DataOperation[], dependencies?: Map<ID, Builder<Ent<Viewer<Ent<any> | null, ID | null>>, Viewer<Ent<any> | null, ID | null>, Ent<Viewer<Ent<any> | null, ID | null>> | null>> | undefined, changesets?: Changeset[] | undefined, options?: OrchestratorOptions<T, Data, Viewer<Ent<any> | null, ID | null>, MaybeNull<T>> | undefined);
122
122
  static changesetFrom(builder: Builder<any, any, any>, ops: DataOperation[]): EntChangeset<any>;
123
123
  static changesetFromQueries(builder: Builder<any, any, any>, queries: Array<string | parameterizedQueryOptions>): EntChangeset<any>;
124
+ private static changesetFromEdgeOp;
125
+ static changesetFromOutboundEdge(builder: Builder<any, any, any>, edgeType: string, id2: Builder<any> | ID, nodeType: string, options?: AssocEdgeInputOptions): Promise<EntChangeset<any>>;
126
+ static changesetFromInboundEdge(builder: Builder<any, any, any>, edgeType: string, id1: Builder<any> | ID, nodeType: string, options?: AssocEdgeInputOptions): Promise<EntChangeset<any>>;
127
+ static changesetRemoveFromOutboundEdge(builder: Builder<any, any, any>, edgeType: string, id2: ID, options?: AssocEdgeInputOptions): Promise<EntChangeset<any>>;
128
+ static changesetRemoveFromInboundEdge(builder: Builder<any, any, any>, edgeType: string, id1: ID, options?: AssocEdgeInputOptions): Promise<EntChangeset<any>>;
124
129
  executor(): Executor;
125
130
  }
126
131
  export {};
@@ -161,6 +161,7 @@ class Orchestrator {
161
161
  id: id1,
162
162
  edgeType,
163
163
  direction: edgeDirection.inboundEdge,
164
+ options,
164
165
  }), action_1.WriteOperation.Delete, options?.conditional);
165
166
  }
166
167
  removeOutboundEdge(id2, edgeType, options) {
@@ -168,6 +169,7 @@ class Orchestrator {
168
169
  id: id2,
169
170
  edgeType,
170
171
  direction: edgeDirection.outboundEdge,
172
+ options,
171
173
  }), action_1.WriteOperation.Delete, options?.conditional);
172
174
  }
173
175
  // this doesn't take a direction as that's an implementation detail
@@ -255,10 +257,10 @@ class Orchestrator {
255
257
  }
256
258
  let id2 = edge.id;
257
259
  if (edge.direction === edgeDirection.outboundEdge) {
258
- return operations_1.EdgeOperation.removeOutboundEdge(this.options.builder, edgeType, id2);
260
+ return operations_1.EdgeOperation.removeOutboundEdge(this.options.builder, edgeType, id2, edge.options);
259
261
  }
260
262
  else {
261
- return operations_1.EdgeOperation.removeInboundEdge(this.options.builder, edgeType, id2);
263
+ return operations_1.EdgeOperation.removeInboundEdge(this.options.builder, edgeType, id2, edge.options);
262
264
  }
263
265
  }
264
266
  throw new Error("could not find an edge operation from the given parameters");
@@ -288,6 +290,8 @@ class Orchestrator {
288
290
  if (!edgeData) {
289
291
  throw new Error(`could not load edge data for '${edgeType}'`);
290
292
  }
293
+ // similar logic in EntChangeset.changesetFromEdgeOp
294
+ // doesn't support conditional edges
291
295
  if (edgeData.symmetricEdge) {
292
296
  let symmetric = edgeOp.symmetricEdge();
293
297
  if (conditional) {
@@ -941,9 +945,37 @@ class EntChangeset {
941
945
  `$ent.idPlaceholderID$ ${randomNum()}-${builder.ent.name}`, false, ops);
942
946
  }
943
947
  static changesetFromQueries(builder, queries) {
944
- return new EntChangeset(builder.viewer, builder,
945
- // need unique placeholderID different from the builder. see comment above EntChangeset
946
- `$ent.idPlaceholderID$ ${randomNum()}-${builder.ent.name}`, false, [new operations_2.RawQueryOperation(builder, queries)]);
948
+ return EntChangeset.changesetFrom(builder, [
949
+ new operations_2.RawQueryOperation(builder, queries),
950
+ ]);
951
+ }
952
+ static async changesetFromEdgeOp(builder, op, edgeType) {
953
+ const edgeData = await (0, ent_1.loadEdgeData)(edgeType);
954
+ const ops = [op];
955
+ if (!edgeData) {
956
+ throw new Error(`could not load edge data for '${edgeType}'`);
957
+ }
958
+ // similar logic in Orchestrator.buildEdgeOps
959
+ // doesn't support conditional edges
960
+ if (edgeData.symmetricEdge) {
961
+ ops.push(op.symmetricEdge());
962
+ }
963
+ if (edgeData.inverseEdgeType) {
964
+ ops.push(op.inverseEdge(edgeData));
965
+ }
966
+ return EntChangeset.changesetFrom(builder, ops);
967
+ }
968
+ static async changesetFromOutboundEdge(builder, edgeType, id2, nodeType, options) {
969
+ return EntChangeset.changesetFromEdgeOp(builder, operations_1.EdgeOperation.outboundEdge(builder, edgeType, id2, nodeType, options), edgeType);
970
+ }
971
+ static async changesetFromInboundEdge(builder, edgeType, id1, nodeType, options) {
972
+ return EntChangeset.changesetFromEdgeOp(builder, operations_1.EdgeOperation.inboundEdge(builder, edgeType, id1, nodeType, options), edgeType);
973
+ }
974
+ static changesetRemoveFromOutboundEdge(builder, edgeType, id2, options) {
975
+ return EntChangeset.changesetFromEdgeOp(builder, operations_1.EdgeOperation.removeOutboundEdge(builder, edgeType, id2, options), edgeType);
976
+ }
977
+ static changesetRemoveFromInboundEdge(builder, edgeType, id1, options) {
978
+ return EntChangeset.changesetFromEdgeOp(builder, operations_1.EdgeOperation.removeInboundEdge(builder, edgeType, id1, options), edgeType);
947
979
  }
948
980
  executor() {
949
981
  if (this._executor) {
package/core/base.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import * as clause from "./clause";
2
2
  import { ObjectLoaderFactory } from "./loaders";
3
+ import { OrderBy } from "./query_impl";
3
4
  export interface Loader<K, V> {
4
5
  context?: Context;
5
6
  load(key: K): Promise<V>;
@@ -19,7 +20,8 @@ interface LoaderFactoryWithLoaderMany<T, V> extends LoaderFactory<T, V> {
19
20
  export interface ConfigurableLoaderFactory<T, V> extends LoaderFactory<T, V> {
20
21
  createConfigurableLoader(options: EdgeQueryableDataOptions, context?: Context): Loader<T, V>;
21
22
  }
22
- export type EdgeQueryableDataOptions = Partial<Pick<QueryableDataOptions, "limit" | "orderby" | "clause">>;
23
+ export type EdgeQueryableDataOptions = Partial<Pick<QueryableDataOptions, "limit" | "orderby" | "clause" | "disableTransformations">>;
24
+ export type EdgeQueryableDataOptionsConfigureLoader = Pick<EdgeQueryableDataOptions, "disableTransformations">;
23
25
  export interface PrimableLoader<K, V> extends Loader<K, V> {
24
26
  prime(d: V): void;
25
27
  primeAll?(d: V): void;
@@ -37,7 +39,7 @@ interface queryOptions {
37
39
  fields: string[];
38
40
  tableName: string;
39
41
  clause: clause.Clause;
40
- orderby?: string;
42
+ orderby?: OrderBy;
41
43
  }
42
44
  export interface Context<TViewer extends Viewer = Viewer> {
43
45
  getViewer(): TViewer;
@@ -80,7 +82,7 @@ export interface QueryableDataOptions extends SelectBaseDataOptions, QueryDataOp
80
82
  export interface QueryDataOptions<T extends Data = Data, K = keyof T> {
81
83
  distinct?: boolean;
82
84
  clause: clause.Clause<T, K>;
83
- orderby?: string;
85
+ orderby?: OrderBy;
84
86
  groupby?: K;
85
87
  limit?: number;
86
88
  disableTransformations?: boolean;
package/core/context.d.ts CHANGED
@@ -3,6 +3,7 @@ import { Viewer, Data, Loader, LoaderWithLoadMany } from "./base";
3
3
  import { IncomingMessage, ServerResponse } from "http";
4
4
  import * as clause from "./clause";
5
5
  import { Context } from "./base";
6
+ import { OrderBy } from "./query_impl";
6
7
  export interface RequestContext<TViewer extends Viewer = Viewer> extends Context<TViewer> {
7
8
  authViewer(viewer: TViewer): Promise<void>;
8
9
  logout(): Promise<void>;
@@ -27,6 +28,6 @@ interface queryOptions {
27
28
  fields: string[];
28
29
  tableName: string;
29
30
  clause: clause.Clause;
30
- orderby?: string;
31
+ orderby?: OrderBy;
31
32
  }
32
33
  export {};
package/core/context.js CHANGED
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ContextCache = void 0;
4
4
  const logger_1 = require("./logger");
5
+ const query_impl_1 = require("./query_impl");
5
6
  class ContextCache {
6
7
  constructor() {
7
8
  this.loaders = new Map();
@@ -39,7 +40,7 @@ class ContextCache {
39
40
  options.clause.instanceKey(),
40
41
  ];
41
42
  if (options.orderby) {
42
- parts.push(options.orderby);
43
+ parts.push((0, query_impl_1.getOrderByPhrase)(options.orderby));
43
44
  }
44
45
  return parts.join(",");
45
46
  }
package/core/ent.d.ts CHANGED
@@ -2,6 +2,7 @@ import { Queryer, SyncQueryer } from "./db";
2
2
  import { Viewer, Ent, ID, LoadRowsOptions, LoadRowOptions, Data, DataOptions, QueryableDataOptions, EditRowOptions, LoadEntOptions, LoadCustomEntOptions, EdgeQueryableDataOptions, Context, CreateRowOptions, QueryDataOptions, SelectCustomDataOptions } from "./base";
3
3
  import * as clause from "./clause";
4
4
  import DataLoader from "dataloader";
5
+ import { OrderBy } from "./query_impl";
5
6
  export declare function getEntKey<TEnt extends Ent<TViewer>, TViewer extends Viewer>(viewer: TViewer, id: ID, options: LoadEntOptions<TEnt, TViewer>): string;
6
7
  export declare function loadEnt<TEnt extends Ent<TViewer>, TViewer extends Viewer>(viewer: TViewer, id: ID, options: LoadEntOptions<TEnt, TViewer>): Promise<TEnt | null>;
7
8
  export declare function loadEntViaKey<TEnt extends Ent<TViewer>, TViewer extends Viewer>(viewer: TViewer, key: any, options: LoadEntOptions<TEnt, TViewer>): Promise<TEnt | null>;
@@ -75,7 +76,7 @@ interface GroupQueryOptions<T extends Data, K = keyof T> {
75
76
  groupColumn: K;
76
77
  fields: K[];
77
78
  values: any[];
78
- orderby?: string;
79
+ orderby?: OrderBy;
79
80
  limit: number;
80
81
  }
81
82
  export declare function buildGroupQuery<T extends Data = Data, K = keyof T>(options: GroupQueryOptions<T, K>): [string, clause.Clause<T, K>];
@@ -126,7 +127,6 @@ interface loadEdgesOptions {
126
127
  edgeType: string;
127
128
  context?: Context;
128
129
  queryOptions?: EdgeQueryableDataOptions;
129
- disableTransformations?: boolean;
130
130
  }
131
131
  interface loadCustomEdgesOptions<T extends AssocEdge> extends loadEdgesOptions {
132
132
  ctr: AssocEdgeConstructor<T>;
@@ -134,7 +134,7 @@ interface loadCustomEdgesOptions<T extends AssocEdge> extends loadEdgesOptions {
134
134
  export declare function setDefaultLimit(limit: number): void;
135
135
  export declare function getDefaultLimit(): number;
136
136
  export declare function loadEdges(options: loadEdgesOptions): Promise<AssocEdge[]>;
137
- export declare function getEdgeClauseAndFields(cls: clause.Clause, options: Pick<loadEdgesOptions, "disableTransformations">): {
137
+ export declare function getEdgeClauseAndFields(cls: clause.Clause, options: Pick<loadEdgesOptions, "queryOptions">): {
138
138
  cls: clause.Clause<Data, string | number>;
139
139
  fields: string[];
140
140
  };
package/core/ent.js CHANGED
@@ -33,6 +33,7 @@ const clause = __importStar(require("./clause"));
33
33
  const logger_1 = require("./logger");
34
34
  const dataloader_1 = __importDefault(require("dataloader"));
35
35
  const global_schema_1 = require("./global_schema");
36
+ const query_impl_1 = require("./query_impl");
36
37
  // TODO kill this and createDataLoader
37
38
  class cacheMap {
38
39
  constructor(options) {
@@ -635,7 +636,7 @@ function buildQuery(options) {
635
636
  parts.push(`GROUP BY ${options.groupby}`);
636
637
  }
637
638
  if (options.orderby) {
638
- parts.push(`ORDER BY ${options.orderby}`);
639
+ parts.push(`ORDER BY ${(0, query_impl_1.getOrderByPhrase)(options.orderby)}`);
639
640
  }
640
641
  if (options.limit) {
641
642
  parts.push(`LIMIT ${options.limit}`);
@@ -652,7 +653,7 @@ function buildGroupQuery(options) {
652
653
  }
653
654
  let orderby = "";
654
655
  if (options.orderby) {
655
- orderby = `ORDER BY ${options.orderby}`;
656
+ orderby = `ORDER BY ${(0, query_impl_1.getOrderByPhrase)(options.orderby)}`;
656
657
  }
657
658
  // window functions work in sqlite!
658
659
  // https://www.sqlite.org/windowfunctions.html
@@ -975,7 +976,12 @@ function defaultEdgeQueryOptions(id1, edgeType, id2) {
975
976
  }
976
977
  return {
977
978
  clause: cls,
978
- orderby: "time DESC",
979
+ orderby: [
980
+ {
981
+ column: "time",
982
+ direction: "DESC",
983
+ },
984
+ ],
979
985
  limit: defaultLimit,
980
986
  };
981
987
  }
@@ -988,7 +994,7 @@ function getEdgeClauseAndFields(cls, options) {
988
994
  const transformEdgeRead = (0, global_schema_1.__getGlobalSchema)()?.transformEdgeRead;
989
995
  if (transformEdgeRead) {
990
996
  const transformClause = transformEdgeRead();
991
- if (!options.disableTransformations) {
997
+ if (!options.queryOptions?.disableTransformations) {
992
998
  cls = clause.And(cls, transformClause);
993
999
  }
994
1000
  fields = edgeFields.concat(transformClause.columns());
@@ -1,10 +1,11 @@
1
- import { ID, Context, Loader, LoaderFactory } from "../base";
1
+ import { ID, Context, Loader, LoaderFactory, EdgeQueryableDataOptionsConfigureLoader } from "../base";
2
2
  export declare class AssocEdgeCountLoader implements Loader<ID, number> {
3
3
  private edgeType;
4
4
  context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined;
5
+ private options?;
5
6
  private loaderFn;
6
7
  private loader;
7
- constructor(edgeType: string, context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined);
8
+ constructor(edgeType: string, context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined, options?: EdgeQueryableDataOptionsConfigureLoader | undefined);
8
9
  private getLoader;
9
10
  load(id: ID): Promise<number>;
10
11
  clearAll(): void;
@@ -15,4 +16,5 @@ export declare class AssocEdgeCountLoaderFactory implements LoaderFactory<ID, nu
15
16
  constructor(edgeType: string);
16
17
  getEdgeType(): string;
17
18
  createLoader(context?: Context): AssocEdgeCountLoader;
19
+ createConfigurableLoader(options: EdgeQueryableDataOptionsConfigureLoader, context?: Context): AssocEdgeCountLoader;
18
20
  }
@@ -33,9 +33,10 @@ const loader_1 = require("./loader");
33
33
  const raw_count_loader_1 = require("./raw_count_loader");
34
34
  const memoizee_1 = __importDefault(require("memoizee"));
35
35
  class AssocEdgeCountLoader {
36
- constructor(edgeType, context) {
36
+ constructor(edgeType, context, options) {
37
37
  this.edgeType = edgeType;
38
38
  this.context = context;
39
+ this.options = options;
39
40
  if (context) {
40
41
  this.loaderFn = (0, memoizee_1.default)(this.getLoader);
41
42
  }
@@ -45,7 +46,9 @@ class AssocEdgeCountLoader {
45
46
  if (!edgeData) {
46
47
  throw new Error(`error loading edge data for ${this.edgeType}`);
47
48
  }
48
- const { cls } = (0, ent_1.getEdgeClauseAndFields)(clause.Eq("edge_type", this.edgeType), {});
49
+ const { cls } = (0, ent_1.getEdgeClauseAndFields)(clause.Eq("edge_type", this.edgeType), {
50
+ queryOptions: this.options,
51
+ });
49
52
  this.loader = (0, raw_count_loader_1.createCountDataLoader)({
50
53
  tableName: edgeData.edgeTable,
51
54
  groupCol: "id1",
@@ -58,6 +61,7 @@ class AssocEdgeCountLoader {
58
61
  return (0, ent_1.loadRawEdgeCountX)({
59
62
  id1: id,
60
63
  edgeType: this.edgeType,
64
+ queryOptions: this.options,
61
65
  });
62
66
  }
63
67
  const loader = await this.loaderFn();
@@ -79,5 +83,9 @@ class AssocEdgeCountLoaderFactory {
79
83
  createLoader(context) {
80
84
  return (0, loader_1.getLoader)(this, () => new AssocEdgeCountLoader(this.edgeType, context), context);
81
85
  }
86
+ createConfigurableLoader(options, context) {
87
+ const key = `${this.name}:disableTransformations:${options.disableTransformations}`;
88
+ return (0, loader_1.getCustomLoader)(key, () => new AssocEdgeCountLoader(this.edgeType, context, options), context);
89
+ }
82
90
  }
83
91
  exports.AssocEdgeCountLoaderFactory = AssocEdgeCountLoaderFactory;
@@ -1,6 +1,6 @@
1
1
  import { Context, ID, EdgeQueryableDataOptions, Loader, LoaderFactory } from "../base";
2
2
  import { AssocEdge, AssocEdgeConstructor } from "../ent";
3
- interface AssocLoader<T extends AssocEdge> extends Loader<ID, T[]> {
3
+ export interface AssocLoader<T extends AssocEdge> extends Loader<ID, T[]> {
4
4
  loadEdgeForID2(id: ID, id2: ID): Promise<T | undefined>;
5
5
  }
6
6
  export declare class AssocEdgeLoader<T extends AssocEdge> implements Loader<ID, T[]> {
@@ -21,7 +21,7 @@ export declare class AssocDirectEdgeLoader<T extends AssocEdge> implements Loade
21
21
  private edgeCtr;
22
22
  private options?;
23
23
  context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined;
24
- constructor(edgeType: string, edgeCtr: AssocEdgeConstructor<T>, options?: Partial<Pick<import("../base").QueryableDataOptions, "clause" | "limit" | "orderby">> | undefined, context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined);
24
+ constructor(edgeType: string, edgeCtr: AssocEdgeConstructor<T>, options?: Partial<Pick<import("../base").QueryableDataOptions, "clause" | "limit" | "orderby" | "disableTransformations">> | undefined, context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined);
25
25
  load(id: ID): Promise<T[]>;
26
26
  loadEdgeForID2(id: ID, id2: ID): Promise<T | undefined>;
27
27
  clearAll(): void;
@@ -35,4 +35,3 @@ export declare class AssocEdgeLoaderFactory<T extends AssocEdge> implements Load
35
35
  private isConstructor;
36
36
  createConfigurableLoader(options: EdgeQueryableDataOptions, context?: Context): AssocLoader<T>;
37
37
  }
38
- export {};
@@ -59,11 +59,18 @@ function createLoader(options, edgeType, edgeCtr, edgeData) {
59
59
  // store the index....
60
60
  m.set(keys[i], i);
61
61
  }
62
- options.orderby = options.orderby || "time DESC";
62
+ options.orderby = options.orderby || [
63
+ {
64
+ column: "time",
65
+ direction: "DESC",
66
+ },
67
+ ];
63
68
  // TODO defaultEdgeQueryOptions
64
69
  options.limit = options.limit || (0, ent_1.getDefaultLimit)();
65
70
  const tableName = edgeData.edgeTable;
66
- const { cls: cls1, fields } = (0, ent_1.getEdgeClauseAndFields)(clause.Eq("edge_type", edgeType), {});
71
+ const { cls: cls1, fields } = (0, ent_1.getEdgeClauseAndFields)(clause.Eq("edge_type", edgeType), {
72
+ queryOptions: options,
73
+ });
67
74
  const [query, cls] = (0, ent_1.buildGroupQuery)({
68
75
  tableName: tableName,
69
76
  fields,
@@ -114,6 +121,7 @@ class AssocEdgeLoader {
114
121
  id2,
115
122
  context: this.context,
116
123
  ctr: this.edgeCtr,
124
+ queryOptions: this.options,
117
125
  });
118
126
  }
119
127
  clearAll() {
@@ -129,7 +137,7 @@ class AssocDirectEdgeLoader {
129
137
  this.context = context;
130
138
  }
131
139
  async load(id) {
132
- return await (0, ent_1.loadCustomEdges)({
140
+ return (0, ent_1.loadCustomEdges)({
133
141
  id1: id,
134
142
  edgeType: this.edgeType,
135
143
  context: this.context,
@@ -137,12 +145,14 @@ class AssocDirectEdgeLoader {
137
145
  ctr: this.edgeCtr,
138
146
  });
139
147
  }
148
+ // TODO should this have a disableTransformations flag to get these rows
140
149
  async loadEdgeForID2(id, id2) {
141
150
  return (0, ent_1.loadEdgeForID2)({
142
151
  id1: id,
143
152
  edgeType: this.edgeType,
144
153
  id2,
145
154
  context: this.context,
155
+ queryOptions: this.options,
146
156
  ctr: this.edgeCtr,
147
157
  });
148
158
  }
@@ -181,7 +191,7 @@ class AssocEdgeLoaderFactory {
181
191
  return new AssocDirectEdgeLoader(this.edgeType, edgeCtr, options, context);
182
192
  }
183
193
  // we create a loader which can combine first X queries in the same fetch
184
- const key = `${this.name}:limit:${options.limit}:orderby:${options.orderby}`;
194
+ const key = `${this.name}:limit:${options.limit}:orderby:${options.orderby}:disableTransformations:${options.disableTransformations}`;
185
195
  return (0, loader_1.getCustomLoader)(key, () => new AssocEdgeLoader(this.edgeType, ctr, options, context), context);
186
196
  }
187
197
  }
@@ -1,12 +1,13 @@
1
1
  import { ID, SelectBaseDataOptions, Context, Data, LoaderFactory, EdgeQueryableDataOptions, Loader } from "../base";
2
2
  import * as clause from "../clause";
3
+ import { OrderBy } from "../query_impl";
3
4
  import { ObjectLoaderFactory } from "./object_loader";
4
5
  export declare class IndexLoaderFactory implements LoaderFactory<ID, Data[]> {
5
6
  name: string;
6
7
  private factory;
7
8
  constructor(options: SelectBaseDataOptions, col: string, opts?: {
8
9
  extraClause?: clause.Clause;
9
- sortColumn?: string;
10
+ orderby?: OrderBy;
10
11
  toPrime?: ObjectLoaderFactory<Data>[];
11
12
  });
12
13
  createLoader(context?: Context): any;
@@ -12,7 +12,7 @@ class IndexLoaderFactory {
12
12
  tableName: options.tableName,
13
13
  groupCol: col,
14
14
  clause: opts?.extraClause,
15
- sortColumn: opts?.sortColumn,
15
+ orderby: opts?.orderby,
16
16
  toPrime: opts?.toPrime,
17
17
  });
18
18
  this.name = `indexLoader:${options.tableName}:${col}`;
@@ -1,14 +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 function getOrderBy(sortCol: string, orderby?: string): string;
4
+ import { OrderBy } from "../query_impl";
5
5
  declare class QueryDirectLoader<K extends any> implements Loader<K, Data[]> {
6
6
  private options;
7
7
  private queryOptions?;
8
8
  context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined;
9
9
  private memoizedInitPrime;
10
10
  private primedLoaders;
11
- constructor(options: QueryOptions, queryOptions?: Partial<Pick<import("../base").QueryableDataOptions, "clause" | "limit" | "orderby">> | undefined, context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined);
11
+ constructor(options: QueryOptions, queryOptions?: Partial<Pick<import("../base").QueryableDataOptions, "clause" | "limit" | "orderby" | "disableTransformations">> | undefined, context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined);
12
12
  private initPrime;
13
13
  load(id: K): Promise<Data[]>;
14
14
  clearAll(): void;
@@ -18,7 +18,7 @@ interface QueryOptions {
18
18
  tableName: string;
19
19
  groupCol?: string;
20
20
  clause?: clause.Clause;
21
- sortColumn?: string;
21
+ orderby?: OrderBy;
22
22
  toPrime?: ObjectLoaderFactory<Data>[];
23
23
  }
24
24
  export declare class QueryLoaderFactory<K extends any> implements LoaderFactory<K, Data[]> {
@@ -26,25 +26,22 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
26
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.QueryLoaderFactory = exports.getOrderBy = void 0;
29
+ exports.QueryLoaderFactory = void 0;
30
30
  const dataloader_1 = __importDefault(require("dataloader"));
31
31
  const ent_1 = require("../ent");
32
32
  const clause = __importStar(require("../clause"));
33
33
  const logger_1 = require("../logger");
34
34
  const loader_1 = require("./loader");
35
35
  const memoizee_1 = __importDefault(require("memoizee"));
36
- function getOrderBy(sortCol, orderby) {
37
- if (orderby) {
38
- return orderby;
39
- }
40
- let sortColLower = sortCol.toLowerCase();
41
- let orderbyDirection = " DESC";
42
- if (sortColLower.endsWith("asc") || sortCol.endsWith("desc")) {
43
- orderbyDirection = "";
44
- }
45
- return `${sortCol}${orderbyDirection}`;
36
+ function getOrderByLocal(options, queryOptions) {
37
+ return (options.orderby ??
38
+ queryOptions?.orderby ?? [
39
+ {
40
+ column: "created_at",
41
+ direction: "DESC",
42
+ },
43
+ ]);
46
44
  }
47
- exports.getOrderBy = getOrderBy;
48
45
  async function simpleCase(options, id, queryOptions) {
49
46
  let cls;
50
47
  if (options.groupCol) {
@@ -62,16 +59,14 @@ async function simpleCase(options, id, queryOptions) {
62
59
  if (queryOptions?.clause) {
63
60
  cls = clause.And(cls, queryOptions.clause);
64
61
  }
65
- let sortCol = options.sortColumn || "created_at";
66
62
  return await (0, ent_1.loadRows)({
67
63
  ...options,
68
64
  clause: cls,
69
- orderby: getOrderBy(sortCol, queryOptions?.orderby),
65
+ orderby: getOrderByLocal(options, queryOptions),
70
66
  limit: queryOptions?.limit || (0, ent_1.getDefaultLimit)(),
71
67
  });
72
68
  }
73
69
  function createLoader(options, queryOptions) {
74
- let sortCol = options.sortColumn || "created_at";
75
70
  const loaderOptions = {};
76
71
  // if query logging is enabled, we should log what's happening with loader
77
72
  if ((0, logger_1.logEnabled)("query")) {
@@ -109,7 +104,7 @@ function createLoader(options, queryOptions) {
109
104
  tableName: options.tableName,
110
105
  fields: options.fields,
111
106
  values: keys,
112
- orderby: getOrderBy(sortCol, queryOptions?.orderby),
107
+ orderby: getOrderByLocal(options, queryOptions),
113
108
  limit: queryOptions?.limit || (0, ent_1.getDefaultLimit)(),
114
109
  groupColumn: col,
115
110
  clause: extraClause,