nesoi 3.4.2 → 3.4.4
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.schema.d.ts +1 -0
- package/lib/elements/blocks/resource/resource.builder.js +2 -2
- package/lib/elements/blocks/resource/resource_query.builder.d.ts +3 -0
- package/lib/elements/blocks/resource/resource_query.builder.js +7 -1
- package/lib/elements/entities/bucket/adapters/bucket_adapter.d.ts +5 -3
- package/lib/elements/entities/bucket/adapters/bucket_adapter.js +3 -3
- package/lib/elements/entities/bucket/adapters/memory.bucket_adapter.d.ts +2 -2
- package/lib/elements/entities/bucket/adapters/memory.bucket_adapter.js +5 -5
- package/lib/elements/entities/bucket/adapters/memory.nql.d.ts +3 -1
- package/lib/elements/entities/bucket/adapters/memory.nql.js +14 -5
- package/lib/elements/entities/bucket/adapters/rest.nql.d.ts +1 -1
- package/lib/elements/entities/bucket/adapters/rest.nql.js +1 -1
- package/lib/elements/entities/bucket/bucket.d.ts +12 -0
- package/lib/elements/entities/bucket/bucket.js +23 -4
- package/lib/elements/entities/bucket/cache/bucket_cache.d.ts +4 -2
- package/lib/elements/entities/bucket/cache/bucket_cache.js +7 -3
- package/lib/elements/entities/bucket/graph/bucket_graph.d.ts +10 -1
- package/lib/elements/entities/bucket/graph/bucket_graph.js +50 -4
- package/lib/elements/entities/bucket/model/bucket_model.d.ts +8 -2
- package/lib/elements/entities/bucket/model/bucket_model.js +287 -275
- 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.js +48 -9
- package/lib/elements/entities/message/template/message_template_parser.js +3 -3
- package/lib/engine/data/error.d.ts +4 -0
- package/lib/engine/data/error.js +4 -0
- package/lib/engine/transaction/nodes/bucket.trx_node.d.ts +5 -1
- package/lib/engine/transaction/nodes/bucket.trx_node.js +8 -0
- package/lib/engine/transaction/nodes/bucket_query.trx_node.d.ts +4 -0
- package/lib/engine/transaction/nodes/bucket_query.trx_node.js +22 -0
- package/lib/engine/transaction/trx_engine.d.ts +2 -2
- package/lib/engine/transaction/trx_engine.js +14 -13
- package/lib/engine/util/parse.d.ts +0 -7
- package/package.json +1 -1
- package/tools/joaquin/bucket.d.ts +4 -0
- package/tools/joaquin/bucket.js +13 -0
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -6,6 +6,8 @@ const date_1 = require("../../../../engine/data/date");
|
|
|
6
6
|
const datetime_1 = require("../../../../engine/data/datetime");
|
|
7
7
|
const decimal_1 = require("../../../../engine/data/decimal");
|
|
8
8
|
const duration_1 = require("../../../../engine/data/duration");
|
|
9
|
+
const log_1 = require("../../../../engine/util/log");
|
|
10
|
+
const parse_1 = require("../../../../engine/util/parse");
|
|
9
11
|
/**
|
|
10
12
|
* @category Elements
|
|
11
13
|
* @subcategory Entity
|
|
@@ -19,7 +21,7 @@ class BucketModel {
|
|
|
19
21
|
this.alias = bucket.alias;
|
|
20
22
|
this.schema = bucket.model;
|
|
21
23
|
}
|
|
22
|
-
copy(obj, op, serialize,
|
|
24
|
+
copy(obj, op, serialize, modelpath_or_roots) {
|
|
23
25
|
const meta = this.config?.meta || {
|
|
24
26
|
created_at: 'created_at',
|
|
25
27
|
created_by: 'created_by',
|
|
@@ -28,11 +30,12 @@ class BucketModel {
|
|
|
28
30
|
};
|
|
29
31
|
const copy = {};
|
|
30
32
|
const modelpath_results = [];
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
+
const roots = Array.isArray(modelpath_or_roots) ? modelpath_or_roots : undefined;
|
|
34
|
+
const paths = Array.isArray(modelpath_or_roots) ? undefined : modelpath_or_roots?.split('.');
|
|
35
|
+
const poll = paths
|
|
33
36
|
// Specific modelpath requested, start with root field only
|
|
34
37
|
? [{
|
|
35
|
-
|
|
38
|
+
key: paths[0],
|
|
36
39
|
obj,
|
|
37
40
|
copy,
|
|
38
41
|
field: this.schema.fields[paths[0]],
|
|
@@ -40,300 +43,309 @@ class BucketModel {
|
|
|
40
43
|
modelpath: { i: 0, asterisk_values: [] }
|
|
41
44
|
}]
|
|
42
45
|
// No modelpath, use all fields
|
|
43
|
-
: Object.entries(this.schema.fields)
|
|
44
|
-
|
|
46
|
+
: Object.entries(this.schema.fields)
|
|
47
|
+
.filter(([_, field]) => !roots || roots.includes(field.path))
|
|
48
|
+
.map(([path, field]) => ({
|
|
49
|
+
key: path,
|
|
50
|
+
obj,
|
|
51
|
+
copy,
|
|
52
|
+
field,
|
|
53
|
+
depth: 0
|
|
45
54
|
}));
|
|
55
|
+
modelpath_results.push(...this.runCopyCmdPoll(op, poll, paths, serialize));
|
|
56
|
+
copy[meta.created_by] = obj[meta.created_by];
|
|
57
|
+
copy[meta.updated_by] = obj[meta.updated_by];
|
|
58
|
+
const meta_as_json = serialize?.();
|
|
59
|
+
const created_at = obj[meta.created_at];
|
|
60
|
+
if (typeof created_at === 'string') {
|
|
61
|
+
copy[meta.created_at] = meta_as_json ? created_at : datetime_1.NesoiDatetime.fromISO(obj[created_at]);
|
|
62
|
+
}
|
|
63
|
+
else if (created_at instanceof datetime_1.NesoiDatetime) {
|
|
64
|
+
copy[meta.created_at] = meta_as_json ? created_at.toISO() : created_at;
|
|
65
|
+
}
|
|
66
|
+
const updated_at = obj[meta.updated_at];
|
|
67
|
+
if (typeof updated_at === 'string') {
|
|
68
|
+
copy[meta.updated_at] = meta_as_json ? updated_at : datetime_1.NesoiDatetime.fromISO(obj[updated_at]);
|
|
69
|
+
}
|
|
70
|
+
else if (updated_at instanceof datetime_1.NesoiDatetime) {
|
|
71
|
+
copy[meta.updated_at] = meta_as_json ? updated_at.toISO() : updated_at;
|
|
72
|
+
}
|
|
73
|
+
if (paths)
|
|
74
|
+
return modelpath_results;
|
|
75
|
+
return copy;
|
|
76
|
+
}
|
|
77
|
+
runCopyCmdPoll(op, poll, modelpath, serialize) {
|
|
78
|
+
const modelpath_results = [];
|
|
46
79
|
while (poll.length) {
|
|
47
80
|
const next = [];
|
|
48
|
-
for (const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (alreadyParsed)
|
|
52
|
-
continue;
|
|
53
|
-
}
|
|
54
|
-
const val = entry.obj[entry.path];
|
|
55
|
-
if (val === undefined) {
|
|
56
|
-
delete entry.copy[entry.path];
|
|
57
|
-
continue;
|
|
58
|
-
}
|
|
59
|
-
if (val === null) {
|
|
60
|
-
delete entry.copy[entry.path];
|
|
61
|
-
continue;
|
|
62
|
-
}
|
|
63
|
-
const isLeafPath = entry.modelpath
|
|
64
|
-
? entry.modelpath.i === (paths?.length ?? 0) - 1
|
|
81
|
+
for (const cmd of poll) {
|
|
82
|
+
const isLeafPath = cmd.modelpath
|
|
83
|
+
? cmd.modelpath.i === (modelpath?.length ?? 0) - 1
|
|
65
84
|
: false;
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
}
|
|
104
|
-
}
|
|
105
|
-
else if (entry.field.type === 'dict') {
|
|
106
|
-
if (typeof val !== 'object' || Array.isArray(val))
|
|
107
|
-
continue;
|
|
108
|
-
entry.copy[entry.path] = {};
|
|
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
|
-
}
|
|
137
|
-
}
|
|
138
|
-
else if (entry.field.type === 'obj') {
|
|
139
|
-
if (typeof val !== 'object' || Array.isArray(val))
|
|
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;
|
|
146
|
-
entry.copy[entry.path] = {};
|
|
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
|
-
}
|
|
175
|
-
}
|
|
176
|
-
else if (entry.field.type === 'union') {
|
|
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;
|
|
186
|
-
}
|
|
187
|
-
else if (entry.field.type === 'enum') {
|
|
188
|
-
const v = entry.obj[entry.path];
|
|
189
|
-
const options = entry.field.meta.enum.options;
|
|
190
|
-
if (!(v in options)) {
|
|
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
|
-
}
|
|
194
|
-
}
|
|
195
|
-
entry.copy[entry.path] = entry.obj[entry.path];
|
|
196
|
-
}
|
|
197
|
-
else if (entry.field.type === 'date') {
|
|
198
|
-
const v = entry.obj[entry.path];
|
|
199
|
-
if (serialize?.(entry)) {
|
|
200
|
-
if (op === 'load') {
|
|
201
|
-
try {
|
|
202
|
-
entry.copy[entry.path] = date_1.NesoiDate.fromISO(v);
|
|
203
|
-
}
|
|
204
|
-
catch {
|
|
205
|
-
if (entry.is_union_option !== true) {
|
|
206
|
-
throw error_1.NesoiError.Bucket.Model.InvalidISODate({ bucket: this.alias, value: v });
|
|
207
|
-
}
|
|
208
|
-
continue;
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
else if (op === 'save') {
|
|
212
|
-
try {
|
|
213
|
-
entry.copy[entry.path] = v.toISO();
|
|
214
|
-
}
|
|
215
|
-
catch {
|
|
216
|
-
if (entry.is_union_option !== true) {
|
|
217
|
-
throw error_1.NesoiError.Bucket.Model.InvalidNesoiDate({ bucket: this.alias, value: v });
|
|
218
|
-
}
|
|
219
|
-
continue;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
else {
|
|
224
|
-
entry.copy[entry.path] = entry.obj[entry.path];
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
else if (entry.field.type === 'datetime') {
|
|
228
|
-
const v = entry.obj[entry.path];
|
|
229
|
-
if (serialize?.(entry)) {
|
|
230
|
-
if (op === 'load') {
|
|
231
|
-
try {
|
|
232
|
-
entry.copy[entry.path] = datetime_1.NesoiDatetime.fromISO(v);
|
|
233
|
-
}
|
|
234
|
-
catch {
|
|
235
|
-
if (entry.is_union_option !== true) {
|
|
236
|
-
throw error_1.NesoiError.Bucket.Model.InvalidISODatetime({ bucket: this.alias, value: v });
|
|
237
|
-
}
|
|
238
|
-
continue;
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
else if (op === 'save') {
|
|
242
|
-
try {
|
|
243
|
-
entry.copy[entry.path] = v.toISO();
|
|
244
|
-
}
|
|
245
|
-
catch {
|
|
246
|
-
if (entry.is_union_option !== true) {
|
|
247
|
-
throw error_1.NesoiError.Bucket.Model.InvalidNesoiDatetime({ bucket: this.alias, value: v });
|
|
248
|
-
}
|
|
249
|
-
continue;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
else {
|
|
254
|
-
entry.copy[entry.path] = entry.obj[entry.path];
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
else if (entry.field.type === 'decimal') {
|
|
258
|
-
const meta = entry.field.meta.decimal;
|
|
259
|
-
const v = entry.obj[entry.path];
|
|
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;
|
|
85
|
+
if (cmd.field.type === 'union') {
|
|
86
|
+
const options = Object.values(cmd.field.children);
|
|
87
|
+
let unionErrors = [];
|
|
88
|
+
for (const option of options) {
|
|
89
|
+
try {
|
|
90
|
+
// Clean field for next attempt
|
|
91
|
+
delete cmd.copy[cmd.key];
|
|
92
|
+
// Attempt union option
|
|
93
|
+
modelpath_results.push(...this.runCopyCmdPoll(op, [{
|
|
94
|
+
...cmd,
|
|
95
|
+
field: option
|
|
96
|
+
}], modelpath, serialize));
|
|
97
|
+
// Success, clear errors and proceed
|
|
98
|
+
unionErrors = [];
|
|
99
|
+
break;
|
|
266
100
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
if (op === 'save')
|
|
270
|
-
entry.copy[entry.path] = v.toString();
|
|
271
|
-
}
|
|
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;
|
|
101
|
+
catch (e) {
|
|
102
|
+
unionErrors.push(e);
|
|
278
103
|
}
|
|
279
|
-
entry.copy[entry.path] = v;
|
|
280
104
|
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
const v = entry.obj[entry.path];
|
|
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
|
-
}
|
|
291
|
-
if (op === 'load')
|
|
292
|
-
entry.copy[entry.path] = duration_1.NesoiDuration.fromString(v);
|
|
293
|
-
if (op === 'save')
|
|
294
|
-
entry.copy[entry.path] = v.toString();
|
|
295
|
-
}
|
|
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
|
-
}
|
|
303
|
-
entry.copy[entry.path] = v;
|
|
105
|
+
if (unionErrors.length) {
|
|
106
|
+
throw error_1.NesoiError.Message.ValueDoesntMatchUnion({ alias: cmd.field.alias, path: '', value: cmd.obj[cmd.key], unionErrors });
|
|
304
107
|
}
|
|
305
108
|
}
|
|
306
109
|
else {
|
|
307
|
-
|
|
110
|
+
const as_json = serialize?.(cmd);
|
|
111
|
+
next.push(...this.runCopyCmd(op, cmd, modelpath, as_json));
|
|
308
112
|
}
|
|
309
113
|
if (isLeafPath) {
|
|
310
114
|
modelpath_results.push({
|
|
311
|
-
value:
|
|
312
|
-
index:
|
|
115
|
+
value: cmd.copy[cmd.key],
|
|
116
|
+
index: cmd.modelpath.asterisk_values
|
|
313
117
|
});
|
|
314
118
|
}
|
|
315
119
|
}
|
|
316
120
|
poll = next;
|
|
317
121
|
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
122
|
+
return modelpath_results;
|
|
123
|
+
}
|
|
124
|
+
runCopyCmd(op, cmd, modelpath, as_json = false) {
|
|
125
|
+
const next = [];
|
|
126
|
+
const value = cmd.obj[cmd.key];
|
|
127
|
+
if (value === undefined || value === null) {
|
|
128
|
+
if (cmd.field.path !== 'id' && cmd.field.required) {
|
|
129
|
+
if (op === 'load') {
|
|
130
|
+
log_1.Log.warn('bucket.model', this.alias, `Object with id ${cmd.obj.id} missing required field '${cmd.field.path}' during read`);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
throw error_1.NesoiError.Bucket.Model.FieldRequired({ bucket: this.alias, field: cmd.field.alias });
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
delete cmd.copy[cmd.key];
|
|
137
|
+
return [];
|
|
138
|
+
}
|
|
139
|
+
const isLeafPath = cmd.modelpath
|
|
140
|
+
? cmd.modelpath.i === (modelpath?.length ?? 0) - 1
|
|
141
|
+
: false;
|
|
142
|
+
const nextPath = (!cmd.modelpath || isLeafPath)
|
|
143
|
+
? undefined
|
|
144
|
+
: modelpath[cmd.modelpath.i + 1];
|
|
145
|
+
const addChildrenToQueue = !cmd.modelpath
|
|
146
|
+
|| cmd.modelpath.i >= (modelpath.length - 1) // is leaf or inner field
|
|
147
|
+
|| nextPath === '*';
|
|
148
|
+
if (cmd.field.type === 'list') {
|
|
149
|
+
if (!Array.isArray(value)) {
|
|
150
|
+
throw error_1.NesoiError.Message.InvalidFieldType({ alias: cmd.field.alias, path: '', value, type: 'list' });
|
|
151
|
+
}
|
|
152
|
+
cmd.copy[cmd.key] = [];
|
|
153
|
+
// Leaf path or no modelpath = add entire list to queue
|
|
154
|
+
if (addChildrenToQueue) {
|
|
155
|
+
next.push(...value.map((_, i) => ({
|
|
156
|
+
key: i.toString(),
|
|
157
|
+
obj: value,
|
|
158
|
+
copy: cmd.copy[cmd.key],
|
|
159
|
+
field: cmd.field.children['#'],
|
|
160
|
+
depth: cmd.depth + 1,
|
|
161
|
+
modelpath: cmd.modelpath ? {
|
|
162
|
+
i: cmd.modelpath.i + 1,
|
|
163
|
+
asterisk_values: [...cmd.modelpath.asterisk_values, ...(nextPath === '*' ? [i.toString()] : [])]
|
|
164
|
+
} : undefined
|
|
165
|
+
})));
|
|
166
|
+
}
|
|
167
|
+
// Branch path = add next path to queue
|
|
168
|
+
else {
|
|
169
|
+
next.push({
|
|
170
|
+
key: nextPath,
|
|
171
|
+
obj: value,
|
|
172
|
+
copy: cmd.copy[cmd.key],
|
|
173
|
+
field: cmd.field.children['#'],
|
|
174
|
+
depth: cmd.depth + 1,
|
|
175
|
+
modelpath: cmd.modelpath ? {
|
|
176
|
+
i: cmd.modelpath.i + 1,
|
|
177
|
+
asterisk_values: cmd.modelpath.asterisk_values
|
|
178
|
+
} : undefined
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
return next;
|
|
182
|
+
}
|
|
183
|
+
else if (cmd.field.type === 'dict') {
|
|
184
|
+
if (typeof value !== 'object' || Array.isArray(value)) {
|
|
185
|
+
throw error_1.NesoiError.Message.InvalidFieldType({ alias: cmd.field.alias, path: '', value, type: 'dict' });
|
|
186
|
+
}
|
|
187
|
+
cmd.copy[cmd.key] = {};
|
|
188
|
+
// Leaf path or no modelpath = add entire dict to queue
|
|
189
|
+
if (addChildrenToQueue) {
|
|
190
|
+
next.push(...Object.keys(value).map((key) => ({
|
|
191
|
+
key,
|
|
192
|
+
obj: value,
|
|
193
|
+
copy: cmd.copy[cmd.key],
|
|
194
|
+
field: cmd.field.children['#'],
|
|
195
|
+
depth: cmd.depth + 1,
|
|
196
|
+
modelpath: cmd.modelpath ? {
|
|
197
|
+
i: cmd.modelpath.i + 1,
|
|
198
|
+
asterisk_values: [...cmd.modelpath.asterisk_values, ...(nextPath === '*' ? [key] : [])]
|
|
199
|
+
} : undefined
|
|
200
|
+
})));
|
|
201
|
+
}
|
|
202
|
+
// Branch path = add next path to queue
|
|
203
|
+
else if (nextPath in value) {
|
|
204
|
+
next.push({
|
|
205
|
+
key: nextPath,
|
|
206
|
+
obj: value,
|
|
207
|
+
copy: cmd.copy[cmd.key],
|
|
208
|
+
field: cmd.field.children['#'],
|
|
209
|
+
depth: cmd.depth + 1,
|
|
210
|
+
modelpath: cmd.modelpath ? {
|
|
211
|
+
i: cmd.modelpath.i + 1,
|
|
212
|
+
asterisk_values: cmd.modelpath.asterisk_values
|
|
213
|
+
} : undefined
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
return next;
|
|
217
|
+
}
|
|
218
|
+
else if (cmd.field.type === 'obj') {
|
|
219
|
+
if (typeof value !== 'object' || Array.isArray(value)) {
|
|
220
|
+
throw error_1.NesoiError.Message.InvalidFieldType({ alias: cmd.field.alias, path: '', value, type: 'obj' });
|
|
221
|
+
}
|
|
222
|
+
if (op === 'save') {
|
|
223
|
+
const missingKeys = Object.entries(cmd.field.children)
|
|
224
|
+
.filter(([key, child]) => child.required
|
|
225
|
+
&& key !== 'id'
|
|
226
|
+
&& !(key in cmd.obj[cmd.key]));
|
|
227
|
+
if (missingKeys.length) {
|
|
228
|
+
throw new Error(`Object with id ${cmd.obj.id} from bucket ${this.alias} is missing keys`);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
const matchingKeys = Object.entries(cmd.field.children)
|
|
233
|
+
.filter(([key, child]) => !child.required
|
|
234
|
+
|| (key !== 'id' && key in cmd.obj[cmd.key]));
|
|
235
|
+
if (!matchingKeys.length) {
|
|
236
|
+
throw new Error(`Object with id ${cmd.obj.id} from bucket ${this.alias} has no matching keys`);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
cmd.copy[cmd.key] = {};
|
|
240
|
+
// Leaf path or no modelpath = add entire dict to queue
|
|
241
|
+
if (addChildrenToQueue) {
|
|
242
|
+
next.push(...Object.keys(cmd.field.children).map(path => ({
|
|
243
|
+
key: path,
|
|
244
|
+
obj: value,
|
|
245
|
+
copy: cmd.copy[cmd.key],
|
|
246
|
+
field: cmd.field.children[path],
|
|
247
|
+
depth: cmd.depth + 1,
|
|
248
|
+
modelpath: cmd.modelpath ? {
|
|
249
|
+
i: cmd.modelpath.i + 1,
|
|
250
|
+
asterisk_values: [...cmd.modelpath.asterisk_values, ...(nextPath === '*' ? [path] : [])]
|
|
251
|
+
} : undefined
|
|
252
|
+
})));
|
|
253
|
+
}
|
|
254
|
+
// Branch path = add next path to queue
|
|
255
|
+
else {
|
|
256
|
+
next.push({
|
|
257
|
+
key: nextPath,
|
|
258
|
+
obj: value,
|
|
259
|
+
copy: cmd.copy[cmd.key],
|
|
260
|
+
field: cmd.field.children[nextPath],
|
|
261
|
+
depth: cmd.depth + 1,
|
|
262
|
+
modelpath: cmd.modelpath ? {
|
|
263
|
+
i: cmd.modelpath.i + 1,
|
|
264
|
+
asterisk_values: cmd.modelpath.asterisk_values
|
|
265
|
+
} : undefined
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
return next;
|
|
269
|
+
}
|
|
270
|
+
else if (cmd.field.type === 'enum') {
|
|
271
|
+
if (typeof value !== 'string') {
|
|
272
|
+
throw error_1.NesoiError.Message.InvalidFieldType({ alias: cmd.field.alias, path: '', value, type: 'obj' });
|
|
273
|
+
}
|
|
274
|
+
const options = cmd.field.meta.enum.options;
|
|
275
|
+
if (!(value in options)) {
|
|
276
|
+
throw error_1.NesoiError.Bucket.Model.InvalidEnum({ bucket: this.alias, value, options: Object.keys(options) });
|
|
324
277
|
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
278
|
+
cmd.copy[cmd.key] = cmd.obj[cmd.key];
|
|
279
|
+
return [];
|
|
280
|
+
}
|
|
281
|
+
else if (cmd.field.type === 'date') {
|
|
282
|
+
if (value instanceof date_1.NesoiDate) {
|
|
283
|
+
cmd.copy[cmd.key] = as_json ? value.toISO() : value;
|
|
284
|
+
}
|
|
285
|
+
else if (typeof value === 'string') {
|
|
286
|
+
const date = date_1.NesoiDate.fromISO(value);
|
|
287
|
+
cmd.copy[cmd.key] = as_json ? date.toISO() : date;
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
throw error_1.NesoiError.Message.InvalidFieldType({ alias: cmd.field.alias, path: '', value, type: 'date' });
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
else if (cmd.field.type === 'datetime') {
|
|
294
|
+
if (value instanceof datetime_1.NesoiDatetime) {
|
|
295
|
+
cmd.copy[cmd.key] = as_json ? value.toISO() : value;
|
|
296
|
+
}
|
|
297
|
+
else if (typeof value === 'string') {
|
|
298
|
+
const datetime = datetime_1.NesoiDatetime.fromISO(value);
|
|
299
|
+
cmd.copy[cmd.key] = as_json ? datetime.toISO() : datetime;
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
throw error_1.NesoiError.Message.InvalidFieldType({ alias: cmd.field.alias, path: '', value, type: 'datetime' });
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
else if (cmd.field.type === 'decimal') {
|
|
306
|
+
if (value instanceof decimal_1.NesoiDecimal) {
|
|
307
|
+
cmd.copy[cmd.key] = as_json ? value.toString() : value;
|
|
308
|
+
}
|
|
309
|
+
else if (typeof value === 'string') {
|
|
310
|
+
const meta = cmd.field.meta.decimal;
|
|
311
|
+
const decimal = new decimal_1.NesoiDecimal(value, meta?.left, meta?.right);
|
|
312
|
+
cmd.copy[cmd.key] = as_json ? decimal.toString() : decimal;
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
315
|
+
throw error_1.NesoiError.Message.InvalidFieldType({ alias: cmd.field.alias, path: '', value, type: 'decimal' });
|
|
328
316
|
}
|
|
329
317
|
}
|
|
318
|
+
else if (cmd.field.type === 'duration') {
|
|
319
|
+
if (value instanceof duration_1.NesoiDuration) {
|
|
320
|
+
cmd.copy[cmd.key] = as_json ? value.toString() : value;
|
|
321
|
+
}
|
|
322
|
+
else if (typeof value === 'string') {
|
|
323
|
+
const duration = duration_1.NesoiDuration.fromString(value);
|
|
324
|
+
cmd.copy[cmd.key] = as_json ? duration.toString() : duration;
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
throw error_1.NesoiError.Message.InvalidFieldType({ alias: cmd.field.alias, path: '', value, type: 'decimal' });
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
else if (cmd.field.type === 'int') {
|
|
331
|
+
cmd.copy[cmd.key] = (0, parse_1.parseInt_)({ alias: cmd.field.alias }, [], cmd.obj[cmd.key]);
|
|
332
|
+
}
|
|
333
|
+
else if (cmd.field.type === 'float') {
|
|
334
|
+
cmd.copy[cmd.key] = (0, parse_1.parseFloat_)({ alias: cmd.field.alias }, [], cmd.obj[cmd.key]);
|
|
335
|
+
}
|
|
336
|
+
else if (cmd.field.type === 'string') {
|
|
337
|
+
cmd.copy[cmd.key] = (0, parse_1.parseString)({ alias: cmd.field.alias }, [], cmd.obj[cmd.key]);
|
|
338
|
+
}
|
|
339
|
+
else if (cmd.field.type === 'literal') {
|
|
340
|
+
cmd.copy[cmd.key] = (0, parse_1.parseLiteral)({ alias: cmd.field.alias }, [], cmd.obj[cmd.key], cmd.field.meta.literal.template);
|
|
341
|
+
}
|
|
342
|
+
else if (cmd.field.type === 'boolean') {
|
|
343
|
+
cmd.copy[cmd.key] = (0, parse_1.parseBoolean)({ alias: cmd.field.alias }, [], cmd.obj[cmd.key]);
|
|
344
|
+
}
|
|
330
345
|
else {
|
|
331
|
-
copy[
|
|
332
|
-
copy[meta.updated_at] = obj[meta.updated_at];
|
|
346
|
+
cmd.copy[cmd.key] = cmd.obj[cmd.key];
|
|
333
347
|
}
|
|
334
|
-
|
|
335
|
-
return modelpath_results;
|
|
336
|
-
return copy;
|
|
348
|
+
return next;
|
|
337
349
|
}
|
|
338
350
|
}
|
|
339
351
|
exports.BucketModel = BucketModel;
|
|
@@ -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>[], param_templates: Record<string, string>[], pagination?: NQL_Pagination, view?: $BucketView): Promise<NQL_Result>;
|
|
18
|
+
abstract run(trx: AnyTrxNode, part: NQL_Part, params: Record<string, any>[], param_templates: Record<string, string>[], pagination?: NQL_Pagination, view?: $BucketView, serialize?: boolean): Promise<NQL_Result>;
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
21
|
* @category NQL
|
|
@@ -27,7 +27,7 @@ export declare class NQL_Engine {
|
|
|
27
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
28
|
scope: string;
|
|
29
29
|
nql: NQLRunner;
|
|
30
|
-
}
|
|
30
|
+
}>, serialize?: boolean): Promise<NQL_Result>;
|
|
31
31
|
linkExternal(bucket: AnyBucket): void;
|
|
32
32
|
}
|
|
33
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, customBuckets) {
|
|
26
|
+
async run(trx, query, pagination, params = [{}], param_templates = [], view, customBuckets, serialize) {
|
|
27
27
|
if (!params.length)
|
|
28
28
|
params = [{}];
|
|
29
29
|
let result = {
|
|
@@ -35,7 +35,7 @@ class NQL_Engine {
|
|
|
35
35
|
// Run part
|
|
36
36
|
const _runner = Object.values(customBuckets || {}).find(b => b.scope === part.union.meta.scope)?.nql
|
|
37
37
|
|| this.runners[part.union.meta.scope];
|
|
38
|
-
const out = await _runner.run(trx, part, params, param_templates, pagination, view);
|
|
38
|
+
const out = await _runner.run(trx, part, params, param_templates, pagination, view, serialize);
|
|
39
39
|
result = out;
|
|
40
40
|
// Part failed, return
|
|
41
41
|
// Failure here is only when a single value is expected,
|