nesoi 3.3.24 → 3.3.26

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.
@@ -22,9 +22,8 @@ class ControllerAdapter {
22
22
  const trx = this.daemon.trx(this.schema.module)
23
23
  .origin('controller:' + this.schema.name + ':' + endpoint.name)
24
24
  .auth(auth);
25
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions
26
25
  if (endpoint.idempotent)
27
- trx.idempotent;
26
+ trx.idempotent();
28
27
  return await trx.run(fn);
29
28
  }
30
29
  catch (e) {
@@ -66,7 +66,7 @@ class JSONBucketAdapter extends memory_bucket_adapter_1.MemoryBucketAdapter {
66
66
  const file = fs.readFileSync(this.file);
67
67
  const fileData = JSON.parse(file.toString());
68
68
  for (const id in fileData[this.refName]) {
69
- this.data[id] = this.model.copy(fileData[this.refName][id], 'parse');
69
+ this.data[id] = this.model.copy(fileData[this.refName][id], 'load', () => true);
70
70
  }
71
71
  }
72
72
  dump() {
@@ -79,7 +79,7 @@ class JSONBucketAdapter extends memory_bucket_adapter_1.MemoryBucketAdapter {
79
79
  }
80
80
  data[this.refName] ??= {};
81
81
  for (const id in this.data) {
82
- data[this.refName][id] = this.model.copy(this.data[id], 'dump');
82
+ data[this.refName][id] = this.model.copy(this.data[id], 'save', () => true);
83
83
  }
84
84
  fs.writeFileSync(this.file, JSON.stringify(data));
85
85
  }
@@ -41,18 +41,18 @@ class MemoryBucketAdapter extends bucket_adapter_1.BucketAdapter {
41
41
  }
42
42
  /* Read operations */
43
43
  index(trx) {
44
- const objs = Object.values(this.data).map(obj => this.model.copy(obj));
44
+ const objs = Object.values(this.data).map(obj => this.model.copy(obj, 'load'));
45
45
  return Promise.resolve(objs);
46
46
  }
47
47
  get(trx, id) {
48
48
  if (!(id in this.data))
49
49
  return Promise.resolve(undefined);
50
- const output = this.model.copy(this.data[id]);
50
+ const output = this.model.copy(this.data[id], 'load');
51
51
  return Promise.resolve(output);
52
52
  }
53
53
  /* Write Operations */
54
54
  async create(trx, obj) {
55
- const input = this.model.copy(obj);
55
+ const input = this.model.copy(obj, 'save');
56
56
  if (!input.id) {
57
57
  const lastId = Object.values(this.data)
58
58
  .map((_obj) => parseInt(_obj.id))
@@ -60,7 +60,7 @@ class MemoryBucketAdapter extends bucket_adapter_1.BucketAdapter {
60
60
  input.id = lastId + 1;
61
61
  }
62
62
  this.data[input.id] = input;
63
- const output = this.model.copy(input);
63
+ const output = this.model.copy(input, 'load');
64
64
  return Promise.resolve(output);
65
65
  }
66
66
  async createMany(trx, objs) {
@@ -74,9 +74,9 @@ class MemoryBucketAdapter extends bucket_adapter_1.BucketAdapter {
74
74
  if (!obj.id || !this.data[obj.id]) {
75
75
  throw new Error(`Object with id ${obj.id} not found for replace`);
76
76
  }
77
- const input = this.model.copy(obj);
77
+ const input = this.model.copy(obj, 'save');
78
78
  this.data[input.id] = input;
79
- const output = this.model.copy(input);
79
+ const output = this.model.copy(input, 'load');
80
80
  return Promise.resolve(output);
81
81
  }
82
82
  async replaceMany(trx, objs) {
@@ -92,7 +92,7 @@ class MemoryBucketAdapter extends bucket_adapter_1.BucketAdapter {
92
92
  throw new Error(`Object with id ${obj.id} not found for patch`);
93
93
  }
94
94
  const data = this.data[obj.id];
95
- const input = this.model.copy(obj);
95
+ const input = this.model.copy(obj, 'save');
96
96
  for (const key in input) {
97
97
  if (input[key] === null) {
98
98
  delete data[key];
@@ -101,7 +101,7 @@ class MemoryBucketAdapter extends bucket_adapter_1.BucketAdapter {
101
101
  data[key] = input[key];
102
102
  }
103
103
  }
104
- const output = this.model.copy(data);
104
+ const output = this.model.copy(data, 'load');
105
105
  return Promise.resolve(output);
106
106
  }
107
107
  async patchMany(trx, objs) {
@@ -113,7 +113,7 @@ class MemoryBucketAdapter extends bucket_adapter_1.BucketAdapter {
113
113
  return Promise.resolve(out);
114
114
  }
115
115
  async put(trx, obj) {
116
- const input = this.model.copy(obj);
116
+ const input = this.model.copy(obj, 'save');
117
117
  if (!input.id) {
118
118
  const lastId = Object.values(this.data)
119
119
  .map((_obj) => parseInt(_obj.id))
@@ -121,7 +121,7 @@ class MemoryBucketAdapter extends bucket_adapter_1.BucketAdapter {
121
121
  input.id = lastId + 1;
122
122
  }
123
123
  this.data[input.id] = input;
124
- const output = this.model.copy(input);
124
+ const output = this.model.copy(input, 'load');
125
125
  return Promise.resolve(output);
126
126
  }
127
127
  async putMany(trx, objs) {
@@ -131,12 +131,12 @@ class MemoryBucketAdapter extends bucket_adapter_1.BucketAdapter {
131
131
  let id = lastId + 1;
132
132
  const out = [];
133
133
  for (const obj of objs) {
134
- const input = this.model.copy(obj);
134
+ const input = this.model.copy(obj, 'save');
135
135
  if (!input.id) {
136
136
  input.id = id;
137
137
  }
138
138
  this.data[input.id] = input;
139
- const output = this.model.copy(input);
139
+ const output = this.model.copy(input, 'load');
140
140
  out.push(output);
141
141
  id++;
142
142
  }
@@ -1,5 +1,13 @@
1
1
  import { $Module, $Bucket } from "../../..";
2
+ import { $BucketModelField } from './bucket_model.schema';
2
3
  import { BucketAdapterConfig } from '../adapters/bucket_adapter';
4
+ type BucketModelCopyCmd = {
5
+ field: $BucketModelField;
6
+ obj: Record<string, any>;
7
+ copy: Record<string, any>;
8
+ path: string;
9
+ depth: number;
10
+ };
3
11
  /**
4
12
  * @category Elements
5
13
  * @subcategory Entity
@@ -9,5 +17,6 @@ export declare class BucketModel<M extends $Module, $ extends $Bucket> {
9
17
  private alias;
10
18
  private schema;
11
19
  constructor(bucket: $Bucket, config?: BucketAdapterConfig | undefined);
12
- copy<T extends Record<string, any>>(obj: T, serial?: 'parse' | 'dump'): T;
20
+ copy<T extends Record<string, any>>(obj: T, op: 'save' | 'load', serialize?: (cmd?: BucketModelCopyCmd) => boolean): T;
13
21
  }
22
+ export {};
@@ -4,6 +4,8 @@ exports.BucketModel = void 0;
4
4
  const error_1 = require("../../../../engine/data/error");
5
5
  const date_1 = require("../../../../engine/data/date");
6
6
  const datetime_1 = require("../../../../engine/data/datetime");
7
+ const decimal_1 = require("../../../../engine/data/decimal");
8
+ const duration_1 = require("../../../../engine/data/duration");
7
9
  /**
8
10
  * @category Elements
9
11
  * @subcategory Entity
@@ -17,7 +19,7 @@ class BucketModel {
17
19
  this.alias = bucket.alias;
18
20
  this.schema = bucket.model;
19
21
  }
20
- copy(obj, serial) {
22
+ copy(obj, op, serialize) {
21
23
  const meta = this.config?.meta || {
22
24
  created_at: 'created_at',
23
25
  created_by: 'created_by',
@@ -25,7 +27,9 @@ class BucketModel {
25
27
  updated_by: 'updated_by',
26
28
  };
27
29
  const copy = {};
28
- let poll = Object.entries(this.schema.fields).map(([path, field]) => ({ path, obj, copy, field }));
30
+ let poll = Object.entries(this.schema.fields).map(([path, field]) => ({
31
+ path, obj, copy, field, depth: 0
32
+ }));
29
33
  while (poll.length) {
30
34
  const next = [];
31
35
  for (const entry of poll) {
@@ -45,7 +49,8 @@ class BucketModel {
45
49
  path: i.toString(),
46
50
  obj: val,
47
51
  copy: entry.copy[entry.path],
48
- field: entry.field.children['#']
52
+ field: entry.field.children['#'],
53
+ depth: entry.depth + 1
49
54
  })));
50
55
  }
51
56
  else if (entry.field.type === 'dict') {
@@ -56,7 +61,8 @@ class BucketModel {
56
61
  path,
57
62
  obj: val,
58
63
  copy: entry.copy[entry.path],
59
- field: entry.field.children['#']
64
+ field: entry.field.children['#'],
65
+ depth: entry.depth + 1
60
66
  })));
61
67
  }
62
68
  else if (entry.field.type === 'obj') {
@@ -67,7 +73,8 @@ class BucketModel {
67
73
  path: path,
68
74
  obj: val,
69
75
  copy: entry.copy[entry.path],
70
- field: entry.field.children[path]
76
+ field: entry.field.children[path],
77
+ depth: entry.depth + 1
71
78
  })));
72
79
  }
73
80
  else if (entry.field.type === 'union') {
@@ -82,10 +89,10 @@ class BucketModel {
82
89
  }
83
90
  entry.copy[entry.path] = entry.obj[entry.path];
84
91
  }
85
- else if (serial) {
92
+ else if (entry.field.type === 'date') {
86
93
  const v = entry.obj[entry.path];
87
- if (entry.field.type === 'date') {
88
- if (serial === 'parse') {
94
+ if (serialize?.(entry)) {
95
+ if (op === 'load') {
89
96
  try {
90
97
  entry.copy[entry.path] = date_1.NesoiDate.fromISO(v);
91
98
  }
@@ -93,7 +100,7 @@ class BucketModel {
93
100
  throw error_1.NesoiError.Bucket.Model.InvalidISODate({ bucket: this.alias, value: v });
94
101
  }
95
102
  }
96
- else if (serial === 'dump') {
103
+ else if (op === 'save') {
97
104
  try {
98
105
  entry.copy[entry.path] = v.toISO();
99
106
  }
@@ -102,8 +109,14 @@ class BucketModel {
102
109
  }
103
110
  }
104
111
  }
105
- else if (entry.field.type === 'datetime') {
106
- if (serial === 'parse') {
112
+ else {
113
+ entry.copy[entry.path] = entry.obj[entry.path];
114
+ }
115
+ }
116
+ else if (entry.field.type === 'datetime') {
117
+ const v = entry.obj[entry.path];
118
+ if (serialize?.(entry)) {
119
+ if (op === 'load') {
107
120
  try {
108
121
  entry.copy[entry.path] = datetime_1.NesoiDatetime.fromISO(v);
109
122
  }
@@ -111,7 +124,7 @@ class BucketModel {
111
124
  throw error_1.NesoiError.Bucket.Model.InvalidISODatetime({ bucket: this.alias, value: v });
112
125
  }
113
126
  }
114
- else if (serial === 'dump') {
127
+ else if (op === 'save') {
115
128
  try {
116
129
  entry.copy[entry.path] = v.toISO();
117
130
  }
@@ -120,6 +133,31 @@ class BucketModel {
120
133
  }
121
134
  }
122
135
  }
136
+ else {
137
+ entry.copy[entry.path] = entry.obj[entry.path];
138
+ }
139
+ }
140
+ else if (entry.field.type === 'decimal') {
141
+ const meta = entry.field.meta.decimal;
142
+ const v = entry.obj[entry.path];
143
+ if (serialize?.(entry)) {
144
+ if (op === 'load')
145
+ entry.copy[entry.path] = new decimal_1.NesoiDecimal(v, meta?.left, meta?.right);
146
+ if (op === 'save')
147
+ entry.copy[entry.path] = v.toString();
148
+ }
149
+ else {
150
+ entry.copy[entry.path] = v;
151
+ }
152
+ }
153
+ else if (entry.field.type === 'duration') {
154
+ const v = entry.obj[entry.path];
155
+ if (serialize?.(entry)) {
156
+ if (op === 'load')
157
+ entry.copy[entry.path] = duration_1.NesoiDuration.fromString(v);
158
+ if (op === 'save')
159
+ entry.copy[entry.path] = v.toString();
160
+ }
123
161
  else {
124
162
  entry.copy[entry.path] = v;
125
163
  }
@@ -132,13 +170,15 @@ class BucketModel {
132
170
  }
133
171
  copy[meta.created_by] = obj[meta.created_by];
134
172
  copy[meta.updated_by] = obj[meta.updated_by];
135
- if (serial === 'parse') {
136
- copy[meta.created_at] = obj[meta.created_at] ? datetime_1.NesoiDatetime.fromISO(obj[meta.created_at]) : undefined;
137
- copy[meta.updated_at] = obj[meta.updated_at] ? datetime_1.NesoiDatetime.fromISO(obj[meta.updated_at]) : undefined;
138
- }
139
- else if (serial === 'dump') {
140
- copy[meta.created_at] = obj[meta.created_at]?.toISO?.();
141
- copy[meta.updated_at] = obj[meta.updated_at]?.toISO?.();
173
+ if (serialize?.()) {
174
+ if (op === 'load') {
175
+ copy[meta.created_at] = obj[meta.created_at] ? datetime_1.NesoiDatetime.fromISO(obj[meta.created_at]) : undefined;
176
+ copy[meta.updated_at] = obj[meta.updated_at] ? datetime_1.NesoiDatetime.fromISO(obj[meta.updated_at]) : undefined;
177
+ }
178
+ else if (op === 'save') {
179
+ copy[meta.created_at] = obj[meta.created_at]?.toISO?.();
180
+ copy[meta.updated_at] = obj[meta.updated_at]?.toISO?.();
181
+ }
142
182
  }
143
183
  else {
144
184
  copy[meta.created_at] = obj[meta.created_at];
@@ -10,8 +10,12 @@ export declare class BucketView<$ extends $BucketView> {
10
10
  private bucket;
11
11
  schema: $;
12
12
  constructor(bucket: Bucket<any, any>, schema: $);
13
- parse<Obj extends NesoiObj>(trx: AnyTrxNode, raw: Obj): Promise<$['#data']>;
14
- parseMany<Obj extends NesoiObj>(trx: AnyTrxNode, raws: Obj[]): Promise<$['#data']>;
13
+ parse<Obj extends NesoiObj>(trx: AnyTrxNode, raw: Obj, flags?: {
14
+ nesoi_serial: boolean;
15
+ }): Promise<$['#data']>;
16
+ parseMany<Obj extends NesoiObj>(trx: AnyTrxNode, raws: Obj[], flags?: {
17
+ nesoi_serial: boolean;
18
+ }): Promise<$['#data']>;
15
19
  private parseLayer;
16
20
  /**
17
21
  * [model]
@@ -25,7 +25,7 @@ class BucketView {
25
25
  this.bucket = bucket;
26
26
  this.schema = schema;
27
27
  }
28
- async parse(trx, raw) {
28
+ async parse(trx, raw, flags) {
29
29
  const module = trx_node_1.TrxNode.getModule(trx);
30
30
  const tag = new dependency_1.Tag(this.bucket.module.name, 'bucket', this.bucket.schema.name);
31
31
  const meta = await daemon_1.Daemon.getBucketMetadata(module.daemon, tag);
@@ -44,7 +44,7 @@ class BucketView {
44
44
  }]
45
45
  }));
46
46
  while (layer.length) {
47
- layer = await this.parseLayer(trx, layer);
47
+ layer = await this.parseLayer(trx, layer, flags);
48
48
  }
49
49
  parsed['$v'] = this.schema.name;
50
50
  return {
@@ -52,7 +52,7 @@ class BucketView {
52
52
  ...parsed
53
53
  };
54
54
  }
55
- async parseMany(trx, raws) {
55
+ async parseMany(trx, raws, flags) {
56
56
  const module = trx_node_1.TrxNode.getModule(trx);
57
57
  const tag = new dependency_1.Tag(this.bucket.module.name, 'bucket', this.bucket.schema.name);
58
58
  const meta = await daemon_1.Daemon.getBucketMetadata(module.daemon, tag);
@@ -75,7 +75,7 @@ class BucketView {
75
75
  }))
76
76
  }));
77
77
  while (layer.length) {
78
- layer = await this.parseLayer(trx, layer);
78
+ layer = await this.parseLayer(trx, layer, flags);
79
79
  }
80
80
  for (let i = 0; i < raws.length; i++) {
81
81
  parseds[i].id = raws[i].id;
@@ -83,13 +83,13 @@ class BucketView {
83
83
  }
84
84
  return parseds;
85
85
  }
86
- async parseLayer(trx, layer) {
86
+ async parseLayer(trx, layer, flags) {
87
87
  const next = [];
88
88
  // Model props
89
89
  for (const node of layer) {
90
90
  if (node.field.scope !== 'model')
91
91
  continue;
92
- next.push(...this.parseModelProp(node));
92
+ next.push(...this.parseModelProp(node, flags));
93
93
  }
94
94
  // Computed props
95
95
  for (const node of layer) {
@@ -147,10 +147,10 @@ class BucketView {
147
147
  * [model]
148
148
  * Read one property from
149
149
  */
150
- parseModelProp(node) {
150
+ parseModelProp(node, flags) {
151
151
  const initAs = (!node.field.children) ? 'value' : 'obj';
152
152
  const rawChild = '__raw' in (node.field.children || {});
153
- const nextData = this.doParseModelProp(node, initAs, rawChild);
153
+ const nextData = this.doParseModelProp(node, initAs, rawChild, flags);
154
154
  if (!node.field.children)
155
155
  return [];
156
156
  const next = [];
@@ -166,7 +166,7 @@ class BucketView {
166
166
  }
167
167
  return next;
168
168
  }
169
- doParseModelProp(node, initAs, rawChild) {
169
+ doParseModelProp(node, initAs, rawChild, flags) {
170
170
  const modelpath = node.field.meta.model.path;
171
171
  const isValueModel = modelpath === '.';
172
172
  const name = node.field.name;
@@ -73,7 +73,7 @@ class CLI {
73
73
  }
74
74
  async run(cmd) {
75
75
  if (cmd) {
76
- this.runCmd(cmd);
76
+ await this.runCmd(cmd);
77
77
  return;
78
78
  }
79
79
  console_1.default.header('CLI');
@@ -84,8 +84,8 @@ declare class ScriptValueBuilder<T = string> {
84
84
  constructor(name: string);
85
85
  d(description: string): this;
86
86
  get optional(): ScriptValueBuilder<T | undefined>;
87
- get zero_or_more(): this;
88
- get one_or_more(): this;
87
+ get zero_or_more(): ScriptValueBuilder<T[]>;
88
+ get one_or_more(): ScriptValueBuilder<T[]>;
89
89
  get boolean(): ScriptValueBuilder<boolean>;
90
90
  enum<E extends string>(options: E[] | Record<E, string>): ScriptValueBuilder<undefined extends T ? E | undefined : E>;
91
91
  private build;
@@ -141,11 +141,7 @@ export declare class DaemonTrx<S extends $Space, M extends $Module, AuthUsers ex
141
141
  * This means its not stored, neither commited/rolled back.
142
142
  * This should generally be used for readonly transactions.
143
143
  */
144
- get idempotent(): this;
145
- /**
146
- * Inherit authentication from another transaction node.
147
- */
148
- idempotent_inherit(trx: AnyTrxNode): this;
144
+ idempotent(value?: boolean): this;
149
145
  /**
150
146
  * Inherit authentication from another transaction node.
151
147
  */
@@ -199,15 +199,8 @@ class DaemonTrx {
199
199
  * This means its not stored, neither commited/rolled back.
200
200
  * This should generally be used for readonly transactions.
201
201
  */
202
- get idempotent() {
203
- this._idempotent = true;
204
- return this;
205
- }
206
- /**
207
- * Inherit authentication from another transaction node.
208
- */
209
- idempotent_inherit(trx) {
210
- this._idempotent = trx.trx.idempotent;
202
+ idempotent(value = true) {
203
+ this._idempotent = value;
211
204
  return this;
212
205
  }
213
206
  /**
@@ -32,16 +32,16 @@ class ExternalTrxNode {
32
32
  let out;
33
33
  try {
34
34
  const dtrx = await this.daemon.trx(this.tag.module)
35
- .origin('ext:' + root.id);
36
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions
37
- if (this.idempotent)
38
- dtrx.idempotent;
39
- else
40
- dtrx.idempotent_inherit(trx);
41
- const res = await dtrx
35
+ .origin('ext:' + root.id)
36
+ // This can be overriden by the TrxEngine if the root
37
+ // it not idempotent (which makes it not idempotent)
38
+ .idempotent(this.idempotent);
39
+ let idempotent = false;
40
+ const hold = await dtrx
42
41
  .auth_inherit(trx)
43
42
  .run_and_hold(async (extTrx) => {
44
43
  try {
44
+ idempotent = extTrx.trx.idempotent;
45
45
  return await fn(extTrx, element(extTrx));
46
46
  }
47
47
  catch (e) {
@@ -51,12 +51,14 @@ class ExternalTrxNode {
51
51
  trx_node_1.TrxNode.merge(trx, extTrx);
52
52
  }
53
53
  }, root.id);
54
- if (res.status.state === 'error') {
55
- throw res.status.error;
54
+ if (hold.status.state === 'error') {
55
+ throw hold.status.error;
56
56
  }
57
- out = res.status.output;
58
- if (!trx.trx.idempotent) {
59
- root.holdNode(res);
57
+ out = hold.status.output;
58
+ if (!idempotent) {
59
+ if (!(root.id in root.holds)) {
60
+ root.holds[root.id] = hold;
61
+ }
60
62
  }
61
63
  }
62
64
  catch (e) {
@@ -75,12 +77,10 @@ class ExternalTrxNode {
75
77
  let out;
76
78
  try {
77
79
  const dtrx = await this.daemon.trx(this.tag.module)
78
- .origin('ext:' + root.id);
79
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions
80
- if (this.idempotent)
81
- dtrx.idempotent;
82
- else
83
- dtrx.idempotent_inherit(trx);
80
+ .origin('ext:' + root.id)
81
+ // This can be overriden by the TrxEngine if the root
82
+ // it not idempotent (which makes it not idempotent)
83
+ .idempotent(this.idempotent);
84
84
  const res = await dtrx
85
85
  .auth_inherit(trx)
86
86
  .run(async (extTrx) => {
@@ -45,7 +45,6 @@ export declare class Trx<S extends $Space, M extends $Module, AuthUsers extends
45
45
  users: AuthUsers;
46
46
  }, id?: string, root?: TrxNode<S, M, AuthUsers>, nodes?: Record<string, TrxNode<S, M, AuthUsers>>);
47
47
  addNode(node: TrxNode<S, M, AuthUsers>): void;
48
- holdNode(node: TrxNodeHold<any>): void;
49
48
  status(): TrxStatus<any>;
50
49
  /**
51
50
  * Cache
@@ -90,10 +90,6 @@ class Trx {
90
90
  const nodeId = node.id;
91
91
  this.nodes[nodeId] = node;
92
92
  }
93
- holdNode(node) {
94
- const nodeId = node.id;
95
- this.holds[nodeId] = node;
96
- }
97
93
  status() {
98
94
  const state = this.root.state;
99
95
  const output = this.root.output;