@snowtop/ent 0.1.0-alpha9 → 0.1.0-alpha90

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 (116) hide show
  1. package/action/action.d.ts +36 -31
  2. package/action/action.js +2 -6
  3. package/action/executor.d.ts +3 -3
  4. package/action/executor.js +2 -2
  5. package/action/experimental_action.d.ts +29 -22
  6. package/action/experimental_action.js +29 -6
  7. package/action/orchestrator.d.ts +38 -16
  8. package/action/orchestrator.js +219 -61
  9. package/action/privacy.d.ts +2 -2
  10. package/core/base.d.ts +45 -24
  11. package/core/base.js +7 -1
  12. package/core/clause.d.ts +68 -7
  13. package/core/clause.js +291 -62
  14. package/core/config.d.ts +8 -0
  15. package/core/context.d.ts +5 -3
  16. package/core/context.js +20 -2
  17. package/core/convert.d.ts +1 -1
  18. package/core/db.d.ts +2 -2
  19. package/core/db.js +1 -1
  20. package/core/ent.d.ts +79 -24
  21. package/core/ent.js +520 -168
  22. package/core/loaders/assoc_count_loader.d.ts +2 -2
  23. package/core/loaders/assoc_count_loader.js +6 -1
  24. package/core/loaders/assoc_edge_loader.d.ts +2 -2
  25. package/core/loaders/index.d.ts +1 -1
  26. package/core/loaders/index.js +1 -3
  27. package/core/loaders/index_loader.d.ts +2 -2
  28. package/core/loaders/loader.js +5 -5
  29. package/core/loaders/object_loader.d.ts +6 -5
  30. package/core/loaders/object_loader.js +62 -58
  31. package/core/loaders/query_loader.d.ts +6 -12
  32. package/core/loaders/query_loader.js +47 -10
  33. package/core/loaders/raw_count_loader.d.ts +2 -2
  34. package/core/logger.d.ts +1 -1
  35. package/core/logger.js +1 -0
  36. package/core/privacy.d.ts +26 -25
  37. package/core/privacy.js +21 -25
  38. package/core/query/assoc_query.d.ts +6 -6
  39. package/core/query/custom_clause_query.d.ts +24 -0
  40. package/core/query/custom_clause_query.js +72 -0
  41. package/core/query/custom_query.d.ts +20 -5
  42. package/core/query/custom_query.js +77 -10
  43. package/core/query/index.d.ts +1 -0
  44. package/core/query/index.js +3 -1
  45. package/core/query/query.d.ts +1 -1
  46. package/core/query/query.js +8 -1
  47. package/core/query/shared_assoc_test.d.ts +1 -1
  48. package/core/query/shared_assoc_test.js +17 -5
  49. package/core/query/shared_test.d.ts +3 -0
  50. package/core/query/shared_test.js +211 -30
  51. package/core/viewer.d.ts +3 -3
  52. package/core/viewer.js +1 -1
  53. package/graphql/graphql.js +6 -0
  54. package/graphql/query/edge_connection.d.ts +9 -9
  55. package/graphql/query/page_info.d.ts +1 -1
  56. package/index.d.ts +11 -5
  57. package/index.js +15 -6
  58. package/package.json +1 -1
  59. package/parse_schema/parse.d.ts +12 -3
  60. package/parse_schema/parse.js +70 -11
  61. package/schema/base_schema.js +3 -0
  62. package/schema/field.d.ts +44 -8
  63. package/schema/field.js +125 -9
  64. package/schema/index.d.ts +2 -2
  65. package/schema/json_field.d.ts +13 -1
  66. package/schema/json_field.js +28 -1
  67. package/schema/schema.d.ts +65 -11
  68. package/schema/schema.js +18 -4
  69. package/schema/struct_field.d.ts +11 -1
  70. package/schema/struct_field.js +44 -5
  71. package/scripts/custom_graphql.js +8 -3
  72. package/scripts/{transform_schema.d.ts → migrate_v0.1.d.ts} +0 -0
  73. package/scripts/migrate_v0.1.js +36 -0
  74. package/scripts/read_schema.js +15 -4
  75. package/testutils/builder.d.ts +31 -21
  76. package/testutils/builder.js +83 -29
  77. package/testutils/db/fixture.d.ts +10 -0
  78. package/testutils/db/fixture.js +26 -0
  79. package/testutils/db/{test_db.d.ts → temp_db.d.ts} +15 -3
  80. package/testutils/db/{test_db.js → temp_db.js} +70 -16
  81. package/testutils/db/value.d.ts +6 -0
  82. package/testutils/db/value.js +251 -0
  83. package/testutils/db_time_zone.d.ts +4 -0
  84. package/testutils/db_time_zone.js +41 -0
  85. package/testutils/fake_data/fake_contact.d.ts +5 -4
  86. package/testutils/fake_data/fake_contact.js +14 -6
  87. package/testutils/fake_data/fake_event.d.ts +5 -3
  88. package/testutils/fake_data/fake_event.js +8 -5
  89. package/testutils/fake_data/fake_user.d.ts +4 -4
  90. package/testutils/fake_data/fake_user.js +16 -13
  91. package/testutils/fake_data/test_helpers.d.ts +3 -2
  92. package/testutils/fake_data/test_helpers.js +8 -6
  93. package/testutils/fake_data/user_query.d.ts +8 -6
  94. package/testutils/fake_data/user_query.js +28 -21
  95. package/testutils/fake_log.d.ts +3 -3
  96. package/testutils/parse_sql.d.ts +6 -0
  97. package/testutils/parse_sql.js +16 -2
  98. package/testutils/test_edge_global_schema.d.ts +15 -0
  99. package/testutils/test_edge_global_schema.js +58 -0
  100. package/testutils/write.d.ts +2 -2
  101. package/testutils/write.js +29 -7
  102. package/tsc/ast.d.ts +44 -0
  103. package/tsc/ast.js +267 -0
  104. package/tsc/compilerOptions.d.ts +6 -0
  105. package/tsc/compilerOptions.js +40 -1
  106. package/tsc/move_generated.d.ts +1 -0
  107. package/tsc/move_generated.js +160 -0
  108. package/tsc/transform.d.ts +21 -0
  109. package/tsc/transform.js +167 -0
  110. package/tsc/transform_action.d.ts +22 -0
  111. package/tsc/transform_action.js +179 -0
  112. package/tsc/transform_ent.d.ts +17 -0
  113. package/tsc/transform_ent.js +59 -0
  114. package/tsc/transform_schema.d.ts +27 -0
  115. package/tsc/transform_schema.js +379 -0
  116. package/scripts/transform_schema.js +0 -445
package/core/privacy.js CHANGED
@@ -1,9 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AllowIfViewerHasIdentityPrivacyPolicy = exports.AllowIfViewerPrivacyPolicy = exports.AlwaysDenyPrivacyPolicy = exports.AlwaysAllowPrivacyPolicy = exports.applyPrivacyPolicyX = exports.applyPrivacyPolicy = exports.AllowIfSubPolicyAllowsRule = exports.DelayedResultRule = exports.AllowIfConditionAppliesRule = exports.DenyIfViewerOutboundEdgeDoesNotExistRule = exports.DenyIfViewerInboundEdgeDoesNotExistRule = exports.DenyIfEdgeDoesNotExistRule = exports.DenyIfViewerOutboundEdgeExistsRule = exports.DenyIfViewerInboundEdgeExistsRule = exports.DenyIfEdgeExistsRule = exports.AllowIfViewerOutboundEdgeExistsRule = exports.AllowIfViewerInboundEdgeExistsRule = exports.AllowIfEdgeExistsRule = exports.DenyIfEntIsNotVisibleRule = exports.DenyIfEntIsVisibleRule = exports.DenyIfEntIsVisiblePolicy = exports.AllowIfEntIsVisiblePolicy = exports.AllowIfEntIsNotVisibleRule = exports.AllowIfEntIsVisibleRule = exports.DenyIfEntPropertyIsRule = exports.AllowIfEntPropertyIsRule = exports.AllowIfViewerIsEntPropertyRule = exports.AllowIfViewerIsRule = exports.DenyIfFuncRule = exports.AllowIfFuncRule = exports.DenyIfViewerEqualsRule = exports.AllowIfViewerEqualsRule = exports.AllowIfViewerRule = exports.AllowIfHasIdentity = exports.DenyIfLoggedInRule = exports.DenyIfLoggedOutRule = exports.AlwaysDenyRule = exports.AlwaysAllowRule = exports.EntPrivacyError = void 0;
3
+ exports.AllowIfViewerHasIdentityPrivacyPolicy = exports.AllowIfViewerPrivacyPolicy = exports.AlwaysDenyPrivacyPolicy = exports.AlwaysAllowPrivacyPolicy = exports.applyPrivacyPolicyImpl = exports.applyPrivacyPolicyX = exports.applyPrivacyPolicy = exports.AllowIfSubPolicyAllowsRule = exports.DelayedResultRule = exports.AllowIfConditionAppliesRule = exports.DenyIfViewerOutboundEdgeDoesNotExistRule = exports.DenyIfViewerInboundEdgeDoesNotExistRule = exports.DenyIfEdgeDoesNotExistRule = exports.DenyIfViewerOutboundEdgeExistsRule = exports.DenyIfViewerInboundEdgeExistsRule = exports.DenyIfEdgeExistsRule = exports.AllowIfViewerOutboundEdgeExistsRule = exports.AllowIfViewerInboundEdgeExistsRule = exports.AllowIfEdgeExistsRule = exports.DenyIfEntIsNotVisibleRule = exports.DenyIfEntIsVisibleRule = exports.DenyIfEntIsVisiblePolicy = exports.AllowIfEntIsVisiblePolicy = exports.AllowIfEntIsNotVisibleRule = exports.AllowIfEntIsVisibleRule = exports.DenyIfEntPropertyIsRule = exports.AllowIfEntPropertyIsRule = exports.AllowIfViewerIsEntPropertyRule = exports.AllowIfViewerIsRule = exports.DenyIfFuncRule = exports.AllowIfFuncRule = exports.DenyIfViewerEqualsRule = exports.AllowIfViewerEqualsRule = exports.AllowIfViewerRule = exports.AllowIfHasIdentity = exports.DenyIfLoggedInRule = exports.DenyIfLoggedOutRule = exports.AlwaysDenyRule = exports.AlwaysAllowRule = exports.EntPrivacyError = void 0;
4
4
  const base_1 = require("./base");
5
5
  const ent_1 = require("./ent");
6
- const logger_1 = require("./logger");
7
6
  // copied from ./base
8
7
  var privacyResult;
9
8
  (function (privacyResult) {
@@ -437,45 +436,42 @@ class AllowIfSubPolicyAllowsRule {
437
436
  }
438
437
  exports.AllowIfSubPolicyAllowsRule = AllowIfSubPolicyAllowsRule;
439
438
  async function applyPrivacyPolicy(v, policy, ent) {
440
- try {
441
- return await applyPrivacyPolicyX(v, policy, ent);
442
- }
443
- catch (e) {
444
- // TODO privacy errors should not throw
445
- // but other expected errors should throw...
446
- // we shouldn't just hide them
447
- (0, logger_1.log)("debug", e);
448
- return false;
449
- }
439
+ const err = await applyPrivacyPolicyImpl(v, policy, ent);
440
+ return err === null;
450
441
  }
451
442
  exports.applyPrivacyPolicy = applyPrivacyPolicy;
452
- // this will throw an exception if fails or return error | null?
453
443
  async function applyPrivacyPolicyX(v, policy, ent, throwErr) {
454
- // right now we apply all at same time. todo: be smart about this in the future
455
- const results = await Promise.all(policy.rules.map((rule) => rule.apply(v, ent)));
456
- for (let i = 0; i < results.length; i++) {
457
- const res = results[i];
458
- const rule = policy.rules[i];
444
+ const err = await applyPrivacyPolicyImpl(v, policy, ent, throwErr);
445
+ if (err !== null) {
446
+ throw err;
447
+ }
448
+ return true;
449
+ }
450
+ exports.applyPrivacyPolicyX = applyPrivacyPolicyX;
451
+ // this will throw an exception if fails or return error | null?
452
+ async function applyPrivacyPolicyImpl(v, policy, ent, throwErr) {
453
+ for (const rule of policy.rules) {
454
+ const res = await rule.apply(v, ent);
459
455
  if (res.result == privacyResult.Allow) {
460
- return true;
456
+ return null;
461
457
  }
462
458
  else if (res.result == privacyResult.Deny) {
463
459
  // specific error throw that
464
460
  if (res.error) {
465
- throw res.error;
461
+ return res.error;
466
462
  }
467
463
  if (res.getError) {
468
- throw res.getError(policy, rule, ent);
464
+ return res.getError(policy, rule, ent);
469
465
  }
470
466
  if (throwErr) {
471
- throw throwErr();
467
+ return throwErr();
472
468
  }
473
- throw new EntPrivacyError(policy, rule, ent);
469
+ return new EntPrivacyError(policy, rule, ent);
474
470
  }
475
471
  }
476
- throw new EntInvalidPrivacyPolicyError(policy, ent);
472
+ return new EntInvalidPrivacyPolicyError(policy, ent);
477
473
  }
478
- exports.applyPrivacyPolicyX = applyPrivacyPolicyX;
474
+ exports.applyPrivacyPolicyImpl = applyPrivacyPolicyImpl;
479
475
  exports.AlwaysAllowPrivacyPolicy = {
480
476
  rules: [exports.AlwaysAllowRule],
481
477
  };
@@ -3,15 +3,15 @@ import { AssocEdge } from "../ent";
3
3
  import { AssocEdgeCountLoaderFactory } from "../loaders/assoc_count_loader";
4
4
  import { AssocEdgeLoaderFactory } from "../loaders/assoc_edge_loader";
5
5
  import { EdgeQuery, BaseEdgeQuery, IDInfo } from "./query";
6
- export declare type EdgeQuerySource<TSource extends Ent, TDest extends Ent = Ent> = TSource | TSource[] | ID | ID[] | EdgeQuery<TDest, Ent, AssocEdge>;
7
- declare type loaderOptionsFunc = (type: string) => LoadEntOptions<Ent>;
8
- export declare abstract class AssocEdgeQueryBase<TSource extends Ent, TDest extends Ent, TEdge extends AssocEdge> extends BaseEdgeQuery<TSource, TDest, TEdge> implements EdgeQuery<TSource, TDest, TEdge> {
9
- viewer: Viewer;
10
- src: EdgeQuerySource<TSource, TDest>;
6
+ export declare type EdgeQuerySource<TSource extends Ent<TViewer>, TDest extends Ent<TViewer> = Ent<any>, TViewer extends Viewer = Viewer> = TSource | TSource[] | ID | ID[] | EdgeQuery<TDest, Ent, AssocEdge>;
7
+ declare type loaderOptionsFunc<TViewer extends Viewer> = (type: string) => LoadEntOptions<Ent, TViewer>;
8
+ export declare abstract class AssocEdgeQueryBase<TSource extends Ent<TViewer>, TDest extends Ent<TViewer>, TEdge extends AssocEdge, TViewer extends Viewer = Viewer> extends BaseEdgeQuery<TSource, TDest, TEdge> implements EdgeQuery<TSource, TDest, TEdge> {
9
+ viewer: TViewer;
10
+ src: EdgeQuerySource<TSource, TDest, TViewer>;
11
11
  private countLoaderFactory;
12
12
  private dataLoaderFactory;
13
13
  private options;
14
- constructor(viewer: Viewer, src: EdgeQuerySource<TSource, TDest>, countLoaderFactory: AssocEdgeCountLoaderFactory, dataLoaderFactory: AssocEdgeLoaderFactory<TEdge>, options: LoadEntOptions<TDest> | loaderOptionsFunc);
14
+ constructor(viewer: TViewer, src: EdgeQuerySource<TSource, TDest, TViewer>, countLoaderFactory: AssocEdgeCountLoaderFactory, dataLoaderFactory: AssocEdgeLoaderFactory<TEdge>, options: LoadEntOptions<TDest, TViewer> | loaderOptionsFunc<TViewer>);
15
15
  private isEdgeQuery;
16
16
  abstract sourceEnt(id: ID): Promise<Ent | null>;
17
17
  private getSingleID;
@@ -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, TDest extends Ent> {
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
- options: LoadEntOptions<TDest>;
8
+ options: LoadEntOptions<TDest, TViewer>;
8
9
  sortColumn?: string;
9
10
  }
10
- export declare abstract class CustomEdgeQueryBase<TSource extends Ent, TDest extends Ent> extends BaseEdgeQuery<TSource, TDest, Data> implements EdgeQuery<TSource, TDest, Data> {
11
- viewer: Viewer;
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
+ }
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> {
21
+ viewer: TViewer;
12
22
  private options;
13
23
  private id;
14
- constructor(viewer: Viewer, options: CustomEdgeQueryOptions<TSource, TDest>);
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[]>;
@@ -1,11 +1,54 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CustomEdgeQueryBase = void 0;
4
+ const clause_1 = require("../clause");
4
5
  const ent_1 = require("../ent");
6
+ const loaders_1 = require("../loaders");
5
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
+ function getRawCountLoader(viewer, opts) {
23
+ if (!viewer.context?.cache) {
24
+ return new loaders_1.RawCountLoader({
25
+ tableName: opts.loadEntOptions.tableName,
26
+ groupCol: opts.groupCol,
27
+ clause: getClause(opts),
28
+ });
29
+ }
30
+ const name = `custom_query_count_loader:${opts.name}`;
31
+ return viewer.context.cache.getLoader(name, () => new loaders_1.RawCountLoader({
32
+ tableName: opts.loadEntOptions.tableName,
33
+ groupCol: opts.groupCol,
34
+ clause: getClause(opts),
35
+ }));
36
+ }
37
+ function getQueryLoader(viewer, opts, options) {
38
+ const loader = opts.loadEntOptions.loaderFactory;
39
+ const name = `custom_query_loader:${opts.name}`;
40
+ return loaders_1.QueryLoaderFactory.createConfigurableLoader(name, {
41
+ tableName: opts.loadEntOptions.tableName,
42
+ fields: opts.loadEntOptions.fields,
43
+ groupCol: opts.groupCol,
44
+ clause: getClause(opts),
45
+ toPrime: [loader],
46
+ }, options, viewer.context);
47
+ }
6
48
  class CustomEdgeQueryBase extends query_1.BaseEdgeQuery {
7
49
  constructor(viewer, options) {
8
- super(viewer, options.sortColumn || "created_at");
50
+ // @ts-ignore
51
+ super(viewer, options?.sortColumn || "created_at");
9
52
  this.viewer = viewer;
10
53
  this.options = options;
11
54
  options.sortColumn = options.sortColumn || "created_at";
@@ -15,6 +58,7 @@ class CustomEdgeQueryBase extends query_1.BaseEdgeQuery {
15
58
  else {
16
59
  this.id = options.src;
17
60
  }
61
+ this.opts = this.getLoadEntOptions();
18
62
  }
19
63
  async idVisible() {
20
64
  const ids = await this.genIDInfosToFetch();
@@ -23,14 +67,28 @@ class CustomEdgeQueryBase extends query_1.BaseEdgeQuery {
23
67
  }
24
68
  return !ids[0].invalidated;
25
69
  }
70
+ isDeprecatedOptions(options) {
71
+ return (options
72
+ .countLoaderFactory !== undefined);
73
+ }
74
+ getCountLoader() {
75
+ if (this.isDeprecatedOptions(this.options)) {
76
+ return this.options.countLoaderFactory.createLoader(this.viewer.context);
77
+ }
78
+ return getRawCountLoader(this.viewer, this.options);
79
+ }
80
+ getQueryLoader(options) {
81
+ if (this.isDeprecatedOptions(this.options)) {
82
+ return this.options.dataLoaderFactory.createConfigurableLoader(options, this.viewer.context);
83
+ }
84
+ return getQueryLoader(this.viewer, this.options, options);
85
+ }
26
86
  async queryRawCount() {
27
87
  const idVisible = await this.idVisible();
28
88
  if (!idVisible) {
29
89
  return 0;
30
90
  }
31
- return await this.options.countLoaderFactory
32
- .createLoader(this.viewer.context)
33
- .load(this.id);
91
+ return this.getCountLoader().load(this.id);
34
92
  }
35
93
  async queryAllRawCount() {
36
94
  let count = 0;
@@ -43,17 +101,27 @@ class CustomEdgeQueryBase extends query_1.BaseEdgeQuery {
43
101
  async loadRawIDs(addID) {
44
102
  addID(this.options.src);
45
103
  }
104
+ getLoadEntOptions() {
105
+ let opts;
106
+ if (this.isDeprecatedOptions(this.options)) {
107
+ opts = this.options.options;
108
+ }
109
+ else {
110
+ opts = this.options.loadEntOptions;
111
+ }
112
+ return opts;
113
+ }
46
114
  async loadRawData(infos, options) {
47
- const loader = this.options.dataLoaderFactory.createConfigurableLoader(options, this.viewer.context);
115
+ if (infos.length !== 1) {
116
+ throw new Error(`expected 1 info passed to loadRawData. ${infos.length} passed`);
117
+ }
48
118
  if (!options.orderby) {
49
119
  options.orderby = `${this.options.sortColumn} DESC`;
50
120
  }
51
121
  if (!options.limit) {
52
122
  options.limit = ent_1.DefaultLimit;
53
123
  }
54
- if (infos.length !== 1) {
55
- throw new Error(`expected 1 info passed to loadRawData. ${infos.length} passed`);
56
- }
124
+ const loader = this.getQueryLoader(options);
57
125
  const info = infos[0];
58
126
  if (info.invalidated) {
59
127
  this.edges.set(this.id, []);
@@ -66,8 +134,7 @@ class CustomEdgeQueryBase extends query_1.BaseEdgeQuery {
66
134
  return edge.id;
67
135
  }
68
136
  async loadEntsFromEdges(id, rows) {
69
- const ents = await (0, ent_1.applyPrivacyPolicyForRows)(this.viewer, rows, this.options.options);
70
- return Array.from(ents.values());
137
+ return (0, ent_1.applyPrivacyPolicyForRows)(this.viewer, rows, this.opts);
71
138
  }
72
139
  }
73
140
  exports.CustomEdgeQueryBase = CustomEdgeQueryBase;
@@ -1,3 +1,4 @@
1
1
  export { EdgeQuery, BaseEdgeQuery, EdgeQueryFilter, PaginationInfo, } from "./query";
2
2
  export { AssocEdgeQueryBase, EdgeQuerySource } from "./assoc_query";
3
3
  export { CustomEdgeQueryBase } from "./custom_query";
4
+ export { CustomClauseQuery } from "./custom_clause_query";
@@ -1,9 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CustomEdgeQueryBase = exports.AssocEdgeQueryBase = exports.BaseEdgeQuery = void 0;
3
+ exports.CustomClauseQuery = exports.CustomEdgeQueryBase = exports.AssocEdgeQueryBase = exports.BaseEdgeQuery = void 0;
4
4
  var query_1 = require("./query");
5
5
  Object.defineProperty(exports, "BaseEdgeQuery", { enumerable: true, get: function () { return query_1.BaseEdgeQuery; } });
6
6
  var assoc_query_1 = require("./assoc_query");
7
7
  Object.defineProperty(exports, "AssocEdgeQueryBase", { enumerable: true, get: function () { return assoc_query_1.AssocEdgeQueryBase; } });
8
8
  var custom_query_1 = require("./custom_query");
9
9
  Object.defineProperty(exports, "CustomEdgeQueryBase", { enumerable: true, get: function () { return custom_query_1.CustomEdgeQueryBase; } });
10
+ var custom_clause_query_1 = require("./custom_clause_query");
11
+ Object.defineProperty(exports, "CustomClauseQuery", { enumerable: true, get: function () { return custom_clause_query_1.CustomClauseQuery; } });
@@ -41,7 +41,7 @@ export declare abstract class BaseEdgeQuery<TSource extends Ent, TDest extends E
41
41
  private idMap;
42
42
  private idsToFetch;
43
43
  constructor(viewer: Viewer, sortCol: string);
44
- getPrivacyPolicy(): PrivacyPolicy<Ent>;
44
+ getPrivacyPolicy(): PrivacyPolicy<Ent<Viewer<Ent<any> | null, ID | null>>, Viewer<Ent<any> | null, ID | null>>;
45
45
  abstract sourceEnt(id: ID): Promise<Ent | null>;
46
46
  first(n: number, after?: string): this;
47
47
  last(n: number, before?: string): this;
@@ -89,7 +89,13 @@ class FirstFilter {
89
89
  // todo may not be desc
90
90
  // and if asc
91
91
  // clause below should switch to greater...
92
- options.orderby = `${this.sortCol} DESC`;
92
+ const sortCol = this.sortCol.toLowerCase();
93
+ if (sortCol.endsWith("desc") || sortCol.endsWith("asc")) {
94
+ options.orderby = `${this.sortCol}`;
95
+ }
96
+ else {
97
+ options.orderby = `${this.sortCol} DESC`;
98
+ }
93
99
  // we sort by most recent first
94
100
  // so when paging, we fetch afterCursor X
95
101
  if (this.offset) {
@@ -100,6 +106,7 @@ class FirstFilter {
100
106
  options.clause = clause.Less(this.sortCol, new Date(this.offset).toISOString());
101
107
  }
102
108
  }
109
+ // console.debug("filter opts", options, this.options);
103
110
  return options;
104
111
  }
105
112
  // TODO?
@@ -1 +1 @@
1
- export declare function assocTests(): void;
1
+ export declare function assocTests(global?: boolean): void;
@@ -27,7 +27,7 @@ const jest_date_mock_1 = require("jest-date-mock");
27
27
  const index_1 = require("../../testutils/fake_data/index");
28
28
  const test_helpers_1 = require("../../testutils/fake_data/test_helpers");
29
29
  const db_1 = __importStar(require("../db"));
30
- function assocTests() {
30
+ function assocTests(global = false) {
31
31
  describe("custom edge", () => {
32
32
  let user1, user2;
33
33
  beforeEach(async () => {
@@ -76,9 +76,16 @@ function assocTests() {
76
76
  for (let i = 0; i < numQueries; i++) {
77
77
  const query = queries[i];
78
78
  let expLimit = disablePaginationBump ? limit : limit + 1;
79
- expect(query.qs?.whereClause, `${i}`).toBe(
80
- // default limit
81
- `id1 = $1 AND edge_type = $2 ORDER BY time DESC LIMIT ${expLimit}`);
79
+ if (global) {
80
+ expect(query.qs?.whereClause, `${i}`).toBe(
81
+ // default limit
82
+ `id1 = $1 AND edge_type = $2 AND deleted_at IS NULL ORDER BY time DESC LIMIT ${expLimit}`);
83
+ }
84
+ else {
85
+ expect(query.qs?.whereClause, `${i}`).toBe(
86
+ // default limit
87
+ `id1 = $1 AND edge_type = $2 ORDER BY time DESC LIMIT ${expLimit}`);
88
+ }
82
89
  }
83
90
  }
84
91
  function verifyCountQuery({ length = 1, numQueries = 1 }) {
@@ -89,7 +96,12 @@ function assocTests() {
89
96
  expect(queries.length).toBe(length);
90
97
  for (let i = 0; i < numQueries; i++) {
91
98
  const query = queries[i];
92
- expect(query.qs?.whereClause).toBe(`id1 = $1 AND edge_type = $2`);
99
+ if (global) {
100
+ expect(query.qs?.whereClause).toBe(`id1 = $1 AND edge_type = $2 AND deleted_at IS NULL`);
101
+ }
102
+ else {
103
+ expect(query.qs?.whereClause).toBe(`id1 = $1 AND edge_type = $2`);
104
+ }
93
105
  }
94
106
  }
95
107
  // TODO need to test multi-ids with id1s that aren't visible...
@@ -4,11 +4,14 @@ import { EdgeQuery } from "./query";
4
4
  interface options<TData extends Data> {
5
5
  newQuery: (v: Viewer, user: FakeUser) => EdgeQuery<FakeUser, FakeContact, TData>;
6
6
  tableName: string;
7
+ uniqKey: string;
7
8
  entsLength?: number;
8
9
  where: string;
9
10
  sortCol: string;
10
11
  livePostgresDB?: boolean;
11
12
  sqlite?: boolean;
13
+ globalSchema?: boolean;
14
+ rawDataVerify?(user: FakeUser): Promise<void>;
12
15
  }
13
16
  export declare const commonTests: <TData extends Data>(opts: options<TData>) => void;
14
17
  export {};