@asteby/metacore-runtime-react 32.0.0 → 33.0.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.
@@ -10,17 +10,36 @@
10
10
  // or report it. This module keeps the headline but ALSO surfaces the cause as
11
11
  // the toast description, in ONE place so every call site behaves identically.
12
12
  import { toast } from 'sonner';
13
+ import { validationCatalog, validationMessageKey } from './validation-catalog';
14
+ function formatIssueEntry(v) {
15
+ if (v == null)
16
+ return '';
17
+ if (typeof v === 'string')
18
+ return v;
19
+ if (typeof v === 'object' && 'code' in v) {
20
+ const e = v;
21
+ if (typeof e.message === 'string' && e.message.trim())
22
+ return e.message.trim();
23
+ if (typeof e.code === 'string' && e.code)
24
+ return e.code;
25
+ }
26
+ return String(v);
27
+ }
13
28
  /** Flattens a validation `errors` payload (string | string[] | field→msgs map)
14
- * into a single newline-joined string, or undefined when empty. */
29
+ * into a single newline-joined string, or undefined when empty. Object entries
30
+ * `{code, params}` render as the code (never `[object Object]`). */
15
31
  function joinErrors(errors) {
16
32
  if (!errors)
17
33
  return undefined;
18
34
  if (typeof errors === 'string')
19
35
  return errors || undefined;
20
36
  if (Array.isArray(errors))
21
- return errors.filter(Boolean).map(String).join('\n') || undefined;
37
+ return errors.map(formatIssueEntry).filter(Boolean).join('\n') || undefined;
22
38
  if (typeof errors === 'object') {
23
- const parts = Object.entries(errors).map(([k, v]) => `${k}: ${Array.isArray(v) ? v.join(', ') : String(v)}`);
39
+ const parts = Object.entries(errors).map(([k, v]) => {
40
+ const body = Array.isArray(v) ? v.map(formatIssueEntry).filter(Boolean).join(', ') : formatIssueEntry(v);
41
+ return body ? `${k}: ${body}` : '';
42
+ }).filter(Boolean);
24
43
  return parts.join('\n') || undefined;
25
44
  }
26
45
  return undefined;
@@ -59,17 +78,12 @@ export function extractServerError(err, fallbackTitle) {
59
78
  return { title: fallbackTitle, description: raw.trim() };
60
79
  return { title: fallbackTitle };
61
80
  }
62
- /** Spanish defaults per known validation code. `{{label}}` (and code params like
63
- * `allowed`/`ref`/`expected`) are interpolated by i18next, so a host can override
64
- * any of these via its addon i18n bundle under `validation.<code>`. */
65
- const VALIDATION_DEFAULTS = {
66
- required: 'El campo {{label}} es obligatorio',
67
- invalid_option: 'El valor de {{label}} no es válido',
68
- not_found: 'El {{label}} seleccionado no existe',
69
- duplicate: 'Ya existe un registro con ese {{label}}',
70
- invalid_type: 'El campo {{label}} tiene un formato inválido',
71
- };
72
- const VALIDATION_FALLBACK = '{{label}}: valor inválido';
81
+ /** Spanish/English catalogs live in `validation-catalog.ts`. Hosts override any
82
+ * key via i18next `validation.<code>`. `{{label}}` and code params (min/max/
83
+ * allowed/ref/expected) interpolate through i18next. */
84
+ function humanizeKey(k) {
85
+ return k.replace(/[._-]+/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
86
+ }
73
87
  /** Normalize one raw `errors` value entry into a `FieldIssue`.
74
88
  * A string → `{message}` (pre-localized, shown verbatim); an object → `{code,params}`. */
75
89
  function toFieldIssue(entry) {
@@ -113,17 +127,28 @@ export function extractFieldErrors(err) {
113
127
  return Object.keys(out).length ? out : undefined;
114
128
  }
115
129
  /**
116
- * Localize a single `FieldIssue` to a human, Spanish-by-default string using the
117
- * field `label`. A pre-localized `message` passes through verbatim. Otherwise the
118
- * `code` is translated via `t('validation.'+code, { defaultValue, label, ...params })`
119
- * so hosts can override the copy and `{{label}}`/param interpolation still works.
130
+ * Localize a single `FieldIssue` to a human string using the field `label` and
131
+ * the operator's language. A pre-localized `message` passes through verbatim.
132
+ * Otherwise `code` is translated via `t('validation.'+key)` with a catalog
133
+ * default (es unless `language` is `en` / `en-*`).
120
134
  */
121
- export function localizeFieldIssue(issue, label, t) {
135
+ export function localizeFieldIssue(issue, label, t, language) {
122
136
  if (issue.message)
123
137
  return issue.message;
124
- const code = issue.code ?? '';
125
- const defaultValue = VALIDATION_DEFAULTS[code] ?? VALIDATION_FALLBACK;
126
- return t(`validation.${code}`, { defaultValue, label, ...(issue.params ?? {}) });
138
+ const key = validationMessageKey(issue.code ?? '', issue.params);
139
+ const cat = validationCatalog(language);
140
+ const defaultValue = cat[key] ?? cat.fallback ?? '{{label}}: valor inválido';
141
+ return t(`validation.${key}`, { defaultValue, label, ...(issue.params ?? {}) });
142
+ }
143
+ /** Localize a whole 422 `errors` map into `{ [field]: firstMessage }` using
144
+ * optional per-key labels (already translated) and the current language. */
145
+ export function localizeFieldErrorMap(map, t, opts) {
146
+ const out = {};
147
+ for (const [k, issues] of Object.entries(map)) {
148
+ const label = opts?.labels?.[k] ?? humanizeKey(k);
149
+ out[k] = localizeFieldIssue(issues[0], label, t, opts?.language);
150
+ }
151
+ return out;
127
152
  }
128
153
  /** A dotted, space-free token (e.g. "pos.rate.created") — the shape of an i18n
129
154
  * key, as opposed to human prose ("Record created successfully"). Used to
@@ -153,14 +178,36 @@ export function toastServerSuccess(data, opts) {
153
178
  }
154
179
  /**
155
180
  * Toast a server/network error, surfacing the REAL cause as the description
156
- * instead of a bare generic line. Pass the app's `t` so an i18n-key `message`
157
- * (e.g. "pos.error.no_rate") is localized; a plain-text message passes through
158
- * unchanged. Use everywhere a mutation/action can fail.
181
+ * instead of a bare generic line. A 422 `{errors:{field:[{code}]}}` bag is
182
+ * localized per-field (never `[object Object]` / English "validation failed").
183
+ * Pass `language` (i18n.language) so catalogs match the operator's lang;
184
+ * pass `labels` so field keys map to translated headers.
159
185
  */
160
186
  export function toastServerError(err, opts) {
161
187
  const t = opts?.t;
188
+ const lang = opts?.language;
189
+ const cat = validationCatalog(lang);
190
+ const map = extractFieldErrors(err);
191
+ if (map) {
192
+ const localized = t
193
+ ? localizeFieldErrorMap(map, t, { labels: opts?.labels, language: lang })
194
+ : undefined;
195
+ const title = t
196
+ ? t('validation.failed', { defaultValue: cat.failed })
197
+ : cat.failed;
198
+ const description = localized
199
+ ? Object.values(localized).join('\n')
200
+ : Object.entries(map)
201
+ .map(([k, issues]) => `${k}: ${issues[0]?.code ?? issues[0]?.message ?? ''}`)
202
+ .join('\n');
203
+ toast.error(title, description ? { description } : undefined);
204
+ return;
205
+ }
162
206
  const fallback = opts?.fallback ?? (t ? t('common.error', { defaultValue: 'Something went wrong' }) : 'Something went wrong');
163
- const { title, description } = extractServerError(err, fallback);
164
- const shownTitle = t ? t(title, { defaultValue: title }) : title;
165
- toast.error(shownTitle, description ? { description } : undefined);
207
+ const extracted = extractServerError(err, fallback);
208
+ let shownTitle = t ? t(extracted.title, { defaultValue: extracted.title }) : extracted.title;
209
+ if (extracted.title === 'validation failed' || extracted.title === 'validation.failed') {
210
+ shownTitle = t ? t('validation.failed', { defaultValue: cat.failed }) : cat.failed;
211
+ }
212
+ toast.error(shownTitle, extracted.description ? { description: extracted.description } : undefined);
166
213
  }
package/dist/types.d.ts CHANGED
@@ -291,11 +291,10 @@ export interface ColumnDefinition {
291
291
  */
292
292
  ref?: string;
293
293
  /**
294
- * Server-side validation rules the SDK can also pre-flight in the
295
- * form layer. `custom` may be a literal slug or a $org.<key>
296
- * reference resolved through the OrgConfigProvider.
294
+ * Write-time rules the SDK also pre-flights. Object form `{regex,min,max,custom}`
295
+ * or a Laravel / go-playground string (`required|min:2|email`).
297
296
  */
298
- validation?: FieldValidation;
297
+ validation?: FieldValidation | string;
299
298
  /**
300
299
  * Declared schema for a jsonb line-items column (kernel v3 `item_fields`).
301
300
  * Each entry describes one sub-field of the array's row objects: a `key`
@@ -415,7 +414,7 @@ export interface ActionFieldDef {
415
414
  defaultValue?: any;
416
415
  placeholder?: string;
417
416
  searchEndpoint?: string;
418
- validation?: FieldValidation;
417
+ validation?: FieldValidation | string;
419
418
  widget?: FieldWidget | string;
420
419
  /**
421
420
  * FK target model — same semantics as ColumnDefinition.ref. When
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /** Laravel-style validation catalogs. Hosts override any key via i18next
2
+ * `validation.<code>`; these are the defaults when the key is missing, picked
3
+ * by the operator's language (es by default — the product language). */
4
+ export declare const VALIDATION_CATALOGS: Record<string, Record<string, string>>;
5
+ export declare function validationCatalog(language?: string): Record<string, string>;
6
+ /** Pick the catalog key for a code, folding min/max + kind=length into *_length. */
7
+ export declare function validationMessageKey(code: string, params?: Record<string, unknown>): string;
8
+ //# sourceMappingURL=validation-catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation-catalog.d.ts","sourceRoot":"","sources":["../src/validation-catalog.ts"],"names":[],"mappings":"AAAA;;yEAEyE;AAEzE,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA2CtE,CAAA;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAG3E;AAED,oFAAoF;AACpF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAI3F"}
@@ -0,0 +1,59 @@
1
+ /** Laravel-style validation catalogs. Hosts override any key via i18next
2
+ * `validation.<code>`; these are the defaults when the key is missing, picked
3
+ * by the operator's language (es by default — the product language). */
4
+ export const VALIDATION_CATALOGS = {
5
+ es: {
6
+ failed: 'Revisa los campos marcados',
7
+ required: 'El campo {{label}} es obligatorio',
8
+ invalid_option: 'El valor de {{label}} no es válido',
9
+ not_found: 'El {{label}} seleccionado no existe',
10
+ duplicate: 'Ya existe un registro con ese {{label}}',
11
+ invalid_type: 'El campo {{label}} tiene un formato inválido',
12
+ min: 'El campo {{label}} debe ser al menos {{min}}',
13
+ min_length: '{{label}} debe tener al menos {{min}} caracteres',
14
+ max: 'El campo {{label}} no puede ser mayor que {{max}}',
15
+ max_length: '{{label}} no puede tener más de {{max}} caracteres',
16
+ regex: 'El formato de {{label}} no es válido',
17
+ email: '{{label}} debe ser un correo válido',
18
+ uuid: '{{label}} no es un identificador válido',
19
+ url: '{{label}} debe ser una URL válida',
20
+ numeric: '{{label}} debe ser un número',
21
+ integer: '{{label}} debe ser un entero',
22
+ custom: '{{label}} no es válido',
23
+ line_items_required: '{{label}} requiere al menos un renglón',
24
+ fallback: '{{label}}: valor inválido',
25
+ },
26
+ en: {
27
+ failed: 'Please check the highlighted fields',
28
+ required: 'The {{label}} field is required',
29
+ invalid_option: 'The selected {{label}} is invalid',
30
+ not_found: 'The selected {{label}} does not exist',
31
+ duplicate: 'A record with that {{label}} already exists',
32
+ invalid_type: 'The {{label}} field has an invalid format',
33
+ min: 'The {{label}} must be at least {{min}}',
34
+ min_length: 'The {{label}} must be at least {{min}} characters',
35
+ max: 'The {{label}} may not be greater than {{max}}',
36
+ max_length: 'The {{label}} may not be greater than {{max}} characters',
37
+ regex: 'The {{label}} format is invalid',
38
+ email: 'The {{label}} must be a valid email address',
39
+ uuid: 'The {{label}} is not a valid identifier',
40
+ url: 'The {{label}} must be a valid URL',
41
+ numeric: 'The {{label}} must be a number',
42
+ integer: 'The {{label}} must be an integer',
43
+ custom: 'The {{label}} is invalid',
44
+ line_items_required: '{{label}} requires at least one row',
45
+ fallback: '{{label}}: invalid value',
46
+ },
47
+ };
48
+ export function validationCatalog(language) {
49
+ const short = (language ?? 'es').split(/[-_]/)[0].toLowerCase();
50
+ return VALIDATION_CATALOGS[short] ?? VALIDATION_CATALOGS.es;
51
+ }
52
+ /** Pick the catalog key for a code, folding min/max + kind=length into *_length. */
53
+ export function validationMessageKey(code, params) {
54
+ if (code === 'min' && params?.kind === 'length')
55
+ return 'min_length';
56
+ if (code === 'max' && params?.kind === 'length')
57
+ return 'max_length';
58
+ return code;
59
+ }
@@ -0,0 +1,22 @@
1
+ import type { ActionFieldDef, FieldValidation } from './types';
2
+ import type { FieldIssue } from './server-error';
3
+ export interface ValidationSpec {
4
+ required?: boolean;
5
+ type?: string;
6
+ regex?: string;
7
+ min?: number;
8
+ max?: number;
9
+ custom?: string;
10
+ options?: string[];
11
+ }
12
+ /** Parse `required|min:2|email` or `required,min=2,max=100` or a custom slug. */
13
+ export declare function parseRuleString(s: string): ValidationSpec;
14
+ /** Normalize ActionFieldDef.validation (object, laravel string, or `rules`). */
15
+ export declare function fieldValidationOf(field: ActionFieldDef | Record<string, unknown>): FieldValidation;
16
+ /** Evaluate spec against one value; collect every issue (not fail-fast). */
17
+ export declare function checkValue(value: unknown, spec: ValidationSpec): FieldIssue[];
18
+ /** Validate a form payload the way Laravel's Validator does: collect every
19
+ * field issue, dotted keys for line-items (`items.0.qty`). */
20
+ export declare function validateValues(fields: readonly ActionFieldDef[], values: Record<string, unknown>): Record<string, FieldIssue[]>;
21
+ export declare function bagHasErrors(bag: Record<string, FieldIssue[]>): boolean;
22
+ //# sourceMappingURL=validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAC9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAKhD,MAAM,WAAW,cAAc;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CACrB;AAQD,iFAAiF;AACjF,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,cAAc,CAyCzD;AAqCD,gFAAgF;AAChF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,eAAe,CAUlG;AAiCD,4EAA4E;AAC5E,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,GAAG,UAAU,EAAE,CAmC7E;AAgDD;+DAC+D;AAC/D,wBAAgB,cAAc,CAC1B,MAAM,EAAE,SAAS,cAAc,EAAE,EACjC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,CAI9B;AA8BD,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,GAAG,OAAO,CAEvE"}
@@ -0,0 +1,261 @@
1
+ const NIL_UUID = '00000000-0000-0000-0000-000000000000';
2
+ const NUMERIC_TYPES = new Set(['int', 'integer', 'bigint', 'decimal', 'numeric', 'number', 'float', 'double']);
3
+ const RULE_NAMES = new Set([
4
+ 'required', 'nullable', 'sometimes', 'present',
5
+ 'min', 'max', 'regex', 'email', 'uuid', 'url',
6
+ 'numeric', 'integer', 'int', 'in',
7
+ ]);
8
+ /** Parse `required|min:2|email` or `required,min=2,max=100` or a custom slug. */
9
+ export function parseRuleString(s) {
10
+ const spec = {};
11
+ const trimmed = s.trim();
12
+ if (!trimmed)
13
+ return spec;
14
+ for (const part of splitRules(trimmed)) {
15
+ const { name, param } = splitNameParam(part);
16
+ switch (name.toLowerCase()) {
17
+ case 'required':
18
+ spec.required = true;
19
+ break;
20
+ case 'min': {
21
+ const n = Number(param);
22
+ if (!Number.isNaN(n))
23
+ spec.min = n;
24
+ break;
25
+ }
26
+ case 'max': {
27
+ const n = Number(param);
28
+ if (!Number.isNaN(n))
29
+ spec.max = n;
30
+ break;
31
+ }
32
+ case 'regex':
33
+ spec.regex = trimLaravelRegex(param);
34
+ break;
35
+ case 'email':
36
+ case 'uuid':
37
+ case 'url':
38
+ case 'numeric':
39
+ case 'integer':
40
+ spec.custom = name.toLowerCase();
41
+ break;
42
+ case 'int':
43
+ spec.custom = 'integer';
44
+ break;
45
+ case 'in':
46
+ spec.options = param.split(',').map(x => x.trim()).filter(Boolean);
47
+ break;
48
+ default:
49
+ if (!spec.custom)
50
+ spec.custom = part;
51
+ }
52
+ }
53
+ return spec;
54
+ }
55
+ function splitRules(s) {
56
+ if (s.includes('|'))
57
+ return s.split('|').map(x => x.trim()).filter(Boolean);
58
+ const raw = s.split(',');
59
+ const out = [];
60
+ for (const p of raw) {
61
+ const part = p.trim();
62
+ if (!part)
63
+ continue;
64
+ const { name } = splitNameParam(part);
65
+ if (!RULE_NAMES.has(name.toLowerCase()) && out.length) {
66
+ const prev = splitNameParam(out[out.length - 1]).name;
67
+ if (prev.toLowerCase() === 'in') {
68
+ out[out.length - 1] += `,${part}`;
69
+ continue;
70
+ }
71
+ }
72
+ out.push(part);
73
+ }
74
+ return out;
75
+ }
76
+ function splitNameParam(p) {
77
+ const colon = p.indexOf(':');
78
+ const eq = p.indexOf('=');
79
+ const i = colon >= 0 && (eq < 0 || colon < eq) ? colon : eq;
80
+ if (i < 0)
81
+ return { name: p.trim(), param: '' };
82
+ return { name: p.slice(0, i).trim(), param: p.slice(i + 1).trim() };
83
+ }
84
+ function trimLaravelRegex(p) {
85
+ if (p.length >= 2 && p.startsWith('/') && p.lastIndexOf('/') > 0) {
86
+ return p.slice(1, p.lastIndexOf('/'));
87
+ }
88
+ return p;
89
+ }
90
+ /** Normalize ActionFieldDef.validation (object, laravel string, or `rules`). */
91
+ export function fieldValidationOf(field) {
92
+ const rec = field;
93
+ const raw = rec.validation ?? rec.rules ?? rec.validation_rule;
94
+ if (!raw)
95
+ return {};
96
+ if (typeof raw === 'string') {
97
+ const s = parseRuleString(raw);
98
+ return { regex: s.regex, min: s.min, max: s.max, custom: s.custom };
99
+ }
100
+ if (typeof raw === 'object' && !Array.isArray(raw))
101
+ return raw;
102
+ return {};
103
+ }
104
+ function isEmpty(raw) {
105
+ if (raw == null)
106
+ return true;
107
+ if (typeof raw === 'string') {
108
+ const t = raw.trim();
109
+ return t === '' || t === NIL_UUID;
110
+ }
111
+ if (Array.isArray(raw))
112
+ return raw.length === 0;
113
+ return false;
114
+ }
115
+ function asString(raw) {
116
+ if (raw == null)
117
+ return '';
118
+ return String(raw).trim();
119
+ }
120
+ function isNumeric(raw) {
121
+ if (typeof raw === 'number' && Number.isFinite(raw))
122
+ return true;
123
+ if (typeof raw === 'string')
124
+ return raw.trim() !== '' && !Number.isNaN(Number(raw));
125
+ return false;
126
+ }
127
+ function numericValue(raw) {
128
+ return typeof raw === 'number' ? raw : Number(asString(raw));
129
+ }
130
+ function lengthOf(raw) {
131
+ if (typeof raw === 'string')
132
+ return [...raw.trim()].length;
133
+ if (Array.isArray(raw))
134
+ return raw.length;
135
+ return [...asString(raw)].length;
136
+ }
137
+ /** Evaluate spec against one value; collect every issue (not fail-fast). */
138
+ export function checkValue(value, spec) {
139
+ const empty = isEmpty(value);
140
+ if (spec.required && empty)
141
+ return [{ code: 'required' }];
142
+ if (empty)
143
+ return [];
144
+ const out = [];
145
+ const typ = (spec.type ?? '').toLowerCase();
146
+ if (NUMERIC_TYPES.has(typ) && !isNumeric(value)) {
147
+ out.push({ code: 'invalid_type', params: { expected: 'number' } });
148
+ return out;
149
+ }
150
+ if (spec.options && spec.options.length) {
151
+ const want = asString(value);
152
+ if (!spec.options.includes(want)) {
153
+ out.push({ code: 'invalid_option', params: { allowed: spec.options } });
154
+ }
155
+ }
156
+ if (spec.regex) {
157
+ try {
158
+ if (!new RegExp(spec.regex).test(asString(value))) {
159
+ out.push({ code: 'regex', params: { pattern: spec.regex } });
160
+ }
161
+ }
162
+ catch { /* malformed — skip */ }
163
+ }
164
+ if (spec.min != null || spec.max != null) {
165
+ const isNum = NUMERIC_TYPES.has(typ);
166
+ const kind = isNum ? 'value' : 'length';
167
+ const n = isNum ? numericValue(value) : lengthOf(value);
168
+ if (spec.min != null && n < spec.min)
169
+ out.push({ code: 'min', params: { min: spec.min, kind } });
170
+ if (spec.max != null && n > spec.max)
171
+ out.push({ code: 'max', params: { max: spec.max, kind } });
172
+ }
173
+ if (spec.custom) {
174
+ const custom = checkBuiltin(spec.custom, value);
175
+ if (custom)
176
+ out.push(custom);
177
+ }
178
+ return out;
179
+ }
180
+ function checkBuiltin(slug, value) {
181
+ const s = asString(value);
182
+ switch (slug) {
183
+ case 'email':
184
+ return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(s) ? undefined : { code: 'email' };
185
+ case 'uuid':
186
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(s)
187
+ ? undefined : { code: 'uuid' };
188
+ case 'url':
189
+ try {
190
+ const u = new URL(s);
191
+ return u.protocol && u.host ? undefined : { code: 'url' };
192
+ }
193
+ catch {
194
+ return { code: 'url' };
195
+ }
196
+ case 'numeric':
197
+ return isNumeric(value) ? undefined : { code: 'numeric', params: { expected: 'number' } };
198
+ case 'integer':
199
+ case 'int':
200
+ return /^-?\d+$/.test(s) || (typeof value === 'number' && Number.isInteger(value))
201
+ ? undefined : { code: 'integer', params: { expected: 'integer' } };
202
+ default:
203
+ return undefined;
204
+ }
205
+ }
206
+ function specFromField(field) {
207
+ const v = fieldValidationOf(field);
208
+ const spec = {
209
+ required: !!field.required,
210
+ type: field.type,
211
+ regex: v.regex,
212
+ min: v.min,
213
+ max: v.max,
214
+ custom: v.custom,
215
+ };
216
+ if (field.options?.length)
217
+ spec.options = field.options.map(o => String(o.value));
218
+ return spec;
219
+ }
220
+ function isLineItems(field) {
221
+ const raw = field.itemFields ?? field.item_fields;
222
+ return Array.isArray(raw) && raw.length > 0;
223
+ }
224
+ function itemFieldsOf(field) {
225
+ const raw = field.itemFields ?? field.item_fields;
226
+ return Array.isArray(raw) ? raw : [];
227
+ }
228
+ /** Validate a form payload the way Laravel's Validator does: collect every
229
+ * field issue, dotted keys for line-items (`items.0.qty`). */
230
+ export function validateValues(fields, values) {
231
+ const bag = {};
232
+ walk(fields, values ?? {}, '', bag);
233
+ return bag;
234
+ }
235
+ function walk(fields, values, prefix, bag) {
236
+ for (const field of fields) {
237
+ const key = field.key;
238
+ if (!key)
239
+ continue;
240
+ const path = prefix ? `${prefix}.${key}` : key;
241
+ const raw = values[key];
242
+ if (isLineItems(field)) {
243
+ const rows = Array.isArray(raw) ? raw : [];
244
+ if (field.required && rows.length === 0) {
245
+ bag[path] = [{ code: 'line_items_required' }];
246
+ continue;
247
+ }
248
+ rows.forEach((row, i) => {
249
+ const obj = row && typeof row === 'object' ? row : {};
250
+ walk(itemFieldsOf(field), obj, `${path}.${i}`, bag);
251
+ });
252
+ continue;
253
+ }
254
+ const issues = checkValue(raw, specFromField(field));
255
+ if (issues.length)
256
+ bag[path] = issues;
257
+ }
258
+ }
259
+ export function bagHasErrors(bag) {
260
+ return Object.keys(bag).length > 0;
261
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asteby/metacore-runtime-react",
3
- "version": "32.0.0",
3
+ "version": "33.0.0",
4
4
  "description": "React runtime for metacore hosts — renders addon contributions dynamically",
5
5
  "repository": {
6
6
  "type": "git",
@@ -37,7 +37,7 @@
37
37
  "react-i18next": ">=13",
38
38
  "sonner": ">=1.7",
39
39
  "zustand": ">=5",
40
- "@asteby/metacore-sdk": "^3.5.0",
40
+ "@asteby/metacore-sdk": "^3.6.0",
41
41
  "@asteby/metacore-ui": "^2.15.0"
42
42
  },
43
43
  "peerDependenciesMeta": {
@@ -67,7 +67,7 @@
67
67
  "typescript": "^6.0.0",
68
68
  "vitest": "^4.0.0",
69
69
  "zustand": "^5.0.0",
70
- "@asteby/metacore-sdk": "3.5.0",
70
+ "@asteby/metacore-sdk": "3.6.0",
71
71
  "@asteby/metacore-ui": "2.15.0"
72
72
  },
73
73
  "scripts": {
@@ -1,5 +1,5 @@
1
1
  import { describe, it, expect } from 'vitest'
2
- import { extractFieldErrors, localizeFieldIssue, type FieldIssue } from '../server-error'
2
+ import { extractFieldErrors, localizeFieldIssue, extractServerError, type FieldIssue } from '../server-error'
3
3
 
4
4
  // A minimal i18next-like translator: honors defaultValue and does {{var}}
5
5
  // interpolation, so the tests assert BOTH the resolved Spanish default and that
@@ -70,6 +70,22 @@ describe('extractFieldErrors', () => {
70
70
  })
71
71
  })
72
72
 
73
+ describe('extractServerError', () => {
74
+ it('does not stringify field-error objects as [object Object]', () => {
75
+ const { title, description } = extractServerError(
76
+ {
77
+ success: false,
78
+ message: 'validation failed',
79
+ errors: { sku: [{ code: 'required', params: {} }] },
80
+ },
81
+ 'fallback',
82
+ )
83
+ expect(title).toBe('validation failed')
84
+ expect(description).toBe('sku: required')
85
+ expect(description).not.toContain('[object Object]')
86
+ })
87
+ })
88
+
73
89
  describe('localizeFieldIssue', () => {
74
90
  it('required → interpolates label', () => {
75
91
  expect(localizeFieldIssue({ code: 'required' }, 'Nombre', t)).toBe('El campo Nombre es obligatorio')
@@ -95,6 +111,14 @@ describe('localizeFieldIssue', () => {
95
111
  it('unknown code → generic fallback with label', () => {
96
112
  expect(localizeFieldIssue({ code: 'weird_code' }, 'Campo', t)).toBe('Campo: valor inválido')
97
113
  })
114
+ it('min + kind=length uses min_length catalog', () => {
115
+ expect(localizeFieldIssue({ code: 'min', params: { min: 3, kind: 'length' } }, 'SKU', t)).toBe(
116
+ 'SKU debe tener al menos 3 caracteres',
117
+ )
118
+ })
119
+ it('en catalog when language is en', () => {
120
+ expect(localizeFieldIssue({ code: 'required' }, 'Name', t, 'en')).toBe('The Name field is required')
121
+ })
98
122
  it('message passthrough (pre-localized) ignores code/label', () => {
99
123
  const issue: FieldIssue = { message: 'Texto ya localizado' }
100
124
  expect(localizeFieldIssue(issue, 'Ignorado', t)).toBe('Texto ya localizado')