nesoi 3.0.18 → 3.0.20

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 (27) hide show
  1. package/lib/compiler/elements/bucket.element.d.ts +1 -1
  2. package/lib/compiler/elements/bucket.element.js +25 -27
  3. package/lib/compiler/elements/message.element.js +50 -20
  4. package/lib/elements/blocks/block.builder.d.ts +10 -1
  5. package/lib/elements/blocks/block.builder.js +26 -0
  6. package/lib/elements/blocks/job/job.builder.d.ts +7 -1
  7. package/lib/elements/blocks/job/job.builder.js +4 -0
  8. package/lib/elements/entities/bucket/model/bucket_model.convert.js +11 -9
  9. package/lib/elements/entities/bucket/model/bucket_model_field.builder.d.ts +1 -1
  10. package/lib/elements/entities/bucket/model/bucket_model_field.builder.js +11 -8
  11. package/lib/elements/entities/bucket/view/bucket_view.js +2 -2
  12. package/lib/elements/entities/message/message_parser.d.ts +0 -4
  13. package/lib/elements/entities/message/message_parser.js +41 -75
  14. package/lib/elements/entities/message/template/message_template.schema.d.ts +25 -2
  15. package/lib/elements/entities/message/template/message_template.schema.js +16 -2
  16. package/lib/elements/entities/message/template/message_template_field.builder.d.ts +2 -2
  17. package/lib/elements/entities/message/template/message_template_field.builder.js +12 -10
  18. package/lib/elements/entities/message/template/message_template_parser.d.ts +6 -2
  19. package/lib/elements/entities/message/template/message_template_parser.js +121 -76
  20. package/lib/engine/data/error.d.ts +11 -0
  21. package/lib/engine/data/error.js +4 -0
  22. package/lib/engine/util/deep.d.ts +2 -0
  23. package/lib/engine/util/deep.js +30 -0
  24. package/lib/engine/util/parse.d.ts +39 -28
  25. package/lib/engine/util/parse.js +159 -188
  26. package/package.json +1 -1
  27. package/tsconfig.build.tsbuildinfo +1 -1
@@ -14,7 +14,7 @@ export declare class BucketElement extends Element<$Bucket> {
14
14
  private buildModelFieldType;
15
15
  private buildCompositionType;
16
16
  buildModelType(fields?: $BucketModelFields): ObjTypeAsObj;
17
- buildModelFieldNamesType(model: ObjTypeAsObj, fields?: $BucketModelFields, path?: string): Record<string, TypeAsObj>;
17
+ buildModelFieldNamesType(model: ObjTypeAsObj, fields?: $BucketModelFields): Record<string, TypeAsObj>;
18
18
  private buildGraphType;
19
19
  private buildViewsType;
20
20
  private buildViewType;
@@ -64,7 +64,7 @@ class BucketElement extends element_1.Element {
64
64
  bucket
65
65
  };
66
66
  }
67
- buildModelFieldType(field) {
67
+ buildModelFieldType(field, isUnion = false) {
68
68
  let type = 'unknown';
69
69
  if (field.type === 'boolean') {
70
70
  type = 'boolean';
@@ -119,35 +119,38 @@ class BucketElement extends element_1.Element {
119
119
  '[x in string]': field.children.__dict
120
120
  });
121
121
  }
122
- if (!field.required && field.defaultValue === undefined) {
123
- if (typeof type === 'object') {
124
- type.__optional = true;
125
- }
126
- else {
127
- type += ' | undefined';
128
- }
129
- }
130
- if (field.array) {
131
- if (typeof type === 'object') {
132
- type.__array = true;
133
- }
134
- else {
135
- type += '[]';
136
- }
137
- }
138
122
  if (field.or) {
139
- const orType = this.buildModelFieldType(field.or);
123
+ const orType = this.buildModelFieldType(field.or, true);
140
124
  if (typeof type === 'object') {
141
125
  type.__or = orType;
142
126
  }
143
127
  else if (typeof orType === 'object') {
128
+ const nonObj = type;
144
129
  type = orType;
145
- type.__or = orType;
130
+ type.__or = nonObj;
146
131
  }
147
132
  else {
148
133
  type = `${type} | ${orType}`;
149
134
  }
150
135
  }
136
+ if (!isUnion) {
137
+ if (!field.required && field.defaultValue === undefined) {
138
+ if (typeof type === 'object') {
139
+ type.__optional = true;
140
+ }
141
+ else {
142
+ type = `(${type}) | undefined`;
143
+ }
144
+ }
145
+ if (field.array) {
146
+ if (typeof type === 'object') {
147
+ type.__array = true;
148
+ }
149
+ else {
150
+ type = `(${type})[]`;
151
+ }
152
+ }
153
+ }
151
154
  return type;
152
155
  }
153
156
  buildCompositionType() {
@@ -171,25 +174,20 @@ class BucketElement extends element_1.Element {
171
174
  });
172
175
  return model;
173
176
  }
174
- buildModelFieldNamesType(model, fields = this.schema.model.fields, path) {
177
+ buildModelFieldNamesType(model, fields = this.schema.model.fields) {
175
178
  const fieldPaths = {};
176
179
  Object.entries(fields).forEach(([key, field]) => {
177
180
  if (key === '__dict') {
178
181
  return;
179
182
  }
180
- const keyPath = (path ? path + '.' : '') + key;
181
- fieldPaths[keyPath] = model[key];
183
+ fieldPaths[field.path] = model[key];
182
184
  if (field.children) {
183
185
  let nextFields = field.children;
184
- let nextKey = keyPath;
185
186
  if ('__dict' in field.children) {
186
187
  nextFields = field.children.__dict.children;
187
- nextKey += '.#';
188
188
  }
189
- if (field.array)
190
- nextKey += '.#';
191
189
  if (nextFields) {
192
- Object.assign(fieldPaths, this.buildModelFieldNamesType(model[key], nextFields, nextKey));
190
+ Object.assign(fieldPaths, this.buildModelFieldNamesType(model[key], nextFields));
193
191
  }
194
192
  }
195
193
  });
@@ -44,7 +44,7 @@ class MessageElement extends element_1.Element {
44
44
  buildIO(fields = this.schema.template.fields) {
45
45
  const input = {};
46
46
  const output = {};
47
- Object.entries(fields).forEach(([key, field]) => {
47
+ const buildField = (key, field, isUnion = false) => {
48
48
  if (field.type === 'boolean') {
49
49
  input[key] = 'boolean';
50
50
  output[key] = 'boolean';
@@ -138,36 +138,66 @@ class MessageElement extends element_1.Element {
138
138
  input[key] = 'unknown';
139
139
  output[key] = 'unknown';
140
140
  }
141
- if (!field.required) {
141
+ if (field.or) {
142
+ const orType = buildField(key, field.or, true);
142
143
  if (typeof input[key] === 'object') {
143
- input[key].__optional = true;
144
+ input[key].__or = orType;
145
+ }
146
+ else if (typeof orType === 'object') {
147
+ const nonObj = input[key];
148
+ input[key] = orType;
149
+ input[key].__or = nonObj;
144
150
  }
145
151
  else {
146
- input[key] += ' | undefined';
152
+ input[key] = `${input[key]} | ${orType}`;
147
153
  }
148
- if (field.defaultValue === undefined) {
149
- if (typeof output[key] === 'object') {
150
- output[key].__optional = true;
151
- }
152
- else {
153
- output[key] += ' | undefined';
154
- }
154
+ if (typeof output[key] === 'object') {
155
+ output[key].__or = orType;
155
156
  }
156
- }
157
- if (field.array) {
158
- if (typeof input[key] === 'object') {
159
- input[key].__array = true;
157
+ else if (typeof orType === 'object') {
158
+ const nonObj = output[key];
159
+ output[key] = orType;
160
+ output[key].__or = nonObj;
160
161
  }
161
162
  else {
162
- input[key] += '[]';
163
+ output[key] = `${output[key]} | ${orType}`;
163
164
  }
164
- if (typeof output[key] === 'object') {
165
- output[key].__array = true;
165
+ }
166
+ if (!isUnion) {
167
+ if (!field.required) {
168
+ if (typeof input[key] === 'object') {
169
+ input[key].__optional = true;
170
+ }
171
+ else {
172
+ input[key] = `(${input[key]}) | undefined`;
173
+ }
174
+ if (field.defaultValue === undefined) {
175
+ if (typeof output[key] === 'object') {
176
+ output[key].__optional = true;
177
+ }
178
+ else {
179
+ output[key] = `(${output[key]}) | undefined`;
180
+ }
181
+ }
166
182
  }
167
- else {
168
- output[key] += '[]';
183
+ if (field.array) {
184
+ if (typeof input[key] === 'object') {
185
+ input[key].__array = true;
186
+ }
187
+ else {
188
+ input[key] = `(${input[key]})[]`;
189
+ }
190
+ if (typeof output[key] === 'object') {
191
+ output[key].__array = true;
192
+ }
193
+ else {
194
+ output[key] = `(${output[key]})[]`;
195
+ }
169
196
  }
170
197
  }
198
+ };
199
+ Object.entries(fields).forEach(([key, field]) => {
200
+ buildField(key, field);
171
201
  });
172
202
  return { input, output };
173
203
  }
@@ -1,6 +1,6 @@
1
1
  import { $Module, $Space } from "../../schema";
2
2
  import { $BlockOutput, $BlockType } from './block.schema';
3
- import { MultiMessageTemplateDef } from "../entities/message/template/message_template.builder";
3
+ import { MessageTemplateDef, MultiMessageTemplateDef } from "../entities/message/template/message_template.builder";
4
4
  import { $Dependency, BuilderNode } from "../../engine/dependency";
5
5
  /**
6
6
  * @category Builders
@@ -19,11 +19,20 @@ export declare abstract class BlockBuilder<Space extends $Space, Module extends
19
19
  /** Block "human" name */
20
20
  as(alias: string): this;
21
21
  /**
22
+ * Inline messages. This messages is exposed to the module,
23
+ * with a name prefixed by the block name.
24
+ * @param def A method which takes a field factory as input and outputs a template builder
25
+ * @returns The Builder, for call-chaining
26
+ */
27
+ protected message<Name extends string, Def extends MessageTemplateDef<Space, Module, Name>>(name: Name, def: Def): unknown;
28
+ /**
29
+ * @deprecated
22
30
  * Inline messages. These messages are exposed to the module,
23
31
  * with a name prefixed by the block name.
24
32
  * @param def A method which takes a field factory as input and outputs a template builder
25
33
  * @returns The Builder, for call-chaining
26
34
  */
35
+ /** @deprecated Use `.message` instead. Will be removed on 3.1 */
27
36
  protected messages<Def extends MultiMessageTemplateDef<Space, Module>>(def: Def): unknown;
28
37
  authn(...providers: string[]): unknown;
29
38
  protected _input(...names: string[]): unknown;
@@ -26,11 +26,37 @@ class BlockBuilder {
26
26
  }
27
27
  // Inline Messages
28
28
  /**
29
+ * Inline messages. This messages is exposed to the module,
30
+ * with a name prefixed by the block name.
31
+ * @param def A method which takes a field factory as input and outputs a template builder
32
+ * @returns The Builder, for call-chaining
33
+ */
34
+ message(name, def) {
35
+ const msgName = `${this.name}${name.length ? ('.' + name) : ''}`;
36
+ this._inputMsgs.push(new dependency_1.$Dependency(this.module, 'message', msgName));
37
+ const builder = new message_builder_1.MessageBuilder(this.module, msgName)
38
+ .template(def);
39
+ this._inlineNodes.push(new dependency_1.BuilderNode({
40
+ module: this.module,
41
+ type: 'message',
42
+ name: msgName,
43
+ builder,
44
+ isInline: true,
45
+ filepath: [], // This is added later by Treeshake.blockInlineNodes()
46
+ dependencies: [] // This is added later by Treeshake.*()
47
+ }));
48
+ const dep = new dependency_1.$Dependency(this.module, 'message', msgName);
49
+ this._inputMsgs.push(dep);
50
+ return this;
51
+ }
52
+ /**
53
+ * @deprecated
29
54
  * Inline messages. These messages are exposed to the module,
30
55
  * with a name prefixed by the block name.
31
56
  * @param def A method which takes a field factory as input and outputs a template builder
32
57
  * @returns The Builder, for call-chaining
33
58
  */
59
+ /** @deprecated Use `.message` instead. Will be removed on 3.1 */
34
60
  messages(def) {
35
61
  const factory = new message_template_field_builder_1.MessageTemplateFieldFactory(this.module);
36
62
  const schema = def(factory);
@@ -1,7 +1,7 @@
1
1
  import { $Module, $Space, ScopedMessage, ScopedMessageName } from "../../../schema";
2
2
  import { $Job, $JobAssert, $JobMethod } from './job.schema';
3
3
  import { BlockBuilder } from '../block.builder';
4
- import { MultiMessageTemplateDef } from "../../entities/message/template/message_template.builder";
4
+ import { MessageTemplateDef, MultiMessageTemplateDef } from "../../entities/message/template/message_template.builder";
5
5
  import { Overlay } from "../../../engine/util/type";
6
6
  import { $MessageInfer } from "../../entities/message/message.infer";
7
7
  import { TrxNode } from "../../../engine/transaction/trx_node";
@@ -33,6 +33,12 @@ export declare class JobBuilder<Space extends $Space, Module extends $Module, Jo
33
33
  from: keyof Machine["states"] & string;
34
34
  to: keyof Machine["states"] & string;
35
35
  }>;
36
+ message<Name extends string, Def extends MessageTemplateDef<Space, Module, Name>, FullName extends string = `${Job['name']}${Name extends '' ? '' : '.'}${Name & string}`, Msg extends $Message = $MessageInfer<FullName, ($: any) => ReturnType<Def>>>(name: Name, def: Def): JobBuilder<Space, Overlay<Module, {
37
+ messages: Overlay<Module["messages"], { [K in FullName]: Msg; }>;
38
+ }>, Overlay<Job, {
39
+ "#input": Msg;
40
+ }>, Ctx>;
41
+ /** @deprecated Use `.message` instead. Will be removed on 3.1 */
36
42
  messages<Def extends MultiMessageTemplateDef<Space, Module>>(def: Def): JobBuilder<Space, Overlay<Module, {
37
43
  messages: Overlay<Module["messages"], { [K in keyof ReturnType<Def> as `${Job["name"]}${K extends "" ? "" : "."}${K & string}`]: $MessageInfer<`${Job["name"]}${K extends "" ? "" : "."}${K & string}`, ($: any) => ReturnType<Def>[K], ReturnType<Def>[K], import("../../entities/message/message.infer").$MessageInputInfer<ReturnType<Def>[K], ReturnType<Def>[K] extends infer T ? { [K_1 in keyof T]: ReturnType<Def>[K][K_1] extends import("../../entities/message/template/message_template_field.builder").MessageTemplateFieldBuilder<any, any, infer I, any, any, infer Opt extends [undefined, undefined], infer Nul extends [null, null]> ? {
38
44
  path: `${K_1 & string}${keyof I & string}`;
@@ -31,6 +31,10 @@ class JobBuilder extends block_builder_1.BlockBuilder {
31
31
  return this;
32
32
  }
33
33
  /* [Job] */
34
+ message(name, def) {
35
+ return super.message(name, def);
36
+ }
37
+ /** @deprecated Use `.message` instead. Will be removed on 3.1 */
34
38
  messages(def) {
35
39
  return super.messages(def);
36
40
  }
@@ -35,21 +35,23 @@ function convertToView(model, name, fields = model.fields, path) {
35
35
  * @subcategory Entity
36
36
  * */
37
37
  function convertToMessage(module, model, name, alias, include = [], exclude = []) {
38
+ const convertField = (field) => {
39
+ return new message_template_schema_1.$MessageTemplateField(field.type, field.name, field.alias, field.path, field.path, field.array, field.required, undefined, false, [], {
40
+ enum: field.meta?.enum ? {
41
+ options: field.meta.enum.options,
42
+ dep: field.meta.enum.dep ? new dependency_1.$Dependency(module, 'constants', `${field.meta.enum.dep.module}::${field.meta.enum.dep.name}`) : undefined
43
+ } : undefined
44
+ }, field.children ? convertFields(field.children, include, exclude) : undefined, field.or ? convertField(field.or) : undefined);
45
+ };
38
46
  const convertFields = (fields, include = [], exclude = [], root = '') => {
39
47
  const msgFields = {};
40
48
  for (const f in fields) {
41
49
  const field = fields[f];
42
- const path = root.length ? `${root}.${f}` : f;
43
- if ((include.length && !include.includes(path))
44
- || exclude.includes(path)) {
50
+ if ((include.length && !include.includes(field.path))
51
+ || exclude.includes(field.path)) {
45
52
  continue;
46
53
  }
47
- msgFields[f] = new message_template_schema_1.$MessageTemplateField(field.type, field.name, field.alias, path, field.array, field.required, undefined, false, [], {
48
- enum: field.meta?.enum ? {
49
- options: field.meta.enum.options,
50
- dep: field.meta.enum.dep ? new dependency_1.$Dependency(module, 'constants', `${field.meta.enum.dep.module}::${field.meta.enum.dep.name}`) : undefined
51
- } : undefined
52
- }, field.children ? convertFields(field.children, include, exclude) : undefined);
54
+ msgFields[f] = convertField(field);
53
55
  }
54
56
  return msgFields;
55
57
  };
@@ -132,7 +132,7 @@ export declare class BucketModelFieldBuilder<Module extends $Module, DefinedData
132
132
  */
133
133
  maxLength(val: number | null): void;
134
134
  encrypt(key: keyof Module['constants']['values'], algorithm?: string): void;
135
- static build(builder: BucketModelFieldBuilder<any, any>, name: string, path?: string): {
135
+ static build(builder: BucketModelFieldBuilder<any, any>, name: string, basePath?: string): {
136
136
  schema: $BucketModelField;
137
137
  hasFile: boolean;
138
138
  hasEncrypted: boolean;
@@ -129,11 +129,15 @@ class BucketModelFieldBuilder {
129
129
  }
130
130
  get array() {
131
131
  this._array = true;
132
+ if (this._or) {
133
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
134
+ this._or.array;
135
+ }
132
136
  return this;
133
137
  }
134
138
  or(def) {
135
- this._or = def;
136
- return this;
139
+ def._or = this;
140
+ return def;
137
141
  }
138
142
  /**
139
143
  * This can be applied to `string` and `enum` fields,
@@ -153,18 +157,17 @@ class BucketModelFieldBuilder {
153
157
  };
154
158
  }
155
159
  // Build
156
- static build(builder, name, path = '') {
157
- path += name;
160
+ static build(builder, name, basePath = '') {
161
+ const path = basePath + name;
162
+ const itemPath = builder._array ? path + '.#.' : path + '.';
158
163
  const children = builder.children
159
- ? BucketModelFieldBuilder.buildChildren(builder.module, builder.children, builder._array
160
- ? path + '.#.'
161
- : path + '.')
164
+ ? BucketModelFieldBuilder.buildChildren(builder.module, builder.children, itemPath)
162
165
  : undefined;
163
166
  const defaults = builder._defaultValue && builder.children
164
167
  ? Object.assign({}, builder._defaultValue, children?.defaults)
165
168
  : builder._defaultValue;
166
169
  const or = builder._or
167
- ? this.build(builder._or, name)
170
+ ? this.build(builder._or, name, basePath)
168
171
  : undefined;
169
172
  const schema = new bucket_model_schema_1.$BucketModelField(name, path, builder.type, builder.alias || name, builder._array, builder._required, builder.meta, defaults, children?.schema, or?.schema, builder.crypto);
170
173
  const hasFile = builder.type === 'file'
@@ -95,7 +95,6 @@ class BucketView {
95
95
  }
96
96
  parsedObj[k] = await doParse(prop.children || {}, index);
97
97
  }
98
- parsedObj['$v'] = this.schema.name;
99
98
  return parsedObj;
100
99
  };
101
100
  const parseModelProp = async (obj, prop, index, key) => {
@@ -129,7 +128,8 @@ class BucketView {
129
128
  }
130
129
  return rawValue;
131
130
  };
132
- const parsedObj = await doParse(this.schema.fields, '*');
131
+ const parsedObj = await doParse(this.schema.fields);
132
+ parsedObj['$v'] = this.schema.name;
133
133
  return {
134
134
  id: raw.id,
135
135
  ...parsedObj
@@ -12,9 +12,5 @@ export declare class MessageParser<$ extends $Message> {
12
12
  static parseWithTrxModule(trx: AnyTrxNode, raw: RawMessageInput<any, any>, sigKey?: string): Promise<any>;
13
13
  parse(trx: AnyTrxNode, raw: $['#raw'], sigKey?: string): Promise<Message<$>>;
14
14
  private sanitize;
15
- /**
16
- * Empty values: `{}`, `[]`, `''`, `null`, `undefined`
17
- */
18
- static isEmpty(value: any): boolean;
19
15
  }
20
16
  export type AnyMessageParser = MessageParser<$Message>;
@@ -33,80 +33,64 @@ class MessageParser {
33
33
  // parsing ids etc.
34
34
  async parse(trx, raw, sigKey) {
35
35
  log_1.Log.debug('trx', trx.globalId, `${(0, log_1.scopeTag)('message', this.schema.name)} Parse${sigKey ? ' (signed)' : ''}`, raw);
36
- const parseFields = async (trx, fields, obj) => {
37
- const parsedObj = {};
38
- for (const k in fields) {
39
- const field = fields[k];
40
- const keyWithSuffix = field.type === 'id'
41
- ? field.array ? `${k.slice(0, -1)}_ids` : `${k}_id`
42
- : k;
43
- const parsedField = await parseField(trx, field, obj[keyWithSuffix]);
44
- for (const suffix in parsedField) {
45
- parsedObj[field.name + suffix] = parsedField[suffix];
36
+ const applyFieldRules = async (field, parent, value, path) => {
37
+ // Apply rules to the field
38
+ // If field is an array, the value passed to the rule is the array itself
39
+ for (const r in field.rules) {
40
+ const rule = field.rules[r];
41
+ const res = await rule({ field, value, path: path.join('.'), msg: parsed });
42
+ if (typeof res === 'object') {
43
+ parent[path.at(-1)] = res.set;
46
44
  }
47
- }
48
- return parsedObj;
49
- };
50
- const parseField = async (trx, field, value) => {
51
- // 1. Sanitize input
52
- this.sanitize(value);
53
- // 2. Check for required fields
54
- let parsedValue;
55
- if (MessageParser.isEmpty(value)) {
56
- if (field.required) {
57
- const pathWithSuffix = field.type === 'id' ? `${field.path}_id` : field.path;
58
- throw error_1.NesoiError.Message.FieldIsRequired({ field: field.alias, path: pathWithSuffix, value });
45
+ else if (res !== true) {
46
+ throw error_1.NesoiError.Message.RuleFailed({ rule, error: res });
59
47
  }
60
- else if (field.defaultValue !== undefined) {
61
- parsedValue = { '': field.defaultValue };
48
+ }
49
+ if (!value)
50
+ return;
51
+ if (field.type === 'obj') {
52
+ if (field.array) {
53
+ for (let i = 0; i < value?.length; i++) {
54
+ await applyRules(field.children, value[i] || {}, [...path, i.toString()]);
55
+ }
62
56
  }
63
57
  else {
64
- parsedValue = { '': undefined };
58
+ await applyRules(field.children, value || {}, path);
65
59
  }
66
60
  }
67
- else {
61
+ else if (field.type === 'dict') {
68
62
  if (field.array) {
69
- if (!Array.isArray(value)) {
70
- throw error_1.NesoiError.Message.InvalidFieldType({ field: field.alias, value, type: 'list' });
63
+ for (let i = 0; i < value?.length; i++) {
64
+ for (const k in value[i]) {
65
+ await applyFieldRules(field.children.__dict, value[i], value[i][k], [...path, i.toString(), k]);
66
+ }
71
67
  }
72
68
  }
73
- // 3. Run parse method
74
- try {
75
- parsedValue = await (0, message_template_parser_1.MessageTemplateFieldParser)(raw, trx, field, value, parseFields);
76
- }
77
- catch (e) {
78
- // If this error was not triggered by a nested field,
79
- // and we have another option, we try that option.
80
- if (field.or && !e.__msg_deep_error) {
81
- return parseField(trx, field.or, value);
69
+ else {
70
+ for (const k in value) {
71
+ await applyFieldRules(field.children.__dict, value, value[k], [...path, k]);
82
72
  }
83
- e.__msg_deep_error = true;
84
- throw e;
85
73
  }
86
74
  }
87
- return parsedValue;
88
75
  };
89
- const applyRules = async (fields, parsed, parsedValue = parsed) => {
76
+ const applyRules = async (fields, parent, path = []) => {
90
77
  for (const f in fields) {
91
78
  const field = fields[f];
92
- for (const r in field.rules) {
93
- const rule = field.rules[r];
94
- const value = parsedValue?.[field.name];
95
- const res = await rule({ field, value, msg: parsed });
96
- if (typeof res === 'object') {
97
- parsedValue ?? (parsedValue = {});
98
- parsedValue[field.name] = res.set;
99
- }
100
- else if (res !== true) {
101
- throw error_1.NesoiError.Message.RuleFailed({ rule, error: res });
102
- }
103
- }
104
- if (field.children) {
105
- await applyRules(field.children, parsed, parsedValue?.[field.name]);
106
- }
79
+ const value = parent[field.name];
80
+ const _path = [...path, field.name];
81
+ await applyFieldRules(field, parent, value, _path);
107
82
  }
108
83
  };
109
- const parsed = await parseFields(trx, this.schema.template.fields, raw);
84
+ const fields = this.schema.template.fields;
85
+ const parsed = {};
86
+ for (const k in fields) {
87
+ const field = fields[k];
88
+ const key_raw = field.path_raw.split('.')[0];
89
+ const key_parsed = field.path_parsed.split('.')[0];
90
+ const value = raw[key_raw];
91
+ this.sanitize(value);
92
+ parsed[key_parsed] = await (0, message_template_parser_1.MessageTemplateFieldParser)(raw, trx, field, value);
93
+ }
110
94
  await applyRules(this.schema.template.fields, parsed);
111
95
  return message_1.Message.new(this.schema.name, parsed, sigKey);
112
96
  }
@@ -117,23 +101,5 @@ class MessageParser {
117
101
  });
118
102
  }
119
103
  }
120
- /**
121
- * Empty values: `{}`, `[]`, `''`, `null`, `undefined`
122
- */
123
- static isEmpty(value) {
124
- if (value === null || value === undefined) {
125
- return true;
126
- }
127
- if (Array.isArray(value)) {
128
- return value.length === 0;
129
- }
130
- if (typeof value === 'object') {
131
- return Object.keys(value).length === 0;
132
- }
133
- if (typeof value === 'string') {
134
- return value.length === 0;
135
- }
136
- return false;
137
- }
138
104
  }
139
105
  exports.MessageParser = MessageParser;
@@ -3,6 +3,7 @@ import { $BucketModelFieldType } from "../../bucket/model/bucket_model.schema";
3
3
  import { $Dependency } from "../../../../engine/dependency";
4
4
  export type $MessageTemplateRule = (def: {
5
5
  field: $MessageTemplateField;
6
+ path: string;
6
7
  value: any;
7
8
  msg: $Message['#raw'];
8
9
  }) => {
@@ -36,10 +37,19 @@ export type $MessageTemplateFieldType = $BucketModelFieldType | 'string_or_numbe
36
37
  * @subcategory Entity
37
38
  * */
38
39
  export declare class $MessageTemplateField {
40
+ /** A string representing the type of data carried by the field */
39
41
  type: $MessageTemplateFieldType;
42
+ /**
43
+ * - A machine name for the field, unique inside it's parent (either another field or a message).
44
+ * - Matches the relative path for writing the field value on the parent parsed object (key_parsed).
45
+ */
40
46
  name: string;
47
+ /** A human name for the field */
41
48
  alias: string;
42
- path: string;
49
+ /** The absolute path for reading the field value on the raw object */
50
+ path_raw: string;
51
+ /** The absolute path for writing the field value on the parsed object */
52
+ path_parsed: string;
43
53
  array: boolean;
44
54
  required: boolean;
45
55
  defaultValue: any;
@@ -51,7 +61,20 @@ export declare class $MessageTemplateField {
51
61
  '#raw': unknown;
52
62
  '#parsed': unknown;
53
63
  $t: string;
54
- constructor(type: $MessageTemplateFieldType, name: string, alias: string, path: string, array: boolean, required: boolean, defaultValue: any, nullable: boolean, rules: $MessageTemplateRule[], meta: $MessageTemplateFieldMeta, children?: $MessageTemplateFields | undefined, or?: $MessageTemplateField | undefined);
64
+ constructor(
65
+ /** A string representing the type of data carried by the field */
66
+ type: $MessageTemplateFieldType,
67
+ /**
68
+ * - A machine name for the field, unique inside it's parent (either another field or a message).
69
+ * - Matches the relative path for writing the field value on the parent parsed object (key_parsed).
70
+ */
71
+ name: string,
72
+ /** A human name for the field */
73
+ alias: string,
74
+ /** The absolute path for reading the field value on the raw object */
75
+ path_raw: string,
76
+ /** The absolute path for writing the field value on the parsed object */
77
+ path_parsed: string, array: boolean, required: boolean, defaultValue: any, nullable: boolean, rules: $MessageTemplateRule[], meta: $MessageTemplateFieldMeta, children?: $MessageTemplateFields | undefined, or?: $MessageTemplateField | undefined);
55
78
  }
56
79
  export type $MessageTemplateFields = {
57
80
  [x: string]: $MessageTemplateField;
@@ -6,11 +6,25 @@ exports.$MessageTemplate = exports.$MessageTemplateField = void 0;
6
6
  * @subcategory Entity
7
7
  * */
8
8
  class $MessageTemplateField {
9
- constructor(type, name, alias, path, array, required, defaultValue, nullable, rules, meta, children, or) {
9
+ constructor(
10
+ /** A string representing the type of data carried by the field */
11
+ type,
12
+ /**
13
+ * - A machine name for the field, unique inside it's parent (either another field or a message).
14
+ * - Matches the relative path for writing the field value on the parent parsed object (key_parsed).
15
+ */
16
+ name,
17
+ /** A human name for the field */
18
+ alias,
19
+ /** The absolute path for reading the field value on the raw object */
20
+ path_raw,
21
+ /** The absolute path for writing the field value on the parsed object */
22
+ path_parsed, array, required, defaultValue, nullable, rules, meta, children, or) {
10
23
  this.type = type;
11
24
  this.name = name;
12
25
  this.alias = alias;
13
- this.path = path;
26
+ this.path_raw = path_raw;
27
+ this.path_parsed = path_parsed;
14
28
  this.array = array;
15
29
  this.required = required;
16
30
  this.defaultValue = defaultValue;