Convert JSON Schema definitions into Angular Signal Forms schema functions.
Requires Angular 21+ — Signal Forms are experimental. See the Angular docs for details.
Borboleta is Portuguese for butterfly — a symbol of transformation. This library transforms JSON Schema definitions into Angular Signal Forms schemas, much like a caterpillar becomes a butterfly. 🦋
npm install @easyware/borboletaPeer dependencies: @angular/core, @angular/common, @angular/forms (all ^21.2.0).
import { signal } from '@angular/core';
import { form } from '@angular/forms/signals';
import { toSignalSchema } from '@easyware/borboleta';
const jsonSchema = {
type: 'object',
required: ['email', 'age'],
properties: {
email: { type: 'string', format: 'email' },
age: { type: 'number', minimum: 18, maximum: 120 },
role: { type: 'string', enum: ['admin', 'user', 'guest'] },
},
};
const model = signal({ email: '', age: 0, role: '' });
const myForm = form(model, toSignalSchema(jsonSchema));This generates the same validators as writing the schema by hand:
const myForm = form(model, (s) => {
required(s.email);
email(s.email);
required(s.age);
min(s.age, 18);
max(s.age, 120);
validate(s.role, ({ value }) => {
const v = value();
if (v != null && v !== '' && !['admin', 'user', 'guest'].includes(v)) {
return { kind: 'enum', message: 'Must be one of: admin, user, guest' };
}
return null;
});
});| JSON Schema | Signal Forms validator |
|---|---|
required |
required() |
enum |
validate() (custom) |
minimum / maximum |
min() / max() |
minLength / maxLength |
minLength() / maxLength() |
pattern |
pattern() |
format: "email" |
email() |
Nested object |
Recursive descent |
items (array) |
applyEach() |
Use composeSchemas() to layer custom validators on top of the generated ones:
import { form, validate, required } from '@angular/forms/signals';
import { toSignalSchema, composeSchemas } from '@easyware/borboleta';
const myForm = form(
model,
composeSchemas(
toSignalSchema(jsonSchema),
(s) => {
// Custom: URL must use HTTPS
validate(s.run.url, ({ value }) => {
if (!value().startsWith('https://')) {
return { kind: 'https', message: 'URL must use HTTPS' };
}
return null;
});
// Custom: conditional required
required(s.monitor.url, {
when: ({ valueOf }) => valueOf(s.monitor.isMonitored),
});
},
),
);Or just call toSignalSchema() inside your own schema function — no utility needed:
const myForm = form(model, (s) => {
toSignalSchema(jsonSchema)(s);
validate(s.run.url, /* ... */);
});Converts a JSON Schema object into an Angular Signal Forms SchemaFn<T>. Pass the result directly to form() or combine it with composeSchemas().
Combines multiple schema functions into one. Each schema is called in order on the same SchemaPathTree, so validators accumulate.
TypeScript interface describing the subset of JSON Schema Draft-07 that Borboleta understands.
npm install # Install dependencies
npm run build # Build the library (output: dist/borboleta/)
npm test # Run tests (Vitest)