Shared schema definitions for the FormFiller application. Provides TypeScript types and JSON Schema validation for frontend, backend, and embed packages.
- FieldConfig: Field configurations (text, number, date, dropdown, htmleditor, etc.)
- ItemConfig: View configurations (grid, tree, form)
- ValidationRule: DevExtreme-compatible validation rules
- SchemaValidator: Multi-level validation with caching
This package is a core dependency for multiple FormFiller repositories:
flowchart TB
subgraph schema [formfiller-schema]
INTS["src/interfaces/index.ts<br/>TypeScript interfaces"]
CSCHEMA["dist/schemas/complete-schema.json<br/>JSON Schema"]
end
subgraph libs [Library Packages]
VAL[formfiller-validator]
EMBED[formfiller-embed]
end
subgraph apps [Application Packages]
BE[formfiller-backend]
FE[formfiller-frontend]
end
INTS --> VAL
INTS --> EMBED
INTS --> BE
INTS --> FE
VAL --> EMBED
VAL --> BE
VAL --> FE
CSCHEMA --> BE
CSCHEMA --> FE
Build order for libraries:
formfiller-types → formfiller-schema → formfiller-validator → formfiller-embed
| Repository | TypeScript Interfaces Used | complete-schema.json Usage |
|---|---|---|
| formfiller-frontend | FieldConfig, ViewConfig, ValidationRule, FieldType, LookupConfig |
Monaco editor IntelliSense in ConfigJSONEditor.tsx |
| formfiller-backend | ItemConfig, FormPreferences, FieldConfig, ValidationRule |
AJV runtime validation in configValidator.ts |
| formfiller-embed | ViewConfig, FieldConfig, FormPreferences, ValidationRuleOrGroup |
Not used directly |
| formfiller-validator | ValidationRule, FieldConfig, ConditionalExpression, ComputedRule, CrossFieldType |
Not used directly |
Frontend (Monaco IntelliSense):
// TypeScript types
import { FieldConfig, ViewConfig } from 'formfiller-schema';
// JSON Schema for Monaco editor
import completeSchemaRaw from 'formfiller-schema/dist/schemas/complete-schema.json';Backend (AJV Validation):
// TypeScript types
import { ItemConfig, FieldConfig } from 'formfiller-schema';
// Schema for AJV validation
import { schemas } from 'formfiller-schema';
const { completeSchema } = schemas;Validator/Embed (Types only):
import { ValidationRule, ConditionalExpression } from 'formfiller-schema';npm install github:LowCoders/formfiller-schemaFor local development, use formfiller-dev-setup which symlinks all packages together:
cd /var/www/formfiller-dev-setup
./deploy.sh
cd /var/www
npm install
npm run build:libsflowchart TD
subgraph source [Source - Single Source of Truth]
TS[src/interfaces/index.ts]
end
subgraph build [npm run build]
TSC[tsc compile]
GEN[generate:schema]
TRANS[transform:schema]
MONACO[generate:monaco]
end
subgraph output [Output]
DTS[dist/*.d.ts]
RAW[dist/schemas/raw-schema.json]
COMPLETE[dist/schemas/complete-schema.json]
MTYPES[dist/monaco-types.d.ts]
end
TS --> TSC
TS --> GEN
TSC --> DTS
DTS --> MONACO
GEN --> RAW
RAW --> TRANS
TRANS --> COMPLETE
MONACO --> MTYPES
The npm run build command executes:
- TypeScript compilation - Compiles
src/todist/ - generate:schema - Generates JSON Schema from TypeScript interfaces using
ts-json-schema-generator - transform:schema - Transforms FieldConfig from
anyOftoif/then/allOffor Monaco IntelliSense - generate:monaco - Bundles TypeScript definitions for Monaco editor
| Script | Description |
|---|---|
build |
Full build pipeline (tsc + schema generation + transform + monaco types) |
generate:schema |
Generates JSON Schema from TypeScript interfaces |
transform:schema |
Transforms anyOf to if/then/allOf structure for Monaco |
generate:monaco |
Bundles .d.ts files into monaco-types.d.ts |
build:legacy |
Legacy build using manual schema (fallback) |
test |
Run Jest tests |
Generates JSON Schema from TypeScript interfaces using ts-json-schema-generator:
- Reads
src/interfaces/index.ts - Outputs
dist/schemas/raw-schema.json - Preserves JSDoc comments as descriptions
- Creates
anyOfstructures for union types
Transforms the generated JSON Schema for better Monaco editor IntelliSense:
flowchart LR
subgraph input [Input: anyOf structure]
A[FieldConfig]
A --> B[anyOf]
B --> C[TextFieldConfig]
B --> D[NumberFieldConfig]
B --> E[HtmlEditorFieldConfig]
end
subgraph output [Output: if/then structure]
F[FieldConfig]
F --> G[properties: base props]
F --> H[allOf]
H --> I["if type=text then ..."]
H --> J["if type=number then ..."]
H --> K["if type=htmleditor then ..."]
end
input --> |transform| output
Input (anyOf structure from generator):
{
"FieldConfig": {
"anyOf": [
{ "$ref": "#/definitions/TextFieldConfig" },
{ "$ref": "#/definitions/HtmlEditorFieldConfig" }
]
}
}Output (if/then/allOf structure):
{
"FieldConfig": {
"properties": { /* base properties from BaseFieldConfig */ },
"allOf": [
{
"if": { "properties": { "type": { "const": "htmleditor" } } },
"then": { "properties": { "toolbar": {...}, "mediaResizing": {...} } }
}
]
}
}This allows Monaco to show type-specific properties based on the type field value.
Collects all TypeScript definition files from dist/ and bundles them into a single monaco-types.d.ts file for Monaco editor TypeScript IntelliSense.
flowchart LR
subgraph schema_pkg [formfiller-schema]
SCHEMA[complete-schema.json]
end
subgraph frontend [formfiller-frontend]
EDITOR[ConfigJSONEditor.tsx]
MONACO[Monaco Editor]
end
subgraph features [Features]
F1[Type-specific IntelliSense]
F2[Enum autocomplete]
F3[Validation errors]
end
SCHEMA --> |import| EDITOR
EDITOR --> MONACO
MONACO --> F1
MONACO --> F2
MONACO --> F3
The frontend ConfigJSONEditor.tsx imports the transformed schema:
import completeSchemaRaw from 'formfiller-schema/dist/schemas/complete-schema.json';Key features:
- Type-specific IntelliSense via
if/thenblocks - Enum values for autocomplete (e.g., toolbar item names:
bold,italic,header, etc.) - Validation errors shown in editor
The TypeScript interfaces in src/interfaces/index.ts are the Single Source of Truth. The JSON Schema is automatically generated from them.
- Edit TypeScript types:
src/interfaces/index.ts - Build:
npm run build - Test in Monaco: Restart frontend dev server and verify IntelliSense
flowchart LR
A[1. Add to FieldType enum] --> B[2. Create NewFieldConfig interface]
B --> C["3. Add type: 'yourtype' literal"]
C --> D[4. Add to FieldConfig union]
D --> E[5. npm run build]
E --> F[JSON Schema auto-generated!]
- Add the type to
FieldTypeenum insrc/interfaces/index.ts - Create
NewFieldConfiginterface extendingBaseFieldConfig - Add
type: 'yourtype'literal property to the interface - Add to
FieldConfigunion type - Build and test - JSON Schema is auto-generated!
For Monaco autocomplete to work with enum values:
{
"propertyName": {
"type": "string",
"enum": ["value1", "value2", "value3"],
"description": "Description for IntelliSense"
}
}sequenceDiagram
participant Dev as Developer
participant Schema as formfiller-schema
participant Validator as formfiller-validator
participant Embed as formfiller-embed
participant Apps as backend/frontend
Dev->>Schema: 1. Edit src/interfaces/index.ts
Dev->>Schema: 2. npm run build
Note over Schema: tsc + generate:schema + transform:schema
Dev->>Schema: 3. git commit && git push
alt Local Development - Workspace
Dev->>Validator: 4a. npm run build:validator
Dev->>Embed: 4b. npm run build:embed
Note over Apps: Changes visible via symlinks
else Production - GitHub
Dev->>Apps: 4. npm update formfiller-schema
Dev->>Apps: 5. Restart servers
end
Using formfiller-dev-setup workspace:
# 1. Edit the schema
cd /var/www/formfiller-schema
# ... make changes to src/interfaces/index.ts ...
# 2. Build schema
npm run build
# 3. Rebuild dependent libraries
cd /var/www
npm run build:libs # Builds: types → schema → validator → embed
# 4. Test in apps
# Frontend: refresh browser (Vite hot-reloads)
# Backend: restart if runningFor production environments where packages are installed from GitHub:
Option A: Using sync-dependents.sh (automated)
cd /var/www/formfiller-schema
# Build, commit, push, and update all dependent projects
./sync-dependents.sh
# With options:
DRY_RUN=true ./sync-dependents.sh # Preview only
AUTO_RESTART=true ./sync-dependents.sh # Restart backend automatically
SKIP_PUSH=true ./sync-dependents.sh # Skip git push (local testing)Option B: Manual update
# 1. Build and push schema
cd /var/www/formfiller-schema
npm run build
git add -A && git commit -m "chore: update schema"
git push
# 2. Update dependent projects
cd /var/www/formfiller-backend
npm update formfiller-schema formfiller-validator
npm run build
cd /var/www/formfiller-frontend
npm update formfiller-schema formfiller-validator
# 3. Restart serversThe sync-dependents.sh script automates the schema update process for GitHub-based deployments:
| Step | Action |
|---|---|
| 1 | Build formfiller-schema (npm run build) |
| 2 | Commit and push changes to GitHub |
| 3 | Update backend (npm update formfiller-schema formfiller-validator formfiller-types) |
| 4 | Rebuild backend |
| 5 | Update frontend packages |
| 6 | Verify installation |
Environment Variables:
| Variable | Default | Description |
|---|---|---|
DRY_RUN |
false |
Preview mode - no actual changes |
AUTO_RESTART |
false |
Automatically restart backend server |
SKIP_PUSH |
false |
Skip git push (for local testing) |
import { FieldConfig, ItemConfig } from 'formfiller-schema';
const myField: FieldConfig = {
name: 'description',
label: 'Description',
type: 'htmleditor',
toolbar: {
items: ['bold', 'italic', 'header', 'separator', 'orderedList', 'bulletList']
}
};Full documentation: formfiller-docs
MIT