@asteby/metacore-runtime-react 25.1.3 → 25.1.5

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.
@@ -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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asteby/metacore-runtime-react",
3
- "version": "25.1.3",
3
+ "version": "25.1.5",
4
4
  "description": "React runtime for metacore hosts — renders addon contributions dynamically",
5
5
  "repository": {
6
6
  "type": "git",
@@ -67,8 +67,8 @@
67
67
  "typescript": "^6.0.0",
68
68
  "vitest": "^4.0.0",
69
69
  "zustand": "^5.0.0",
70
- "@asteby/metacore-ui": "2.10.1",
71
- "@asteby/metacore-sdk": "3.3.0"
70
+ "@asteby/metacore-sdk": "3.3.0",
71
+ "@asteby/metacore-ui": "2.10.1"
72
72
  },
73
73
  "scripts": {
74
74
  "build": "tsc -p tsconfig.json",
@@ -0,0 +1,102 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { extractFieldErrors, localizeFieldIssue, type FieldIssue } from '../server-error'
3
+
4
+ // A minimal i18next-like translator: honors defaultValue and does {{var}}
5
+ // interpolation, so the tests assert BOTH the resolved Spanish default and that
6
+ // the field label / code params are interpolated.
7
+ const t = (_key: string, opts?: { defaultValue?: string; [k: string]: unknown }) => {
8
+ let out = opts?.defaultValue ?? _key
9
+ if (opts) {
10
+ for (const [k, v] of Object.entries(opts)) {
11
+ if (k === 'defaultValue') continue
12
+ out = out.replace(new RegExp(`{{\\s*${k}\\s*}}`, 'g'), String(v))
13
+ }
14
+ }
15
+ return out
16
+ }
17
+
18
+ describe('extractFieldErrors', () => {
19
+ it('normalizes object entries {code,params} from an axios error', () => {
20
+ const err = {
21
+ response: {
22
+ data: {
23
+ success: false,
24
+ message: 'validation failed',
25
+ errors: { name: [{ code: 'required', params: {} }], sku: [{ code: 'duplicate' }] },
26
+ },
27
+ },
28
+ }
29
+ expect(extractFieldErrors(err)).toEqual({
30
+ name: [{ code: 'required', params: {} }],
31
+ sku: [{ code: 'duplicate', params: undefined }],
32
+ })
33
+ })
34
+
35
+ it('normalizes string entries to {message}', () => {
36
+ const err = { errors: { name: ['El nombre es obligatorio'], sku: 'Duplicado' } }
37
+ expect(extractFieldErrors(err)).toEqual({
38
+ name: [{ message: 'El nombre es obligatorio' }],
39
+ sku: [{ message: 'Duplicado' }],
40
+ })
41
+ })
42
+
43
+ it('accepts a bare response body as well as an axios error', () => {
44
+ const bare = { errors: { qty: [{ code: 'invalid_type', params: { expected: 'number' } }] } }
45
+ expect(extractFieldErrors(bare)).toEqual({
46
+ qty: [{ code: 'invalid_type', params: { expected: 'number' } }],
47
+ })
48
+ })
49
+
50
+ it('carries code params through (allowed / ref)', () => {
51
+ const err = {
52
+ errors: {
53
+ status: [{ code: 'invalid_option', params: { allowed: ['a', 'b'] } }],
54
+ owner: [{ code: 'not_found', params: { ref: 'users' } }],
55
+ },
56
+ }
57
+ expect(extractFieldErrors(err)).toEqual({
58
+ status: [{ code: 'invalid_option', params: { allowed: ['a', 'b'] } }],
59
+ owner: [{ code: 'not_found', params: { ref: 'users' } }],
60
+ })
61
+ })
62
+
63
+ it('returns undefined when there is no usable errors map', () => {
64
+ expect(extractFieldErrors(undefined)).toBeUndefined()
65
+ expect(extractFieldErrors({ response: { data: { message: 'boom' } } })).toBeUndefined()
66
+ expect(extractFieldErrors({ errors: 'oops' })).toBeUndefined() // string, not a map
67
+ expect(extractFieldErrors({ errors: ['a', 'b'] })).toBeUndefined() // array, not a map
68
+ expect(extractFieldErrors({ errors: {} })).toBeUndefined() // empty
69
+ expect(extractFieldErrors({ errors: { x: [null, ''] } })).toBeUndefined() // nothing normalizes
70
+ })
71
+ })
72
+
73
+ describe('localizeFieldIssue', () => {
74
+ it('required → interpolates label', () => {
75
+ expect(localizeFieldIssue({ code: 'required' }, 'Nombre', t)).toBe('El campo Nombre es obligatorio')
76
+ })
77
+ it('invalid_option', () => {
78
+ expect(localizeFieldIssue({ code: 'invalid_option', params: { allowed: ['a'] } }, 'Estado', t)).toBe(
79
+ 'El valor de Estado no es válido',
80
+ )
81
+ })
82
+ it('not_found', () => {
83
+ expect(localizeFieldIssue({ code: 'not_found', params: { ref: 'users' } }, 'Responsable', t)).toBe(
84
+ 'El Responsable seleccionado no existe',
85
+ )
86
+ })
87
+ it('duplicate', () => {
88
+ expect(localizeFieldIssue({ code: 'duplicate' }, 'SKU', t)).toBe('Ya existe un registro con ese SKU')
89
+ })
90
+ it('invalid_type', () => {
91
+ expect(localizeFieldIssue({ code: 'invalid_type', params: { expected: 'number' } }, 'Cantidad', t)).toBe(
92
+ 'El campo Cantidad tiene un formato inválido',
93
+ )
94
+ })
95
+ it('unknown code → generic fallback with label', () => {
96
+ expect(localizeFieldIssue({ code: 'weird_code' }, 'Campo', t)).toBe('Campo: valor inválido')
97
+ })
98
+ it('message passthrough (pre-localized) ignores code/label', () => {
99
+ const issue: FieldIssue = { message: 'Texto ya localizado' }
100
+ expect(localizeFieldIssue(issue, 'Ignorado', t)).toBe('Texto ya localizado')
101
+ })
102
+ })
@@ -60,4 +60,49 @@ describe('normalizeRefFieldsForSubmit', () => {
60
60
  normalizeRefFieldsForSubmit(input, fields)
61
61
  expect(input.category_id).toBe('')
62
62
  })
63
+
64
+ // --- Fase 4: explicit `nullable` flag from the kernel contract ---
65
+
66
+ it('nulls an empty ref when the explicit nullable:true flag is present', () => {
67
+ const out = normalizeRefFieldsForSubmit(
68
+ { supplier_id: '' },
69
+ [{ key: 'supplier_id', ref: 'suppliers', nullable: true }],
70
+ )
71
+ expect(out.supplier_id).toBeNull()
72
+ })
73
+
74
+ it('respects an empty value when nullable:false (does not null)', () => {
75
+ const out = normalizeRefFieldsForSubmit(
76
+ { supplier_id: '' },
77
+ [{ key: 'supplier_id', ref: 'suppliers', nullable: false }],
78
+ )
79
+ expect(out.supplier_id).toBe('')
80
+ })
81
+
82
+ it('nulls an empty NON-uuid optional ref via explicit nullable:true', () => {
83
+ // A ref over a non-uuid column: the uuid-only heuristic never covered
84
+ // this, but the explicit flag + ref-shape does.
85
+ const out = normalizeRefFieldsForSubmit(
86
+ { warehouse_code: '' },
87
+ [{ key: 'warehouse_code', type: 'dynamic_select', nullable: true }],
88
+ )
89
+ expect(out.warehouse_code).toBeNull()
90
+ })
91
+
92
+ it('does NOT null a nullable:true plain-text field (empty string stays)', () => {
93
+ const out = normalizeRefFieldsForSubmit(
94
+ { note: '' },
95
+ [{ key: 'note', type: 'text', nullable: true }],
96
+ )
97
+ expect(out.note).toBe('')
98
+ })
99
+
100
+ it('falls back to the heuristic when the flag is undefined (older host)', () => {
101
+ const out = normalizeRefFieldsForSubmit(
102
+ { category_id: '', name: '' },
103
+ fields, // fields carry no `nullable` flag
104
+ )
105
+ expect(out.category_id).toBeNull() // ref → heuristic nulls it
106
+ expect(out.name).toBe('') // plain text stays
107
+ })
63
108
  })
@@ -35,7 +35,8 @@ import {
35
35
  } from '@asteby/metacore-ui/primitives'
36
36
  import { Loader2 } from 'lucide-react'
37
37
  import { toast } from 'sonner'
38
- import { toastServerError, toastServerSuccess } from './server-error'
38
+ import { toastServerError, toastServerSuccess, extractFieldErrors, localizeFieldIssue } from './server-error'
39
+ import type { Translate } from './server-error'
39
40
  import { useApi } from './api-context'
40
41
  import { DynamicIcon } from './dynamic-icon'
41
42
  import { DynamicLineItems } from './dynamic-line-items'
@@ -403,6 +404,44 @@ function RecordPreview({ model, record }: { model: string; record: any }) {
403
404
  )
404
405
  }
405
406
 
407
+ /** Humanize a field key for a label fallback ("unit_price" → "Unit Price"). */
408
+ function humanizeKey(k: string): string {
409
+ return k.replace(/[._-]+/g, ' ').replace(/\b\w/g, c => c.toUpperCase())
410
+ }
411
+
412
+ /** Localize a failed action submit's per-field `errors` (422 map or `{errors}`
413
+ * body) into `{ [fieldKey]: localizedMessage }`, using each field's label.
414
+ * Returns undefined when there is no usable per-field map. */
415
+ function localizeActionFieldErrors(
416
+ err: unknown,
417
+ fields: readonly ActionFieldDef[] | undefined,
418
+ t: Translate,
419
+ ): Record<string, string> | undefined {
420
+ const map = extractFieldErrors(err)
421
+ if (!map) return undefined
422
+ const labelFor = (k: string) => {
423
+ const f = (fields ?? []).find(x => x.key === k)
424
+ return f?.label ? t(f.label, { defaultValue: f.label }) : humanizeKey(k)
425
+ }
426
+ const out: Record<string, string> = {}
427
+ for (const [k, issues] of Object.entries(map)) out[k] = localizeFieldIssue(issues[0], labelFor(k), t)
428
+ return out
429
+ }
430
+
431
+ /** Toast a failed action: a summary + localized per-field lines when the server
432
+ * returned a per-field `errors` map, else the standard cause-carrying toast.
433
+ * Used where inline rendering isn't wired (confirm / multi-step wizard). */
434
+ function toastActionError(err: unknown, fields: readonly ActionFieldDef[] | undefined, t: Translate): void {
435
+ const localized = localizeActionFieldErrors(err, fields, t)
436
+ if (localized) {
437
+ toast.error(t('dynamic.validation_failed', { defaultValue: 'Revisa los campos marcados' }), {
438
+ description: Object.values(localized).join('\n'),
439
+ })
440
+ return
441
+ }
442
+ toastServerError(err, { t })
443
+ }
444
+
406
445
  function ConfirmActionDialog({ open, onOpenChange, action, model, record, endpoint, onSuccess }: ActionModalProps) {
407
446
  const { t } = useTranslation()
408
447
  const api = useApi()
@@ -422,10 +461,10 @@ function ConfirmActionDialog({ open, onOpenChange, action, model, record, endpoi
422
461
  onOpenChange(false)
423
462
  onSuccess()
424
463
  } else {
425
- toastServerError({ response: { data: res.data } }, { t })
464
+ toastActionError({ response: { data: res.data } }, action.fields, t)
426
465
  }
427
466
  } catch (err: any) {
428
- toastServerError(err, { t })
467
+ toastActionError(err, action.fields, t)
429
468
  } finally {
430
469
  setExecuting(false)
431
470
  }
@@ -469,6 +508,8 @@ function GenericActionModal({ open, onOpenChange, action, model, record, endpoin
469
508
  const api = useApi()
470
509
  const [formData, setFormData] = useState<Record<string, any>>({})
471
510
  const [executing, setExecuting] = useState(false)
511
+ // Per-field validation errors (localized), shown inline under each input.
512
+ const [fieldErrors, setFieldErrors] = useState<Record<string, string>>({})
472
513
  // Related records to surface BELOW the form, as read-only context for the
473
514
  // record being acted on — e.g. the reception history of a transfer while
474
515
  // receiving against it. Sourced from the model's metadata.relations (the
@@ -512,29 +553,57 @@ function GenericActionModal({ open, onOpenChange, action, model, record, endpoin
512
553
  defaults[field.key] = field.defaultValue ?? (field.type === 'boolean' ? false : '')
513
554
  }
514
555
  setFormData(defaults)
556
+ setFieldErrors({})
515
557
  }
516
558
  }, [open, action.fields, record])
517
559
 
518
- const updateField = (key: string, value: any) => setFormData((prev: Record<string, any>) => ({ ...prev, [key]: value }))
560
+ const updateField = (key: string, value: any) => {
561
+ setFormData((prev: Record<string, any>) => ({ ...prev, [key]: value }))
562
+ setFieldErrors(prev => {
563
+ if (!prev[key]) return prev
564
+ const next = { ...prev }
565
+ delete next[key]
566
+ return next
567
+ })
568
+ }
569
+
570
+ const handleActionError = (err: unknown) => {
571
+ const localized = localizeActionFieldErrors(err, action.fields, t)
572
+ if (localized) {
573
+ setFieldErrors(localized)
574
+ toast.error(t('dynamic.validation_failed', { defaultValue: 'Revisa los campos marcados' }))
575
+ return
576
+ }
577
+ toastServerError(err, { t })
578
+ }
519
579
 
520
580
  const execute = async () => {
521
581
  if (action.fields) {
582
+ // Client-side required check → mark ALL missing fields inline.
583
+ const missing: Record<string, string> = {}
522
584
  for (const field of action.fields) {
523
585
  if (!field.required) continue
524
586
  if (isLineItemsField(field)) {
525
587
  const rows = formData[field.key]
526
588
  if (!Array.isArray(rows) || rows.length === 0) {
527
- toast.error(`${tl(field.label)} requiere al menos un renglón`)
528
- return
589
+ missing[field.key] = t('validation.line_items_required', {
590
+ defaultValue: '{{label}} requiere al menos un renglón',
591
+ label: tl(field.label),
592
+ })
529
593
  }
530
594
  continue
531
595
  }
532
596
  if (!formData[field.key] && formData[field.key] !== false) {
533
- toast.error(`${tl(field.label)} es requerido`)
534
- return
597
+ missing[field.key] = localizeFieldIssue({ code: 'required' }, tl(field.label), t)
535
598
  }
536
599
  }
600
+ if (Object.keys(missing).length) {
601
+ setFieldErrors(missing)
602
+ toast.error(t('dynamic.validation_failed', { defaultValue: 'Revisa los campos marcados' }))
603
+ return
604
+ }
537
605
  }
606
+ setFieldErrors({})
538
607
  setExecuting(true)
539
608
  try {
540
609
  const url = buildActionUrl(endpoint, model, record.id, action.key)
@@ -544,10 +613,10 @@ function GenericActionModal({ open, onOpenChange, action, model, record, endpoin
544
613
  onOpenChange(false)
545
614
  onSuccess()
546
615
  } else {
547
- toastServerError({ response: { data: res.data } }, { t })
616
+ handleActionError({ response: { data: res.data } })
548
617
  }
549
618
  } catch (err: any) {
550
- toastServerError(err, { t })
619
+ handleActionError(err)
551
620
  } finally {
552
621
  setExecuting(false)
553
622
  }
@@ -609,6 +678,9 @@ function GenericActionModal({ open, onOpenChange, action, model, record, endpoin
609
678
  {tl(field.label)}
610
679
  </FieldLabel>
611
680
  {renderField(field, formData[field.key], (v: any) => updateField(field.key, v), formData)}
681
+ {fieldErrors[field.key] && (
682
+ <p className="text-destructive text-xs mt-1">{fieldErrors[field.key]}</p>
683
+ )}
612
684
  </FieldCell>
613
685
  )
614
686
  })}
@@ -749,10 +821,10 @@ function WizardActionModal({ open, onOpenChange, action, model, record, endpoint
749
821
  onOpenChange(false)
750
822
  onSuccess()
751
823
  } else {
752
- toastServerError({ response: { data: res.data } }, { t })
824
+ toastActionError({ response: { data: res.data } }, steps.flatMap(s => s.fields ?? []), t)
753
825
  }
754
826
  } catch (err: any) {
755
- toastServerError(err, { t })
827
+ toastActionError(err, steps.flatMap(s => s.fields ?? []), t)
756
828
  } finally {
757
829
  setExecuting(false)
758
830
  }
@@ -48,7 +48,7 @@ import { format, parseISO } from 'date-fns'
48
48
  import { es } from 'date-fns/locale'
49
49
  import { ExternalLink, Loader2, CalendarIcon, ChevronDown, Check, Upload, X as XIcon } from 'lucide-react'
50
50
  import { useApi } from '../api-context'
51
- import { toastServerError } from '../server-error'
51
+ import { toastServerError, extractFieldErrors, localizeFieldIssue } from '../server-error'
52
52
  import { DynamicSelectField, OptionLead, OptionThumb } from '../dynamic-select-field'
53
53
  import { DynamicRelations } from '../dynamic-relations'
54
54
  import { useOptionsResolver, type ResolvedOption } from '../use-options-resolver'
@@ -497,6 +497,10 @@ export function DynamicRecordDialog({
497
497
  const [relations, setRelations] = useState<RelationMeta[]>([])
498
498
  const [record, setRecord] = useState<any | null>(null)
499
499
  const [formValues, setFormValues] = useState<Record<string, any>>({})
500
+ // Per-field validation errors (localized strings), keyed by field.key. Shown
501
+ // inline under each input; populated from a 422 `errors` map or the client
502
+ // required-field check, cleared per-field on change and wholesale on reopen.
503
+ const [fieldErrors, setFieldErrors] = useState<Record<string, string>>({})
500
504
  const [loading, setLoading] = useState(false)
501
505
  const [saving, setSaving] = useState(false)
502
506
  const [deleting, setDeleting] = useState(false)
@@ -511,6 +515,9 @@ export function DynamicRecordDialog({
511
515
  if (!open) return
512
516
  if (!isCreate && !recordId) return
513
517
 
518
+ // Fresh open → drop any validation errors from a prior submit.
519
+ setFieldErrors({})
520
+
514
521
  let cancelled = false
515
522
 
516
523
  // Seed instantly from the row the table already has so view/edit render
@@ -671,19 +678,55 @@ export function DynamicRecordDialog({
671
678
  onChange?.()
672
679
  }, [api, endpoint, model, recordId, isCreate, modalMeta, onChange])
673
680
 
681
+ // The human label for a field key, for localizing validation errors. Falls
682
+ // back to a humanized key when the field is unknown (e.g. a server-side key
683
+ // with no matching form field).
684
+ const labelForKey = (key: string): string => {
685
+ const f = (modalMeta?.fields ?? []).find(x => x.key === key)
686
+ if (f?.label) return f.label
687
+ return key.replace(/[._-]+/g, ' ').replace(/\b\w/g, c => c.toUpperCase())
688
+ }
689
+
690
+ // Turn a failed submit (422 `errors` map, or a bare `{errors}` body) into
691
+ // inline field errors + a summary toast. When there is no field map, fall
692
+ // back to the existing single cause-carrying toast.
693
+ const handleSubmitError = (err: unknown) => {
694
+ const map = extractFieldErrors(err)
695
+ if (map) {
696
+ const next: Record<string, string> = {}
697
+ for (const [key, issues] of Object.entries(map)) {
698
+ next[key] = localizeFieldIssue(issues[0], labelForKey(key), t)
699
+ }
700
+ setFieldErrors(next)
701
+ toast.error(t('dynamic.validation_failed', { defaultValue: 'Revisa los campos marcados' }))
702
+ return
703
+ }
704
+ toastServerError(err, { t, fallback: t('dynamic.save_error', { defaultValue: 'No se pudo guardar' }) })
705
+ }
706
+
674
707
  const handleSubmit = async (e?: React.FormEvent) => {
675
708
  e?.preventDefault()
676
709
  if (!modalMeta) return
677
710
 
678
711
  if (isEditable) {
712
+ // Collect ALL missing required fields (not just the first) and mark
713
+ // each inline instead of a single toast.
714
+ const missing: Record<string, string> = {}
679
715
  for (const field of modalMeta.fields ?? []) {
680
716
  if (field.required && !formValues[field.key] && formValues[field.key] !== 0 && formValues[field.key] !== false) {
681
- toast.error(`El campo "${field.label}" es obligatorio`)
682
- return
717
+ missing[field.key] = localizeFieldIssue({ code: 'required' }, field.label, t)
683
718
  }
684
719
  }
720
+ if (Object.keys(missing).length) {
721
+ setFieldErrors(missing)
722
+ toast.error(t('dynamic.validation_failed', { defaultValue: 'Revisa los campos marcados' }))
723
+ return
724
+ }
685
725
  }
686
726
 
727
+ // Required check passed → clear any prior validation errors.
728
+ setFieldErrors({})
729
+
687
730
  // Empty reference pickers → null (not "" / nil-UUID) so nullable FK
688
731
  // columns accept them instead of raising a 23503 FK violation.
689
732
  const payload = normalizeRefFieldsForSubmit(formValues, modalMeta.fields)
@@ -734,10 +777,10 @@ export function DynamicRecordDialog({
734
777
  // Surface the server's real cause (`details`) as the toast
735
778
  // description, not just the generic headline. `res.data` is the
736
779
  // `{ success:false, message, details }` envelope.
737
- toastServerError(res.data, { t, fallback: t('dynamic.save_error', { defaultValue: 'No se pudo guardar' }) })
780
+ handleSubmitError(res.data)
738
781
  }
739
782
  } catch (err: any) {
740
- toastServerError(err, { t, fallback: t('dynamic.save_error', { defaultValue: 'No se pudo guardar' }) })
783
+ handleSubmitError(err)
741
784
  } finally {
742
785
  setSaving(false)
743
786
  }
@@ -798,9 +841,17 @@ export function DynamicRecordDialog({
798
841
  record={record}
799
842
  value={formValues[field.key] ?? ''}
800
843
  mode={mode}
801
- onChange={val =>
844
+ error={fieldErrors[field.key]}
845
+ onChange={val => {
802
846
  setFormValues((prev: Record<string, any>) => ({ ...prev, [field.key]: val }))
803
- }
847
+ // Clear this field's error as soon as the user edits it.
848
+ setFieldErrors(prev => {
849
+ if (!prev[field.key]) return prev
850
+ const next = { ...prev }
851
+ delete next[field.key]
852
+ return next
853
+ })
854
+ }}
804
855
  />
805
856
  </FieldCell>
806
857
  )
@@ -910,9 +961,11 @@ interface FieldRowProps {
910
961
  value: any
911
962
  mode: 'view' | 'edit' | 'create'
912
963
  onChange: (val: any) => void
964
+ /** Localized validation error for this field, shown in red under the input. */
965
+ error?: string
913
966
  }
914
967
 
915
- function FieldRow({ field, record, value, mode, onChange }: FieldRowProps) {
968
+ function FieldRow({ field, record, value, mode, onChange, error }: FieldRowProps) {
916
969
  // A `readonly` field is server/system-generated (e.g. the GitHub addon's
917
970
  // `number`/`github_url`, filled by the API after the outbound create). On
918
971
  // CREATE it is excluded from the form entirely (see `visibleFields`); on EDIT
@@ -937,6 +990,10 @@ function FieldRow({ field, record, value, mode, onChange }: FieldRowProps) {
937
990
  ) : (
938
991
  <EditField field={field} value={value} onChange={onChange} record={record} />
939
992
  )}
993
+
994
+ {error && mode !== 'view' && (
995
+ <p className="text-destructive text-xs mt-1">{error}</p>
996
+ )}
940
997
  </div>
941
998
  )
942
999
  }
@@ -15,26 +15,40 @@ type RefFieldMeta = Record<string, any>
15
15
  * (e.g. products.category_id, a nullable `ref`) rejects a non-null value that
16
16
  * points at no row: sending `""`/nil-UUID triggers
17
17
  * insert ... violates foreign key constraint "fk_products_category" (23503)
18
- * even though the user left the picker empty. This is generic — it keys off the
19
- * field metadata (`getFieldRef` / dynamic_select / search), so every addon's
20
- * optional relations benefit, not just products. Non-reference fields are left
21
- * untouched (an empty text field is a legitimate `""`). Does not mutate `values`.
18
+ * even though the user left the picker empty.
19
+ *
20
+ * Nullability decision (Fase 4): prefer the EXPLICIT `nullable` flag the kernel
21
+ * (v0.77.1+) now serves per field (`modelbase.FieldDef.Nullable`, `!Required`).
22
+ * When `field.nullable === true` an empty value is submitted as `null`; when
23
+ * `field.nullable === false` the value is respected. When the flag is absent
24
+ * (undefined — older hosts that don't serve it yet) we fall back to the legacy
25
+ * type-based heuristic (`getFieldRef` / dynamic_select / search). This keeps
26
+ * backward-compat while letting the contract, not a guess, drive the decision.
27
+ *
28
+ * The explicit flag also lets us null an empty OPTIONAL ref whose column is NOT
29
+ * a uuid (which the uuid-only heuristic never covered). To avoid nulling a plain
30
+ * optional text field — where `""` is a legitimate value, not "no relation" — we
31
+ * gate the explicit path on the field ALSO looking like a reference/relation
32
+ * (`getFieldRef` / dynamic_select / search). A nullable non-ref scalar keeps its
33
+ * `""`. This is generic — every addon's optional relations benefit. Does not
34
+ * mutate `values`.
22
35
  */
23
36
  export function normalizeRefFieldsForSubmit(
24
37
  values: Record<string, any>,
25
38
  fields: RefFieldMeta[] | undefined,
26
39
  ): Record<string, any> {
27
- const refKeys = new Set(
28
- (fields ?? [])
29
- .filter(
30
- (f) =>
31
- !!getFieldRef(f as unknown as ActionFieldDef) ||
32
- f.type === 'dynamic_select' ||
33
- f.widget === 'dynamic_select' ||
34
- f.type === 'search',
35
- )
36
- .map((f) => f.key),
37
- )
40
+ const isRefField = (f: RefFieldMeta): boolean =>
41
+ !!getFieldRef(f as unknown as ActionFieldDef) ||
42
+ f.type === 'dynamic_select' ||
43
+ f.widget === 'dynamic_select' ||
44
+ f.type === 'search'
45
+
46
+ // Index fields by key so we can consult the explicit `nullable` flag.
47
+ const fieldByKey = new Map<string, RefFieldMeta>()
48
+ for (const f of fields ?? []) {
49
+ if (f && typeof f.key === 'string') fieldByKey.set(f.key, f)
50
+ }
51
+
38
52
  const out: Record<string, any> = { ...values }
39
53
  for (const [k, v] of Object.entries(out)) {
40
54
  // A nil UUID is never a real target row — null it out on any field.
@@ -42,8 +56,23 @@ export function normalizeRefFieldsForSubmit(
42
56
  out[k] = null
43
57
  continue
44
58
  }
45
- // An empty reference picker means "no relation" null (not "").
46
- if (refKeys.has(k) && (v === '' || v == null)) out[k] = null
59
+ const isEmpty = v === '' || v == null
60
+ if (!isEmpty) continue
61
+
62
+ const f = fieldByKey.get(k)
63
+ const nullable = f?.nullable
64
+ if (nullable === true) {
65
+ // Explicit contract flag wins. Only null a reference/relation so a
66
+ // legitimately-empty optional plain-text field keeps its `""`.
67
+ if (f && isRefField(f)) out[k] = null
68
+ continue
69
+ }
70
+ if (nullable === false) {
71
+ // Explicitly non-nullable → respect the empty value as-is.
72
+ continue
73
+ }
74
+ // No explicit flag (older host): fall back to the type-based heuristic.
75
+ if (f && isRefField(f)) out[k] = null
47
76
  }
48
77
  return out
49
78
  }