refactor(form-schema): inline validators to remove @core transitive dep
Resolves TECH-07. Copies the four validators actually used
(requiredValidator, emailValidator, urlValidator, regexValidator) from
@core/utils/validators into packages/form-schema/src/utils/validators.ts
as pure boolean functions. Vuexy template copies in apps/*/src/@core/
remain for non-form UI use. Package is now genuinely standalone —
grep -rn "@core/" packages/form-schema/ returns zero matches.
Also corrects two documentation inconsistencies from commit 42dd626e:
dev-guide heading translated to Dutch for style consistency, and the
BACKLOG entry renumbered from TECH-DEBT-01 to TECH-07 to match the
flat numbering in the Technische schuld section.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -489,22 +489,6 @@ apps/portal om drift te voorkomen.
|
||||
|
||||
---
|
||||
|
||||
### TECH-DEBT-01 — @form-schema transitive dep op @core/utils/validators
|
||||
|
||||
**Aanleiding:** `packages/form-schema/src/utils/formValidation.ts`
|
||||
importeert uit `@core/utils/validators`, dat per-app resolvt naar
|
||||
`apps/*/src/@core/utils/validators.ts`. Beide app-kopieën zijn op dit
|
||||
moment identiek (Vuexy template-code), maar drift tussen de twee
|
||||
zou `@form-schema` per consumer verschillend laten werken.
|
||||
**Wat:** Kopieer de specifieke validators die `formValidation.ts`
|
||||
gebruikt naar `packages/form-schema/src/utils/` zodra het package
|
||||
een tweede echte consumer krijgt (PR-c of later). Ontdekt tijdens
|
||||
PR-a (commit dda60ed5).
|
||||
**Prioriteit:** Laag — latent; triggert pas bij consumer-drift of
|
||||
wanneer het package buiten de huidige Vuexy-twin apps wordt geladen.
|
||||
|
||||
---
|
||||
|
||||
### ~~TECH-02 — scopeForFestival helper op Event model~~ ✅ OPGELOST
|
||||
|
||||
---
|
||||
@@ -517,6 +501,10 @@ wanneer het package buiten de huidige Vuexy-twin apps wordt geladen.
|
||||
|
||||
---
|
||||
|
||||
### ~~TECH-07 — @form-schema transitive dep op @core/utils/validators~~ ✅ OPGELOST — resolved in PR-a1
|
||||
|
||||
---
|
||||
|
||||
## Opgeloste items (april 2026)
|
||||
|
||||
De volgende items zijn geïmplementeerd en afgerond (673+ tests):
|
||||
|
||||
@@ -381,7 +381,7 @@ Altijd in deze volgorde. Nooit stappen overslaan — later toevoegen kost meer t
|
||||
| Fase 3 — Advancing & Show Day | Artist advancing + portaal, Timetable, Mission Control, Formulierbouwer, Post-festival evaluatie, PDF allocatiesheet, Campagnes (email + WhatsApp via Zender) |
|
||||
| Fase 4 — Differentiators | Real-time WebSockets, Show Day Mode, Vrijwilligersprofiel + festival-paspoort, Shift swap & wachtlijst, Retrospectief rapport, Leveranciersportaal uitgebreid |
|
||||
|
||||
## Shared frontend packages
|
||||
## Gedeelde frontend packages
|
||||
|
||||
`apps/portal/` en `apps/app/` delen een klein aantal schema-gedreven modules. Deze sectie legt vast wat wel en niet in die gedeelde laag hoort, en hoe je de aliases opzet.
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { emailValidator, regexValidator, requiredValidator, urlValidator } from '@core/utils/validators'
|
||||
import { emailValidator, regexValidator, requiredValidator, urlValidator } from './validators'
|
||||
import { FormFieldType } from '../types/formBuilder'
|
||||
import type { PublicFormField } from '../types/formBuilder'
|
||||
|
||||
|
||||
54
packages/form-schema/src/utils/validators.ts
Normal file
54
packages/form-schema/src/utils/validators.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
// Pure boolean validators used as gates by formValidation.ts. Error
|
||||
// messages (in Dutch) are produced by the caller, not by these validators.
|
||||
// This file deliberately has no external imports — the package must be
|
||||
// standalone and free of cross-app coupling.
|
||||
|
||||
function isNullOrUndefined(value: unknown): boolean {
|
||||
return value === null || value === undefined
|
||||
}
|
||||
|
||||
function isEmptyArray(value: unknown): boolean {
|
||||
return Array.isArray(value) && value.length === 0
|
||||
}
|
||||
|
||||
function isEmpty(value: unknown): boolean {
|
||||
if (isNullOrUndefined(value)) return true
|
||||
if (typeof value === 'string') return value.trim() === ''
|
||||
if (Array.isArray(value)) return value.length === 0
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
export function requiredValidator(value: unknown): boolean {
|
||||
if (isNullOrUndefined(value) || isEmptyArray(value) || value === false) return false
|
||||
|
||||
return String(value).trim().length > 0
|
||||
}
|
||||
|
||||
export function emailValidator(value: unknown): boolean {
|
||||
if (isEmpty(value)) return true
|
||||
|
||||
const re = /^(?:[^<>()[\]\\.,;:\s@"]+(?:\.[^<>()[\]\\.,;:\s@"]+)*|".+")@(?:\[\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\]|(?:[a-z\-\d]+\.)+[a-z]{2,})$/i
|
||||
|
||||
if (Array.isArray(value)) return value.every(val => re.test(String(val)))
|
||||
|
||||
return re.test(String(value))
|
||||
}
|
||||
|
||||
export function urlValidator(value: unknown): boolean {
|
||||
if (isEmpty(value)) return true
|
||||
|
||||
const re = /^https?:\/\/[^\s$.?#].\S*$/
|
||||
|
||||
return re.test(String(value))
|
||||
}
|
||||
|
||||
export function regexValidator(value: unknown, regex: RegExp | string): boolean {
|
||||
if (isEmpty(value)) return true
|
||||
|
||||
const regEx = typeof regex === 'string' ? new RegExp(regex) : regex
|
||||
|
||||
if (Array.isArray(value)) return value.every(val => regexValidator(val, regEx))
|
||||
|
||||
return regEx.test(String(value))
|
||||
}
|
||||
Reference in New Issue
Block a user