acceptableLengths
function
The lengths a string domain accepts, after the patterns are applied.
| Package | @formscript/validation |
|---|---|
| Specification | 4.8, 10, 10.1, 10.2, 10.3, 10.4, 10.5, 10.6 |
| Depends on | ast, decimal, errors, evaluator, types |
The validation model of the FormScript Language Specification 1.0.0, §10.
The package is pure: it judges a field's constraints and a form's validity from the values it is given. It never fetches, never schedules and never reads the clock, so two conforming runtimes reach the same verdict for the same inputs.
| Section | What this package implements |
|---|---|
| §10.1 | validateOn — blur | change | submit | blur+submit, default blur |
| §10.2 | Constraint evaluation, constraint accumulation (Spec-10.5), custom (Spec-10.6, Spec-10.7) |
| §10.2.1 | accepted (Spec-10.9, Spec-10.10), required on a boolean (Spec-10.8) |
| §10.3 | cross and the other cross-field constraints (Spec-10.12) |
| §10.4 | Form-level validity (Spec-10.13 to Spec-10.17) and the "do not show a violation too early" rule (Spec-10.4) |
| §10.5 | Message severity: error by default, warn for a warning (Spec-10.18) |
| §10.6 | Satisfiability analysis, tiers A1 (MUST) and A2 (SHOULD) (Spec-10.19 to Spec-10.29) |
@formscript/types owns the field-state lattice; this package uses
deriveValidity, mayShowViolation and satisfiesRequired rather than
re-deriving them.
type ValidateOn = 'blur' | 'change' | 'submit' | 'blur+submit';
const VALIDATE_ON_VALUES: readonly ValidateOn[];
const DEFAULT_VALIDATE_ON: ValidateOn; // 'blur'
interface ConstraintSpec {
readonly severity: 'error' | 'warning';
readonly constraint: Constraint; // @formscript/ast
readonly span: SourceSpan;
}
function collectConstraints(block: Block): readonly ConstraintSpec[];
function validateOnOf(block: Block): ValidateOn;
function validatesOn(validateOn: ValidateOn, event: 'blur' | 'change' | 'submit'): boolean;
function isUnguarded(constraint: Constraint): boolean;
collectConstraints also expands the required property into its required
constraint (Spec-8.29).
type ViolationCode = 'E-VAL-01' | 'E-VAL-02' | 'E-VAL-03' | 'E-VAL-04' | 'E-VAL-05';
interface Violation {
readonly code: ViolationCode;
readonly severity: 'error' | 'warning';
readonly message: string;
readonly messageKey: string; // a catalogue key, for localisation
readonly kind: Constraint['kind'];
readonly path: readonly string[];
readonly span: SourceSpan;
}
interface ValidationEnvironment {
evaluate(expression: Expression, context: ConstraintContext): unknown;
read(path: readonly string[]): unknown;
peers(path: readonly string[]): readonly unknown[];
}
function evaluateField(input: FieldValidationInput, environment: ValidationEnvironment): FieldValidationResult;
function guardOf(constraint: Constraint): Expression | undefined;
function compareDataPlane(left: unknown, right: unknown): number | null;
function scalarLength(text: string): number;
evaluateField returns the field's validity, every failing constraint
(Spec-10.5), the deferred constraints (E-VAL-05), whether a violation may be
shown (Spec-10.4) and whether an error value reached a constraint.
function judgeForm(input: FormValidationInput): FormValidationResult;
FormValidationResult carries valid (the $form.valid judgement, Spec-10.17),
submittable (the strict-aware judgement, Spec-10.14), firstFailing (the
first failing field in document order, Spec-10.16), invalidFields,
pendingFields, violations and deferred.
function analyzeSatisfiability(document: Document, options?: SatisfiabilityOptions): SatisfiabilityReport;
function findingsToDiagnostics(findings: readonly SatisfiabilityFinding[]): Diagnostic[];
function analyzePattern(pattern: string): PatternInfo;
The analysis is a decision procedure over domains, not a solver: no search, no backtracking and no value enumeration (Spec-10.20). The conclusion of every field follows from the rules of §10.6.1 and §10.6.2, so two conforming implementations agree.
The specification leaves the following open. Each choice is noted here rather than hidden in the code.
min, max,
minLength, maxLength, pattern, email, phone, url, in,
notIn, multipleOf, equal, notEqual, cross and unique are
vacuously satisfied when the field holds nothing. Only required (and
accepted) inspect emptiness. The alternative — treating an absent value as
an undetermined comparison — would make every optional field with a min
constraint pending, which contradicts required existing as a separate
constraint.required = false is a constraint guarded by the literal false.
Spec-8.29 says "required = <bool literal> is exactly validate { required }",
which read literally would make required = false mean required. Spec-8.31
("required = false with accepted is the normal spelling") shows that the
intended meaning is "not required", so required = false is modelled as a
constraint whose guard is the literal false and therefore never binds
(Spec-5.10).min, max,
minLength, maxLength or multipleOf evaluates to null or
inapplicable, the constraint is deferred (E-VAL-05) rather than
silently passing, so the deferral is visible rather than silent.custom returning anything other than true, null or a string fails.
Spec-10.6 lists only those three results. false and inapplicable are
therefore treated as failures with the default message; the error value
aborts the enclosing transaction (E-EVAL-07).email, phone and url grammars are this implementation's choice.
§4.8 names the three constraints but fixes no grammar. The patterns are
conservative and locale-independent (Spec-12.9). A phone must also carry
between 7 and 15 digits.minLength and
maxLength.$form.valid is the base judgement, not the strict-aware one.
Spec-10.17 says $form.valid evaluates to the result of Spec-10.13, but
Spec-10.14 makes Spec-10.13 strict-dependent and Spec-10.15 forbids strict
from affecting any data-plane result. $form.valid is therefore "no field is
invalid" (Spec-5.13) and never depends on strict; submittable is the
strict-aware judgement.E-BOUND-* codes are not re-reported. Spec-10.22 gives the
E-BOUND-* codes precedence over E-SAT-01, but @formscript/analyzer
already reports them. This package suppresses E-SAT-01 and E-SAT-02
for a field that has an E-BOUND-* finding, so the more specific code wins
without the diagnostic being emitted twice.true (Spec-10.25).
Narrowing a guard to a value it may or may not take would require
enumerating the value space, which Spec-10.20 forbids; such a field is
therefore undetermined at tier A2 and is not reported.W-SAT-01 is also reported for a field inside an entity whose when is
the literal false. The entity's own when makes the field
unreachable by Spec-8.2, so the field is provably dead in exactly the sense
Spec-10.28 describes.messageKey. Spec-10.10 requires the
accepted message to be localisable (Spec-12.7); every violation therefore
carries a stable key next to its message so a host can localise it.@formscript/analyzerThe analyzer reports the static half of §10.6 — it already emits E-SAT-01
for an enum whose option set is disjoint from the declared options, and the
E-BOUND-*, W-VAL-01 and E-CYCLE-01 codes. This package does not duplicate
those diagnostics. Its tier A1 domain intersection is a superset of the
analyzer's enum/options check: it also reports E-SAT-01 for a pattern that
cannot match inside the declared length range, for a notIn that empties an
enum, for a multipleOf whose interval holds no multiple, and for a required
that removes the only value of the domain. A host should not run both
reporters without deduplicating.
44 exported symbols.
acceptableLengths
function
The lengths a string domain accepts, after the patterns are applied.
analyzePattern
re-exportanalyzeSatisfiability
re-exportcollectConstraints
re-exportcompareDataPlane
re-exportConstraintContext
interface
The context a constraint is evaluated in.
ConstraintSpec
interface
A constraint together with the severity of its message (Spec-10.18).
DEFAULT_VALIDATE_ON
re-exportDomain
interfaceentityAt
function
The entity a path names, or `null`.
evaluateField
re-exportFieldValidationInput
interfaceFieldValidationResult
interfacefindingsToDiagnostics
re-exportFORMAT_PATTERNS
const
The `email`, `phone` and `url` grammars of §4.8; the specification fixes none, so these are this implementation's choice.
FormFieldValidation
interfaceFormValidationInput
interfaceFormValidationResult
interfaceguardOf
re-exporthasE164DigitCount
function
Whether a string has between 7 and 15 digits, the E.164 count.
intersectDomains
function
The intersection of two domains (Spec-10.21).
isEmptyDomain
function
Whether the domain is provably empty (Spec-10.23, Spec-10.24).
isUnguarded
re-exportjudgeForm
function
Judges the form as a whole; `valid` never depends on `strict` (Spec-10.15).
LengthRange
interfaceNumericRange
interfacePatternInfo
interface
The length analysis a `pattern` constraint needs for tier A1 (Spec-10.23); it enumerates no values (Spec-10.20).
patternSource
function
A pattern's analysis, or `null` when the pattern cannot be used.
PatternSource
interfaceSatisfiabilityCode
typeSatisfiabilityFinding
interfaceSatisfiabilityOptions
interfaceSatisfiabilityReport
interfacescalarLength
re-exporttypeDomain
function
The domain a declared type admits (Spec-10.21).
UNRESTRICTED
constVALIDATE_ON_VALUES
re-exportValidateOn
type
When a field's constraints are evaluated (§10.1).
validateOnOf
re-exportvalidatesOn
re-exportValidationEnvironment
interface
What a runtime supplies to the validator.
ValidationEvent
type
The events that can trigger validation.
Violation
interface
A message that failed a constraint (Spec-10.5).
ViolationCode
type