@snowtop/ent 0.2.4 → 0.2.6

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 (98) hide show
  1. package/action/action.js +5 -5
  2. package/action/executor.d.ts +1 -1
  3. package/action/executor.js +4 -4
  4. package/action/experimental_action.d.ts +7 -4
  5. package/action/experimental_action.js +18 -8
  6. package/action/operations.js +17 -7
  7. package/action/orchestrator.d.ts +10 -2
  8. package/action/orchestrator.js +29 -31
  9. package/action/privacy.d.ts +2 -2
  10. package/action/relative_value.js +3 -3
  11. package/auth/auth.d.ts +0 -1
  12. package/auth/auth.js +4 -5
  13. package/core/base.js +5 -5
  14. package/core/clause.js +76 -67
  15. package/core/config.d.ts +1 -1
  16. package/core/config.js +22 -9
  17. package/core/context.d.ts +0 -1
  18. package/core/convert.d.ts +0 -1
  19. package/core/convert.js +16 -17
  20. package/core/date.js +1 -2
  21. package/core/db.js +17 -7
  22. package/core/ent.d.ts +2 -0
  23. package/core/ent.js +127 -92
  24. package/core/global_schema.js +6 -7
  25. package/core/loaders/assoc_count_loader.d.ts +2 -2
  26. package/core/loaders/assoc_count_loader.js +17 -7
  27. package/core/loaders/assoc_edge_loader.d.ts +2 -2
  28. package/core/loaders/assoc_edge_loader.js +44 -20
  29. package/core/loaders/cache_utils.d.ts +1 -0
  30. package/core/loaders/cache_utils.js +28 -0
  31. package/core/loaders/index.d.ts +1 -0
  32. package/core/loaders/index.js +4 -1
  33. package/core/loaders/loader.d.ts +2 -0
  34. package/core/loaders/loader.js +20 -3
  35. package/core/loaders/object_loader.d.ts +6 -4
  36. package/core/loaders/object_loader.js +86 -48
  37. package/core/loaders/query_loader.d.ts +2 -2
  38. package/core/loaders/query_loader.js +25 -9
  39. package/core/loaders/raw_count_loader.d.ts +2 -2
  40. package/core/loaders/raw_count_loader.js +22 -10
  41. package/core/logger.js +6 -7
  42. package/core/privacy.d.ts +2 -2
  43. package/core/privacy.js +4 -5
  44. package/core/query/assoc_query.js +17 -7
  45. package/core/query/query.js +17 -7
  46. package/core/query/shared_assoc_test.js +1 -2
  47. package/core/query_impl.js +4 -5
  48. package/core/viewer.d.ts +2 -2
  49. package/graphql/graphql_field_helpers.js +22 -22
  50. package/graphql/mutations/union.js +1 -2
  51. package/graphql/node_resolver.js +7 -7
  52. package/graphql/query/shared_assoc_test.js +1 -2
  53. package/graphql/scalars/date.js +8 -3
  54. package/graphql/scalars/time.d.ts +1 -1
  55. package/imports/dataz/example1/_auth.js +14 -10
  56. package/imports/index.js +18 -9
  57. package/index.js +17 -7
  58. package/names/names.js +61 -18
  59. package/package.json +14 -17
  60. package/parse_schema/parse.js +2 -3
  61. package/schema/binary_field.js +3 -3
  62. package/schema/field.js +45 -35
  63. package/schema/json_field.js +7 -7
  64. package/schema/schema.js +12 -12
  65. package/schema/struct_field.js +4 -4
  66. package/schema/union_field.js +3 -3
  67. package/scripts/custom_compiler.js +17 -7
  68. package/scripts/custom_graphql.js +17 -7
  69. package/scripts/fix_action_exports.js +17 -7
  70. package/scripts/move_types.js +17 -7
  71. package/scripts/read_schema.js +17 -7
  72. package/testutils/action/complex_schemas.js +28 -18
  73. package/testutils/builder.d.ts +1 -1
  74. package/testutils/builder.js +7 -7
  75. package/testutils/db/fixture.js +1 -2
  76. package/testutils/db/temp_db.js +54 -44
  77. package/testutils/db/value.js +3 -4
  78. package/testutils/db_mock.js +12 -0
  79. package/testutils/ent-graphql-tests/index.d.ts +3 -3
  80. package/testutils/ent-graphql-tests/index.js +27 -18
  81. package/testutils/fake_data/const.js +2 -2
  82. package/testutils/fake_data/fake_contact.js +20 -10
  83. package/testutils/fake_data/fake_event.js +20 -10
  84. package/testutils/fake_data/fake_tag.js +21 -11
  85. package/testutils/fake_data/fake_user.js +21 -11
  86. package/testutils/fake_data/test_helpers.js +17 -17
  87. package/testutils/fake_data/user_query.js +19 -9
  88. package/testutils/parse_sql.js +151 -43
  89. package/testutils/query.js +2 -3
  90. package/testutils/soft_delete.js +17 -7
  91. package/testutils/test_edge_global_schema.js +17 -7
  92. package/testutils/write.js +20 -11
  93. package/tsc/ast.js +27 -18
  94. package/tsc/compilerOptions.js +22 -13
  95. package/tsc/move_generated.js +18 -9
  96. package/tsc/transform.js +18 -9
  97. package/tsc/transform_action.js +17 -7
  98. package/tsc/transform_schema.js +17 -7
@@ -15,13 +15,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
15
15
  }) : function(o, v) {
16
16
  o["default"] = v;
17
17
  });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
25
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
37
  };
@@ -22,8 +22,8 @@ export declare class AssocDirectEdgeLoader<T extends AssocEdge> implements Loade
22
22
  private edgeType;
23
23
  private edgeCtr;
24
24
  private options?;
25
- context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined;
26
- 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
+ context?: Context | undefined;
26
+ constructor(edgeType: string, edgeCtr: AssocEdgeConstructor<T>, options?: EdgeQueryableDataOptions | undefined, context?: Context | undefined);
27
27
  load(id: ID): Promise<T[]>;
28
28
  loadTwoWay(id: ID): Promise<T[]>;
29
29
  loadEdgeForID2(id: ID, id2: ID): Promise<T | undefined>;
@@ -15,13 +15,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
15
15
  }) : function(o, v) {
16
16
  o["default"] = v;
17
17
  });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
25
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
37
  };
@@ -32,9 +42,28 @@ const memoizee_1 = __importDefault(require("memoizee"));
32
42
  const clause = __importStar(require("../clause"));
33
43
  const ent_1 = require("../ent");
34
44
  const logger_1 = require("../logger");
45
+ const cache_utils_1 = require("./cache_utils");
35
46
  const loader_1 = require("./loader");
47
+ function getDefaultOrderBy() {
48
+ return [
49
+ {
50
+ column: "time",
51
+ direction: "DESC",
52
+ },
53
+ ];
54
+ }
55
+ function getEffectiveOptions(options) {
56
+ return {
57
+ ...options,
58
+ orderby: options.orderby ?? getDefaultOrderBy(),
59
+ limit: options.limit || (0, ent_1.getDefaultLimit)(),
60
+ disableTransformations: options.disableTransformations ?? false,
61
+ };
62
+ }
36
63
  function createLoader(options, edgeType, edgeCtr, edgeData) {
37
- const loaderOptions = {};
64
+ const loaderOptions = {
65
+ maxBatchSize: (0, loader_1.getLoaderMaxBatchSize)(),
66
+ };
38
67
  if ((0, logger_1.logEnabled)("query")) {
39
68
  loaderOptions.cacheMap = new loader_1.CacheMap({
40
69
  tableName: edgeData.edgeTable,
@@ -59,14 +88,9 @@ function createLoader(options, edgeType, edgeCtr, edgeData) {
59
88
  // store the index....
60
89
  m.set(keys[i], i);
61
90
  }
62
- options.orderby = options.orderby || [
63
- {
64
- column: "time",
65
- direction: "DESC",
66
- },
67
- ];
91
+ const orderby = options.orderby ?? getDefaultOrderBy();
68
92
  // TODO defaultEdgeQueryOptions
69
- options.limit = options.limit || (0, ent_1.getDefaultLimit)();
93
+ const limit = options.limit || (0, ent_1.getDefaultLimit)();
70
94
  const tableName = edgeData.edgeTable;
71
95
  const { cls: cls1, fields } = (0, ent_1.getEdgeClauseAndFields)(clause.Eq("edge_type", edgeType), {
72
96
  queryOptions: options,
@@ -75,8 +99,8 @@ function createLoader(options, edgeType, edgeCtr, edgeData) {
75
99
  tableName: tableName,
76
100
  fields,
77
101
  values: keys,
78
- orderby: options.orderby,
79
- limit: options.limit || (0, ent_1.getDefaultLimit)(),
102
+ orderby,
103
+ limit,
80
104
  groupColumn: "id1",
81
105
  clause: cls1,
82
106
  });
@@ -207,9 +231,9 @@ class AssocEdgeLoaderFactory {
207
231
  if (options?.clause || !context) {
208
232
  return new AssocDirectEdgeLoader(this.edgeType, edgeCtr, options, context);
209
233
  }
210
- // we create a loader which can combine first X queries in the same fetch
211
- const key = `${this.name}:limit:${options.limit}:orderby:${options.orderby?.map((orderBy) => JSON.stringify(orderBy))}:disableTransformations:${options.disableTransformations}`;
212
- return (0, loader_1.getCustomLoader)(key, () => new AssocEdgeLoader(this.edgeType, ctr, options, context), context);
234
+ const effectiveOptions = getEffectiveOptions(options);
235
+ const key = `${this.name}:limit:${effectiveOptions.limit}:orderby:${(0, cache_utils_1.stableStringify)(effectiveOptions.orderby)}:disableTransformations:${effectiveOptions.disableTransformations}`;
236
+ return (0, loader_1.getCustomLoader)(key, () => new AssocEdgeLoader(this.edgeType, ctr, effectiveOptions, context), context);
213
237
  }
214
238
  }
215
239
  exports.AssocEdgeLoaderFactory = AssocEdgeLoaderFactory;
@@ -0,0 +1 @@
1
+ export declare function stableStringify(value: unknown): string;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.stableStringify = stableStringify;
4
+ function isPlainObject(value) {
5
+ if (!value || typeof value !== "object") {
6
+ return false;
7
+ }
8
+ const proto = Object.getPrototypeOf(value);
9
+ return proto === Object.prototype || proto === null;
10
+ }
11
+ function normalizeForStableStringify(value) {
12
+ if (Array.isArray(value)) {
13
+ return value.map((item) => normalizeForStableStringify(item));
14
+ }
15
+ if (isPlainObject(value)) {
16
+ const sorted = {};
17
+ for (const key of Object.keys(value).sort()) {
18
+ sorted[key] = normalizeForStableStringify(value[key]);
19
+ }
20
+ return sorted;
21
+ }
22
+ return value;
23
+ }
24
+ function stableStringify(value) {
25
+ const normalized = normalizeForStableStringify(value);
26
+ const result = JSON.stringify(normalized);
27
+ return result === undefined ? "undefined" : result;
28
+ }
@@ -3,3 +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 { QueryLoaderFactory } from "./query_loader";
6
+ export { getLoaderMaxBatchSize, setLoaderMaxBatchSize } from "./loader";
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.QueryLoaderFactory = exports.AssocEdgeLoaderFactory = exports.AssocEdgeLoader = exports.AssocDirectEdgeLoader = exports.AssocEdgeCountLoaderFactory = exports.AssocEdgeCountLoader = exports.RawCountLoaderFactory = exports.RawCountLoader = exports.ObjectLoaderFactory = exports.ObjectLoader = void 0;
3
+ exports.setLoaderMaxBatchSize = exports.getLoaderMaxBatchSize = exports.QueryLoaderFactory = 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; } });
@@ -16,3 +16,6 @@ Object.defineProperty(exports, "AssocEdgeLoader", { enumerable: true, get: funct
16
16
  Object.defineProperty(exports, "AssocEdgeLoaderFactory", { enumerable: true, get: function () { return assoc_edge_loader_1.AssocEdgeLoaderFactory; } });
17
17
  var query_loader_1 = require("./query_loader");
18
18
  Object.defineProperty(exports, "QueryLoaderFactory", { enumerable: true, get: function () { return query_loader_1.QueryLoaderFactory; } });
19
+ var loader_1 = require("./loader");
20
+ Object.defineProperty(exports, "getLoaderMaxBatchSize", { enumerable: true, get: function () { return loader_1.getLoaderMaxBatchSize; } });
21
+ Object.defineProperty(exports, "setLoaderMaxBatchSize", { enumerable: true, get: function () { return loader_1.setLoaderMaxBatchSize; } });
@@ -1,4 +1,6 @@
1
1
  import { Loader, LoaderFactory, Context, DataOptions } from "../base";
2
+ export declare function getLoaderMaxBatchSize(): number;
3
+ export declare function setLoaderMaxBatchSize(size?: number | null): void;
2
4
  export declare function getLoader<K, V>(factory: LoaderFactory<K, V>, create: () => Loader<K, V>, context?: Context): Loader<K, V>;
3
5
  export declare function getCustomLoader<K, V>(key: string, create: () => Loader<K, V>, context?: Context): Loader<K, V>;
4
6
  export declare class CacheMap {
@@ -1,7 +1,26 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CacheMap = exports.getCustomLoader = exports.getLoader = void 0;
3
+ exports.CacheMap = void 0;
4
+ exports.getLoaderMaxBatchSize = getLoaderMaxBatchSize;
5
+ exports.setLoaderMaxBatchSize = setLoaderMaxBatchSize;
6
+ exports.getLoader = getLoader;
7
+ exports.getCustomLoader = getCustomLoader;
4
8
  const logger_1 = require("../logger");
9
+ const DEFAULT_MAX_BATCH_SIZE = 1000;
10
+ let loaderMaxBatchSize = DEFAULT_MAX_BATCH_SIZE;
11
+ function getLoaderMaxBatchSize() {
12
+ return loaderMaxBatchSize;
13
+ }
14
+ function setLoaderMaxBatchSize(size) {
15
+ if (size === undefined || size === null) {
16
+ loaderMaxBatchSize = DEFAULT_MAX_BATCH_SIZE;
17
+ return;
18
+ }
19
+ if (!Number.isFinite(size) || size <= 0) {
20
+ throw new Error(`maxBatchSize must be a positive number`);
21
+ }
22
+ loaderMaxBatchSize = Math.floor(size);
23
+ }
5
24
  // this is like factory factory FML
6
25
  // helper function to handle context vs not
7
26
  // and to keep the API clean for clients who shouldn't have to worry about this
@@ -14,7 +33,6 @@ function getLoader(factory, create, context) {
14
33
  // g|set from context cache
15
34
  return context.cache.getLoader(factory.name, create);
16
35
  }
17
- exports.getLoader = getLoader;
18
36
  function getCustomLoader(key, create, context) {
19
37
  // just create a new one every time if no context cache
20
38
  if (!context?.cache) {
@@ -24,7 +42,6 @@ function getCustomLoader(key, create, context) {
24
42
  // g|set from context cache
25
43
  return context.cache.getLoader(key, create);
26
44
  }
27
- exports.getCustomLoader = getCustomLoader;
28
45
  class CacheMap {
29
46
  constructor(options) {
30
47
  this.options = options;
@@ -1,14 +1,16 @@
1
1
  import { ID, Data, SelectDataOptions, Context, Loader, LoaderFactory } from "../base";
2
2
  import * as clause from "../clause";
3
+ export declare function setClauseLoaderConcurrency(limit: number): void;
4
+ export declare function mapWithConcurrency<T, R>(items: T[], limit: number, mapper: (item: T, index: number) => Promise<R>): Promise<R[]>;
3
5
  export declare class ObjectLoader<TQueryData extends Data = Data, TResultData extends Data = TQueryData, K = keyof TQueryData> implements Loader<ID, TResultData | null>, Loader<clause.Clause<TQueryData, K>, TResultData[] | null> {
4
6
  private options;
5
- context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined;
7
+ context?: Context | undefined;
6
8
  private toPrime?;
7
9
  private idLoader;
8
10
  private clauseLoader;
9
11
  private primedLoaders;
10
12
  private memoizedInitPrime;
11
- constructor(options: SelectDataOptions, context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined, toPrime?: ObjectLoaderFactory<TResultData>[] | undefined);
13
+ constructor(options: SelectDataOptions, context?: Context | undefined, toPrime?: ObjectLoaderFactory<TResultData>[] | undefined);
12
14
  getOptions(): SelectDataOptions;
13
15
  private initPrime;
14
16
  load(key: ID): Promise<TResultData | null>;
@@ -25,9 +27,9 @@ export declare class ObjectLoader<TQueryData extends Data = Data, TResultData ex
25
27
  }
26
28
  export declare class ObjectCountLoader<V extends Data = Data, K = keyof V> implements Loader<clause.Clause<V, K>, number> {
27
29
  private options;
28
- context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined;
30
+ context?: Context | undefined;
29
31
  private loader;
30
- constructor(options: SelectDataOptions, context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined);
32
+ constructor(options: SelectDataOptions, context?: Context | undefined);
31
33
  getOptions(): SelectDataOptions;
32
34
  load(key: clause.Clause<V, K>): Promise<number>;
33
35
  clearAll(): void;
@@ -15,18 +15,30 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
15
15
  }) : function(o, v) {
16
16
  o["default"] = v;
17
17
  });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
25
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
37
  };
28
38
  Object.defineProperty(exports, "__esModule", { value: true });
29
39
  exports.ObjectLoaderFactory = exports.ObjectCountLoader = exports.ObjectLoader = void 0;
40
+ exports.setClauseLoaderConcurrency = setClauseLoaderConcurrency;
41
+ exports.mapWithConcurrency = mapWithConcurrency;
30
42
  const dataloader_1 = __importDefault(require("dataloader"));
31
43
  const ent_1 = require("../ent");
32
44
  const clause = __importStar(require("../clause"));
@@ -34,14 +46,48 @@ const logger_1 = require("../logger");
34
46
  const clause_1 = require("../clause");
35
47
  const loader_1 = require("./loader");
36
48
  const memoizee_1 = __importDefault(require("memoizee"));
49
+ const DEFAULT_CLAUSE_LOADER_CONCURRENCY = 10;
50
+ let clauseLoaderConcurrency = DEFAULT_CLAUSE_LOADER_CONCURRENCY;
51
+ function setClauseLoaderConcurrency(limit) {
52
+ if (!Number.isFinite(limit) || limit < 1) {
53
+ clauseLoaderConcurrency = DEFAULT_CLAUSE_LOADER_CONCURRENCY;
54
+ return;
55
+ }
56
+ clauseLoaderConcurrency = Math.floor(limit);
57
+ }
58
+ async function mapWithConcurrency(items, limit, mapper) {
59
+ if (!items.length) {
60
+ return [];
61
+ }
62
+ const results = new Array(items.length);
63
+ const workerCount = Math.min(items.length, Math.max(1, limit));
64
+ let nextIndex = 0;
65
+ const workers = Array.from({ length: workerCount }, async () => {
66
+ while (true) {
67
+ const currentIndex = nextIndex;
68
+ nextIndex += 1;
69
+ if (currentIndex >= items.length) {
70
+ return;
71
+ }
72
+ results[currentIndex] = await mapper(items[currentIndex], currentIndex);
73
+ }
74
+ });
75
+ await Promise.all(workers);
76
+ return results;
77
+ }
37
78
  async function loadRowsForIDLoader(options, ids, context) {
38
79
  let col = options.key;
39
- const cls = (0, clause_1.getCombinedClause)(options, clause.DBTypeIn(col, ids, options.keyType || "uuid"));
40
- const rowOptions = {
41
- ...options,
42
- clause: cls,
43
- context,
44
- };
80
+ const typ = options.keyType || "uuid";
81
+ const maxBatchSize = (0, loader_1.getLoaderMaxBatchSize)();
82
+ const batches = [];
83
+ if (maxBatchSize > 0 && ids.length > maxBatchSize) {
84
+ for (let i = 0; i < ids.length; i += maxBatchSize) {
85
+ batches.push(ids.slice(i, i + maxBatchSize));
86
+ }
87
+ }
88
+ else {
89
+ batches.push(ids);
90
+ }
45
91
  let m = new Map();
46
92
  let result = [];
47
93
  for (let i = 0; i < ids.length; i++) {
@@ -49,17 +95,25 @@ async function loadRowsForIDLoader(options, ids, context) {
49
95
  // store the index....
50
96
  m.set(ids[i], i);
51
97
  }
52
- const rows = (await (0, ent_1.loadRows)(rowOptions));
53
- for (const row of rows) {
54
- const id = row[col];
55
- if (id === undefined) {
56
- throw new Error(`need to query for column ${col} when using an object loader because the query may not be sorted and we need the id to maintain sort order`);
57
- }
58
- const idx = m.get(id);
59
- if (idx === undefined) {
60
- throw new Error(`malformed query. got ${id} back but didn't query for it`);
98
+ for (const batch of batches) {
99
+ const cls = (0, clause_1.getCombinedClause)(options, clause.DBTypeIn(col, batch, typ));
100
+ const rowOptions = {
101
+ ...options,
102
+ clause: cls,
103
+ context,
104
+ };
105
+ const rows = (await (0, ent_1.loadRows)(rowOptions));
106
+ for (const row of rows) {
107
+ const id = row[col];
108
+ if (id === undefined) {
109
+ throw new Error(`need to query for column ${col} when using an object loader because the query may not be sorted and we need the id to maintain sort order`);
110
+ }
111
+ const idx = m.get(id);
112
+ if (idx === undefined) {
113
+ throw new Error(`malformed query. got ${id} back but didn't query for it`);
114
+ }
115
+ result[idx] = row;
61
116
  }
62
- result[idx] = row;
63
117
  }
64
118
  return result;
65
119
  }
@@ -90,7 +144,9 @@ async function loadCountForClauseLoader(options, clause) {
90
144
  // so ObjectLoaderFactory and createDataLoader need to take a new optional field which is a clause that's always added here
91
145
  // and we need a disableTransform which skips loader completely and uses loadRow...
92
146
  function createDataLoader(options) {
93
- const loaderOptions = {};
147
+ const loaderOptions = {
148
+ maxBatchSize: (0, loader_1.getLoaderMaxBatchSize)(),
149
+ };
94
150
  // if query logging is enabled, we should log what's happening with loader
95
151
  if ((0, logger_1.logEnabled)("query")) {
96
152
  loaderOptions.cacheMap = new loader_1.CacheMap(options);
@@ -135,14 +191,10 @@ function createClauseDataLoder(options) {
135
191
  if (!clauses.length) {
136
192
  return [];
137
193
  }
138
- const ret = [];
139
- for await (const clause of clauses) {
140
- const data = await loadRowsForClauseLoader(options, clause);
141
- ret.push(data);
142
- }
143
- return ret;
194
+ return mapWithConcurrency(clauses, clauseLoaderConcurrency, (clauseItem) => loadRowsForClauseLoader(options, clauseItem));
144
195
  }, {
145
196
  cacheMap: new clauseCacheMap(options),
197
+ maxBatchSize: (0, loader_1.getLoaderMaxBatchSize)(),
146
198
  });
147
199
  }
148
200
  function createClauseCountDataLoader(options) {
@@ -150,14 +202,10 @@ function createClauseCountDataLoader(options) {
150
202
  if (!clauses.length) {
151
203
  return [];
152
204
  }
153
- const ret = [];
154
- for await (const clause of clauses) {
155
- const data = await loadCountForClauseLoader(options, clause);
156
- ret.push(data);
157
- }
158
- return ret;
205
+ return mapWithConcurrency(clauses, clauseLoaderConcurrency, (clauseItem) => loadCountForClauseLoader(options, clauseItem));
159
206
  }, {
160
207
  cacheMap: new clauseCacheMap(options, true),
208
+ maxBatchSize: (0, loader_1.getLoaderMaxBatchSize)(),
161
209
  });
162
210
  }
163
211
  class ObjectLoader {
@@ -252,12 +300,7 @@ class ObjectLoader {
252
300
  // @ts-expect-error TODO?
253
301
  return this.clauseLoader.loadMany(keys);
254
302
  }
255
- const res = [];
256
- for await (const key of keys) {
257
- const rows = await loadRowsForClauseLoader(this.options, key);
258
- res.push(rows);
259
- }
260
- return res;
303
+ return mapWithConcurrency(keys, clauseLoaderConcurrency, (key) => loadRowsForClauseLoader(this.options, key));
261
304
  }
262
305
  prime(data) {
263
306
  // we have this data from somewhere else, prime it in the c
@@ -309,12 +352,7 @@ class ObjectCountLoader {
309
352
  // @ts-expect-error
310
353
  return this.loader.loadMany(keys);
311
354
  }
312
- const res = [];
313
- for await (const key of keys) {
314
- const r = await loadCountForClauseLoader(this.options, key);
315
- res.push(r);
316
- }
317
- return res;
355
+ return mapWithConcurrency(keys, clauseLoaderConcurrency, (key) => loadCountForClauseLoader(this.options, key));
318
356
  }
319
357
  }
320
358
  exports.ObjectCountLoader = ObjectCountLoader;
@@ -5,10 +5,10 @@ import { ObjectLoaderFactory } from "./object_loader";
5
5
  declare class QueryDirectLoader<K extends any> implements Loader<K, Data[]> {
6
6
  private options;
7
7
  private queryOptions?;
8
- context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, import("../base").ID | null>> | undefined;
8
+ context?: Context | undefined;
9
9
  private memoizedInitPrime;
10
10
  private primedLoaders;
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, import("../base").ID | null>> | undefined);
11
+ constructor(options: QueryOptions, queryOptions?: EdgeQueryableDataOptions | undefined, context?: Context | undefined);
12
12
  private initPrime;
13
13
  load(id: K): Promise<Data[]>;
14
14
  clearAll(): void;
@@ -15,13 +15,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
15
15
  }) : function(o, v) {
16
16
  o["default"] = v;
17
17
  });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
25
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
37
  };
@@ -32,6 +42,7 @@ const memoizee_1 = __importDefault(require("memoizee"));
32
42
  const clause = __importStar(require("../clause"));
33
43
  const ent_1 = require("../ent");
34
44
  const logger_1 = require("../logger");
45
+ const cache_utils_1 = require("./cache_utils");
35
46
  const loader_1 = require("./loader");
36
47
  function getOrderByLocal(options, queryOptions) {
37
48
  return (options.orderby ??
@@ -68,7 +79,9 @@ async function simpleCase(options, id, queryOptions) {
68
79
  });
69
80
  }
70
81
  function createLoader(options, queryOptions) {
71
- const loaderOptions = {};
82
+ const loaderOptions = {
83
+ maxBatchSize: (0, loader_1.getLoaderMaxBatchSize)(),
84
+ };
72
85
  // if query logging is enabled, we should log what's happening with loader
73
86
  if ((0, logger_1.logEnabled)("query")) {
74
87
  loaderOptions.cacheMap = new loader_1.CacheMap(options);
@@ -234,7 +247,10 @@ class QueryLoaderFactory {
234
247
  if (options.clause || !context) {
235
248
  return new QueryDirectLoader(queryOptions, options, context);
236
249
  }
237
- const key = `${name}:limit:${options.limit}:orderby:${options.orderby}`;
250
+ const effectiveOrderBy = getOrderByLocal(queryOptions, options);
251
+ const effectiveLimit = options.limit || (0, ent_1.getDefaultLimit)();
252
+ const disableTransformations = options.disableTransformations ?? false;
253
+ const key = `${name}:limit:${effectiveLimit}:orderby:${(0, cache_utils_1.stableStringify)(effectiveOrderBy)}:disableTransformations:${disableTransformations}`;
238
254
  return (0, loader_1.getCustomLoader)(key, () => new QueryLoader(queryOptions, context, options), context);
239
255
  }
240
256
  }
@@ -10,9 +10,9 @@ interface QueryCountOptions {
10
10
  export declare function createCountDataLoader<K extends any>(options: QueryCountOptions): DataLoader<K, number, K>;
11
11
  export declare class RawCountLoader<K extends any> implements Loader<K, number> {
12
12
  private options;
13
- context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined;
13
+ context?: Context | undefined;
14
14
  private loader;
15
- constructor(options: QueryCountOptions, context?: Context<import("../base").Viewer<import("../base").Ent<any> | null, ID | null>> | undefined);
15
+ constructor(options: QueryCountOptions, context?: Context | undefined);
16
16
  load(id: K): Promise<number>;
17
17
  clearAll(): void;
18
18
  }
@@ -15,18 +15,29 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
15
15
  }) : function(o, v) {
16
16
  o["default"] = v;
17
17
  });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
25
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
37
  };
28
38
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.RawCountLoaderFactory = exports.RawCountLoader = exports.createCountDataLoader = void 0;
39
+ exports.RawCountLoaderFactory = exports.RawCountLoader = void 0;
40
+ exports.createCountDataLoader = createCountDataLoader;
30
41
  const dataloader_1 = __importDefault(require("dataloader"));
31
42
  const ent_1 = require("../ent");
32
43
  const clause = __importStar(require("../clause"));
@@ -56,7 +67,9 @@ async function simpleCase(options, key, context) {
56
67
  return [parseInt(row?.count, 10) || 0];
57
68
  }
58
69
  function createCountDataLoader(options) {
59
- const loaderOptions = {};
70
+ const loaderOptions = {
71
+ maxBatchSize: (0, loader_1.getLoaderMaxBatchSize)(),
72
+ };
60
73
  // if query logging is enabled, we should log what's happening with loader
61
74
  if ((0, logger_1.logEnabled)("query")) {
62
75
  loaderOptions.cacheMap = new loader_1.CacheMap(options);
@@ -99,7 +112,6 @@ function createCountDataLoader(options) {
99
112
  return result;
100
113
  }, loaderOptions);
101
114
  }
102
- exports.createCountDataLoader = createCountDataLoader;
103
115
  // for now this only works for single column counts
104
116
  // e.g. foreign key count
105
117
  class RawCountLoader {