nesoi 3.3.4 → 3.3.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 (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 +1 -1
  3. package/lib/elements/entities/bucket/adapters/bucket_adapter.d.ts +1 -1
  4. package/lib/elements/entities/bucket/adapters/bucket_adapter.js +2 -2
  5. package/lib/elements/entities/bucket/adapters/memory.nql.d.ts +1 -1
  6. package/lib/elements/entities/bucket/adapters/memory.nql.js +33 -15
  7. package/lib/elements/entities/bucket/bucket.builder.js +1 -1
  8. package/lib/elements/entities/bucket/bucket.d.ts +4 -0
  9. package/lib/elements/entities/bucket/bucket.infer.d.ts +7 -7
  10. package/lib/elements/entities/bucket/bucket.js +9 -9
  11. package/lib/elements/entities/bucket/cache/bucket_cache.js +3 -3
  12. package/lib/elements/entities/bucket/graph/bucket_graph.d.ts +13 -3
  13. package/lib/elements/entities/bucket/graph/bucket_graph.infer.d.ts +1 -1
  14. package/lib/elements/entities/bucket/graph/bucket_graph.js +21 -11
  15. package/lib/elements/entities/bucket/graph/bucket_graph_link.builder.d.ts +6 -5
  16. package/lib/elements/entities/bucket/model/bucket_model.convert.js +4 -4
  17. package/lib/elements/entities/bucket/query/nql.schema.d.ts +2 -0
  18. package/lib/elements/entities/bucket/query/nql_compiler.js +6 -1
  19. package/lib/elements/entities/bucket/query/nql_engine.d.ts +2 -2
  20. package/lib/elements/entities/bucket/query/nql_engine.js +2 -2
  21. package/lib/elements/entities/bucket/view/bucket_view.builder.d.ts +3 -2
  22. package/lib/elements/entities/bucket/view/bucket_view.builder.js +3 -3
  23. package/lib/elements/entities/bucket/view/bucket_view.js +123 -32
  24. package/lib/elements/entities/bucket/view/bucket_view.schema.d.ts +6 -3
  25. package/lib/elements/entities/bucket/view/bucket_view.schema.js +2 -1
  26. package/lib/elements/entities/bucket/view/bucket_view_field.builder.d.ts +25 -24
  27. package/lib/elements/entities/bucket/view/bucket_view_field.builder.js +65 -25
  28. package/lib/engine/app/inline.app.js +6 -0
  29. package/lib/engine/app/native/distributed_node.app.js +6 -0
  30. package/lib/engine/app/service.d.ts +7 -0
  31. package/lib/engine/app/service.js +2 -0
  32. package/lib/engine/module.js +1 -0
  33. package/lib/engine/transaction/nodes/bucket.trx_node.d.ts +2 -2
  34. package/lib/engine/transaction/nodes/bucket.trx_node.js +6 -4
  35. package/lib/engine/transaction/nodes/bucket_query.trx_node.d.ts +2 -0
  36. package/lib/engine/transaction/nodes/bucket_query.trx_node.js +15 -4
  37. package/lib/engine/transaction/nodes/job.trx_node.js +1 -1
  38. package/lib/engine/transaction/trx_engine.js +1 -1
  39. package/lib/engine/transaction/trx_node.d.ts +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)
@@ -170,7 +170,7 @@ class ResourceBuilder extends block_builder_1.BlockBuilder {
170
170
  const defaultTrigger = (0, bucket_model_convert_1.convertToMessage)(module.name, model, createDep.tag.name, `Create ${node.builder._alias || node.builder.name}`, [], [], ['id']);
171
171
  inlineJobsConfig[createDep.tag.name] = {
172
172
  ResourceJob: {
173
- idType: null,
173
+ idType: undefined,
174
174
  output: { raw: modelName },
175
175
  defaultTrigger
176
176
  }
@@ -137,7 +137,7 @@ export declare abstract class BucketAdapter<Obj extends NesoiObj> {
137
137
  /**
138
138
  * Return the results of a query
139
139
  */
140
- query<MetadataOnly extends boolean>(trx: AnyTrxNode, query: NQL_AnyQuery, pagination?: NQL_Pagination, params?: Record<string, any>[], config?: {
140
+ query<MetadataOnly extends boolean>(trx: AnyTrxNode, query: NQL_AnyQuery, pagination?: NQL_Pagination, params?: Record<string, any>[], path_params?: Record<string, string>[], config?: {
141
141
  view?: string;
142
142
  metadataOnly?: MetadataOnly;
143
143
  }, custom?: {
@@ -25,7 +25,7 @@ class BucketAdapter {
25
25
  /**
26
26
  * Return the results of a query
27
27
  */
28
- async query(trx, query, pagination, params, config,
28
+ async query(trx, query, pagination, params, path_params, config,
29
29
  // When running a temporary local memory adapter,
30
30
  // these are required
31
31
  custom) {
@@ -33,7 +33,7 @@ class BucketAdapter {
33
33
  const moduleName = custom?.module || module.name;
34
34
  const compiled = await nql_compiler_1.NQL_Compiler.build(module.daemon, moduleName, this.schema.name, query, custom?.metadata);
35
35
  const view = config?.view ? this.schema.views[config.view] : undefined;
36
- const result = await module.nql.run(trx, compiled, pagination, params, view, custom?.runners);
36
+ const result = await module.nql.run(trx, compiled, pagination, params, path_params, view, custom?.runners);
37
37
  if (config?.metadataOnly) {
38
38
  result.data = result.data.map(obj => ({
39
39
  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[], path_params: Obj[], 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, path_params, pagination) {
17
17
  if (!this.adapter) {
18
18
  throw new Error('No adapter bound to NQL Runner');
19
19
  }
@@ -25,7 +25,7 @@ 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, path_params);
29
29
  }
30
30
  let output = Object.values(response);
31
31
  if (part.union.order) {
@@ -84,16 +84,16 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
84
84
  * testing objects unnecessarily. Returns a dict of results by id.
85
85
  * @returns A dict of results by id
86
86
  */
87
- filter(part, objs, params) {
87
+ filter(part, objs, params, path_params) {
88
88
  // Accumulate results from n intersections,
89
89
  // avoiding a re-check of already matched objects.
90
- const _union = (union, objs, params) => {
90
+ const _union = (union, objs, params, path_params) => {
91
91
  const out = {};
92
92
  const remaining = { ...objs };
93
93
  for (const inter of union.inters) {
94
94
  if (Object.keys(remaining).length === 0)
95
95
  break;
96
- const interOut = _inter(inter, remaining, params);
96
+ const interOut = _inter(inter, remaining, params, path_params);
97
97
  Object.assign(out, interOut);
98
98
  for (const k in interOut) {
99
99
  delete remaining[k];
@@ -103,7 +103,7 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
103
103
  };
104
104
  // Sieves results from n unions or rules,
105
105
  // avoiding a re-check of already filtered-out objects.
106
- const _inter = (inter, objs, params) => {
106
+ const _inter = (inter, objs, params, path_params) => {
107
107
  let out = {};
108
108
  const remaining = { ...objs };
109
109
  for (const rule of inter.rules) {
@@ -111,11 +111,11 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
111
111
  break;
112
112
  // <Union>
113
113
  if ('inters' in rule) {
114
- out = _union(rule, remaining, params);
114
+ out = _union(rule, remaining, params, path_params);
115
115
  }
116
116
  // <Rule>
117
117
  else {
118
- out = _rule(rule, remaining, params);
118
+ out = _rule(rule, remaining, params, path_params);
119
119
  }
120
120
  for (const k in remaining) {
121
121
  if (!(k in out)) {
@@ -125,13 +125,24 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
125
125
  }
126
126
  return out;
127
127
  };
128
- const _rule = (rule, objs, params) => {
128
+ const _rule = (rule, objs, params, path_params) => {
129
129
  const out = {};
130
130
  for (const id in objs) {
131
131
  const obj = objs[id];
132
132
  let match = false;
133
- for (const paramGroup of params) {
134
- match = _obj(rule, obj, paramGroup);
133
+ const combos = [];
134
+ for (const param of params) {
135
+ if (path_params.length) {
136
+ for (const path_param of path_params) {
137
+ combos.push({ params: param, path_params: path_param });
138
+ }
139
+ }
140
+ else {
141
+ combos.push({ params: param, path_params: {} });
142
+ }
143
+ }
144
+ for (const combo of combos) {
145
+ match = _obj(rule, obj, combo.params, combo.path_params);
135
146
  if (match)
136
147
  break;
137
148
  }
@@ -149,7 +160,7 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
149
160
  }
150
161
  return out;
151
162
  };
152
- const _obj = (rule, obj, params) => {
163
+ const _obj = (rule, obj, params, path_params) => {
153
164
  const fieldValue = tree_1.Tree.get(obj, rule.fieldpath);
154
165
  // Value is undefined, only 'present' rule applies
155
166
  if (fieldValue === undefined) {
@@ -161,7 +172,7 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
161
172
  // Fieldpath is a spread, apply rule to each item
162
173
  if (rule.fieldpath.includes('.#')) {
163
174
  for (const item of fieldValue) {
164
- if (_obj(rule, item, params))
175
+ if (_obj(rule, item, params, path_params))
165
176
  return true;
166
177
  }
167
178
  return false;
@@ -169,7 +180,7 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
169
180
  let queryValue;
170
181
  // Value is a subquery, run union
171
182
  if ('subquery' in rule.value) {
172
- const subOut = _union(rule.value.subquery.union, objs, [params]);
183
+ const subOut = _union(rule.value.subquery.union, objs, [params], Object.keys(path_params).length ? [path_params] : []);
173
184
  const subList = Object.values(subOut);
174
185
  // Subquery operator is for a list, filter
175
186
  if (rule.op === 'in' || rule.op === 'contains_any') {
@@ -188,6 +199,13 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
188
199
  queryValue = params[rule.value.param];
189
200
  }
190
201
  }
202
+ else if ('path_param' in rule.value) {
203
+ let path = rule.value.path_param;
204
+ for (const key in path_params) {
205
+ path = path.replace(new RegExp(key, 'g'), path_params[key]);
206
+ }
207
+ queryValue = tree_1.Tree.get(params, path);
208
+ }
191
209
  else if ('static' in rule.value) {
192
210
  queryValue = rule.value.static;
193
211
  }
@@ -278,7 +296,7 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
278
296
  }
279
297
  return false;
280
298
  };
281
- return _union(part.union, objs, params);
299
+ return _union(part.union, objs, params, path_params);
282
300
  }
283
301
  }
284
302
  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
+ path_params?: 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);
@@ -714,7 +714,7 @@ class Bucket {
714
714
  };
715
715
  // Query
716
716
  const adapter = this.cache || this.adapter;
717
- const result = await adapter.query(trx, query, pagination, options?.params);
717
+ const result = await adapter.query(trx, query, pagination, options?.params, options?.path_params);
718
718
  if (!result.data.length)
719
719
  return result;
720
720
  // Encryption
@@ -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
+ path_params?: 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 {};
@@ -26,8 +26,8 @@ class BucketGraph {
26
26
  * - `no_tenancy`: Don't apply tenancy rules (default: `false`)
27
27
  */
28
28
  async readLink(trx, obj, link, options) {
29
- log_1.Log.trace('bucket', this.bucketName, `Read link ${link}`);
30
- const schema = this.schema.links[link];
29
+ log_1.Log.trace('bucket', this.bucketName, `Read link ${link.name}`);
30
+ const schema = this.schema.links[link.name];
31
31
  // Make tenancy query
32
32
  const tenancy = (options?.no_tenancy)
33
33
  ? undefined
@@ -38,23 +38,29 @@ class BucketGraph {
38
38
  ...schema.query,
39
39
  '#and __tenancy__': tenancy
40
40
  };
41
- const params = [{ ...obj }];
42
41
  const page = {
43
42
  perPage: schema.many ? undefined : 1,
44
43
  };
44
+ // Params
45
+ const params = [{ ...obj }];
46
+ const path_params = link.index.length
47
+ ? Object.fromEntries(link.index
48
+ .map((s, i) => [`$${i}`, s]))
49
+ : undefined;
45
50
  // External
46
51
  let links;
47
52
  if (schema.bucket.module !== module.name) {
48
53
  links = await trx.bucket(schema.bucket.short)
49
54
  .query(query)
50
55
  .params(params)
56
+ .path_params(path_params)
51
57
  .page(page);
52
58
  }
53
59
  // Internal
54
60
  else {
55
61
  const otherBucket = dependency_1.Tag.element(schema.bucket, trx);
56
62
  const adapter = otherBucket.cache || otherBucket.adapter;
57
- links = await adapter.query(trx, query, page, params);
63
+ links = await adapter.query(trx, query, page, params, path_params ? [path_params] : undefined);
58
64
  }
59
65
  // Empty response
60
66
  if (!schema.many && !schema.optional && !links.data.length) {
@@ -65,7 +71,7 @@ class BucketGraph {
65
71
  else {
66
72
  throw error_1.NesoiError.Bucket.Graph.RequiredLinkNotFound({
67
73
  bucket: this.bucketName,
68
- link: link,
74
+ link: link.name,
69
75
  id: obj.id
70
76
  });
71
77
  }
@@ -85,8 +91,8 @@ class BucketGraph {
85
91
  * - `no_tenancy`: Don't apply tenancy rules (default: `false`)
86
92
  */
87
93
  async readManyLinks(trx, objs, link, options) {
88
- log_1.Log.trace('bucket', this.bucketName, `Read link ${link}`);
89
- const schema = this.schema.links[link];
94
+ log_1.Log.trace('bucket', this.bucketName, `Read link ${link.name}`);
95
+ const schema = this.schema.links[link.name];
90
96
  // Make tenancy query
91
97
  const tenancy = (options?.no_tenancy)
92
98
  ? undefined
@@ -98,12 +104,16 @@ class BucketGraph {
98
104
  '#and __tenancy__': tenancy
99
105
  };
100
106
  const params = objs.map(obj => ({ ...obj }));
107
+ const path_params = link.indexes.length
108
+ ? link.indexes.map(index => Object.fromEntries(index
109
+ .map((s, i) => [`$${i}`, s]))) : undefined;
101
110
  let tempAdapter;
102
111
  // External
103
112
  if (schema.bucket.module !== module.name) {
104
113
  const allLinks = await trx.bucket(schema.bucket.short)
105
114
  .query(query)
106
115
  .params(params)
116
+ .path_params(path_params)
107
117
  .all();
108
118
  const tempData = {};
109
119
  for (const obj of allLinks)
@@ -119,7 +129,7 @@ class BucketGraph {
119
129
  }
120
130
  else {
121
131
  const adapter = otherBucket.cache || otherBucket.adapter;
122
- const allLinks = await adapter.query(trx, query, undefined, params);
132
+ const allLinks = await adapter.query(trx, query, undefined, params, path_params);
123
133
  const tempData = {};
124
134
  for (const obj of allLinks.data)
125
135
  tempData[obj.id] = obj;
@@ -135,7 +145,7 @@ class BucketGraph {
135
145
  }, [{ ...obj }], undefined)
136
146
  : await tempAdapter.query(trx, schema.query, {
137
147
  perPage: schema.many ? undefined : 1,
138
- }, [{ ...obj }], undefined, {
148
+ }, [{ ...obj }], undefined, undefined, {
139
149
  module: schema.bucket.module,
140
150
  runners: {
141
151
  [tempAdapter.getQueryMeta().scope]: tempAdapter.nql
@@ -165,8 +175,8 @@ class BucketGraph {
165
175
  * - `no_tenancy`: Don't apply tenancy rules (default: `false`)
166
176
  */
167
177
  async viewLink(trx, obj, link, view, options) {
168
- log_1.Log.trace('bucket', this.bucketName, `Read link ${link}`);
169
- const schema = this.schema.links[link];
178
+ log_1.Log.trace('bucket', this.bucketName, `Read link ${link.name}`);
179
+ const schema = this.schema.links[link.name];
170
180
  const links = await this.readLink(trx, obj, link, options);
171
181
  if (!links)
172
182
  return undefined;
@@ -15,27 +15,28 @@ export declare class BucketGraphLinkFactory<Module extends $Module, SelfBucket e
15
15
  constructor(module: string);
16
16
  as(alias: string): this;
17
17
  get compose(): typeof this;
18
- one<N extends keyof Module['buckets'], Bucket extends $Bucket = Module['buckets'][N]>(bucket: N, query: NQL_Query<Module, Bucket, Fieldpaths>): BucketGraphLinkBuilder<Module, SelfBucket, Module["buckets"][N]>;
19
- many<N extends keyof Module['buckets'], Bucket extends $Bucket = Module['buckets'][N]>(bucket: N, query: NQL_Query<Module, Bucket, Fieldpaths>): BucketGraphLinkBuilder<Module, SelfBucket, Module["buckets"][N]>;
18
+ one<N extends keyof Module['buckets'], Bucket extends $Bucket = Module['buckets'][N]>(bucket: N, query: NQL_Query<Module, Bucket, Fieldpaths>): BucketGraphLinkBuilder<Module, SelfBucket, Module["buckets"][N], false>;
19
+ many<N extends keyof Module['buckets'], Bucket extends $Bucket = Module['buckets'][N]>(bucket: N, query: NQL_Query<Module, Bucket, Fieldpaths>): BucketGraphLinkBuilder<Module, SelfBucket, Module["buckets"][N], true>;
20
20
  }
21
21
  /**
22
22
  * @category Builders
23
23
  * @subcategory Entity
24
24
  * */
25
- export declare class BucketGraphLinkBuilder<Module extends $Module, SelfBucket extends $Bucket, OtherBucket extends $Bucket> {
25
+ export declare class BucketGraphLinkBuilder<Module extends $Module, SelfBucket extends $Bucket, OtherBucket extends $Bucket, Many extends boolean> {
26
26
  private bucket;
27
27
  private rel;
28
28
  private query;
29
29
  private many;
30
30
  private alias?;
31
31
  '#other': OtherBucket;
32
+ '#many': Many;
32
33
  private _optional;
33
34
  constructor(bucket: Dependency, rel: 'aggregation' | 'composition', query: NQL_AnyQuery, many: boolean, alias?: string | undefined);
34
35
  as(alias: string): this;
35
36
  get optional(): this;
36
- static build(node: BucketBuilderNode, builder: BucketGraphLinkBuilder<any, any, any>, name: string): $BucketGraphLink;
37
+ static build(node: BucketBuilderNode, builder: BucketGraphLinkBuilder<any, any, any, any>, name: string): $BucketGraphLink;
37
38
  static inferKeyOwner(query: NQL_AnyQuery): "self";
38
39
  }
39
40
  export type BucketGraphLinkBuilders = {
40
- [x: string]: BucketGraphLinkBuilder<any, any, any>;
41
+ [x: string]: BucketGraphLinkBuilder<any, any, any, any>;
41
42
  };
@@ -18,7 +18,7 @@ function convertToView(model, name, fields = model.fields, path, depth = 0) {
18
18
  const viewFields = {};
19
19
  for (const f in fields) {
20
20
  const field = fields[f];
21
- const $ = new bucket_view_field_builder_1.BucketViewFieldFactory(view);
21
+ const $ = new bucket_view_field_builder_1.BucketViewFieldFactory();
22
22
  const key = (path ? path + '.' : '')
23
23
  + field.name;
24
24
  const builder = $.model(key);
@@ -38,9 +38,9 @@ function convertToMessage(module, model, name, alias, include = [], exclude = []
38
38
  const convertField = (field) => {
39
39
  return new message_template_schema_1.$MessageTemplateField(field.type, field.name, field.alias, field.path, field.path, optional.includes(field.path) ? false : field.required, undefined, false, [], {
40
40
  enum: field.meta?.enum
41
- }, field.children ? convertFields(field.children, include, exclude, optional) : undefined);
41
+ }, field.children ? convertFields(field.children) : undefined);
42
42
  };
43
- const convertFields = (fields, include = [], exclude = [], optional = [], root = '') => {
43
+ const convertFields = (fields) => {
44
44
  const msgFields = {};
45
45
  for (const f in fields) {
46
46
  const field = fields[f];
@@ -52,7 +52,7 @@ function convertToMessage(module, model, name, alias, include = [], exclude = []
52
52
  }
53
53
  return msgFields;
54
54
  };
55
- const msgFields = convertFields(model.fields, include, exclude);
55
+ const msgFields = convertFields(model.fields);
56
56
  const template = new message_template_schema_1.$MessageTemplate(msgFields);
57
57
  return new message_schema_1.$Message(module, name, alias, template);
58
58
  }
@@ -32,6 +32,8 @@ export type NQL_Rule = {
32
32
  static: any | any[];
33
33
  } | {
34
34
  param: string | string[];
35
+ } | {
36
+ path_param: string;
35
37
  } | {
36
38
  subquery: {
37
39
  bucket: $Bucket;
@@ -233,6 +233,10 @@ class NQL_RuleTree {
233
233
  if ('.' in value) {
234
234
  return { param: value['.'] };
235
235
  }
236
+ // Path Parameter
237
+ else if ('$' in value) {
238
+ return { path_param: value['$'] };
239
+ }
236
240
  // Sub-Query
237
241
  return { subquery: await this.parseSubQuery(value, parsedKey, meta, select) };
238
242
  }
@@ -459,7 +463,8 @@ class NQL_RuleTree {
459
463
  + `@${node.meta.schema?.name}.${node.fieldpath}${node.not ? ' not' : ''} ${node.case_i ? '~' : ''}${node.op}`
460
464
  + (('static' in node.value) ? ` ${node.value.static}`
461
465
  : ('param' in node.value) ? ` ->${node.value.param}`
462
- : ' ▼ ' + (0, string_1.colored)('(' + node.value.subquery.bucket.name + '.' + node.value.subquery.select + ')', 'brown'))
466
+ : ('path_param' in node.value) ? ` ->>${node.value.path_param}`
467
+ : ' ▼ ' + (0, string_1.colored)('(' + node.value.subquery.bucket.name + '.' + node.value.subquery.select + ')', 'brown'))
463
468
  + '\n';
464
469
  if ('subquery' in node.value) {
465
470
  str += this.describe(node.value['subquery'].union, d + 1);
@@ -15,7 +15,7 @@ export type NQL_Result<T = Obj> = {
15
15
  * @category NQL
16
16
  * */
17
17
  export declare abstract class NQLRunner {
18
- abstract run(trx: AnyTrxNode, part: NQL_Part, params: Record<string, any>[], pagination?: NQL_Pagination, view?: $BucketView): Promise<NQL_Result>;
18
+ abstract run(trx: AnyTrxNode, part: NQL_Part, params: Record<string, any>[], path_params: Record<string, any>[], pagination?: NQL_Pagination, view?: $BucketView): Promise<NQL_Result>;
19
19
  }
20
20
  /**
21
21
  * @category NQL
@@ -24,7 +24,7 @@ export declare class NQL_Engine {
24
24
  private module;
25
25
  private runners;
26
26
  constructor(module: AnyModule);
27
- run(trx: AnyTrxNode, query: NQL_CompiledQuery, pagination?: NQL_Pagination, params?: Record<string, any>[], view?: $BucketView, customRunners?: Record<string, NQLRunner>): Promise<NQL_Result>;
27
+ run(trx: AnyTrxNode, query: NQL_CompiledQuery, pagination?: NQL_Pagination, params?: Record<string, any>[], path_params?: Record<string, any>[], view?: $BucketView, customRunners?: Record<string, NQLRunner>): Promise<NQL_Result>;
28
28
  linkExternal(bucket: AnyBucket): void;
29
29
  }
30
30
  export {};