nesoi 3.0.21 → 3.1.1
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/apps/monolyth/stages/2_build_typescript_stage.js +1 -0
- package/lib/compiler/apps/monolyth/stages/4_dump_modules_stage.js +8 -0
- package/lib/compiler/compiler.js +1 -1
- package/lib/compiler/elements/bucket.element.d.ts +3 -2
- package/lib/compiler/elements/bucket.element.js +86 -128
- package/lib/compiler/elements/element.js +4 -2
- package/lib/compiler/elements/externals.element.js +3 -0
- package/lib/compiler/elements/machine.element.js +2 -2
- package/lib/compiler/elements/message.element.js +35 -57
- package/lib/compiler/elements/queue.element.js +1 -1
- package/lib/compiler/helpers/dump_helpers.d.ts +5 -3
- package/lib/compiler/helpers/dump_helpers.js +43 -26
- package/lib/compiler/stages/4_build_schemas_stage.js +12 -0
- package/lib/compiler/stages/5_inject_ts_stage.js +4 -1
- package/lib/compiler/stages/7_dump_stage.js +7 -1
- package/lib/compiler/treeshake.js +4 -2
- package/lib/compiler/typescript/bridge/extract.js +37 -107
- package/lib/compiler/typescript/bridge/inject.d.ts +1 -1
- package/lib/compiler/typescript/bridge/inject.js +73 -45
- package/lib/compiler/typescript/bridge/organize.js +9 -5
- package/lib/compiler/typescript/typescript_compiler.d.ts +4 -6
- package/lib/compiler/typescript/typescript_compiler.js +139 -75
- package/lib/elements/blocks/block.builder.d.ts +1 -10
- package/lib/elements/blocks/block.builder.js +0 -32
- package/lib/elements/blocks/job/internal/resource_job.builder.d.ts +3 -21
- package/lib/elements/blocks/job/job.builder.d.ts +6 -20
- package/lib/elements/blocks/job/job.builder.js +0 -4
- package/lib/elements/blocks/machine/machine.builder.d.ts +5 -14
- package/lib/elements/blocks/machine/machine.builder.js +2 -2
- package/lib/elements/blocks/queue/queue.builder.d.ts +6 -15
- package/lib/elements/blocks/queue/queue.builder.js +2 -2
- package/lib/elements/edge/externals/externals.builder.d.ts +2 -0
- package/lib/elements/edge/externals/externals.builder.js +6 -1
- package/lib/elements/edge/externals/externals.schema.d.ts +2 -1
- package/lib/elements/edge/externals/externals.schema.js +3 -1
- package/lib/elements/entities/bucket/adapters/bucket_adapter.d.ts +1 -1
- package/lib/elements/entities/bucket/adapters/memory.bucket_adapter.d.ts +7 -0
- package/lib/elements/entities/bucket/adapters/memory.bucket_adapter.js +46 -36
- package/lib/elements/entities/bucket/adapters/memory.nql.js +1 -1
- package/lib/elements/entities/bucket/bucket.builder.d.ts +6 -4
- package/lib/elements/entities/bucket/bucket.js +42 -43
- package/lib/elements/entities/bucket/bucket.schema.d.ts +2 -1
- package/lib/elements/entities/bucket/cache/bucket_cache.d.ts +1 -4
- package/lib/elements/entities/bucket/graph/bucket_graph.infer.d.ts +7 -5
- package/lib/elements/entities/bucket/graph/bucket_graph_link.builder.d.ts +2 -1
- package/lib/elements/entities/bucket/model/bucket_model.builder.d.ts +1 -1
- package/lib/elements/entities/bucket/model/bucket_model.convert.d.ts +1 -1
- package/lib/elements/entities/bucket/model/bucket_model.convert.js +4 -4
- package/lib/elements/entities/bucket/model/bucket_model.infer.d.ts +41 -9
- package/lib/elements/entities/bucket/model/bucket_model.schema.d.ts +8 -6
- package/lib/elements/entities/bucket/model/bucket_model.schema.js +184 -21
- package/lib/elements/entities/bucket/model/bucket_model_field.builder.d.ts +89 -56
- package/lib/elements/entities/bucket/model/bucket_model_field.builder.js +22 -30
- package/lib/elements/entities/bucket/query/nql.schema.d.ts +13 -10
- package/lib/elements/entities/bucket/query/nql_compiler.js +46 -21
- package/lib/elements/entities/bucket/view/bucket_view.builder.js +1 -1
- package/lib/elements/entities/bucket/view/bucket_view.d.ts +19 -0
- package/lib/elements/entities/bucket/view/bucket_view.js +230 -108
- package/lib/elements/entities/bucket/view/bucket_view.schema.d.ts +5 -10
- package/lib/elements/entities/bucket/view/bucket_view.schema.js +3 -5
- package/lib/elements/entities/bucket/view/bucket_view_field.builder.d.ts +16 -12
- package/lib/elements/entities/bucket/view/bucket_view_field.builder.js +55 -40
- package/lib/elements/entities/message/message.builder.d.ts +1 -11
- package/lib/elements/entities/message/message.infer.d.ts +6 -30
- package/lib/elements/entities/message/message.schema.js +2 -2
- package/lib/elements/entities/message/template/message_template.builder.js +1 -1
- package/lib/elements/entities/message/template/message_template.schema.d.ts +10 -15
- package/lib/elements/entities/message/template/message_template.schema.js +29 -12
- package/lib/elements/entities/message/template/message_template_field.builder.d.ts +45 -209
- package/lib/elements/entities/message/template/message_template_field.builder.js +69 -85
- package/lib/elements/entities/message/template/message_template_parser.js +52 -64
- package/lib/engine/apps/inline.app.js +1 -0
- package/lib/engine/data/trash.js +7 -7
- package/lib/engine/data/tree.d.ts +3 -0
- package/lib/engine/data/tree.js +36 -0
- package/lib/engine/space.js +1 -1
- package/lib/engine/transaction/trx_engine.config.d.ts +3 -2
- package/lib/engine/transaction/trx_engine.d.ts +9 -1
- package/lib/engine/transaction/trx_engine.js +52 -9
- package/lib/engine/util/deep.js +4 -0
- package/lib/engine/util/parse.d.ts +22 -14
- package/lib/engine/util/parse.js +20 -5
- package/lib/engine/util/type.d.ts +3 -0
- package/package.json +1 -1
- package/tools/joaquin/bucket.d.ts +9 -0
- package/tools/joaquin/bucket.js +49 -0
- package/tools/joaquin/message.d.ts +2 -1
- package/tools/joaquin/message.js +9 -2
- package/tools/joaquin/mock.d.ts +1 -0
- package/tools/joaquin/mock.js +13 -5
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -2,6 +2,7 @@ import { $Bucket } from '../bucket.schema';
|
|
|
2
2
|
import { $Module } from "../../../../schema";
|
|
3
3
|
import { NesoiDate } from "../../../../engine/data/date";
|
|
4
4
|
import { NesoiDatetime } from "../../../../engine/data/datetime";
|
|
5
|
+
import { NesoiDuration } from "../../../../engine/data/duration";
|
|
5
6
|
export type NQL_QueryMeta = {
|
|
6
7
|
bucket?: $Bucket;
|
|
7
8
|
scope?: string;
|
|
@@ -49,8 +50,8 @@ export type NQL_Node = NQL_Union | NQL_Intersection | NQL_Rule;
|
|
|
49
50
|
* All operations
|
|
50
51
|
*/
|
|
51
52
|
export type NQL_Operation = '==' | '>' | '<' | '>=' | '<=' | 'in' | 'contains' | 'contains_any' | 'present';
|
|
52
|
-
export type NQL_Order<
|
|
53
|
-
by?: keyof
|
|
53
|
+
export type NQL_Order<Querypath> = {
|
|
54
|
+
by?: (keyof Querypath)[];
|
|
54
55
|
dir?: ('asc' | 'desc')[];
|
|
55
56
|
};
|
|
56
57
|
export type NQL_Pagination = {
|
|
@@ -61,7 +62,7 @@ export type NQL_Pagination = {
|
|
|
61
62
|
/**
|
|
62
63
|
* A union of all operators which apply to the selected field
|
|
63
64
|
*/
|
|
64
|
-
type NQL_OpFromField<T> = T extends boolean ? '' | ' ==' | ' in' | ' present' : T extends number | NesoiDate | NesoiDatetime ? '' | ' ==' | ' >' | ' <' | ' >=' | ' <=' | ' in' | ' present' : T extends string ? '' | ' ==' | ' in' | ' contains' | ' contains_any' | ' present' | ' ~' | ' ~in' | ' ~contains' | ' ~contains_any' : T extends
|
|
65
|
+
type NQL_OpFromField<T> = T extends boolean ? '' | ' ==' | ' in' | ' present' : T extends number | NesoiDate | NesoiDatetime | NesoiDuration ? '' | ' ==' | ' >' | ' <' | ' >=' | ' <=' | ' in' | ' present' : T extends string ? '' | ' ==' | ' in' | ' contains' | ' contains_any' | ' present' | ' ~' | ' ~in' | ' ~contains' | ' ~contains_any' : T extends object ? ' contains' | ' contains_any' | ' present' : ' present';
|
|
65
66
|
/**
|
|
66
67
|
* A dict of accepted values for a given operator on a bucket field
|
|
67
68
|
*/
|
|
@@ -92,13 +93,15 @@ type NQL_ConditionValue<T, Parameters, Titem = NoInfer<T extends (infer X)[] ? X
|
|
|
92
93
|
'.': P;
|
|
93
94
|
} | {
|
|
94
95
|
'.': PArr;
|
|
95
|
-
}[]
|
|
96
|
+
}[] | {
|
|
97
|
+
'$': string;
|
|
98
|
+
};
|
|
96
99
|
/**
|
|
97
100
|
* A field name of the subquery bucket which resolves to
|
|
98
101
|
* a type that's compatible with the query
|
|
99
102
|
*/
|
|
100
|
-
type NQL_SubQueryField<$ extends $Bucket, Field,
|
|
101
|
-
[X in keyof
|
|
103
|
+
type NQL_SubQueryField<$ extends $Bucket, Field, Querypath = NoInfer<$['#modelpath']>, T = NoInfer<Querypath[Field & keyof Querypath]>> = keyof {
|
|
104
|
+
[X in keyof Querypath as NonNullable<T> extends NonNullable<Querypath[X]> ? X : never]: any;
|
|
102
105
|
};
|
|
103
106
|
/**
|
|
104
107
|
* A subquery passed as value to a query
|
|
@@ -120,14 +123,14 @@ type NQL_GraphLinks<M extends $Module, $ extends $Bucket, Parameters = {}> = {
|
|
|
120
123
|
All possible query rules on the format:
|
|
121
124
|
(or |)FIELDNAME( not|)OPERATOR
|
|
122
125
|
*/
|
|
123
|
-
type NQL_Terms<M extends $Module, $ extends $Bucket, Parameters = {},
|
|
124
|
-
[Field in keyof
|
|
125
|
-
[Op in NQL_OpFromField<
|
|
126
|
+
type NQL_Terms<M extends $Module, $ extends $Bucket, Parameters = {}, Querypath = NoInfer<$['#querypath']>, Conditions = NoInfer<{
|
|
127
|
+
[Field in keyof Querypath as Field]: {
|
|
128
|
+
[Op in NQL_OpFromField<Querypath[Field]> as `${'or ' | ''}${Field & string}${' not' | ''}${Op}`]?: NQL_ConditionValue<NQL_ValueFromOp<Querypath[Field]>[Op], Parameters> | NQL_SubQuery<M, Field, Parameters>;
|
|
126
129
|
};
|
|
127
130
|
}>> = Conditions[keyof Conditions] & {
|
|
128
131
|
[K in `${'#and' | '#or'}${string}`]?: NQL_Terms<M, $, Parameters>;
|
|
129
132
|
} & NQL_GraphLinks<M, $, Parameters> & {
|
|
130
|
-
'#order'?: NQL_Order<
|
|
133
|
+
'#order'?: NQL_Order<Querypath>;
|
|
131
134
|
};
|
|
132
135
|
/**
|
|
133
136
|
* NQL Dynamic Query Type
|
|
@@ -86,14 +86,16 @@ class NQL_RuleTree {
|
|
|
86
86
|
let by = value['by'];
|
|
87
87
|
if (by) {
|
|
88
88
|
for (const key of by) {
|
|
89
|
-
const
|
|
90
|
-
if (!
|
|
89
|
+
const fields = bucket_model_schema_1.$BucketModel.getField(bucket.schema.model, key);
|
|
90
|
+
if (!fields.length) {
|
|
91
91
|
throw new Error(`Field '${key}' not found on bucket '${bucket.schema.name}'`);
|
|
92
92
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
93
|
+
for (const field of fields) {
|
|
94
|
+
if (![
|
|
95
|
+
'date', 'datetime', 'duration', 'decimal', 'enum', 'float', 'int', 'string'
|
|
96
|
+
].includes(field.type)) {
|
|
97
|
+
throw new Error(`Field '${key}' is not sortable`);
|
|
98
|
+
}
|
|
97
99
|
}
|
|
98
100
|
}
|
|
99
101
|
}
|
|
@@ -141,25 +143,46 @@ class NQL_RuleTree {
|
|
|
141
143
|
throw new Error(`Invalid term '${key}'`);
|
|
142
144
|
}
|
|
143
145
|
const [_, or, fieldpath, not, case_i, op] = term;
|
|
144
|
-
const
|
|
145
|
-
if (!
|
|
146
|
+
const fields = bucket_model_schema_1.$BucketModel.getField(bucket.schema.model, fieldpath);
|
|
147
|
+
if (!fields.length) {
|
|
146
148
|
throw new Error(`Field '${fieldpath}' not found on bucket '${bucket.schema.name}'`);
|
|
147
149
|
}
|
|
148
|
-
const _op = this.parseOp(bucket.schema.name,
|
|
150
|
+
const _op = this.parseOp(bucket.schema.name, fields, op);
|
|
149
151
|
return { type: 'fieldpath', or: !!or, fieldpath, not: !!not, case_i: !!case_i, op: _op };
|
|
150
152
|
}
|
|
151
153
|
}
|
|
152
|
-
parseOp(bucketName,
|
|
154
|
+
parseOp(bucketName, fields, op) {
|
|
153
155
|
const _op = (op === '' ? '==' : op);
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
156
|
+
for (const field of fields) {
|
|
157
|
+
if (![
|
|
158
|
+
'==', '>', '<', '>=', '<=',
|
|
159
|
+
'in', 'contains', 'contains_any', 'present'
|
|
160
|
+
].includes(_op)) {
|
|
161
|
+
throw new Error(`Invalid operation '${_op}'`);
|
|
162
|
+
}
|
|
163
|
+
let allowedOps;
|
|
164
|
+
// If field is a union, use the intersection of allowed operations
|
|
165
|
+
if (field.type === 'union') {
|
|
166
|
+
const children = Object.values(field.children);
|
|
167
|
+
const opsUnion = children
|
|
168
|
+
.map(f => NQL_RuleTree.OpByType[f.type])
|
|
169
|
+
.flat(1);
|
|
170
|
+
const dict = {};
|
|
171
|
+
for (const op of opsUnion) {
|
|
172
|
+
dict[op] ?? (dict[op] = 0);
|
|
173
|
+
dict[op]++;
|
|
174
|
+
}
|
|
175
|
+
allowedOps = Object.entries(dict)
|
|
176
|
+
.filter(([k, v]) => v === children.length)
|
|
177
|
+
.map(([k]) => k);
|
|
178
|
+
}
|
|
179
|
+
// If not, use the field allowed operations
|
|
180
|
+
else {
|
|
181
|
+
allowedOps = NQL_RuleTree.OpByType[field.type];
|
|
182
|
+
}
|
|
183
|
+
if (!allowedOps.includes(_op)) {
|
|
184
|
+
throw new Error(`Field '${field.name}' of type '${field.type}' doesn't support operation '${_op}'`);
|
|
185
|
+
}
|
|
163
186
|
}
|
|
164
187
|
return _op;
|
|
165
188
|
}
|
|
@@ -223,7 +246,7 @@ class NQL_RuleTree {
|
|
|
223
246
|
if (!bucket) {
|
|
224
247
|
throw new Error(`Bucket '${bucket}' not found on module`);
|
|
225
248
|
}
|
|
226
|
-
const field = bucket_model_schema_1.$BucketModel.
|
|
249
|
+
const field = bucket_model_schema_1.$BucketModel.getField(bucket.schema.model, fieldpath);
|
|
227
250
|
if (!field) {
|
|
228
251
|
throw new Error(`Field '${fieldpath}' not found on bucket '${bucket.schema.name}'`);
|
|
229
252
|
}
|
|
@@ -442,8 +465,10 @@ NQL_RuleTree.OpByType = {
|
|
|
442
465
|
'file': [],
|
|
443
466
|
'float': ['<', '<=', '==', '>', '>=', 'in', 'present'],
|
|
444
467
|
'int': ['<', '<=', '==', '>', '>=', 'in', 'present'],
|
|
445
|
-
'obj': ['==', 'contains', 'contains_any', 'in', 'present'],
|
|
446
468
|
'string': ['==', 'contains', 'contains_any', 'in', 'present'],
|
|
469
|
+
'obj': ['contains_any', 'in', 'present'],
|
|
470
|
+
'list': ['contains', 'contains_any', 'present'],
|
|
471
|
+
'union': [],
|
|
447
472
|
'unknown': ['present']
|
|
448
473
|
};
|
|
449
474
|
/**
|
|
@@ -21,7 +21,7 @@ class BucketViewBuilder {
|
|
|
21
21
|
static build(builder, model, graph, views) {
|
|
22
22
|
const fields = bucket_view_field_builder_1.BucketViewFieldBuilder.buildFields(builder._fields, model, graph, views);
|
|
23
23
|
const schema = new bucket_view_schema_1.$BucketView(builder.name, fields);
|
|
24
|
-
schema.fields.id = new bucket_view_schema_1.$BucketViewField('id', 'model', 'id',
|
|
24
|
+
schema.fields.id = new bucket_view_schema_1.$BucketViewField('id', 'model', 'id', { model: { path: 'id' } });
|
|
25
25
|
return schema;
|
|
26
26
|
}
|
|
27
27
|
}
|
|
@@ -11,4 +11,23 @@ export declare class BucketView<$ extends $BucketView> {
|
|
|
11
11
|
schema: $;
|
|
12
12
|
constructor(bucket: Bucket<any, any>, schema: $);
|
|
13
13
|
parse<Obj extends NesoiObj>(trx: AnyTrxNode, raw: Obj): Promise<$['#data']>;
|
|
14
|
+
private parseLayer;
|
|
15
|
+
/**
|
|
16
|
+
* [model]
|
|
17
|
+
* Read one property from
|
|
18
|
+
*/
|
|
19
|
+
private parseModelProp;
|
|
20
|
+
private doParseModelProp;
|
|
21
|
+
/**
|
|
22
|
+
* [computed]
|
|
23
|
+
*/
|
|
24
|
+
private parseComputedProp;
|
|
25
|
+
/**
|
|
26
|
+
* [graph]
|
|
27
|
+
*/
|
|
28
|
+
private parseGraphProp;
|
|
29
|
+
/**
|
|
30
|
+
* [drive]
|
|
31
|
+
*/
|
|
32
|
+
private parseDriveProp;
|
|
14
33
|
}
|
|
@@ -5,8 +5,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.BucketView = void 0;
|
|
7
7
|
const promise_1 = __importDefault(require("../../../../engine/util/promise"));
|
|
8
|
-
const tree_1 = require("../../../../engine/data/tree");
|
|
9
8
|
const error_1 = require("../../../../engine/data/error");
|
|
9
|
+
const tree_1 = require("../../../../engine/data/tree");
|
|
10
|
+
class ViewValue {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.value = undefined;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
10
15
|
/**
|
|
11
16
|
* @category Elements
|
|
12
17
|
* @subcategory Entity
|
|
@@ -17,123 +22,240 @@ class BucketView {
|
|
|
17
22
|
this.schema = schema;
|
|
18
23
|
}
|
|
19
24
|
async parse(trx, raw) {
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
25
|
+
const parsed = {};
|
|
26
|
+
if ('__raw' in this.schema.fields) {
|
|
27
|
+
Object.assign(parsed, raw);
|
|
28
|
+
}
|
|
29
|
+
let layer = Object.values(this.schema.fields).map(field => ({
|
|
30
|
+
field,
|
|
31
|
+
data: [{
|
|
32
|
+
value: raw,
|
|
33
|
+
index: [],
|
|
34
|
+
target: parsed
|
|
35
|
+
}]
|
|
36
|
+
}));
|
|
37
|
+
while (layer.length) {
|
|
38
|
+
layer = await this.parseLayer(trx, raw, layer);
|
|
39
|
+
}
|
|
40
|
+
parsed['$v'] = this.schema.name;
|
|
41
|
+
return {
|
|
42
|
+
id: raw.id,
|
|
43
|
+
...parsed
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
async parseLayer(trx, raw, layer) {
|
|
47
|
+
const next = [];
|
|
48
|
+
// Model props
|
|
49
|
+
for (const node of layer) {
|
|
50
|
+
if (node.field.scope !== 'model')
|
|
51
|
+
continue;
|
|
52
|
+
next.push(...this.parseModelProp(raw, node));
|
|
53
|
+
}
|
|
54
|
+
// Computed props
|
|
55
|
+
for (const node of layer) {
|
|
56
|
+
if (node.field.scope !== 'computed')
|
|
57
|
+
continue;
|
|
58
|
+
await this.parseComputedProp(trx, raw, node);
|
|
59
|
+
}
|
|
60
|
+
// Graph props
|
|
61
|
+
for (const node of layer) {
|
|
62
|
+
if (node.field.scope !== 'graph')
|
|
63
|
+
continue;
|
|
64
|
+
await this.parseGraphProp(trx, raw, node);
|
|
65
|
+
}
|
|
66
|
+
// Drive props
|
|
67
|
+
for (const node of layer) {
|
|
68
|
+
if (node.field.scope !== 'drive')
|
|
69
|
+
continue;
|
|
70
|
+
await this.parseDriveProp(trx, raw, node);
|
|
71
|
+
}
|
|
72
|
+
// Group props
|
|
73
|
+
for (const node of layer) {
|
|
74
|
+
if (node.field.scope !== 'group')
|
|
75
|
+
continue;
|
|
76
|
+
if (!node.field.children)
|
|
77
|
+
continue;
|
|
78
|
+
if ('__raw' in node.field.children) {
|
|
79
|
+
for (const d of node.data) {
|
|
80
|
+
d.target[node.field.name] = d.value;
|
|
59
81
|
}
|
|
60
|
-
parsedObj[k] = await promise_1.default.solve(link);
|
|
61
82
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
83
|
+
next.push(...Object.values(node.field.children).map(field => ({
|
|
84
|
+
field,
|
|
85
|
+
data: node.data
|
|
86
|
+
})));
|
|
87
|
+
}
|
|
88
|
+
// Chains
|
|
89
|
+
for (const node of layer) {
|
|
90
|
+
if (!node.field.chain)
|
|
91
|
+
continue;
|
|
92
|
+
next.push({
|
|
93
|
+
field: node.field.chain,
|
|
94
|
+
data: node.data.map(d => ({
|
|
95
|
+
index: d.index,
|
|
96
|
+
target: d.target,
|
|
97
|
+
value: d.target[node.field.name]
|
|
98
|
+
}))
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
return next;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* [model]
|
|
105
|
+
* Read one property from
|
|
106
|
+
*/
|
|
107
|
+
parseModelProp(raw, node) {
|
|
108
|
+
const initAs = (!node.field.children) ? 'value' : 'obj';
|
|
109
|
+
const rawChild = '__raw' in (node.field.children || {});
|
|
110
|
+
const nextData = this.doParseModelProp(raw, node, initAs, rawChild);
|
|
111
|
+
if (!node.field.children)
|
|
112
|
+
return [];
|
|
113
|
+
const next = [];
|
|
114
|
+
for (const key in node.field.children) {
|
|
115
|
+
if (key === '__raw')
|
|
116
|
+
continue;
|
|
117
|
+
next.push({
|
|
118
|
+
field: node.field.children[key],
|
|
119
|
+
data: nextData
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
return next;
|
|
123
|
+
}
|
|
124
|
+
doParseModelProp(raw, node, initAs, rawChild) {
|
|
125
|
+
const modelpath = node.field.meta.model.path;
|
|
126
|
+
const paths = modelpath.split('.');
|
|
127
|
+
const name = node.field.name;
|
|
128
|
+
let poll = node.data.map(d => ({
|
|
129
|
+
...d,
|
|
130
|
+
value: raw,
|
|
131
|
+
key: name
|
|
132
|
+
}));
|
|
133
|
+
for (const path of paths) {
|
|
134
|
+
// *
|
|
135
|
+
if (path === '*') {
|
|
136
|
+
// Expand each value of the poll (assumed to be a dict or list)
|
|
137
|
+
poll = poll.map(item => {
|
|
138
|
+
if (typeof item.value !== 'object') {
|
|
139
|
+
throw new Error(`Failed to parse ${paths}, intermediate value ${item.value} is not a list or object`);
|
|
80
140
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
continue;
|
|
92
|
-
}
|
|
93
|
-
if (prop.scope !== 'group') {
|
|
94
|
-
continue;
|
|
95
|
-
}
|
|
96
|
-
parsedObj[k] = await doParse(prop.children || {}, index);
|
|
97
|
-
}
|
|
98
|
-
return parsedObj;
|
|
99
|
-
};
|
|
100
|
-
const parseModelProp = async (obj, prop, index, key) => {
|
|
101
|
-
const value = prop.value.model;
|
|
102
|
-
const rawValue = tree_1.Tree.get(obj, key || value.key, index);
|
|
103
|
-
if (prop.children) {
|
|
104
|
-
if (prop.array) {
|
|
105
|
-
if (!Array.isArray(rawValue)) {
|
|
106
|
-
return undefined;
|
|
141
|
+
if (Array.isArray(item.value)) {
|
|
142
|
+
item.target[item.key] = initAs === 'value'
|
|
143
|
+
? [...item.value]
|
|
144
|
+
: item.value.map(() => ({}));
|
|
145
|
+
return item.value.map((v, i) => ({
|
|
146
|
+
index: [...item.index, i],
|
|
147
|
+
value: v,
|
|
148
|
+
target: item.target[item.key],
|
|
149
|
+
key: i
|
|
150
|
+
}));
|
|
107
151
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
152
|
+
else {
|
|
153
|
+
item.target[item.key] = initAs === 'value'
|
|
154
|
+
? { ...item.value }
|
|
155
|
+
: Object.fromEntries(Object.entries(item.value).map(([k]) => [k, {}]));
|
|
156
|
+
return Object.entries(item.value).map(([k, v]) => ({
|
|
157
|
+
index: [...item.index, k],
|
|
158
|
+
value: v,
|
|
159
|
+
target: item.target[item.key],
|
|
160
|
+
key: k
|
|
161
|
+
}));
|
|
112
162
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
163
|
+
}).flat(1);
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
// $1, $2.. or string|number
|
|
167
|
+
else {
|
|
168
|
+
// Walk each node
|
|
169
|
+
const next = [];
|
|
170
|
+
for (const item of poll) {
|
|
171
|
+
// $0, $1.. -> string
|
|
172
|
+
const idx = path.match(/^\$(\d+)/)?.[1];
|
|
173
|
+
let _path = path;
|
|
174
|
+
if (idx !== undefined) {
|
|
175
|
+
// Replace by index key
|
|
176
|
+
_path = item.index[parseInt(idx)];
|
|
118
177
|
}
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
178
|
+
const n = typeof item.value === 'object'
|
|
179
|
+
? item.value[_path]
|
|
180
|
+
: undefined;
|
|
181
|
+
item.target[item.key] = initAs === 'value'
|
|
182
|
+
? n
|
|
183
|
+
: {};
|
|
184
|
+
if (n !== undefined) {
|
|
185
|
+
next.push({
|
|
186
|
+
index: item.index,
|
|
187
|
+
value: n,
|
|
188
|
+
target: item.target,
|
|
189
|
+
key: item.key
|
|
190
|
+
});
|
|
122
191
|
}
|
|
123
|
-
return parsedDict;
|
|
124
192
|
}
|
|
125
|
-
|
|
126
|
-
|
|
193
|
+
poll = next;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
// For each leaf, if it's an object (not an array),
|
|
197
|
+
// pre-fill with it's value.
|
|
198
|
+
// This means that ...$.raw() only works on modelpaths that
|
|
199
|
+
// result in an object. Otherwise, it's ignored.
|
|
200
|
+
if (rawChild) {
|
|
201
|
+
for (const data of poll) {
|
|
202
|
+
if (typeof data.value === 'object' && !Array.isArray(data.value)) {
|
|
203
|
+
data.target[data.key] = data.value;
|
|
127
204
|
}
|
|
128
205
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
206
|
+
}
|
|
207
|
+
return poll.map(p => ({
|
|
208
|
+
index: p.index,
|
|
209
|
+
value: p.value,
|
|
210
|
+
target: p.target[p.key]
|
|
211
|
+
}));
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* [computed]
|
|
215
|
+
*/
|
|
216
|
+
async parseComputedProp(trx, raw, node) {
|
|
217
|
+
const meta = node.field.meta.computed;
|
|
218
|
+
for (const entry of node.data) {
|
|
219
|
+
entry.target[node.field.name] = await promise_1.default.solve(meta.fn({ trx, raw, bucket: this.bucket.schema }));
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* [graph]
|
|
224
|
+
*/
|
|
225
|
+
async parseGraphProp(trx, raw, node) {
|
|
226
|
+
const meta = node.field.meta.graph;
|
|
227
|
+
for (const entry of node.data) {
|
|
228
|
+
let link;
|
|
229
|
+
if (!meta.view) {
|
|
230
|
+
link = this.bucket.graph.readLink(trx, raw, meta.link, { silent: true });
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
link = this.bucket.graph.viewLink(trx, raw, meta.link, meta.view, { silent: true });
|
|
234
|
+
}
|
|
235
|
+
entry.target[node.field.name] = await promise_1.default.solve(link);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* [drive]
|
|
240
|
+
*/
|
|
241
|
+
async parseDriveProp(trx, raw, node) {
|
|
242
|
+
if (!this.bucket.drive) {
|
|
243
|
+
throw error_1.NesoiError.Bucket.Drive.NoAdapter({ bucket: this.bucket.schema.alias });
|
|
244
|
+
}
|
|
245
|
+
const meta = node.field.meta.drive;
|
|
246
|
+
for (const entry of node.data) {
|
|
247
|
+
const value = tree_1.Tree.get(raw, meta.path);
|
|
248
|
+
if (Array.isArray(value)) {
|
|
249
|
+
const public_urls = [];
|
|
250
|
+
for (const obj of value) {
|
|
251
|
+
public_urls.push(await this.bucket.drive.public(obj));
|
|
252
|
+
}
|
|
253
|
+
entry.target[node.field.name] = public_urls;
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
entry.target[node.field.name] = await this.bucket.drive.public(value);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
137
259
|
}
|
|
138
260
|
}
|
|
139
261
|
exports.BucketView = BucketView;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { $BucketModelFieldType } from '../model/bucket_model.schema';
|
|
2
1
|
import { $Bucket } from '../bucket.schema';
|
|
3
2
|
import { AnyTrxNode } from "../../../../engine/transaction/trx_node";
|
|
4
3
|
export type $BucketViewFieldFn<TrxNode extends AnyTrxNode, B extends $Bucket> = (ctx: {
|
|
@@ -6,10 +5,9 @@ export type $BucketViewFieldFn<TrxNode extends AnyTrxNode, B extends $Bucket> =
|
|
|
6
5
|
raw: B['#data'];
|
|
7
6
|
bucket: $Bucket;
|
|
8
7
|
}) => any | Promise<any>;
|
|
9
|
-
export type $
|
|
8
|
+
export type $BucketViewFieldMeta = {
|
|
10
9
|
model?: {
|
|
11
|
-
|
|
12
|
-
enumOptions?: string | string[];
|
|
10
|
+
path: string;
|
|
13
11
|
};
|
|
14
12
|
graph?: {
|
|
15
13
|
link: string;
|
|
@@ -24,7 +22,6 @@ export type $BucketViewFieldValue = {
|
|
|
24
22
|
drive?: {
|
|
25
23
|
path: string;
|
|
26
24
|
};
|
|
27
|
-
group?: {};
|
|
28
25
|
};
|
|
29
26
|
/**
|
|
30
27
|
* @category Schemas
|
|
@@ -33,15 +30,13 @@ export type $BucketViewFieldValue = {
|
|
|
33
30
|
export declare class $BucketViewField {
|
|
34
31
|
name: string;
|
|
35
32
|
scope: 'model' | 'graph' | 'computed' | 'group' | 'view' | 'drive';
|
|
36
|
-
type: $BucketModelFieldType | 'id';
|
|
37
33
|
alias: string;
|
|
38
|
-
|
|
39
|
-
required: boolean;
|
|
40
|
-
value: $BucketViewFieldValue;
|
|
34
|
+
meta: $BucketViewFieldMeta;
|
|
41
35
|
children?: $BucketViewFields | undefined;
|
|
36
|
+
chain?: $BucketViewField | undefined;
|
|
42
37
|
$t: string;
|
|
43
38
|
'#data': unknown;
|
|
44
|
-
constructor(name: string, scope: 'model' | 'graph' | 'computed' | 'group' | 'view' | 'drive',
|
|
39
|
+
constructor(name: string, scope: 'model' | 'graph' | 'computed' | 'group' | 'view' | 'drive', alias: string, meta: $BucketViewFieldMeta, children?: $BucketViewFields | undefined, chain?: $BucketViewField | undefined);
|
|
45
40
|
}
|
|
46
41
|
export type $BucketViewFields = {
|
|
47
42
|
[x: string]: $BucketViewField;
|
|
@@ -6,15 +6,13 @@ exports.$BucketView = exports.$BucketViewField = void 0;
|
|
|
6
6
|
* @subcategory Entity
|
|
7
7
|
* */
|
|
8
8
|
class $BucketViewField {
|
|
9
|
-
constructor(name, scope,
|
|
9
|
+
constructor(name, scope, alias, meta, children, chain) {
|
|
10
10
|
this.name = name;
|
|
11
11
|
this.scope = scope;
|
|
12
|
-
this.type = type;
|
|
13
12
|
this.alias = alias;
|
|
14
|
-
this.
|
|
15
|
-
this.required = required;
|
|
16
|
-
this.value = value;
|
|
13
|
+
this.meta = meta;
|
|
17
14
|
this.children = children;
|
|
15
|
+
this.chain = chain;
|
|
18
16
|
this.$t = 'bucket.view.field';
|
|
19
17
|
}
|
|
20
18
|
}
|