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.
Files changed (47) hide show
  1. package/lib/compiler/elements/bucket.element.js +3 -3
  2. package/lib/elements/edge/controller/adapters/controller_adapter.js +1 -3
  3. package/lib/elements/entities/bucket/adapters/memory.nql.js +12 -18
  4. package/lib/elements/entities/bucket/bucket.d.ts +6 -2
  5. package/lib/elements/entities/bucket/bucket.js +4 -4
  6. package/lib/elements/entities/bucket/graph/bucket_graph.js +13 -3
  7. package/lib/elements/entities/bucket/model/bucket_model.convert.js +9 -17
  8. package/lib/elements/entities/bucket/model/bucket_model.d.ts +6 -1
  9. package/lib/elements/entities/bucket/model/bucket_model.js +182 -33
  10. package/lib/elements/entities/bucket/model/bucket_model.schema.d.ts +1 -1
  11. package/lib/elements/entities/bucket/model/bucket_model.schema.js +2 -2
  12. package/lib/elements/entities/bucket/query/nql.schema.d.ts +1 -0
  13. package/lib/elements/entities/bucket/query/nql_compiler.js +5 -4
  14. package/lib/elements/entities/bucket/query/nql_engine.js +0 -2
  15. package/lib/elements/entities/bucket/view/bucket_view.d.ts +5 -4
  16. package/lib/elements/entities/bucket/view/bucket_view.js +300 -188
  17. package/lib/elements/entities/bucket/view/bucket_view.schema.d.ts +5 -3
  18. package/lib/elements/entities/bucket/view/bucket_view.schema.js +3 -1
  19. package/lib/elements/entities/bucket/view/bucket_view_field.builder.d.ts +15 -5
  20. package/lib/elements/entities/bucket/view/bucket_view_field.builder.js +82 -28
  21. package/lib/elements/entities/message/template/message_template_parser.d.ts +5 -1
  22. package/lib/elements/entities/message/template/message_template_parser.js +13 -7
  23. package/lib/engine/daemon.d.ts +1 -11
  24. package/lib/engine/daemon.js +3 -26
  25. package/lib/engine/data/datetime.d.ts +35 -1
  26. package/lib/engine/data/datetime.js +103 -16
  27. package/lib/engine/data/error.d.ts +17 -0
  28. package/lib/engine/data/error.js +16 -0
  29. package/lib/engine/transaction/nodes/bucket.trx_node.d.ts +8 -2
  30. package/lib/engine/transaction/nodes/bucket.trx_node.js +16 -4
  31. package/lib/engine/transaction/nodes/bucket_query.trx_node.js +1 -1
  32. package/lib/engine/transaction/nodes/external.trx_node.d.ts +4 -1
  33. package/lib/engine/transaction/nodes/external.trx_node.js +19 -19
  34. package/lib/engine/transaction/nodes/job.trx_node.d.ts +4 -3
  35. package/lib/engine/transaction/nodes/job.trx_node.js +6 -2
  36. package/lib/engine/transaction/nodes/resource.trx_node.js +2 -1
  37. package/lib/engine/transaction/trx.d.ts +4 -3
  38. package/lib/engine/transaction/trx.js +15 -11
  39. package/lib/engine/transaction/trx_engine.config.d.ts +7 -3
  40. package/lib/engine/transaction/trx_engine.d.ts +7 -3
  41. package/lib/engine/transaction/trx_engine.js +99 -45
  42. package/lib/engine/transaction/trx_node.d.ts +4 -1
  43. package/lib/engine/transaction/trx_node.js +12 -9
  44. package/package.json +1 -1
  45. package/tools/joaquin/bucket.d.ts +6 -2
  46. package/tools/joaquin/bucket.js +4 -4
  47. 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, Raw, Value> = (ctx: {
3
+ export type $BucketViewFieldFn<TrxNode extends AnyTrxNode, B extends $Bucket, Parent, Value, Return = any> = (ctx: {
4
4
  trx: TrxNode;
5
- raw: B['#data'];
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
- raw(): {
23
- [K in keyof Bucket['#data']]: BucketViewFieldBuilder<Module, Bucket, Bucket, Bucket['#data'][K], 'model'>;
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?: BucketViewFieldBuilder<any, any, any, any, any>;
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<Fn extends $BucketViewFieldFn<TrxNode<any, Module, never>, ChainBucket, Bucket['#data'], Data>>(fn: Fn): BucketViewFieldBuilder<Module, Bucket, ChainBucket, ComputedData<Fn, ReturnType<Fn>>, Scope, GraphLink>;
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
- raw() {
17
+ get inject() {
18
18
  return {
19
- __raw: {}
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
- model(path) {
36
+ get root() {
23
37
  return new BucketViewFieldBuilder('model', {
24
38
  model: {
25
- path: path
39
+ path: '__root'
26
40
  }
27
41
  });
28
42
  }
29
- value() {
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(fn) {
115
- this._chain = new BucketViewFieldBuilder('computed', {
116
- computed: {
117
- fn: fn
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
- // Retrieve one or more BucketModelFields referenced by a modelpath.
144
- // (It's only more than one when using unions)
145
- // The field itself is not used, but serves to validate that the modelpath exists.
146
- const modelFields = bucket_model_schema_1.$BucketModel.getField(model, path);
147
- if (!modelFields.length) {
148
- throw error_1.NesoiError.Builder.Bucket.UnknownModelField(builder.meta.model.path);
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 (chainBuilder) {
188
- chain = BucketViewFieldBuilder.build(chainBuilder, model, graph, views, name, n_indexes, tree);
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 === '__raw') {
204
- schema['__raw'] = {};
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): boolean;
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
- if (isEmpty(value)) {
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
- else {
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 true;
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 false;
199
+ return 0;
194
200
  }
195
201
  /**
196
202
  * Rules
@@ -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.
@@ -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, this._idempotent);
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
- // Idempotent transactions are not commited/rolled back, so they don't need to be held.
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
- toISO(): string;
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 || new Date().getTime();
46
+ this.epoch = epoch ?? new Date().getTime();
47
47
  this.tz = tz;
48
48
  }
49
- // Dump
50
- toISO() {
51
- return new Date(this.epoch).toLocaleString('sv-SE', {
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($: {