nesoi 3.3.20 → 3.3.21

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 (44) hide show
  1. package/lib/elements/edge/controller/adapters/controller_adapter.d.ts +4 -1
  2. package/lib/elements/edge/controller/adapters/controller_adapter.js +8 -4
  3. package/lib/elements/edge/controller/controller.js +3 -3
  4. package/lib/elements/edge/controller/controller.schema.d.ts +2 -1
  5. package/lib/elements/edge/controller/controller.schema.js +3 -1
  6. package/lib/elements/entities/bucket/adapters/bucket_adapter.d.ts +25 -3
  7. package/lib/elements/entities/bucket/adapters/bucket_adapter.js +21 -2
  8. package/lib/elements/entities/bucket/adapters/memory.nql.js +80 -44
  9. package/lib/elements/entities/bucket/adapters/test.bucket_adapter.d.ts +22 -0
  10. package/lib/elements/entities/bucket/adapters/test.bucket_adapter.js +23 -0
  11. package/lib/elements/entities/bucket/bucket.js +2 -2
  12. package/lib/elements/entities/bucket/cache/bucket_cache.d.ts +16 -1
  13. package/lib/elements/entities/bucket/cache/bucket_cache.js +36 -15
  14. package/lib/elements/entities/bucket/graph/bucket_graph.js +28 -18
  15. package/lib/elements/entities/bucket/query/nql.schema.d.ts +3 -0
  16. package/lib/elements/entities/bucket/query/nql_compiler.d.ts +10 -4
  17. package/lib/elements/entities/bucket/query/nql_compiler.js +42 -35
  18. package/lib/elements/entities/bucket/query/nql_engine.d.ts +4 -1
  19. package/lib/elements/entities/bucket/query/nql_engine.js +3 -5
  20. package/lib/elements/entities/message/template/message_template_field.builder.d.ts +2 -0
  21. package/lib/elements/entities/message/template/message_template_field.builder.js +5 -0
  22. package/lib/engine/daemon.d.ts +19 -0
  23. package/lib/engine/daemon.js +40 -2
  24. package/lib/engine/data/tree.d.ts +1 -2
  25. package/lib/engine/data/tree.js +6 -94
  26. package/lib/engine/transaction/nodes/bucket.trx_node.d.ts +1 -1
  27. package/lib/engine/transaction/nodes/bucket.trx_node.js +15 -15
  28. package/lib/engine/transaction/nodes/bucket_query.trx_node.js +2 -2
  29. package/lib/engine/transaction/nodes/external.trx_node.d.ts +3 -1
  30. package/lib/engine/transaction/nodes/external.trx_node.js +54 -4
  31. package/lib/engine/transaction/nodes/job.trx_node.js +3 -2
  32. package/lib/engine/transaction/nodes/machine.trx_node.js +1 -1
  33. package/lib/engine/transaction/nodes/queue.trx_node.js +1 -1
  34. package/lib/engine/transaction/nodes/resource.trx_node.js +1 -1
  35. package/lib/engine/transaction/nodes/topic.trx_node.js +1 -1
  36. package/lib/engine/transaction/trx.d.ts +7 -1
  37. package/lib/engine/transaction/trx.js +15 -1
  38. package/lib/engine/transaction/trx_engine.config.d.ts +6 -1
  39. package/lib/engine/transaction/trx_engine.d.ts +5 -5
  40. package/lib/engine/transaction/trx_engine.js +59 -36
  41. package/lib/engine/transaction/trx_node.d.ts +1 -1
  42. package/lib/engine/transaction/trx_node.js +1 -1
  43. package/package.json +1 -1
  44. package/tsconfig.build.tsbuildinfo +1 -1
@@ -13,7 +13,10 @@ export declare abstract class ControllerAdapter {
13
13
  protected schema: $Controller;
14
14
  protected daemon?: AnyDaemon;
15
15
  constructor(module: $Module, schema: $Controller);
16
- trx(fn: (trx: AnyTrxNode) => Promise<any>, auth?: AuthRequest<any>): Promise<import("../../../../engine/transaction/trx").TrxStatus<any>>;
16
+ trx(fn: (trx: AnyTrxNode) => Promise<any>, endpoint: {
17
+ name: string;
18
+ idempotent?: boolean;
19
+ }, auth?: AuthRequest<any>): Promise<import("../../../../engine/transaction/trx").TrxStatus<any>>;
17
20
  bind(daemon: AnyDaemon): void;
18
21
  protected abstract makeEndpoint(path: string, schema: $ControllerEndpoint): void;
19
22
  protected abstract makeTopic(schema: $ControllerTopic): void;
@@ -14,14 +14,18 @@ class ControllerAdapter {
14
14
  this.module = module;
15
15
  this.schema = schema;
16
16
  }
17
- async trx(fn, auth) {
17
+ async trx(fn, endpoint, auth) {
18
18
  if (!this.daemon) {
19
19
  throw new Error('Controller not bound to a daemon');
20
20
  }
21
21
  try {
22
- return await this.daemon.trx(this.schema.module)
23
- .auth(auth)
24
- .run(fn);
22
+ const trx = this.daemon.trx(this.schema.module)
23
+ .origin(endpoint.name)
24
+ .auth(auth);
25
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
26
+ if (endpoint.idempotent)
27
+ trx.idempotent;
28
+ return await trx.run(fn);
25
29
  }
26
30
  catch (e) {
27
31
  log_1.Log.error('controller', this.schema.name, 'Unknown error', e);
@@ -36,7 +36,7 @@ class ControllerEndpoint {
36
36
  if (this.schema.target.type === 'machine') {
37
37
  return trx.machine(this.schema.target.short).run(raw);
38
38
  }
39
- }, auth);
39
+ }, this.schema, auth);
40
40
  }
41
41
  }
42
42
  exports.ControllerEndpoint = ControllerEndpoint;
@@ -57,7 +57,7 @@ class ControllerTopic {
57
57
  const response = await this.adapter.trx(async (trx) => {
58
58
  await trx_node_1.TrxNode.checkAuth(trx, this.schema.auth);
59
59
  return trx.topic(this.schema.name).subscribe(fn);
60
- }, auth);
60
+ }, this.schema, auth);
61
61
  if (response.state === 'error') {
62
62
  throw error_1.NesoiError.Controller.SubscribeFailed({ topic: this.schema.alias });
63
63
  }
@@ -67,7 +67,7 @@ class ControllerTopic {
67
67
  const response = await this.adapter.trx(async (trx) => {
68
68
  await trx_node_1.TrxNode.checkAuth(trx, this.schema.auth);
69
69
  return trx.topic(this.schema.name).unsubscribe(id);
70
- });
70
+ }, this.schema);
71
71
  if (response.state === 'error') {
72
72
  throw error_1.NesoiError.Controller.UnsubscribeFailed({ topic: this.schema.alias });
73
73
  }
@@ -14,8 +14,9 @@ export declare class $ControllerEndpoint {
14
14
  msg: Tag;
15
15
  target: Tag;
16
16
  implicit?: Record<string, any> | undefined;
17
+ idempotent: boolean;
17
18
  $t: string;
18
- constructor(name: string, alias: string, auth: $BlockAuth[], tags: string[], msg: Tag, target: Tag, implicit?: Record<string, any> | undefined);
19
+ constructor(name: string, alias: string, auth: $BlockAuth[], tags: string[], msg: Tag, target: Tag, implicit?: Record<string, any> | undefined, idempotent?: boolean);
19
20
  }
20
21
  /**
21
22
  * @category Schemas
@@ -13,8 +13,9 @@ class $ControllerEndpoint {
13
13
  msg;
14
14
  target;
15
15
  implicit;
16
+ idempotent;
16
17
  $t = 'controller.endpoint';
17
- constructor(name, alias, auth, tags, msg, target, implicit) {
18
+ constructor(name, alias, auth, tags, msg, target, implicit, idempotent = false) {
18
19
  this.name = name;
19
20
  this.alias = alias;
20
21
  this.auth = auth;
@@ -22,6 +23,7 @@ class $ControllerEndpoint {
22
23
  this.msg = msg;
23
24
  this.target = target;
24
25
  this.implicit = implicit;
26
+ this.idempotent = idempotent;
25
27
  }
26
28
  }
27
29
  exports.$ControllerEndpoint = $ControllerEndpoint;
@@ -3,8 +3,8 @@ import { NesoiObj, ObjWithOptionalId } from "../../../../engine/data/obj";
3
3
  import { BucketCacheSync } from '../cache/bucket_cache';
4
4
  import { NQL_AnyQuery, NQL_Pagination } from '../query/nql.schema';
5
5
  import { NQLRunner, NQL_Result } from '../query/nql_engine';
6
+ import { NQL_CompiledQuery } from '../query/nql_compiler';
6
7
  import { $Bucket } from "../../..";
7
- import { BucketMetadata } from "../../../../engine/transaction/trx_engine";
8
8
  export type BucketAdapterConfig = {
9
9
  meta: {
10
10
  created_at: string;
@@ -146,8 +146,30 @@ export declare abstract class BucketAdapter<Obj extends NesoiObj, Config extends
146
146
  metadataOnly?: MetadataOnly;
147
147
  }, custom?: {
148
148
  module?: string;
149
- runners?: Record<string, NQLRunner>;
150
- metadata?: BucketMetadata;
149
+ buckets?: Record<string, {
150
+ scope: string;
151
+ nql: NQLRunner;
152
+ }>;
153
+ }): Promise<NQL_Result<MetadataOnly extends true ? {
154
+ id: Obj['id'];
155
+ [x: string]: any;
156
+ } : Obj>>;
157
+ _compileQuery(trx: AnyTrxNode, query: NQL_AnyQuery, custom?: {
158
+ module?: string;
159
+ buckets?: Record<string, {
160
+ scope: string;
161
+ nql: NQLRunner;
162
+ }>;
163
+ }): Promise<NQL_CompiledQuery>;
164
+ _queryCompiled<MetadataOnly extends boolean>(trx: AnyTrxNode, compiled: NQL_CompiledQuery, pagination?: NQL_Pagination, params?: Record<string, any>[], param_templates?: Record<string, string>[], config?: {
165
+ view?: string;
166
+ metadataOnly?: MetadataOnly;
167
+ }, custom?: {
168
+ module?: string;
169
+ buckets?: Record<string, {
170
+ scope: string;
171
+ nql: NQLRunner;
172
+ }>;
151
173
  }): Promise<NQL_Result<MetadataOnly extends true ? {
152
174
  id: Obj['id'];
153
175
  [x: string]: any;
@@ -4,6 +4,7 @@ exports.BucketAdapter = void 0;
4
4
  const trx_node_1 = require("../../../../engine/transaction/trx_node");
5
5
  const error_1 = require("../../../../engine/data/error");
6
6
  const nql_compiler_1 = require("../query/nql_compiler");
7
+ const trx_1 = require("../../../../engine/transaction/trx");
7
8
  /**
8
9
  * @category Adapters
9
10
  * @subcategory Entity
@@ -36,12 +37,30 @@ class BucketAdapter {
36
37
  async query(trx, query, pagination, params, param_templates, config,
37
38
  // When running a temporary local memory adapter,
38
39
  // these are required
40
+ custom) {
41
+ const compiled = await this._compileQuery(trx, query, custom);
42
+ return this._queryCompiled(trx, compiled, pagination, params, param_templates, config, custom);
43
+ }
44
+ async _compileQuery(trx, query,
45
+ // When running a temporary local memory adapter,
46
+ // these are required
39
47
  custom) {
40
48
  const module = trx_node_1.TrxNode.getModule(trx);
41
49
  const moduleName = custom?.module || module.name;
42
- const compiled = await nql_compiler_1.NQL_Compiler.build(module.daemon, moduleName, this.schema.name, query, custom?.metadata);
50
+ const customBuckets = {
51
+ ...(custom?.buckets || {}),
52
+ ...trx_1.Trx.getCacheCustomBuckets(trx)
53
+ };
54
+ return nql_compiler_1.NQL_Compiler.build(module.daemon, moduleName, this.schema.name, query, customBuckets);
55
+ }
56
+ async _queryCompiled(trx, compiled, pagination, params, param_templates, config, custom) {
57
+ const module = trx_node_1.TrxNode.getModule(trx);
58
+ const customBuckets = {
59
+ ...(custom?.buckets || {}),
60
+ ...trx_1.Trx.getCacheCustomBuckets(trx)
61
+ };
43
62
  const view = config?.view ? this.schema.views[config.view] : undefined;
44
- const result = await module.nql.run(trx, compiled, pagination, params, param_templates, view, custom?.runners);
63
+ const result = await module.nql.run(trx, compiled, pagination, params, param_templates, view, customBuckets);
45
64
  if (config?.metadataOnly) {
46
65
  result.data = result.data.map(obj => ({
47
66
  id: obj.id,
@@ -36,8 +36,8 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
36
36
  let fallback = 0;
37
37
  for (let i = 0; i < sort.length; i++) {
38
38
  const s = sort[i];
39
- const a_val = tree_1.Tree.get(a, s.key);
40
- const b_val = tree_1.Tree.get(b, s.key);
39
+ const a_val = s.key_is_deep ? tree_1.Tree.get(a, s.key) : a[s.key];
40
+ const b_val = s.key_is_deep ? tree_1.Tree.get(b, s.key) : b[s.key];
41
41
  if (a_val == null) {
42
42
  if (b_val == null)
43
43
  return 0;
@@ -172,56 +172,42 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
172
172
  };
173
173
  const _rule = (rule, objs, params, param_templates) => {
174
174
  const out = {};
175
- for (const id in objs) {
176
- const obj = objs[id];
177
- let match = false;
178
- const combos = [];
179
- for (const param of params) {
180
- if (param_templates.length) {
181
- for (const template of param_templates) {
182
- combos.push({ params: param, param_template: template });
183
- }
184
- }
185
- else {
186
- combos.push({ params: param, param_template: {} });
175
+ const combos = [];
176
+ for (const param of params) {
177
+ if (param_templates.length) {
178
+ for (const template of param_templates) {
179
+ combos.push({ params: param, param_template: template });
187
180
  }
188
181
  }
189
- for (const combo of combos) {
190
- match = _obj(rule, obj, combo.params, combo.param_template);
191
- if (match)
192
- break;
193
- }
194
- if (rule.not) {
195
- match = !match;
182
+ else {
183
+ combos.push({ params: param, param_template: {} });
196
184
  }
185
+ }
186
+ for (const combo of combos) {
187
+ const match = _index(rule, objs, combo.params, combo.param_template);
197
188
  if (match) {
198
- if (rule.select) {
199
- out[obj.id] = obj[rule.select];
189
+ Object.assign(out, match);
190
+ continue;
191
+ }
192
+ for (const id in objs) {
193
+ const obj = objs[id];
194
+ let match = _obj(rule, obj, combo.params, combo.param_template);
195
+ if (rule.not) {
196
+ match = !match;
200
197
  }
201
- else {
202
- out[obj.id] = obj;
198
+ if (match) {
199
+ if (rule.select) {
200
+ out[obj.id] = obj[rule.select];
201
+ }
202
+ else {
203
+ out[obj.id] = obj;
204
+ }
203
205
  }
204
206
  }
205
207
  }
206
208
  return out;
207
209
  };
208
- const _obj = (rule, obj, params, param_template) => {
209
- const fieldValue = tree_1.Tree.get(obj, rule.fieldpath);
210
- // Value is undefined, only 'present' rule applies
211
- if (fieldValue === undefined) {
212
- if (rule.op === 'present') {
213
- return false;
214
- }
215
- return false;
216
- }
217
- // Fieldpath is a spread, apply rule to each item
218
- if (rule.fieldpath.includes('.#')) {
219
- for (const item of fieldValue) {
220
- if (_obj(rule, item, params, param_template))
221
- return true;
222
- }
223
- return false;
224
- }
210
+ const _value = (rule, params, param_template) => {
225
211
  let queryValue;
226
212
  // Value is a subquery, run union
227
213
  if ('subquery' in rule.value) {
@@ -238,10 +224,14 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
238
224
  }
239
225
  else if ('param' in rule.value) {
240
226
  if (Array.isArray(rule.value.param)) {
241
- queryValue = rule.value.param.map(p => tree_1.Tree.get(params, p));
227
+ queryValue = rule.value.param_is_deep
228
+ ? rule.value.param.map(p => tree_1.Tree.get(params, p))
229
+ : rule.value.param.map(p => params[p]);
242
230
  }
243
231
  else {
244
- queryValue = tree_1.Tree.get(params, rule.value.param);
232
+ queryValue = rule.value.param_is_deep
233
+ ? tree_1.Tree.get(params, rule.value.param)
234
+ : params[rule.value.param];
245
235
  }
246
236
  }
247
237
  else if ('param_with_$' in rule.value) {
@@ -254,6 +244,52 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
254
244
  else if ('static' in rule.value) {
255
245
  queryValue = rule.value.static;
256
246
  }
247
+ return queryValue;
248
+ };
249
+ const _index = (rule, objs, params, param_template) => {
250
+ if (rule.op !== '==')
251
+ return undefined;
252
+ if (rule.fieldpath !== 'id')
253
+ return undefined;
254
+ const queryValue = _value(rule, params, param_template);
255
+ let out = {};
256
+ if (rule.not) {
257
+ out = Object.assign({}, objs);
258
+ delete out[queryValue];
259
+ }
260
+ else {
261
+ const obj = objs[queryValue];
262
+ if (obj) {
263
+ out[obj.id] = obj;
264
+ }
265
+ }
266
+ if (rule.select) {
267
+ for (const id in out) {
268
+ out[id] = out[id][rule.select];
269
+ }
270
+ }
271
+ return out;
272
+ };
273
+ const _obj = (rule, obj, params, param_template) => {
274
+ const fieldValue = rule.fieldpath_is_deep
275
+ ? tree_1.Tree.get(obj, rule.fieldpath)
276
+ : obj[rule.fieldpath];
277
+ // Value is undefined, only 'present' rule applies
278
+ if (fieldValue === undefined) {
279
+ if (rule.op === 'present') {
280
+ return false;
281
+ }
282
+ return false;
283
+ }
284
+ // Fieldpath is a spread, apply rule to each item
285
+ if (rule.fieldpath.includes('.#')) {
286
+ for (const item of fieldValue) {
287
+ if (_obj(rule, item, params, param_template))
288
+ return true;
289
+ }
290
+ return false;
291
+ }
292
+ const queryValue = _value(rule, params, param_template);
257
293
  // Check each operation
258
294
  // (Compatible operations and types have already been validated)
259
295
  if (rule.op === '<') {
@@ -0,0 +1,22 @@
1
+ import { BucketAdapterConfig } from './bucket_adapter';
2
+ import { $Bucket, MemoryBucketAdapter } from "../../..";
3
+ /**
4
+ * @category Adapters
5
+ * @subcategory Entity
6
+ */
7
+ export declare class TestBucketAdapter<B extends $Bucket, Obj extends B['#data']> extends MemoryBucketAdapter<B, Obj> {
8
+ schema: B;
9
+ data: NoInfer<Record<Obj['id'], Obj>>;
10
+ private queryMeta?;
11
+ constructor(schema: B, data?: NoInfer<Record<Obj['id'], Obj>>, config?: BucketAdapterConfig & {
12
+ queryMeta?: {
13
+ scope: string;
14
+ avgTime: number;
15
+ };
16
+ });
17
+ getQueryMeta(): {
18
+ scope: string;
19
+ avgTime: number;
20
+ };
21
+ }
22
+ export type AnyTestBucketAdapter = TestBucketAdapter<any, any>;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TestBucketAdapter = void 0;
4
+ const elements_1 = require("../../..");
5
+ /**
6
+ * @category Adapters
7
+ * @subcategory Entity
8
+ */
9
+ class TestBucketAdapter extends elements_1.MemoryBucketAdapter {
10
+ schema;
11
+ data;
12
+ queryMeta;
13
+ constructor(schema, data = {}, config) {
14
+ super(schema, data, config);
15
+ this.schema = schema;
16
+ this.data = data;
17
+ this.queryMeta = config?.queryMeta;
18
+ }
19
+ getQueryMeta() {
20
+ return this.queryMeta || super.getQueryMeta();
21
+ }
22
+ }
23
+ exports.TestBucketAdapter = TestBucketAdapter;
@@ -88,8 +88,8 @@ class Bucket {
88
88
  ? undefined
89
89
  : this.getTenancyQuery(trx);
90
90
  let raw;
91
- // With Tenancy
92
91
  const adapter = await trx_1.Trx.getCache(trx, this) || this.cache || this.adapter;
92
+ // With Tenancy
93
93
  if (tenancy) {
94
94
  const result = await adapter.query(trx, {
95
95
  id,
@@ -127,8 +127,8 @@ class Bucket {
127
127
  ? undefined
128
128
  : this.getTenancyQuery(trx);
129
129
  let raws;
130
- // With Tenancy
131
130
  const adapter = await trx_1.Trx.getCache(trx, this) || this.cache || this.adapter;
131
+ // With Tenancy
132
132
  if (tenancy) {
133
133
  const result = await adapter.query(trx, tenancy, undefined, undefined, undefined, options?.query_view ? { view: options?.query_view } : undefined);
134
134
  raws = result.data;
@@ -2,8 +2,9 @@ import { BucketConfig } from '../bucket.config';
2
2
  import { AnyTrxNode } from "../../../../engine/transaction/trx_node";
3
3
  import { NesoiObj } from "../../../../engine/data/obj";
4
4
  import { NQL_AnyQuery, NQL_Pagination } from '../query/nql.schema';
5
- import { NQL_Result } from '../query/nql_engine';
5
+ import { NQL_Result, NQLRunner } from '../query/nql_engine';
6
6
  import { AnyBucket } from '../bucket';
7
+ import { NQL_CompiledQuery } from '../query/nql_compiler';
7
8
  export type BucketCacheSync<T> = {
8
9
  obj: T;
9
10
  updateEpoch: number;
@@ -42,6 +43,20 @@ export declare class BucketCache<Obj extends NesoiObj> {
42
43
  id: Obj['id'];
43
44
  [x: string]: any;
44
45
  } : Obj>>;
46
+ _compileQuery(trx: AnyTrxNode, query: NQL_AnyQuery, custom?: {
47
+ module?: string;
48
+ buckets?: Record<string, {
49
+ scope: string;
50
+ nql: NQLRunner;
51
+ }>;
52
+ }): Promise<NQL_CompiledQuery>;
53
+ _queryCompiled<MetadataOnly extends boolean>(trx: AnyTrxNode, query: NQL_CompiledQuery, pagination?: NQL_Pagination, params?: Record<string, any>[], param_templates?: Record<string, string>[], config?: {
54
+ view?: string;
55
+ metadataOnly?: MetadataOnly;
56
+ }): Promise<NQL_Result<MetadataOnly extends true ? {
57
+ id: Obj['id'];
58
+ [x: string]: any;
59
+ } : Obj>>;
45
60
  /**
46
61
  * Update inner adapter with data from outer adapter.
47
62
  */
@@ -2,11 +2,15 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.BucketCache = exports.BucketCacheEntry = void 0;
4
4
  const log_1 = require("../../../../engine/util/log");
5
+ const trx_node_1 = require("../../../../engine/transaction/trx_node");
5
6
  const memory_bucket_adapter_1 = require("../adapters/memory.bucket_adapter");
6
7
  const datetime_1 = require("../../../../engine/data/datetime");
7
8
  const bucket_schema_1 = require("../bucket.schema");
8
9
  const bucket_model_schema_1 = require("../model/bucket_model.schema");
9
10
  const bucket_graph_schema_1 = require("../graph/bucket_graph.schema");
11
+ const dependency_1 = require("../../../../engine/dependency");
12
+ const nql_compiler_1 = require("../query/nql_compiler");
13
+ const trx_1 = require("../../../../engine/transaction/trx");
10
14
  /**
11
15
  * @category Elements
12
16
  * @subcategory Entity
@@ -105,26 +109,42 @@ class BucketCache {
105
109
  return out;
106
110
  }
107
111
  async query(trx, query, pagination, params, param_templates, config) {
112
+ const compiled = await this._compileQuery(trx, query);
113
+ return this._queryCompiled(trx, compiled, pagination, params, param_templates, config);
114
+ }
115
+ async _compileQuery(trx, query,
116
+ // When running a temporary local memory adapter,
117
+ // these are required
118
+ custom) {
119
+ const module = trx_node_1.TrxNode.getModule(trx);
120
+ const moduleName = custom?.module || module.name;
121
+ const customBuckets = {
122
+ ...(custom?.buckets || {}),
123
+ ...trx_1.Trx.getCacheCustomBuckets(trx)
124
+ };
125
+ return nql_compiler_1.NQL_Compiler.build(module.daemon, moduleName, this.bucket.schema.name, query, customBuckets);
126
+ }
127
+ async _queryCompiled(trx, query, pagination, params, param_templates, config) {
128
+ const tag = new dependency_1.Tag(this.bucket.schema.module, 'bucket', this.bucket.schema.name);
108
129
  const mode = this.config?.mode?.query;
109
130
  let data;
110
131
  if (mode === 'eager') {
111
132
  log_1.Log.debug('bucket', this.bucket.schema.name, 'CACHE index.eager');
112
- data = await this.innerAdapter.query(trx, query, pagination, params, param_templates, config);
133
+ const result = await this.innerAdapter._queryCompiled(trx, query, pagination, params, param_templates, config, {
134
+ module: this.bucket.schema.module
135
+ });
136
+ data = result.data;
113
137
  }
114
- if (mode === 'incremental') {
115
- const { action, sync } = await this.syncQuery(trx, query, pagination, params);
138
+ else if (mode === 'incremental') {
139
+ const { action, sync } = await this.syncQuery(trx, query /* TODO */, pagination, params);
116
140
  log_1.Log.debug('bucket', this.bucket.schema.name, `CACHE query.incremental, ${action}`);
117
141
  data = sync;
118
142
  }
119
143
  else if (mode === 'all') {
120
144
  const { action, sync } = await this.syncAll(trx);
121
145
  log_1.Log.debug('bucket', this.bucket.schema.name, `CACHE query.all, ${action}`);
122
- const meta = this.innerAdapter.getQueryMeta();
123
- const entries = (await this.innerAdapter.query(trx, query, pagination, params, undefined, undefined, {
124
- module: this.bucket.schema.module,
125
- runners: {
126
- [meta.scope]: this.innerAdapter.nql
127
- }
146
+ const entries = (await this.innerAdapter._queryCompiled(trx, query, pagination, params, undefined, undefined, {
147
+ module: this.bucket.schema.module
128
148
  })).data;
129
149
  data = [];
130
150
  for (const e of entries) {
@@ -132,8 +152,10 @@ class BucketCache {
132
152
  data.push(obj);
133
153
  }
134
154
  }
155
+ // Invalid mode, bypass cache
135
156
  else {
136
- data = (await this.outerAdapter.query(trx, query, pagination, params)).data;
157
+ const result = await this.outerAdapter.query(trx, query /* TODO */, pagination, params);
158
+ data = result.data;
137
159
  }
138
160
  for (const entry of data) {
139
161
  delete entry['__update_epoch'];
@@ -149,6 +171,7 @@ class BucketCache {
149
171
  * Update inner adapter with data from outer adapter.
150
172
  */
151
173
  async sync(trx) {
174
+ log_1.Log.debug('bucket', this.bucket.schema.name, `CACHE sync, trx: ${trx.globalId}`);
152
175
  const objects = await this.outerAdapter.index(trx);
153
176
  const entries = objects.map(obj => new BucketCacheEntry(obj, this.outerAdapter.getUpdateEpoch(obj), this.lastSyncEpoch));
154
177
  await this.innerAdapter.deleteEverything(trx);
@@ -162,6 +185,7 @@ class BucketCache {
162
185
  * - reduces transit payload for data that doesn't change much
163
186
  */
164
187
  async syncOne(trx, id) {
188
+ log_1.Log.debug('bucket', this.bucket.schema.name, `CACHE sync one: ${id}, trx: ${trx.globalId}`);
165
189
  let localObj = await this.innerAdapter.get(trx, id);
166
190
  if (!localObj) {
167
191
  const obj = await this.outerAdapter.get(trx, id);
@@ -253,14 +277,11 @@ class BucketCache {
253
277
  return { action: 'none', sync: [] };
254
278
  }
255
279
  // 2. Read ids from the inner adapter
256
- const meta = this.innerAdapter.getQueryMeta();
280
+ const tag = new dependency_1.Tag(this.bucket.schema.module, 'bucket', this.bucket.schema.name);
257
281
  const innerData = await this.innerAdapter.query(trx, {
258
282
  'id in': outerMetadata.data.map(obj => obj.id)
259
283
  }, undefined, undefined, undefined, undefined, {
260
- module: this.bucket.schema.module,
261
- runners: {
262
- [meta.scope]: this.innerAdapter.nql
263
- }
284
+ module: this.bucket.schema.module
264
285
  });
265
286
  // 3. Filter modified query results
266
287
  const outerEpoch = {};
@@ -62,7 +62,7 @@ class BucketGraph {
62
62
  ...schema.query,
63
63
  '#and __tenancy__': tenancy
64
64
  };
65
- const adapter = await trx_1.Trx.getCache(trx, this.bucket) || otherBucket.cache || otherBucket.adapter;
65
+ const adapter = await trx_1.Trx.getCache(trx, otherBucket) || otherBucket.cache || otherBucket.adapter;
66
66
  links = await adapter.query(trx, query, page, params, param_templates ? [param_templates] : undefined);
67
67
  }
68
68
  // Empty response
@@ -113,8 +113,8 @@ class BucketGraph {
113
113
  const tempData = {};
114
114
  for (const obj of allLinks)
115
115
  tempData[obj.id] = obj;
116
- const otherBucket = await daemon_1.Daemon.getBucketMetadata(module.daemon, schema.bucket);
117
- tempAdapter = new memory_bucket_adapter_1.MemoryBucketAdapter(otherBucket.schema, tempData);
116
+ const otherMeta = await daemon_1.Daemon.getBucketMetadata(module.daemon, schema.bucket);
117
+ tempAdapter = new memory_bucket_adapter_1.MemoryBucketAdapter(otherMeta.schema, tempData);
118
118
  }
119
119
  // Internal
120
120
  else {
@@ -128,10 +128,10 @@ class BucketGraph {
128
128
  '#and __tenancy__': tenancy
129
129
  };
130
130
  if (otherBucket.adapter instanceof memory_bucket_adapter_1.MemoryBucketAdapter) {
131
- tempAdapter = await trx_1.Trx.getCache(trx, this.bucket) || otherBucket.cache || otherBucket.adapter;
131
+ tempAdapter = await trx_1.Trx.getCache(trx, otherBucket) || otherBucket.cache || otherBucket.adapter;
132
132
  }
133
133
  else {
134
- const adapter = await trx_1.Trx.getCache(trx, this.bucket) || otherBucket.cache || otherBucket.adapter;
134
+ const adapter = await trx_1.Trx.getCache(trx, otherBucket) || otherBucket.cache || otherBucket.adapter;
135
135
  const allLinks = await adapter.query(trx, query, undefined, params, param_templates);
136
136
  const tempData = {};
137
137
  for (const obj of allLinks.data)
@@ -141,25 +141,35 @@ class BucketGraph {
141
141
  }
142
142
  // 2nd Query
143
143
  const links = [];
144
+ const compiled = await tempAdapter._compileQuery(trx, schema.query, {
145
+ module: schema.bucket.module,
146
+ buckets: {
147
+ [schema.bucket.short]: {
148
+ scope: '__graph__',
149
+ nql: (tempAdapter instanceof bucket_cache_1.BucketCache) ? undefined : tempAdapter.nql
150
+ }
151
+ },
152
+ });
144
153
  for (const obj of objs) {
145
- const result = tempAdapter instanceof bucket_cache_1.BucketCache
146
- ? await tempAdapter.query(trx, schema.query, {
154
+ let result;
155
+ if (tempAdapter instanceof bucket_cache_1.BucketCache) {
156
+ result = await tempAdapter._queryCompiled(trx, compiled, {
147
157
  perPage: schema.many ? undefined : 1,
148
- }, [{ ...obj }], undefined)
149
- : await tempAdapter.query(trx, schema.query, {
158
+ }, [{ ...obj }], undefined);
159
+ }
160
+ else {
161
+ result = await tempAdapter._queryCompiled(trx, compiled, {
150
162
  perPage: schema.many ? undefined : 1,
151
163
  }, [{ ...obj }], undefined, undefined, {
152
164
  module: schema.bucket.module,
153
- runners: {
154
- [tempAdapter.getQueryMeta().scope]: tempAdapter.nql
165
+ buckets: {
166
+ [schema.bucket.short]: {
167
+ scope: '__graph__',
168
+ nql: tempAdapter.nql
169
+ }
155
170
  },
156
- metadata: {
157
- ...tempAdapter.getQueryMeta(),
158
- schema: tempAdapter.schema,
159
- tag: schema.bucket,
160
- meta: tempAdapter.config.meta
161
- }
162
171
  });
172
+ }
163
173
  if (schema.many) {
164
174
  links.push(result.data);
165
175
  }
@@ -239,7 +249,7 @@ class BucketGraph {
239
249
  ...schema.query,
240
250
  '#and__tenancy__': tenancy
241
251
  };
242
- const adapter = await trx_1.Trx.getCache(trx, this.bucket) || otherBucket.cache || otherBucket.adapter;
252
+ const adapter = await trx_1.Trx.getCache(trx, otherBucket) || otherBucket.cache || otherBucket.adapter;
243
253
  links = await adapter.query(trx, query, page, params);
244
254
  }
245
255
  return !!links.data.length;