The Validator runs after Sanitizer. It receives SanitizedSheet and SheetLayout, runs cell → row → table validators in a Web Worker, and returns only a delta of errors (not the full sheet). The main thread builds an initial sheet and applies the delta to produce the final Sheet with errors attached to cells, rows, or the sheet.
Parser → Convert → Sanitizer → Validator → Transform
The Validator consumes SanitizedSheet and layout identifiers (e.g. validators: ['required', 'email']). Cell and row validators are synchronous; only table validators may be async (e.g. backend integrity checks).
In SheetLayout you can set:
fields[].validators— run per cell (e.g.['required', 'email']).rowValidators— run per row after cell validators.sheetValidators— run once at the end with the full dataset; these may be async.
Each entry is a string id or { name: 'id', params?: {...} }. Validators are resolved by id from the registry (built-in or registered via registerValidator).
Validators must not return static message strings. They return SheetError objects:
code— stable key for translation (e.g.'REQUIRED','INVALID_EMAIL').params— optional data for the UI (e.g.{ value, min, actual }).level—'error' | 'warning' | 'fatal' | 'info'.message— optional fallback for debugging; the UI should translate by code.rowIndex— optional; for sheet-level errors, indicates which row the error refers to (validation runs at sheet level but the error can be scoped to a row).cellKey— optional; for sheet-level errors, indicates which cell (together withrowIndex); for row-level errors, indicates which cell in that row — the error is then applied to that cell instead of the row.
The consumer translates code and params into localized text. Use rowIndex and cellKey when present to highlight or show the error next to the specific row/cell.
- Cell and row validators are strictly synchronous for performance (thousands of rows).
- Table validators may be async (e.g. one batched request to the backend). On network/backend failure the runner returns
EXTERNAL_VALIDATION_FAILEDwith optionalparams: { reason: 'network' | 'timeout' | 'server_error' }.
The Worker does not return the full sheet. It returns ValidatorDelta: an array of errors with coordinates (rowIndex, cellKey for cell errors; rowIndex for row errors; no coordinates for sheet errors). The main thread:
- Builds an initial Sheet from SanitizedSheet (empty errors).
- Applies the delta with
applyValidatorDelta(sheet, delta). - Updates the Provider result with the patched sheet.
All built-in validators are cell-level and are registered automatically in the Worker registry. Use the string id in the layout (e.g. validators: ['required', 'string:email']) or with params (e.g. { name: 'string:maxLength', params: { maxLength: 100 } }).
required— value must be non-empty (not null, undefined, or blank string).- String:
string:byregex,string:maxLength,string:minLength,string:email,string:phone,string:phoneInternational,string:phoneLocal,string:onlyNumbers,string:onlyLetters. - Number:
number:min,number:max,number:float,number:integer,number:nonNegative,number:nonPositive,number:nonZero. - Date:
date:min,date:max,date:onlyYear,date:onlyTime,date:datetime,date:timestamp,date:utc. - Bool:
bool:onlyTrue,bool:onlyFalse.
See validators.md for the full compatibility table and params.
The Validator runs in a Web Worker (Comlink). Internal hook useValidatorWorker (from core/validator) exposes:
validate(sanitizedSheet, sheetLayout, options?, onProgress?)— returnsPromise<ValidatorDelta>.validateAndApply(sanitizedSheet, options?, onProgress?)— runs validate, builds initial sheet, applies delta, and callssetResult(patchedSheet)using the Provider’s layout.
Progress is reported via the same EventTarget (importer-progress). abort() terminates the worker and passes an AbortSignal to async table validators so backend requests can be cancelled.
If a validator returns an error with level: 'fatal', the runner stops running further validators for that cell or row to save CPU.
- How to: Sanitizer — Produces
sanitizedSheetwhich is the input to the Validator. - Architecture — Data flow, Registry pattern, Sync Row Loop → Async Table Check, Delta strategy.