nesoi 3.0.21 → 3.1.0

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 (80) hide show
  1. package/lib/compiler/apps/monolyth/stages/4_dump_modules_stage.js +8 -0
  2. package/lib/compiler/compiler.js +1 -1
  3. package/lib/compiler/elements/bucket.element.d.ts +2 -1
  4. package/lib/compiler/elements/bucket.element.js +68 -122
  5. package/lib/compiler/elements/element.js +2 -1
  6. package/lib/compiler/elements/externals.element.js +3 -0
  7. package/lib/compiler/elements/message.element.js +34 -57
  8. package/lib/compiler/elements/queue.element.js +1 -1
  9. package/lib/compiler/helpers/dump_helpers.d.ts +2 -0
  10. package/lib/compiler/helpers/dump_helpers.js +12 -2
  11. package/lib/compiler/stages/4_build_schemas_stage.js +12 -0
  12. package/lib/compiler/stages/5_inject_ts_stage.js +4 -1
  13. package/lib/compiler/stages/7_dump_stage.js +7 -1
  14. package/lib/compiler/treeshake.js +4 -2
  15. package/lib/compiler/typescript/bridge/extract.js +37 -107
  16. package/lib/compiler/typescript/bridge/inject.d.ts +1 -1
  17. package/lib/compiler/typescript/bridge/inject.js +73 -45
  18. package/lib/compiler/typescript/bridge/organize.js +9 -5
  19. package/lib/compiler/typescript/typescript_compiler.d.ts +4 -6
  20. package/lib/compiler/typescript/typescript_compiler.js +139 -75
  21. package/lib/elements/blocks/block.builder.d.ts +1 -10
  22. package/lib/elements/blocks/block.builder.js +0 -32
  23. package/lib/elements/blocks/job/internal/resource_job.builder.d.ts +3 -21
  24. package/lib/elements/blocks/job/job.builder.d.ts +6 -20
  25. package/lib/elements/blocks/job/job.builder.js +0 -4
  26. package/lib/elements/blocks/machine/machine.builder.d.ts +5 -14
  27. package/lib/elements/blocks/machine/machine.builder.js +2 -2
  28. package/lib/elements/blocks/queue/queue.builder.d.ts +6 -15
  29. package/lib/elements/blocks/queue/queue.builder.js +2 -2
  30. package/lib/elements/edge/externals/externals.builder.d.ts +2 -0
  31. package/lib/elements/edge/externals/externals.builder.js +6 -1
  32. package/lib/elements/edge/externals/externals.schema.d.ts +2 -1
  33. package/lib/elements/edge/externals/externals.schema.js +3 -1
  34. package/lib/elements/entities/bucket/adapters/memory.nql.js +1 -1
  35. package/lib/elements/entities/bucket/bucket.builder.d.ts +6 -4
  36. package/lib/elements/entities/bucket/bucket.js +7 -16
  37. package/lib/elements/entities/bucket/bucket.schema.d.ts +2 -1
  38. package/lib/elements/entities/bucket/graph/bucket_graph.infer.d.ts +7 -5
  39. package/lib/elements/entities/bucket/graph/bucket_graph_link.builder.d.ts +2 -1
  40. package/lib/elements/entities/bucket/model/bucket_model.builder.d.ts +1 -1
  41. package/lib/elements/entities/bucket/model/bucket_model.convert.d.ts +1 -1
  42. package/lib/elements/entities/bucket/model/bucket_model.convert.js +4 -4
  43. package/lib/elements/entities/bucket/model/bucket_model.infer.d.ts +45 -9
  44. package/lib/elements/entities/bucket/model/bucket_model.schema.d.ts +5 -6
  45. package/lib/elements/entities/bucket/model/bucket_model.schema.js +64 -21
  46. package/lib/elements/entities/bucket/model/bucket_model_field.builder.d.ts +88 -55
  47. package/lib/elements/entities/bucket/model/bucket_model_field.builder.js +22 -30
  48. package/lib/elements/entities/bucket/query/nql.schema.d.ts +13 -10
  49. package/lib/elements/entities/bucket/query/nql_compiler.js +46 -21
  50. package/lib/elements/entities/bucket/view/bucket_view.builder.js +1 -1
  51. package/lib/elements/entities/bucket/view/bucket_view.d.ts +19 -0
  52. package/lib/elements/entities/bucket/view/bucket_view.js +230 -108
  53. package/lib/elements/entities/bucket/view/bucket_view.schema.d.ts +5 -10
  54. package/lib/elements/entities/bucket/view/bucket_view.schema.js +3 -5
  55. package/lib/elements/entities/bucket/view/bucket_view_field.builder.d.ts +16 -12
  56. package/lib/elements/entities/bucket/view/bucket_view_field.builder.js +55 -40
  57. package/lib/elements/entities/message/message.builder.d.ts +1 -11
  58. package/lib/elements/entities/message/message.infer.d.ts +6 -30
  59. package/lib/elements/entities/message/message.schema.js +2 -2
  60. package/lib/elements/entities/message/template/message_template.builder.js +1 -1
  61. package/lib/elements/entities/message/template/message_template.schema.d.ts +10 -15
  62. package/lib/elements/entities/message/template/message_template.schema.js +29 -12
  63. package/lib/elements/entities/message/template/message_template_field.builder.d.ts +45 -209
  64. package/lib/elements/entities/message/template/message_template_field.builder.js +69 -85
  65. package/lib/elements/entities/message/template/message_template_parser.js +50 -65
  66. package/lib/engine/apps/inline.app.js +1 -0
  67. package/lib/engine/data/trash.js +7 -7
  68. package/lib/engine/data/tree.d.ts +3 -0
  69. package/lib/engine/data/tree.js +36 -0
  70. package/lib/engine/util/parse.d.ts +22 -14
  71. package/lib/engine/util/parse.js +18 -3
  72. package/lib/engine/util/type.d.ts +3 -0
  73. package/package.json +1 -1
  74. package/tools/joaquin/bucket.d.ts +9 -0
  75. package/tools/joaquin/bucket.js +49 -0
  76. package/tools/joaquin/message.d.ts +2 -1
  77. package/tools/joaquin/message.js +9 -2
  78. package/tools/joaquin/mock.d.ts +1 -0
  79. package/tools/joaquin/mock.js +13 -5
  80. package/tsconfig.build.tsbuildinfo +1 -1
@@ -14,10 +14,6 @@ class MessageTemplateFieldFactory {
14
14
  }
15
15
  /**
16
16
  * Specifies an alias for the field.
17
- * - If this field is a union (.or), this alias is used when
18
- * referring to the union and it's first option.
19
- * - You can specify a different alias for the first options
20
- * by also using the .as() after the type
21
17
  */
22
18
  as(alias) {
23
19
  const chain = new MessageTemplateFieldFactory(this.module);
@@ -82,10 +78,15 @@ class MessageTemplateFieldFactory {
82
78
  return new MessageTemplateFieldBuilder('obj', {}, this.alias, children);
83
79
  }
84
80
  dict(item) {
85
- item = item.optional;
86
81
  return new MessageTemplateFieldBuilder('dict', {}, this.alias, { __dict: item });
87
82
  }
88
- msg(msg, extra) {
83
+ list(item) {
84
+ return new MessageTemplateFieldBuilder('list', {}, this.alias, { '#': item });
85
+ }
86
+ union(...children) {
87
+ return new MessageTemplateFieldBuilder('union', {}, this.alias, Object.fromEntries(children.map((c, i) => [i, c])));
88
+ }
89
+ msg(msg, extra = {}) {
89
90
  // Module and tag are updated on build
90
91
  const ref = new dependency_1.$Dependency(this.module, 'message', msg);
91
92
  return new MessageTemplateFieldBuilder('msg', { msg: ref }, this.alias, extra);
@@ -109,13 +110,10 @@ class MessageTemplateFieldBuilder {
109
110
  this.value = value;
110
111
  this.alias = alias;
111
112
  this.children = children;
112
- this._array = false;
113
113
  this._required = true;
114
114
  this._defaultValue = undefined;
115
- this._nullable = true;
115
+ this._nullable = false;
116
116
  this._rules = [];
117
- this._arrayRules = [];
118
- this.preAlias = alias;
119
117
  }
120
118
  as(alias) {
121
119
  this.alias = alias;
@@ -123,105 +121,91 @@ class MessageTemplateFieldBuilder {
123
121
  }
124
122
  get optional() {
125
123
  this._required = false;
126
- if (this._or) {
127
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions
128
- this._or.optional;
129
- }
130
124
  return this;
131
125
  }
132
126
  default(value) {
133
127
  this._required = false;
134
128
  this._defaultValue = value;
135
- if (this._or) {
136
- this._or.default(value);
137
- }
138
129
  return this;
139
130
  }
140
131
  get nullable() {
141
132
  this._nullable = true;
142
- if (this._or) {
143
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions
144
- this._or.nullable;
145
- }
146
133
  return this;
147
134
  }
148
135
  rule(rule) {
149
- if (this._array) {
150
- this._arrayRules.push(rule);
151
- }
152
- else {
153
- this._rules.push(rule);
154
- }
155
- return this;
156
- }
157
- get array() {
158
- this._array = true;
159
- if (this._or) {
160
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions
161
- this._or.array;
162
- }
163
- return this;
164
- }
165
- or(def) {
166
- this._or = def;
167
- this._or.preAlias = this.preAlias;
168
- this._or._array = this._array;
169
- this._or._defaultValue = this._defaultValue;
170
- this._or._nullable = this._nullable;
171
- this._or._required = this._required;
172
- this._or._arrayRules = this._arrayRules;
136
+ this._rules.push(rule);
173
137
  return this;
174
138
  }
175
139
  // Build
176
140
  static build(builder, name, tree, module, basePathRaw, basePathParsed) {
177
- const or = builder._or
178
- ? this.build(builder._or, name, tree, module, basePathRaw, basePathParsed)
179
- : undefined;
141
+ const pathRaw = basePathRaw + (builder.type === 'id' ? `${name}_id` : name);
180
142
  const pathParsed = basePathParsed + name;
181
- const pathRaw = basePathParsed + (builder.type === 'id'
182
- ? builder._array ? `${name}_ids` : `${name}_id`
183
- : name);
184
- const childrenBasePathRaw = pathRaw + (builder._array ? '.#.' : '.');
185
- const childrenBasePathParsed = pathParsed + (builder._array ? '.#.' : '.');
186
- if (builder.value.id) {
143
+ const childrenBasePathRaw = pathRaw + '.';
144
+ const childrenBasePathParsed = pathParsed + '.';
145
+ let type = builder.type;
146
+ let children;
147
+ if (builder.type === 'id') {
187
148
  const bucket = tree.getSchema(builder.value.id.bucket);
188
149
  builder.value.id.type = bucket.model.fields.id.type;
189
150
  }
190
- return new message_template_schema_1.$MessageTemplateField(builder.type, name, builder.alias || name, builder.preAlias || name, pathRaw, pathParsed, builder._array, builder._required, builder._defaultValue, builder._nullable, builder._rules, builder._arrayRules, builder.value, builder.children ? MessageTemplateFieldBuilder.buildChildren(builder.children, tree, module, childrenBasePathRaw, childrenBasePathParsed) : undefined, or);
151
+ // A .msg() parameter is an obj which takes fields from
152
+ // another message
153
+ else if (builder.type === 'msg') {
154
+ const dep = builder.value.msg;
155
+ if (dep.type !== 'message') {
156
+ throw error_1.NesoiError.Builder.Message.UnknownModuleMessage(dep.tag);
157
+ }
158
+ const $msg = tree.getSchema(dep);
159
+ if (!$msg) {
160
+ throw error_1.NesoiError.Builder.Message.UnknownModuleMessage(dep.tag);
161
+ }
162
+ if (dep.module !== module.name) {
163
+ if (!(dep.refName in module.externals.messages)) {
164
+ throw error_1.NesoiError.Builder.Message.UnknownModuleMessage(dep.tag);
165
+ }
166
+ }
167
+ const injectFields = (target, fields) => {
168
+ for (const key in fields) {
169
+ target[key] = message_template_schema_1.$MessageTemplateField.clone(fields[key]);
170
+ target[key].pathRaw = childrenBasePathRaw + target[key].pathRaw;
171
+ target[key].pathParsed = childrenBasePathParsed + target[key].pathParsed;
172
+ if (fields[key].children) {
173
+ target[key].children = {};
174
+ injectFields(target[key].children, fields[key].children);
175
+ }
176
+ }
177
+ };
178
+ type = 'obj';
179
+ children = {};
180
+ injectFields(children, $msg.template.fields);
181
+ }
182
+ else if (builder.type === 'list') {
183
+ children = MessageTemplateFieldBuilder.buildMany(builder.children, tree, module, childrenBasePathRaw, childrenBasePathParsed, '#', '#');
184
+ }
185
+ else if (builder.type === 'dict') {
186
+ children = MessageTemplateFieldBuilder.buildMany(builder.children, tree, module, childrenBasePathRaw, childrenBasePathParsed, '#', '#');
187
+ }
188
+ else if (builder.type === 'union') {
189
+ children = MessageTemplateFieldBuilder.buildMany(builder.children, tree, module, basePathRaw, basePathParsed, name, undefined);
190
+ }
191
+ // All other fields build their children directly
192
+ else if (builder.children) {
193
+ children = MessageTemplateFieldBuilder.buildMany(builder.children, tree, module, childrenBasePathRaw, childrenBasePathParsed);
194
+ }
195
+ return new message_template_schema_1.$MessageTemplateField(type, name, builder.alias || name, pathRaw, pathParsed, builder._required, builder._defaultValue, builder._nullable, builder._rules, builder.value, children);
191
196
  }
192
- static buildChildren(fields, tree, module, basePathRaw = '', basePathParsed = '') {
197
+ static buildMany(fields, tree, module, basePathRaw = '', basePathParsed = '', name, key) {
193
198
  const schema = {};
194
199
  for (const c in fields) {
195
- const child = fields[c];
196
- // Extended fields inherit from other messages
197
- if (child.__ext) {
198
- const ext = tree.getSchema(child.__ext);
199
- schema[c].children = Object.assign({}, ext.template.fields, schema[c].children || {});
200
- continue;
201
- }
202
- const param = c;
203
- // A .msg() parameter is an obj which takes fields from
204
- // another message
205
- if (child.type === 'msg') {
206
- const name = child.value.msg.name;
207
- const $msg = module.messages[name];
208
- if (!$msg) {
209
- throw error_1.NesoiError.Builder.Message.UnknownModuleMessage(name);
210
- }
211
- const builder = new MessageTemplateFieldFactory(module.name).obj({});
212
- builder.alias = child.alias;
213
- builder._required = child._required;
214
- builder._defaultValue = child._defaultValue;
215
- builder._nullable = child._nullable;
216
- builder._rules = child._rules.slice(0, -1);
217
- builder.children = child.children;
218
- schema[param] = MessageTemplateFieldBuilder.build(builder, c, tree, module, basePathRaw, basePathParsed);
219
- schema[param].children = schema[param].children || {};
220
- Object.assign(schema[param].children, $msg.template.fields);
200
+ if (c === '__ext')
221
201
  continue;
222
- }
223
- // All other parameters are built directly
224
- schema[param] = MessageTemplateFieldBuilder.build(child, c, tree, module, basePathRaw, basePathParsed);
202
+ const child = fields[c];
203
+ schema[key || c] = MessageTemplateFieldBuilder.build(child, name || c, tree, module, basePathRaw, basePathParsed);
204
+ }
205
+ // Extended field groups inherit from other messages
206
+ if ('__ext' in fields) {
207
+ const ext = tree.getSchema(fields.__ext);
208
+ Object.assign(schema, ext.template.fields);
225
209
  }
226
210
  return schema;
227
211
  }
@@ -12,8 +12,8 @@ async function MessageTemplateFieldParser(trx, fields, raw) {
12
12
  const inject = {};
13
13
  for (const k in fields) {
14
14
  const field = fields[k];
15
- const key_raw = field.path_raw.split('.')[0];
16
- const key_parsed = field.path_parsed.split('.')[0];
15
+ const key_raw = field.pathRaw.split('.')[0];
16
+ const key_parsed = field.pathParsed.split('.')[0];
17
17
  const value = raw[key_raw];
18
18
  parsed[key_parsed] = await parseFieldValue(trx, field, [field.name], raw, value, inject);
19
19
  }
@@ -40,22 +40,8 @@ async function parseFieldValue(trx, field, path, raw, value, inject) {
40
40
  return undefined;
41
41
  }
42
42
  }
43
- let output;
44
- if (field.array) {
45
- if (!Array.isArray(value)) {
46
- throw error_1.NesoiError.Message.InvalidFieldType({ alias: field.alias, path: path.join('.'), value, type: 'list' });
47
- }
48
- output = [];
49
- for (let i = 0; i < value.length; i++) {
50
- const v = value[i];
51
- const parsedValue = await _attemptUnion(trx, field, [...path, i.toString()], raw, v, inject);
52
- output.push(parsedValue);
53
- }
54
- output = await applyFieldRules('array', field, path, raw, output, inject);
55
- }
56
- else {
57
- output = await _attemptUnion(trx, field, path, raw, value, inject);
58
- }
43
+ let output = await _attemptUnion(trx, field, path, raw, value, inject);
44
+ output = await applyFieldRules(field, path, raw, output, inject);
59
45
  return output;
60
46
  }
61
47
  /**
@@ -65,35 +51,31 @@ async function parseFieldValue(trx, field, path, raw, value, inject) {
65
51
  * - If it fails, attempt other union options (step 2) (if available), with same path
66
52
  * - If it works, apply field rules.
67
53
  */
68
- async function _attemptUnion(trx, field, path, raw, value, inject, unionErrors = []) {
69
- let output = undefined;
70
- try {
71
- output = await _runParseMethod(trx, field, path, raw, value, inject);
54
+ async function _attemptUnion(trx, field, path, raw, value, inject) {
55
+ if (field.type !== 'union') {
56
+ return _runParseMethod(trx, field, path, raw, value, inject);
72
57
  }
73
- catch (e) {
74
- const ue = [
75
- ...unionErrors,
76
- {
77
- option: field.alias,
58
+ const unionErrors = [];
59
+ let output = undefined;
60
+ for (const k in field.children) {
61
+ const option = field.children[k];
62
+ try {
63
+ output = await _runParseMethod(trx, option, path, raw, value, inject);
64
+ break;
65
+ }
66
+ catch (e) {
67
+ unionErrors.push({
68
+ option: option.alias,
78
69
  name: e.name,
79
70
  status: e.status,
80
71
  message: e.message,
81
72
  data: e.data,
82
- }
83
- ];
84
- // If failed and there's a second option, atempt it
85
- if (field.or) {
86
- return await _attemptUnion(trx, field.or, path, raw, value, inject, ue);
73
+ });
87
74
  }
88
- // If this error was not the first attempt, and we have no other option
89
- // we throw a specific error
90
- // This avoid confusion for the client when parsing unions
91
- if (unionErrors.length) {
92
- throw error_1.NesoiError.Message.ValueDoesntMatchUnion({ alias: field.preAlias, path: path.join('.'), value, unionErrors: ue });
93
- }
94
- throw e;
95
75
  }
96
- output = await applyFieldRules('item', field, path, raw, output, inject);
76
+ if (unionErrors.length === Object.keys(field.children).length) {
77
+ throw error_1.NesoiError.Message.ValueDoesntMatchUnion({ alias: field.alias, path: path.join('.'), value, unionErrors });
78
+ }
97
79
  return output;
98
80
  }
99
81
  /**
@@ -105,7 +87,8 @@ async function _runParseMethod(trx, field, path, raw, value, inject) {
105
87
  switch (field.type) {
106
88
  case 'obj':
107
89
  case 'dict':
108
- return await parseParentField(trx, field, path, raw, value, inject);
90
+ case 'list':
91
+ return parseParentField(trx, field, path, raw, value, inject);
109
92
  case 'unknown':
110
93
  return value;
111
94
  case 'boolean':
@@ -131,30 +114,41 @@ async function _runParseMethod(trx, field, path, raw, value, inject) {
131
114
  case 'string_or_number':
132
115
  return (0, parse_1.parseStringOrNumber)(field, path, value);
133
116
  case 'id':
134
- return await parseIdField(trx, field, path, value);
117
+ return parseIdField(trx, field, path, value);
135
118
  }
136
119
  throw error_1.NesoiError.Builder.Message.UnknownTemplateFieldType(field.type);
137
120
  }
138
121
  /**
139
- * [Parser Step 3-b]: 'obj' or 'dict'
122
+ * [Parser Step 3-b]: 'obj' or 'dict' or 'list'
140
123
  *
141
124
  * - The parser methods only return a tuple of field and value, to be parsed again by (step 1)
142
125
  * - When calling step 1, the child property name is appended to the path
143
126
  */
144
127
  async function parseParentField(trx, field, path, raw, value, inject) {
145
- let children;
146
- if (field.type === 'obj') {
147
- children = (0, parse_1.parseObj)(field, path, value);
128
+ if (field.type === 'list') {
129
+ const children = (0, parse_1.parseList)(field, path, value);
130
+ const parsedParent = [];
131
+ for (const key in children) {
132
+ const child = children[key];
133
+ parsedParent.push(await parseFieldValue(trx, child.field, [...path, key], raw, child.value, inject));
134
+ }
135
+ return parsedParent;
148
136
  }
149
137
  else {
150
- children = (0, parse_1.parseDict)(field, path, value);
151
- }
152
- const parsedParent = {};
153
- for (const key in children) {
154
- const child = children[key];
155
- parsedParent[key] = await parseFieldValue(trx, child.field, [...path, key], raw, child.value, inject);
138
+ let children;
139
+ if (field.type === 'obj') {
140
+ children = (0, parse_1.parseObj)(field, path, value);
141
+ }
142
+ else {
143
+ children = (0, parse_1.parseDict)(field, path, value);
144
+ }
145
+ const parsedParent = {};
146
+ for (const key in children) {
147
+ const child = children[key];
148
+ parsedParent[key] = await parseFieldValue(trx, child.field, [...path, key], raw, child.value, inject);
149
+ }
150
+ return parsedParent;
156
151
  }
157
- return parsedParent;
158
152
  }
159
153
  /**
160
154
  * [Parser Step 3-b]: 'id'
@@ -166,12 +160,7 @@ async function parseIdField(trx, field, path, value) {
166
160
  const type = field.meta.id.type;
167
161
  const view = field.meta.id.view;
168
162
  const parsed = await (0, parse_1.parseId)(field, path, value, trx, bucket.refName, type, view);
169
- if (field.array) {
170
- return parsed.map((p) => p.obj);
171
- }
172
- else {
173
- return parsed.obj;
174
- }
163
+ return parsed.obj;
175
164
  }
176
165
  function sanitize(field, path, value) {
177
166
  if (typeof value === 'function') {
@@ -201,13 +190,9 @@ function isEmpty(value) {
201
190
  /**
202
191
  * Rules
203
192
  */
204
- async function applyFieldRules(mode, field, path, raw, value, inject) {
193
+ async function applyFieldRules(field, path, raw, value, inject) {
205
194
  let output = value;
206
- // If mode is item, the value received is not an array
207
- // - This comes from a .rule *before* .array
208
- // If mode is array, the value received is an array
209
- // - This comes from a .rule *after* .array
210
- const rules = mode === 'item' ? field.rules : field.arrayRules;
195
+ const rules = field.rules;
211
196
  for (const r in rules) {
212
197
  const rule = rules[r];
213
198
  const res = await rule({ field, value, path: path.join('.'), msg: raw, inject });
@@ -122,6 +122,7 @@ class InlineApp extends app_1.App {
122
122
  Object.values(modules).forEach(module => {
123
123
  module.injectDependencies(modules, {
124
124
  buckets: Object.values(module.schema.externals.buckets),
125
+ messages: Object.values(module.schema.externals.messages),
125
126
  jobs: Object.values(module.schema.externals.jobs),
126
127
  machines: Object.values(module.schema.externals.machines),
127
128
  });
@@ -5,14 +5,14 @@ const bucket_schema_1 = require("../../elements/entities/bucket/bucket.schema");
5
5
  const bucket_model_schema_1 = require("../../elements/entities/bucket/model/bucket_model.schema");
6
6
  const bucket_graph_schema_1 = require("../../elements/entities/bucket/graph/bucket_graph.schema");
7
7
  exports.$TrashBucket = new bucket_schema_1.$Bucket('__trash__', 'trash', 'Trash', new bucket_model_schema_1.$BucketModel({
8
- id: new bucket_model_schema_1.$BucketModelField('id', 'id', 'int', 'id', false, true),
9
- module: new bucket_model_schema_1.$BucketModelField('module', 'module', 'string', 'Module Name', false, true),
10
- bucket: new bucket_model_schema_1.$BucketModelField('bucket', 'bucket', 'string', 'Bucket Name', false, true),
11
- object_id: new bucket_model_schema_1.$BucketModelField('object_id', 'object_id', 'int', 'Object ID', false, true),
12
- object: new bucket_model_schema_1.$BucketModelField('object', 'object', 'dict', 'Object', false, true, undefined, undefined, {
13
- __dict: new bucket_model_schema_1.$BucketModelField('', '', 'unknown', '', false, true, undefined, undefined)
8
+ id: new bucket_model_schema_1.$BucketModelField('id', 'id', 'int', 'id', true),
9
+ module: new bucket_model_schema_1.$BucketModelField('module', 'module', 'string', 'Module Name', true),
10
+ bucket: new bucket_model_schema_1.$BucketModelField('bucket', 'bucket', 'string', 'Bucket Name', true),
11
+ object_id: new bucket_model_schema_1.$BucketModelField('object_id', 'object_id', 'int', 'Object ID', true),
12
+ object: new bucket_model_schema_1.$BucketModelField('object', 'object', 'dict', 'Object', true, undefined, undefined, {
13
+ '#': new bucket_model_schema_1.$BucketModelField('', '', 'unknown', '', true, undefined, undefined)
14
14
  }),
15
- delete_trx_id: new bucket_model_schema_1.$BucketModelField('delete_trx_id', 'delete_trx_id', 'int', 'ID of Delete Transaction', false, true),
15
+ delete_trx_id: new bucket_model_schema_1.$BucketModelField('delete_trx_id', 'delete_trx_id', 'int', 'ID of Delete Transaction', true),
16
16
  }), new bucket_graph_schema_1.$BucketGraph(), {});
17
17
  class Trash {
18
18
  static async add(trx, module, bucket, object) {
@@ -10,7 +10,10 @@ export declare class Tree {
10
10
  * - `*`: Return all values of the matched array or dict
11
11
  * - `0`: Return the first value of an array or dict (dict ordering is unstable)
12
12
  * - `(number|string)[]`: Sequence of values to replace the `#`s on the fieldpath
13
+ *
14
+ * @deprecated Fieldpath was consolidated into Modelpath and Querypath.
13
15
  */
14
16
  static get(obj: Record<string, any>, fieldpath: string, index?: '*' | 0 | (number | string)[]): any;
17
+ static getModelpath(obj: Record<string, any>, modelpath: string, index: (string | number)[]): any[];
15
18
  static set(obj: Record<string, any>, fieldpath: string, replacer: (v: any, i: (number | string)[]) => any, __index?: (number | string)[]): void;
16
19
  }
@@ -17,6 +17,8 @@ class Tree {
17
17
  * - `*`: Return all values of the matched array or dict
18
18
  * - `0`: Return the first value of an array or dict (dict ordering is unstable)
19
19
  * - `(number|string)[]`: Sequence of values to replace the `#`s on the fieldpath
20
+ *
21
+ * @deprecated Fieldpath was consolidated into Modelpath and Querypath.
20
22
  */
21
23
  static get(obj, fieldpath, index = '*') {
22
24
  index = (!Array.isArray(index)) ? index : [...index];
@@ -90,6 +92,40 @@ class Tree {
90
92
  }
91
93
  return ref;
92
94
  }
95
+ static getModelpath(obj, modelpath, index) {
96
+ const paths = modelpath.split('.');
97
+ let poll = [obj];
98
+ while (poll.length) {
99
+ const next = [];
100
+ for (const item of poll) {
101
+ const path = paths[item.i];
102
+ // '*'
103
+ if (path === '*') {
104
+ if (typeof item !== 'object') {
105
+ throw new Error(`Can't read *, item is not object (${item})`);
106
+ }
107
+ next.push(...Object.values(item));
108
+ }
109
+ else {
110
+ const idx_str = path.match(/^\$(\d+)/)?.[1];
111
+ let _path = path;
112
+ // $0, $1..
113
+ if (idx_str !== undefined) {
114
+ const idx = parseInt(idx_str);
115
+ if (idx >= index.length) {
116
+ throw new Error(`Can't read $${idx}, too few indexes (${index.length})`);
117
+ }
118
+ _path = index[idx];
119
+ }
120
+ const n = typeof item === 'object' ? item[_path] : undefined;
121
+ if (n)
122
+ next.push(n);
123
+ }
124
+ }
125
+ poll = next;
126
+ }
127
+ return poll;
128
+ }
93
129
  static set(obj, fieldpath, replacer, __index = []) {
94
130
  const paths = fieldpath.split('.');
95
131
  class Ptr {
@@ -7,32 +7,32 @@ import { NesoiDatetime } from '../data/datetime';
7
7
  import { NesoiFile } from '../data/file';
8
8
  import { NesoiDuration } from '../data/duration';
9
9
  export declare function parseBoolean(field: {
10
- path_raw: string;
10
+ pathRaw: string;
11
11
  alias: string;
12
12
  }, path: string[], value: any): boolean;
13
13
  export declare function parseDate(field: {
14
- path_raw: string;
14
+ pathRaw: string;
15
15
  alias: string;
16
16
  }, path: string[], value: any): NesoiDate;
17
17
  export declare function parseDatetime(field: {
18
- path_raw: string;
18
+ pathRaw: string;
19
19
  alias: string;
20
20
  }, path: string[], value: any): NesoiDatetime;
21
21
  export declare function parseDuration(field: {
22
- path_raw: string;
22
+ pathRaw: string;
23
23
  alias: string;
24
24
  }, path: string[], value: any): NesoiDuration;
25
25
  export declare function parseDecimal(field: {
26
- path_raw: string;
26
+ pathRaw: string;
27
27
  alias: string;
28
28
  }, path: string[], value: any): NesoiDecimal;
29
29
  export declare function parseEnum(raw: Record<string, any>, field: {
30
- path_raw: string;
30
+ pathRaw: string;
31
31
  name: string;
32
32
  alias: string;
33
33
  }, path: string[], value: any, options: string | readonly string[] | Record<string, any>, trx: AnyTrxNode): any;
34
34
  export declare function parseFile(field: {
35
- path_raw: string;
35
+ pathRaw: string;
36
36
  name: string;
37
37
  alias: string;
38
38
  }, path: string[], value: any, options?: {
@@ -40,30 +40,38 @@ export declare function parseFile(field: {
40
40
  extnames?: string[];
41
41
  }): NesoiFile;
42
42
  export declare function parseFloat_(field: {
43
- path_raw: string;
43
+ pathRaw: string;
44
44
  alias: string;
45
45
  }, path: string[], value: any): number;
46
46
  export declare function parseId<M extends $Module, Name extends BucketName<M>, View extends ViewName<M['buckets'][Name]> | undefined>(field: {
47
- path_raw: string;
47
+ pathRaw: string;
48
48
  alias: string;
49
49
  }, path: string[], value: any, trx: AnyTrxNode, bucket: Name, type?: 'int' | 'string', view?: View): Promise<{
50
50
  id: string | number;
51
51
  obj: any;
52
52
  }>;
53
53
  export declare function parseInt_(field: {
54
- path_raw: string;
54
+ pathRaw: string;
55
55
  alias: string;
56
56
  }, path: string[], value: any): number;
57
57
  export declare function parseString(field: {
58
- path_raw: string;
58
+ pathRaw: string;
59
59
  alias: string;
60
60
  }, path: string[], value: any): string;
61
61
  export declare function parseStringOrNumber(field: {
62
- path_raw: string;
62
+ pathRaw: string;
63
63
  alias: string;
64
64
  }, path: string[], value: any): string | number;
65
65
  export declare function parseDict(field: {
66
- path_raw: string;
66
+ pathRaw: string;
67
+ alias: string;
68
+ children?: $MessageTemplateFields;
69
+ }, path: string[], value: any): Record<string, {
70
+ field: $MessageTemplateField;
71
+ value?: any;
72
+ }>;
73
+ export declare function parseList(field: {
74
+ pathRaw: string;
67
75
  alias: string;
68
76
  children?: $MessageTemplateFields;
69
77
  }, path: string[], value: any): Record<string, {
@@ -71,7 +79,7 @@ export declare function parseDict(field: {
71
79
  value?: any;
72
80
  }>;
73
81
  export declare function parseObj(field: {
74
- path_raw: string;
82
+ pathRaw: string;
75
83
  alias: string;
76
84
  children?: $MessageTemplateFields;
77
85
  }, path: string[], value: any): Record<string, {
@@ -13,6 +13,7 @@ exports.parseInt_ = parseInt_;
13
13
  exports.parseString = parseString;
14
14
  exports.parseStringOrNumber = parseStringOrNumber;
15
15
  exports.parseDict = parseDict;
16
+ exports.parseList = parseList;
16
17
  exports.parseObj = parseObj;
17
18
  const date_1 = require("../data/date");
18
19
  const error_1 = require("../data/error");
@@ -180,7 +181,7 @@ function parseDict(field, path, value) {
180
181
  if (typeof value === 'object') {
181
182
  const children = {};
182
183
  for (const key in value) {
183
- const _field = field.children['__dict'];
184
+ const _field = field.children['#'];
184
185
  children[key] = {
185
186
  field: _field,
186
187
  value: value[key]
@@ -190,6 +191,20 @@ function parseDict(field, path, value) {
190
191
  }
191
192
  throw error_1.NesoiError.Message.InvalidFieldType({ alias: field.alias, path: path.join('.'), value, type: 'dict' });
192
193
  }
194
+ function parseList(field, path, value) {
195
+ if (!Array.isArray(value)) {
196
+ throw error_1.NesoiError.Message.InvalidFieldType({ alias: field.alias, path: path.join('.'), value, type: 'list' });
197
+ }
198
+ const children = {};
199
+ for (let i = 0; i < value.length; i++) {
200
+ const _field = field.children['#'];
201
+ children[i] = {
202
+ field: _field,
203
+ value: value[i]
204
+ };
205
+ }
206
+ return children;
207
+ }
193
208
  function parseObj(field, path, value) {
194
209
  if (typeof value === 'object') {
195
210
  if (!field.children)
@@ -197,8 +212,8 @@ function parseObj(field, path, value) {
197
212
  const children = {};
198
213
  for (const key in field.children) {
199
214
  const _field = field.children[key];
200
- const key_raw = _field.path_raw.split('.')[path.length];
201
- const key_parsed = _field.path_parsed.split('.')[path.length];
215
+ const key_raw = _field.pathRaw.split('.')[path.length];
216
+ const key_parsed = _field.pathParsed.split('.')[path.length];
202
217
  children[key_parsed] = {
203
218
  field: _field,
204
219
  value: value[key_raw]
@@ -5,3 +5,6 @@ export type MergeUnion<T> = {
5
5
  [J in K]: any;
6
6
  } ? T[K] : never;
7
7
  };
8
+ export type UnionToIntersection<T> = {
9
+ [K in T as K & string]: K;
10
+ }[any];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nesoi",
3
- "version": "3.0.21",
3
+ "version": "3.1.0",
4
4
  "description": "Declarative framework for data-driven applications",
5
5
  "repository": {
6
6
  "type": "git",
@@ -0,0 +1,9 @@
1
+ import { AnyBucketBuilder } from "../../src/elements/entities/bucket/bucket.builder";
2
+ import { NesoiError } from "../../src/engine/data/error";
3
+ import { AnyBuilder } from "../../src/engine/module";
4
+ export declare function expectBucket(def: (builder: AnyBucketBuilder) => any, inject?: AnyBuilder[]): {
5
+ toBuildOne(raw: Record<string, any>, view: string): {
6
+ as(parsed: Record<string, any>): Promise<void>;
7
+ butFail(error: (...args: any[]) => NesoiError.BaseError): Promise<void>;
8
+ };
9
+ };