nesoi 3.3.5 → 3.3.7

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 (42) hide show
  1. package/lib/elements/blocks/job/internal/resource_job.builder.js +3 -1
  2. package/lib/elements/blocks/resource/resource.builder.js +2 -3
  3. package/lib/elements/blocks/resource/resource.js +1 -0
  4. package/lib/elements/entities/bucket/adapters/bucket_adapter.d.ts +5 -1
  5. package/lib/elements/entities/bucket/adapters/bucket_adapter.js +6 -2
  6. package/lib/elements/entities/bucket/adapters/memory.nql.d.ts +1 -1
  7. package/lib/elements/entities/bucket/adapters/memory.nql.js +55 -35
  8. package/lib/elements/entities/bucket/bucket.builder.js +1 -1
  9. package/lib/elements/entities/bucket/bucket.d.ts +4 -0
  10. package/lib/elements/entities/bucket/bucket.infer.d.ts +7 -7
  11. package/lib/elements/entities/bucket/bucket.js +14 -9
  12. package/lib/elements/entities/bucket/bucket.schema.d.ts +1 -1
  13. package/lib/elements/entities/bucket/cache/bucket_cache.js +3 -3
  14. package/lib/elements/entities/bucket/graph/bucket_graph.d.ts +13 -3
  15. package/lib/elements/entities/bucket/graph/bucket_graph.infer.d.ts +1 -1
  16. package/lib/elements/entities/bucket/graph/bucket_graph.js +23 -13
  17. package/lib/elements/entities/bucket/graph/bucket_graph_link.builder.d.ts +6 -5
  18. package/lib/elements/entities/bucket/model/bucket_model.convert.js +4 -4
  19. package/lib/elements/entities/bucket/query/nql.schema.d.ts +8 -9
  20. package/lib/elements/entities/bucket/query/nql_compiler.d.ts +1 -1
  21. package/lib/elements/entities/bucket/query/nql_compiler.js +38 -27
  22. package/lib/elements/entities/bucket/query/nql_engine.d.ts +2 -2
  23. package/lib/elements/entities/bucket/query/nql_engine.js +4 -2
  24. package/lib/elements/entities/bucket/view/bucket_view.builder.d.ts +3 -2
  25. package/lib/elements/entities/bucket/view/bucket_view.builder.js +3 -3
  26. package/lib/elements/entities/bucket/view/bucket_view.js +123 -32
  27. package/lib/elements/entities/bucket/view/bucket_view.schema.d.ts +6 -3
  28. package/lib/elements/entities/bucket/view/bucket_view.schema.js +2 -1
  29. package/lib/elements/entities/bucket/view/bucket_view_field.builder.d.ts +25 -24
  30. package/lib/elements/entities/bucket/view/bucket_view_field.builder.js +65 -25
  31. package/lib/engine/app/inline.app.js +6 -0
  32. package/lib/engine/app/native/distributed_node.app.js +6 -0
  33. package/lib/engine/app/service.d.ts +7 -0
  34. package/lib/engine/app/service.js +2 -0
  35. package/lib/engine/transaction/nodes/bucket.trx_node.d.ts +2 -2
  36. package/lib/engine/transaction/nodes/bucket.trx_node.js +6 -4
  37. package/lib/engine/transaction/nodes/bucket_query.trx_node.d.ts +2 -0
  38. package/lib/engine/transaction/nodes/bucket_query.trx_node.js +15 -4
  39. package/lib/engine/transaction/trx_engine.js +1 -1
  40. package/lib/engine/transaction/trx_node.js +3 -3
  41. package/package.json +1 -1
  42. package/tsconfig.build.tsbuildinfo +1 -1
@@ -51,7 +51,9 @@ class ResourceJobBuilder extends block_builder_1.BlockBuilder {
51
51
  input(def) {
52
52
  this._msg.template($ => {
53
53
  const fields = def($);
54
- for (const f in this.implicitFields || []) {
54
+ for (const f in this.implicitFields || {}) {
55
+ if (f in fields)
56
+ continue;
55
57
  const [type, arg, required] = this.implicitFields[f];
56
58
  fields[f] = arg
57
59
  ? $[type](arg)
@@ -42,8 +42,7 @@ class ResourceBuilder extends block_builder_1.BlockBuilder {
42
42
  id: $.string_or_number.optional,
43
43
  perPage: $.int.default(10),
44
44
  page: $.int.default(0),
45
- orderBy: $.string.optional,
46
- orderDesc: $.boolean.default(false)
45
+ sort: $.list($.literal(/.@(asc|desc)/)).optional
47
46
  }))
48
47
  .prepare(resource_job_1.ResourceJob.prepareMsgData);
49
48
  this._inlineNodes.push(new dependency_1.BuilderNode({
@@ -170,7 +169,7 @@ class ResourceBuilder extends block_builder_1.BlockBuilder {
170
169
  const defaultTrigger = (0, bucket_model_convert_1.convertToMessage)(module.name, model, createDep.tag.name, `Create ${node.builder._alias || node.builder.name}`, [], [], ['id']);
171
170
  inlineJobsConfig[createDep.tag.name] = {
172
171
  ResourceJob: {
173
- idType: null,
172
+ idType: undefined,
174
173
  output: { raw: modelName },
175
174
  defaultTrigger
176
175
  }
@@ -76,6 +76,7 @@ class Resource extends block_1.Block {
76
76
  /* Implementations */
77
77
  static view($) {
78
78
  const scope = $.job.scope;
79
+ // TODO: sort
79
80
  return $.msg.id
80
81
  ? $.trx.bucket(scope.bucket).viewOneOrFail($.msg.id, $.msg.view)
81
82
  : $.trx.bucket(scope.bucket).viewAll($.msg.view);
@@ -136,8 +136,12 @@ export declare abstract class BucketAdapter<Obj extends NesoiObj> {
136
136
  };
137
137
  /**
138
138
  * Return the results of a query
139
+ * - `pagination`: Limits the number of results.
140
+ * - `perPage`: If 0, returns no results (useful with config.metadataOnly). If -1, returns all results.
141
+ * - `params`: Objects to be used when filling param values. The query returns objects matching *any* of the param objects.
142
+ * - `param_templates`: Path parameter replacements to be used when filling param_with_$ values. The query returns objects matching *any* of the param objects.
139
143
  */
140
- query<MetadataOnly extends boolean>(trx: AnyTrxNode, query: NQL_AnyQuery, pagination?: NQL_Pagination, params?: Record<string, any>[], config?: {
144
+ query<MetadataOnly extends boolean>(trx: AnyTrxNode, query: NQL_AnyQuery, pagination?: NQL_Pagination, params?: Record<string, any>[], param_templates?: Record<string, string>[], config?: {
141
145
  view?: string;
142
146
  metadataOnly?: MetadataOnly;
143
147
  }, custom?: {
@@ -24,8 +24,12 @@ class BucketAdapter {
24
24
  /* Generic Implementation */
25
25
  /**
26
26
  * Return the results of a query
27
+ * - `pagination`: Limits the number of results.
28
+ * - `perPage`: If 0, returns no results (useful with config.metadataOnly). If -1, returns all results.
29
+ * - `params`: Objects to be used when filling param values. The query returns objects matching *any* of the param objects.
30
+ * - `param_templates`: Path parameter replacements to be used when filling param_with_$ values. The query returns objects matching *any* of the param objects.
27
31
  */
28
- async query(trx, query, pagination, params, config,
32
+ async query(trx, query, pagination, params, param_templates, config,
29
33
  // When running a temporary local memory adapter,
30
34
  // these are required
31
35
  custom) {
@@ -33,7 +37,7 @@ class BucketAdapter {
33
37
  const moduleName = custom?.module || module.name;
34
38
  const compiled = await nql_compiler_1.NQL_Compiler.build(module.daemon, moduleName, this.schema.name, query, custom?.metadata);
35
39
  const view = config?.view ? this.schema.views[config.view] : undefined;
36
- const result = await module.nql.run(trx, compiled, pagination, params, view, custom?.runners);
40
+ const result = await module.nql.run(trx, compiled, pagination, params, param_templates, view, custom?.runners);
37
41
  if (config?.metadataOnly) {
38
42
  result.data = result.data.map(obj => ({
39
43
  id: obj.id,
@@ -10,7 +10,7 @@ export declare class MemoryNQLRunner extends NQLRunner {
10
10
  protected adapter?: AnyMemoryBucketAdapter;
11
11
  constructor();
12
12
  bind(adapter: AnyMemoryBucketAdapter): void;
13
- run(trx: AnyTrxNode, part: NQL_Part, params: Obj[], pagination?: NQL_Pagination): Promise<{
13
+ run(trx: AnyTrxNode, part: NQL_Part, params: Obj[], param_templates: Record<string, string>[], pagination?: NQL_Pagination): Promise<{
14
14
  data: any[];
15
15
  totalItems: number | undefined;
16
16
  page: number | undefined;
@@ -13,7 +13,7 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
13
13
  bind(adapter) {
14
14
  this.adapter = adapter;
15
15
  }
16
- async run(trx, part, params, pagination) {
16
+ async run(trx, part, params, param_templates, pagination) {
17
17
  if (!this.adapter) {
18
18
  throw new Error('No adapter bound to NQL Runner');
19
19
  }
@@ -25,33 +25,35 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
25
25
  }
26
26
  // Non-empty query
27
27
  else {
28
- response = await this.filter(part, data, params);
28
+ response = await this.filter(part, data, params, param_templates);
29
29
  }
30
30
  let output = Object.values(response);
31
- if (part.union.order) {
32
- const by = part.union.order.by.length
33
- ? part.union.order.by
34
- : [this.adapter.config.meta.updated_at];
31
+ if (part.union.sort) {
32
+ const sort = part.union.sort.length
33
+ ? part.union.sort
34
+ : [{ key: this.adapter.config.meta.updated_at, dir: 'desc' }];
35
35
  output.sort((a, b) => {
36
- for (let i = 0; i < by.length; i++) {
37
- const key = by[i];
38
- if (typeof a[key] == 'number') {
39
- if (typeof b[key] !== 'number')
40
- throw new Error(`Cannot compare number and ${typeof b[key]}`);
41
- let d = a[key] - b[key];
36
+ for (let i = 0; i < sort.length; i++) {
37
+ const s = sort[i];
38
+ const a_val = tree_1.Tree.get(a, s.key);
39
+ const b_val = tree_1.Tree.get(b, s.key);
40
+ if (typeof a_val == 'number') {
41
+ if (typeof b_val !== 'number')
42
+ throw new Error(`Cannot compare number and ${typeof b_val}`);
43
+ let d = a_val - b_val;
42
44
  if (d !== 0) {
43
- if (part.union.order.dir[i] === 'desc') {
45
+ if (s.dir === 'desc') {
44
46
  d *= -1;
45
47
  }
46
48
  return d;
47
49
  }
48
50
  }
49
- else if (typeof a[key] == 'string') {
50
- if (typeof b[key] !== 'string')
51
- throw new Error(`Cannot compare string and ${typeof b[key]}`);
52
- let d = a[key].localeCompare(b[key]);
51
+ else if (typeof a_val == 'string') {
52
+ if (typeof b_val !== 'string')
53
+ throw new Error(`Cannot compare string and ${typeof b_val}`);
54
+ let d = a_val.localeCompare(b_val);
53
55
  if (d !== 0) {
54
- if (part.union.order.dir[i] === 'desc') {
56
+ if (s.dir === 'desc') {
55
57
  d *= -1;
56
58
  }
57
59
  return d;
@@ -67,8 +69,8 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
67
69
  totalItems = output.length;
68
70
  }
69
71
  if (pagination.page !== undefined || pagination.perPage !== undefined) {
70
- const a = ((pagination.page || 1) - 1) * (pagination.perPage || 10);
71
- const b = a + (pagination.perPage || 10);
72
+ const a = ((pagination.page || 1) - 1) * (pagination.perPage ?? 10);
73
+ const b = a + (pagination.perPage ?? 10);
72
74
  output = output.slice(a, b);
73
75
  }
74
76
  }
@@ -84,16 +86,16 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
84
86
  * testing objects unnecessarily. Returns a dict of results by id.
85
87
  * @returns A dict of results by id
86
88
  */
87
- filter(part, objs, params) {
89
+ filter(part, objs, params, param_templates) {
88
90
  // Accumulate results from n intersections,
89
91
  // avoiding a re-check of already matched objects.
90
- const _union = (union, objs, params) => {
92
+ const _union = (union, objs, params, param_templates) => {
91
93
  const out = {};
92
94
  const remaining = { ...objs };
93
95
  for (const inter of union.inters) {
94
96
  if (Object.keys(remaining).length === 0)
95
97
  break;
96
- const interOut = _inter(inter, remaining, params);
98
+ const interOut = _inter(inter, remaining, params, param_templates);
97
99
  Object.assign(out, interOut);
98
100
  for (const k in interOut) {
99
101
  delete remaining[k];
@@ -103,7 +105,7 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
103
105
  };
104
106
  // Sieves results from n unions or rules,
105
107
  // avoiding a re-check of already filtered-out objects.
106
- const _inter = (inter, objs, params) => {
108
+ const _inter = (inter, objs, params, param_templates) => {
107
109
  let out = {};
108
110
  const remaining = { ...objs };
109
111
  for (const rule of inter.rules) {
@@ -111,11 +113,11 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
111
113
  break;
112
114
  // <Union>
113
115
  if ('inters' in rule) {
114
- out = _union(rule, remaining, params);
116
+ out = _union(rule, remaining, params, param_templates);
115
117
  }
116
118
  // <Rule>
117
119
  else {
118
- out = _rule(rule, remaining, params);
120
+ out = _rule(rule, remaining, params, param_templates);
119
121
  }
120
122
  for (const k in remaining) {
121
123
  if (!(k in out)) {
@@ -125,13 +127,24 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
125
127
  }
126
128
  return out;
127
129
  };
128
- const _rule = (rule, objs, params) => {
130
+ const _rule = (rule, objs, params, param_templates) => {
129
131
  const out = {};
130
132
  for (const id in objs) {
131
133
  const obj = objs[id];
132
134
  let match = false;
133
- for (const paramGroup of params) {
134
- match = _obj(rule, obj, paramGroup);
135
+ const combos = [];
136
+ for (const param of params) {
137
+ if (param_templates.length) {
138
+ for (const template of param_templates) {
139
+ combos.push({ params: param, param_template: template });
140
+ }
141
+ }
142
+ else {
143
+ combos.push({ params: param, param_template: {} });
144
+ }
145
+ }
146
+ for (const combo of combos) {
147
+ match = _obj(rule, obj, combo.params, combo.param_template);
135
148
  if (match)
136
149
  break;
137
150
  }
@@ -149,7 +162,7 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
149
162
  }
150
163
  return out;
151
164
  };
152
- const _obj = (rule, obj, params) => {
165
+ const _obj = (rule, obj, params, param_template) => {
153
166
  const fieldValue = tree_1.Tree.get(obj, rule.fieldpath);
154
167
  // Value is undefined, only 'present' rule applies
155
168
  if (fieldValue === undefined) {
@@ -161,7 +174,7 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
161
174
  // Fieldpath is a spread, apply rule to each item
162
175
  if (rule.fieldpath.includes('.#')) {
163
176
  for (const item of fieldValue) {
164
- if (_obj(rule, item, params))
177
+ if (_obj(rule, item, params, param_template))
165
178
  return true;
166
179
  }
167
180
  return false;
@@ -169,7 +182,7 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
169
182
  let queryValue;
170
183
  // Value is a subquery, run union
171
184
  if ('subquery' in rule.value) {
172
- const subOut = _union(rule.value.subquery.union, objs, [params]);
185
+ const subOut = _union(rule.value.subquery.union, objs, [params], Object.keys(param_template).length ? [param_template] : []);
173
186
  const subList = Object.values(subOut);
174
187
  // Subquery operator is for a list, filter
175
188
  if (rule.op === 'in' || rule.op === 'contains_any') {
@@ -182,11 +195,18 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
182
195
  }
183
196
  else if ('param' in rule.value) {
184
197
  if (Array.isArray(rule.value.param)) {
185
- queryValue = rule.value.param.map(p => params[p]);
198
+ queryValue = rule.value.param.map(p => tree_1.Tree.get(params, p));
186
199
  }
187
200
  else {
188
- queryValue = params[rule.value.param];
201
+ queryValue = tree_1.Tree.get(params, rule.value.param);
202
+ }
203
+ }
204
+ else if ('param_with_$' in rule.value) {
205
+ let path = rule.value.param_with_$;
206
+ for (const key in param_template) {
207
+ path = path.replace(new RegExp(key.replace('$', '\\$'), 'g'), param_template[key]);
189
208
  }
209
+ queryValue = tree_1.Tree.get(params, path);
190
210
  }
191
211
  else if ('static' in rule.value) {
192
212
  queryValue = rule.value.static;
@@ -278,7 +298,7 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
278
298
  }
279
299
  return false;
280
300
  };
281
- return _union(part.union, objs, params);
301
+ return _union(part.union, objs, params, param_templates);
282
302
  }
283
303
  }
284
304
  exports.MemoryNQLRunner = MemoryNQLRunner;
@@ -98,7 +98,7 @@ class BucketBuilder {
98
98
  Object.assign(views, ext.views);
99
99
  }
100
100
  for (const v in builder._views) {
101
- views[v] = bucket_view_builder_1.BucketViewBuilder.build(builder._views[v], model, graph, views);
101
+ views[v] = bucket_view_builder_1.BucketViewBuilder.build(builder._views[v], model, graph, views, tree);
102
102
  }
103
103
  return views;
104
104
  }
@@ -95,6 +95,7 @@ export declare class Bucket<M extends $Module, $ extends $Bucket> {
95
95
  readLink<LinkName extends keyof $['graph']['links'], Link extends $['graph']['links'][LinkName], LinkBucket extends Link['#bucket'], V extends ViewName<LinkBucket>, Obj extends ViewObj<LinkBucket, V>>(trx: AnyTrxNode, id: $['#data']['id'], link: LinkName, options?: {
96
96
  silent?: boolean;
97
97
  no_tenancy?: boolean;
98
+ index?: string[];
98
99
  }): Promise<Link['#many'] extends true ? Obj[] : (Obj | undefined)>;
99
100
  /**
100
101
  * Read raw entities of a graph link for N objects
@@ -106,6 +107,7 @@ export declare class Bucket<M extends $Module, $ extends $Bucket> {
106
107
  readManyLinks<LinkName extends keyof $['graph']['links'], Link extends $['graph']['links'][LinkName], LinkBucket extends Link['#bucket'], V extends ViewName<LinkBucket>, Obj extends ViewObj<LinkBucket, V>>(trx: AnyTrxNode, ids: $['#data']['id'][], link: LinkName, options?: {
107
108
  silent?: boolean;
108
109
  no_tenancy?: boolean;
110
+ indexes?: string[][];
109
111
  }): Promise<Link['#many'] extends true ? Obj[] : (Obj | undefined)>;
110
112
  /**
111
113
  * Read the view of an entity of a graph link
@@ -117,6 +119,7 @@ export declare class Bucket<M extends $Module, $ extends $Bucket> {
117
119
  viewLink<LinkName extends keyof $['graph']['links'], Link extends $['graph']['links'][LinkName], LinkBucket extends Link['#bucket'], V extends ViewName<LinkBucket>, Obj extends ViewObj<LinkBucket, V>>(trx: AnyTrxNode, id: $['#data']['id'], link: LinkName, view: V, options?: {
118
120
  silent?: boolean;
119
121
  no_tenancy?: boolean;
122
+ index?: string[];
120
123
  }): Promise<Obj | Obj[] | undefined>;
121
124
  /**
122
125
  * Return true if the graph link refers to at least one object
@@ -203,6 +206,7 @@ export declare class Bucket<M extends $Module, $ extends $Bucket> {
203
206
  query<V extends ViewName<$>, Obj extends ViewObj<$, V>>(trx: AnyTrxNode, query: NQL_AnyQuery, pagination?: NQL_Pagination, view?: V, options?: {
204
207
  no_tenancy?: boolean;
205
208
  params?: Record<string, any>[];
209
+ param_templates?: Record<string, any>[];
206
210
  }): Promise<NQL_Result<Obj>>;
207
211
  /**
208
212
  * Add `created_by`, `created_at`, `updated_by` and `updated_at` fields to object
@@ -1,17 +1,17 @@
1
1
  import { $BucketViewField, $BucketViewFields } from './view/bucket_view.schema';
2
2
  import { BucketViewFieldBuilder, BucketViewFieldBuilders } from './view/bucket_view_field.builder';
3
- export type $BucketViewFieldsInfer<Builder extends BucketViewFieldBuilders> = Builder extends (...args: any[]) => $BucketViewFields ? ReturnType<Builder> : {
4
- [K in keyof Builder]: Builder[K] extends BucketViewFieldBuilders ? ($BucketViewField & {
3
+ export type $BucketViewFieldsInfer<Builder extends BucketViewFieldBuilders<any>> = Builder extends (...args: any[]) => $BucketViewFields ? ReturnType<Builder> : {
4
+ [K in keyof Builder]: Builder[K] extends BucketViewFieldBuilders<any> ? ($BucketViewField & {
5
5
  '#data': $BucketViewFieldsInfer<Builder[K]>;
6
- }) : Builder[K] extends BucketViewFieldBuilder<any, any, any> ? $BucketViewField & {
7
- '#data': Builder[K] extends BucketViewFieldBuilder<infer X, any> ? X : never;
6
+ }) : Builder[K] extends BucketViewFieldBuilder<any, any, any, any, any> ? $BucketViewField & {
7
+ '#data': Builder[K] extends BucketViewFieldBuilder<any, any, any, infer X, any> ? X : never;
8
8
  } : never;
9
9
  };
10
- export type $BucketViewDataInfer<Builder extends BucketViewFieldBuilders> = {
11
- [K in keyof Builder]: Builder[K] extends BucketViewFieldBuilders ? $BucketViewDataInfer<Builder[K]> : Builder[K] extends BucketViewFieldBuilder<infer X, any> ? X : never;
10
+ export type $BucketViewDataInfer<Builders extends BucketViewFieldBuilders<any>> = {
11
+ [K in keyof Builders]: Builders[K] extends BucketViewFieldBuilder<any, any, any, infer X, any> ? X : never;
12
12
  };
13
13
  export type $BucketViewFieldBuilderInfer<Data> = {
14
- [K in keyof Data]: BucketViewFieldBuilder<Data[K], any>;
14
+ [K in keyof Data]: BucketViewFieldBuilder<any, any, any, Data[K], any>;
15
15
  };
16
16
  /**
17
17
  * [Fieldpaths]
@@ -84,7 +84,7 @@ class Bucket {
84
84
  const result = await adapter.query(trx, {
85
85
  id,
86
86
  '#and __tenancy__': tenancy
87
- }, { perPage: 1 }, undefined, options?.query_view ? { view: options?.query_view } : undefined);
87
+ }, { perPage: 1 }, undefined, undefined, options?.query_view ? { view: options?.query_view } : undefined);
88
88
  raw = result.data[0];
89
89
  }
90
90
  // Without Tenancy
@@ -190,7 +190,7 @@ class Bucket {
190
190
  return undefined;
191
191
  }
192
192
  // Read link
193
- const linkObj = await this.graph.readLink(trx, obj, link, options);
193
+ const linkObj = await this.graph.readLink(trx, obj, { name: link, index: options?.index || [] }, options);
194
194
  // Encryption
195
195
  if (linkObj) {
196
196
  if (this.schema.model.hasEncryptedField) {
@@ -227,7 +227,7 @@ class Bucket {
227
227
  return undefined;
228
228
  }
229
229
  // Read link
230
- const linkObj = await this.graph.readManyLinks(trx, objs, link, options);
230
+ const linkObj = await this.graph.readManyLinks(trx, objs, { name: link, indexes: options?.indexes || [] }, options);
231
231
  // TODO
232
232
  // // Encryption
233
233
  // if (linkObj) {
@@ -261,7 +261,7 @@ class Bucket {
261
261
  return undefined;
262
262
  }
263
263
  // View link
264
- const linkObj = await this.graph.viewLink(trx, obj, link, view, options);
264
+ const linkObj = await this.graph.viewLink(trx, obj, { name: link, index: options?.index || [] }, view, options);
265
265
  // Encryption
266
266
  if (linkObj && this.schema.model.hasEncryptedField) {
267
267
  if (Array.isArray(linkObj)) {
@@ -430,7 +430,7 @@ class Bucket {
430
430
  const result = await adapter.query(trx, {
431
431
  id: obj.id,
432
432
  '#and __tenancy__': tenancy
433
- }, { perPage: 1 }, undefined, {
433
+ }, { perPage: 1 }, undefined, undefined, {
434
434
  metadataOnly: true
435
435
  });
436
436
  oldObj = result.data[0];
@@ -563,7 +563,7 @@ class Bucket {
563
563
  // Check if object exists
564
564
  result = await this.adapter.query(trx, {
565
565
  id, '#and __tenancy__': tenancy
566
- }, { perPage: 1 }, undefined, {
566
+ }, { perPage: 1 }, undefined, undefined, {
567
567
  metadataOnly: true
568
568
  });
569
569
  if (!result.data.length && !options?.unsafe) {
@@ -598,7 +598,7 @@ class Bucket {
598
598
  const linked = result
599
599
  // If safe, avoid reading the object again inside readLink.
600
600
  // Instead, use graph's readLink which takes the object.
601
- ? await this.graph.readLink(trx, result.data[0], link.name, {
601
+ ? await this.graph.readLink(trx, result.data[0], { name: link.name, index: [] }, {
602
602
  silent: true
603
603
  })
604
604
  // If unsafe, read the link base by id.
@@ -643,7 +643,7 @@ class Bucket {
643
643
  result = await this.adapter.query(trx, {
644
644
  'id in': ids,
645
645
  '#and __tenancy__': tenancy
646
- }, undefined, undefined, {
646
+ }, undefined, undefined, undefined, {
647
647
  metadataOnly: true
648
648
  });
649
649
  ids = result.data.map(obj => obj.id);
@@ -712,9 +712,14 @@ class Bucket {
712
712
  ...query,
713
713
  '#and __tenancy__': tenancy
714
714
  };
715
+ // Pagination
716
+ if (pagination) {
717
+ if (pagination.perPage && pagination.perPage < 0)
718
+ pagination.perPage = undefined;
719
+ }
715
720
  // Query
716
721
  const adapter = this.cache || this.adapter;
717
- const result = await adapter.query(trx, query, pagination, options?.params);
722
+ const result = await adapter.query(trx, query, pagination, options?.params, options?.param_templates);
718
723
  if (!result.data.length)
719
724
  return result;
720
725
  // Encryption
@@ -29,7 +29,7 @@ export declare class $Bucket {
29
29
  optional: boolean;
30
30
  }>;
31
31
  '#modelpath': {};
32
- '#querypath': {};
32
+ '#querypath': Record<never, any>;
33
33
  '#defaults': Record<string, any>;
34
34
  constructor(module: string, name: string, alias: string, model: $BucketModel, graph: $BucketGraph, views: $BucketViews, tenancy?: $BucketTenancy<any, any> | undefined, extendsFrom?: Tag | undefined);
35
35
  }
@@ -90,7 +90,7 @@ class BucketCache {
90
90
  const { action, sync } = await this.syncAll(trx);
91
91
  log_1.Log.debug('bucket', this.bucket.schema.name, `CACHE query.all, ${action}`);
92
92
  const meta = this.innerAdapter.getQueryMeta();
93
- const entries = (await this.innerAdapter.query(trx, query, pagination, params, undefined, {
93
+ const entries = (await this.innerAdapter.query(trx, query, pagination, params, undefined, undefined, {
94
94
  module: this.bucket.schema.module,
95
95
  runners: {
96
96
  [meta.scope]: this.innerAdapter.nql
@@ -180,7 +180,7 @@ class BucketCache {
180
180
  }
181
181
  async syncQuery(trx, query, pagination, params) {
182
182
  // 1. Query id and epoch from outer adapter
183
- const outerMetadata = await this.outerAdapter.query(trx, query, pagination, params, {
183
+ const outerMetadata = await this.outerAdapter.query(trx, query, pagination, params, undefined, {
184
184
  metadataOnly: true
185
185
  });
186
186
  if (!outerMetadata.data.length) {
@@ -190,7 +190,7 @@ class BucketCache {
190
190
  const meta = this.innerAdapter.getQueryMeta();
191
191
  const innerData = await this.innerAdapter.query(trx, {
192
192
  'id in': outerMetadata.data.map(obj => obj.id)
193
- }, undefined, undefined, undefined, {
193
+ }, undefined, undefined, undefined, undefined, {
194
194
  module: this.bucket.schema.module,
195
195
  runners: {
196
196
  [meta.scope]: this.innerAdapter.nql
@@ -18,7 +18,10 @@ export declare class BucketGraph<M extends $Module, $ extends $Bucket> {
18
18
  * - `silent`: If not found, returns undefined instead of raising an exception (default: `false`)
19
19
  * - `no_tenancy`: Don't apply tenancy rules (default: `false`)
20
20
  */
21
- readLink<LinkName extends keyof $['graph']['links'], LinkBucketName extends $['graph']['links'][LinkName]['bucket']['short'], LinkBucket extends M['buckets'][LinkBucketName], Obj = LinkBucket['#data']>(trx: AnyTrxNode, obj: $['#data'], link: LinkName, options?: {
21
+ readLink<LinkName extends keyof $['graph']['links'], LinkBucketName extends $['graph']['links'][LinkName]['bucket']['short'], LinkBucket extends M['buckets'][LinkBucketName], Obj = LinkBucket['#data']>(trx: AnyTrxNode, obj: $['#data'], link: {
22
+ name: LinkName;
23
+ index: string[];
24
+ }, options?: {
22
25
  silent?: boolean;
23
26
  no_tenancy?: boolean;
24
27
  }): Promise<Obj | Obj[] | undefined>;
@@ -29,7 +32,10 @@ export declare class BucketGraph<M extends $Module, $ extends $Bucket> {
29
32
  * - `silent`: If not found, returns undefined instead of raising an exception (default: `false`)
30
33
  * - `no_tenancy`: Don't apply tenancy rules (default: `false`)
31
34
  */
32
- readManyLinks<LinkName extends keyof $['graph']['links'], LinkBucketName extends $['graph']['links'][LinkName]['bucket']['short'], LinkBucket extends M['buckets'][LinkBucketName], Obj = LinkBucket['#data']>(trx: AnyTrxNode, objs: $['#data'][], link: LinkName, options?: {
35
+ readManyLinks<LinkName extends keyof $['graph']['links'], LinkBucketName extends $['graph']['links'][LinkName]['bucket']['short'], LinkBucket extends M['buckets'][LinkBucketName], Obj = LinkBucket['#data']>(trx: AnyTrxNode, objs: $['#data'][], link: {
36
+ name: LinkName;
37
+ indexes: string[][];
38
+ }, options?: {
33
39
  silent?: boolean;
34
40
  no_tenancy?: boolean;
35
41
  }): Promise<Obj[] | Obj[][]>;
@@ -40,9 +46,13 @@ export declare class BucketGraph<M extends $Module, $ extends $Bucket> {
40
46
  * - `silent`: If not found, returns undefined instead of raising an exception (default: `false`)
41
47
  * - `no_tenancy`: Don't apply tenancy rules (default: `false`)
42
48
  */
43
- viewLink<LinkName extends keyof $['graph']['links'], LinkBucketName extends $['graph']['links'][LinkName]['bucket']['short'], LinkBucket extends M['buckets'][LinkBucketName], V extends ViewName<LinkBucket>, Obj extends ViewObj<LinkBucket, V>>(trx: AnyTrxNode, obj: $['#data'], link: LinkName, view: V, options?: {
49
+ viewLink<LinkName extends keyof $['graph']['links'], LinkBucketName extends $['graph']['links'][LinkName]['bucket']['short'], LinkBucket extends M['buckets'][LinkBucketName], V extends ViewName<LinkBucket>, Obj extends ViewObj<LinkBucket, V>>(trx: AnyTrxNode, obj: $['#data'], link: {
50
+ name: LinkName;
51
+ index: string[];
52
+ }, view: V, options?: {
44
53
  silent?: boolean;
45
54
  no_tenancy?: boolean;
55
+ param_templates?: Record<string, any>;
46
56
  }): Promise<Obj | Obj[] | undefined>;
47
57
  /**
48
58
  * Return true if the link resolves to at least one object
@@ -5,7 +5,7 @@ type Replace<T extends string> = T extends `${infer L}$${infer R}` ? `${L}${stri
5
5
  export type $BucketGraphLinksInfer<Builders extends BucketGraphLinkBuilders> = {
6
6
  [K in keyof Builders as Replace<K & string>]: Overlay<$BucketGraphLink, {
7
7
  '#bucket': Builders[K]['#other'];
8
- '#data': Builders[K]['#other']['#data'];
8
+ '#many': Builders[K]['#many'];
9
9
  }>;
10
10
  };
11
11
  export {};