@sigamix/form-core
v0.3.0
Published
Core form engine — types, condition evaluation, validation, navigation
Readme
@sigamix/form-core
Pure TypeScript form engine — zero external dependencies. The logic core shared by all @sigamix/form-* packages.
Installation
npm install @sigamix/form-coreConcepts
The form hierarchy follows an explicit composition model:
IFormDefinition
└── pages: IFormPage[] ← Navigation units
├── variables: IFormVariable[] ← Input fields
└── rosters: IFormRoster[] ← Pilot-driven sub-sections
└── variables: IFormVariable[]- IFormPage — A navigation step containing fields and rosters
- IFormVariable — A single input field (text, number, date, select, etc.)
- IFormRoster — A repeating section driven by
pilotVariableCode(no add/remove — row count comes from a numeric variable) - IFormDefinition — The top-level form schema containing pages
Rosters are sub-components of pages, never at the same level. The relationship is modeled via composition (IFormPage.rosters), not parentId.
Engines
| Engine | Purpose |
|--------|---------|
| ConditionEngine | Evaluate ${VAR} expressions with 20+ built-in functions, caching, iteration support |
| ValidationEngine | Rule-based validation (required, min, max, pattern, email, url) + ConditionEval |
| NavigationEngine | Page ordering, visibility filtering, instance management, progress tracking |
| FormTree | Centralized visibility and jump management — evaluates all conditions in one pass |
| InstanceManager | Add/remove instances for repeatable pages with min/max constraints |
| DependencyResolver | Inter-variable dependency graph with transitive resolution |
| SchemaValidator | Design-time structural validation of form definitions |
Usage
import {
ConditionEngine,
FormTree,
NavigationEngine,
type IFormDefinition,
type IFormPage,
type IFormVariable,
} from '@sigamix/form-core'
// Define a form
const form: IFormDefinition = {
id: 'demo',
code: 'REGISTRATION',
name: 'Registration Form',
version: '1.0.0',
isPublished: true,
pages: [
{
id: 'p1',
code: 'INFO',
name: 'Personal Information',
order: 0,
isRepeatable: false,
variables: [
{
id: 'v1', code: 'NAME', name: 'Full Name', type: 'text',
order: 0, isRequired: true, isReadonly: false, isHidden: false,
},
{
id: 'v2', code: 'AGE', name: 'Age', type: 'number',
order: 1, isRequired: true, isReadonly: false, isHidden: false,
},
],
rosters: [
{
id: 'r1', code: 'CHILDREN', name: 'Children',
rosterType: 'collection', order: 2,
pilotVariableCode: 'NB_CHILDREN',
variables: [
{
id: 'rv1', code: 'CHILD_NAME', name: 'Child Name', type: 'text',
order: 0, isRequired: true, isReadonly: false, isHidden: false,
},
],
},
],
},
],
}
// Evaluate conditions
const engine = new ConditionEngine({
AGE: { variableCode: 'AGE', value: 25 },
})
engine.evaluate('${AGE} >= 18') // true
engine.evaluate('show(${AGE} < 65)') // true
// Build form tree for visibility
const tree = new FormTree()
tree.build(form, { AGE: { variableCode: 'AGE', value: 25 } })
const visible = tree.getVisibleVariables('INFO')Variable Types
text · textarea · number · date · datetime · time · select · multiselect · checkbox · radio · file · gps · calculated · hidden · label
License
Copyright (c) 2026 AFINOV SARL — All rights reserved. Commercial license required. Contact: [email protected]
