@moatamed-sce/form-engine 0.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"moatamed-sce-form-engine.mjs","sources":["../../../../libs/form-engine/src/lib/coerce-value.ts","../../../../libs/form-engine/src/lib/evaluate-rules.ts","../../../../libs/form-engine/src/lib/named-validators.ts","../../../../libs/form-engine/src/lib/build-form-group.ts","../../../../libs/form-engine/src/lib/array-rows.ts","../../../../libs/form-engine/src/lib/data-source.port.ts","../../../../libs/form-engine/src/lib/form-steps.ts","../../../../libs/form-engine/src/moatamed-sce-form-engine.ts"],"sourcesContent":["import type { FormFieldType } from '@moatamed-sce/form-schema';\n\n/**\n * The value shape each control type holds.\n *\n * A `FormGroup` built from a definition has to be typed before any data arrives, and getting\n * this wrong is subtle: a multi-select seeded with `''` instead of `[]` makes `value.length`\n * read 0 either way, then throws the first time something calls `.map`. A currency field seeded\n * with `''` submits an empty string where the API expects a number or null.\n */\n\n/** Types whose value is an array rather than a scalar. */\nexport const MULTI_VALUE_TYPES: ReadonlySet<FormFieldType> = new Set<FormFieldType>([\n 'multiselect',\n 'checkbox',\n // A searchable checkbox list is still a checkbox list. Leaving it out seeded it with `''`,\n // so `.length` read 0 like an empty selection and the first `.map` threw.\n 'checkbox-search',\n 'file',\n]);\n\n/**\n * Types whose value is structured and must not be coerced at all.\n *\n * `geo` holds `{ lat, lng, address }`. The default branch below runs `String(provided)`, which\n * turns that into the literal text `[object Object]` — the coordinates are gone, and nothing\n * downstream can tell that they ever existed. A structured value is passed through untouched.\n */\nconst OPAQUE_TYPES: ReadonlySet<FormFieldType> = new Set<FormFieldType>(['geo']);\n\n/** The empty value a type holds before any input. */\nexport function typeFallback(type: FormFieldType): unknown {\n if (MULTI_VALUE_TYPES.has(type)) {\n return [];\n }\n switch (type) {\n case 'switch':\n return false;\n case 'rating':\n // 0 stars, not `''` — the widget takes a number, and `''` renders as no rating while\n // failing a `min` check with a type error rather than a rating error.\n return 0;\n case 'currency':\n // null, not 0: an untouched amount is \"not stated\", and 0 is a real figure.\n return null;\n case 'geo':\n // null: no location picked. `''` is not a place.\n return null;\n default:\n return '';\n }\n}\n\n/** Coerces a provided value into the shape the type expects. */\nexport function coerceValue(type: FormFieldType, provided: unknown): unknown {\n if (MULTI_VALUE_TYPES.has(type)) {\n return Array.isArray(provided) ? provided : provided == null || provided === '' ? [] : [provided];\n }\n if (OPAQUE_TYPES.has(type)) {\n return provided ?? null;\n }\n switch (type) {\n case 'switch':\n return Boolean(provided);\n case 'rating': {\n const parsed = Number(provided);\n return Number.isFinite(parsed) ? parsed : 0;\n }\n case 'currency':\n case 'number': {\n if (provided == null || provided === '') {\n return type === 'currency' ? null : '';\n }\n const parsed = Number(provided);\n return Number.isFinite(parsed) ? parsed : type === 'currency' ? null : String(provided);\n }\n default:\n return provided == null ? '' : String(provided);\n }\n}\n","import {\n isFieldCondition,\n isFormArrayNode,\n isFormField,\n isFormGroupNode,\n type Condition,\n type FormArrayNode,\n type FormDefinition,\n type FormField,\n type FormNode,\n type RuleAction,\n} from '@moatamed-sce/form-schema';\n\n/**\n * Rule evaluation.\n *\n * No `eval`, no `new Function`, no expression parser — a closed operator set walked recursively.\n * A definition may arrive from an API, so the evaluator has to be safe against a hostile\n * document by construction rather than by sanitising one.\n */\n\n/** What the rules currently say about one field. */\nexport interface FieldRuleState {\n readonly hidden: boolean;\n readonly disabled: boolean;\n readonly readonly: boolean;\n /** `true` when a rule added a requirement, `false` when one removed it, `undefined` when rules are silent. */\n readonly required?: boolean;\n}\n\n/**\n * Rule state for every field, keyed by the **control path** that addresses it.\n *\n * For a flat definition a path is just the field's key, so nothing changes. Inside a group it is\n * dotted — `riyadh.q-5` — which is what `FormGroup.get` needs. Keying by the bare key instead\n * meant a rule silently did nothing the moment a definition used groups: `group.get('q-5')`\n * returns null when the control lives at `riyadh.q-5`, and the follow-up it was meant to reveal\n * stayed hidden with nothing to say so.\n */\nexport type RuleState = ReadonlyMap<string, FieldRuleState>;\n\n/**\n * The repeater row a field lives in.\n *\n * Rules are authored against a definition, which knows the *shape* of a row and never how many\n * of them exist — so an effect naming `crNumber` has to mean \"that field, in whichever row is\n * being resolved\". The prefix is what turns it into a control path, and `keys` is what decides\n * whether a condition is asking about this row or about the form.\n */\nexport interface RowScope {\n /** Control path of the row group — `partners.0`. */\n readonly prefix: string;\n /** Field paths declared inside one row, relative to {@link prefix}. */\n readonly keys: ReadonlySet<string>;\n}\n\n/** A field and the control path that reaches it. */\nexport interface FieldPath {\n readonly field: FormField;\n readonly path: string;\n /** Set when the field is inside a repeater row, which is what scopes a rule to that row. */\n readonly row?: RowScope;\n}\n\n/** The field paths one row of a repeater declares, relative to the row. */\nfunction rowKeys(node: FormArrayNode): ReadonlySet<string> {\n const keys = new Set<string>();\n const walk = (nodes: readonly FormNode[], prefix: string): void => {\n for (const inner of nodes) {\n const at = prefix ? `${prefix}.${inner.key}` : inner.key;\n if (isFormField(inner)) {\n keys.add(at);\n } else if (isFormGroupNode(inner)) {\n walk(inner.nodes, at);\n }\n }\n };\n walk(node.nodes, '');\n return keys;\n}\n\n/**\n * Every field a rule can address, with its control path.\n *\n * Repeater rows are walked only when `values` are supplied, because how many rows exist is a\n * fact about the data and never about the definition — the same reason `buildFormGroup` seeds\n * `max(rows.length, minItems)` rather than a number the schema could state. Called without\n * values this returns the static tree, which is what a caller wants when it needs the fields a\n * definition declares rather than the controls a form currently holds.\n */\nexport function fieldPaths(definition: FormDefinition, values?: Readonly<Record<string, unknown>>): FieldPath[] {\n const out: FieldPath[] = [];\n\n const walk = (nodes: readonly FormNode[], prefix: string, local: Record<string, unknown>, row?: RowScope): void => {\n for (const node of nodes) {\n const path = prefix ? `${prefix}.${node.key}` : node.key;\n\n if (isFormField(node)) {\n out.push(row ? { field: node, path, row } : { field: node, path });\n continue;\n }\n\n if (isFormGroupNode(node)) {\n walk(node.nodes, path, asRecord(local[node.key]), row);\n continue;\n }\n\n if (!values || !isFormArrayNode(node)) {\n continue;\n }\n\n const rows = Array.isArray(local[node.key]) ? (local[node.key] as unknown[]) : [];\n // The same count `buildFormGroup` seeds, so the state map describes the controls that\n // exist rather than the ones the data happened to arrive with.\n const rowCount = Math.max(rows.length, node.minItems ?? 0);\n const keys = rowKeys(node);\n for (let index = 0; index < rowCount; index += 1) {\n const rowPrefix = `${path}.${index}`;\n walk(node.nodes, rowPrefix, asRecord(rows[index]), { prefix: rowPrefix, keys });\n }\n }\n };\n\n const root = values ?? {};\n for (const page of definition.pages) {\n walk(page.nodes, '', root as Record<string, unknown>);\n }\n return out;\n}\n\n/** A nested value as a record, so the walk can keep descending without a null check per branch. */\nfunction asRecord(value: unknown): Record<string, unknown> {\n return value !== null && typeof value === 'object' ? (value as Record<string, unknown>) : {};\n}\n\n/** Reads a control value by key, or by dotted path for a field inside a group or a row. */\nfunction readPath(values: Readonly<Record<string, unknown>>, field: string): unknown {\n if (!field.includes('.')) {\n return values[field];\n }\n let current: unknown = values;\n for (const segment of field.split('.')) {\n if (current === null || typeof current !== 'object') {\n return undefined;\n }\n current = (current as Record<string, unknown>)[segment];\n }\n return current;\n}\n\n/**\n * Reads the value a condition names, from the row when the row declares that field.\n *\n * Membership decides this, not whether the row happens to hold a value: `undefined` is a real\n * answer to an unanswered question, and choosing by value would make a rule read the *form's*\n * `type` for the first row and the row's own `type` for the second.\n */\nfunction readValue(values: Readonly<Record<string, unknown>>, field: string, scope?: RowScope): unknown {\n return scope?.keys.has(field) ? readPath(values, `${scope.prefix}.${field}`) : readPath(values, field);\n}\n\n/**\n * Evaluates a condition against the live form values.\n *\n * `scope` is the row a rule is being resolved for. Inside one, a condition naming a field the\n * row declares reads *that row's* answer — which is the only reading that lets \"when this\n * partner is a company, require this partner's CR number\" be written at all. Every other field\n * it names is read from the form, so a row can still depend on a question asked once above it.\n */\nexport function evaluateCondition(\n condition: Condition,\n values: Readonly<Record<string, unknown>>,\n scope?: RowScope\n): boolean {\n if (!isFieldCondition(condition)) {\n return condition.op === 'and'\n ? condition.clauses.every(clause => evaluateCondition(clause, values, scope))\n : condition.clauses.some(clause => evaluateCondition(clause, values, scope));\n }\n\n const value = readValue(values, condition.field, scope);\n switch (condition.op) {\n case 'eq':\n return value === condition.value;\n case 'neq':\n return value !== condition.value;\n case 'in':\n return Array.isArray(condition.value) && condition.value.some(candidate => candidate === value);\n case 'truthy':\n // An empty array is falsy here even though `Boolean([])` is true: a multi-select with\n // nothing chosen has not been answered, and every rule that reads one means it that way.\n return Array.isArray(value) ? value.length > 0 : Boolean(value);\n case 'falsy':\n return Array.isArray(value) ? value.length === 0 : !value;\n default:\n return false;\n }\n}\n\nconst APPLY: Readonly<Record<RuleAction, (state: FieldRuleState) => FieldRuleState>> = {\n show: state => ({ ...state, hidden: false }),\n hide: state => ({ ...state, hidden: true }),\n enable: state => ({ ...state, disabled: false }),\n disable: state => ({ ...state, disabled: true }),\n require: state => ({ ...state, required: true }),\n unrequire: state => ({ ...state, required: false }),\n readonly: state => ({ ...state, readonly: true }),\n};\n\n/**\n * Resolves every field's visibility, enablement and requirement for the current values.\n *\n * Starts from the definition's static state — `hiddenByDefault` — then applies each matching\n * rule in document order, so a later rule wins over an earlier one. That ordering is the reason\n * rules live on the definition rather than the field: it is deterministic and reviewable in one\n * place, where a per-field predicate is neither.\n *\n * A rule that reaches into a repeater is resolved **once per row**, against that row's answers.\n * Evaluating the condition once for the whole form instead would make every row share one\n * verdict — the first partner declared a company would require a CR number from all of them.\n */\nexport function evaluateRules(definition: FormDefinition, values: Readonly<Record<string, unknown>>): RuleState {\n const state = new Map<string, FieldRuleState>();\n const paths = fieldPaths(definition, values);\n const scopes = new Map<string, RowScope | undefined>();\n\n for (const { field, path, row } of paths) {\n state.set(path, {\n hidden: field.hiddenByDefault === true,\n disabled: field.props?.['disabled'] === true,\n readonly: field.props?.['readonly'] === true,\n });\n scopes.set(path, row);\n }\n\n for (const rule of definition.rules ?? []) {\n // One verdict per scope, not per target: a rule with four effects on the same row must not\n // evaluate its condition four times, and two rows must not share one.\n const verdicts = new Map<string, boolean>();\n\n for (const effect of rule.then) {\n for (const path of resolveTarget(effect.target, state, paths)) {\n const scope = scopes.get(path);\n const key = scope?.prefix ?? '';\n let holds = verdicts.get(key);\n if (holds === undefined) {\n holds = evaluateCondition(rule.when, values, scope);\n verdicts.set(key, holds);\n }\n if (holds) {\n state.set(path, APPLY[effect.action](state.get(path) as FieldRuleState));\n }\n }\n }\n }\n\n return state;\n}\n\n/**\n * The control paths a rule effect names.\n *\n * An effect may address a field by full path or by bare key. The bare key is what every mapper\n * writes, because a `Requirement` knows its own id and not which group it landed in — resolving\n * it here is what lets the mapper stay ignorant of the tree it produced. A key matching several\n * groups applies to all of them, which is right for a definition that repeats the same question\n * per scope, and it is also how a rule reaches a repeater: a row's controls are indexed, so\n * `partners.0.crNumber` is a path no author can write and `crNumber` has to mean every row.\n *\n * A target matching nothing is skipped: a rule pointing at a deleted field is an authoring\n * mistake, not a reason to stop rendering the rest of the form.\n */\nfunction resolveTarget(target: string, state: RuleState, paths: readonly FieldPath[]): string[] {\n if (state.has(target)) {\n return [target];\n }\n return paths.filter(({ field }) => field.key === target).map(({ path }) => path);\n}\n\n/** Convenience default for a field the rules never mention. */\nexport const DEFAULT_FIELD_RULE_STATE: FieldRuleState = { hidden: false, disabled: false, readonly: false };\n","import { Validators, type ValidatorFn } from '@angular/forms';\nimport {\n crNumberValidator,\n ibanValidator,\n iqamaValidator,\n saudiIdValidator,\n saudiMobile05Validator,\n shortAddressValidator,\n vatNumberValidator,\n} from '@moatamed-sce/core';\nimport { PATTERN_SOURCE_MAX_LENGTH, type NamedValidator, type NamedValidatorName } from '@moatamed-sce/form-schema';\n\n/**\n * Resolves the names on a `FormDefinition` to the real validators.\n *\n * This is the seam that makes named validators worth having. The Saudi rules already exist,\n * tested, in `libs/core/src/lib/validation/` — the problem was that a form had to import each\n * one and attach it as a function, so a JSON document could not describe them and pages kept\n * re-typing the regexes instead.\n *\n * Deliberately NOT wired: `libs/core/src/lib/utils/validation.utils.ts` also exports\n * `isValidSaudiId` and `isValidIBAN`, and they disagree with the validators above — the utils\n * version applies a Luhn check and only accepts a `1` prefix, rejecting the Iqama-holder `2`\n * prefix the validator accepts. The validator directory is canonical here; see ADR 0002.\n */\n\n/** Reads a numeric parameter, tolerating the string form an API may send. */\nfunction numberParam(params: Readonly<Record<string, unknown>> | undefined, key: string): number | null {\n const raw = params?.[key];\n const value = typeof raw === 'string' ? Number(raw) : raw;\n return typeof value === 'number' && Number.isFinite(value) ? value : null;\n}\n\n/**\n * Flags that make a `RegExp` carry state between calls.\n *\n * `Validators.pattern` uses a supplied `RegExp` object directly, and `.test()` on a `g` or `y`\n * regex advances `lastIndex` — so validating the *same unchanged value* returned valid, invalid,\n * valid, invalid on successive passes. A field flickered between states on every keystroke, and\n * whether a form could be submitted depended on how many times it had been validated. Dropping\n * the flag is the only reading that makes a stored pattern mean one thing.\n */\nconst STATEFUL_REGEX_FLAGS = /[gy]/g;\n\n/** Rebuilds a `RegExp` from the serialized `{ source, flags }` a JSON definition carries. */\nfunction patternParam(params: Readonly<Record<string, unknown>> | undefined): RegExp | string | null {\n const source = params?.['source'];\n if (typeof source !== 'string' || source === '') {\n return null;\n }\n // A pathological pattern from an untrusted definition is a ReDoS vector. The cap is the\n // schema's, imported rather than restated: two copies of a security bound drift, and the one\n // that drifts down is the one nobody notices.\n if (source.length > PATTERN_SOURCE_MAX_LENGTH) {\n return null;\n }\n const flags = params?.['flags'];\n const safeFlags = typeof flags === 'string' ? flags.replace(STATEFUL_REGEX_FLAGS, '') : '';\n try {\n return new RegExp(source, safeFlags);\n } catch {\n return null;\n }\n}\n\n/** At least `minSelected` entries chosen in a multi-value control. */\nfunction minSelectedValidator(min: number): ValidatorFn {\n return control => {\n const value = control.value;\n const count = Array.isArray(value) ? value.length : value == null || value === '' ? 0 : 1;\n return count >= min ? null : { minSelected: { required: min, actual: count } };\n };\n}\n\n/** Value must differ from `expected`. */\nfunction notEqualValidator(expected: unknown): ValidatorFn {\n return control => (control.value === expected ? { notEqual: { disallowed: expected } } : null);\n}\n\n/** Every selected file is at or under `bytes`. */\nfunction fileSizeValidator(bytes: number): ValidatorFn {\n return control => {\n const files = Array.isArray(control.value) ? (control.value as File[]) : [];\n const tooBig = files.filter(file => file instanceof File && file.size > bytes);\n return tooBig.length ? { fileSize: { max: bytes, files: tooBig.map(file => file.name) } } : null;\n };\n}\n\n/**\n * One `accept` entry against one file: an extension, an exact MIME type, or a `type/*` wildcard.\n *\n * The wildcard is not a nicety. `sce-file-upload-zone` has always honoured `image/*`, so a\n * definition written with it let the user pick a PNG, accepted it into the control — and then\n * this validator marked the control invalid, because it compared `'image/png' === 'image/*'`.\n * The file was allowed in and made the form unsubmittable, with an error naming a type the file\n * plainly was. The two checks have to agree.\n */\nfunction fileMatches(file: File, entry: string): boolean {\n if (entry.startsWith('.')) {\n return file.name.toLowerCase().endsWith(entry);\n }\n const type = file.type.toLowerCase();\n return entry.endsWith('/*') ? type.startsWith(entry.slice(0, -1)) : type === entry;\n}\n\n/** Every selected file matches one of the accepted extensions or MIME types. */\nfunction fileTypeValidator(accept: readonly string[]): ValidatorFn {\n const normalized = accept.map(entry => entry.trim().toLowerCase()).filter(Boolean);\n return control => {\n const files = Array.isArray(control.value) ? (control.value as File[]) : [];\n const rejected = files.filter(file => file instanceof File && !normalized.some(entry => fileMatches(file, entry)));\n return rejected.length ? { fileType: { accept: normalized, files: rejected.map(file => file.name) } } : null;\n };\n}\n\n/**\n * The accepted types, from either shape a definition writes them in.\n *\n * An array is the schema's own form. A comma-separated string is the **HTML `accept` attribute**,\n * which is what `sce-file-upload-zone` takes and what `fromLegacyConfig` carries across from a\n * legacy config — so a definition written that way is not malformed, it is written the way the\n * widget is. Accepting only the array made `resolveNamedValidator` return `null`, and an\n * unresolved validator is not a validator that fails: it is one that never runs. The field\n * advertised `.pdf,.png,.jpg`, accepted an `.exe`, and submitted valid.\n */\nfunction acceptParam(params: Readonly<Record<string, unknown>> | undefined): string[] {\n const accept = params?.['accept'];\n const entries = Array.isArray(accept) ? accept : typeof accept === 'string' ? accept.split(',') : [];\n // Empties are dropped here rather than inside the validator, so that a param carrying nothing\n // usable — `''`, or `','` — resolves to no validator at all instead of to one that rejects\n // every file for not matching a type nobody named.\n return entries.filter((entry): entry is string => typeof entry === 'string' && entry.trim() !== '');\n}\n\n/** `YYYY-MM-DD` — the shape `sce-date-field` emits and every date bound in a definition is written in. */\nconst DATE_ONLY = /^\\d{4}-\\d{2}-\\d{2}$/;\n\n/**\n * Orders a value against a date bound: negative before, zero same, positive after.\n *\n * A date-only bound is compared by **calendar day**, not by instant. Comparing timestamps meant\n * `max: '2026-08-21'` parsed as midnight UTC while a value of `2026-08-21T14:00` parsed as local\n * time that afternoon — so the last day the bound permits rejected every answer given on it. The\n * user is told the date is too late while looking at the date they were told to use.\n *\n * `null` when either side cannot be read. A bound nobody can parse must not fail every value,\n * and an unparseable value is a different validator's complaint.\n */\nfunction compareToDateBound(value: unknown, bound: string): number | null {\n const text = String(value);\n if (DATE_ONLY.test(bound)) {\n const day = text.slice(0, 10);\n if (DATE_ONLY.test(day)) {\n return Math.sign(day.localeCompare(bound));\n }\n }\n const left = new Date(text).getTime();\n const right = new Date(bound).getTime();\n return Number.isNaN(left) || Number.isNaN(right) ? null : Math.sign(left - right);\n}\n\n/** A date at or after `dateMin`. */\nfunction dateMinValidator(min: string): ValidatorFn {\n return control => {\n if (!control.value) {\n return null;\n }\n const order = compareToDateBound(control.value, min);\n return order === null || order >= 0 ? null : { dateMin: { min } };\n };\n}\n\n/** A date at or before `dateMax`. */\nfunction dateMaxValidator(max: string): ValidatorFn {\n return control => {\n if (!control.value) {\n return null;\n }\n const order = compareToDateBound(control.value, max);\n return order === null || order <= 0 ? null : { dateMax: { max } };\n };\n}\n\n/** Validators that take no parameters, resolved by name alone. */\nconst ZERO_ARG: Readonly<Partial<Record<NamedValidatorName, () => ValidatorFn>>> = {\n required: () => Validators.required,\n requiredTrue: () => Validators.requiredTrue,\n email: () => Validators.email,\n saudiId: saudiIdValidator,\n iqama: iqamaValidator,\n saudiMobile05: saudiMobile05Validator,\n iban: ibanValidator,\n vat: vatNumberValidator,\n cr: crNumberValidator,\n shortAddress: shortAddressValidator,\n};\n\n/**\n * Resolves one named validator, or `null` when its parameters are missing or unusable.\n *\n * Returning `null` rather than throwing is deliberate: a definition with a malformed `min` should\n * render the form without that one check, not blank the screen. Callers that need to know use\n * {@link resolveNamedValidators}, which reports what it could not build.\n */\nexport function resolveNamedValidator(validator: NamedValidator): ValidatorFn | null {\n const zeroArg = ZERO_ARG[validator.name];\n if (zeroArg) {\n return zeroArg();\n }\n\n const { name, params } = validator;\n switch (name) {\n case 'min': {\n const min = numberParam(params, 'min');\n return min === null ? null : Validators.min(min);\n }\n case 'max': {\n const max = numberParam(params, 'max');\n return max === null ? null : Validators.max(max);\n }\n case 'minLength': {\n const min = numberParam(params, 'minLength');\n return min === null ? null : Validators.minLength(min);\n }\n case 'maxLength': {\n const max = numberParam(params, 'maxLength');\n return max === null ? null : Validators.maxLength(max);\n }\n case 'pattern': {\n const pattern = patternParam(params);\n return pattern === null ? null : Validators.pattern(pattern);\n }\n case 'minSelected': {\n const min = numberParam(params, 'min');\n return min === null ? null : minSelectedValidator(min);\n }\n case 'notEqual':\n return params && 'value' in params ? notEqualValidator(params['value']) : null;\n case 'fileSize': {\n const bytes = numberParam(params, 'bytes');\n return bytes === null ? null : fileSizeValidator(bytes);\n }\n case 'fileType': {\n const accept = acceptParam(params);\n return accept.length ? fileTypeValidator(accept) : null;\n }\n case 'dateMin': {\n const min = params?.['min'];\n return typeof min === 'string' ? dateMinValidator(min) : null;\n }\n case 'dateMax': {\n const max = params?.['max'];\n return typeof max === 'string' ? dateMaxValidator(max) : null;\n }\n default:\n return null;\n }\n}\n\n/** Resolves a list of named validators, reporting the names that could not be built. */\nexport function resolveNamedValidators(validators: readonly NamedValidator[] = []): {\n readonly fns: ValidatorFn[];\n readonly unresolved: NamedValidatorName[];\n} {\n const fns: ValidatorFn[] = [];\n const unresolved: NamedValidatorName[] = [];\n for (const validator of validators) {\n const fn = resolveNamedValidator(validator);\n if (fn) {\n fns.push(fn);\n } else {\n unresolved.push(validator.name);\n }\n }\n return { fns, unresolved };\n}\n","import {\n FormArray,\n FormControl,\n FormGroup,\n NonNullableFormBuilder,\n Validators,\n type ValidatorFn,\n} from '@angular/forms';\nimport {\n isFormArrayNode,\n isFormField,\n isFormGroupNode,\n type FormArrayNode,\n type FormDefinition,\n type FormField,\n type FormNode,\n} from '@moatamed-sce/form-schema';\nimport { coerceValue, typeFallback } from './coerce-value';\nimport { evaluateRules, fieldPaths, type FieldRuleState, type RuleState } from './evaluate-rules';\nimport { resolveNamedValidators } from './named-validators';\n\n/**\n * Builds the `FormGroup` a definition describes.\n *\n * Three decisions here are the ones that bite if they are made the other way:\n *\n * - **Hidden fields still get a control.** They are `disable()`d rather than omitted, so\n * `getRawValue()` still carries their key and a rule can reveal one without rebuilding the\n * group and losing everything the user has typed. A hidden control that is merely absent is\n * how a conditional field ends up blocking submit with an error nobody can see.\n * - **`emitEvent: false` on every disable.** Toggling enablement during a `valueChanges`\n * handler otherwise re-enters the rule pass, and the second pass sees a half-applied state.\n * - **Requirement is reconciled, never toggled.** Each pass recomputes it from the rules and\n * the definition together, so a field a rule un-required becomes required again the moment\n * the condition stops matching.\n */\n\n/** Everything the renderer needs after a build: the group, and what could not be resolved. */\nexport interface BuiltForm {\n readonly group: FormGroup;\n /** Validator names present in the definition that the engine could not resolve. Empty on a clean build. */\n readonly unresolvedValidators: readonly string[];\n}\n\nfunction fieldValidators(field: FormField): { fns: ValidatorFn[]; unresolved: string[] } {\n const { fns, unresolved } = resolveNamedValidators(field.validators);\n return { fns, unresolved };\n}\n\n/** True when the definition itself marks a field required, before any rule speaks. */\nfunction isStaticallyRequired(field: FormField): boolean {\n return field.validators?.some(validator => validator.name === 'required') === true;\n}\n\n/**\n * Whether a field is required right now.\n *\n * A rule wins when it has something to say and the definition applies otherwise — which is what\n * makes `unrequire` work at all. Toggling instead of reconciling would leave a field that a rule\n * un-required stuck that way after the condition stopped matching.\n */\nfunction isRequiredNow(field: FormField, ruleState: FieldRuleState | undefined): boolean {\n return ruleState?.required ?? isStaticallyRequired(field);\n}\n\n/**\n * Adds or removes `Validators.required` to match the rules, leaving every other validator alone.\n *\n * `require` and `unrequire` were evaluated and then dropped on the floor: `evaluateRules` wrote\n * the flag into its state map and no one read it, so a definition saying \"when the answer is\n * yes, require the follow-up\" produced a form where the follow-up was never required. It looked\n * right — the renderer draws its asterisk from the same flag — and submitted empty.\n *\n * Reference identity is what makes this safe to do repeatedly: `Validators.required` is the same\n * function object every time, and `resolveNamedValidator` hands back that exact reference for\n * the `required` name, so adding and removing it cannot disturb a `saudiId` or `maxLength` sharing\n * the control. `emitEvent: false` for the same reason every `disable` here uses it — re-validating\n * inside a `valueChanges` handler otherwise re-enters the rule pass mid-flight.\n */\nfunction syncRequired(control: FormControl, required: boolean): void {\n if (required === control.hasValidator(Validators.required)) {\n return;\n }\n if (required) {\n control.addValidators(Validators.required);\n } else {\n control.removeValidators(Validators.required);\n }\n control.updateValueAndValidity({ emitEvent: false });\n}\n\n/** Resolves a field's starting value: supplied initial → definition default → type fallback. */\nfunction initialValue(field: FormField, initial: Readonly<Record<string, unknown>>): unknown {\n if (Object.prototype.hasOwnProperty.call(initial, field.key)) {\n return coerceValue(field.type, initial[field.key]);\n }\n if (field.defaultValue !== undefined && field.defaultValue !== null) {\n return coerceValue(field.type, field.defaultValue);\n }\n return typeFallback(field.type);\n}\n\nfunction buildField(\n field: FormField,\n path: string,\n initial: Readonly<Record<string, unknown>>,\n state: RuleState,\n fb: NonNullableFormBuilder,\n unresolved: string[]\n): FormControl {\n const { fns, unresolved: missing } = fieldValidators(field);\n unresolved.push(...missing);\n\n const control = fb.control(initialValue(field, initial), { validators: fns });\n const ruleState = state.get(path);\n\n syncRequired(control, isRequiredNow(field, ruleState));\n\n if (ruleState?.hidden || ruleState?.disabled || ruleState?.readonly || field.type === 'display') {\n control.disable({ emitEvent: false });\n }\n\n return control;\n}\n\n/**\n * Builds one repeater row: a group of the array node's fields, stated for *that* row.\n *\n * The prefix is the whole point. A row built at prefix `''` looked its state up by bare key, so\n * `state.get('name')` inside a row resolved to whatever *top-level* field happened to be called\n * `name` — a partner's name disabled because an unrelated question shared its key. Passing\n * `partners.0` down means every lookup addresses the control it is actually building, and a\n * rule that resolved per row reaches it.\n */\nfunction buildRow(\n node: FormArrayNode,\n rowPath: string,\n initial: Readonly<Record<string, unknown>>,\n state: RuleState,\n fb: NonNullableFormBuilder,\n unresolved: string[]\n): FormGroup {\n return fb.group(buildNodes(node.nodes, rowPath, initial, state, fb, unresolved));\n}\n\n/**\n * Builds a row for an existing repeater, so a consumer can append one.\n *\n * Exported because `addArrayRow` has to produce a row indistinguishable from the ones the\n * initial build produced — a second implementation would drift the moment a field type gained a\n * coercion rule.\n *\n * A fresh row carries the definition's static state only. Rule state cannot be known here: the\n * row does not exist in the values yet, so there is nothing for a condition to read. The caller\n * settles it by running {@link applyRuleState} once the row is in the array, which\n * {@link addArrayRow} documents as the step that must follow.\n */\nexport function buildArrayRow(\n node: FormArrayNode,\n initial: Readonly<Record<string, unknown>>,\n fb: NonNullableFormBuilder,\n rowPath = ''\n): FormGroup {\n // Unresolved names are discarded: the row's validators are the same set the definition\n // declares, which `buildFormGroup` already reported when it built the form.\n return buildRow(node, rowPath, initial, staticRowState(node, rowPath), fb, []);\n}\n\n/**\n * A row's state before any rule speaks: what the fields themselves declare.\n *\n * Without this a row added by the user starts every `hiddenByDefault` field visible and every\n * statically-disabled one editable, until the next rule pass corrects it — a flash of controls\n * the definition says are not there, on a row the user just created and is looking at.\n */\nfunction staticRowState(node: FormArrayNode, rowPath: string): RuleState {\n const state = new Map<string, FieldRuleState>();\n const walk = (nodes: readonly FormNode[], prefix: string): void => {\n for (const inner of nodes) {\n const path = prefix ? `${prefix}.${inner.key}` : inner.key;\n if (isFormField(inner)) {\n state.set(path, {\n hidden: inner.hiddenByDefault === true,\n disabled: inner.props?.['disabled'] === true,\n readonly: inner.props?.['readonly'] === true,\n });\n } else if (isFormGroupNode(inner)) {\n // Positively narrowed rather than \"not an array\": a double negative treats anything\n // unrecognised as a group and reads `.nodes` off it, which throws on the first node\n // shape that is neither.\n walk(inner.nodes, path);\n }\n }\n };\n walk(node.nodes, rowPath);\n return state;\n}\n\nfunction buildNodes(\n nodes: readonly FormNode[],\n prefix: string,\n initial: Readonly<Record<string, unknown>>,\n state: RuleState,\n fb: NonNullableFormBuilder,\n unresolved: string[]\n): Record<string, FormControl | FormGroup | FormArray> {\n const controls: Record<string, FormControl | FormGroup | FormArray> = {};\n\n for (const node of nodes) {\n const path = prefix ? `${prefix}.${node.key}` : node.key;\n\n if (isFormField(node)) {\n controls[node.key] = buildField(node, path, initial, state, fb, unresolved);\n continue;\n }\n\n if (isFormArrayNode(node)) {\n const rows = Array.isArray(initial[node.key]) ? (initial[node.key] as Record<string, unknown>[]) : [];\n // A minItems array with no data still renders its required rows, so the user sees the\n // shape of what is being asked for rather than an empty list with an add button.\n const rowCount = Math.max(rows.length, node.minItems ?? 0);\n const array = fb.array(\n Array.from({ length: rowCount }, (_, index) =>\n buildRow(node, `${path}.${index}`, rows[index] ?? {}, state, fb, unresolved)\n )\n );\n controls[node.key] = array;\n continue;\n }\n\n const nested = (initial[node.key] ?? {}) as Record<string, unknown>;\n controls[node.key] = fb.group(buildNodes(node.nodes, path, nested, state, fb, unresolved));\n }\n\n return controls;\n}\n\n/** Builds a typed, non-nullable `FormGroup` from a definition and its initial values. */\nexport function buildFormGroup(\n definition: FormDefinition,\n initial: Readonly<Record<string, unknown>>,\n fb: NonNullableFormBuilder\n): BuiltForm {\n const state = evaluateRules(definition, initial);\n const unresolved: string[] = [];\n const controls: Record<string, FormControl | FormGroup | FormArray> = {};\n\n for (const page of definition.pages) {\n Object.assign(controls, buildNodes(page.nodes, '', initial, state, fb, unresolved));\n }\n\n return { group: fb.group(controls), unresolvedValidators: unresolved };\n}\n\n/**\n * Re-applies rule state to an existing group after a value change.\n *\n * Rebuilding the group instead would discard `touched`, `dirty` and focus — which is exactly\n * what users report as \"the form reset itself while I was typing\".\n */\nexport function applyRuleState(definition: FormDefinition, group: FormGroup): RuleState {\n const values = group.getRawValue() as Record<string, unknown>;\n const state = evaluateRules(definition, values);\n // Expanded against the same values the rules were evaluated with, so a row's fields are in the\n // map. Walking the definition alone would leave every `partners.0.name` unmatched, and the\n // loop below skips what it cannot name — the row would keep whatever state it was built with.\n const fields = new Map(fieldPaths(definition, values).map(({ field, path }) => [path, field]));\n\n for (const [path, fieldState] of state) {\n const control = group.get(path);\n if (!control) {\n continue;\n }\n const field = fields.get(path);\n // A display field is never editable, so a rule that merely un-hides it must not hand the\n // user a live control — nor let its (absent) value re-enter the payload.\n const shouldDisable = fieldState.hidden || fieldState.disabled || fieldState.readonly || field?.type === 'display';\n\n // Requirement is reconciled against the definition on every pass, not toggled: a field a\n // rule un-required has to become required again when the condition stops matching.\n if (field && control instanceof FormControl) {\n syncRequired(control, isRequiredNow(field, fieldState));\n }\n\n if (shouldDisable && control.enabled) {\n control.disable({ emitEvent: false });\n } else if (!shouldDisable && control.disabled) {\n control.enable({ emitEvent: false });\n }\n }\n\n return state;\n}\n\n/**\n * The values a submit should carry.\n *\n * Hidden fields are omitted rather than sent as empty: a conditional branch the user never saw\n * should not appear in the payload at all, which is different from appearing as `\"\"`.\n */\nexport function pickActiveValues(\n definition: FormDefinition,\n group: FormGroup,\n state: RuleState\n): Record<string, unknown> {\n const raw = group.getRawValue() as Record<string, unknown>;\n\n const prune = (\n nodes: readonly FormNode[],\n values: Record<string, unknown>,\n prefix: string\n ): Record<string, unknown> => {\n const out: Record<string, unknown> = {};\n\n for (const node of nodes) {\n const path = prefix ? `${prefix}.${node.key}` : node.key;\n\n if (isFormField(node)) {\n if (!state.get(path)?.hidden) {\n out[node.key] = values[node.key];\n }\n continue;\n }\n\n if (isFormArrayNode(node)) {\n const rows = Array.isArray(values[node.key]) ? (values[node.key] as Record<string, unknown>[]) : [];\n // Each row prunes against its own indexed prefix. Pruning at `''` looked every row field\n // up by bare key, so a row's `name` was dropped from the payload whenever an unrelated\n // top-level `name` happened to be hidden.\n out[node.key] = rows.map((row, index) => prune(node.nodes, row ?? {}, `${path}.${index}`));\n continue;\n }\n\n // A group is kept even when empty: its key is part of the payload shape the API expects,\n // and an absent group reads as \"not submitted\" rather than \"nothing was asked here\".\n out[node.key] = prune(node.nodes, (values[node.key] ?? {}) as Record<string, unknown>, path);\n }\n\n return out;\n };\n\n const out: Record<string, unknown> = {};\n for (const page of definition.pages) {\n Object.assign(out, prune(page.nodes, raw, ''));\n }\n return out;\n}\n\n/**\n * A signature of everything about a definition that requires a *rebuild* rather than a patch.\n *\n * Options are deliberately excluded. Including them meant every lookup fetch changed the\n * signature, rebuilt the group and wiped whatever the user had already typed — options change\n * what a select offers, never the shape of the control holding it. Keys are sorted so that two\n * definitions differing only in property order produce the same signature.\n */\nexport function structureSignature(definition: FormDefinition): string {\n const parts: string[] = [];\n const walk = (nodes: readonly FormNode[], prefix: string): void => {\n for (const node of nodes) {\n const path = prefix ? `${prefix}.${node.key}` : node.key;\n if (isFormField(node)) {\n const validators = (node.validators ?? [])\n .map(validator => `${validator.name}(${stableStringify(validator.params)})`)\n .sort()\n .join(',');\n // `hiddenByDefault` and a static `disabled` both decide whether the control is built\n // enabled, so a definition that flips either has to rebuild rather than wait for the\n // next value change to notice.\n const flags = `${node.hiddenByDefault ? 'h' : ''}${node.props?.['disabled'] === true ? 'd' : ''}`;\n parts.push(`${path}:${node.type}:${validators}:${flags}`);\n } else if (isFormArrayNode(node)) {\n // The bounds are structural: `minItems` decides how many rows a fresh build seeds, so a\n // definition raising it must rebuild or the rows it now requires never appear.\n parts.push(`${path}:array:${node.minItems ?? ''}:${node.maxItems ?? ''}`);\n walk(node.nodes, path);\n } else {\n parts.push(`${path}:${node.kind}`);\n walk(node.nodes, path);\n }\n }\n };\n for (const page of definition.pages) {\n walk(page.nodes, '');\n }\n return parts.join('|');\n}\n\n/** `JSON.stringify` with sorted keys, so property order cannot change the result. */\nfunction stableStringify(value: unknown): string {\n if (value === undefined) {\n return '';\n }\n if (value === null || typeof value !== 'object') {\n return JSON.stringify(value) ?? '';\n }\n if (Array.isArray(value)) {\n return `[${value.map(stableStringify).join(',')}]`;\n }\n const entries = Object.entries(value as Record<string, unknown>).sort(([a], [b]) => a.localeCompare(b));\n return `{${entries.map(([key, entry]) => `${key}:${stableStringify(entry)}`).join(',')}}`;\n}\n","import { FormArray, FormGroup, type NonNullableFormBuilder } from '@angular/forms';\nimport {\n isFormArrayNode,\n isFormGroupNode,\n type FormArrayNode,\n type FormDefinition,\n type FormNode,\n} from '@moatamed-sce/form-schema';\nimport { buildArrayRow } from './build-form-group';\n\n/**\n * Growing and shrinking a repeater.\n *\n * `buildFormGroup` already produces a `FormArray` for an `array` node and seeds it to `minItems`,\n * and there it stopped: nothing could add a row or take one away, so a repeater rendered a fixed\n * number of rows forever and `maxItems` described a limit nothing enforced. The capability was\n * half-built, which is worse than absent — a definition could declare `minItems: 1, maxItems: 5`\n * and get neither.\n *\n * Both bounds are enforced here rather than as validators on the array. A validator would let the\n * user delete the last row and *then* tell them the form is invalid; refusing the removal keeps\n * the form in a state the definition allows at every moment, and lets the renderer disable the\n * button instead of rendering an error. {@link canAddArrayRow} and {@link canRemoveArrayRow} are\n * that button's enabled state.\n *\n * Nothing throws. A path that names no repeater is an authoring mistake in the caller, and it is\n * reported the way the rest of the engine reports one — in the result, with the form untouched.\n *\n * **Run `applyRuleState` after any change here.** Row state is keyed by index, so removing row 0\n * makes what was row 1 into row 0 and every state below the cut is now describing its neighbour\n * — a hidden field reappears one row up. A new row likewise has only its static state until a\n * rule pass reads the values it was seeded with. Callers driven by a value-change effect get\n * this for free, because both operations move `getRawValue()`.\n */\n\n/** Why a row could not be added or removed. */\nexport type ArrayRowRefusal =\n /** The path names no `array` node, or the group holds no `FormArray` there. */\n | 'no-such-array'\n /** Already at `maxItems`. */\n | 'at-max'\n /** Already at `minItems`. */\n | 'at-min'\n /** The index is outside the rows that exist. */\n | 'no-such-row';\n\n/** What happened to the repeater. */\nexport interface ArrayRowResult {\n readonly changed: boolean;\n /** Row count after the attempt — unchanged when `changed` is false. */\n readonly rows: number;\n /** Set when `changed` is false. */\n readonly refused?: ArrayRowRefusal;\n}\n\n/**\n * The `array` node a control path names.\n *\n * Arrays nested inside arrays are not walked: their controls are indexed (`partners.0.phones`),\n * and v1 has no way to address one. A definition that nests them still builds — only this lookup\n * declines to find the inner one.\n */\nexport function arrayNodeAt(definition: FormDefinition, path: string): FormArrayNode | undefined {\n let byKey: FormArrayNode | undefined;\n\n const walk = (nodes: readonly FormNode[], prefix: string): FormArrayNode | undefined => {\n for (const node of nodes) {\n const at = prefix ? `${prefix}.${node.key}` : node.key;\n if (isFormArrayNode(node)) {\n if (at === path) {\n return node;\n }\n // A repeater inside a group is declared at `applicant.partners` but a renderer that\n // flattens groups holds its control at `partners`. Remembered rather than returned, so\n // an exact path always wins over a bare key that happens to match deeper.\n if (node.key === path) {\n byKey ??= node;\n }\n continue;\n }\n if (isFormGroupNode(node)) {\n const found = walk(node.nodes, at);\n if (found) {\n return found;\n }\n }\n }\n return undefined;\n };\n\n for (const page of definition.pages) {\n const found = walk(page.nodes, '');\n if (found) {\n return found;\n }\n }\n return byKey;\n}\n\n/** The node and control a path names, when both are really a repeater. */\nfunction repeaterAt(\n definition: FormDefinition,\n group: FormGroup,\n path: string\n): { node: FormArrayNode; array: FormArray } | null {\n const node = arrayNodeAt(definition, path);\n const control = group.get(path);\n return node && control instanceof FormArray ? { node, array: control } : null;\n}\n\n/** True when the repeater has room for another row. An absent `maxItems` means no ceiling. */\nexport function canAddArrayRow(definition: FormDefinition, group: FormGroup, path: string): boolean {\n const repeater = repeaterAt(definition, group, path);\n if (!repeater) {\n return false;\n }\n return repeater.node.maxItems === undefined || repeater.array.length < repeater.node.maxItems;\n}\n\n/** True when a row can be taken away without dropping below `minItems`. */\nexport function canRemoveArrayRow(definition: FormDefinition, group: FormGroup, path: string): boolean {\n const repeater = repeaterAt(definition, group, path);\n if (!repeater) {\n return false;\n }\n return repeater.array.length > (repeater.node.minItems ?? 0);\n}\n\n/**\n * Appends a row, seeded from `initial` where it has values for the row's fields.\n *\n * The row is built by the same code that built the ones already there, so a field's coercion and\n * validators cannot drift between \"was in the initial data\" and \"was added by the user\".\n */\nexport function addArrayRow(\n definition: FormDefinition,\n group: FormGroup,\n path: string,\n fb: NonNullableFormBuilder,\n initial: Readonly<Record<string, unknown>> = {}\n): ArrayRowResult {\n const repeater = repeaterAt(definition, group, path);\n if (!repeater) {\n return { changed: false, rows: 0, refused: 'no-such-array' };\n }\n\n const { node, array } = repeater;\n if (node.maxItems !== undefined && array.length >= node.maxItems) {\n return { changed: false, rows: array.length, refused: 'at-max' };\n }\n\n array.push(buildArrayRow(node, initial, fb, `${path}.${array.length}`));\n return { changed: true, rows: array.length };\n}\n\n/**\n * Removes one row.\n *\n * A missing row is reported before the `minItems` check, so a stale index from a double click\n * does not come back as \"you cannot remove any more rows\" — which would be a lie the user would\n * act on.\n */\nexport function removeArrayRow(\n definition: FormDefinition,\n group: FormGroup,\n path: string,\n index: number\n): ArrayRowResult {\n const repeater = repeaterAt(definition, group, path);\n if (!repeater) {\n return { changed: false, rows: 0, refused: 'no-such-array' };\n }\n\n const { node, array } = repeater;\n if (!Number.isInteger(index) || index < 0 || index >= array.length) {\n return { changed: false, rows: array.length, refused: 'no-such-row' };\n }\n if (array.length <= (node.minItems ?? 0)) {\n return { changed: false, rows: array.length, refused: 'at-min' };\n }\n\n array.removeAt(index);\n return { changed: true, rows: array.length };\n}\n","import { InjectionToken } from '@angular/core';\nimport { of, type Observable } from 'rxjs';\nimport type { DataSourceRef, FormDefinition, I18nText } from '@moatamed-sce/form-schema';\n\n/**\n * Where a select's options come from at runtime.\n *\n * A definition can already say `{ type: 'lookup', lookupKey: 'cities' }`, and until now nothing\n * turned that into options — `formDefinitionToConfig` renders an empty list and says so in a\n * comment. This is the seam that closes it, and the shape of the seam is the whole point:\n *\n * - **The engine never fetches.** It is `type:core` and must not know `HttpClient` exists. A\n * feature implements this interface over whatever it already uses — `LookupApiService` here\n * returns promises, so `from()` is the adapter — and provides it at the route.\n * - **A lookup is a key, never a URL.** Enforced at the schema boundary already; restated here\n * because the port is the place an endpoint would otherwise sneak back in. A host maps keys\n * it recognises and refuses the rest, so a definition from an API cannot make the app fetch\n * from an arbitrary origin.\n * - **Only the declared dependency is passed.** A dependent dropdown needs its parent's value\n * and nothing else. Handing the resolver the whole value record would send every answer the\n * user has typed — a national ID, a salary — to whichever service happens to serve city\n * names.\n * - **Static sources never reach the port.** They are data on the document; routing them\n * through an injected service would make a form that renders perfectly offline fail because\n * a provider was missing.\n */\n\n/** One option a select-like field offers. Mirrors the shape a static `DataSourceRef` carries. */\nexport interface FormOption {\n readonly value: string;\n readonly label: I18nText;\n}\n\n/** The control a dependent source reads, and what it currently holds. */\nexport interface FormDataSourceDependency {\n /** Control key named by `DataSourceRef.dependsOn`. */\n readonly field: string;\n readonly value: unknown;\n}\n\n/** What the host is asked to resolve. */\nexport interface FormDataSourceRequest {\n /** The definition's `lookupKey` — a key the host maps to an endpoint, never a URL. */\n readonly lookupKey: string;\n /** The definition asking, so a host serving several forms can scope caching or permissions. */\n readonly definitionId: string;\n /** Present only when the source declares `dependsOn`. */\n readonly dependsOn?: FormDataSourceDependency;\n}\n\n/** The port a feature implements so the engine never has to know about HTTP. */\nexport interface FormDataSource {\n options(request: FormDataSourceRequest): Observable<readonly FormOption[]>;\n}\n\n/**\n * Provided in **features**, never in `ui-components`.\n *\n * The renderer injects it `{ optional: true }`: a form built entirely from static sources has\n * no reason to force every host that renders one to supply a resolver.\n */\nexport const FORM_DATA_SOURCE = new InjectionToken<FormDataSource>('sce.form-engine.dataSource');\n\n/** The outcome of resolving one field's data source. */\nexport interface ResolvedDataSource {\n /** Options as they arrive. Emits once and completes for a static source. */\n readonly options$: Observable<readonly FormOption[]>;\n /**\n * Why the list is empty, when it is empty for a reason worth surfacing.\n *\n * Follows `BuiltForm.unresolvedValidators`: the engine reports what it could not do and\n * renders the rest, rather than throwing and blanking a page over one missing dropdown.\n */\n readonly issue?: string;\n}\n\n/** No options, for every case that resolves to nothing. */\nconst NONE: Observable<readonly FormOption[]> = of([]);\n\n/** The source a field's `dataSourceId` names, if the definition declares one. */\nexport function dataSourceById(definition: FormDefinition, id: string | undefined): DataSourceRef | undefined {\n if (!id) {\n return undefined;\n }\n return definition.dataSources?.find(source => source.id === id);\n}\n\n/**\n * A dependency's value is \"set\" when it would pass a `truthy` condition.\n *\n * Same rule as the rule evaluator's `truthy`, deliberately: an empty multi-select has not been\n * answered, so a city list keyed on it must not fetch with an empty region.\n */\nfunction isSet(value: unknown): boolean {\n return Array.isArray(value) ? value.length > 0 : value !== '' && value !== null && value !== undefined;\n}\n\n/** Reads a control value by key, or by dotted path for a field inside a group. */\nfunction readValue(values: Readonly<Record<string, unknown>>, field: string): unknown {\n let current: unknown = values;\n for (const segment of field.split('.')) {\n if (current === null || typeof current !== 'object') {\n return undefined;\n }\n current = (current as Record<string, unknown>)[segment];\n }\n return current;\n}\n\n/**\n * Resolves the options for one data source id.\n *\n * `source` is the injected port, or `null` when the host provided none. Passing it in rather\n * than injecting it here keeps this function callable from a test — and from a mapper — without\n * an injection context.\n */\nexport function resolveDataSource(\n definition: FormDefinition,\n dataSourceId: string | undefined,\n values: Readonly<Record<string, unknown>>,\n source: FormDataSource | null\n): ResolvedDataSource {\n if (!dataSourceId) {\n return { options$: NONE };\n }\n\n const ref = dataSourceById(definition, dataSourceId);\n if (!ref) {\n return { options$: NONE, issue: `\"${dataSourceId}\" names no data source on the definition` };\n }\n\n if (ref.type === 'static') {\n return { options$: of(ref.options ?? []) };\n }\n\n if (!ref.lookupKey) {\n return { options$: NONE, issue: `lookup source \"${ref.id}\" carries no lookupKey` };\n }\n\n if (!source) {\n return { options$: NONE, issue: `lookup \"${ref.lookupKey}\" needs FORM_DATA_SOURCE, which no provider supplied` };\n }\n\n // A dependent source with nothing chosen yet is not an error: the list is empty until the\n // parent is answered, which is exactly what a region/city pair should do on first paint.\n if (ref.dependsOn) {\n const value = readValue(values, ref.dependsOn);\n if (!isSet(value)) {\n return { options$: NONE };\n }\n return {\n options$: source.options({\n lookupKey: ref.lookupKey,\n definitionId: definition.id,\n dependsOn: { field: ref.dependsOn, value },\n }),\n };\n }\n\n return { options$: source.options({ lookupKey: ref.lookupKey, definitionId: definition.id }) };\n}\n\n/**\n * The value that decides whether a source must be re-fetched.\n *\n * A renderer re-resolves a dependent source when this changes and leaves every other source\n * alone — refetching all of them on each keystroke is how a form ends up firing a request per\n * character typed into an unrelated field.\n */\nexport function dataSourceDependencyValue(\n definition: FormDefinition,\n dataSourceId: string | undefined,\n values: Readonly<Record<string, unknown>>\n): unknown {\n const ref = dataSourceById(definition, dataSourceId);\n return ref?.dependsOn ? readValue(values, ref.dependsOn) : undefined;\n}\n","import { FormGroup, type AbstractControl } from '@angular/forms';\nimport type { FormDefinition, FormPage, FormStep, I18nText } from '@moatamed-sce/form-schema';\nimport { fieldPaths } from './evaluate-rules';\n\n/**\n * Wizard steps.\n *\n * `FormDefinition.steps` groups pages under a label, and until now nothing read it: a definition\n * could describe a six-step service journey and the renderer drew all six pages stacked in one\n * scroll. The schema said wizard and the runtime said long form.\n *\n * What lives here is the arithmetic a wizard needs and nothing else — which controls belong to a\n * step, whether that step is answered, how far the user may go. Deliberately no chrome and no\n * current-step state: the stepper is `sce-stepper`, and which step is showing is the host's, so\n * that a wizard driven by a route parameter and one driven by a signal share one notion of\n * \"step 3 is not finished\".\n */\n\n/** Why a definition's steps could not be taken at face value. */\nexport interface FormStepIssue {\n /** The step or page the problem is about. */\n readonly id: string;\n readonly reason: string;\n}\n\n/** One step, resolved against the pages and controls it actually covers. */\nexport interface FormStepView {\n readonly id: string;\n readonly index: number;\n readonly title: I18nText;\n readonly pages: readonly FormPage[];\n /**\n * Control paths this step holds, expanded against the current values.\n *\n * Repeater rows are included — `partners.0.name` — because a step containing a repeater is\n * finished only when the rows the user actually added are.\n */\n readonly paths: readonly string[];\n}\n\n/** Steps as the runtime sees them, with whatever the definition got wrong. */\nexport interface ResolvedSteps {\n readonly steps: readonly FormStepView[];\n readonly issues: readonly FormStepIssue[];\n}\n\n/**\n * Resolves a definition's steps, or falls back to one step per page.\n *\n * The fallback is what makes a step-aware host safe to point at any definition: a form that\n * declares no steps is a one-page-per-step wizard, which for the single-page case is exactly the\n * flat form it already was. A host that had to branch on `definition.steps` being present would\n * end up with two layouts to keep in step.\n *\n * A page no step claims is reported rather than appended. Appending it would invent a step the\n * author never wrote; dropping it in silence would lose the questions on it. The caller has an\n * issues list to render, which is how the rest of this platform reports a document it cannot\n * take literally.\n */\nexport function resolveSteps(\n definition: FormDefinition,\n values: Readonly<Record<string, unknown>> = {}\n): ResolvedSteps {\n const issues: FormStepIssue[] = [];\n const pagesById = new Map(definition.pages.map(page => [page.id, page]));\n const pathsByPage = pagePaths(definition, values);\n\n if (!definition.steps?.length) {\n return {\n steps: definition.pages.map((page, index) => ({\n id: page.id,\n index,\n title: page.title ?? { ar: '', en: '' },\n pages: [page],\n paths: pathsByPage.get(page.id) ?? [],\n })),\n issues,\n };\n }\n\n const claimed = new Set<string>();\n const steps: FormStepView[] = [];\n\n definition.steps.forEach((step: FormStep, index: number) => {\n const pages: FormPage[] = [];\n for (const pageId of step.pageIds) {\n const page = pagesById.get(pageId);\n if (!page) {\n issues.push({ id: step.id, reason: `step names page \"${pageId}\", which the definition does not contain` });\n continue;\n }\n if (claimed.has(pageId)) {\n // Two steps sharing a page means answering it twice and validating it in two places.\n issues.push({ id: step.id, reason: `page \"${pageId}\" is already claimed by an earlier step` });\n continue;\n }\n claimed.add(pageId);\n pages.push(page);\n }\n\n steps.push({\n id: step.id,\n index,\n title: step.title,\n pages,\n paths: pages.flatMap(page => pathsByPage.get(page.id) ?? []),\n });\n });\n\n for (const page of definition.pages) {\n if (!claimed.has(page.id)) {\n issues.push({ id: page.id, reason: 'page belongs to no step, so a stepped render never reaches it' });\n }\n }\n\n return { steps, issues };\n}\n\n/** The control paths each page contributes, expanded for the rows the values carry. */\nfunction pagePaths(\n definition: FormDefinition,\n values: Readonly<Record<string, unknown>>\n): ReadonlyMap<string, string[]> {\n const byPage = new Map<string, string[]>();\n\n for (const page of definition.pages) {\n // One page at a time, so a path can be attributed to the page that declared it. Walking the\n // whole definition would give the paths and lose which page each came from.\n const single: FormDefinition = { ...definition, pages: [page] };\n byPage.set(\n page.id,\n fieldPaths(single, values).map(entry => entry.path)\n );\n }\n\n return byPage;\n}\n\n/**\n * The controls a step holds, skipping paths the group does not have.\n *\n * A missing control is not an error here: a renderer that flattens groups holds `q-5` where the\n * definition says `riyadh.q-5`, and a step asserting on every path would call such a form\n * permanently incomplete.\n */\nexport function stepControls(step: FormStepView, group: FormGroup): AbstractControl[] {\n return step.paths.map(path => group.get(path)).filter((control): control is AbstractControl => control !== null);\n}\n\n/**\n * True when nothing in the step is blocking.\n *\n * Disabled controls are skipped rather than counted valid, because Angular reports a disabled\n * control's `valid` as **false** — a step whose conditional half is currently hidden would never\n * pass, and the Next button would sit dead with no error to explain why.\n *\n * A step holding no controls at all is complete: a page of `display` copy is something the user\n * reads, not something they answer.\n */\nexport function isStepComplete(step: FormStepView, group: FormGroup): boolean {\n return stepControls(step, group).every(control => control.disabled || control.valid);\n}\n\n/** Marks everything in the step touched, so `Next` reveals the errors instead of doing nothing. */\nexport function markStepTouched(step: FormStepView, group: FormGroup): void {\n for (const control of stepControls(step, group)) {\n control.markAllAsTouched();\n }\n}\n\n/**\n * Whether the user may move on from `index`.\n *\n * False on the last step: advancing past the end is a submit, and a wizard that treats it as a\n * step change is how a form gets a seventh page nobody wrote.\n */\nexport function canAdvance(steps: readonly FormStepView[], group: FormGroup, index: number): boolean {\n const step = steps[index];\n return step !== undefined && index < steps.length - 1 && isStepComplete(step, group);\n}\n\n/**\n * The furthest step the user has earned.\n *\n * Every step up to it is complete. This is what a stepper binds its clickable steps to — letting\n * someone jump to step 5 from an unfinished step 2 produces a review page summarising answers\n * that were never given.\n */\nexport function furthestReachableStep(steps: readonly FormStepView[], group: FormGroup): number {\n let reached = 0;\n while (reached < steps.length - 1 && isStepComplete(steps[reached], group)) {\n reached += 1;\n }\n return reached;\n}\n\n/**\n * The first step that is not complete, or `-1` when all of them are.\n *\n * A submit that fails should land the user on the question that failed it, not on step 1 with a\n * toast — this is the index to navigate to.\n */\nexport function firstIncompleteStep(steps: readonly FormStepView[], group: FormGroup): number {\n return steps.findIndex(step => !isStepComplete(step, group));\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["readValue"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@moatamed-sce/form-engine",
3
+ "version": "0.1.5",
4
+ "description": "FormGroup construction, named Saudi validators and rule evaluation for SCE form definitions.",
5
+ "license": "MIT",
6
+ "peerDependencies": {
7
+ "@angular/core": "^21.0.0",
8
+ "@angular/forms": "^21.0.0",
9
+ "@moatamed-sce/core": "^0.1.5",
10
+ "@moatamed-sce/form-schema": "^0.1.5",
11
+ "rxjs": "^7.8.0"
12
+ },
13
+ "dependencies": {
14
+ "tslib": "^2.3.0"
15
+ },
16
+ "publishConfig": {
17
+ "access": "public",
18
+ "registry": "https://registry.npmjs.org"
19
+ },
20
+ "sideEffects": false,
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/sce-platform/fe-sce-marketplace.git",
24
+ "directory": "libs/form-engine"
25
+ },
26
+ "homepage": "https://github.com/sce-platform/fe-sce-marketplace/tree/main/libs/form-engine#readme",
27
+ "bugs": {
28
+ "url": "https://github.com/sce-platform/fe-sce-marketplace/issues"
29
+ },
30
+ "keywords": [
31
+ "sce",
32
+ "angular",
33
+ "forms",
34
+ "validation",
35
+ "saudi"
36
+ ],
37
+ "module": "fesm2022/moatamed-sce-form-engine.mjs",
38
+ "typings": "types/moatamed-sce-form-engine.d.ts",
39
+ "exports": {
40
+ "./package.json": {
41
+ "default": "./package.json"
42
+ },
43
+ ".": {
44
+ "types": "./types/moatamed-sce-form-engine.d.ts",
45
+ "default": "./fesm2022/moatamed-sce-form-engine.mjs"
46
+ }
47
+ },
48
+ "type": "module"
49
+ }