4.0.5 âĒ Published 7 months ago
@pbinj/pbj-guards v4.0.5
@pbinj/pbj-guards
Type-safe runtime validation guards for PBinJ applications.
Features
- ðĄïļ Runtime type validation
- ð TypeScript type inference
- ð Detailed validation errors
- ðŊ Schema-based validation
- ð Composable guards
- ðŠķ Zero runtime dependencies
Installation
npm install @pbinj/pbj-guardspnpm add @pbinj/pbj-guardsyarn add @pbinj/pbj-guardsBasic Usage
import { isString, isNumber, isBoolean, shape, array } from "@pbinj/pbj-guards";
// Basic type guards
const str = "hello";
isString(str); // true
// Object shape validation
const userGuard = shape({
id: isNumber,
name: isString,
isActive: isBoolean,
});
const user = {
id: 1,
name: "John",
isActive: true,
};
if (userGuard(user)) {
// user is typed as { id: number; name: string; isActive: boolean }
console.log(user.name);
}Advanced Features
Array Validation
import { array, isString } from "@pbinj/pbj-guards";
const stringArrayGuard = array(isString);
const values = ["a", "b", "c"];
if (stringArrayGuard(values)) {
// values is typed as string[]
values.map((v) => v.toUpperCase());
}Schema Composition
import { shape, array, isString, isNumber, required } from "@pbinj/pbj-guards";
const addressGuard = shape({
street: required(isString),
city: required(isString),
zipCode: isString,
});
const userGuard = shape({
id: required(isNumber),
name: required(isString),
addresses: array(addressGuard),
});
type User = GuardType<typeof userGuard>;
// User is now typed as {
// id: number;
// name: string;
// addresses?: Array<{
// street: string;
// city: string;
// zipCode?: string;
// }>;
// }Integration with PBinJ
import { context, pbjKey } from "@pbinj/pbj";
import { shape, isString, required } from "@pbinj/pbj-guards";
const configGuard = shape({
apiKey: required(isString),
baseUrl: required(isString),
});
const configKey = pbjKey<Config>("config");
context.register(configKey, () => {
const config = loadConfig();
if (!configGuard(config)) {
throw new Error("Invalid configuration");
}
return config;
});Available Guards
isString- Validates stringsisNumber- Validates numbersisBoolean- Validates booleansisInteger- Validates integer numbersisNullish- Validates null or undefined valuesisRequired- Validates non-null valuesarray- Creates array validatorsshape- Creates object shape validatorsallOf- Combines multiple guardsoneOf- Matches one of several guards$ref- Creates recursive type references
Type Inference
The library provides full TypeScript type inference:
import { shape, isString, isNumber, GuardType } from "@pbinj/pbj-guards";
const personGuard = shape({
name: isString,
age: isNumber,
});
type Person = GuardType<typeof personGuard>;
// Person = { name?: string; age?: number }JSON Schema Compatibility
Converting Guards to JSON Schema
The library provides built-in support for converting guards to JSON Schema (Draft 2020-12):
import { toSchema, shape, isString, isNumber, array } from "@pbinj/pbj-guards";
const userGuard = shape({
name: isString,
age: isNumber,
tags: array(isString),
});
const schema = toSchema(userGuard);
// Outputs:
// {
// "$schema": "https://json-schema.org/draft/2020-12/schema",
// "type": "object",
// "properties": {
// "name": { "type": "string" },
// "age": { "type": "number" },
// "tags": {
// "type": "array",
// "items": { "type": "string" }
// }
// }
// }OpenAPI 3.1.0 Compatibility
Guards can be used to generate OpenAPI 3.1.0 compatible schemas:
import { toSchema, shape, isString, isNumber } from "@pbinj/pbj-guards";
const userGuard = shape(
{
id: isNumber,
email: isString,
},
{
description: "A user in the system",
title: "User",
},
);
const schema = toSchema(userGuard, {
// OpenAPI-specific metadata
deprecated: false,
example: {
id: 1,
email: "user@example.com",
},
});Advanced Schema Configuration
You can customize the generated schema with additional JSON Schema keywords:
import { array, isString, toSchema } from "@pbinj/pbj-guards";
const tagsGuard = array(isString, {
minItems: 1,
maxItems: 10,
uniqueItems: true,
});
const schema = toSchema(tagsGuard);
// Outputs:
// {
// "$schema": "https://json-schema.org/draft/2020-12/schema",
// "type": "array",
// "items": { "type": "string" },
// "minItems": 1,
// "maxItems": 10,
// "uniqueItems": true
// }Custom Formats and Patterns
Support for string formats and patterns:
import { isString, shape, toSchema } from "@pbinj/pbj-guards";
const userGuard = shape({
email: isString({ format: "email" }),
phone: isString({ pattern: "^\\+[1-9]\\d{1,14}$" }),
website: isString({ format: "uri" }),
});
const schema = toSchema(userGuard);Schema References and Definitions
Support for schema references and definitions:
import { shape, isString, isNumber, $ref, toSchema } from "@pbinj/pbj-guards";
const addressGuard = shape({
street: isString,
city: isString,
country: isString,
});
const userGuard = shape({
id: isNumber,
name: isString,
address: $ref("Address", addressGuard),
});
const schema = toSchema(userGuard);Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT