hyperjump/json-schema
Form validator implementation based on @hyperjump/json-schema.
Installation
Section titled “Installation”npm i @sjsf-lab/hyperjump-validator @hyperjump/json-schemapnpm add @sjsf-lab/hyperjump-validator @hyperjump/json-schemayarn add @sjsf-lab/hyperjump-validator @hyperjump/json-schemabun add @sjsf-lab/hyperjump-validator @hyperjump/json-schemadeno add @sjsf-lab/hyperjump-validator @hyperjump/json-schemaSchema precompilation
Section titled “Schema precompilation”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 { registerSchema, type SchemaObject,} from "@hyperjump/json-schema/draft-07";import { compile, getSchema } from "@hyperjump/json-schema/experimental";import { uneval } from "devalue";
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 formlet id = 0;const toId = (n: number) => `https://example.com/v${n}`;const patch = insertSubSchemaIds(inputSchema as any, { fieldsValidationMode, createId: () => toId(id++),});
// 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 schemas = fragmentSchema(patch);
for (const schema of schemas) { registerSchema( Object.assign( { $schema: "http://json-schema.org/draft-07/schema" }, schema as SchemaObject ) );}
const { ast } = await compile(await getSchema(toId(0)));
fs.writeFileSync( path.join(import.meta.dirname, "ast.ts"), `import type { AST } from "@hyperjump/json-schema/experimental";export const ast = ${uneval(ast)} as unknown as AST`);{ "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/hyperjump-validator/precompile"; import { localization } from "@sjsf-lab/hyperjump-validator/localizations/en-us"; import { resolver } from "@sjsf/form/resolvers/compat"; import "@hyperjump/json-schema/formats-lite"; import "@hyperjump/json-schema/draft-07";
import * as defaults from "@/lib/form/defaults";
import { schema, fieldsValidationMode } from "./patched-schema"; import { ast } from "./ast";
const form = createForm({ ...defaults, schema, validator: createFormValidatorFactory({ ast, localization }), 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": "https://example.com/v1" }, "email": { "type": "string", "format": "email", "$id": "https://example.com/v2" }, "age": { "type": "integer", "minimum": 21, "maximum": 100, "$id": "https://example.com/v3" }, "roles": { "type": "array", "items": { "type": "string", "enum": [ "admin", "editor", "viewer" ], "$id": "https://example.com/v5" }, "uniqueItems": true, "minItems": 1, "$id": "https://example.com/v4" } }, "additionalProperties": false, "$id": "https://example.com/v0"} as const satisfies Schema;