Generate standalone validation functions that don't require the Ajv runtime for deployment optimization, reduced bundle sizes, and self-contained validation logic.
Generates standalone JavaScript code for validation functions that can run independently without the Ajv library.
/**
* Generates standalone validation code
* @param ajv - Ajv instance with code.source option enabled
* @param refsOrFunc - Validation function, mapping of refs to validation functions, or undefined for all schemas
* @returns Self-contained JavaScript code as string
*/
function standaloneCode(
ajv: AjvCore,
refsOrFunc?: {[K in string]?: string} | AnyValidateFunction
): string;Usage Examples:
import Ajv from "ajv";
import standaloneCode from "ajv/dist/standalone";
const ajv = new Ajv({ code: { source: true, esm: true } });
// Simple schema
const schema = {
type: "object",
properties: {
name: { type: "string" },
age: { type: "number", minimum: 0 }
},
required: ["name", "age"],
additionalProperties: false
};
// Compile validation function
const validate = ajv.compile(schema);
// Generate standalone code
const moduleCode = standaloneCode(ajv, validate);
console.log(moduleCode);
/* Generated code will be similar to:
export const validate = (function() {
"use strict";
const schema0 = {"type":"object","properties":{"name":{"type":"string"},"age":{"type":"number","minimum":0}},"required":["name","age"],"additionalProperties":false};
return function validate(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}) {
let vErrors = null;
let errors = 0;
if (!(data && typeof data == "object" && !Array.isArray(data))) {
const err0 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"};
if (vErrors === null) vErrors = [err0];
else vErrors.push(err0);
errors++;
}
// ... rest of validation logic
validate.errors = vErrors;
return errors === 0;
};
})();
export default validate;
*/Generate standalone code for multiple validation functions in a single module.
/**
* Generates standalone code for multiple validation functions
* @param ajv - Ajv instance with code.source option enabled
* @param refs - Object mapping schema keys/refs to export names
* @returns Module code with multiple exported validation functions
*/
function standaloneCode(
ajv: AjvCore,
refs: {[schemaKeyRef: string]: string}
): string;Usage Examples:
import Ajv from "ajv";
import standaloneCode from "ajv/dist/standalone";
const ajv = new Ajv({ code: { source: true, esm: true } });
// Define multiple schemas
const userSchema = {
type: "object",
properties: {
id: { type: "integer" },
name: { type: "string" },
email: { type: "string", format: "email" }
},
required: ["id", "name", "email"]
};
const productSchema = {
type: "object",
properties: {
id: { type: "string" },
name: { type: "string" },
price: { type: "number", minimum: 0 },
category: { enum: ["electronics", "clothing", "books"] }
},
required: ["id", "name", "price"]
};
const orderSchema = {
type: "object",
properties: {
id: { type: "string" },
userId: { type: "integer" },
items: {
type: "array",
items: {
type: "object",
properties: {
productId: { type: "string" },
quantity: { type: "integer", minimum: 1 }
},
required: ["productId", "quantity"]
}
},
total: { type: "number", minimum: 0 }
},
required: ["id", "userId", "items", "total"]
};
// Compile validation functions
const validateUser = ajv.compile(userSchema);
const validateProduct = ajv.compile(productSchema);
const validateOrder = ajv.compile(orderSchema);
// Generate standalone module with multiple functions
const moduleCode = standaloneCode(ajv, {
validateUser,
validateProduct,
validateOrder
});
// Write to file for deployment
import { writeFileSync } from "fs";
writeFileSync("./dist/validators.js", moduleCode);
/* Generated module exports:
export const validateUser = function(data) { ... };
export const validateProduct = function(data) { ... };
export const validateOrder = function(data) { ... };
*/Control the output format and features of generated standalone code.
/**
* Code generation options for standalone output
*/
interface CodeOptions {
/** Generate source code mappings - required for standalone code */
source?: boolean;
/** Output ES modules (import/export) instead of CommonJS */
esm?: boolean;
/** Include line numbers in generated code */
lines?: boolean;
/** Optimize generated code (0=none, 1=basic, 2=advanced) */
optimize?: boolean | number;
/** Use ES5 compatible syntax */
es5?: boolean;
/** Code to require formats map (for standalone) */
formats?: Code;
/** Post-process generated code */
process?: (code: string, schema?: SchemaEnv) => string;
/** Regular expression engine */
regExp?: RegExpEngine;
}Usage Examples:
import Ajv from "ajv";
import standaloneCode from "ajv/dist/standalone";
// Different output formats
const ajvESM = new Ajv({
code: {
source: true, // Include source mappings
esm: true, // ES module format
lines: true, // Include line numbers
optimize: true, // Optimize code
format: true // Format for readability
}
});
const ajvCommonJS = new Ajv({
code: {
source: true,
esm: false, // CommonJS format
es5: true, // ES5 compatible
optimize: false // Keep all variables for debugging
}
});
const schema = {
type: "object",
properties: {
id: { type: "string" },
value: { type: "number" }
}
};
// Generate ES module
const validateESM = ajvESM.compile(schema);
const esmCode = standaloneCode(ajvESM, validateESM);
console.log("ES Module format:");
console.log(esmCode);
// Generate CommonJS module
const validateCJS = ajvCommonJS.compile(schema);
const cjsCode = standaloneCode(ajvCommonJS, validateCJS);
console.log("CommonJS format:");
console.log(cjsCode);Examples of integrating standalone code generation into build processes.
/**
* Build integration utilities
*/
interface BuildIntegration {
/** Generate validation modules during build */
generateValidators(schemas: Record<string, AnySchema>, outputDir: string): void;
/** Watch schemas and regenerate on changes */
watchSchemas(schemaDir: string, outputDir: string): void;
}Usage Examples:
// build-validators.js - Build script
import Ajv from "ajv";
import standaloneCode from "ajv/dist/standalone";
import { writeFileSync, readFileSync, mkdirSync } from "fs";
import { join, dirname } from "path";
interface SchemaDefinition {
name: string;
schema: any;
outputPath: string;
}
class ValidatorBuilder {
private ajv: Ajv;
constructor() {
this.ajv = new Ajv({
code: { source: true, esm: true, optimize: true },
strict: true
});
}
generateValidators(schemas: SchemaDefinition[]) {
const validationFunctions: Record<string, any> = {};
// Compile all schemas
schemas.forEach(({ name, schema }) => {
validationFunctions[name] = this.ajv.compile(schema);
});
// Generate standalone code
const code = standaloneCode(this.ajv, validationFunctions);
// Write to output file
const outputPath = "./dist/validators.js";
mkdirSync(dirname(outputPath), { recursive: true });
writeFileSync(outputPath, code);
console.log(`Generated validators: ${outputPath}`);
}
generateIndividualValidators(schemas: SchemaDefinition[]) {
schemas.forEach(({ name, schema, outputPath }) => {
const validate = this.ajv.compile(schema);
const code = standaloneCode(this.ajv, validate);
mkdirSync(dirname(outputPath), { recursive: true });
writeFileSync(outputPath, code);
console.log(`Generated ${name}: ${outputPath}`);
});
}
}
// Usage in build script
const builder = new ValidatorBuilder();
const schemas: SchemaDefinition[] = [
{
name: "validateUser",
schema: JSON.parse(readFileSync("./schemas/user.json", "utf8")),
outputPath: "./dist/validators/user.js"
},
{
name: "validateProduct",
schema: JSON.parse(readFileSync("./schemas/product.json", "utf8")),
outputPath: "./dist/validators/product.js"
}
];
// Generate all validators
builder.generateValidators(schemas);
// Or generate individual files
builder.generateIndividualValidators(schemas);Using generated standalone validators in production applications.
/**
* Runtime usage of standalone validators
*/
interface StandaloneValidator {
(data: unknown): boolean;
errors?: ErrorObject[] | null;
}Usage Examples:
// Using generated standalone validator
import { validateUser, validateProduct, validateOrder } from "./dist/validators.js";
// API endpoint using standalone validator
export async function createUser(req: Request, res: Response) {
const userData = req.body;
// Validate with standalone function (no Ajv runtime needed)
if (!validateUser(userData)) {
return res.status(400).json({
error: "Validation failed",
details: validateUser.errors
});
}
// Process valid user data
const user = await userService.create(userData);
res.json(user);
}
// Middleware for request validation
function validateRequest(validator: StandaloneValidator) {
return (req: Request, res: Response, next: NextFunction) => {
if (!validator(req.body)) {
return res.status(400).json({
error: "Invalid request data",
errors: validator.errors
});
}
next();
};
}
// Use validation middleware
app.post("/users", validateRequest(validateUser), createUser);
app.post("/products", validateRequest(validateProduct), createProduct);
app.post("/orders", validateRequest(validateOrder), createOrder);Standalone validation provides significant performance advantages:
// Without standalone: Include full Ajv library (~200KB)
import Ajv from "ajv";
const ajv = new Ajv();
const validate = ajv.compile(schema);
// With standalone: Only validation logic (~2-10KB per validator)
import { validateUser } from "./validators.js";// Benchmark comparison
import Ajv from "ajv";
import standaloneCode from "ajv/dist/standalone";
const ajv = new Ajv();
const schema = { /* complex schema */ };
// Runtime compilation approach
const runtimeValidate = ajv.compile(schema);
// Standalone approach
const standaloneValidate = eval(standaloneCode(ajv, ajv.compile(schema)));
// Performance test
const testData = { /* test data */ };
console.time("Runtime validation");
for (let i = 0; i < 100000; i++) {
runtimeValidate(testData);
}
console.timeEnd("Runtime validation");
console.time("Standalone validation");
for (let i = 0; i < 100000; i++) {
standaloneValidate(testData);
}
console.timeEnd("Standalone validation");
// Standalone is typically 10-30% faster due to:
// - No runtime schema resolution
// - Direct function calls
// - Optimized code paths
// - Reduced memory allocations// Optimized deployment structure
/*
dist/
├── validators/
│ ├── user.js (standalone user validator)
│ ├── product.js (standalone product validator)
│ └── order.js (standalone order validator)
├── api/
│ ├── users.js (uses validators/user.js)
│ ├── products.js (uses validators/product.js)
│ └── orders.js (uses validators/order.js)
└── main.js (no Ajv dependency needed)
*/
// Each validator is self-contained and optimized
// Total validation bundle: ~50KB vs ~200KB+ with runtime Ajv