@lsolova/json-schema-validator
v0.3.0
Published
JSON schema validator (with Rust WASM based on jsonschema)
Readme
JSON Schema Validator
A JSON schema validator for browser and Node.js environments. It wraps the jsonschema Rust crate as a WebAssembly module, exposing functionality through the SchemaValidator object.
Installation
npm install @lsolova/json-schema-validatorInitialization
You must initialize SchemaValidator first by passing the WASM file to SchemaValidator.init(). The initialization is an async operation and should be done once at application startup.
Validation
SchemaValidator.validate() is asynchronous and returns a Promise<void>. If validation fails, the promise is rejected with a SchemaValidationError object.
type SchemaValidationError = {
error: string | object
} | {
// Key is field name, value is the validation error related to that field
[key: string]: string
}Error handling example
try {
await SchemaValidator.validate(schema, data);
console.log("Validation passed");
} catch (error) {
console.error("Validation failed", error);
}Browser
Browser integration requires the WASM file to be served from your deployment. The WASM file must be copied to your output directory during the build process (see deployment section below).
Basic usage
You can validate by passing either:
- Schema URL: A URL to a remote schema file (HTTP(S) or a relative path)
- Schema content: The schema definition as a JSON object or string
Schemas are automatically cached for the lifetime of the SchemaValidator object, improving validation performance on subsequent calls.
import { SchemaValidator } from "@lsolova/json-schema-validator";
// Initialize once at app startup
async function initValidation(wasmURL: string) {
// wasmURL is the path to the exposed WASM file
await SchemaValidator.init(wasmURL);
// Optionally pre-register schemas to avoid runtime loading
await SchemaValidator.registerSchema("my-schema-id", schemaObject);
}
// Use throughout your app
async function validateData(schema: string | object, data: unknown) {
try {
await SchemaValidator.validate(schema, data);
// Validation passed
} catch (error) {
// Handle validation errors
}
}Schema references
This validator fully supports JSON Schema $ref directives, including HTTP(S) references. Schemas can reference other schemas via URLs or IDs.
{
"$id": "my-schema-id",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"name": {"type": "string"},
"email": {"$ref": "https://example.com/schemas/email.schema.json"}
},
"required": ["name", "email"]
}Performance optimization
Validators generated from schemas with a $id are internally cached. This can significantly improve performance: subsequent validations with the same validator can be 75% faster due to caching.
Security
Although it doesn't use eval, a special Content Security Policy setting is required in high-security environments.
If a script-src directive is set in the Content-Security-Policy header, 'wasm-unsafe-eval' must be added to it. (See MDN documentation for details.)
Content-Security-Policy: ...;script-src your entries 'wasm-unsafe-eval'; ...Node.js
This module runs in Node.js thanks to its native WebAssembly support. It's a pure ESM module and cannot be used with CommonJS.
Setup
Load the WASM file once at application startup before performing any validations:
import { readFile } from "node:fs/promises";
import { SchemaValidator } from "@lsolova/json-schema-validator";
// Initialize at app startup
async function initValidator() {
const wasmBuffer = await readFile(
"./node_modules/@lsolova/json-schema-validator/dist/assets/schema_validator.wasm"
);
await SchemaValidator.init(wasmBuffer);
}
// Use throughout your app
async function validateConfig(data) {
const schemaContent = await readFile("./schema.json", { encoding: "utf8" });
try {
await SchemaValidator.validate(schemaContent, data);
console.log("Valid");
} catch (error) {
console.error("Validation failed:", error);
}
}How it works
Node.js has no window object and this WASM can use Window.fetch only. Therefore in Node environment Reqwest is utilized.
Deployment
The WASM file must be accessible to your application at runtime. The approach depends on your build tool.
Vite
Vite has built-in support for assets by URL. Use the explicit URL import syntax:
import { SchemaValidator } from "@lsolova/json-schema-validator";
import wasmURL from "@lsolova/json-schema-validator/dist/assets/schema_validator.wasm?url";
async function initValidator() {
await SchemaValidator.init(wasmURL);
}The WASM file is automatically processed and included in your build output.
esbuild
TBD
Node.js
For Node.js, pass the WASM as a Buffer to init(). The file location is predictable in node_modules:
import { readFile } from "node:fs/promises";
import { SchemaValidator } from "@lsolova/json-schema-validator";
import path from "node:path";
async function initValidator() {
const wasmPath = path.join(
process.cwd(),
"node_modules/@lsolova/json-schema-validator/dist/assets/schema_validator.wasm"
);
const wasmBuffer = await readFile(wasmPath);
await SchemaValidator.init(wasmBuffer);
}Development
Setup for local development:
npm install
npm run buildTesting
Browser: Start a local web server:
npm run serveNode.js: Run the example:
npx tsx node-example.ts