nesoi 3.4.0 → 3.4.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.
- package/lib/compiler/elements/bucket.element.js +3 -3
- package/lib/compiler/typescript/bridge/extract.js +1 -1
- package/lib/compiler/typescript/bridge/organize.js +3 -3
- package/lib/elements/entities/bucket/adapters/memory.nql.js +12 -18
- package/lib/elements/entities/bucket/bucket.d.ts +6 -2
- package/lib/elements/entities/bucket/bucket.js +4 -4
- package/lib/elements/entities/bucket/graph/bucket_graph.js +13 -3
- package/lib/elements/entities/bucket/model/bucket_model.convert.js +9 -17
- package/lib/elements/entities/bucket/model/bucket_model.d.ts +6 -1
- package/lib/elements/entities/bucket/model/bucket_model.js +182 -33
- package/lib/elements/entities/bucket/model/bucket_model.schema.d.ts +1 -1
- package/lib/elements/entities/bucket/model/bucket_model.schema.js +2 -2
- package/lib/elements/entities/bucket/query/nql.schema.d.ts +1 -0
- package/lib/elements/entities/bucket/query/nql_compiler.js +5 -4
- package/lib/elements/entities/bucket/query/nql_engine.js +0 -2
- package/lib/elements/entities/bucket/view/bucket_view.d.ts +5 -4
- package/lib/elements/entities/bucket/view/bucket_view.js +300 -188
- package/lib/elements/entities/bucket/view/bucket_view.schema.d.ts +5 -3
- package/lib/elements/entities/bucket/view/bucket_view.schema.js +3 -1
- package/lib/elements/entities/bucket/view/bucket_view_field.builder.d.ts +16 -5
- package/lib/elements/entities/bucket/view/bucket_view_field.builder.js +86 -24
- package/lib/engine/data/error.d.ts +12 -0
- package/lib/engine/data/error.js +12 -0
- package/lib/engine/transaction/nodes/bucket.trx_node.d.ts +6 -2
- package/lib/engine/transaction/nodes/bucket.trx_node.js +4 -4
- package/lib/engine/transaction/nodes/external.trx_node.d.ts +4 -1
- package/lib/engine/transaction/nodes/external.trx_node.js +5 -2
- package/lib/engine/transaction/nodes/job.trx_node.js +0 -1
- package/lib/engine/transaction/trx_engine.js +8 -10
- package/package.json +1 -1
- package/tools/joaquin/bucket.d.ts +6 -2
- package/tools/joaquin/bucket.js +4 -4
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -206,9 +206,9 @@ class BucketElement extends element_1.Element {
|
|
|
206
206
|
for (const key in fields) {
|
|
207
207
|
const field = fields[key];
|
|
208
208
|
if (field.scope === 'model' && 'model' in field.meta) {
|
|
209
|
-
const modelFields = bucket_model_schema_1.$BucketModel.
|
|
209
|
+
const modelFields = bucket_model_schema_1.$BucketModel.getFields(this.schema.model, field.meta.model.path);
|
|
210
210
|
const types = [];
|
|
211
|
-
if (!field.children || '
|
|
211
|
+
if (!field.children || '__root' in field.children) {
|
|
212
212
|
types.push(dump_helpers_1.DumpHelpers.dumpUnionType(modelFields.map(f => this.buildModelFieldType(f))));
|
|
213
213
|
}
|
|
214
214
|
// Contains children
|
|
@@ -238,7 +238,7 @@ class BucketElement extends element_1.Element {
|
|
|
238
238
|
return data;
|
|
239
239
|
};
|
|
240
240
|
const data = {};
|
|
241
|
-
if ('
|
|
241
|
+
if ('__root' in schema) {
|
|
242
242
|
Object.assign(data, model);
|
|
243
243
|
}
|
|
244
244
|
const viewData = buildFields(schema);
|
|
@@ -99,7 +99,7 @@ class TSBridgeExtract {
|
|
|
99
99
|
expectedKinds: [ts.SyntaxKind.FunctionExpression, ts.SyntaxKind.ArrowFunction, ts.SyntaxKind.Identifier, ts.SyntaxKind.CallExpression]
|
|
100
100
|
}));
|
|
101
101
|
functions.push(...tsCompiler.query(node.filepath, {
|
|
102
|
-
query: 'bucket.*.view.1.return.**.
|
|
102
|
+
query: 'bucket.*.view.1.return.**.transform.0',
|
|
103
103
|
expectedKinds: [ts.SyntaxKind.FunctionExpression, ts.SyntaxKind.ArrowFunction, ts.SyntaxKind.Identifier, ts.SyntaxKind.CallExpression]
|
|
104
104
|
}));
|
|
105
105
|
functions.push(...tsCompiler.query(node.filepath, {
|
|
@@ -54,9 +54,9 @@ class TSBridgeOrganize {
|
|
|
54
54
|
organized.buckets[tag].views[view].computed[prop] = node;
|
|
55
55
|
return;
|
|
56
56
|
}
|
|
57
|
-
const
|
|
58
|
-
if (
|
|
59
|
-
const [_, view, prop] =
|
|
57
|
+
const viewTransform = path.match(/view▹(\w+)▹1▹return▹([\w|\\.]+)▹transform▹0/);
|
|
58
|
+
if (viewTransform) {
|
|
59
|
+
const [_, view, prop] = viewTransform;
|
|
60
60
|
organized.buckets[tag] ??= { views: {}, tenancy: {} };
|
|
61
61
|
organized.buckets[tag].views[view] ??= { computed: {}, chain: {} };
|
|
62
62
|
organized.buckets[tag].views[view].chain[prop] = node;
|
|
@@ -172,26 +172,15 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
|
|
|
172
172
|
};
|
|
173
173
|
const _rule = (rule, objs, params, param_templates) => {
|
|
174
174
|
const out = {};
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
if (param_templates.length) {
|
|
178
|
-
for (const template of param_templates) {
|
|
179
|
-
combos.push({ params: param, param_template: template });
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
else {
|
|
183
|
-
combos.push({ params: param, param_template: {} });
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
for (const combo of combos) {
|
|
187
|
-
const match = _index(rule, objs, combo.params, combo.param_template);
|
|
175
|
+
for (let i = 0; i < params.length; i++) {
|
|
176
|
+
const match = _index(rule, objs, params[i], param_templates[i] ?? {});
|
|
188
177
|
if (match) {
|
|
189
178
|
Object.assign(out, match);
|
|
190
179
|
continue;
|
|
191
180
|
}
|
|
192
181
|
for (const id in objs) {
|
|
193
182
|
const obj = objs[id];
|
|
194
|
-
let match = _obj(rule, obj,
|
|
183
|
+
let match = _obj(rule, obj, params[i], param_templates[i] ?? {});
|
|
195
184
|
if (rule.not) {
|
|
196
185
|
match = !match;
|
|
197
186
|
}
|
|
@@ -235,11 +224,16 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
|
|
|
235
224
|
}
|
|
236
225
|
}
|
|
237
226
|
else if ('param_with_$' in rule.value) {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
227
|
+
if (Object.keys(param_template).length) {
|
|
228
|
+
let path = rule.value.param_with_$;
|
|
229
|
+
for (const key in param_template) {
|
|
230
|
+
path = path.replace(new RegExp(key.replace('$', '\\$'), 'g'), param_template[key]);
|
|
231
|
+
}
|
|
232
|
+
queryValue = tree_1.Tree.get(params, path);
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
queryValue = undefined;
|
|
241
236
|
}
|
|
242
|
-
queryValue = tree_1.Tree.get(params, path);
|
|
243
237
|
}
|
|
244
238
|
else if ('static' in rule.value) {
|
|
245
239
|
queryValue = rule.value.static;
|
|
@@ -133,11 +133,15 @@ export declare class Bucket<M extends $Module, $ extends $Bucket> {
|
|
|
133
133
|
/**
|
|
134
134
|
* Build one object with a view
|
|
135
135
|
*/
|
|
136
|
-
buildOne<V extends ViewName<$>, Obj extends ViewObj<$, V>>(trx: AnyTrxNode, obj: $['#data'], view: V
|
|
136
|
+
buildOne<V extends ViewName<$>, Obj extends ViewObj<$, V>>(trx: AnyTrxNode, obj: $['#data'], view: V, flags?: {
|
|
137
|
+
serialize: boolean;
|
|
138
|
+
}): Promise<Obj>;
|
|
137
139
|
/**
|
|
138
140
|
* Build a list ob objects with a view
|
|
139
141
|
*/
|
|
140
|
-
buildMany<V extends ViewName<$>, Obj extends ViewObj<$, V>>(trx: AnyTrxNode, objs: $['#data'][], view: V
|
|
142
|
+
buildMany<V extends ViewName<$>, Obj extends ViewObj<$, V>>(trx: AnyTrxNode, objs: $['#data'][], view: V, flags?: {
|
|
143
|
+
serialize: boolean;
|
|
144
|
+
}): Promise<Obj[]>;
|
|
141
145
|
/**
|
|
142
146
|
* Create an entity
|
|
143
147
|
*/
|
|
@@ -304,20 +304,20 @@ class Bucket {
|
|
|
304
304
|
/**
|
|
305
305
|
* Build one object with a view
|
|
306
306
|
*/
|
|
307
|
-
async buildOne(trx, obj, view) {
|
|
307
|
+
async buildOne(trx, obj, view, flags) {
|
|
308
308
|
if (!(view in this.views)) {
|
|
309
309
|
throw error_1.NesoiError.Bucket.ViewNotFound({ bucket: this.schema.alias, view: view });
|
|
310
310
|
}
|
|
311
|
-
return this.views[view].parse(trx, obj);
|
|
311
|
+
return this.views[view].parse(trx, obj, flags);
|
|
312
312
|
}
|
|
313
313
|
/**
|
|
314
314
|
* Build a list ob objects with a view
|
|
315
315
|
*/
|
|
316
|
-
async buildMany(trx, objs, view) {
|
|
316
|
+
async buildMany(trx, objs, view, flags) {
|
|
317
317
|
if (!(view in this.views)) {
|
|
318
318
|
throw error_1.NesoiError.Bucket.ViewNotFound({ bucket: this.schema.alias, view: view });
|
|
319
319
|
}
|
|
320
|
-
return this.views[view].parseMany(trx, objs);
|
|
320
|
+
return this.views[view].parseMany(trx, objs, flags);
|
|
321
321
|
}
|
|
322
322
|
// Create
|
|
323
323
|
/**
|
|
@@ -94,6 +94,14 @@ class BucketGraph {
|
|
|
94
94
|
* - `no_tenancy`: Don't apply tenancy rules (default: `false`)
|
|
95
95
|
*/
|
|
96
96
|
async readManyLinks(trx, objs, link, options) {
|
|
97
|
+
// Optimization
|
|
98
|
+
if (objs.length <= 1) {
|
|
99
|
+
const result = await this.readLink(trx, objs[0], {
|
|
100
|
+
name: link.name,
|
|
101
|
+
index: link.indexes[0] ?? []
|
|
102
|
+
}, options);
|
|
103
|
+
return [result];
|
|
104
|
+
}
|
|
97
105
|
log_1.Log.trace('bucket', this.bucketName, `Read link ${link.name}`);
|
|
98
106
|
const schema = this.schema.links[link.name];
|
|
99
107
|
// 1st Query
|
|
@@ -150,17 +158,19 @@ class BucketGraph {
|
|
|
150
158
|
}
|
|
151
159
|
},
|
|
152
160
|
});
|
|
153
|
-
for (
|
|
161
|
+
for (let i = 0; i < objs.length; i++) {
|
|
154
162
|
let result;
|
|
163
|
+
const param = [{ ...objs[i] }];
|
|
164
|
+
const param_template = param_templates ? [param_templates[i]] : [];
|
|
155
165
|
if (tempAdapter instanceof bucket_cache_1.BucketCache) {
|
|
156
166
|
result = await tempAdapter._queryCompiled(trx, compiled, {
|
|
157
167
|
perPage: schema.many ? undefined : 1,
|
|
158
|
-
},
|
|
168
|
+
}, param, param_template);
|
|
159
169
|
}
|
|
160
170
|
else {
|
|
161
171
|
result = await tempAdapter._queryCompiled(trx, compiled, {
|
|
162
172
|
perPage: schema.many ? undefined : 1,
|
|
163
|
-
},
|
|
173
|
+
}, param, param_template, undefined, {
|
|
164
174
|
module: schema.bucket.module,
|
|
165
175
|
buckets: {
|
|
166
176
|
[schema.bucket.short]: {
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.convertToView = convertToView;
|
|
4
4
|
exports.convertToMessage = convertToMessage;
|
|
5
|
-
const bucket_view_builder_1 = require("../view/bucket_view.builder");
|
|
6
5
|
const bucket_view_schema_1 = require("../view/bucket_view.schema");
|
|
7
6
|
const message_template_schema_1 = require("../../message/template/message_template.schema");
|
|
8
7
|
const bucket_graph_schema_1 = require("../graph/bucket_graph.schema");
|
|
@@ -13,22 +12,15 @@ const message_schema_1 = require("../../message/message.schema");
|
|
|
13
12
|
* @subcategory Entity
|
|
14
13
|
* */
|
|
15
14
|
function convertToView(model, name, fields = model.fields, path, depth = 0) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const graph = new bucket_graph_schema_1.$BucketGraph();
|
|
26
|
-
viewFields[f] = bucket_view_field_builder_1.BucketViewFieldBuilder.build(builder, model, graph, {}, field.name, depth);
|
|
27
|
-
}
|
|
28
|
-
return viewFields;
|
|
29
|
-
};
|
|
30
|
-
const v = new bucket_view_schema_1.$BucketView(name, convertFields(fields));
|
|
31
|
-
return v;
|
|
15
|
+
return new bucket_view_schema_1.$BucketView(name, Object.fromEntries(Object.entries(fields).map(([model_key, model_field]) => {
|
|
16
|
+
const $ = new bucket_view_field_builder_1.BucketViewFieldFactory();
|
|
17
|
+
const key = (path ? path + '.' : '')
|
|
18
|
+
+ model_field.name;
|
|
19
|
+
const builder = $.model(key);
|
|
20
|
+
const graph = new bucket_graph_schema_1.$BucketGraph();
|
|
21
|
+
const view_field = bucket_view_field_builder_1.BucketViewFieldBuilder.build(builder, model, graph, {}, model_field.name, depth);
|
|
22
|
+
return [model_key, view_field];
|
|
23
|
+
})));
|
|
32
24
|
}
|
|
33
25
|
/**
|
|
34
26
|
* @category Elements
|
|
@@ -7,6 +7,11 @@ type BucketModelCopyCmd = {
|
|
|
7
7
|
copy: Record<string, any>;
|
|
8
8
|
path: string;
|
|
9
9
|
depth: number;
|
|
10
|
+
modelpath?: {
|
|
11
|
+
i: number;
|
|
12
|
+
asterisk_values: string[];
|
|
13
|
+
};
|
|
14
|
+
is_union_option?: boolean | 'last';
|
|
10
15
|
};
|
|
11
16
|
/**
|
|
12
17
|
* @category Elements
|
|
@@ -17,6 +22,6 @@ export declare class BucketModel<M extends $Module, $ extends $Bucket> {
|
|
|
17
22
|
private alias;
|
|
18
23
|
private schema;
|
|
19
24
|
constructor(bucket: $Bucket, config?: BucketAdapterConfig | undefined);
|
|
20
|
-
copy<T extends Record<string, any>>(obj: T, op: 'save' | 'load', serialize?: (cmd?: BucketModelCopyCmd) => boolean): T;
|
|
25
|
+
copy<T extends Record<string, any>>(obj: T, op: 'save' | 'load', serialize?: (cmd?: BucketModelCopyCmd) => boolean, modelpath?: string): T;
|
|
21
26
|
}
|
|
22
27
|
export {};
|
|
@@ -19,7 +19,7 @@ class BucketModel {
|
|
|
19
19
|
this.alias = bucket.alias;
|
|
20
20
|
this.schema = bucket.model;
|
|
21
21
|
}
|
|
22
|
-
copy(obj, op, serialize) {
|
|
22
|
+
copy(obj, op, serialize, modelpath) {
|
|
23
23
|
const meta = this.config?.meta || {
|
|
24
24
|
created_at: 'created_at',
|
|
25
25
|
created_by: 'created_by',
|
|
@@ -27,65 +27,170 @@ class BucketModel {
|
|
|
27
27
|
updated_by: 'updated_by',
|
|
28
28
|
};
|
|
29
29
|
const copy = {};
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
const modelpath_results = [];
|
|
31
|
+
const paths = modelpath?.split('.');
|
|
32
|
+
let poll = paths
|
|
33
|
+
// Specific modelpath requested, start with root field only
|
|
34
|
+
? [{
|
|
35
|
+
path: paths[0],
|
|
36
|
+
obj,
|
|
37
|
+
copy,
|
|
38
|
+
field: this.schema.fields[paths[0]],
|
|
39
|
+
depth: 0,
|
|
40
|
+
modelpath: { i: 0, asterisk_values: [] }
|
|
41
|
+
}]
|
|
42
|
+
// No modelpath, use all fields
|
|
43
|
+
: Object.entries(this.schema.fields).map(([path, field]) => ({
|
|
44
|
+
path, obj, copy, field, depth: 0
|
|
45
|
+
}));
|
|
33
46
|
while (poll.length) {
|
|
34
47
|
const next = [];
|
|
35
48
|
for (const entry of poll) {
|
|
49
|
+
if (entry.is_union_option) {
|
|
50
|
+
const alreadyParsed = entry.copy[entry.path] !== undefined;
|
|
51
|
+
if (alreadyParsed)
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
36
54
|
const val = entry.obj[entry.path];
|
|
37
55
|
if (val === undefined) {
|
|
56
|
+
delete entry.copy[entry.path];
|
|
38
57
|
continue;
|
|
39
58
|
}
|
|
40
59
|
if (val === null) {
|
|
41
|
-
entry.copy[entry.path]
|
|
60
|
+
delete entry.copy[entry.path];
|
|
42
61
|
continue;
|
|
43
62
|
}
|
|
63
|
+
const isLeafPath = entry.modelpath
|
|
64
|
+
? entry.modelpath.i === (paths?.length ?? 0) - 1
|
|
65
|
+
: false;
|
|
66
|
+
const nextPath = (!entry.modelpath || isLeafPath)
|
|
67
|
+
? undefined
|
|
68
|
+
: paths[entry.modelpath.i + 1];
|
|
69
|
+
const addChildrenToQueue = !entry.modelpath
|
|
70
|
+
|| entry.modelpath.i >= (paths.length - 1)
|
|
71
|
+
|| nextPath === '*';
|
|
44
72
|
if (entry.field.type === 'list') {
|
|
45
73
|
if (!Array.isArray(val))
|
|
46
74
|
continue;
|
|
47
75
|
entry.copy[entry.path] = [];
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
76
|
+
// Leaf path or no modelpath = add entire list to queue
|
|
77
|
+
if (addChildrenToQueue) {
|
|
78
|
+
next.push(...val.map((_, i) => ({
|
|
79
|
+
path: i.toString(),
|
|
80
|
+
obj: val,
|
|
81
|
+
copy: entry.copy[entry.path],
|
|
82
|
+
field: entry.field.children['#'],
|
|
83
|
+
depth: entry.depth + 1,
|
|
84
|
+
modelpath: entry.modelpath ? {
|
|
85
|
+
i: entry.modelpath.i + 1,
|
|
86
|
+
asterisk_values: [...entry.modelpath.asterisk_values, ...(nextPath === '*' ? [i.toString()] : [])]
|
|
87
|
+
} : undefined
|
|
88
|
+
})));
|
|
89
|
+
}
|
|
90
|
+
// Branch path = add next path to queue
|
|
91
|
+
else {
|
|
92
|
+
next.push({
|
|
93
|
+
path: nextPath,
|
|
94
|
+
obj: val,
|
|
95
|
+
copy: entry.copy[entry.path],
|
|
96
|
+
field: entry.field.children['#'],
|
|
97
|
+
depth: entry.depth + 1,
|
|
98
|
+
modelpath: entry.modelpath ? {
|
|
99
|
+
i: entry.modelpath.i + 1,
|
|
100
|
+
asterisk_values: entry.modelpath.asterisk_values
|
|
101
|
+
} : undefined
|
|
102
|
+
});
|
|
103
|
+
}
|
|
55
104
|
}
|
|
56
105
|
else if (entry.field.type === 'dict') {
|
|
57
106
|
if (typeof val !== 'object' || Array.isArray(val))
|
|
58
107
|
continue;
|
|
59
108
|
entry.copy[entry.path] = {};
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
109
|
+
// Leaf path or no modelpath = add entire dict to queue
|
|
110
|
+
if (addChildrenToQueue) {
|
|
111
|
+
next.push(...Object.keys(val).map((path) => ({
|
|
112
|
+
path,
|
|
113
|
+
obj: val,
|
|
114
|
+
copy: entry.copy[entry.path],
|
|
115
|
+
field: entry.field.children['#'],
|
|
116
|
+
depth: entry.depth + 1,
|
|
117
|
+
modelpath: entry.modelpath ? {
|
|
118
|
+
i: entry.modelpath.i + 1,
|
|
119
|
+
asterisk_values: [...entry.modelpath.asterisk_values, ...(nextPath === '*' ? [path] : [])]
|
|
120
|
+
} : undefined
|
|
121
|
+
})));
|
|
122
|
+
}
|
|
123
|
+
// Branch path = add next path to queue
|
|
124
|
+
else {
|
|
125
|
+
next.push({
|
|
126
|
+
path: nextPath,
|
|
127
|
+
obj: val,
|
|
128
|
+
copy: entry.copy[entry.path],
|
|
129
|
+
field: entry.field.children['#'],
|
|
130
|
+
depth: entry.depth + 1,
|
|
131
|
+
modelpath: entry.modelpath ? {
|
|
132
|
+
i: entry.modelpath.i + 1,
|
|
133
|
+
asterisk_values: entry.modelpath.asterisk_values
|
|
134
|
+
} : undefined
|
|
135
|
+
});
|
|
136
|
+
}
|
|
67
137
|
}
|
|
68
138
|
else if (entry.field.type === 'obj') {
|
|
69
139
|
if (typeof val !== 'object' || Array.isArray(val))
|
|
70
140
|
continue;
|
|
141
|
+
// disambiguate between dict and obj when obj comes first
|
|
142
|
+
// on a union
|
|
143
|
+
const objectHasValidFields = Object.keys(val).some(key => key in entry.field.children);
|
|
144
|
+
if (!objectHasValidFields)
|
|
145
|
+
continue;
|
|
71
146
|
entry.copy[entry.path] = {};
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
147
|
+
// Leaf path or no modelpath = add entire dict to queue
|
|
148
|
+
if (addChildrenToQueue) {
|
|
149
|
+
next.push(...Object.keys(entry.field.children).map(path => ({
|
|
150
|
+
path: path,
|
|
151
|
+
obj: val,
|
|
152
|
+
copy: entry.copy[entry.path],
|
|
153
|
+
field: entry.field.children[path],
|
|
154
|
+
depth: entry.depth + 1,
|
|
155
|
+
modelpath: entry.modelpath ? {
|
|
156
|
+
i: entry.modelpath.i + 1,
|
|
157
|
+
asterisk_values: [...entry.modelpath.asterisk_values, ...(nextPath === '*' ? [path] : [])]
|
|
158
|
+
} : undefined
|
|
159
|
+
})));
|
|
160
|
+
}
|
|
161
|
+
// Branch path = add next path to queue
|
|
162
|
+
else {
|
|
163
|
+
next.push({
|
|
164
|
+
path: nextPath,
|
|
165
|
+
obj: val,
|
|
166
|
+
copy: entry.copy[entry.path],
|
|
167
|
+
field: entry.field.children[nextPath],
|
|
168
|
+
depth: entry.depth + 1,
|
|
169
|
+
modelpath: entry.modelpath ? {
|
|
170
|
+
i: entry.modelpath.i + 1,
|
|
171
|
+
asterisk_values: entry.modelpath.asterisk_values
|
|
172
|
+
} : undefined
|
|
173
|
+
});
|
|
174
|
+
}
|
|
79
175
|
}
|
|
80
176
|
else if (entry.field.type === 'union') {
|
|
81
|
-
|
|
82
|
-
|
|
177
|
+
const options = Object.entries(entry.field.children);
|
|
178
|
+
// Add union options to queue with flag
|
|
179
|
+
// This flag avoids reparsing a value if an earlier option already did it
|
|
180
|
+
next.push(...options.map(([_, option], i) => ({
|
|
181
|
+
...entry,
|
|
182
|
+
field: option,
|
|
183
|
+
is_union_option: i === options.length - 1 ? 'last' : true
|
|
184
|
+
})));
|
|
185
|
+
continue;
|
|
83
186
|
}
|
|
84
187
|
else if (entry.field.type === 'enum') {
|
|
85
188
|
const v = entry.obj[entry.path];
|
|
86
189
|
const options = entry.field.meta.enum.options;
|
|
87
190
|
if (!(v in options)) {
|
|
88
|
-
|
|
191
|
+
if (entry.is_union_option !== true) {
|
|
192
|
+
throw error_1.NesoiError.Bucket.Model.InvalidEnum({ bucket: this.alias, value: v, options: Object.keys(options) });
|
|
193
|
+
}
|
|
89
194
|
}
|
|
90
195
|
entry.copy[entry.path] = entry.obj[entry.path];
|
|
91
196
|
}
|
|
@@ -97,7 +202,10 @@ class BucketModel {
|
|
|
97
202
|
entry.copy[entry.path] = date_1.NesoiDate.fromISO(v);
|
|
98
203
|
}
|
|
99
204
|
catch {
|
|
100
|
-
|
|
205
|
+
if (entry.is_union_option !== true) {
|
|
206
|
+
throw error_1.NesoiError.Bucket.Model.InvalidISODate({ bucket: this.alias, value: v });
|
|
207
|
+
}
|
|
208
|
+
continue;
|
|
101
209
|
}
|
|
102
210
|
}
|
|
103
211
|
else if (op === 'save') {
|
|
@@ -105,7 +213,10 @@ class BucketModel {
|
|
|
105
213
|
entry.copy[entry.path] = v.toISO();
|
|
106
214
|
}
|
|
107
215
|
catch {
|
|
108
|
-
|
|
216
|
+
if (entry.is_union_option !== true) {
|
|
217
|
+
throw error_1.NesoiError.Bucket.Model.InvalidNesoiDate({ bucket: this.alias, value: v });
|
|
218
|
+
}
|
|
219
|
+
continue;
|
|
109
220
|
}
|
|
110
221
|
}
|
|
111
222
|
}
|
|
@@ -121,7 +232,10 @@ class BucketModel {
|
|
|
121
232
|
entry.copy[entry.path] = datetime_1.NesoiDatetime.fromISO(v);
|
|
122
233
|
}
|
|
123
234
|
catch {
|
|
124
|
-
|
|
235
|
+
if (entry.is_union_option !== true) {
|
|
236
|
+
throw error_1.NesoiError.Bucket.Model.InvalidISODatetime({ bucket: this.alias, value: v });
|
|
237
|
+
}
|
|
238
|
+
continue;
|
|
125
239
|
}
|
|
126
240
|
}
|
|
127
241
|
else if (op === 'save') {
|
|
@@ -129,7 +243,10 @@ class BucketModel {
|
|
|
129
243
|
entry.copy[entry.path] = v.toISO();
|
|
130
244
|
}
|
|
131
245
|
catch {
|
|
132
|
-
|
|
246
|
+
if (entry.is_union_option !== true) {
|
|
247
|
+
throw error_1.NesoiError.Bucket.Model.InvalidNesoiDatetime({ bucket: this.alias, value: v });
|
|
248
|
+
}
|
|
249
|
+
continue;
|
|
133
250
|
}
|
|
134
251
|
}
|
|
135
252
|
}
|
|
@@ -141,30 +258,60 @@ class BucketModel {
|
|
|
141
258
|
const meta = entry.field.meta.decimal;
|
|
142
259
|
const v = entry.obj[entry.path];
|
|
143
260
|
if (serialize?.(entry)) {
|
|
261
|
+
if ((op === 'load' && typeof v !== 'string') || (op === 'save' && !(v instanceof decimal_1.NesoiDecimal))) {
|
|
262
|
+
if (entry.is_union_option !== true) {
|
|
263
|
+
throw error_1.NesoiError.Bucket.Model.InvalidNesoiDecimal({ bucket: this.alias, value: v });
|
|
264
|
+
}
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
144
267
|
if (op === 'load')
|
|
145
268
|
entry.copy[entry.path] = new decimal_1.NesoiDecimal(v, meta?.left, meta?.right);
|
|
146
269
|
if (op === 'save')
|
|
147
270
|
entry.copy[entry.path] = v.toString();
|
|
148
271
|
}
|
|
149
272
|
else {
|
|
273
|
+
if (!(v instanceof decimal_1.NesoiDecimal)) {
|
|
274
|
+
if (entry.is_union_option !== true) {
|
|
275
|
+
throw error_1.NesoiError.Bucket.Model.InvalidNesoiDecimal({ bucket: this.alias, value: v });
|
|
276
|
+
}
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
150
279
|
entry.copy[entry.path] = v;
|
|
151
280
|
}
|
|
152
281
|
}
|
|
153
282
|
else if (entry.field.type === 'duration') {
|
|
154
283
|
const v = entry.obj[entry.path];
|
|
155
284
|
if (serialize?.(entry)) {
|
|
285
|
+
if ((op === 'load' && typeof v !== 'string') || (op === 'save' && !(v instanceof duration_1.NesoiDuration))) {
|
|
286
|
+
if (entry.is_union_option !== true) {
|
|
287
|
+
throw error_1.NesoiError.Bucket.Model.InvalidNesoiDuration({ bucket: this.alias, value: v });
|
|
288
|
+
}
|
|
289
|
+
continue;
|
|
290
|
+
}
|
|
156
291
|
if (op === 'load')
|
|
157
292
|
entry.copy[entry.path] = duration_1.NesoiDuration.fromString(v);
|
|
158
293
|
if (op === 'save')
|
|
159
294
|
entry.copy[entry.path] = v.toString();
|
|
160
295
|
}
|
|
161
296
|
else {
|
|
297
|
+
if (!(v instanceof duration_1.NesoiDuration)) {
|
|
298
|
+
if (entry.is_union_option !== true) {
|
|
299
|
+
throw error_1.NesoiError.Bucket.Model.InvalidNesoiDuration({ bucket: this.alias, value: v });
|
|
300
|
+
}
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
162
303
|
entry.copy[entry.path] = v;
|
|
163
304
|
}
|
|
164
305
|
}
|
|
165
306
|
else {
|
|
166
307
|
entry.copy[entry.path] = entry.obj[entry.path];
|
|
167
308
|
}
|
|
309
|
+
if (isLeafPath) {
|
|
310
|
+
modelpath_results.push({
|
|
311
|
+
value: entry.copy[entry.path],
|
|
312
|
+
index: entry.modelpath.asterisk_values
|
|
313
|
+
});
|
|
314
|
+
}
|
|
168
315
|
}
|
|
169
316
|
poll = next;
|
|
170
317
|
}
|
|
@@ -184,6 +331,8 @@ class BucketModel {
|
|
|
184
331
|
copy[meta.created_at] = obj[meta.created_at];
|
|
185
332
|
copy[meta.updated_at] = obj[meta.updated_at];
|
|
186
333
|
}
|
|
334
|
+
if (modelpath)
|
|
335
|
+
return modelpath_results;
|
|
187
336
|
return copy;
|
|
188
337
|
}
|
|
189
338
|
}
|
|
@@ -69,7 +69,7 @@ export declare class $BucketModel {
|
|
|
69
69
|
constructor(fields: $BucketModelFields & {
|
|
70
70
|
id: $BucketModelField;
|
|
71
71
|
}, defaults?: Record<string, any>, hasFileField?: boolean, hasEncryptedField?: boolean);
|
|
72
|
-
static
|
|
72
|
+
static getFields(model: $BucketModel, modelpath: string): $BucketModelField[];
|
|
73
73
|
static fieldsOfType(model: $BucketModel, type: $BucketModelFieldType): $BucketModelField[];
|
|
74
74
|
static forEachField(model: $BucketModel, predicate: (field: $BucketModelField, path: string) => Promise<void>): Promise<void>;
|
|
75
75
|
static getModelpaths(model: $BucketModel): Record<string, $BucketModelField[]>;
|
|
@@ -45,7 +45,7 @@ class $BucketModel {
|
|
|
45
45
|
this.hasFileField = hasFileField;
|
|
46
46
|
this.hasEncryptedField = hasEncryptedField;
|
|
47
47
|
}
|
|
48
|
-
static
|
|
48
|
+
static getFields(model, modelpath) {
|
|
49
49
|
const paths = modelpath.split('.');
|
|
50
50
|
const results = [];
|
|
51
51
|
let poll = [{ i: 0, field: { children: model.fields } }];
|
|
@@ -66,7 +66,7 @@ class $BucketModel {
|
|
|
66
66
|
})));
|
|
67
67
|
continue;
|
|
68
68
|
}
|
|
69
|
-
// If it's a list or dict,
|
|
69
|
+
// If it's a list or dict, add the index field
|
|
70
70
|
if (field.type === 'list' || field.type === 'dict') {
|
|
71
71
|
next.push({
|
|
72
72
|
i: item.i + 1,
|
|
@@ -142,7 +142,7 @@ class NQL_RuleTree {
|
|
|
142
142
|
}
|
|
143
143
|
const is_metadata_field = Object.values(meta.meta).includes(key);
|
|
144
144
|
if (!is_metadata_field) {
|
|
145
|
-
const fields = bucket_model_schema_1.$BucketModel.
|
|
145
|
+
const fields = bucket_model_schema_1.$BucketModel.getFields(meta.schema.model, key);
|
|
146
146
|
if (!fields.length) {
|
|
147
147
|
throw new Error(`Field '${key}' not found on bucket '${meta.schema.name}'`);
|
|
148
148
|
}
|
|
@@ -191,7 +191,7 @@ class NQL_RuleTree {
|
|
|
191
191
|
const _op = this.parseOp([{ type: 'datetime', name: fieldpath }], op);
|
|
192
192
|
return { type: 'fieldpath', or: !!or, fieldpath, not: !!not, case_i: !!case_i, op: _op };
|
|
193
193
|
}
|
|
194
|
-
const fields = bucket_model_schema_1.$BucketModel.
|
|
194
|
+
const fields = bucket_model_schema_1.$BucketModel.getFields(meta.schema.model, fieldpath);
|
|
195
195
|
if (!fields.length) {
|
|
196
196
|
throw new Error(`Field '${fieldpath}' not found on bucket '${meta.schema.name}'`);
|
|
197
197
|
}
|
|
@@ -300,7 +300,7 @@ class NQL_RuleTree {
|
|
|
300
300
|
throw new Error(`Bucket '${subMeta}' not found on module`);
|
|
301
301
|
}
|
|
302
302
|
subMeta.scope = this.customBuckets[tag.short]?.scope || subMeta.scope;
|
|
303
|
-
const field = bucket_model_schema_1.$BucketModel.
|
|
303
|
+
const field = bucket_model_schema_1.$BucketModel.getFields(subMeta.schema.model, fieldpath);
|
|
304
304
|
if (!field) {
|
|
305
305
|
throw new Error(`Field '${fieldpath}' not found on bucket '${subMeta.schema.name}'`);
|
|
306
306
|
}
|
|
@@ -617,7 +617,8 @@ class NQL_Compiler {
|
|
|
617
617
|
...union,
|
|
618
618
|
inters: Array.from(Array(union.inters.length), _ => ({}))
|
|
619
619
|
},
|
|
620
|
-
parent: partStack.at(-1)
|
|
620
|
+
parent: partStack.at(-1),
|
|
621
|
+
select: rule.value.subquery.select
|
|
621
622
|
};
|
|
622
623
|
// debugLog.push('+ [part] ' + newPart.i);
|
|
623
624
|
parts.push(newPart);
|