nesoi 3.1.0 → 3.1.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/apps/monolyth/stages/2_build_typescript_stage.js +1 -0
- package/lib/compiler/elements/bucket.element.d.ts +2 -2
- package/lib/compiler/elements/bucket.element.js +25 -13
- package/lib/compiler/elements/element.js +2 -1
- package/lib/compiler/elements/machine.element.js +2 -2
- package/lib/compiler/elements/message.element.js +3 -2
- package/lib/compiler/helpers/dump_helpers.d.ts +5 -5
- package/lib/compiler/helpers/dump_helpers.js +37 -30
- package/lib/compiler/typescript/typescript_compiler.js +3 -0
- 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/bucket.js +35 -27
- package/lib/elements/entities/bucket/cache/bucket_cache.d.ts +1 -4
- package/lib/elements/entities/bucket/model/bucket_model.infer.d.ts +2 -6
- package/lib/elements/entities/bucket/model/bucket_model.schema.d.ts +4 -1
- package/lib/elements/entities/bucket/model/bucket_model.schema.js +125 -5
- package/lib/elements/entities/bucket/model/bucket_model_field.builder.d.ts +7 -7
- package/lib/elements/entities/bucket/query/nql.schema.d.ts +1 -1
- package/lib/elements/entities/message/template/message_template_parser.js +6 -3
- package/lib/engine/space.js +1 -1
- package/lib/engine/transaction/nodes/bucket.trx_node.d.ts +15 -0
- package/lib/engine/transaction/nodes/bucket.trx_node.js +24 -0
- 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.js +2 -2
- package/package.json +1 -1
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -62,12 +62,13 @@ class $BucketModel {
|
|
|
62
62
|
});
|
|
63
63
|
continue;
|
|
64
64
|
}
|
|
65
|
-
// If it's an object, walk it's children
|
|
65
|
+
// If it's an object and the path is '*', walk all of it's children
|
|
66
66
|
if (field.type === 'obj' && path === '*') {
|
|
67
67
|
next.push(...Object.values(field.children).map(field => ({
|
|
68
68
|
i: item.i + 1,
|
|
69
69
|
field
|
|
70
70
|
})));
|
|
71
|
+
continue;
|
|
71
72
|
}
|
|
72
73
|
const child = field.children[path];
|
|
73
74
|
if (child) {
|
|
@@ -98,22 +99,141 @@ class $BucketModel {
|
|
|
98
99
|
}
|
|
99
100
|
return fields;
|
|
100
101
|
}
|
|
101
|
-
static
|
|
102
|
-
let poll = Object.
|
|
102
|
+
static forEachField(model, predicate) {
|
|
103
|
+
let poll = Object.entries(model.fields).map(([path, field]) => ({ path, field }));
|
|
103
104
|
while (poll.length) {
|
|
104
105
|
const next = [];
|
|
105
106
|
for (const obj of poll) {
|
|
106
|
-
|
|
107
|
+
predicate(obj.field, obj.path);
|
|
107
108
|
if (obj.field.children) {
|
|
108
109
|
next.push(...Object.values(obj.field.children)
|
|
109
110
|
.map((field, i) => ({
|
|
110
111
|
field,
|
|
111
|
-
|
|
112
|
+
path: obj.path + '.' + (obj.field.type === 'union' ? i : field.name)
|
|
113
|
+
})));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
poll = next;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
static copy(model, obj, meta = {
|
|
120
|
+
created_at: 'created_at',
|
|
121
|
+
created_by: 'created_by',
|
|
122
|
+
updated_at: 'updated_at',
|
|
123
|
+
updated_by: 'updated_by',
|
|
124
|
+
}) {
|
|
125
|
+
const copy = {};
|
|
126
|
+
let poll = Object.entries(model.fields).map(([path, field]) => ({ path, obj, copy, field }));
|
|
127
|
+
while (poll.length) {
|
|
128
|
+
const next = [];
|
|
129
|
+
for (const entry of poll) {
|
|
130
|
+
const val = obj[entry.path];
|
|
131
|
+
if (val === undefined) {
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
if (val === null) {
|
|
135
|
+
copy[entry.path] = null;
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
if (entry.field.type === 'list') {
|
|
139
|
+
if (!Array.isArray(val))
|
|
140
|
+
continue;
|
|
141
|
+
copy[entry.path] = [];
|
|
142
|
+
next.push(...val.map((_, i) => ({
|
|
143
|
+
path: i.toString(),
|
|
144
|
+
obj: val,
|
|
145
|
+
copy: copy[entry.path],
|
|
146
|
+
field: entry.field.children['*']
|
|
147
|
+
})));
|
|
148
|
+
}
|
|
149
|
+
else if (entry.field.type === 'dict') {
|
|
150
|
+
if (typeof val !== 'object' || Array.isArray(val))
|
|
151
|
+
continue;
|
|
152
|
+
copy[entry.path] = {};
|
|
153
|
+
next.push(...Object.keys(val).map((path) => ({
|
|
154
|
+
path,
|
|
155
|
+
obj: val,
|
|
156
|
+
copy: copy[entry.path],
|
|
157
|
+
field: entry.field.children['*']
|
|
158
|
+
})));
|
|
159
|
+
}
|
|
160
|
+
else if (entry.field.type === 'obj') {
|
|
161
|
+
if (typeof val !== 'object' || Array.isArray(val))
|
|
162
|
+
continue;
|
|
163
|
+
copy[entry.path] = {};
|
|
164
|
+
next.push(...Object.keys(entry.field.children).map(path => ({
|
|
165
|
+
path: path,
|
|
166
|
+
obj: val,
|
|
167
|
+
copy: copy[entry.path],
|
|
168
|
+
field: entry.field.children[path]
|
|
112
169
|
})));
|
|
113
170
|
}
|
|
171
|
+
else if (entry.field.type === 'union') {
|
|
172
|
+
// TODO: ??????????
|
|
173
|
+
copy[entry.path] = obj[entry.path];
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
copy[entry.path] = obj[entry.path];
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
poll = next;
|
|
180
|
+
}
|
|
181
|
+
copy[meta.created_at] = obj[meta.created_at];
|
|
182
|
+
copy[meta.created_by] = obj[meta.created_by];
|
|
183
|
+
copy[meta.updated_at] = obj[meta.updated_at];
|
|
184
|
+
copy[meta.updated_by] = obj[meta.updated_by];
|
|
185
|
+
return copy;
|
|
186
|
+
}
|
|
187
|
+
static getModelpaths(model) {
|
|
188
|
+
const modelpaths = {};
|
|
189
|
+
let poll = Object.entries(model.fields).map(([path, field]) => ({ path, field }));
|
|
190
|
+
while (poll.length) {
|
|
191
|
+
const next = [];
|
|
192
|
+
for (const obj of poll) {
|
|
193
|
+
if (obj.field.type === 'union') {
|
|
194
|
+
modelpaths[obj.path] = [obj.field];
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
modelpaths[obj.path] = [obj.field];
|
|
198
|
+
if (obj.field.children) {
|
|
199
|
+
if (obj.field.type === 'dict') {
|
|
200
|
+
modelpaths[obj.path + '{*}'] = [obj.field.children['#']];
|
|
201
|
+
}
|
|
202
|
+
else if (obj.field.type === 'list') {
|
|
203
|
+
modelpaths[obj.path + '[*]'] = [obj.field.children['#']];
|
|
204
|
+
}
|
|
205
|
+
else if (obj.field.type === 'obj') {
|
|
206
|
+
modelpaths[obj.path + '{*}'] = Object.values(obj.field.children);
|
|
207
|
+
}
|
|
208
|
+
for (const key in obj.field.children) {
|
|
209
|
+
const child = obj.field.children[key];
|
|
210
|
+
if (obj.field.type === 'dict') {
|
|
211
|
+
modelpaths[obj.path + '{$${number}}'] = [child];
|
|
212
|
+
next.push({
|
|
213
|
+
field: child,
|
|
214
|
+
path: obj.path + '{${string}}'
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
else if (obj.field.type === 'list') {
|
|
218
|
+
modelpaths[obj.path + '[$${number}]'] = [child];
|
|
219
|
+
next.push({
|
|
220
|
+
field: child,
|
|
221
|
+
path: obj.path + '[${number}]'
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
next.push({
|
|
226
|
+
field: child,
|
|
227
|
+
path: obj.path + '.' + child.name
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
114
233
|
}
|
|
115
234
|
poll = next;
|
|
116
235
|
}
|
|
236
|
+
return modelpaths;
|
|
117
237
|
}
|
|
118
238
|
}
|
|
119
239
|
exports.$BucketModel = $BucketModel;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { $Module, $Space } from "../../../../schema";
|
|
2
2
|
import { $BucketModelField, $BucketModelFieldType, $BucketModelFields } from './bucket_model.schema';
|
|
3
3
|
import { NesoiDate } from "../../../../engine/data/date";
|
|
4
|
-
import { BucketModelpathObjInfer, BucketModelObjInfer, BucketQuerypathDictInfer, BucketQuerypathListInfer, BucketQuerypathObjInfer, BucketModelpathUnionInfer } from './bucket_model.infer';
|
|
4
|
+
import { BucketModelpathObjInfer, BucketModelpathDictInfer, BucketModelpathListInfer, BucketModelObjInfer, BucketQuerypathDictInfer, BucketQuerypathListInfer, BucketQuerypathObjInfer, BucketModelpathUnionInfer } from './bucket_model.infer';
|
|
5
5
|
import { EnumFromName, EnumName } from '../../constants/constants.schema';
|
|
6
6
|
import { NesoiDecimal } from "../../../../engine/data/decimal";
|
|
7
7
|
import { NesoiDatetime } from "../../../../engine/data/datetime";
|
|
@@ -49,10 +49,10 @@ export declare class BucketModelFieldFactory<Space extends $Space, Module extend
|
|
|
49
49
|
}, {
|
|
50
50
|
'': NesoiDecimal;
|
|
51
51
|
}>;
|
|
52
|
-
enum<Enums extends EnumName<Space>, Options extends (keyof Enums & string) | (readonly string[])>(options: Options): BucketModelFieldBuilder<Module, Options extends string ? EnumFromName<Space, Options>["#data"] : Options extends (infer X)[] | readonly (infer X)[] ? X : Options[keyof Options], Options extends string ? EnumFromName<Space, Options>["#data"] : Options extends (infer X)[] | readonly (infer X)[] ? X : Options[keyof Options], [false, false], {
|
|
53
|
-
'': Options extends string ? EnumFromName<Space, Options>["#data"] : Options extends (infer X)[] | readonly (infer X)[] ? X : Options[keyof Options];
|
|
52
|
+
enum<Enums extends EnumName<Space>, Options extends (keyof Enums & string) | (readonly string[])>(options: Options): BucketModelFieldBuilder<Module, Options extends string ? keyof EnumFromName<Space, Options>["#data"] : Options extends (infer X)[] | readonly (infer X)[] ? X : Options[keyof Options], Options extends string ? keyof EnumFromName<Space, Options>["#data"] : Options extends (infer X)[] | readonly (infer X)[] ? X : Options[keyof Options], [false, false], {
|
|
53
|
+
'': Options extends string ? keyof EnumFromName<Space, Options>["#data"] : Options extends (infer X)[] | readonly (infer X)[] ? X : Options[keyof Options];
|
|
54
54
|
}, {
|
|
55
|
-
'': Options extends string ? EnumFromName<Space, Options>["#data"] : Options extends (infer X)[] | readonly (infer X)[] ? X : Options[keyof Options];
|
|
55
|
+
'': Options extends string ? keyof EnumFromName<Space, Options>["#data"] : Options extends (infer X)[] | readonly (infer X)[] ? X : Options[keyof Options];
|
|
56
56
|
}>;
|
|
57
57
|
get int(): BucketModelFieldBuilder<Module, number, number, [false, false], {
|
|
58
58
|
'': number;
|
|
@@ -83,7 +83,7 @@ export declare class BucketModelFieldFactory<Space extends $Space, Module extend
|
|
|
83
83
|
obj<T extends BucketModelFieldBuilders<Module>>(fields?: T): BucketModelFieldBuilder<Module, BucketModelObjInfer<T>, BucketModelObjInfer<T>, [false, false], {
|
|
84
84
|
'': BucketModelObjInfer<T>;
|
|
85
85
|
} & {
|
|
86
|
-
'.*': BucketModelObjInfer<T
|
|
86
|
+
'.*': BucketModelObjInfer<T>[keyof { [K in keyof T as T[K]["#optional"][1] extends true ? never : `${K & string}`]: T[K]["#output"]; } | keyof { [K_1 in keyof T as T[K_1]["#optional"][1] extends true ? `${K_1 & string}` : never]?: T[K_1]["#output"] | undefined; }];
|
|
87
87
|
} & BucketModelpathObjInfer<T>, {
|
|
88
88
|
'': BucketModelObjInfer<T>;
|
|
89
89
|
} & BucketQuerypathObjInfer<T>>;
|
|
@@ -94,7 +94,7 @@ export declare class BucketModelFieldFactory<Space extends $Space, Module extend
|
|
|
94
94
|
*/
|
|
95
95
|
dict<T extends BucketModelFieldBuilder<Module, any, any, any, any>>(dictItem: T): BucketModelFieldBuilder<Module, Record<string, T["#input"]>, Record<string, T["#output"]>, [false, false], {
|
|
96
96
|
'': Record<string, T["#output"]>;
|
|
97
|
-
} &
|
|
97
|
+
} & BucketModelpathDictInfer<T>, {
|
|
98
98
|
'': Record<string, T["#output"]>;
|
|
99
99
|
} & BucketQuerypathDictInfer<T>>;
|
|
100
100
|
/**
|
|
@@ -103,7 +103,7 @@ export declare class BucketModelFieldFactory<Space extends $Space, Module extend
|
|
|
103
103
|
*/
|
|
104
104
|
list<T extends BucketModelFieldBuilder<Module, any, any, any, any>>(listItem: T): BucketModelFieldBuilder<Module, T["#input"][], T["#output"][], [false, false], {
|
|
105
105
|
'': T["#output"][];
|
|
106
|
-
} &
|
|
106
|
+
} & BucketModelpathListInfer<T>, {
|
|
107
107
|
'': T["#output"][];
|
|
108
108
|
} & BucketQuerypathListInfer<T>>;
|
|
109
109
|
union<Builders extends AnyBucketModelFieldBuilder[]>(...children: Builders): BucketModelFieldBuilder<Module, Builders[number]["#input"], Builders[number]["#output"], [false, false], BucketModelpathUnionInfer<Builders>, Builders[number]["#querypath"]>;
|
|
@@ -51,7 +51,7 @@ export type NQL_Node = NQL_Union | NQL_Intersection | NQL_Rule;
|
|
|
51
51
|
*/
|
|
52
52
|
export type NQL_Operation = '==' | '>' | '<' | '>=' | '<=' | 'in' | 'contains' | 'contains_any' | 'present';
|
|
53
53
|
export type NQL_Order<Querypath> = {
|
|
54
|
-
by?: keyof Querypath[];
|
|
54
|
+
by?: (keyof Querypath)[];
|
|
55
55
|
dir?: ('asc' | 'desc')[];
|
|
56
56
|
};
|
|
57
57
|
export type NQL_Pagination = {
|
|
@@ -29,18 +29,21 @@ async function MessageTemplateFieldParser(trx, fields, raw) {
|
|
|
29
29
|
*/
|
|
30
30
|
async function parseFieldValue(trx, field, path, raw, value, inject) {
|
|
31
31
|
sanitize(field, path, value);
|
|
32
|
+
let output;
|
|
32
33
|
if (isEmpty(value)) {
|
|
33
34
|
if (field.required) {
|
|
34
35
|
throw error_1.NesoiError.Message.FieldIsRequired({ alias: field.alias, path: path.join('.'), value });
|
|
35
36
|
}
|
|
36
37
|
else if (field.defaultValue !== undefined) {
|
|
37
|
-
|
|
38
|
+
output = field.defaultValue;
|
|
38
39
|
}
|
|
39
40
|
else {
|
|
40
|
-
|
|
41
|
+
output = undefined;
|
|
41
42
|
}
|
|
42
43
|
}
|
|
43
|
-
|
|
44
|
+
else {
|
|
45
|
+
output = await _attemptUnion(trx, field, path, raw, value, inject);
|
|
46
|
+
}
|
|
44
47
|
output = await applyFieldRules(field, path, raw, output, inject);
|
|
45
48
|
return output;
|
|
46
49
|
}
|
package/lib/engine/space.js
CHANGED
|
@@ -301,7 +301,7 @@ class Space {
|
|
|
301
301
|
.filter(node => node.isDirectory());
|
|
302
302
|
for (const dir of dirs) {
|
|
303
303
|
const modulePath = path.join(dirpath, dir.name);
|
|
304
|
-
if (fs.existsSync(path.join(modulePath, '.
|
|
304
|
+
if (fs.existsSync(path.join(modulePath, '.subset'))) {
|
|
305
305
|
perform(modulePath, [...subdir, dir.name]);
|
|
306
306
|
}
|
|
307
307
|
else {
|
|
@@ -127,6 +127,21 @@ export declare class BucketTrxNode<M extends $Module, $ extends $Bucket> {
|
|
|
127
127
|
* **WARNING** Tenancy currently not implemented for put.
|
|
128
128
|
*/
|
|
129
129
|
put(obj: PutObj<$>): Promise<$['#data']>;
|
|
130
|
+
/**
|
|
131
|
+
* Create, replace or delete all the objects passed as an argument.
|
|
132
|
+
* Does the same for compositions of this bucket, from the
|
|
133
|
+
* `#composition` field passed in the message.
|
|
134
|
+
*
|
|
135
|
+
* - If `#composition` is wrong, this will throw an exception.
|
|
136
|
+
* - This will **REPLACE** objects and it's compositions if they already exist,
|
|
137
|
+
* so there might be unexpected data loss, use it carefully.
|
|
138
|
+
* - It will only delete an object from the bucket if it contains `id` and `__delete: true`.
|
|
139
|
+
*
|
|
140
|
+
* **WARNING** Tenancy currently not implemented for put.
|
|
141
|
+
*/
|
|
142
|
+
sync(objs: (PutObj<$> & {
|
|
143
|
+
__delete: boolean;
|
|
144
|
+
})[]): Promise<$['#data']>;
|
|
130
145
|
/**
|
|
131
146
|
* Attempts to read an object by `id`, if found, deletes it.
|
|
132
147
|
*
|
|
@@ -236,6 +236,30 @@ class BucketTrxNode {
|
|
|
236
236
|
async put(obj) {
|
|
237
237
|
return this.wrap('put', { obj }, trx => this.bucket.put(trx, obj), () => undefined);
|
|
238
238
|
}
|
|
239
|
+
/**
|
|
240
|
+
* Create, replace or delete all the objects passed as an argument.
|
|
241
|
+
* Does the same for compositions of this bucket, from the
|
|
242
|
+
* `#composition` field passed in the message.
|
|
243
|
+
*
|
|
244
|
+
* - If `#composition` is wrong, this will throw an exception.
|
|
245
|
+
* - This will **REPLACE** objects and it's compositions if they already exist,
|
|
246
|
+
* so there might be unexpected data loss, use it carefully.
|
|
247
|
+
* - It will only delete an object from the bucket if it contains `id` and `__delete: true`.
|
|
248
|
+
*
|
|
249
|
+
* **WARNING** Tenancy currently not implemented for put.
|
|
250
|
+
*/
|
|
251
|
+
async sync(objs) {
|
|
252
|
+
return this.wrap('put', { objs }, async (trx) => {
|
|
253
|
+
for (const obj of objs) {
|
|
254
|
+
if (obj.id && obj.__delete) {
|
|
255
|
+
await this.bucket.delete(trx, obj.id);
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
await this.bucket.put(trx, obj);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}, () => undefined);
|
|
262
|
+
}
|
|
239
263
|
/*
|
|
240
264
|
Delete
|
|
241
265
|
*/
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { $Module, $Space } from "../../elements";
|
|
2
2
|
import { BucketAdapter } from "../../elements/entities/bucket/adapters/bucket_adapter";
|
|
3
|
-
import {
|
|
3
|
+
import { Trx } from './trx';
|
|
4
4
|
import { AnyUsers } from '../auth/authn';
|
|
5
5
|
import { TrxNode, TrxNodeStatus } from './trx_node';
|
|
6
|
+
import { TrxData } from './trx_engine';
|
|
6
7
|
export type TrxEngineWrapFn<S extends $Space, M extends $Module> = (trx: TrxNode<S, M, any>) => Promise<TrxNodeStatus>;
|
|
7
8
|
export type TrxEngineConfig<S extends $Space, M extends $Module, Authn extends AnyUsers, Services extends Record<string, any>> = {
|
|
8
9
|
/**
|
|
9
10
|
* Adapter used to store transactions of this module.
|
|
10
11
|
*/
|
|
11
|
-
adapter?: (schema: M) => BucketAdapter<
|
|
12
|
+
adapter?: (schema: M) => BucketAdapter<TrxData>;
|
|
12
13
|
wrap?: <T extends Trx<S, M, Authn>>(trx: T, fn: TrxEngineWrapFn<S, M>, services: Services) => Promise<any>;
|
|
13
14
|
};
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import { $Module, $Space } from "../../schema";
|
|
2
2
|
import { Module } from '../module';
|
|
3
|
-
import { Trx } from './trx';
|
|
3
|
+
import { AnyTrx, Trx } from './trx';
|
|
4
4
|
import { TrxNode, TrxNodeStatus } from './trx_node';
|
|
5
5
|
import { AnyAuthnProviders, AuthnRequest } from '../auth/authn';
|
|
6
6
|
import { TrxEngineConfig } from './trx_engine.config';
|
|
7
7
|
import { IService } from '../apps/service';
|
|
8
8
|
export type TrxEngineOrigin = `app:${string}` | `plugin:${string}`;
|
|
9
|
+
export type TrxData = {
|
|
10
|
+
id: AnyTrx['id'];
|
|
11
|
+
origin: AnyTrx['origin'];
|
|
12
|
+
module: string;
|
|
13
|
+
start: AnyTrx['start'];
|
|
14
|
+
end: AnyTrx['end'];
|
|
15
|
+
};
|
|
9
16
|
/**
|
|
10
17
|
* @category Engine
|
|
11
18
|
* @subcategory Transaction
|
|
@@ -16,6 +23,7 @@ export declare class TrxEngine<S extends $Space, M extends $Module, Authn extend
|
|
|
16
23
|
private authnProviders?;
|
|
17
24
|
private config?;
|
|
18
25
|
private services;
|
|
26
|
+
private $TrxBucket;
|
|
19
27
|
/**
|
|
20
28
|
* Transaction used to read/write transactions on the adapter
|
|
21
29
|
*/
|
|
@@ -6,6 +6,9 @@ const trx_1 = require("./trx");
|
|
|
6
6
|
const trx_node_1 = require("./trx_node");
|
|
7
7
|
const error_1 = require("../data/error");
|
|
8
8
|
const memory_bucket_adapter_1 = require("../../elements/entities/bucket/adapters/memory.bucket_adapter");
|
|
9
|
+
const elements_1 = require("../../elements");
|
|
10
|
+
const bucket_model_schema_1 = require("../../elements/entities/bucket/model/bucket_model.schema");
|
|
11
|
+
const bucket_graph_schema_1 = require("../../elements/entities/bucket/graph/bucket_graph.schema");
|
|
9
12
|
/**
|
|
10
13
|
* @category Engine
|
|
11
14
|
* @subcategory Transaction
|
|
@@ -17,28 +20,56 @@ class TrxEngine {
|
|
|
17
20
|
this.authnProviders = authnProviders;
|
|
18
21
|
this.config = config;
|
|
19
22
|
this.services = services;
|
|
23
|
+
this.$TrxBucket = new elements_1.$Bucket(this.module.name, '__trx__', `Transaction of Module '${this.module.name}'`, new bucket_model_schema_1.$BucketModel({
|
|
24
|
+
id: new bucket_model_schema_1.$BucketModelField('id', 'id', 'string', 'ID', true),
|
|
25
|
+
origin: new bucket_model_schema_1.$BucketModelField('origin', 'origin', 'string', 'Origin', true),
|
|
26
|
+
module: new bucket_model_schema_1.$BucketModelField('module', 'module', 'string', 'Module', true),
|
|
27
|
+
start: new bucket_model_schema_1.$BucketModelField('start', 'start', 'datetime', 'Start', true),
|
|
28
|
+
end: new bucket_model_schema_1.$BucketModelField('end', 'end', 'datetime', 'Start', false),
|
|
29
|
+
}), new bucket_graph_schema_1.$BucketGraph(), {});
|
|
20
30
|
this.innerTrx = new trx_1.Trx(this, this.module, `trx:${origin}`);
|
|
21
|
-
this.adapter = config?.adapter?.(module.schema) || new memory_bucket_adapter_1.MemoryBucketAdapter(
|
|
31
|
+
this.adapter = config?.adapter?.(module.schema) || new memory_bucket_adapter_1.MemoryBucketAdapter(this.$TrxBucket, {});
|
|
22
32
|
}
|
|
23
33
|
getModule() {
|
|
24
34
|
return this.module;
|
|
25
35
|
}
|
|
26
36
|
async get(id) {
|
|
27
|
-
let trx
|
|
37
|
+
let trx;
|
|
28
38
|
if (!id) {
|
|
29
39
|
trx = new trx_1.Trx(this, this.module, this.origin);
|
|
30
40
|
log_1.Log.info('module', this.module.name, `Begin ${(0, log_1.scopeTag)('trx', trx.id)} @ ${(0, log_1.anyScopeTag)(this.origin)}`);
|
|
31
|
-
|
|
41
|
+
await this.adapter.create(this.innerTrx.root, {
|
|
42
|
+
id: trx.id,
|
|
43
|
+
origin: trx.origin,
|
|
44
|
+
start: trx.start,
|
|
45
|
+
end: trx.end,
|
|
46
|
+
module: this.module.name
|
|
47
|
+
});
|
|
48
|
+
return trx;
|
|
32
49
|
}
|
|
33
50
|
else {
|
|
34
|
-
|
|
35
|
-
if (
|
|
36
|
-
log_1.Log.info('module', this.module.name, `Continue ${(0, log_1.scopeTag)('trx',
|
|
51
|
+
const trxData = await this.adapter.get(this.innerTrx.root, id);
|
|
52
|
+
if (trxData) {
|
|
53
|
+
log_1.Log.info('module', this.module.name, `Continue ${(0, log_1.scopeTag)('trx', trxData.id)} @ ${(0, log_1.anyScopeTag)(this.origin)}`);
|
|
54
|
+
// Objects read from adapters are not the proper JS class, so they don't
|
|
55
|
+
// carry methods. This must be used to recover the methods.
|
|
56
|
+
trx = Object.assign(new trx_1.Trx(this, this.module, this.origin), {
|
|
57
|
+
id: trxData.id,
|
|
58
|
+
origin: trxData.origin,
|
|
59
|
+
start: trxData.start,
|
|
60
|
+
end: trxData.end
|
|
61
|
+
});
|
|
37
62
|
}
|
|
38
63
|
else {
|
|
39
64
|
log_1.Log.info('module', this.module.name, `Chain ${(0, log_1.scopeTag)('trx', id)} @ ${(0, log_1.anyScopeTag)(this.origin)}`);
|
|
40
65
|
trx = new trx_1.Trx(this, this.module, this.origin, undefined, id);
|
|
41
|
-
|
|
66
|
+
await this.adapter.create(this.innerTrx.root, {
|
|
67
|
+
id: trx.id,
|
|
68
|
+
origin: this.origin,
|
|
69
|
+
start: trx.start,
|
|
70
|
+
end: trx.end,
|
|
71
|
+
module: this.module.name
|
|
72
|
+
});
|
|
42
73
|
}
|
|
43
74
|
}
|
|
44
75
|
return trx;
|
|
@@ -87,7 +118,13 @@ class TrxEngine {
|
|
|
87
118
|
log_1.Log.info('module', this.module.name, `Commit ${(0, log_1.scopeTag)('trx', trx.id)} @ ${(0, log_1.anyScopeTag)(this.origin)}`);
|
|
88
119
|
await trx_node_1.TrxNode.ok(trx.root, output);
|
|
89
120
|
trx_1.Trx.onFinish(trx);
|
|
90
|
-
await this.adapter.put(this.innerTrx.root,
|
|
121
|
+
await this.adapter.put(this.innerTrx.root, {
|
|
122
|
+
id: trx.id,
|
|
123
|
+
origin: this.origin,
|
|
124
|
+
start: trx.start,
|
|
125
|
+
end: trx.end,
|
|
126
|
+
module: this.module.name
|
|
127
|
+
});
|
|
91
128
|
return trx;
|
|
92
129
|
}
|
|
93
130
|
async rollback(trx, error) {
|
|
@@ -95,7 +132,13 @@ class TrxEngine {
|
|
|
95
132
|
log_1.Log.warn('module', this.module.name, `Rollback ${(0, log_1.scopeTag)('trx', trx.id)} @ ${(0, log_1.anyScopeTag)(this.origin)}`);
|
|
96
133
|
await trx_node_1.TrxNode.error(trx.root, error);
|
|
97
134
|
trx_1.Trx.onFinish(trx);
|
|
98
|
-
await this.adapter.put(this.innerTrx.root,
|
|
135
|
+
await this.adapter.put(this.innerTrx.root, {
|
|
136
|
+
id: trx.id,
|
|
137
|
+
origin: this.origin,
|
|
138
|
+
start: trx.start,
|
|
139
|
+
end: trx.end,
|
|
140
|
+
module: this.module.name
|
|
141
|
+
});
|
|
99
142
|
return trx;
|
|
100
143
|
}
|
|
101
144
|
}
|
package/lib/engine/util/deep.js
CHANGED
|
@@ -10,6 +10,8 @@ class Deep {
|
|
|
10
10
|
for (const [obj, copy] of poll) {
|
|
11
11
|
if (Array.isArray(obj)) {
|
|
12
12
|
for (const item of obj) {
|
|
13
|
+
if (typeof item === 'function')
|
|
14
|
+
continue;
|
|
13
15
|
if (item === null) {
|
|
14
16
|
copy.push(null);
|
|
15
17
|
}
|
|
@@ -26,6 +28,8 @@ class Deep {
|
|
|
26
28
|
else {
|
|
27
29
|
for (const key in obj) {
|
|
28
30
|
const item = obj[key];
|
|
31
|
+
if (typeof item === 'function')
|
|
32
|
+
continue;
|
|
29
33
|
if (item === null) {
|
|
30
34
|
copy[key] = null;
|
|
31
35
|
}
|
package/lib/engine/util/parse.js
CHANGED
|
@@ -66,12 +66,12 @@ function parseEnum(raw, field, path, value, options, trx) {
|
|
|
66
66
|
const enumPath = enumName.match(/(.*)\.\{(.*)\}$/);
|
|
67
67
|
let _enum;
|
|
68
68
|
if (enumPath) {
|
|
69
|
-
|
|
69
|
+
const v = tree_1.Tree.get(raw, enumPath[2]);
|
|
70
|
+
enumName = enumPath[1] + '.' + v;
|
|
70
71
|
try {
|
|
71
72
|
_enum = trx.enum(enumName);
|
|
72
73
|
}
|
|
73
74
|
catch {
|
|
74
|
-
const v = tree_1.Tree.get(raw, enumPath[2]);
|
|
75
75
|
throw error_1.NesoiError.Message.InvalidEnumScope({ alias: field.alias, path: path.join('.'), value: v, fieldpath: enumPath[2] });
|
|
76
76
|
}
|
|
77
77
|
}
|