nesoi 3.0.20 → 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 (86) 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.builder.js +2 -2
  59. package/lib/elements/entities/message/message.infer.d.ts +6 -30
  60. package/lib/elements/entities/message/message.schema.js +2 -2
  61. package/lib/elements/entities/message/message_parser.d.ts +0 -1
  62. package/lib/elements/entities/message/message_parser.js +1 -68
  63. package/lib/elements/entities/message/template/message_template.builder.js +1 -1
  64. package/lib/elements/entities/message/template/message_template.schema.d.ts +11 -6
  65. package/lib/elements/entities/message/template/message_template.schema.js +29 -6
  66. package/lib/elements/entities/message/template/message_template_field.builder.d.ts +50 -203
  67. package/lib/elements/entities/message/template/message_template_field.builder.js +74 -74
  68. package/lib/elements/entities/message/template/message_template_parser.d.ts +2 -2
  69. package/lib/elements/entities/message/template/message_template_parser.js +137 -71
  70. package/lib/engine/apps/inline.app.js +1 -0
  71. package/lib/engine/data/error.d.ts +12 -11
  72. package/lib/engine/data/error.js +7 -7
  73. package/lib/engine/data/trash.js +7 -7
  74. package/lib/engine/data/tree.d.ts +3 -0
  75. package/lib/engine/data/tree.js +36 -0
  76. package/lib/engine/util/parse.d.ts +36 -28
  77. package/lib/engine/util/parse.js +53 -43
  78. package/lib/engine/util/type.d.ts +3 -0
  79. package/package.json +1 -1
  80. package/tools/joaquin/bucket.d.ts +9 -0
  81. package/tools/joaquin/bucket.js +49 -0
  82. package/tools/joaquin/message.d.ts +2 -1
  83. package/tools/joaquin/message.js +9 -2
  84. package/tools/joaquin/mock.d.ts +1 -0
  85. package/tools/joaquin/mock.js +13 -5
  86. package/tsconfig.build.tsbuildinfo +1 -1
@@ -12,9 +12,13 @@ class MessageTemplateFieldFactory {
12
12
  constructor(module) {
13
13
  this.module = module;
14
14
  }
15
+ /**
16
+ * Specifies an alias for the field.
17
+ */
15
18
  as(alias) {
16
- this.alias = alias;
17
- return this;
19
+ const chain = new MessageTemplateFieldFactory(this.module);
20
+ chain.alias = alias;
21
+ return chain;
18
22
  }
19
23
  get any() {
20
24
  return new MessageTemplateFieldBuilder('unknown', {}, this.alias);
@@ -74,10 +78,15 @@ class MessageTemplateFieldFactory {
74
78
  return new MessageTemplateFieldBuilder('obj', {}, this.alias, children);
75
79
  }
76
80
  dict(item) {
77
- item = item.optional;
78
81
  return new MessageTemplateFieldBuilder('dict', {}, this.alias, { __dict: item });
79
82
  }
80
- 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 = {}) {
81
90
  // Module and tag are updated on build
82
91
  const ref = new dependency_1.$Dependency(this.module, 'message', msg);
83
92
  return new MessageTemplateFieldBuilder('msg', { msg: ref }, this.alias, extra);
@@ -101,10 +110,9 @@ class MessageTemplateFieldBuilder {
101
110
  this.value = value;
102
111
  this.alias = alias;
103
112
  this.children = children;
104
- this._array = false;
105
113
  this._required = true;
106
114
  this._defaultValue = undefined;
107
- this._nullable = true;
115
+ this._nullable = false;
108
116
  this._rules = [];
109
117
  }
110
118
  as(alias) {
@@ -113,99 +121,91 @@ class MessageTemplateFieldBuilder {
113
121
  }
114
122
  get optional() {
115
123
  this._required = false;
116
- if (this._or) {
117
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions
118
- this._or.optional;
119
- }
120
124
  return this;
121
125
  }
122
126
  default(value) {
123
127
  this._required = false;
124
128
  this._defaultValue = value;
125
- if (this._or) {
126
- this._or.default(value);
127
- }
128
129
  return this;
129
130
  }
130
131
  get nullable() {
131
132
  this._nullable = true;
132
- if (this._or) {
133
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions
134
- this._or.nullable;
135
- }
136
133
  return this;
137
134
  }
138
135
  rule(rule) {
139
136
  this._rules.push(rule);
140
137
  return this;
141
138
  }
142
- get array() {
143
- this._array = true;
144
- if (this._or) {
145
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions
146
- this._or.array;
147
- }
148
- return this;
149
- }
150
- or(def) {
151
- this._or = def;
152
- this._or._array = this._array;
153
- this._or._defaultValue = this._defaultValue;
154
- this._or._nullable = this._nullable;
155
- this._or._required = this._required;
156
- this._or._rules = this._rules;
157
- return this;
158
- }
159
139
  // Build
160
140
  static build(builder, name, tree, module, basePathRaw, basePathParsed) {
161
- const or = builder._or
162
- ? this.build(builder._or, name, tree, module, basePathRaw, basePathParsed)
163
- : undefined;
141
+ const pathRaw = basePathRaw + (builder.type === 'id' ? `${name}_id` : name);
164
142
  const pathParsed = basePathParsed + name;
165
- const pathRaw = basePathParsed + (builder.type === 'id'
166
- ? builder._array ? `${name}_ids` : `${name}_id`
167
- : name);
168
- const childrenBasePathRaw = pathRaw + (builder._array ? '.#.' : '.');
169
- const childrenBasePathParsed = pathParsed + (builder._array ? '.#.' : '.');
170
- 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') {
171
148
  const bucket = tree.getSchema(builder.value.id.bucket);
172
149
  builder.value.id.type = bucket.model.fields.id.type;
173
150
  }
174
- return new message_template_schema_1.$MessageTemplateField(builder.type, name, builder.alias || name, pathRaw, pathParsed, builder._array, builder._required, builder._defaultValue, builder._nullable, builder._rules, 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);
175
196
  }
176
- static buildChildren(fields, tree, module, basePathRaw = '', basePathParsed = '') {
197
+ static buildMany(fields, tree, module, basePathRaw = '', basePathParsed = '', name, key) {
177
198
  const schema = {};
178
199
  for (const c in fields) {
179
- const child = fields[c];
180
- // Extended fields inherit from other messages
181
- if (child.__ext) {
182
- const ext = tree.getSchema(child.__ext);
183
- schema[c].children = Object.assign({}, ext.template.fields, schema[c].children || {});
184
- continue;
185
- }
186
- const param = c;
187
- // A .msg() parameter is an obj which takes fields from
188
- // another message
189
- if (child.type === 'msg') {
190
- const name = child.value.msg.name;
191
- const $msg = module.messages[name];
192
- if (!$msg) {
193
- throw error_1.NesoiError.Builder.Message.UnknownModuleMessage(name);
194
- }
195
- const builder = new MessageTemplateFieldFactory(module.name).obj({});
196
- builder.alias = child.alias;
197
- builder._required = child._required;
198
- builder._defaultValue = child._defaultValue;
199
- builder._nullable = child._nullable;
200
- builder._rules = child._rules.slice(0, -1);
201
- builder.children = child.children;
202
- schema[param] = MessageTemplateFieldBuilder.build(builder, c, tree, module, basePathRaw, basePathParsed);
203
- schema[param].children = schema[param].children || {};
204
- Object.assign(schema[param].children, $msg.template.fields);
200
+ if (c === '__ext')
205
201
  continue;
206
- }
207
- // All other parameters are built directly
208
- 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);
209
209
  }
210
210
  return schema;
211
211
  }
@@ -1,6 +1,6 @@
1
- import { $MessageTemplateField } from './message_template.schema';
1
+ import { $MessageTemplateFields } from './message_template.schema';
2
2
  import { AnyTrxNode } from "../../../../engine/transaction/trx_node";
3
- export declare function MessageTemplateFieldParser(raw: Record<string, any>, trx: AnyTrxNode, field: $MessageTemplateField, value: any): Promise<any>;
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
6
  */
@@ -4,19 +4,34 @@ exports.MessageTemplateFieldParser = MessageTemplateFieldParser;
4
4
  exports.isEmpty = isEmpty;
5
5
  const parse_1 = require("../../../../engine/util/parse");
6
6
  const error_1 = require("../../../../engine/data/error");
7
- async function MessageTemplateFieldParser(raw, trx, field, value) {
8
- return parseFieldValue(trx, field, raw, value, 0);
7
+ // TODO: OPTIMIZATION
8
+ // Parse everything that's static first, then move on to
9
+ // parsing ids etc.
10
+ async function MessageTemplateFieldParser(trx, fields, raw) {
11
+ const parsed = {};
12
+ const inject = {};
13
+ for (const k in fields) {
14
+ const field = fields[k];
15
+ const key_raw = field.pathRaw.split('.')[0];
16
+ const key_parsed = field.pathParsed.split('.')[0];
17
+ const value = raw[key_raw];
18
+ parsed[key_parsed] = await parseFieldValue(trx, field, [field.name], raw, value, inject);
19
+ }
20
+ Object.assign(parsed, inject);
21
+ return parsed;
9
22
  }
10
- // Attempt to parse a field value
11
- // - If field is an array, this method is run for each value, sequentially
12
- // - If not, it's run for the original value, once
13
- //
14
- // - This method stacks with the .or options
15
- //
16
- async function parseFieldValue(trx, field, raw, value, path_idx) {
23
+ /**
24
+ * [Parser Step 1]
25
+ *
26
+ * - Check for empty fields ({}, [], '', null, undefined)
27
+ * - If it's array, run step 2 for each value (with this field and path+i)
28
+ * - If not, run step 2 for the original value (with this field and path)
29
+ */
30
+ async function parseFieldValue(trx, field, path, raw, value, inject) {
31
+ sanitize(field, path, value);
17
32
  if (isEmpty(value)) {
18
33
  if (field.required) {
19
- throw error_1.NesoiError.Message.FieldIsRequired({ field: field.alias, path: field.path_raw, value });
34
+ throw error_1.NesoiError.Message.FieldIsRequired({ alias: field.alias, path: path.join('.'), value });
20
35
  }
21
36
  else if (field.defaultValue !== undefined) {
22
37
  return field.defaultValue;
@@ -25,100 +40,133 @@ async function parseFieldValue(trx, field, raw, value, path_idx) {
25
40
  return undefined;
26
41
  }
27
42
  }
28
- if (field.array) {
29
- if (!Array.isArray(value)) {
30
- throw error_1.NesoiError.Message.InvalidFieldType({ field: field.alias, path: field.path_raw, value, type: 'list' });
31
- }
32
- if (field.required && !value.length) {
33
- throw error_1.NesoiError.Message.FieldIsRequired({ field: field.alias, path: field.path_raw, value });
34
- }
35
- const parsedValue = [];
36
- for (let i = 0; i < value.length; i++) {
37
- const v = value[i];
38
- const parsed = await _attemptUnion(trx, field, raw, v, path_idx + 1);
39
- parsedValue.push(parsed);
40
- }
41
- return parsedValue;
42
- }
43
- return _attemptUnion(trx, field, raw, value, path_idx);
43
+ let output = await _attemptUnion(trx, field, path, raw, value, inject);
44
+ output = await applyFieldRules(field, path, raw, output, inject);
45
+ return output;
44
46
  }
45
- async function _attemptUnion(trx, field, raw, value, path_idx, unionErrors = []) {
46
- try {
47
- return await _runParseMethod(trx, field, raw, value, path_idx);
47
+ /**
48
+ * [Parser Step 2]
49
+ *
50
+ * - Attempt to run parse method (step 3) for field.
51
+ * - If it fails, attempt other union options (step 2) (if available), with same path
52
+ * - If it works, apply field rules.
53
+ */
54
+ async function _attemptUnion(trx, field, path, raw, value, inject) {
55
+ if (field.type !== 'union') {
56
+ return _runParseMethod(trx, field, path, raw, value, inject);
48
57
  }
49
- catch (e) {
50
- // If failed and there's a second option, atempt it
51
- if (field.or) {
52
- return await _attemptUnion(trx, field.or, raw, value, path_idx, [...unionErrors, e]);
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;
53
65
  }
54
- // If this error was not the first attempt, and we have no other option
55
- // we throw a specific error
56
- // This avoid confusion for the client when parsing unions
57
- if (unionErrors.length) {
58
- throw error_1.NesoiError.Message.ValueDoesntMatchUnion({ field: field.alias, path: field.path_raw, value, unionErrors: [...unionErrors, e] });
66
+ catch (e) {
67
+ unionErrors.push({
68
+ option: option.alias,
69
+ name: e.name,
70
+ status: e.status,
71
+ message: e.message,
72
+ data: e.data,
73
+ });
59
74
  }
60
- throw e;
61
75
  }
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
+ }
79
+ return output;
62
80
  }
63
- async function _runParseMethod(trx, field, raw, value, path_idx) {
81
+ /**
82
+ * [Parser Step 3]
83
+ *
84
+ * - Run a specific parsing method based on the field type
85
+ */
86
+ async function _runParseMethod(trx, field, path, raw, value, inject) {
64
87
  switch (field.type) {
65
88
  case 'obj':
66
89
  case 'dict':
67
- return await parseParentField(trx, field, raw, value, path_idx);
90
+ case 'list':
91
+ return parseParentField(trx, field, path, raw, value, inject);
68
92
  case 'unknown':
69
93
  return value;
70
94
  case 'boolean':
71
- return (0, parse_1.parseBoolean)(field, value);
95
+ return (0, parse_1.parseBoolean)(field, path, value);
72
96
  case 'date':
73
- return (0, parse_1.parseDate)(field, value);
97
+ return (0, parse_1.parseDate)(field, path, value);
74
98
  case 'datetime':
75
- return (0, parse_1.parseDatetime)(field, value);
99
+ return (0, parse_1.parseDatetime)(field, path, value);
76
100
  case 'duration':
77
- return (0, parse_1.parseDuration)(field, value);
101
+ return (0, parse_1.parseDuration)(field, path, value);
78
102
  case 'decimal':
79
- return (0, parse_1.parseDecimal)(field, value);
103
+ return (0, parse_1.parseDecimal)(field, path, value);
80
104
  case 'enum':
81
- return (0, parse_1.parseEnum)(raw, field, value, field.meta.enum.options, trx);
105
+ return (0, parse_1.parseEnum)(raw, field, path, value, field.meta.enum.options, trx);
82
106
  case 'file':
83
- return (0, parse_1.parseFile)(field, value, field.meta.file);
107
+ return (0, parse_1.parseFile)(field, path, value, field.meta.file);
84
108
  case 'float':
85
- return (0, parse_1.parseFloat_)(field, value);
109
+ return (0, parse_1.parseFloat_)(field, path, value);
86
110
  case 'int':
87
- return (0, parse_1.parseInt_)(field, value);
111
+ return (0, parse_1.parseInt_)(field, path, value);
88
112
  case 'string':
89
- return (0, parse_1.parseString)(field, value);
113
+ return (0, parse_1.parseString)(field, path, value);
90
114
  case 'string_or_number':
91
- return (0, parse_1.parseStringOrNumber)(field, value);
115
+ return (0, parse_1.parseStringOrNumber)(field, path, value);
92
116
  case 'id':
93
- return await parseIdField(trx, field, value);
117
+ return parseIdField(trx, field, path, value);
94
118
  }
95
119
  throw error_1.NesoiError.Builder.Message.UnknownTemplateFieldType(field.type);
96
120
  }
97
- async function parseParentField(trx, field, raw, value, path_idx) {
98
- let children;
99
- if (field.type === 'obj') {
100
- children = (0, parse_1.parseObj)(field, value, path_idx);
121
+ /**
122
+ * [Parser Step 3-b]: 'obj' or 'dict' or 'list'
123
+ *
124
+ * - The parser methods only return a tuple of field and value, to be parsed again by (step 1)
125
+ * - When calling step 1, the child property name is appended to the path
126
+ */
127
+ async function parseParentField(trx, field, path, raw, value, inject) {
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;
101
136
  }
102
137
  else {
103
- children = (0, parse_1.parseDict)(field, value);
104
- }
105
- const parsed = {};
106
- for (const key in children) {
107
- const child = children[key];
108
- parsed[key] = await parseFieldValue(trx, child.field, raw, child.value, path_idx + 1);
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;
109
151
  }
110
- return parsed;
111
152
  }
112
- async function parseIdField(trx, field, value) {
153
+ /**
154
+ * [Parser Step 3-b]: 'id'
155
+ *
156
+ * - Gathers the data for parsing a id
157
+ */
158
+ async function parseIdField(trx, field, path, value) {
113
159
  const bucket = field.meta.id.bucket;
114
160
  const type = field.meta.id.type;
115
161
  const view = field.meta.id.view;
116
- const parsed = await (0, parse_1.parseId)(field, value, trx, bucket.refName, type, view);
117
- if (field.array) {
118
- return parsed.map((p) => p.obj);
119
- }
120
- else {
121
- return parsed.obj;
162
+ const parsed = await (0, parse_1.parseId)(field, path, value, trx, bucket.refName, type, view);
163
+ return parsed.obj;
164
+ }
165
+ function sanitize(field, path, value) {
166
+ if (typeof value === 'function') {
167
+ throw error_1.NesoiError.Message.UnsanitaryValue({
168
+ alias: field.alias, path: path.join('.'), details: 'Functions not allowed as message inputs.'
169
+ });
122
170
  }
123
171
  }
124
172
  /**
@@ -139,3 +187,21 @@ function isEmpty(value) {
139
187
  }
140
188
  return false;
141
189
  }
190
+ /**
191
+ * Rules
192
+ */
193
+ async function applyFieldRules(field, path, raw, value, inject) {
194
+ let output = value;
195
+ const rules = field.rules;
196
+ for (const r in rules) {
197
+ const rule = rules[r];
198
+ const res = await rule({ field, value, path: path.join('.'), msg: raw, inject });
199
+ if (typeof res === 'object') {
200
+ output = res.set;
201
+ }
202
+ else if (res !== true) {
203
+ throw error_1.NesoiError.Message.RuleFailed({ alias: field.alias, path: path.join('.'), rule, error: res });
204
+ }
205
+ }
206
+ return output;
207
+ }
@@ -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
  });
@@ -169,53 +169,54 @@ export declare namespace NesoiError {
169
169
  module: string;
170
170
  }): BaseError;
171
171
  function InvalidEnumScope($: {
172
+ alias: string;
172
173
  path: string;
173
- name: string;
174
- alias?: string;
175
174
  value: any;
176
175
  fieldpath: string;
177
176
  }): BaseError;
178
177
  function InvalidFieldEnumValue($: {
179
- field: string;
178
+ alias: string;
180
179
  path: string;
181
180
  value: any;
182
181
  type: string;
183
182
  options: string[];
184
183
  }): BaseError;
185
184
  function InvalidFieldType($: {
186
- field: string;
185
+ alias: string;
187
186
  path: string;
188
187
  value: any;
189
188
  type: string;
190
189
  }): BaseError;
191
190
  function ValueDoesntMatchUnion($: {
192
- field: string;
191
+ alias: string;
193
192
  path: string;
194
193
  value: any;
195
- unionErrors: string[];
194
+ unionErrors: Record<string, any>[];
196
195
  }): BaseError;
197
196
  function UnsanitaryValue($: {
197
+ alias: string;
198
+ path: string;
198
199
  details: string;
199
200
  }): BaseError;
200
201
  function FieldIsRequired($: {
201
- field: string;
202
+ alias: string;
202
203
  path: string;
203
204
  value: any;
204
205
  }): BaseError;
205
206
  function RuleFailed($: {
207
+ alias: string;
208
+ path: string;
206
209
  rule: $MessageTemplateRule;
207
210
  error: string;
208
211
  }): BaseError;
209
212
  function FileTooBig($: {
213
+ alias: string;
210
214
  path: string;
211
- name: string;
212
- alias?: string;
213
215
  maxsize: number;
214
216
  }): BaseError;
215
217
  function FileExtNotAllowed($: {
218
+ alias: string;
216
219
  path: string;
217
- name: string;
218
- alias?: string;
219
220
  options: string[];
220
221
  }): BaseError;
221
222
  }
@@ -302,19 +302,19 @@ var NesoiError;
302
302
  }
303
303
  Message.NotSupportedByModule = NotSupportedByModule;
304
304
  function InvalidEnumScope($) {
305
- return new BaseError('Message.InvalidEnumScope', `${$.alias || $.name} is an enum with dynamic scope, and the path '${$.fieldpath}' of the message has an invalid value '${$.value}'`, Status.BAD_REQUEST, $);
305
+ return new BaseError('Message.InvalidEnumScope', `${$.alias} is an enum with dynamic scope, and the path '${$.fieldpath}' of the message has an invalid value '${$.value}'`, Status.BAD_REQUEST, $);
306
306
  }
307
307
  Message.InvalidEnumScope = InvalidEnumScope;
308
308
  function InvalidFieldEnumValue($) {
309
- return new BaseError('Message.InvalidFieldEnumValue', `Message field '${$.field}' value '${$.value}' should be one of the following: ${$.options?.join(',')}`, Status.BAD_REQUEST, $);
309
+ return new BaseError('Message.InvalidFieldEnumValue', `Message field '${$.alias}' value '${$.value}' should be one of the following: ${$.options?.join(',')}`, Status.BAD_REQUEST, $);
310
310
  }
311
311
  Message.InvalidFieldEnumValue = InvalidFieldEnumValue;
312
312
  function InvalidFieldType($) {
313
- return new BaseError('Message.InvalidFieldType', `Message field '${$.field}' value '${$.value}' is not of type '${$.type}'`, Status.BAD_REQUEST, $);
313
+ return new BaseError('Message.InvalidFieldType', `Message field '${$.alias}' value '${$.value}' is not of type '${$.type}'`, Status.BAD_REQUEST, $);
314
314
  }
315
315
  Message.InvalidFieldType = InvalidFieldType;
316
316
  function ValueDoesntMatchUnion($) {
317
- return new BaseError('Message.ValueDoesntMatchUnion', `Message field '${$.field}' (${$.path}) value '${$.value}' doesn't match any of the union options'`, Status.BAD_REQUEST, $);
317
+ return new BaseError('Message.ValueDoesntMatchUnion', `Message field '${$.alias}' (${$.path}) value '${$.value}' doesn't match any of the union options'`, Status.BAD_REQUEST, $);
318
318
  }
319
319
  Message.ValueDoesntMatchUnion = ValueDoesntMatchUnion;
320
320
  function UnsanitaryValue($) {
@@ -322,7 +322,7 @@ var NesoiError;
322
322
  }
323
323
  Message.UnsanitaryValue = UnsanitaryValue;
324
324
  function FieldIsRequired($) {
325
- return new BaseError('Message.FieldIsRequired', `Field ${$.field} (${$.path}) is required`, Status.BAD_REQUEST, $);
325
+ return new BaseError('Message.FieldIsRequired', `Field ${$.alias} (${$.path}) is required`, Status.BAD_REQUEST, $);
326
326
  }
327
327
  Message.FieldIsRequired = FieldIsRequired;
328
328
  function RuleFailed($) {
@@ -330,11 +330,11 @@ var NesoiError;
330
330
  }
331
331
  Message.RuleFailed = RuleFailed;
332
332
  function FileTooBig($) {
333
- return new BaseError('Message.FileTooBig', `${$.alias || $.name} size exceeds max (${$.maxsize})`, Status.BAD_REQUEST, $);
333
+ return new BaseError('Message.FileTooBig', `${$.alias} size exceeds max (${$.maxsize})`, Status.BAD_REQUEST, $);
334
334
  }
335
335
  Message.FileTooBig = FileTooBig;
336
336
  function FileExtNotAllowed($) {
337
- return new BaseError('Message.FileExtNotAllowed', `${$.alias || $.name} extension not allowed. Options: ${$.options}`, Status.BAD_REQUEST, $);
337
+ return new BaseError('Message.FileExtNotAllowed', `${$.alias} extension not allowed. Options: ${$.options}`, Status.BAD_REQUEST, $);
338
338
  }
339
339
  Message.FileExtNotAllowed = FileExtNotAllowed;
340
340
  })(Message = NesoiError.Message || (NesoiError.Message = {}));
@@ -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
  }