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.
- package/lib/elements/blocks/job/internal/resource_job.builder.js +3 -1
- package/lib/elements/blocks/resource/resource.builder.js +1 -1
- package/lib/elements/entities/bucket/adapters/bucket_adapter.d.ts +1 -1
- package/lib/elements/entities/bucket/adapters/bucket_adapter.js +2 -2
- package/lib/elements/entities/bucket/adapters/memory.nql.d.ts +1 -1
- package/lib/elements/entities/bucket/adapters/memory.nql.js +33 -15
- package/lib/elements/entities/bucket/bucket.builder.js +1 -1
- package/lib/elements/entities/bucket/bucket.d.ts +4 -0
- package/lib/elements/entities/bucket/bucket.infer.d.ts +7 -7
- package/lib/elements/entities/bucket/bucket.js +9 -9
- package/lib/elements/entities/bucket/cache/bucket_cache.js +3 -3
- package/lib/elements/entities/bucket/graph/bucket_graph.d.ts +13 -3
- package/lib/elements/entities/bucket/graph/bucket_graph.infer.d.ts +1 -1
- package/lib/elements/entities/bucket/graph/bucket_graph.js +21 -11
- package/lib/elements/entities/bucket/graph/bucket_graph_link.builder.d.ts +6 -5
- package/lib/elements/entities/bucket/model/bucket_model.convert.js +4 -4
- package/lib/elements/entities/bucket/query/nql.schema.d.ts +2 -0
- package/lib/elements/entities/bucket/query/nql_compiler.js +6 -1
- package/lib/elements/entities/bucket/query/nql_engine.d.ts +2 -2
- package/lib/elements/entities/bucket/query/nql_engine.js +2 -2
- package/lib/elements/entities/bucket/view/bucket_view.builder.d.ts +3 -2
- package/lib/elements/entities/bucket/view/bucket_view.builder.js +3 -3
- package/lib/elements/entities/bucket/view/bucket_view.js +123 -32
- package/lib/elements/entities/bucket/view/bucket_view.schema.d.ts +6 -3
- package/lib/elements/entities/bucket/view/bucket_view.schema.js +2 -1
- package/lib/elements/entities/bucket/view/bucket_view_field.builder.d.ts +25 -24
- package/lib/elements/entities/bucket/view/bucket_view_field.builder.js +65 -25
- package/lib/engine/app/inline.app.js +6 -0
- package/lib/engine/app/native/distributed_node.app.js +6 -0
- package/lib/engine/app/service.d.ts +7 -0
- package/lib/engine/app/service.js +2 -0
- package/lib/engine/module.js +1 -0
- package/lib/engine/transaction/nodes/bucket.trx_node.d.ts +2 -2
- package/lib/engine/transaction/nodes/bucket.trx_node.js +6 -4
- package/lib/engine/transaction/nodes/bucket_query.trx_node.d.ts +2 -0
- package/lib/engine/transaction/nodes/bucket_query.trx_node.js +15 -4
- package/lib/engine/transaction/nodes/job.trx_node.js +1 -1
- package/lib/engine/transaction/trx_engine.js +1 -1
- package/lib/engine/transaction/trx_node.d.ts +1 -1
- package/lib/engine/transaction/trx_node.js +3 -3
- package/package.json +1 -1
- 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:
|
|
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
|
-
|
|
134
|
-
|
|
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
|
|
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<
|
|
11
|
-
[K in keyof
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
-
'#
|
|
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(
|
|
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
|
|
41
|
+
}, field.children ? convertFields(field.children) : undefined);
|
|
42
42
|
};
|
|
43
|
-
const convertFields = (fields
|
|
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
|
|
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
|
}
|
|
@@ -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
|
-
:
|
|
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 {};
|