nesoi 3.3.30 → 3.4.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/elements/bucket.element.js +3 -3
- package/lib/elements/edge/controller/adapters/controller_adapter.js +1 -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 +15 -5
- package/lib/elements/entities/bucket/view/bucket_view_field.builder.js +82 -28
- package/lib/elements/entities/message/template/message_template_parser.d.ts +5 -1
- package/lib/elements/entities/message/template/message_template_parser.js +13 -7
- package/lib/engine/daemon.d.ts +1 -11
- package/lib/engine/daemon.js +3 -26
- package/lib/engine/data/datetime.d.ts +35 -1
- package/lib/engine/data/datetime.js +103 -16
- package/lib/engine/data/error.d.ts +17 -0
- package/lib/engine/data/error.js +16 -0
- package/lib/engine/transaction/nodes/bucket.trx_node.d.ts +8 -2
- package/lib/engine/transaction/nodes/bucket.trx_node.js +16 -4
- package/lib/engine/transaction/nodes/bucket_query.trx_node.js +1 -1
- package/lib/engine/transaction/nodes/external.trx_node.d.ts +4 -1
- package/lib/engine/transaction/nodes/external.trx_node.js +19 -19
- package/lib/engine/transaction/nodes/job.trx_node.d.ts +4 -3
- package/lib/engine/transaction/nodes/job.trx_node.js +6 -2
- package/lib/engine/transaction/nodes/resource.trx_node.js +2 -1
- package/lib/engine/transaction/trx.d.ts +4 -3
- package/lib/engine/transaction/trx.js +15 -11
- package/lib/engine/transaction/trx_engine.config.d.ts +7 -3
- package/lib/engine/transaction/trx_engine.d.ts +7 -3
- package/lib/engine/transaction/trx_engine.js +99 -45
- package/lib/engine/transaction/trx_node.d.ts +4 -1
- package/lib/engine/transaction/trx_node.js +12 -9
- 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
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { $Bucket } from '../bucket.schema';
|
|
2
2
|
import { AnyTrxNode } from "../../../../engine/transaction/trx_node";
|
|
3
|
-
export type $BucketViewFieldFn<TrxNode extends AnyTrxNode, B extends $Bucket,
|
|
3
|
+
export type $BucketViewFieldFn<TrxNode extends AnyTrxNode, B extends $Bucket, Parent, Value, Return = any> = (ctx: {
|
|
4
4
|
trx: TrxNode;
|
|
5
|
-
|
|
5
|
+
root: B['#data'];
|
|
6
|
+
parent: Parent;
|
|
6
7
|
value: Value;
|
|
7
8
|
bucket: $Bucket;
|
|
8
9
|
}) => any | Promise<any>;
|
|
@@ -37,9 +38,10 @@ export declare class $BucketViewField {
|
|
|
37
38
|
prop?: string | undefined;
|
|
38
39
|
children?: $BucketViewFields | undefined;
|
|
39
40
|
chain?: $BucketViewField | undefined;
|
|
41
|
+
as_dict?: number[] | undefined;
|
|
40
42
|
$t: string;
|
|
41
43
|
'#data': unknown;
|
|
42
|
-
constructor(name: string, scope: 'model' | 'graph' | 'computed' | 'group' | 'view' | 'drive', alias: string, meta: $BucketViewFieldMeta, prop?: string | undefined, children?: $BucketViewFields | undefined, chain?: $BucketViewField | undefined);
|
|
44
|
+
constructor(name: string, scope: 'model' | 'graph' | 'computed' | 'group' | 'view' | 'drive', alias: string, meta: $BucketViewFieldMeta, prop?: string | undefined, children?: $BucketViewFields | undefined, chain?: $BucketViewField | undefined, as_dict?: number[] | undefined);
|
|
43
45
|
}
|
|
44
46
|
export type $BucketViewFields = {
|
|
45
47
|
[x: string]: $BucketViewField;
|
|
@@ -13,9 +13,10 @@ class $BucketViewField {
|
|
|
13
13
|
prop;
|
|
14
14
|
children;
|
|
15
15
|
chain;
|
|
16
|
+
as_dict;
|
|
16
17
|
$t = 'bucket.view.field';
|
|
17
18
|
'#data';
|
|
18
|
-
constructor(name, scope, alias, meta, prop, children, chain) {
|
|
19
|
+
constructor(name, scope, alias, meta, prop, children, chain, as_dict) {
|
|
19
20
|
this.name = name;
|
|
20
21
|
this.scope = scope;
|
|
21
22
|
this.alias = alias;
|
|
@@ -23,6 +24,7 @@ class $BucketViewField {
|
|
|
23
24
|
this.prop = prop;
|
|
24
25
|
this.children = children;
|
|
25
26
|
this.chain = chain;
|
|
27
|
+
this.as_dict = as_dict;
|
|
26
28
|
}
|
|
27
29
|
}
|
|
28
30
|
exports.$BucketViewField = $BucketViewField;
|
|
@@ -19,11 +19,15 @@ type ComputedData<Fn extends $BucketViewFieldFn<any, any, any, any>, R = ReturnT
|
|
|
19
19
|
export declare class BucketViewFieldFactory<Space extends $Space, Module extends $Module, Bucket extends $Bucket> {
|
|
20
20
|
protected scope: $BucketViewField['scope'];
|
|
21
21
|
protected meta: $BucketViewField['meta'];
|
|
22
|
-
|
|
23
|
-
[K in keyof Bucket[
|
|
22
|
+
get inject(): {
|
|
23
|
+
readonly root: { [K in keyof Bucket["#data"]]: BucketViewFieldBuilder<Module, Bucket, Bucket, Bucket["#data"][K], "model">; };
|
|
24
|
+
readonly parent: { [K in keyof Bucket["#data"]]: BucketViewFieldBuilder<Module, Bucket, Bucket, Bucket["#data"][K], "model">; };
|
|
25
|
+
readonly value: { [K in keyof Bucket["#data"]]: BucketViewFieldBuilder<Module, Bucket, Bucket, Bucket["#data"][K], "model">; };
|
|
24
26
|
};
|
|
27
|
+
get root(): BucketViewFieldBuilder<Module, Bucket, Bucket, any, "model", never>;
|
|
28
|
+
get parent(): BucketViewFieldBuilder<Module, Bucket, Bucket, any, "model", never>;
|
|
29
|
+
get value(): BucketViewFieldBuilder<Module, Bucket, Bucket, any, "model", never>;
|
|
25
30
|
model<K extends keyof Bucket['#modelpath']>(path: K): BucketViewFieldBuilder<Module, Bucket, Bucket, Bucket["#modelpath"][K], "model", never>;
|
|
26
|
-
value(): BucketViewFieldBuilder<Module, Bucket, Bucket, any, "model", never>;
|
|
27
31
|
computed<Fn extends $BucketViewFieldFn<TrxNode<Space, Module, Space['authnUsers']>, Bucket, Bucket['#data'], Bucket['#data']>>(fn: Fn): BucketViewFieldBuilder<Module, Bucket, Bucket, ComputedData<Fn, ReturnType<Fn>>, "computed", never>;
|
|
28
32
|
graph<L extends keyof Bucket['graph']['links'], V extends (keyof Bucket['graph']['links'][L]['#bucket']['views']) | undefined>(link: L, view?: V): BucketViewFieldBuilder<Module, Bucket, Bucket["graph"]["links"][L]["#bucket"], Bucket["graph"]["links"][L]["#many"] extends true ? (undefined extends V ? Bucket["graph"]["links"][L]["#bucket"]["#data"] : ViewObj<Bucket["graph"]["links"][L]["#bucket"], NonNullable<V>>)[] : undefined extends V ? Bucket["graph"]["links"][L]["#bucket"]["#data"] : ViewObj<Bucket["graph"]["links"][L]["#bucket"], NonNullable<V>>, "graph", `${Bucket["graph"]["links"][L]["#bucket"]["name"]}.${V & string}`>;
|
|
29
33
|
drive<F extends DriveFieldpath<Bucket>>(path: F): BucketViewFieldBuilder<Module, Bucket, Bucket, string, "drive", never>;
|
|
@@ -41,11 +45,17 @@ export declare class BucketViewFieldBuilder<Module extends $Module, Bucket exten
|
|
|
41
45
|
protected subview?: (BucketViewFieldBuilders<any> | BucketViewDef<any, any, any>) | undefined;
|
|
42
46
|
$b: "view.field";
|
|
43
47
|
protected _prop?: string;
|
|
44
|
-
protected _chain?:
|
|
48
|
+
protected _chain?: ($: BucketViewFieldFactory<any, Module, Bucket>) => BucketViewFieldBuilder<Module, Bucket, any, any, any>;
|
|
49
|
+
protected _as_dict?: number[];
|
|
45
50
|
constructor(scope: $BucketViewField['scope'], meta: $BucketViewFieldMeta, subview?: (BucketViewFieldBuilders<any> | BucketViewDef<any, any, any>) | undefined);
|
|
46
51
|
prop<Obj extends Data extends any[] ? Data[number] : Data, K extends keyof Obj>(prop: K): BucketViewFieldBuilder<Module, Bucket, ChainBucket, Obj[K], Scope, GraphLink>;
|
|
47
52
|
map<Def extends BucketViewDef<any, Module, ChainBucket>>(def: Def): BucketViewFieldBuilder<Module, Bucket, ChainBucket, { [K in keyof Def]: Def extends BucketViewFieldBuilder<any, any, infer X, any, any> ? X : never; }, Scope, GraphLink>;
|
|
48
|
-
chain<
|
|
53
|
+
chain<Def extends ($: BucketViewFieldFactory<any, Module, Bucket>) => BucketViewFieldBuilder<Module, Bucket, any, any, any>>(def: Def): BucketViewFieldBuilder<Module, Bucket, ChainBucket, Data, Scope, GraphLink>;
|
|
54
|
+
dict(indexes?: number[]): BucketViewFieldBuilder<Module, Bucket, ChainBucket, Data extends any[] ? {
|
|
55
|
+
[x: string]: Data[number];
|
|
56
|
+
} : {
|
|
57
|
+
[x: string]: Data;
|
|
58
|
+
}, Scope, GraphLink>;
|
|
49
59
|
static build(builder: BucketViewFieldBuilder<any, any, any, any, any>, model: $BucketModel, graph: $BucketGraph, views: $BucketViews, name: string, n_indexes: number, tree?: ModuleTree): $BucketViewField;
|
|
50
60
|
static buildFields(fields: BucketViewFieldBuilders<any>, model: $BucketModel, graph: $BucketGraph, views: $BucketViews, n_indexes?: number, tree?: ModuleTree): $BucketViewFields;
|
|
51
61
|
}
|
|
@@ -14,22 +14,50 @@ const bucket_model_schema_1 = require("../model/bucket_model.schema");
|
|
|
14
14
|
class BucketViewFieldFactory {
|
|
15
15
|
scope;
|
|
16
16
|
meta;
|
|
17
|
-
|
|
17
|
+
get inject() {
|
|
18
18
|
return {
|
|
19
|
-
|
|
19
|
+
get root() {
|
|
20
|
+
return {
|
|
21
|
+
__root: {}
|
|
22
|
+
};
|
|
23
|
+
},
|
|
24
|
+
get parent() {
|
|
25
|
+
return {
|
|
26
|
+
__parent: {}
|
|
27
|
+
};
|
|
28
|
+
},
|
|
29
|
+
get value() {
|
|
30
|
+
return {
|
|
31
|
+
__value: {}
|
|
32
|
+
};
|
|
33
|
+
},
|
|
20
34
|
};
|
|
21
35
|
}
|
|
22
|
-
|
|
36
|
+
get root() {
|
|
23
37
|
return new BucketViewFieldBuilder('model', {
|
|
24
38
|
model: {
|
|
25
|
-
path:
|
|
39
|
+
path: '__root'
|
|
26
40
|
}
|
|
27
41
|
});
|
|
28
42
|
}
|
|
29
|
-
|
|
43
|
+
get parent() {
|
|
30
44
|
return new BucketViewFieldBuilder('model', {
|
|
31
45
|
model: {
|
|
32
|
-
path: '
|
|
46
|
+
path: '__parent'
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
get value() {
|
|
51
|
+
return new BucketViewFieldBuilder('model', {
|
|
52
|
+
model: {
|
|
53
|
+
path: '__value'
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
model(path) {
|
|
58
|
+
return new BucketViewFieldBuilder('model', {
|
|
59
|
+
model: {
|
|
60
|
+
path: path
|
|
33
61
|
}
|
|
34
62
|
});
|
|
35
63
|
}
|
|
@@ -63,10 +91,6 @@ class BucketViewFieldFactory {
|
|
|
63
91
|
}
|
|
64
92
|
});
|
|
65
93
|
}
|
|
66
|
-
// from<
|
|
67
|
-
// >(
|
|
68
|
-
// ) {
|
|
69
|
-
// }
|
|
70
94
|
extend(view, fields) {
|
|
71
95
|
return {
|
|
72
96
|
__ext: view,
|
|
@@ -92,6 +116,7 @@ class BucketViewFieldBuilder {
|
|
|
92
116
|
$b = 'view.field';
|
|
93
117
|
_prop;
|
|
94
118
|
_chain;
|
|
119
|
+
_as_dict;
|
|
95
120
|
constructor(scope, meta, subview) {
|
|
96
121
|
this.scope = scope;
|
|
97
122
|
this.meta = meta;
|
|
@@ -108,21 +133,37 @@ class BucketViewFieldBuilder {
|
|
|
108
133
|
if (this._prop) {
|
|
109
134
|
throw new Error('Subview not allowed for view field which picks a prop');
|
|
110
135
|
}
|
|
136
|
+
if (this._chain) {
|
|
137
|
+
throw new Error('Subview not allowed on field with chain');
|
|
138
|
+
}
|
|
139
|
+
if (this.subview) {
|
|
140
|
+
throw new Error('Cannot map the same field more than once');
|
|
141
|
+
}
|
|
111
142
|
this.subview = def;
|
|
112
143
|
return this;
|
|
113
144
|
}
|
|
114
|
-
chain(
|
|
115
|
-
this.
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
145
|
+
chain(def) {
|
|
146
|
+
if (this.subview) {
|
|
147
|
+
throw new Error('Chain not allowed on field with subiew (map)');
|
|
148
|
+
}
|
|
149
|
+
if (this._chain) {
|
|
150
|
+
throw new Error('Cannot chain the same field more than once');
|
|
151
|
+
}
|
|
152
|
+
this._chain = def;
|
|
153
|
+
// TODO
|
|
154
|
+
// type CData = ComputedData<Fn>
|
|
155
|
+
return this;
|
|
156
|
+
}
|
|
157
|
+
dict(indexes) {
|
|
158
|
+
if (!this.meta.model || !this.meta.model.path.split('.').includes('*')) {
|
|
159
|
+
throw new Error('Dict can only be used on model fields containing at least one \'*\'');
|
|
160
|
+
}
|
|
161
|
+
this._as_dict = indexes ?? [-1];
|
|
120
162
|
return this;
|
|
121
163
|
}
|
|
122
164
|
// Build
|
|
123
165
|
static build(builder, model, graph, views, name, n_indexes, tree) {
|
|
124
166
|
let children = undefined;
|
|
125
|
-
const chainBuilder = builder._chain;
|
|
126
167
|
let spread_n = 0;
|
|
127
168
|
let graphLink = undefined;
|
|
128
169
|
if (builder.scope === 'model') {
|
|
@@ -140,12 +181,14 @@ class BucketViewFieldBuilder {
|
|
|
140
181
|
}
|
|
141
182
|
throw new Error(`Maximum index allowed: $${n_indexes - 1}`);
|
|
142
183
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
184
|
+
if (path !== '__root' && path !== '__parent' && path !== '__value') {
|
|
185
|
+
// Retrieve one or more BucketModelFields referenced by a modelpath.
|
|
186
|
+
// (It's only more than one when using unions)
|
|
187
|
+
// The field itself is not used, but serves to validate that the modelpath exists.
|
|
188
|
+
const modelFields = bucket_model_schema_1.$BucketModel.getFields(model, path);
|
|
189
|
+
if (!modelFields.length) {
|
|
190
|
+
throw error_1.NesoiError.Builder.Bucket.UnknownModelField(builder.meta.model.path);
|
|
191
|
+
}
|
|
149
192
|
}
|
|
150
193
|
}
|
|
151
194
|
else if (builder.scope === 'graph') {
|
|
@@ -184,10 +227,12 @@ class BucketViewFieldBuilder {
|
|
|
184
227
|
children = Object.assign({}, children, overrides);
|
|
185
228
|
}
|
|
186
229
|
let chain;
|
|
187
|
-
if (
|
|
188
|
-
|
|
230
|
+
if (builder._chain) {
|
|
231
|
+
const factory = new BucketViewFieldFactory();
|
|
232
|
+
const subview = builder._chain(factory);
|
|
233
|
+
chain = BucketViewFieldBuilder.build(subview, model, graph, views, name, n_indexes + spread_n, tree);
|
|
189
234
|
}
|
|
190
|
-
return new bucket_view_schema_1.$BucketViewField(name, builder.scope, name, builder.meta, builder._prop, children, chain);
|
|
235
|
+
return new bucket_view_schema_1.$BucketViewField(name, builder.scope, name, builder.meta, builder._prop, children, chain, builder._as_dict);
|
|
191
236
|
}
|
|
192
237
|
static buildFields(fields, model, graph, views, n_indexes = 0, tree) {
|
|
193
238
|
const schema = {};
|
|
@@ -200,8 +245,17 @@ class BucketViewFieldBuilder {
|
|
|
200
245
|
if (f === '__ext') {
|
|
201
246
|
continue;
|
|
202
247
|
}
|
|
203
|
-
if (f === '
|
|
204
|
-
schema['
|
|
248
|
+
if (f === '__root') {
|
|
249
|
+
schema['__root'] = {};
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
if (f === '__parent') {
|
|
253
|
+
schema['__parent'] = {};
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
if (f === '__value') {
|
|
257
|
+
schema['__value'] = {};
|
|
258
|
+
continue;
|
|
205
259
|
}
|
|
206
260
|
const field = fields[f];
|
|
207
261
|
schema[f] = BucketViewFieldBuilder.build(field, model, graph, views, f, n_indexes, tree);
|
|
@@ -3,5 +3,9 @@ import { AnyTrxNode } from "../../../../engine/transaction/trx_node";
|
|
|
3
3
|
export declare function MessageTemplateFieldParser(trx: AnyTrxNode, fields: $MessageTemplateFields, raw: Record<string, any>): Promise<Record<string, any>>;
|
|
4
4
|
/**
|
|
5
5
|
* Empty values: `{}`, `[]`, `''`, `null`, `undefined`
|
|
6
|
+
* @returns
|
|
7
|
+
* 0: not empty
|
|
8
|
+
* 1: null, undefined
|
|
9
|
+
* 2: {}, [] or ''
|
|
6
10
|
*/
|
|
7
|
-
export declare function isEmpty(value: any):
|
|
11
|
+
export declare function isEmpty(value: any): 0 | 2 | 1;
|
|
@@ -30,14 +30,16 @@ async function MessageTemplateFieldParser(trx, fields, raw) {
|
|
|
30
30
|
async function parseFieldValue(trx, field, path, raw, value, inject) {
|
|
31
31
|
sanitize(field, path, value);
|
|
32
32
|
let output;
|
|
33
|
-
|
|
33
|
+
const empty = isEmpty(value);
|
|
34
|
+
if (empty) {
|
|
34
35
|
if (field.required) {
|
|
35
36
|
throw error_1.NesoiError.Message.FieldIsRequired({ alias: field.alias, path: path.join('.'), value });
|
|
36
37
|
}
|
|
37
38
|
else if (field.defaultValue !== undefined) {
|
|
38
39
|
output = field.defaultValue;
|
|
39
40
|
}
|
|
40
|
-
|
|
41
|
+
// If the value is null/undefined, transform into undefined
|
|
42
|
+
else if (empty === 1) {
|
|
41
43
|
output = undefined;
|
|
42
44
|
}
|
|
43
45
|
}
|
|
@@ -176,21 +178,25 @@ function sanitize(field, path, value) {
|
|
|
176
178
|
}
|
|
177
179
|
/**
|
|
178
180
|
* Empty values: `{}`, `[]`, `''`, `null`, `undefined`
|
|
181
|
+
* @returns
|
|
182
|
+
* 0: not empty
|
|
183
|
+
* 1: null, undefined
|
|
184
|
+
* 2: {}, [] or ''
|
|
179
185
|
*/
|
|
180
186
|
function isEmpty(value) {
|
|
181
187
|
if (value === null || value === undefined) {
|
|
182
|
-
return
|
|
188
|
+
return 1;
|
|
183
189
|
}
|
|
184
190
|
if (Array.isArray(value)) {
|
|
185
|
-
return value.length === 0;
|
|
191
|
+
return value.length === 0 ? 2 : 0;
|
|
186
192
|
}
|
|
187
193
|
if (typeof value === 'object') {
|
|
188
|
-
return Object.keys(value).length === 0;
|
|
194
|
+
return Object.keys(value).length === 0 ? 2 : 0;
|
|
189
195
|
}
|
|
190
196
|
if (typeof value === 'string') {
|
|
191
|
-
return value.length === 0;
|
|
197
|
+
return value.length === 0 ? 2 : 0;
|
|
192
198
|
}
|
|
193
|
-
return
|
|
199
|
+
return 0;
|
|
194
200
|
}
|
|
195
201
|
/**
|
|
196
202
|
* Rules
|
package/lib/engine/daemon.d.ts
CHANGED
|
@@ -127,21 +127,11 @@ export declare class DaemonTrx<S extends $Space, M extends $Module, AuthUsers ex
|
|
|
127
127
|
*
|
|
128
128
|
*/
|
|
129
129
|
private _origin?;
|
|
130
|
-
/**
|
|
131
|
-
* An idempotent transaction doesn't generate a commit/rollback.
|
|
132
|
-
*/
|
|
133
|
-
private _idempotent;
|
|
134
130
|
/**
|
|
135
131
|
* @param trxEngine The transaction engine where to run the transaction.
|
|
136
132
|
*/
|
|
137
133
|
constructor(trxEngine: AnyTrxEngine);
|
|
138
134
|
origin(origin: string): this;
|
|
139
|
-
/**
|
|
140
|
-
* Flags this transaction as idempotent.
|
|
141
|
-
* This means its not stored, neither commited/rolled back.
|
|
142
|
-
* This should generally be used for readonly transactions.
|
|
143
|
-
*/
|
|
144
|
-
idempotent(value?: boolean): this;
|
|
145
135
|
/**
|
|
146
136
|
* Inherit authentication from another transaction node.
|
|
147
137
|
*/
|
|
@@ -158,7 +148,7 @@ export declare class DaemonTrx<S extends $Space, M extends $Module, AuthUsers ex
|
|
|
158
148
|
* @param fn A function to execute inside the transaction
|
|
159
149
|
* @returns A `TrxStatus` containing metadata about the transaction and the function response
|
|
160
150
|
*/
|
|
161
|
-
run<Output>(fn: (trx: TrxNode<S, M, AuthUsers>) => Promise<Output>, id?: string): Promise<TrxStatus<Output>>;
|
|
151
|
+
run<Output>(fn: (trx: TrxNode<S, M, AuthUsers>) => Promise<Output>, id?: string, idempotent?: boolean): Promise<TrxStatus<Output>>;
|
|
162
152
|
/**
|
|
163
153
|
* Run a method inside the transaction, and hold it until
|
|
164
154
|
* the external caller decides to commit.
|
package/lib/engine/daemon.js
CHANGED
|
@@ -180,10 +180,6 @@ class DaemonTrx {
|
|
|
180
180
|
*
|
|
181
181
|
*/
|
|
182
182
|
_origin;
|
|
183
|
-
/**
|
|
184
|
-
* An idempotent transaction doesn't generate a commit/rollback.
|
|
185
|
-
*/
|
|
186
|
-
_idempotent = false;
|
|
187
183
|
/**
|
|
188
184
|
* @param trxEngine The transaction engine where to run the transaction.
|
|
189
185
|
*/
|
|
@@ -194,15 +190,6 @@ class DaemonTrx {
|
|
|
194
190
|
this._origin = origin;
|
|
195
191
|
return this;
|
|
196
192
|
}
|
|
197
|
-
/**
|
|
198
|
-
* Flags this transaction as idempotent.
|
|
199
|
-
* This means its not stored, neither commited/rolled back.
|
|
200
|
-
* This should generally be used for readonly transactions.
|
|
201
|
-
*/
|
|
202
|
-
idempotent(value = true) {
|
|
203
|
-
this._idempotent = value;
|
|
204
|
-
return this;
|
|
205
|
-
}
|
|
206
193
|
/**
|
|
207
194
|
* Inherit authentication from another transaction node.
|
|
208
195
|
*/
|
|
@@ -225,14 +212,14 @@ class DaemonTrx {
|
|
|
225
212
|
* @param fn A function to execute inside the transaction
|
|
226
213
|
* @returns A `TrxStatus` containing metadata about the transaction and the function response
|
|
227
214
|
*/
|
|
228
|
-
run(fn, id) {
|
|
215
|
+
run(fn, id, idempotent) {
|
|
229
216
|
const inheritedAuth = this._inherit?.auth;
|
|
230
217
|
const tokens = {
|
|
231
218
|
...inheritedAuth?.tokens,
|
|
232
219
|
...this.tokens
|
|
233
220
|
};
|
|
234
221
|
const users = inheritedAuth?.users;
|
|
235
|
-
return this.trxEngine.trx(fn, id, tokens, users, this._origin,
|
|
222
|
+
return this.trxEngine.trx(fn, id, tokens, users, this._origin, idempotent);
|
|
236
223
|
}
|
|
237
224
|
/**
|
|
238
225
|
* Run a method inside the transaction, and hold it until
|
|
@@ -248,17 +235,7 @@ class DaemonTrx {
|
|
|
248
235
|
...this.tokens
|
|
249
236
|
};
|
|
250
237
|
const users = inheritedAuth?.users;
|
|
251
|
-
|
|
252
|
-
if (this._idempotent) {
|
|
253
|
-
const status = await this.trxEngine.trx(fn, id, tokens, users, this._origin, this._idempotent);
|
|
254
|
-
return {
|
|
255
|
-
id: status.id,
|
|
256
|
-
status,
|
|
257
|
-
commit: () => Promise.resolve(),
|
|
258
|
-
rollback: () => Promise.resolve(),
|
|
259
|
-
};
|
|
260
|
-
}
|
|
261
|
-
return this.trxEngine.trx_hold(fn, id, tokens, users);
|
|
238
|
+
return this.trxEngine.trx_hold(fn, id, tokens, users, this._origin);
|
|
262
239
|
}
|
|
263
240
|
}
|
|
264
241
|
exports.DaemonTrx = DaemonTrx;
|
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
import { NesoiDuration } from './duration';
|
|
2
|
+
export type NesoiDateTimeValues = {
|
|
3
|
+
year: number;
|
|
4
|
+
month: number;
|
|
5
|
+
day: number;
|
|
6
|
+
hour: number;
|
|
7
|
+
minute: number;
|
|
8
|
+
second: number;
|
|
9
|
+
ms: number;
|
|
10
|
+
tz: NesoiDatetime['tz'];
|
|
11
|
+
};
|
|
2
12
|
/**
|
|
3
13
|
* @category Engine
|
|
4
14
|
* @subcategory Data
|
|
@@ -39,17 +49,41 @@ export declare class NesoiDatetime {
|
|
|
39
49
|
*/
|
|
40
50
|
tz: keyof typeof NesoiDatetime.tz;
|
|
41
51
|
constructor(epoch?: number, tz?: keyof typeof NesoiDatetime.tz);
|
|
42
|
-
|
|
52
|
+
atTimezone(tz: NesoiDatetime['tz']): NesoiDatetime;
|
|
43
53
|
/**
|
|
44
54
|
* Parse a timestamp from ISO 8601 format.
|
|
45
55
|
*
|
|
46
56
|
* Example: `2025-04-16T23:04:42.000-03:00`
|
|
47
57
|
*/
|
|
48
58
|
static fromISO(iso: string): NesoiDatetime;
|
|
59
|
+
/**
|
|
60
|
+
* Make a new `NesoiDateTime`
|
|
61
|
+
* @param year Numeric year
|
|
62
|
+
* @param month 1~12
|
|
63
|
+
* @param day 1~31
|
|
64
|
+
* @param hour 0~24
|
|
65
|
+
* @param minute 0~60
|
|
66
|
+
* @param second 0~60
|
|
67
|
+
* @param ms 0~999
|
|
68
|
+
* @param tz
|
|
69
|
+
* @returns
|
|
70
|
+
*/
|
|
71
|
+
static make(year?: number, month?: number, day?: number, hour?: number, minute?: number, second?: number, ms?: number, tz?: NesoiDatetime['tz']): NesoiDatetime;
|
|
72
|
+
static fromValues(values: Partial<NesoiDateTimeValues>): NesoiDatetime;
|
|
73
|
+
toISO(): string;
|
|
74
|
+
toValues(): NesoiDateTimeValues;
|
|
75
|
+
toJSDate(): Date;
|
|
49
76
|
static now(): NesoiDatetime;
|
|
50
77
|
static isoNow(): string;
|
|
51
78
|
static shortIsoNow(): string;
|
|
52
79
|
plus(period: `${number} ${keyof typeof NesoiDuration.UNITS}`): NesoiDatetime;
|
|
53
80
|
minus(period: `${number} ${keyof typeof NesoiDuration.UNITS}`): NesoiDatetime;
|
|
54
81
|
shift(period: `${'+' | '-'} ${number} ${keyof typeof NesoiDuration.UNITS}`): NesoiDatetime;
|
|
82
|
+
/**
|
|
83
|
+
* Returns a new `NesoiDatetime` which refers to the
|
|
84
|
+
* start of a given period **on the object timezone**.
|
|
85
|
+
* @param period
|
|
86
|
+
* @returns
|
|
87
|
+
*/
|
|
88
|
+
startOf(period: 'day' | 'month' | 'year'): NesoiDatetime;
|
|
55
89
|
}
|
|
@@ -43,25 +43,14 @@ class NesoiDatetime {
|
|
|
43
43
|
*/
|
|
44
44
|
tz;
|
|
45
45
|
constructor(epoch, tz = 'Z') {
|
|
46
|
-
this.epoch = epoch
|
|
46
|
+
this.epoch = epoch ?? new Date().getTime();
|
|
47
47
|
this.tz = tz;
|
|
48
48
|
}
|
|
49
|
-
//
|
|
50
|
-
|
|
51
|
-
return new
|
|
52
|
-
timeZone: NesoiDatetime.tz[this.tz],
|
|
53
|
-
year: 'numeric',
|
|
54
|
-
month: 'numeric',
|
|
55
|
-
day: 'numeric',
|
|
56
|
-
hour: 'numeric',
|
|
57
|
-
minute: 'numeric',
|
|
58
|
-
second: 'numeric',
|
|
59
|
-
fractionalSecondDigits: 3
|
|
60
|
-
})
|
|
61
|
-
.replace(' ', 'T')
|
|
62
|
-
.replace(',', '.')
|
|
63
|
-
+ this.tz;
|
|
49
|
+
// Manipulate timezone
|
|
50
|
+
atTimezone(tz) {
|
|
51
|
+
return new NesoiDatetime(this.epoch, tz);
|
|
64
52
|
}
|
|
53
|
+
// Parse
|
|
65
54
|
/**
|
|
66
55
|
* Parse a timestamp from ISO 8601 format.
|
|
67
56
|
*
|
|
@@ -87,6 +76,79 @@ class NesoiDatetime {
|
|
|
87
76
|
const jsDate = Date.parse(iso);
|
|
88
77
|
return new NesoiDatetime(jsDate, tz);
|
|
89
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* Make a new `NesoiDateTime`
|
|
81
|
+
* @param year Numeric year
|
|
82
|
+
* @param month 1~12
|
|
83
|
+
* @param day 1~31
|
|
84
|
+
* @param hour 0~24
|
|
85
|
+
* @param minute 0~60
|
|
86
|
+
* @param second 0~60
|
|
87
|
+
* @param ms 0~999
|
|
88
|
+
* @param tz
|
|
89
|
+
* @returns
|
|
90
|
+
*/
|
|
91
|
+
static make(year = 0, month = 1, day = 1, hour = 0, minute = 0, second = 0, ms = 0, tz = 'Z') {
|
|
92
|
+
const _month = (month < 10 ? '0' : '') + month;
|
|
93
|
+
const _day = (day < 10 ? '0' : '') + day;
|
|
94
|
+
const _hour = (hour < 10 ? '0' : '') + hour;
|
|
95
|
+
const _minute = (minute < 10 ? '0' : '') + minute;
|
|
96
|
+
const _second = (second < 10 ? '0' : '') + second;
|
|
97
|
+
const _ms = (ms < 100 ? '0' : '') + (ms < 10 ? '0' : '') + ms;
|
|
98
|
+
return this.fromISO(`${year}-${_month}-${_day}T${_hour}:${_minute}:${_second}.${_ms}${tz}`);
|
|
99
|
+
}
|
|
100
|
+
static fromValues(values) {
|
|
101
|
+
return this.make(values.year, values.month, values.day, values.hour, values.minute, values.second, values.ms, values.tz);
|
|
102
|
+
}
|
|
103
|
+
// Dump
|
|
104
|
+
toISO() {
|
|
105
|
+
const date = new Date(0);
|
|
106
|
+
date.setUTCMilliseconds(this.epoch);
|
|
107
|
+
return date.toLocaleString('sv-SE', {
|
|
108
|
+
timeZone: NesoiDatetime.tz[this.tz],
|
|
109
|
+
year: 'numeric',
|
|
110
|
+
month: 'numeric',
|
|
111
|
+
day: 'numeric',
|
|
112
|
+
hour: 'numeric',
|
|
113
|
+
minute: 'numeric',
|
|
114
|
+
second: 'numeric',
|
|
115
|
+
fractionalSecondDigits: 3
|
|
116
|
+
})
|
|
117
|
+
.replace(' ', 'T')
|
|
118
|
+
.replace(',', '.')
|
|
119
|
+
+ this.tz;
|
|
120
|
+
}
|
|
121
|
+
toValues() {
|
|
122
|
+
const date = new Date(0);
|
|
123
|
+
date.setUTCMilliseconds(this.epoch);
|
|
124
|
+
const str = date.toLocaleString('sv-SE', {
|
|
125
|
+
timeZone: NesoiDatetime.tz[this.tz],
|
|
126
|
+
year: 'numeric',
|
|
127
|
+
month: 'numeric',
|
|
128
|
+
day: 'numeric',
|
|
129
|
+
hour: 'numeric',
|
|
130
|
+
minute: 'numeric',
|
|
131
|
+
second: 'numeric',
|
|
132
|
+
fractionalSecondDigits: 3,
|
|
133
|
+
});
|
|
134
|
+
const [_, year, month, day, hour, minute, second, ms] = str.match(/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2}),(\d{3})/);
|
|
135
|
+
return {
|
|
136
|
+
year: parseInt(year),
|
|
137
|
+
month: parseInt(month),
|
|
138
|
+
day: parseInt(day),
|
|
139
|
+
hour: parseInt(hour),
|
|
140
|
+
minute: parseInt(minute),
|
|
141
|
+
second: parseInt(second),
|
|
142
|
+
ms: parseInt(ms),
|
|
143
|
+
tz: this.tz
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
toJSDate() {
|
|
147
|
+
const date = new Date(0);
|
|
148
|
+
date.setUTCMilliseconds(this.epoch);
|
|
149
|
+
return date;
|
|
150
|
+
}
|
|
151
|
+
// Now
|
|
90
152
|
static now() {
|
|
91
153
|
return new NesoiDatetime();
|
|
92
154
|
}
|
|
@@ -96,6 +158,7 @@ class NesoiDatetime {
|
|
|
96
158
|
static shortIsoNow() {
|
|
97
159
|
return new NesoiDatetime().toISO().slice(5, 19);
|
|
98
160
|
}
|
|
161
|
+
// Shift
|
|
99
162
|
plus(period) {
|
|
100
163
|
return this.shift(`+ ${period}`);
|
|
101
164
|
}
|
|
@@ -157,5 +220,29 @@ class NesoiDatetime {
|
|
|
157
220
|
}
|
|
158
221
|
return new NesoiDatetime(epoch, this.tz);
|
|
159
222
|
}
|
|
223
|
+
// Start Of
|
|
224
|
+
/**
|
|
225
|
+
* Returns a new `NesoiDatetime` which refers to the
|
|
226
|
+
* start of a given period **on the object timezone**.
|
|
227
|
+
* @param period
|
|
228
|
+
* @returns
|
|
229
|
+
*/
|
|
230
|
+
startOf(period) {
|
|
231
|
+
const values = this.toValues();
|
|
232
|
+
values.ms = 0;
|
|
233
|
+
values.second = 0;
|
|
234
|
+
values.minute = 0;
|
|
235
|
+
values.hour = 0;
|
|
236
|
+
switch (period) {
|
|
237
|
+
case 'month':
|
|
238
|
+
values.day = 1;
|
|
239
|
+
break;
|
|
240
|
+
case 'year':
|
|
241
|
+
values.day = 1;
|
|
242
|
+
values.month = 1;
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
return NesoiDatetime.fromValues(values);
|
|
246
|
+
}
|
|
160
247
|
}
|
|
161
248
|
exports.NesoiDatetime = NesoiDatetime;
|
|
@@ -120,6 +120,11 @@ export declare namespace NesoiError {
|
|
|
120
120
|
path: string;
|
|
121
121
|
bucket: string;
|
|
122
122
|
}): BaseError;
|
|
123
|
+
function IdempotentTransaction($: {
|
|
124
|
+
bucket: string;
|
|
125
|
+
trx: string;
|
|
126
|
+
action: string;
|
|
127
|
+
}): BaseError;
|
|
123
128
|
namespace Graph {
|
|
124
129
|
function LinkNotFound($: {
|
|
125
130
|
bucket: string;
|
|
@@ -153,6 +158,10 @@ export declare namespace NesoiError {
|
|
|
153
158
|
}): BaseError;
|
|
154
159
|
}
|
|
155
160
|
namespace Model {
|
|
161
|
+
function InvalidModelpath($: {
|
|
162
|
+
bucket: string;
|
|
163
|
+
modelpath: string;
|
|
164
|
+
}): BaseError;
|
|
156
165
|
function InvalidEnum($: {
|
|
157
166
|
bucket: string;
|
|
158
167
|
value: string;
|
|
@@ -174,6 +183,14 @@ export declare namespace NesoiError {
|
|
|
174
183
|
bucket: string;
|
|
175
184
|
value: string;
|
|
176
185
|
}): BaseError;
|
|
186
|
+
function InvalidNesoiDuration($: {
|
|
187
|
+
bucket: string;
|
|
188
|
+
value: string;
|
|
189
|
+
}): BaseError;
|
|
190
|
+
function InvalidNesoiDecimal($: {
|
|
191
|
+
bucket: string;
|
|
192
|
+
value: string;
|
|
193
|
+
}): BaseError;
|
|
177
194
|
}
|
|
178
195
|
namespace Drive {
|
|
179
196
|
function NoAdapter($: {
|