ata-validator
Form validator implementation based on ata-validator JSON schema validator.
Installation
Section titled “Installation”npm i @sjsf-lab/ata-validator ata-validatorpnpm add @sjsf-lab/ata-validator ata-validatoryarn add @sjsf-lab/ata-validator ata-validatorbun add @sjsf-lab/ata-validator ata-validatordeno add @sjsf-lab/ata-validator ata-validatorExample
Section titled “Example”<script lang="ts"> import { ON_INPUT, BasicForm, createForm, ON_CHANGE, ON_ARRAY_CHANGE, getValueSnapshot, } from "@sjsf/form"; import { createFormValidator } from "@sjsf-lab/ata-validator";
import * as defaults from "@/lib/form/defaults";
import { initialValue, schema, uiSchema } from "../shared";
const form = createForm({ ...defaults, schema, uiSchema, validator: createFormValidator, fieldsValidationMode: ON_INPUT | ON_CHANGE | ON_ARRAY_CHANGE, initialValue, });</script>
<BasicForm {form} novalidate />
<pre>{JSON.stringify(getValueSnapshot(form), null, 2)}</pre>import type { Schema, UiSchema } from "@sjsf/form";
export const schema: Schema = { type: "object", properties: { id: { type: "string", minLength: 8, pattern: "^\\d+$", }, active: { type: "boolean", }, skills: { type: "array", minItems: 4, items: { type: "string", minLength: 5, }, }, multipleChoicesList: { type: "array", maxItems: 2, items: { type: "string", enum: ["foo", "bar", "fuzz"], }, }, },};
export const uiSchema: UiSchema = { id: { "ui:options": { title: "Identifier", }, }, active: { "ui:options": { title: "Active", }, }, multipleChoicesList: { "ui:options": { title: "Pick max two items", }, },};
export const initialValue = { id: "Invalid", skills: ["karate", "budo", "aikido"], multipleChoicesList: ["foo", "bar", "fuzz"],} as const;Precompiled validation
Section titled “Precompiled validation”It is possible to use precompiled validator to avoid issues with unsafe-eval
warnings from the browser caused by strict Content Security Policy settings.
Schema precompilation
Section titled “Schema precompilation”The first step in the process is to compile a schema into a set of validate functions.
import fs from "node:fs";import path from "node:path";
import { ON_ARRAY_CHANGE, ON_CHANGE, ON_INPUT } from "@sjsf/form";import { insertSubSchemaIds, fragmentSchema,} from "@sjsf/form/validators/precompile";import { Validator } from "ata-validator";import { DEFAULT_VALIDATOR_OPTIONS, COLOR_FORMAT_REGEX, DATA_URL_FORMAT_REGEX,} from "@sjsf-lab/ata-validator";
import inputSchema from "../../shared/input-schema.json" with { type: "json" };
const fieldsValidationMode = ON_INPUT | ON_CHANGE | ON_ARRAY_CHANGE;
// NOTE: After calling this function, be sure to save the `schema` and// use it to generate the formconst patch = insertSubSchemaIds(inputSchema as any, { fieldsValidationMode,});
// It is easier to save as a TS file// https://github.com/microsoft/TypeScript/issues/32063fs.writeFileSync( path.join(import.meta.dirname, "patched-schema.ts"), `import type { Schema } from "@sjsf/form";export const fieldsValidationMode = ${fieldsValidationMode}export const schema = ${JSON.stringify(patch.schema, null, 2)} as const satisfies Schema;`);
const base = { $schema: "http://json-schema.org/draft-07/schema" };const schemas = fragmentSchema(patch);const bundle = Validator.bundleStandalone( schemas.map((s) => Object.assign(s, base)), { ...DEFAULT_VALIDATOR_OPTIONS, format: "esm" }) .replace( "const validators", `export const [${schemas.map((s) => s.$id).join(", ")}]` ) .slice(0, -50);
fs.writeFileSync( path.join(import.meta.dirname, "validate-functions.js"), `const COLOR_FORMAT_REGEX = ${COLOR_FORMAT_REGEX.toString()};const DATA_URL_FORMAT_REGEX = ${DATA_URL_FORMAT_REGEX.toString()};${bundle}`);{ "title": "User", "type": "object", "required": [ "id", "email", "age", "roles" ], "properties": { "id": { "type": "integer", "minimum": 1 }, "email": { "type": "string", "format": "email" }, "age": { "type": "integer", "minimum": 21, "maximum": 100 }, "roles": { "type": "array", "items": { "type": "string", "enum": [ "admin", "editor", "viewer" ] }, "uniqueItems": true, "minItems": 1 } }, "additionalProperties": false}node compile-schema-script.ts<script lang="ts"> import { BasicForm, createForm, getValueSnapshot } from "@sjsf/form"; import { createFormValidatorFactory } from "@sjsf-lab/ata-validator/precompile"; import { resolver } from "@sjsf/form/resolvers/compat";
import * as defaults from "@/lib/form/defaults";
import { schema, fieldsValidationMode } from "./patched-schema"; import * as validateFunctions from "./validate-functions";
const form = createForm({ ...defaults, schema, validator: createFormValidatorFactory({ validateFunctions }), fieldsValidationMode, resolver, });</script>
<BasicForm {form} novalidate />
<pre>{JSON.stringify(getValueSnapshot(form), null, 2)}</pre>import type { Schema } from "@sjsf/form";export const fieldsValidationMode = 11export const schema = { "title": "User", "type": "object", "required": [ "id", "email", "age", "roles" ], "properties": { "id": { "type": "integer", "minimum": 1, "$id": "v1" }, "email": { "type": "string", "format": "email", "$id": "v2" }, "age": { "type": "integer", "minimum": 21, "maximum": 100, "$id": "v3" }, "roles": { "type": "array", "items": { "type": "string", "enum": [ "admin", "editor", "viewer" ], "$id": "v5" }, "uniqueItems": true, "minItems": 1, "$id": "v4" } }, "additionalProperties": false, "$id": "v0"} as const satisfies Schema;