nesoi 3.3.19 → 3.3.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/elements/edge/controller/adapters/controller_adapter.d.ts +4 -1
- package/lib/elements/edge/controller/adapters/controller_adapter.js +8 -4
- package/lib/elements/edge/controller/controller.js +3 -3
- package/lib/elements/edge/controller/controller.schema.d.ts +2 -1
- package/lib/elements/edge/controller/controller.schema.js +3 -1
- package/lib/elements/entities/bucket/adapters/bucket_adapter.d.ts +25 -3
- package/lib/elements/entities/bucket/adapters/bucket_adapter.js +21 -2
- package/lib/elements/entities/bucket/adapters/memory.nql.js +86 -50
- package/lib/elements/entities/bucket/adapters/test.bucket_adapter.d.ts +22 -0
- package/lib/elements/entities/bucket/adapters/test.bucket_adapter.js +23 -0
- package/lib/elements/entities/bucket/bucket.js +2 -2
- package/lib/elements/entities/bucket/cache/bucket_cache.d.ts +16 -1
- package/lib/elements/entities/bucket/cache/bucket_cache.js +36 -15
- package/lib/elements/entities/bucket/graph/bucket_graph.js +28 -18
- package/lib/elements/entities/bucket/query/nql.schema.d.ts +3 -0
- package/lib/elements/entities/bucket/query/nql_compiler.d.ts +10 -4
- package/lib/elements/entities/bucket/query/nql_compiler.js +42 -35
- package/lib/elements/entities/bucket/query/nql_engine.d.ts +4 -1
- package/lib/elements/entities/bucket/query/nql_engine.js +3 -5
- package/lib/elements/entities/message/template/message_template_field.builder.d.ts +2 -0
- package/lib/elements/entities/message/template/message_template_field.builder.js +5 -0
- package/lib/engine/daemon.d.ts +19 -0
- package/lib/engine/daemon.js +40 -2
- package/lib/engine/data/tree.d.ts +1 -2
- package/lib/engine/data/tree.js +6 -94
- package/lib/engine/transaction/nodes/bucket.trx_node.d.ts +1 -1
- package/lib/engine/transaction/nodes/bucket.trx_node.js +15 -15
- package/lib/engine/transaction/nodes/bucket_query.trx_node.js +2 -2
- package/lib/engine/transaction/nodes/external.trx_node.d.ts +3 -1
- package/lib/engine/transaction/nodes/external.trx_node.js +54 -4
- package/lib/engine/transaction/nodes/job.trx_node.js +3 -2
- package/lib/engine/transaction/nodes/machine.trx_node.js +1 -1
- package/lib/engine/transaction/nodes/queue.trx_node.js +1 -1
- package/lib/engine/transaction/nodes/resource.trx_node.js +1 -1
- package/lib/engine/transaction/nodes/topic.trx_node.js +1 -1
- package/lib/engine/transaction/trx.d.ts +7 -1
- package/lib/engine/transaction/trx.js +15 -1
- package/lib/engine/transaction/trx_engine.config.d.ts +6 -1
- package/lib/engine/transaction/trx_engine.d.ts +5 -5
- package/lib/engine/transaction/trx_engine.js +59 -36
- package/lib/engine/transaction/trx_node.d.ts +1 -1
- package/lib/engine/transaction/trx_node.js +1 -1
- package/package.json +1 -1
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -62,7 +62,7 @@ class BucketGraph {
|
|
|
62
62
|
...schema.query,
|
|
63
63
|
'#and __tenancy__': tenancy
|
|
64
64
|
};
|
|
65
|
-
const adapter = await trx_1.Trx.getCache(trx,
|
|
65
|
+
const adapter = await trx_1.Trx.getCache(trx, otherBucket) || otherBucket.cache || otherBucket.adapter;
|
|
66
66
|
links = await adapter.query(trx, query, page, params, param_templates ? [param_templates] : undefined);
|
|
67
67
|
}
|
|
68
68
|
// Empty response
|
|
@@ -113,8 +113,8 @@ class BucketGraph {
|
|
|
113
113
|
const tempData = {};
|
|
114
114
|
for (const obj of allLinks)
|
|
115
115
|
tempData[obj.id] = obj;
|
|
116
|
-
const
|
|
117
|
-
tempAdapter = new memory_bucket_adapter_1.MemoryBucketAdapter(
|
|
116
|
+
const otherMeta = await daemon_1.Daemon.getBucketMetadata(module.daemon, schema.bucket);
|
|
117
|
+
tempAdapter = new memory_bucket_adapter_1.MemoryBucketAdapter(otherMeta.schema, tempData);
|
|
118
118
|
}
|
|
119
119
|
// Internal
|
|
120
120
|
else {
|
|
@@ -128,10 +128,10 @@ class BucketGraph {
|
|
|
128
128
|
'#and __tenancy__': tenancy
|
|
129
129
|
};
|
|
130
130
|
if (otherBucket.adapter instanceof memory_bucket_adapter_1.MemoryBucketAdapter) {
|
|
131
|
-
tempAdapter = await trx_1.Trx.getCache(trx,
|
|
131
|
+
tempAdapter = await trx_1.Trx.getCache(trx, otherBucket) || otherBucket.cache || otherBucket.adapter;
|
|
132
132
|
}
|
|
133
133
|
else {
|
|
134
|
-
const adapter = await trx_1.Trx.getCache(trx,
|
|
134
|
+
const adapter = await trx_1.Trx.getCache(trx, otherBucket) || otherBucket.cache || otherBucket.adapter;
|
|
135
135
|
const allLinks = await adapter.query(trx, query, undefined, params, param_templates);
|
|
136
136
|
const tempData = {};
|
|
137
137
|
for (const obj of allLinks.data)
|
|
@@ -141,25 +141,35 @@ class BucketGraph {
|
|
|
141
141
|
}
|
|
142
142
|
// 2nd Query
|
|
143
143
|
const links = [];
|
|
144
|
+
const compiled = await tempAdapter._compileQuery(trx, schema.query, {
|
|
145
|
+
module: schema.bucket.module,
|
|
146
|
+
buckets: {
|
|
147
|
+
[schema.bucket.short]: {
|
|
148
|
+
scope: '__graph__',
|
|
149
|
+
nql: (tempAdapter instanceof bucket_cache_1.BucketCache) ? undefined : tempAdapter.nql
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
});
|
|
144
153
|
for (const obj of objs) {
|
|
145
|
-
|
|
146
|
-
|
|
154
|
+
let result;
|
|
155
|
+
if (tempAdapter instanceof bucket_cache_1.BucketCache) {
|
|
156
|
+
result = await tempAdapter._queryCompiled(trx, compiled, {
|
|
147
157
|
perPage: schema.many ? undefined : 1,
|
|
148
|
-
}, [{ ...obj }], undefined)
|
|
149
|
-
|
|
158
|
+
}, [{ ...obj }], undefined);
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
result = await tempAdapter._queryCompiled(trx, compiled, {
|
|
150
162
|
perPage: schema.many ? undefined : 1,
|
|
151
163
|
}, [{ ...obj }], undefined, undefined, {
|
|
152
164
|
module: schema.bucket.module,
|
|
153
|
-
|
|
154
|
-
[
|
|
165
|
+
buckets: {
|
|
166
|
+
[schema.bucket.short]: {
|
|
167
|
+
scope: '__graph__',
|
|
168
|
+
nql: tempAdapter.nql
|
|
169
|
+
}
|
|
155
170
|
},
|
|
156
|
-
metadata: {
|
|
157
|
-
...tempAdapter.getQueryMeta(),
|
|
158
|
-
schema: tempAdapter.schema,
|
|
159
|
-
tag: schema.bucket,
|
|
160
|
-
meta: tempAdapter.config.meta
|
|
161
|
-
}
|
|
162
171
|
});
|
|
172
|
+
}
|
|
163
173
|
if (schema.many) {
|
|
164
174
|
links.push(result.data);
|
|
165
175
|
}
|
|
@@ -239,7 +249,7 @@ class BucketGraph {
|
|
|
239
249
|
...schema.query,
|
|
240
250
|
'#and__tenancy__': tenancy
|
|
241
251
|
};
|
|
242
|
-
const adapter = await trx_1.Trx.getCache(trx,
|
|
252
|
+
const adapter = await trx_1.Trx.getCache(trx, otherBucket) || otherBucket.cache || otherBucket.adapter;
|
|
243
253
|
links = await adapter.query(trx, query, page, params);
|
|
244
254
|
}
|
|
245
255
|
return !!links.data.length;
|
|
@@ -13,6 +13,7 @@ export type NQL_Union = {
|
|
|
13
13
|
inters: NQL_Intersection[];
|
|
14
14
|
sort?: {
|
|
15
15
|
key: string;
|
|
16
|
+
key_is_deep: boolean;
|
|
16
17
|
dir: ('asc' | 'desc');
|
|
17
18
|
}[];
|
|
18
19
|
_debug_id?: number;
|
|
@@ -25,6 +26,7 @@ export type NQL_Intersection = {
|
|
|
25
26
|
export type NQL_Rule = {
|
|
26
27
|
meta: NQL_QueryMeta;
|
|
27
28
|
fieldpath: string;
|
|
29
|
+
fieldpath_is_deep: boolean;
|
|
28
30
|
op: NQL_Operation;
|
|
29
31
|
case_i: boolean;
|
|
30
32
|
not: boolean;
|
|
@@ -32,6 +34,7 @@ export type NQL_Rule = {
|
|
|
32
34
|
static: any | any[];
|
|
33
35
|
} | {
|
|
34
36
|
param: string | string[];
|
|
37
|
+
param_is_deep: boolean;
|
|
35
38
|
} | {
|
|
36
39
|
param_with_$: string;
|
|
37
40
|
} | {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NQL_AnyQuery, NQL_Union, NQL_Part, NQL_Node } from './nql.schema';
|
|
2
2
|
import { AnyDaemon } from "../../../../engine/daemon";
|
|
3
|
-
import {
|
|
3
|
+
import { NQLRunner } from './nql_engine';
|
|
4
4
|
/**
|
|
5
5
|
* @category NQL
|
|
6
6
|
* */
|
|
@@ -9,11 +9,14 @@ export declare class NQL_RuleTree {
|
|
|
9
9
|
private module;
|
|
10
10
|
private bucketName;
|
|
11
11
|
private query;
|
|
12
|
-
private
|
|
12
|
+
private customBuckets;
|
|
13
13
|
private debug;
|
|
14
14
|
private static OpByType;
|
|
15
15
|
root: NQL_Union;
|
|
16
|
-
constructor(daemon: AnyDaemon, module: string, bucketName: string, query: NQL_AnyQuery,
|
|
16
|
+
constructor(daemon: AnyDaemon, module: string, bucketName: string, query: NQL_AnyQuery, customBuckets?: Record<string, {
|
|
17
|
+
scope: string;
|
|
18
|
+
nql: NQLRunner;
|
|
19
|
+
}>, debug?: boolean);
|
|
17
20
|
parse(): Promise<void>;
|
|
18
21
|
private parseUnion;
|
|
19
22
|
private parseSort;
|
|
@@ -39,7 +42,10 @@ export declare class NQL_RuleTree {
|
|
|
39
42
|
* @category NQL
|
|
40
43
|
* */
|
|
41
44
|
export declare class NQL_Compiler {
|
|
42
|
-
static build(daemon: AnyDaemon, module: string, bucketName: string, query: NQL_AnyQuery,
|
|
45
|
+
static build(daemon: AnyDaemon, module: string, bucketName: string, query: NQL_AnyQuery, customBuckets?: Record<string, {
|
|
46
|
+
scope: string;
|
|
47
|
+
nql: NQLRunner;
|
|
48
|
+
}>): Promise<NQL_CompiledQuery>;
|
|
43
49
|
static buildTree(tree: NQL_RuleTree): Promise<NQL_CompiledQuery>;
|
|
44
50
|
}
|
|
45
51
|
/**
|
|
@@ -13,7 +13,7 @@ class NQL_RuleTree {
|
|
|
13
13
|
module;
|
|
14
14
|
bucketName;
|
|
15
15
|
query;
|
|
16
|
-
|
|
16
|
+
customBuckets;
|
|
17
17
|
debug;
|
|
18
18
|
static OpByType = {
|
|
19
19
|
'boolean': ['==', 'in', 'present'],
|
|
@@ -34,18 +34,19 @@ class NQL_RuleTree {
|
|
|
34
34
|
'unknown': ['==', 'contains', 'contains_any', 'in', 'present']
|
|
35
35
|
};
|
|
36
36
|
root;
|
|
37
|
-
constructor(daemon, module, bucketName, query,
|
|
37
|
+
constructor(daemon, module, bucketName, query, customBuckets = {}, debug = false) {
|
|
38
38
|
this.daemon = daemon;
|
|
39
39
|
this.module = module;
|
|
40
40
|
this.bucketName = bucketName;
|
|
41
41
|
this.query = query;
|
|
42
|
-
this.
|
|
42
|
+
this.customBuckets = customBuckets;
|
|
43
43
|
this.debug = debug;
|
|
44
44
|
}
|
|
45
45
|
async parse() {
|
|
46
46
|
const tag = dependency_1.Tag.fromNameOrShort(this.module, 'bucket', this.bucketName);
|
|
47
|
-
const
|
|
48
|
-
|
|
47
|
+
const meta = await daemon_1.Daemon.getBucketMetadata(this.daemon, tag);
|
|
48
|
+
meta.scope = this.customBuckets[tag.short]?.scope || meta.scope;
|
|
49
|
+
this.root = await this.parseUnion(meta, this.query);
|
|
49
50
|
if (this.debug) {
|
|
50
51
|
console.log(this.describe());
|
|
51
52
|
}
|
|
@@ -56,10 +57,10 @@ class NQL_RuleTree {
|
|
|
56
57
|
}
|
|
57
58
|
}
|
|
58
59
|
// Parse NQL
|
|
59
|
-
async parseUnion(
|
|
60
|
+
async parseUnion(meta, query, select) {
|
|
60
61
|
const union = {
|
|
61
62
|
meta: {
|
|
62
|
-
...
|
|
63
|
+
...meta,
|
|
63
64
|
avgTime: 0
|
|
64
65
|
},
|
|
65
66
|
inters: [
|
|
@@ -68,16 +69,17 @@ class NQL_RuleTree {
|
|
|
68
69
|
};
|
|
69
70
|
for (const key in query) {
|
|
70
71
|
const value = query[key];
|
|
71
|
-
const parsedKey = await this.parseKey(
|
|
72
|
+
const parsedKey = await this.parseKey(meta, key);
|
|
72
73
|
// Fieldpath term -> Condition
|
|
73
74
|
if (parsedKey.type === 'fieldpath') {
|
|
74
|
-
const parsed = await this.parseValue(value, parsedKey,
|
|
75
|
+
const parsed = await this.parseValue(value, parsedKey, meta, select);
|
|
75
76
|
const rule = ('subquery' in parsed)
|
|
76
77
|
? parsed.subquery.union
|
|
77
78
|
: {
|
|
78
|
-
meta: { ...
|
|
79
|
+
meta: { ...meta },
|
|
79
80
|
select,
|
|
80
81
|
fieldpath: parsedKey.fieldpath,
|
|
82
|
+
fieldpath_is_deep: parsedKey.fieldpath.includes('.'),
|
|
81
83
|
value: parsed,
|
|
82
84
|
op: parsedKey.op,
|
|
83
85
|
case_i: parsedKey.case_i,
|
|
@@ -102,15 +104,15 @@ class NQL_RuleTree {
|
|
|
102
104
|
throw new Error('Graph Link not supported yet');
|
|
103
105
|
}
|
|
104
106
|
else if (parsedKey.type === 'and') {
|
|
105
|
-
const subInter = await this.parseUnion(
|
|
107
|
+
const subInter = await this.parseUnion(meta, value, select);
|
|
106
108
|
union.inters[0].rules.push(subInter);
|
|
107
109
|
}
|
|
108
110
|
else if (parsedKey.type === 'or') {
|
|
109
|
-
const subInter = await this.parseUnion(
|
|
111
|
+
const subInter = await this.parseUnion(meta, value, select);
|
|
110
112
|
union.inters.push({ meta: {}, rules: [subInter] });
|
|
111
113
|
}
|
|
112
114
|
else if (parsedKey.type === 'sort') {
|
|
113
|
-
union.sort = await this.parseSort(
|
|
115
|
+
union.sort = await this.parseSort(meta, value);
|
|
114
116
|
}
|
|
115
117
|
}
|
|
116
118
|
if (!union.inters[0]?.rules.length) {
|
|
@@ -118,7 +120,7 @@ class NQL_RuleTree {
|
|
|
118
120
|
}
|
|
119
121
|
return union;
|
|
120
122
|
}
|
|
121
|
-
parseSort(
|
|
123
|
+
parseSort(meta, value) {
|
|
122
124
|
if (!Array.isArray(value))
|
|
123
125
|
value = [value];
|
|
124
126
|
if (value.some(v => typeof v !== 'string')) {
|
|
@@ -138,11 +140,11 @@ class NQL_RuleTree {
|
|
|
138
140
|
else {
|
|
139
141
|
throw new Error(`Invalid query sort direction '${key}', string must end with '@asc' or '@desc'`);
|
|
140
142
|
}
|
|
141
|
-
const is_metadata_field = Object.values(
|
|
143
|
+
const is_metadata_field = Object.values(meta.meta).includes(key);
|
|
142
144
|
if (!is_metadata_field) {
|
|
143
|
-
const fields = bucket_model_schema_1.$BucketModel.getField(
|
|
145
|
+
const fields = bucket_model_schema_1.$BucketModel.getField(meta.schema.model, key);
|
|
144
146
|
if (!fields.length) {
|
|
145
|
-
throw new Error(`Field '${key}' not found on bucket '${
|
|
147
|
+
throw new Error(`Field '${key}' not found on bucket '${meta.schema.name}'`);
|
|
146
148
|
}
|
|
147
149
|
for (const field of fields) {
|
|
148
150
|
if (![
|
|
@@ -154,12 +156,13 @@ class NQL_RuleTree {
|
|
|
154
156
|
}
|
|
155
157
|
sort.push({
|
|
156
158
|
key,
|
|
159
|
+
key_is_deep: key.includes('.'),
|
|
157
160
|
dir: vdir
|
|
158
161
|
});
|
|
159
162
|
}
|
|
160
163
|
return sort;
|
|
161
164
|
}
|
|
162
|
-
async parseKey(
|
|
165
|
+
async parseKey(meta, key) {
|
|
163
166
|
if (key === '#sort') {
|
|
164
167
|
return { type: 'sort' };
|
|
165
168
|
}
|
|
@@ -171,9 +174,9 @@ class NQL_RuleTree {
|
|
|
171
174
|
}
|
|
172
175
|
else if (key.startsWith('*')) {
|
|
173
176
|
const linkName = key.slice(1);
|
|
174
|
-
const link =
|
|
177
|
+
const link = meta.schema.graph.links[linkName];
|
|
175
178
|
if (!link) {
|
|
176
|
-
throw new Error(`Graph Link '${linkName}' doesn't exist on the bucket ${
|
|
179
|
+
throw new Error(`Graph Link '${linkName}' doesn't exist on the bucket ${meta}`);
|
|
177
180
|
}
|
|
178
181
|
const linkBucket = await daemon_1.Daemon.getBucketMetadata(this.daemon, link.bucket);
|
|
179
182
|
return { type: 'graphlink', link: link.name, linkBucket: linkBucket.schema };
|
|
@@ -184,13 +187,13 @@ class NQL_RuleTree {
|
|
|
184
187
|
throw new Error(`Invalid term '${key}'`);
|
|
185
188
|
}
|
|
186
189
|
const [_, or, fieldpath, not, case_i, op] = term;
|
|
187
|
-
if (Object.values(
|
|
190
|
+
if (Object.values(meta.meta).includes(fieldpath)) {
|
|
188
191
|
const _op = this.parseOp([{ type: 'datetime', name: fieldpath }], op);
|
|
189
192
|
return { type: 'fieldpath', or: !!or, fieldpath, not: !!not, case_i: !!case_i, op: _op };
|
|
190
193
|
}
|
|
191
|
-
const fields = bucket_model_schema_1.$BucketModel.getField(
|
|
194
|
+
const fields = bucket_model_schema_1.$BucketModel.getField(meta.schema.model, fieldpath);
|
|
192
195
|
if (!fields.length) {
|
|
193
|
-
throw new Error(`Field '${fieldpath}' not found on bucket '${
|
|
196
|
+
throw new Error(`Field '${fieldpath}' not found on bucket '${meta.schema.name}'`);
|
|
194
197
|
}
|
|
195
198
|
const _op = this.parseOp(fields, op);
|
|
196
199
|
return { type: 'fieldpath', or: !!or, fieldpath, not: !!not, case_i: !!case_i, op: _op };
|
|
@@ -253,7 +256,7 @@ class NQL_RuleTree {
|
|
|
253
256
|
throw new Error(`Cannot mix static and parameter values inside array value [${value}]`);
|
|
254
257
|
}
|
|
255
258
|
if (params.length > 0) {
|
|
256
|
-
return { param: params };
|
|
259
|
+
return { param: params, param_is_deep: params.some(p => p.includes('.')) };
|
|
257
260
|
}
|
|
258
261
|
else {
|
|
259
262
|
return { static: statyc };
|
|
@@ -262,7 +265,7 @@ class NQL_RuleTree {
|
|
|
262
265
|
else {
|
|
263
266
|
// Parameter
|
|
264
267
|
if ('.' in value) {
|
|
265
|
-
return { param: value['.'] };
|
|
268
|
+
return { param: value['.'], param_is_deep: value['.'].includes('.') };
|
|
266
269
|
}
|
|
267
270
|
// Path Parameter
|
|
268
271
|
else if ('$' in value) {
|
|
@@ -292,24 +295,28 @@ class NQL_RuleTree {
|
|
|
292
295
|
}
|
|
293
296
|
const [_, or, refBucket, fieldpath] = refField;
|
|
294
297
|
const tag = dependency_1.Tag.fromNameOrShort(this.module, 'bucket', refBucket);
|
|
295
|
-
const
|
|
296
|
-
if (!
|
|
297
|
-
throw new Error(`Bucket '${
|
|
298
|
+
const subMeta = await daemon_1.Daemon.getBucketMetadata(this.daemon, tag);
|
|
299
|
+
if (!subMeta) {
|
|
300
|
+
throw new Error(`Bucket '${subMeta}' not found on module`);
|
|
298
301
|
}
|
|
299
|
-
|
|
302
|
+
subMeta.scope = this.customBuckets[tag.short]?.scope || subMeta.scope;
|
|
303
|
+
const field = bucket_model_schema_1.$BucketModel.getField(subMeta.schema.model, fieldpath);
|
|
300
304
|
if (!field) {
|
|
301
|
-
throw new Error(`Field '${fieldpath}' not found on bucket '${
|
|
305
|
+
throw new Error(`Field '${fieldpath}' not found on bucket '${subMeta.schema.name}'`);
|
|
302
306
|
}
|
|
303
|
-
|
|
307
|
+
// The union belongs to the sub scope.
|
|
308
|
+
const refInter = await this.parseUnion(subMeta, value[key], fieldpath);
|
|
304
309
|
const rule = {
|
|
310
|
+
// This rule belongs to the parent scope.
|
|
305
311
|
meta: { ...meta },
|
|
306
312
|
select,
|
|
307
313
|
fieldpath: parsedKey.fieldpath,
|
|
314
|
+
fieldpath_is_deep: parsedKey.fieldpath.includes('.'),
|
|
308
315
|
case_i: parsedKey.case_i,
|
|
309
316
|
not: parsedKey.not,
|
|
310
317
|
op: parsedKey.op,
|
|
311
318
|
value: {
|
|
312
|
-
subquery: { union: refInter, bucket:
|
|
319
|
+
subquery: { union: refInter, bucket: subMeta.schema, select: fieldpath }
|
|
313
320
|
}
|
|
314
321
|
};
|
|
315
322
|
if (!or) {
|
|
@@ -512,8 +519,8 @@ exports.NQL_RuleTree = NQL_RuleTree;
|
|
|
512
519
|
* @category NQL
|
|
513
520
|
* */
|
|
514
521
|
class NQL_Compiler {
|
|
515
|
-
static async build(daemon, module, bucketName, query,
|
|
516
|
-
const tree = new NQL_RuleTree(daemon, module, bucketName, query,
|
|
522
|
+
static async build(daemon, module, bucketName, query, customBuckets = {}) {
|
|
523
|
+
const tree = new NQL_RuleTree(daemon, module, bucketName, query, customBuckets);
|
|
517
524
|
return this.buildTree(tree);
|
|
518
525
|
}
|
|
519
526
|
static async buildTree(tree) {
|
|
@@ -659,7 +666,7 @@ class NQL_Compiler {
|
|
|
659
666
|
// Close part (&1)
|
|
660
667
|
if (rule.part) {
|
|
661
668
|
// Rebuild Union on original tree as Condition
|
|
662
|
-
buildNode.value = { param: `%__${rule.part}__
|
|
669
|
+
buildNode.value = { param: `%__${rule.part}__%`, param_is_deep: false };
|
|
663
670
|
if (rule.part == partStack.at(-1).i) {
|
|
664
671
|
// debugLog.push('⊙ [part] ' + rule.part);
|
|
665
672
|
orderedParts.push(parts[rule.part]);
|
|
@@ -24,7 +24,10 @@ 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>[], param_templates?: Record<string, string>[], view?: $BucketView,
|
|
27
|
+
run(trx: AnyTrxNode, query: NQL_CompiledQuery, pagination?: NQL_Pagination, params?: Record<string, any>[], param_templates?: Record<string, string>[], view?: $BucketView, customBuckets?: Record<string, {
|
|
28
|
+
scope: string;
|
|
29
|
+
nql: NQLRunner;
|
|
30
|
+
}>): Promise<NQL_Result>;
|
|
28
31
|
linkExternal(bucket: AnyBucket): void;
|
|
29
32
|
}
|
|
30
33
|
export {};
|
|
@@ -23,7 +23,7 @@ class NQL_Engine {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
-
async run(trx, query, pagination, params = [{}], param_templates = [], view,
|
|
26
|
+
async run(trx, query, pagination, params = [{}], param_templates = [], view, customBuckets) {
|
|
27
27
|
if (!params.length)
|
|
28
28
|
params = [{}];
|
|
29
29
|
if (!param_templates.length)
|
|
@@ -35,10 +35,8 @@ class NQL_Engine {
|
|
|
35
35
|
const part_i = query.execOrder[i];
|
|
36
36
|
const part = query.parts[part_i];
|
|
37
37
|
// Run part
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
: this.runners;
|
|
41
|
-
const _runner = runners[part.union.meta.scope];
|
|
38
|
+
const _runner = Object.values(customBuckets || {}).find(b => b.scope === part.union.meta.scope)?.nql
|
|
39
|
+
|| this.runners[part.union.meta.scope];
|
|
42
40
|
const out = await _runner.run(trx, part, params, param_templates, pagination, view);
|
|
43
41
|
result = out;
|
|
44
42
|
// Part failed, return
|
|
@@ -70,6 +70,7 @@ export declare class MessageTemplateFieldBuilder<Module extends $Module, Message
|
|
|
70
70
|
private _required;
|
|
71
71
|
private _defaultValue?;
|
|
72
72
|
private _nullable;
|
|
73
|
+
private _rawName?;
|
|
73
74
|
private _rules;
|
|
74
75
|
constructor(type: $MessageTemplateFieldType, meta: Omit<$MessageTemplateFieldMeta, 'enum' | 'msg' | 'id'> & {
|
|
75
76
|
enum?: {
|
|
@@ -97,6 +98,7 @@ export declare class MessageTemplateFieldBuilder<Module extends $Module, Message
|
|
|
97
98
|
], InputSuffix>;
|
|
98
99
|
get nullable(): MessageTemplateFieldBuilder<Module, Message, Input | null, Output | null, Children, Optional, InputSuffix>;
|
|
99
100
|
rule(rule: MessageTemplateRuleDef<Output, Message['#raw']>): this;
|
|
101
|
+
rawName(name: string): this;
|
|
100
102
|
static build(builder: AnyMessageTemplateFieldBuilder, name: string, tree: ModuleTree, module: $Module, basePathRaw: string, basePathParsed: string): $MessageTemplateField;
|
|
101
103
|
static buildMany(fields: MessageTemplateFieldBuilders, tree: ModuleTree, module: $Module, basePathRaw?: string, basePathParsed?: string, name?: string, key?: string): $MessageTemplateFields;
|
|
102
104
|
}
|
|
@@ -138,6 +138,7 @@ class MessageTemplateFieldBuilder {
|
|
|
138
138
|
_required = true;
|
|
139
139
|
_defaultValue = undefined;
|
|
140
140
|
_nullable = false;
|
|
141
|
+
_rawName;
|
|
141
142
|
_rules = [];
|
|
142
143
|
constructor(type, meta, alias, children) {
|
|
143
144
|
this.type = type;
|
|
@@ -166,6 +167,10 @@ class MessageTemplateFieldBuilder {
|
|
|
166
167
|
this._rules.push(rule);
|
|
167
168
|
return this;
|
|
168
169
|
}
|
|
170
|
+
rawName(name) {
|
|
171
|
+
this._rawName = name;
|
|
172
|
+
return this;
|
|
173
|
+
}
|
|
169
174
|
// Build
|
|
170
175
|
static build(builder, name, tree, module, basePathRaw, basePathParsed) {
|
|
171
176
|
const pathRaw = basePathRaw + (builder.type === 'id' ? `${name}_id` : name);
|
package/lib/engine/daemon.d.ts
CHANGED
|
@@ -123,10 +123,29 @@ export declare class DaemonTrx<S extends $Space, M extends $Module, AuthUsers ex
|
|
|
123
123
|
* authenticate this transaction prior to running.
|
|
124
124
|
*/
|
|
125
125
|
private tokens?;
|
|
126
|
+
/**
|
|
127
|
+
*
|
|
128
|
+
*/
|
|
129
|
+
private _origin?;
|
|
130
|
+
/**
|
|
131
|
+
* An idempotent transaction doesn't generate a commit/rollback.
|
|
132
|
+
*/
|
|
133
|
+
private _idempotent;
|
|
126
134
|
/**
|
|
127
135
|
* @param trxEngine The transaction engine where to run the transaction.
|
|
128
136
|
*/
|
|
129
137
|
constructor(trxEngine: AnyTrxEngine);
|
|
138
|
+
origin(origin: string): this;
|
|
139
|
+
/**
|
|
140
|
+
* Flags this transaction as idempotent.
|
|
141
|
+
* This means its not stored, neither commited/rolled back.
|
|
142
|
+
* This should generally be used for readonly transactions.
|
|
143
|
+
*/
|
|
144
|
+
get idempotent(): this;
|
|
145
|
+
/**
|
|
146
|
+
* Inherit authentication from another transaction node.
|
|
147
|
+
*/
|
|
148
|
+
idempotent_inherit(trx: AnyTrxNode): this;
|
|
130
149
|
/**
|
|
131
150
|
* Inherit authentication from another transaction node.
|
|
132
151
|
*/
|
package/lib/engine/daemon.js
CHANGED
|
@@ -176,12 +176,40 @@ class DaemonTrx {
|
|
|
176
176
|
* authenticate this transaction prior to running.
|
|
177
177
|
*/
|
|
178
178
|
tokens;
|
|
179
|
+
/**
|
|
180
|
+
*
|
|
181
|
+
*/
|
|
182
|
+
_origin;
|
|
183
|
+
/**
|
|
184
|
+
* An idempotent transaction doesn't generate a commit/rollback.
|
|
185
|
+
*/
|
|
186
|
+
_idempotent = false;
|
|
179
187
|
/**
|
|
180
188
|
* @param trxEngine The transaction engine where to run the transaction.
|
|
181
189
|
*/
|
|
182
190
|
constructor(trxEngine) {
|
|
183
191
|
this.trxEngine = trxEngine;
|
|
184
192
|
}
|
|
193
|
+
origin(origin) {
|
|
194
|
+
this._origin = origin;
|
|
195
|
+
return this;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Flags this transaction as idempotent.
|
|
199
|
+
* This means its not stored, neither commited/rolled back.
|
|
200
|
+
* This should generally be used for readonly transactions.
|
|
201
|
+
*/
|
|
202
|
+
get idempotent() {
|
|
203
|
+
this._idempotent = true;
|
|
204
|
+
return this;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Inherit authentication from another transaction node.
|
|
208
|
+
*/
|
|
209
|
+
idempotent_inherit(trx) {
|
|
210
|
+
this._idempotent = trx.trx.idempotent;
|
|
211
|
+
return this;
|
|
212
|
+
}
|
|
185
213
|
/**
|
|
186
214
|
* Inherit authentication from another transaction node.
|
|
187
215
|
*/
|
|
@@ -211,7 +239,7 @@ class DaemonTrx {
|
|
|
211
239
|
...this.tokens
|
|
212
240
|
};
|
|
213
241
|
const users = inheritedAuth?.users;
|
|
214
|
-
return this.trxEngine.trx(fn, id, tokens, users);
|
|
242
|
+
return this.trxEngine.trx(fn, id, tokens, users, this._origin, this._idempotent);
|
|
215
243
|
}
|
|
216
244
|
/**
|
|
217
245
|
* Run a method inside the transaction, and hold it until
|
|
@@ -220,13 +248,23 @@ class DaemonTrx {
|
|
|
220
248
|
* @param fn A function to execute inside the transaction
|
|
221
249
|
* @returns A `TrxStatus` containing metadata about the transaction and the function response
|
|
222
250
|
*/
|
|
223
|
-
run_and_hold(fn, id) {
|
|
251
|
+
async run_and_hold(fn, id) {
|
|
224
252
|
const inheritedAuth = this._inherit.auth;
|
|
225
253
|
const tokens = {
|
|
226
254
|
...inheritedAuth?.tokens,
|
|
227
255
|
...this.tokens
|
|
228
256
|
};
|
|
229
257
|
const users = inheritedAuth?.users;
|
|
258
|
+
// Idempotent transactions are not commited/rolled back, so they don't need to be held.
|
|
259
|
+
if (this._idempotent) {
|
|
260
|
+
const status = await this.trxEngine.trx(fn, id, tokens, users, this._origin, this._idempotent);
|
|
261
|
+
return {
|
|
262
|
+
id: status.id,
|
|
263
|
+
status,
|
|
264
|
+
commit: () => Promise.resolve(),
|
|
265
|
+
rollback: () => Promise.resolve(),
|
|
266
|
+
};
|
|
267
|
+
}
|
|
230
268
|
return this.trxEngine.trx_hold(fn, id, tokens, users);
|
|
231
269
|
}
|
|
232
270
|
}
|
|
@@ -13,7 +13,6 @@ export declare class Tree {
|
|
|
13
13
|
*
|
|
14
14
|
* @deprecated Fieldpath was consolidated into Modelpath and Querypath.
|
|
15
15
|
*/
|
|
16
|
-
static get(obj: Record<string, any>, fieldpath: string
|
|
17
|
-
static getModelpath(obj: Record<string, any>, modelpath: string, index: (string | number)[]): any[];
|
|
16
|
+
static get(obj: Record<string, any>, fieldpath: string): any;
|
|
18
17
|
static set(obj: Record<string, any>, fieldpath: string, replacer: (v: any, i: (number | string)[]) => any, __index?: (number | string)[]): void;
|
|
19
18
|
}
|