nesoi 3.2.1 → 3.2.2

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 (28) hide show
  1. package/lib/elements/blocks/job/internal/resource_job.js +1 -1
  2. package/lib/elements/blocks/resource/resource.builder.js +1 -1
  3. package/lib/elements/blocks/resource/resource.js +1 -0
  4. package/lib/elements/entities/bucket/adapters/bucket_adapter.d.ts +2 -2
  5. package/lib/elements/entities/bucket/adapters/bucket_adapter.js +2 -2
  6. package/lib/elements/entities/bucket/adapters/memory.nql.d.ts +1 -1
  7. package/lib/elements/entities/bucket/adapters/memory.nql.js +9 -5
  8. package/lib/elements/entities/bucket/bucket.d.ts +13 -2
  9. package/lib/elements/entities/bucket/bucket.js +40 -2
  10. package/lib/elements/entities/bucket/graph/bucket_graph.d.ts +11 -0
  11. package/lib/elements/entities/bucket/graph/bucket_graph.js +49 -2
  12. package/lib/elements/entities/bucket/model/bucket_model.schema.js +14 -11
  13. package/lib/elements/entities/bucket/query/nql_engine.d.ts +2 -2
  14. package/lib/elements/entities/bucket/query/nql_engine.js +8 -4
  15. package/lib/elements/entities/bucket/view/bucket_view.js +65 -12
  16. package/lib/engine/transaction/nodes/bucket.trx_node.d.ts +5 -0
  17. package/lib/engine/transaction/nodes/bucket.trx_node.js +10 -0
  18. package/lib/engine/transaction/nodes/bucket_query.trx_node.d.ts +2 -0
  19. package/lib/engine/transaction/nodes/bucket_query.trx_node.js +15 -4
  20. package/lib/engine/util/log.d.ts +1 -1
  21. package/lib/engine/util/log.js +1 -0
  22. package/package.json +1 -1
  23. package/tools/joaquin/bucket.d.ts +23 -3
  24. package/tools/joaquin/bucket.js +48 -20
  25. package/tools/joaquin/job.js +4 -4
  26. package/tsconfig.build.tsbuildinfo +1 -1
  27. /package/lib/engine/apps/distributed/inc/{test.d.ts → sandbox.d.ts} +0 -0
  28. /package/lib/engine/apps/distributed/inc/{test.js → sandbox.js} +0 -0
@@ -30,7 +30,7 @@ class ResourceJob {
30
30
  obj = await scope.execMethod({ ...$, obj, bucket: scope.bucket });
31
31
  }
32
32
  if (scope.afterMethod) {
33
- obj = await scope.afterMethod({ ...$, obj, bucket: scope.bucket });
33
+ await scope.afterMethod({ ...$, obj, bucket: scope.bucket });
34
34
  }
35
35
  return obj;
36
36
  }
@@ -63,7 +63,7 @@ class ResourceBuilder extends block_builder_1.BlockBuilder {
63
63
  const jobBuilder = new resource_job_builder_1.ResourceJobBuilder(this.module, name, this._bucket.refName, 'query', alias, resource_1.Resource.query, this._authn)
64
64
  .input($ => ({
65
65
  view: $.enum(views).default(views[0]),
66
- query: $.dict($.any).default({}),
66
+ query: $.dict($.any.optional).default({}),
67
67
  page: $.int.default(0),
68
68
  perPage: $.int.default(10)
69
69
  }))
@@ -120,6 +120,7 @@ class Resource extends block_1.Block {
120
120
  if (type === 'query is empty') {
121
121
  out = !(await trx.bucket(bucket.refName)
122
122
  .query(arg)
123
+ .params(obj)
123
124
  .first());
124
125
  }
125
126
  else if (type === 'has no link') {
@@ -136,10 +136,10 @@ export declare abstract class BucketAdapter<Obj extends NesoiObj> {
136
136
  /**
137
137
  * Return the results of a query
138
138
  */
139
- query<MetadataOnly extends boolean>(trx: AnyTrxNode, query: NQL_AnyQuery, pagination?: NQL_Pagination, params?: Record<string, any>, config?: {
139
+ query<MetadataOnly extends boolean>(trx: AnyTrxNode, query: NQL_AnyQuery, pagination?: NQL_Pagination, params?: Record<string, any>[], config?: {
140
140
  view?: string;
141
141
  metadataOnly?: MetadataOnly;
142
- }): Promise<NQL_Result<MetadataOnly extends true ? {
142
+ }, runner?: NQLRunner): Promise<NQL_Result<MetadataOnly extends true ? {
143
143
  id: Obj['id'];
144
144
  [x: string]: any;
145
145
  } : Obj>>;
@@ -25,14 +25,14 @@ 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, config, runner) {
29
29
  const module = trx_node_1.TrxNode.getModule(trx);
30
30
  const refName = (module.name === this.schema.module
31
31
  ? '' : `${this.schema.module}::`)
32
32
  + this.schema.name;
33
33
  const compiled = await nql_compiler_1.NQL_Compiler.build(module, refName, query);
34
34
  const view = config?.view ? this.schema.views[config.view] : undefined;
35
- const result = await module.nql.run(trx, compiled, pagination, params, view);
35
+ const result = await module.nql.run(trx, compiled, pagination, params, view, runner);
36
36
  if (config?.metadataOnly) {
37
37
  result.data = result.data.map(obj => ({
38
38
  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[], pagination?: NQL_Pagination): Promise<{
14
14
  data: any[];
15
15
  totalItems: number | undefined;
16
16
  page: number | undefined;
@@ -21,7 +21,7 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
21
21
  let response;
22
22
  // Empty query, don't filter data
23
23
  if (part.union.inters.length === 0) {
24
- response = data;
24
+ response = { ...data };
25
25
  }
26
26
  // Non-empty query
27
27
  else {
@@ -105,7 +105,7 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
105
105
  for (const rule of inter.rules) {
106
106
  // <Union>
107
107
  if ('inters' in rule) {
108
- if (!_union(rule, objs, objs))
108
+ if (!_union(rule, objs, params))
109
109
  return false;
110
110
  }
111
111
  // <Rule>
@@ -132,8 +132,12 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
132
132
  continue;
133
133
  }
134
134
  const obj = objs[id];
135
- let match = _obj(rule, obj, params);
136
- // console.log(` -> match: ${match}\n`)
135
+ let match = false;
136
+ for (const paramGroup of params) {
137
+ match = _obj(rule, obj, paramGroup);
138
+ if (match)
139
+ break;
140
+ }
137
141
  if (rule.not) {
138
142
  match = !match;
139
143
  }
@@ -174,7 +178,7 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
174
178
  let queryValue;
175
179
  // Value is a subquery, run union
176
180
  if ('subquery' in rule.value) {
177
- const subOut = _union(rule.value.subquery.union, objs, params);
181
+ const subOut = _union(rule.value.subquery.union, objs, [params]);
178
182
  const subList = Object.values(subOut);
179
183
  // Subquery operator is for a list, filter
180
184
  if (rule.op === 'in' || rule.op === 'contains_any') {
@@ -85,7 +85,7 @@ export declare class Bucket<M extends $Module, $ extends $Bucket> {
85
85
  no_tenancy: boolean;
86
86
  }): Promise<Obj[]>;
87
87
  /**
88
- * Read raw entity of a graph link
88
+ * Read raw entity of a graph link for 1 object
89
89
  *
90
90
  * - Options:
91
91
  * - `silent`: If not found, return `undefined` instead of throwing an exception
@@ -95,6 +95,17 @@ export declare class Bucket<M extends $Module, $ extends $Bucket> {
95
95
  silent?: boolean;
96
96
  no_tenancy?: boolean;
97
97
  }): Promise<Link['#many'] extends true ? Obj[] : (Obj | undefined)>;
98
+ /**
99
+ * Read raw entities of a graph link for N objects
100
+ *
101
+ * - Options:
102
+ * - `silent`: If not found, return `undefined` instead of throwing an exception
103
+ * - `no_tenancy`: Don't apply tenancy rules.
104
+ */
105
+ 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?: {
106
+ silent?: boolean;
107
+ no_tenancy?: boolean;
108
+ }): Promise<Link['#many'] extends true ? Obj[] : (Obj | undefined)>;
98
109
  /**
99
110
  * Read the view of an entity of a graph link
100
111
  *
@@ -190,7 +201,7 @@ export declare class Bucket<M extends $Module, $ extends $Bucket> {
190
201
  */
191
202
  query<V extends ViewName<$>, Obj extends ViewObj<$, V>>(trx: AnyTrxNode, query: NQL_AnyQuery, pagination?: NQL_Pagination, view?: V, options?: {
192
203
  no_tenancy?: boolean;
193
- params?: Record<string, any>;
204
+ params?: Record<string, any>[];
194
205
  }): Promise<NQL_Result<Obj>>;
195
206
  /**
196
207
  * Add `created_by`, `created_at`, `updated_by` and `updated_at` fields to object
@@ -120,7 +120,7 @@ class Bucket {
120
120
  let raws;
121
121
  // With Tenancy
122
122
  if (tenancy) {
123
- const result = await this.adapter.query(trx, tenancy, undefined, options?.query_view ? { view: options?.query_view } : undefined);
123
+ const result = await this.adapter.query(trx, tenancy, undefined, options?.query_view ? [{ view: options?.query_view }] : undefined);
124
124
  raws = result.data;
125
125
  }
126
126
  // Without Tenancy
@@ -169,7 +169,7 @@ class Bucket {
169
169
  }
170
170
  // Graph
171
171
  /**
172
- * Read raw entity of a graph link
172
+ * Read raw entity of a graph link for 1 object
173
173
  *
174
174
  * - Options:
175
175
  * - `silent`: If not found, return `undefined` instead of throwing an exception
@@ -201,6 +201,44 @@ class Bucket {
201
201
  }
202
202
  return linkObj;
203
203
  }
204
+ /**
205
+ * Read raw entities of a graph link for N objects
206
+ *
207
+ * - Options:
208
+ * - `silent`: If not found, return `undefined` instead of throwing an exception
209
+ * - `no_tenancy`: Don't apply tenancy rules.
210
+ */
211
+ async readManyLinks(trx, ids, link, options) {
212
+ log_1.Log.debug('bucket', this.schema.name, `Read Link, ids=${ids} l=${link}`);
213
+ // Validate IDs
214
+ for (const id of ids) {
215
+ if (typeof id !== 'string' && typeof id !== 'number') {
216
+ throw error_1.NesoiError.Bucket.InvalidId({ bucket: this.schema.alias, id });
217
+ }
218
+ }
219
+ // Read object
220
+ const objs = await this.query(trx, {
221
+ 'id in': ids
222
+ }).then(res => res.data);
223
+ // Empty response
224
+ if (!objs.length) {
225
+ const schema = this.schema.graph.links[link];
226
+ if (schema.many) {
227
+ return [];
228
+ }
229
+ return undefined;
230
+ }
231
+ // Read link
232
+ const linkObj = await this.graph.readManyLinks(trx, objs, link, options);
233
+ // TODO
234
+ // // Encryption
235
+ // if (linkObj) {
236
+ // if (this.schema.model.hasEncryptedField) {
237
+ // await this.decrypt(trx, linkObj);
238
+ // }
239
+ // }
240
+ return linkObj;
241
+ }
204
242
  /**
205
243
  * Read the view of an entity of a graph link
206
244
  *
@@ -22,6 +22,17 @@ export declare class BucketGraph<M extends $Module, $ extends $Bucket> {
22
22
  silent?: boolean;
23
23
  no_tenancy?: boolean;
24
24
  }): Promise<Obj | Obj[] | undefined>;
25
+ /**
26
+ * Read the data from a link
27
+ *
28
+ * - Options
29
+ * - `silent`: If not found, returns undefined instead of raising an exception (default: `false`)
30
+ * - `no_tenancy`: Don't apply tenancy rules (default: `false`)
31
+ */
32
+ readManyLinks<LinkName extends keyof $['graph']['links'], LinkBucketName extends $['graph']['links'][LinkName]['bucket']['refName'], LinkBucket extends M['buckets'][LinkBucketName], Obj = LinkBucket['#data']>(trx: AnyTrxNode, objs: $['#data'][], link: LinkName, options?: {
33
+ silent?: boolean;
34
+ no_tenancy?: boolean;
35
+ }): Promise<Obj[] | Obj[][]>;
25
36
  /**
26
37
  * Read the data from a link and build it with a given view
27
38
  *
@@ -4,6 +4,7 @@ exports.BucketGraph = void 0;
4
4
  const trx_node_1 = require("../../../../engine/transaction/trx_node");
5
5
  const log_1 = require("../../../../engine/util/log");
6
6
  const error_1 = require("../../../../engine/data/error");
7
+ const memory_bucket_adapter_1 = require("../adapters/memory.bucket_adapter");
7
8
  /**
8
9
  * @category Elements
9
10
  * @subcategory Entity
@@ -35,7 +36,7 @@ class BucketGraph {
35
36
  '#and': tenancy
36
37
  }, {
37
38
  perPage: schema.many ? undefined : 1,
38
- }, { ...obj });
39
+ }, [{ ...obj }]);
39
40
  // Empty response
40
41
  if (!schema.many && !schema.optional && !links.data.length) {
41
42
  // silent = undefined
@@ -57,6 +58,52 @@ class BucketGraph {
57
58
  return links.data[0];
58
59
  }
59
60
  }
61
+ /**
62
+ * Read the data from a link
63
+ *
64
+ * - Options
65
+ * - `silent`: If not found, returns undefined instead of raising an exception (default: `false`)
66
+ * - `no_tenancy`: Don't apply tenancy rules (default: `false`)
67
+ */
68
+ async readManyLinks(trx, objs, link, options) {
69
+ log_1.Log.trace('bucket', this.bucketName, `Read link ${link}`);
70
+ const schema = this.schema.links[link];
71
+ // Make tenancy query
72
+ const tenancy = (options?.no_tenancy)
73
+ ? undefined
74
+ : this.bucket.getTenancyQuery(trx);
75
+ // Query
76
+ const otherBucket = trx_node_1.TrxNode.getModule(trx).buckets[schema.bucket.refName];
77
+ // let tempData: Record<string, any> = {};
78
+ let tempAdapter;
79
+ if (otherBucket.adapter instanceof memory_bucket_adapter_1.MemoryBucketAdapter) {
80
+ tempAdapter = otherBucket.adapter;
81
+ }
82
+ else {
83
+ const allLinks = await otherBucket.adapter.query(trx, {
84
+ ...schema.query,
85
+ '#and': tenancy
86
+ }, undefined, objs.map(obj => ({ ...obj })));
87
+ const tempData = {};
88
+ for (const obj of allLinks.data)
89
+ tempData[obj.id] = obj;
90
+ tempAdapter = new memory_bucket_adapter_1.MemoryBucketAdapter(otherBucket.schema, tempData);
91
+ }
92
+ const links = [];
93
+ for (const obj of objs) {
94
+ const result = await tempAdapter.query(trx, schema.query, {
95
+ perPage: schema.many ? undefined : 1,
96
+ }, [{ ...obj }], undefined, tempAdapter.nql);
97
+ if (schema.many) {
98
+ links.push(result.data);
99
+ }
100
+ else {
101
+ links.push(result.data[0]);
102
+ }
103
+ }
104
+ // Empty response
105
+ return links;
106
+ }
60
107
  /**
61
108
  * Read the data from a link and build it with a given view
62
109
  *
@@ -102,7 +149,7 @@ class BucketGraph {
102
149
  '#and': tenancy
103
150
  }, {
104
151
  perPage: 1,
105
- }, { ...obj });
152
+ }, [{ ...obj }]);
106
153
  return !!links.data.length;
107
154
  }
108
155
  }
@@ -55,7 +55,6 @@ class $BucketModel {
55
55
  }
56
56
  // If it's a list or dict, or an object
57
57
  if (field.type === 'list' || field.type === 'dict') {
58
- // If not, iterate
59
58
  next.push({
60
59
  i: item.i + 1,
61
60
  field: field.children['#']
@@ -70,6 +69,10 @@ class $BucketModel {
70
69
  })));
71
70
  continue;
72
71
  }
72
+ if (field.type === 'unknown') {
73
+ results.push(field);
74
+ continue;
75
+ }
73
76
  const child = field.children[path];
74
77
  if (child) {
75
78
  next.push({
@@ -127,53 +130,53 @@ class $BucketModel {
127
130
  while (poll.length) {
128
131
  const next = [];
129
132
  for (const entry of poll) {
130
- const val = obj[entry.path];
133
+ const val = entry.obj[entry.path];
131
134
  if (val === undefined) {
132
135
  continue;
133
136
  }
134
137
  if (val === null) {
135
- copy[entry.path] = null;
138
+ entry.copy[entry.path] = null;
136
139
  continue;
137
140
  }
138
141
  if (entry.field.type === 'list') {
139
142
  if (!Array.isArray(val))
140
143
  continue;
141
- copy[entry.path] = [];
144
+ entry.copy[entry.path] = [];
142
145
  next.push(...val.map((_, i) => ({
143
146
  path: i.toString(),
144
147
  obj: val,
145
- copy: copy[entry.path],
148
+ copy: entry.copy[entry.path],
146
149
  field: entry.field.children['*']
147
150
  })));
148
151
  }
149
152
  else if (entry.field.type === 'dict') {
150
153
  if (typeof val !== 'object' || Array.isArray(val))
151
154
  continue;
152
- copy[entry.path] = {};
155
+ entry.copy[entry.path] = {};
153
156
  next.push(...Object.keys(val).map((path) => ({
154
157
  path,
155
158
  obj: val,
156
- copy: copy[entry.path],
159
+ copy: entry.copy[entry.path],
157
160
  field: entry.field.children['*']
158
161
  })));
159
162
  }
160
163
  else if (entry.field.type === 'obj') {
161
164
  if (typeof val !== 'object' || Array.isArray(val))
162
165
  continue;
163
- copy[entry.path] = {};
166
+ entry.copy[entry.path] = {};
164
167
  next.push(...Object.keys(entry.field.children).map(path => ({
165
168
  path: path,
166
169
  obj: val,
167
- copy: copy[entry.path],
170
+ copy: entry.copy[entry.path],
168
171
  field: entry.field.children[path]
169
172
  })));
170
173
  }
171
174
  else if (entry.field.type === 'union') {
172
175
  // TODO: ??????????
173
- copy[entry.path] = obj[entry.path];
176
+ entry.copy[entry.path] = entry.obj[entry.path];
174
177
  }
175
178
  else {
176
- copy[entry.path] = obj[entry.path];
179
+ entry.copy[entry.path] = entry.obj[entry.path];
177
180
  }
178
181
  }
179
182
  poll = next;
@@ -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>[], 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): Promise<NQL_Result>;
27
+ run(trx: AnyTrxNode, query: NQL_CompiledQuery, pagination?: NQL_Pagination, params?: Record<string, any>[], view?: $BucketView, runner?: NQLRunner): Promise<NQL_Result>;
28
28
  linkExternal(bucket: AnyBucket): void;
29
29
  }
30
30
  export {};
@@ -22,7 +22,9 @@ class NQL_Engine {
22
22
  }
23
23
  }
24
24
  }
25
- async run(trx, query, pagination, params = {}, view) {
25
+ async run(trx, query, pagination, params = [{}], view, runner) {
26
+ if (!params.length)
27
+ params = [{}];
26
28
  let result = {
27
29
  data: []
28
30
  };
@@ -30,8 +32,8 @@ class NQL_Engine {
30
32
  const part_i = query.execOrder[i];
31
33
  const part = query.parts[part_i];
32
34
  // Run part
33
- const runner = this.runners[part.union.meta.scope];
34
- const out = await runner.run(trx, part, params, pagination, view);
35
+ const _runner = runner || this.runners[part.union.meta.scope];
36
+ const out = await _runner.run(trx, part, params, pagination, view);
35
37
  result = out;
36
38
  // Part failed, return
37
39
  // Failure here is only when a single value is expected,
@@ -43,7 +45,9 @@ class NQL_Engine {
43
45
  }
44
46
  }
45
47
  // Fill part params
46
- params[`%__${part_i}__%`] = part.many ? result.data : result.data[0];
48
+ for (const paramGroup of params) {
49
+ paramGroup[`%__${part_i}__%`] = part.many ? result.data : result.data[0];
50
+ }
47
51
  }
48
52
  return result;
49
53
  }
@@ -4,9 +4,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.BucketView = void 0;
7
+ const trx_node_1 = require("../../../../engine/transaction/trx_node");
7
8
  const promise_1 = __importDefault(require("../../../../engine/util/promise"));
8
9
  const error_1 = require("../../../../engine/data/error");
9
10
  const tree_1 = require("../../../../engine/data/tree");
11
+ const dependency_1 = require("../../../../engine/dependency");
10
12
  class ViewValue {
11
13
  constructor() {
12
14
  this.value = undefined;
@@ -27,6 +29,7 @@ class BucketView {
27
29
  Object.assign(parsed, raw);
28
30
  }
29
31
  let layer = Object.values(this.schema.fields).map(field => ({
32
+ bucket: this.bucket,
30
33
  field,
31
34
  data: [{
32
35
  raw,
@@ -54,6 +57,7 @@ class BucketView {
54
57
  parseds.push(parsed);
55
58
  }
56
59
  let layer = Object.values(this.schema.fields).map(field => ({
60
+ bucket: this.bucket,
57
61
  field,
58
62
  data: raws.map((raw, i) => ({
59
63
  raw,
@@ -89,7 +93,7 @@ class BucketView {
89
93
  for (const node of layer) {
90
94
  if (node.field.scope !== 'graph')
91
95
  continue;
92
- await this.parseGraphProp(trx, node);
96
+ next.push(...await this.parseGraphProp(trx, node));
93
97
  }
94
98
  // Drive props
95
99
  for (const node of layer) {
@@ -109,6 +113,7 @@ class BucketView {
109
113
  }
110
114
  }
111
115
  next.push(...Object.values(node.field.children).map(field => ({
116
+ bucket: node.bucket,
112
117
  field,
113
118
  data: node.data
114
119
  })));
@@ -118,6 +123,7 @@ class BucketView {
118
123
  if (!node.field.chain)
119
124
  continue;
120
125
  next.push({
126
+ bucket: node.bucket,
121
127
  field: node.field.chain,
122
128
  data: node.data.map(d => ({
123
129
  index: d.index,
@@ -144,6 +150,7 @@ class BucketView {
144
150
  if (key === '__raw')
145
151
  continue;
146
152
  next.push({
153
+ bucket: node.bucket,
147
154
  field: node.field.children[key],
148
155
  data: nextData
149
156
  });
@@ -249,7 +256,7 @@ class BucketView {
249
256
  async parseComputedProp(trx, node) {
250
257
  const meta = node.field.meta.computed;
251
258
  for (const entry of node.data) {
252
- entry.target[node.field.name] = await promise_1.default.solve(meta.fn({ trx, raw: entry.raw, bucket: this.bucket.schema }));
259
+ entry.target[node.field.name] = await promise_1.default.solve(meta.fn({ trx, raw: entry.raw, bucket: node.bucket.schema }));
253
260
  }
254
261
  }
255
262
  /**
@@ -257,23 +264,69 @@ class BucketView {
257
264
  */
258
265
  async parseGraphProp(trx, node) {
259
266
  const meta = node.field.meta.graph;
260
- for (const entry of node.data) {
261
- let link;
262
- if (!meta.view) {
263
- link = this.bucket.graph.readLink(trx, entry.raw, meta.link, { silent: true });
267
+ const links = await node.bucket.graph.readManyLinks(trx, node.data.map(entry => entry.raw), meta.link, { silent: true });
268
+ for (let i = 0; i < links.length; i++) {
269
+ if (meta.view) {
270
+ const link = node.bucket.schema.graph.links[meta.link];
271
+ node.data[i].target[node.field.name] = link.many ? [] : {};
264
272
  }
265
273
  else {
266
- link = this.bucket.graph.viewLink(trx, entry.raw, meta.link, meta.view, { silent: true });
274
+ node.data[i].target[node.field.name] = links[i];
267
275
  }
268
- entry.target[node.field.name] = await promise_1.default.solve(link);
269
276
  }
277
+ let next = [];
278
+ if (meta.view) {
279
+ const schema = node.bucket.schema;
280
+ const otherBucketDep = schema.graph.links[meta.link].bucket;
281
+ const module = trx_node_1.TrxNode.getModule(trx);
282
+ const otherBucket = dependency_1.$Dependency.resolve(module.schema, otherBucketDep);
283
+ const view = otherBucket.views[meta.view];
284
+ const { __raw, ...v } = view.fields;
285
+ const link = node.bucket.schema.graph.links[meta.link];
286
+ let nextData;
287
+ if (link.many) {
288
+ const _links = links;
289
+ for (let i = 0; i < _links.length; i++) {
290
+ const target = node.data[i].target[node.field.name];
291
+ for (let j = 0; j < _links[i].length; j++) {
292
+ target.push(__raw ? { ..._links[i][j] } : {});
293
+ target[j].$v = meta.view;
294
+ }
295
+ }
296
+ nextData = _links.map((ll, i) => ll.map((l, j) => ({ value: l, target: node.data[i].target[node.field.name][j] }))).flat(1);
297
+ }
298
+ else {
299
+ const _links = links;
300
+ for (let i = 0; i < _links.length; i++) {
301
+ const target = node.data[i].target[node.field.name];
302
+ if (__raw) {
303
+ Object.assign(target, _links[i]);
304
+ }
305
+ target.$v = meta.view;
306
+ }
307
+ nextData = _links.map((l, i) => ({
308
+ value: l, target: node.data[i].target[node.field.name]
309
+ }));
310
+ }
311
+ next = Object.values(v).map(field => ({
312
+ bucket: module.buckets[otherBucketDep.refName],
313
+ field,
314
+ data: nextData.map($ => ({
315
+ raw: $.value,
316
+ value: $.value,
317
+ index: [],
318
+ target: $.target
319
+ }))
320
+ }));
321
+ }
322
+ return next;
270
323
  }
271
324
  /**
272
325
  * [drive]
273
326
  */
274
327
  async parseDriveProp(trx, node) {
275
- if (!this.bucket.drive) {
276
- throw error_1.NesoiError.Bucket.Drive.NoAdapter({ bucket: this.bucket.schema.alias });
328
+ if (!node.bucket.drive) {
329
+ throw error_1.NesoiError.Bucket.Drive.NoAdapter({ bucket: node.bucket.schema.alias });
277
330
  }
278
331
  const meta = node.field.meta.drive;
279
332
  for (const entry of node.data) {
@@ -281,12 +334,12 @@ class BucketView {
281
334
  if (Array.isArray(value)) {
282
335
  const public_urls = [];
283
336
  for (const obj of value) {
284
- public_urls.push(await this.bucket.drive.public(obj));
337
+ public_urls.push(await node.bucket.drive.public(obj));
285
338
  }
286
339
  entry.target[node.field.name] = public_urls;
287
340
  }
288
341
  else {
289
- entry.target[node.field.name] = await this.bucket.drive.public(value);
342
+ entry.target[node.field.name] = await node.bucket.drive.public(value);
290
343
  }
291
344
  }
292
345
  }
@@ -64,6 +64,11 @@ export declare class BucketTrxNode<M extends $Module, $ extends $Bucket> {
64
64
  * or `undefined` if the graph link doesn't resolve.
65
65
  */
66
66
  readLink<LinkName extends keyof $['graph']['links'], Link extends $['graph']['links'][LinkName], Obj extends Link['#bucket']['#data']>(id: $['#data']['id'], link: LinkName): Promise<Link['#many'] extends true ? Obj[] : (Obj | undefined)>;
67
+ /**
68
+ * Returns one or more objects referenced by the graph link,
69
+ * or `undefined` if the graph link doesn't resolve.
70
+ */
71
+ readManyLinks<LinkName extends keyof $['graph']['links'], Link extends $['graph']['links'][LinkName], Obj extends Link['#bucket']['#data']>(ids: $['#data']['id'][], link: LinkName): Promise<Link['#many'] extends true ? Obj[] : (Obj | undefined)>;
67
72
  /**
68
73
  * Returns one or more objects referenced by the graph link built with a view,
69
74
  * or `undefined` if the graph link doesn't resolve.
@@ -133,6 +133,16 @@ class BucketTrxNode {
133
133
  no_tenancy: !this.enableTenancy
134
134
  }));
135
135
  }
136
+ /**
137
+ * Returns one or more objects referenced by the graph link,
138
+ * or `undefined` if the graph link doesn't resolve.
139
+ */
140
+ async readManyLinks(ids, link) {
141
+ return this.wrap('readLinks', { ids, link }, trx => this.bucket.readManyLinks(trx, ids, link, {
142
+ silent: true,
143
+ no_tenancy: !this.enableTenancy
144
+ }));
145
+ }
136
146
  /**
137
147
  * Returns one or more objects referenced by the graph link built with a view,
138
148
  * or `undefined` if the graph link doesn't resolve.
@@ -14,8 +14,10 @@ export declare class BucketQueryTrxNode<M extends $Module, B extends $Bucket, V
14
14
  private query;
15
15
  private enableTenancy;
16
16
  private view?;
17
+ private _params?;
17
18
  constructor(trx: TrxNode<any, M, any>, bucket: Bucket<M, B>, query: NQL_AnyQuery, enableTenancy: boolean, view?: V | undefined);
18
19
  merge($: NQL_Query<M, B>): void;
20
+ params(value: Record<string, any>): this;
19
21
  first(): Promise<Obj | undefined>;
20
22
  firstOrFail(): Promise<Obj>;
21
23
  all(): Promise<Obj[]>;