npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

bguard

v0.5.0

Published

**bguard** is a powerful, flexible, and type-safe validation library for TypeScript. It allows developers to define validation schemas for their data structures and ensures that data conforms to the expected types and constraints.

Downloads

412

Readme

bguard

bguard is a powerful, flexible, and type-safe validation library for TypeScript. It allows developers to define validation schemas for their data structures and ensures that data conforms to the expected types and constraints.

Coveralls branch npm Known Vulnerabilities

Table of contents

Features

  • Type Inference: Automatically infer TypeScript types from your validation schemas.
  • Custom Assertions: Add custom validation logic for your schemas.
  • Chaining Methods: Easily chain methods for complex validations.
  • Nested Validation: Supports complex data structures, including arrays and objects.
  • Optional and Nullable Support: Fine-grained control over optional and nullable fields.
  • Small Bundle Size: Each assertion is in its own file, minimizing your final bundle size.
  • Lightweight: No dependencies and optimized for performance.

Installation

npm install bguard

Usage

Here’s a basic example of how to use bguard to define and validate a schema.

Defining a Schema

Let's define a schema for a Student object:


import { InferType } from 'bguard';
import { object } from 'bguard/object';
import { array } from 'bguard/array';
import { number } from 'bguard/number';
import { string } from 'bguard/string';
import { boolean } from 'bguard/boolean';
import { email } from 'bguard/string/email';
import { min } from 'bguard/number/min';
import { max } from 'bguard/number/max';

// Example: Student Schema
const studentSchema = object({
  email: string().optional().custom(email()),
  age: number().custom(min(18), max(120)),
  address: string().nullable(),
  classes: array(
    object({
      name: string(),
      mandatory: boolean(),
      rooms: array(number()),
    }).optional()
  ),
  verified: boolean().optional(),
});

Inferring TypeScript Types

Using the InferType utility, you can infer the TypeScript type of the schema:

type StudentSchema = InferType<typeof studentSchema>;

This will generate the following type:


type StudentSchema = {
  age: number;
  address: string | null;
  classes: ({
    name: string;
    mandatory: boolean;
    rooms: number[];
  } | undefined)[];
  email?: string | undefined;
  verified?: boolean | undefined;
}

Generating TypeScript Types with codeGen

If you prefer to generate TypeScript types as a string, you can use the codeGen function:

import { codeGen } from 'bguard/codeGen';

The codeGen function takes a schema and returns a string representing the inferred TypeScript type. This string can be written to a file or used in other ways where a static type definition is needed.

Example

const typeString = codeGen(studentSchema);
console.log(typeString);

This would output a string:

{
  email?: string | undefined;
  age: number;
  address: string | null;
  classes: ({
      name: string;
      mandatory: boolean;
      rooms: number[];
    } | undefined)[];
  verified?: boolean | undefined;
}

Notice: The returned string does not include a type name or the = symbol. You would need to add these manually if you want a complete type definition.

Generating Named TypeScript Types with codeGenWithName

For convenience, if you want to generate a complete type definition including a name, use the codeGenWithName function:

import { codeGenWithName } from 'bguard/codeGen';

This function takes two parameters: the name of the type and the schema.

Example:

const namedTypeString = codeGenWithName('StudentSchema', studentSchema);
console.log(namedTypeString);

This would output a string:

type StudentSchema = {
  email?: string | undefined;
  age: number;
  address: string | null;
  classes: ({
      name: string;
      mandatory: boolean;
      rooms: number[];
    } | undefined)[];
  verified?: boolean | undefined;
}

Summary:

codeGen(schema: CommonSchema): string - Generates a string of the TypeScript type based on the schema. You need to manually add a type name and assignment if needed.

codeGenWithName(typeName: string, schema: CommonSchema): string - Generates a complete TypeScript type definition string, including the type keyword and type name.

Validating Data

This library provides two methods to parse data against schemas: parse and parseOrFail. These methods help in validating the data and obtaining structured errors if any issues are found during validation.

Let's use above mentioned studentSchema and:

// example of valid received data
const validStudentData = {
  age: 21,
  address: '123 Main St',
  classes: [
    {
      name: 'Math 101',
      mandatory: true,
      rooms: [101, 102],
    },
  ],
  email: '[email protected]',
};

// example of invalid received data with multiple errors
const invalidStudentData = {
  age: -5,
  address: undefined,
  classes: [
    {
      name: true,
      mandatory: 'true',
      rooms: null,
    },
  ],
  email: 'invalid-example',
};

parse Method

The parse method validates the data and returns a tuple containing errors and the parsed value. This method allows you to choose whether to collect all errors or stop at the first error using an options flag.

Syntax:

import { parse } from 'bguard';
// import other dependencies

const [errors, parsedValue] = parse(studentSchema, validStudentData, { getAllErrors: true });

Returns:

  • If validation succeeds: [undefined, parsedValue]
  • If there are validation errors: [ValidationErrorData[], undefined]

Options:

  • lng: Specifies the language for error messages. Default is 'default'.
  • getAllErrors: If true, collects all validation errors. If false or undefined, stops at the first error. Turning off getAllErrors provides a runtime optimization, as it stops validation at the first error, avoiding unnecessary checks for the remaining received value.

parseOrFail Method

The parseOrFail method validates the data and throws an error on the first validation failure. It is useful when you want to halt processing immediately upon encountering an error.

Syntax:

import { parseOrFail } from 'bguard';
// import other dependencies

try {
  // Attempt to parse and validate the studentData using the studentSchema
  const validatedData = parseOrFail(studentSchema, validStudentData);
  // If the data is valid, validatedData will contain the parsed value with inferred TypeScript types
} catch (error) {
  // If the data does not conform to the schema, an error will be thrown
  console.error(error.message); // Logs the first validation error message, if any
}

Throws:

  • ValidationError: If any validation rule fails, this error is thrown with details of the first encountered error.

Options:

  • lng: Specifies the language for error messages. Default is 'default'.

Explanation

  • parse Method: This method returns a tuple where the first element is an array of validation errors (if any), and the second element is the successfully parsed value (or undefined if errors exist). It allows collecting all errors by setting the getAllErrors flag.

  • parseOrFail Method: This method throws a ValidationError when the first validation rule fails, making it suitable for scenarios where early termination of validation is desired.

  • Options: Both methods accept options for language settings and error collection, enhancing flexibility in handling validation processes.

Chaining Methods

nullable()

Allows the value to be null.

Example:

const nullableSchema = string().nullable().optional();
// This schema allows string or null values.

optional()

Allows the value to be undefined.

Example:

const optionalSchema = string().nullable().optional();
// This schema allows string or undefined values.

default(value: InferType)

Sets a default value if the received value is undefined. The default value must match the inferred type of the schema, ensuring compatibility.

Notice: You cannot chain default() and optional() together, as they are contradictory. The optional() method allows the value to be undefined, while the default() method assigns a value if undefined. Attempting to chain both will throw a BuildSchemaError with the message: "Cannot call method 'default' after method 'optional'".

Notice: Additionally, default() must be the last method in the chain because it validates during schema build time that the default value is compatible with the rest of the schema. For example, if the schema is number(), the default value cannot be a string.

Example:

const schemaWithDefault = string().nullable().default('defaultString'); 
// This schema allows null values and sets 'defaultString' if the value is undefined.

const optionalSchema = string().nullable().optional();
// This schema allows both null and undefined values, but it does not provide a default value.

id(value: string)

Assigns a unique identifier to the schema, useful for tracking or mapping validation errors. The id can be accessed via err.meta?.id in case of a validation error.

description(value: string)

Provides a description for the schema, which can be used to give more context about the validation error. The description can be accessed via err.meta?.description in case of a validation error.

Example:

const addressSchema = string()
  .id('address')
  .description('Users address');
// This schema validates that string and assigns an ID and description for better error handling.

try {
  parseOrFail(addressSchema, undefined);
} catch (e) {
  const err = e as ValidationError;
  console.log(err.message);  // Output: 'The required value is missing'
  console.log(err.pathToError);  // Output: ''
  console.log(err.meta?.id);  // Output:  'address'
  console.log(err.meta?.description);  // Output: 'Users address'
}

transformBeforeValidation<In>(cb: TransformCallback<In, InferType<Schema>>)

This method allows you to apply a transformation to the input value before any validation occurs. The transformation is applied before the schema's other methods (like nullable, custom, etc.). The callback function can receive an input of type unknown by default, but you can specify the type if you know it, such as string. The return value of the callback must be of the same type as the inferred type of the schema, ensuring that the overall type does not change.

Order of Execution: First, transformations specified using transformBeforeValidation are applied. Then, the schema checks for null or undefined based on methods like nullable or optional. Finally, the custom validations and type checks are performed.

This method is particularly useful for normalizing or preparing data before validation, such as trimming whitespace, converting empty strings to null, or handling other preprocessing needs.

Notice: Like default, transformBeforeValidation should be placed at the end of the chain. This ensures that the transformation is correctly applied after all other type checks are resolved, preserving the expected type.

Example:

const stringOrNullSchema = string()
  .nullable()
  .custom(minLength(3))
  .transformBeforeValidation((val) => val + '') // First, transform value to a string
  .transformBeforeValidation((val: string) => (val === '' ? null : val)); // Second, convert empty strings to null

// Parsing 'test' will pass as 'test' is a valid string longer than 3 characters.
parseOrFail(stringOrNullSchema, 'test');

// Parsing '' will be transformed to null and will pass due to .nullable().
parseOrFail(stringOrNullSchema, '');

Literals

  • String Literals: string().equalTo('myStringValue') will infer 'myStringValue' as the type. string().oneOfValues(['foo', 'bar']) will infer 'foo' | 'bar' as the type.

  • Number Literals: number().equalTo(42) will infer 42 as the type. number().oneOfValues([3, 5]) will infer 3 | 5 as the type.

  • Boolean Literals: boolean().onlyTrue() will infer true as the type. boolean().onlyFalse() will infer false as the type.

Custom (Library Built-in) Assertions

The custom method allows you to extend the validation schema with additional asserts. These asserts can either be user-defined or selected from the comprehensive set provided by the library. This flexibility ensures that you can tailor validations to meet specific requirements beyond the standard methods available. All built-in asserts are documented in the Built-in Custom Assert Documentation section.

Example

import { min } from 'bguard/number/min';
import { max } from 'bguard/number/max';

const ageSchema = number().custom(min(18), max(120));

Library built-in assertions are imported from specific paths for better tree-shaking and smaller bundle sizes.

Create Custom Assertions

Bguard allows developers to create custom validation functions that can be integrated seamlessly with the library's existing functionality. Below is a detailed example demonstrating how to create a custom validation function, minLength, and how to properly document and map error messages for translations.

Example: Creating a minLength Custom Validation

import { ExceptionContext, RequiredValidation } from 'bguard/ExceptionContext';
import { setToDefaultLocale } from 'bguard/translationMap';

const minLengthErrorMessage = 'The received value {{r}} is shorter than the expected length {{e}}';
const minLengthErrorKey = 'customPrefix:minLength';

export const minLength =
  (expected: number): RequiredValidation =>
  (received: string, ctx: ExceptionContext) => {
    if (received.length < expected) {
      ctx.addIssue(expected, received, minLengthErrorKey);
    }
  };

minLength.key = minLengthErrorKey;
minLength.message = minLengthErrorMessage;
setToDefaultLocale(minLength);

Explanation

  • Error Key (minLength.key): This key ('customPrefix:minLength') uniquely identifies the validation and is used for mapping error messages, especially when supporting multiple languages. It's essential to avoid collisions with built-in assertions, which use prefixes like s:, n:, and b: etc. More on that in Common and Custom Translations.

  • Error Message (minLength.message): The message supports interpolation, where {{e}} will be replaced by the expected value, and {{r}} will be replaced by the received value during validation .

  • Exception Handling (ctx.addIssue): This method is responsible for throwing the error when the validation fails.

  • Localization Support (setToDefaultLocale): This function registers the default error message with its associated key. If you later decide to support multiple languages, you can easily map this key to different messages.

  • Using ctx.ref to Reference Other Properties: The ctx.ref method allows you to reference other properties in the input object during validation. Method ctx.ref can access nested properties by passing a string that references them, with each level of nesting separated by a dot (.). However, it's important to note that ctx.ref retrieves the original value from the object before any transformations (e.g., transformBeforeValidation). This ensures that validations based on cross-property references work consistently, regardless of any transformations applied before validation.

const loginSchema = object({
 password: string().custom(minLength(8)),
 confirmPassword: string().custom((received, ctx) => {
   if (received !== ctx.ref('password')) {
     ctx.addIssue(ctx.ref('password'), received, 'Not equal to password');
   }
 })
});
  • Key Points for Developers:

    1. Always create unique error keys for custom validations to avoid potential conflicts with Bguard's built-in validations.
    2. Custom validations should use prefixes other than s:, n:, b:, and similar ones reserved for Bguard's internal validations.
    3. The minLengthErrorMessage serves as the default message. If you want to provide translations, you can do so by mapping the error key in the translationMap. For single-language applications, you can override the default message by directly passing your custom message to addIssue method.
    4. If we have a nested object { foo: { bar: 'baz' } }, we should use ctx.ref('foo.bar') to access the value 'baz' in custom assertions.

Translation

Bguard provides default translations for error messages, but you can customize them as needed. Each potential error has an errorKey and errorMessage.

Example:

Consider the schema:

const testSchema = object({ foo: number().custom(min(5)) });

The min function has:

const minErrorMessage = 'The received value is less than expected'; // Default error message
const minErrorKey = 'n:min'; // Error key

If you want to change the error message for min, you can do so by importing the setLocale function and setting your custom message:

import { setLocale } from 'bguard/translationMap';

setLocale('SR', {
  'n:min': 'The received value {{r}} found on path {{p}} is less than expected value {{e}}',
  // ... continue adding other translations
});

With this setup, in the translation namespace 'SR', if the received value is 4, you'll get an error message like:

'The received value 4 found on path .foo is less than expected value 5'

  • {{r}} - Replaced with the received value.
  • {{p}} - Replaced with the path to the error.
  • {{e}} - Replaced with the expected value.

Notice: Do not overwrite the 'default' namespace. If a translation is missing, it will fall back to the 'default' translation.

Using Translations

To apply the new translation, both parse and parseOrFail functions accept a lng property in the options object provided as the third parameter:

parseOrFail(testSchema, { foo: 4 }, { lng: 'SR' });
// or
parse(testSchema, { foo: 4 }, { lng: 'SR' });

Common and Custom Translations

We have two sets of translations: common errors and specific assertions.

Common Error Translations:

'c:optional': 'The required value is missing',
'c:nullable': 'Value should not be null',
'c:array': 'Expected an array but received a different type',
'c:objectType': 'Expected an object but received a different type',
'c:objectTypeAsArray': 'Expected an object but received an array. Invalid type of data',
'c:unrecognizedProperty': 'This property is not allowed in the object',
'c:requiredProperty': 'Missing required property in the object',
'c:invalidType': 'Invalid type of data',
'c:isBoolean': 'The received value is not {{e}}',
'c:date': 'The received value is not a valid instance of Date',

Custom Assertion Translations:

For custom assertions, each key and message are located in separate files for better code splitting. There are multiple ways to identify a key:

1. Key Construction: Keys are constructed as '{typeId}:{functionName}', where typeId represents:

  • c - common
  • n - numbers
  • s - strings
  • b - boolean
  • a - array
  • o - object
  • sy - symbol
  • f - function
  • bi - bigint
  • m - mixed
  • dt - date

Each typeId maps to the folder from which custom assertions are retrieved (except 'common', as explained above).

Example:

import { maxLength } from 'bguard/string/maxLength';

The function located in 'bguard/string/maxLength' will have the key 's:maxLength'.

2. Assertion Function Properties:

Each assert function has two additional properties: key and message.

import { maxLength } from 'bguard/string/maxLength';

console.log(maxLength.key); // Output: 's:maxLength'
console.log(maxLength.message); // Output: 'The received value length is greater than expected'

Notice: Do not directly change these values.

3. IDE Support: Each key and message will be visible in text editors that support JSDoc IntelliSense.

Built-in Custom Assert Documentation

string

Prerequisites

import { string } from 'bguard/string';
  • Description Creates a new schema for validating string values.
  • Example
 const schema = string();
 parseOrFail(schema, 'hello'); // Validates successfully
 parseOrFail(schema, 123); // Throws a validation error
atLeastOneDigit
import { atLeastOneDigit } from 'bguard/string/atLeastOneDigit';
  • Description Asserts that a string value contains at least one digit.
  • Throws {ValidationError} if the received value does not contain at least one digit.
  • Example
 const schema = string().custom(atLeastOneDigit());
 parseOrFail(schema, 'abc123'); // Valid
 parseOrFail(schema, 'abcdef'); // Throws an error: 'The received value does not contain at least one digit'
  • See Error Translation Key = 's:atLeastOneDigit'

atLeastOneLowerChar
import { atLeastOneLowerChar } from 'bguard/string/atLeastOneLowerChar';
  • Description Asserts that a string value contains at least one lowercase character.
  • Throws {ValidationError} if the received value does not contain at least one lowercase character.
  • Example
 const schema = string().custom(atLeastOneLowerChar());
 parseOrFail(schema, 'abcDEF'); // Valid
 parseOrFail(schema, 'ABCDEF'); // Throws an error: 'The received value does not contain at least one lowercase character'
  • See Error Translation Key = 's:atLeastOneLowerChar'

atLeastOneSpecialChar
import { atLeastOneSpecialChar } from 'bguard/string/atLeastOneSpecialChar';
  • Description Asserts that a string value contains at least one special character.
  • Param {string} [allowedSpecialChars=] The string containing allowed special characters. Defaults to '@$!#%&()^~{}'.
  • Throws {ValidationError} if the received value does not contain at least one of the allowed special characters.
  • Example
 const schema = string().custom(atLeastOneSpecialChar()); // Default special characters
 parseOrFail(schema, 'abc!def'); // Valid
 parseOrFail(schema, 'abcdef');  // Throws an error: 'The received value does not contain at least one special character'

 const customSchema = string().custom(atLeastOneSpecialChar('@$')); // Custom special characters
 parseOrFail(customSchema, 'abc@def'); // Valid
 parseOrFail(customSchema, 'abcdef');  // Throws an error: 'The received value does not contain at least one special character'
  • See Error Translation Key = 's:atLeastOneSpecialChar'

atLeastOneUpperChar
import { atLeastOneUpperChar } from 'bguard/string/atLeastOneUpperChar';
  • Description Asserts that a string value contains at least one uppercase character.
  • Throws {ValidationError} if the received value does not contain at least one uppercase character.
  • Example
 const schema = string().custom(atLeastOneUpperChar());
 parseOrFail(schema, 'abcDEF'); // Valid
 parseOrFail(schema, 'abcdef'); // Throws an error: 'The received value does not contain at least one uppercase character'
  • See Error Translation Key = 's:atLeastOneUpperChar'

contains
import { contains } from 'bguard/string/contains';
  • Description Asserts that a string value contains a specified substring.
  • Param {string} substring The substring that must be present in the string value.
  • Throws {ValidationError} if the received value does not contain the required substring.
  • Example
 const schema = string().custom(contains('foo'));
 parseOrFail(schema, 'foobar'); // Valid
 parseOrFail(schema, 'bar'); // Throws an error: 'The received value does not contain the required substring'
  • See Error Translation Key = 's:contains'

email
import { email } from 'bguard/string/email';
  • Description Asserts that a string value matches the email pattern. The pattern checks for a basic email format.
  • Throws {ValidationError} if the received value does not match the email pattern.
  • Example
 const schema = string().custom(email());
 parseOrFail(schema, '[email protected]'); // Valid
 parseOrFail(schema, 'invalid-email');      // Throws an error: 'The received value does not match the required email pattern'
  • See - Error Translation Key = 's:email'

endsWith
import { endsWith } from 'bguard/string/endsWith';
  • Description Asserts that a string value ends with a specified substring.
  • Param {string} substring The substring that the string value must end with.
  • Throws {ValidationError} if the received value does not end with the required substring.
  • Example
 const schema = string().custom(endsWith('bar'));
 parseOrFail(schema, 'foobar'); // Valid
 parseOrFail(schema, 'foofoo'); // Throws an error: 'The received value does not end with the required substring'
  • See Error Translation Key = 's:endsWith'

isValidDate
import { isValidDate } from 'bguard/string/isValidDate';
  • Description Asserts that a string is a valid date in the format YYYY-MM-DD.
  • Throws {ValidationError} if the received string is not a valid date.
  • Example
 const schema = string().custom(isValidDate());
 parseOrFail(schema, "2020-01-01"); // Valid
 parseOrFail(schema, "2020-1-1");   // Throws an error: 'The received value is not a valid date'
 parseOrFail(schema, "2020-01-32"); // Throws an error: 'The received value is not a valid date'
  • See Error Translation Key = 's:isValidDate'

isValidDateTime
import { isValidDateTime } from 'bguard/string/isValidDateTime';
  • Description Asserts that a string value is a valid ISO 8601 datetime string.
  • Param {DateTimeOptions} options Options to control the validation:
  • offset: If true, allows timezone offsets in the datetime string.
  • precision: Specify the exact number of fractional second digits allowed (e.g., 3 for milliseconds).
  • Throws {ValidationError} if the received value is not a valid datetime string according to the options.
  • Example
 const schema = string().custom(isValidDateTime());
 parseOrFail(schema, "2024-01-01T00:00:00Z"); // Valid
 parseOrFail(schema, "2024-01-01T00:00:00.123Z"); // Valid
 parseOrFail(schema, "2024-01-01T00:00:00+03:00"); // Invalid (no offsets allowed)

 const schemaWithOffset = string().custom(isValidDateTime({ offset: true }));
 parseOrFail(schemaWithOffset, "2024-01-01T00:00:00+04:00"); // Valid

 const schemaWithPrecision = string().custom(isValidDateTime({ precision: 3 }));
 parseOrFail(schemaWithPrecision, "2024-01-01T00:00:00.123Z"); // Valid
 parseOrFail(schemaWithPrecision, "2024-01-01T00:00:00.123456Z"); // Invalid
  • See Error Translation Key = 's:isValidDateTime'

isValidTime
import { isValidTime } from 'bguard/string/isValidTime';
  • Description Asserts that a string is a valid time in the format HH:mm:ss, with optional fractional seconds.
  • Param {IsValidTimeOptions} options Optional settings to configure the validation.
  • Throws {ValidationError} if the received string is not a valid time.
  • Example
 const schema = string().custom(isValidTime());
 parseOrFail(schema, "00:00:00"); // Valid
 parseOrFail(schema, "23:59:59.9999999"); // Valid
 parseOrFail(schema, "00:00:00.256Z");   // Throws an error: 'The received value is not a valid time'

 const schemaWithPrecision = string().custom(isValidTime({ precision: 3 }));
 parseOrFail(schemaWithPrecision, "00:00:00.256"); // Valid
 parseOrFail(schemaWithPrecision, "00:00:00");    // Throws an error: 'The received value is not a valid time'
  • See Error Translation Key = 's:isValidTime'

lowerCase
import { lowerCase } from 'bguard/string/lowerCase';
  • Description Asserts that a string value is in lowercase.
  • Throws {ValidationError} if the received value is not in lowercase.
  • Example
 const schema = string().custom(lowerCase());
 parseOrFail(schema, 'valid');   // Valid
 parseOrFail(schema, 'Invalid'); // Throws an error: 'The received value is not in lowercase'
  • See Error Translation Key = 's:lowerCase'

maxLength
import { maxLength } from 'bguard/string/maxLength';
  • Description Asserts that the length of a string value is not greater than a specified maximum length.
  • Param {number} expected The maximum allowed length for the string.
  • Throws {ValidationError} if the length of the received value is greater than the expected length.
  • Example
 const schema = string().custom(maxLength(10));
 parseOrFail(schema, 'short');   // Valid
 parseOrFail(schema, 'this is a very long string'); // Throws an error: 'The received value length is greater than expected'
  • See Error Translation Key = 's:maxLength'

minLength
import { minLength } from 'bguard/string/minLength';
  • Description Asserts that the length of a string value is not less than a specified minimum length.
  • Param {number} expected The minimum required length for the string.
  • Throws {ValidationError} if the length of the received value is less than the expected length.
  • Example
 const schema = string().custom(minLength(5));
 parseOrFail(schema, 'short');    // Throws an error: 'The received value length is less than expected'
 parseOrFail(schema, 'adequate'); // Valid
  • See Error Translation Key = 's:minLength'

regExp
import { regExp } from 'bguard/string/regExp';
  • Description Asserts that a string value matches a specified regular expression pattern.
  • Param {RegExp} expected The regular expression pattern that the string value should match.
  • Throws {ValidationError} if the received value does not match the expected pattern.
  • Example
 const schema = string().custom(regExp(/^[A-Za-z0-9]+$/)); // Validates against alphanumeric pattern
 parseOrFail(schema, 'valid123');   // Valid
 parseOrFail(schema, 'invalid!@#'); // Throws an error: 'The received value does not match the required text pattern'
  • See Error Translation Key = 's:regExp'

startsWith
import { startsWith } from 'bguard/string/startsWith';
  • Description Asserts that a string value starts with a specified substring.
  • Param {string} substring The substring that the string value must start with.
  • Throws {ValidationError} if the received value does not start with the required substring.
  • Example
 const schema = string().custom(startsWith('foo'));
 parseOrFail(schema, 'foobar'); // Valid
 parseOrFail(schema, 'barfoo'); // Throws an error: 'The received value does not start with the required substring'
  • See Error Translation Key = 's:startsWith'

upperCase
import { upperCase } from 'bguard/string/upperCase';
  • Description Asserts that a string value is entirely in uppercase.
  • Throws {ValidationError} if the received value is not in uppercase.
  • Example
 const schema = string().custom(upperCase());
 parseOrFail(schema, 'VALID');    // Valid
 parseOrFail(schema, 'INVALID');  // Throws an error: 'The received value is not in uppercase'
 parseOrFail(schema, 'Valid');    // Throws an error: 'The received value is not in uppercase'
  • See Error Translation Key = 's:upperCase'

uuid
import { uuid } from 'bguard/string/uuid';
  • Description Asserts that a string value matches the UUID format.
  • Throws {ValidationError} if the received value is not a valid UUID.
  • Example
 const schema = string().custom(uuid());
 parseOrFail(schema, '123e4567-e89b-12d3-a456-426614174000'); // Valid
 parseOrFail(schema, 'invalid-uuid'); // Throws an error: 'The received value is not a valid UUID'
  • See Error Translation Key = 's:uuid'

uuidV1
import { uuidV1 } from 'bguard/string/uuidV1';
  • Description Asserts that a string value matches the UUID v1 format.
  • Throws {ValidationError} if the received value is not a valid UUID v1.
  • Example
 const schema = string().custom(uuidV1());
 parseOrFail(schema, '550e8400-e29b-11d4-a716-446655440000'); // Valid
 parseOrFail(schema, '550e8400-e29b-21d4-a716-446655440000'); // Throws an error: 'The received value is not a valid UUID v1'
 parseOrFail(schema, 'invalid-uuid'); // Throws an error: 'The received value is not a valid UUID v1'
  • See Error Translation Key = 's:uuidV1'

uuidV2
import { uuidV2 } from 'bguard/string/uuidV2';
  • Description Asserts that a string value matches the UUID v2 format.
  • Throws {ValidationError} if the received value is not a valid UUID v2.
  • Example
 const schema = string().custom(uuidV2());
 parseOrFail(schema, '550e8400-e29b-21d4-a716-446655440000'); // Valid
 parseOrFail(schema, '550e8400-e29b-31d4-d716-446655440000'); // Throws an error: 'The received value is not a valid UUID v2'
 parseOrFail(schema, 'invalid-uuid'); // Throws an error: 'The received value is not a valid UUID v2'
  • See Error Translation Key = 's:uuidV2'

uuidV3
import { uuidV3 } from 'bguard/string/uuidV3';
  • Description Asserts that a string value matches the UUID v3 format.
  • Throws {ValidationError} if the received value is not a valid UUID v3.
  • Example
 const schema = string().custom(uuidV3());
 parseOrFail(schema, '550e8400-e29b-38d1-a456-426614174000'); // Valid
 parseOrFail(schema, '550e8400-e29b-28d1-a456-426614174000'); // Throws an error: 'The received value is not a valid UUID v3'
 parseOrFail(schema, 'invalid-uuid'); // Throws an error: 'The received value is not a valid UUID v3'
  • See Error Translation Key = 's:uuidV3'

uuidV4
import { uuidV4 } from 'bguard/string/uuidV4';
  • Description Asserts that a string value matches the UUID v4 format.
  • Throws {ValidationError} if the received value is not a valid UUID v4.
  • Example
 const schema = string().custom(uuidV4());
 parseOrFail(schema, '123e4567-e89b-42d3-a456-426614174000'); // Valid
 parseOrFail(schema, '123e4567-e89b-12d3-a456-426614174000'); // Throws an error: 'The received value is not a valid UUID v4'
 parseOrFail(schema, '123e4567-e89b-a2d3-a456-426614174000'); // Throws an error: 'The received value is not a valid UUID v4'
 parseOrFail(schema, '123e4567-e89b-42d3-c456-426614174000'); // Throws an error: 'The received value is not a valid UUID v4'
 parseOrFail(schema, 'invalid-uuid'); // Throws an error: 'The received value is not a valid UUID v4'
  • See Error Translation Key = 's:uuidV4'

uuidV5
import { uuidV5 } from 'bguard/string/uuidV5';
  • Description Asserts that a string value matches the UUID v5 format.
  • Throws {ValidationError} if the received value is not a valid UUID v5.
  • Example
 const schema = string().custom(uuidV5());
 parseOrFail(schema, '550e8400-e29b-51d4-a716-446655440000'); // Valid
 parseOrFail(schema, '550e8400-e29b-41d4-a716-446655440000'); // Throws an error: 'The received value is not a valid UUID v5'
 parseOrFail(schema, 'invalid-uuid'); // Throws an error: 'The received value is not a valid UUID v5'
  • See Error Translation Key = 's:uuidV5'

validUrl
import { validUrl } from 'bguard/string/validUrl';
  • Description Asserts that the string value is a valid URL with optional protocol validation.
  • Param {string} [protocol] The protocol that the URL must start with (e.g., 'http'). If not provided, any URL starting with 'http://' or 'https://' is considered valid.
  • Throws {ValidationError} if the received value does not match the expected URL pattern.
  • Example
 const schema = string().custom(validUrl()); // Validates any URL starting with 'http://' or 'https://'
 parseOrFail(schema, 'http://example.com'); // Valid
 parseOrFail(schema, 'https://example.com'); // Valid
 parseOrFail(schema, 'ftp://example.com');   // Throws an error
 parseOrFail(schema, 'http:example.com');    // Throws an error
  • See Error Translation Key = 's:url'

number

Prerequisites

import { number } from 'bguard/number';
  • Description Creates a new schema for validating number values.
  • Example
 const schema = number();
 parseOrFail(schema, 42); // Validates successfully
 parseOrFail(schema, '42'); // Throws a validation error
max
import { max } from 'bguard/number/max';
  • Description Asserts that a number value does not exceed a specified maximum value.
  • Param {number} expected The maximum allowable value.
  • Throws {ValidationError} if the received value exceeds the expected maximum value.
  • Example
 const schema = number().custom(max(100));
 parseOrFail(schema, 99);  // Valid
 parseOrFail(schema, 100); // Valid
 parseOrFail(schema, 101); // Throws an error: 'The received value is greater than expected'
  • See Error Translation Key = 'n:max'

maxExcluded
import { maxExcluded } from 'bguard/number/maxExcluded';
  • Description - Asserts that a number value is strictly less than a specified maximum value (i.e., the maximum value is excluded).
  • Param {number} expected - The maximum allowable value, which is excluded.
  • Throws {ValidationError} if the received value is greater than or equal to the expected maximum value.
  • Example
 const schema = number().custom(maxExcluded(100));
 parseOrFail(schema, 99);  // Valid
 parseOrFail(schema, 100); // Throws an error: 'The received value is greater than or equal to expected'
 parseOrFail(schema, 101); // Throws an error: 'The received value is greater than or equal to expected'
  • See Error Translation Key = 'n:maxExcluded'

min
import { min } from 'bguard/number/min';
  • Description Asserts that a number value is not less than a specified minimum value.
  • Param {number} expected The minimum allowable value.
  • Throws {ValidationError} if the received value is less than the expected minimum value.
  • Example
 const schema = number().custom(min(10));
 parseOrFail(schema, 11);  // Valid
 parseOrFail(schema, 10);  // Valid
 parseOrFail(schema, 9);   // Throws an error: 'The received value is less than expected'
  • See Error Translation Key = 'n:min'

minExcluded
import { minExcluded } from 'bguard/number/minExcluded';
  • Description Asserts that a number value is strictly greater than a specified minimum value (i.e., the minimum value is excluded).
  • Param {number} expected The minimum allowable value, which is excluded.
  • Throws {ValidationError} if the received value is less than or equal to the expected minimum value.
  • Example
 const schema = number().custom(minExcluded(10));
 parseOrFail(schema, 11);  // Valid
 parseOrFail(schema, 10); // Throws an error: 'The received value is less than or equal to expected'
 parseOrFail(schema, 9);  // Throws an error: 'The received value is less than or equal to expected'
  • See Error Translation Key = 'n:minExcluded'

negative
import { negative } from 'bguard/number/negative';
  • Description Asserts that a number value is negative (less than zero).
  • Throws {ValidationError} if the received value is not negative.
  • Example
 const schema = number().custom(negative());
 parseOrFail(schema, -10); // Valid
 parseOrFail(schema, 0);  // Throws an error: 'The received value is not a negative number'
 parseOrFail(schema, 5);  // Throws an error: 'The received value is not a negative number'
  • See - Error Translation Key = 'n:negative'

positive
import { positive } from 'bguard/number/positive';
  • Description Asserts that a number value is positive (greater than zero).
  • Throws {ValidationError} if the received value is not positive.
  • Example
 const schema = number().custom(positive());
 parseOrFail(schema, 10);  // Valid
 parseOrFail(schema, 0);  // Throws an error: 'The received value is not a positive number'
 parseOrFail(schema, -5); // Throws an error: 'The received value is not a positive number'
  • See Error Translation Key = 'n:positive'

array

Prerequisites

import { array } from 'bguard/array';
  • Description Creates a new schema for validating arrays where each element must match the specified schema.

  • Param {T} arraySchema - The schema that each element of the array must match.

  • Example

 const schema = array(string());
 parseOrFail(schema, ['hello', 'world']); // Validates successfully
 parseOrFail(schema, ['hello', 123]); // Throws a validation error
maxArrayLength
import { maxArrayLength } from 'bguard/array/maxArrayLength';
  • Description Asserts that the length of an array is not greater than a specified maximum length.
  • Param {number} expected The maximum allowed length for the array.
  • Throws {ValidationError} if the length of the received value is greater than the expected length.
  • Example
 const schema = array(string()).custom(maxArrayLength(3));
 parseOrFail(schema, ['adequate', 'array']);   // Valid
 parseOrFail(schema, ['adequate', 'array', 'length']);   // Valid
 parseOrFail(schema, ['adequate', 'array', 'length', 'test']); // Throws an error: 'The received value length is greater than expected'
  • See Error Translation Key = 'a:maxArrayLength'

minArrayLength
import { minArrayLength } from 'bguard/array/minArrayLength';
  • Description Asserts that the length of na array is not less than a specified minimum length.
  • Param {number} expected The minimum required length for the array.
  • Throws {ValidationError} if the length of the received value is less than the expected length.
  • Example
 const schema = array(string()).custom(minArrayLength(3));
 parseOrFail(schema, ['short', 'array']);    // Throws an error: 'The received value length is less than expected'
 parseOrFail(schema, ['adequate', 'array', 'length']); // Valid
 parseOrFail(schema, ['adequate', 'array', 'length', 'test']); // Valid
  • See Error Translation Key = 'a:minArrayLength'

bigint

Prerequisites

import { bigint } from 'bguard/bigint';
  • Description Creates a new schema for validating bigint values.
  • Example
 const schema = bigint();
 parseOrFail(schema, 42n); // Validates successfully
 parseOrFail(schema, 42); // Throws a validation error
 parseOrFail(schema, '42'); // Throws a validation error
bigintMax
import { bigintMax } from 'bguard/bigint/bigintMax';
  • Description Asserts that a bigint value does not exceed a specified maximum value.
  • Param {bigint} expected The maximum allowable value.
  • Throws {ValidationError} if the received value exceeds the expected maximum value.
  • Example
 const schema = bigint().custom(bigintMax(100n));
 parseOrFail(schema, 99n);  // Valid
 parseOrFail(schema, 100n); // Valid
 parseOrFail(schema, 101n); // Throws an error: 'The received value is greater than expected'
  • See Error Translation Key = 'bi:max'

bigintMaxExcluded
import { bigintMaxExcluded } from 'bguard/bigint/bigintMaxExcluded';
  • Description - Asserts that a bigint value is strictly less than a specified maximum value (i.e., the maximum value is excluded).
  • Param {bigint} expected - The maximum allowable value, which is excluded.
  • Throws {ValidationError} if the received value is greater than or equal to the expected maximum value.
  • Example
 const schema = bigint().custom(bigintMaxExcluded(100n));
 parseOrFail(schema, 99n);  // Valid
 parseOrFail(schema, 100n); // Throws an error: 'The received value is greater than or equal to expected'
 parseOrFail(schema, 101n); // Throws an error: 'The received value is greater than or equal to expected'
  • See Error Translation Key = 'bi:maxExcluded'

bigintMin
import { bigintMin } from 'bguard/bigint/bigintMin';
  • Description Asserts that a bigint value is not less than a specified minimum value.
  • Param {bigint} expected The minimum allowable value.
  • Throws {ValidationError} if the received value is less than the expected minimum value.
  • Example
 const schema = bigint().custom(bigintMin(10n));
 parseOrFail(schema, 11n);  // Valid
 parseOrFail(schema, 10n);  // Valid
 parseOrFail(schema, 9n);   // Throws an error: 'The received value is less than expected'
  • See Error Translation Key = 'bi:min'

bigintMinExcluded
import { bigintMinExcluded } from 'bguard/bigint/bigintMinExcluded';
  • Description Asserts that a bigint value is strictly greater than a specified minimum value (i.e., the minimum value is excluded).
  • Param {bigint} expected The minimum allowable value, which is excluded.
  • Throws {ValidationError} if the received value is less than or equal to the expected minimum value.
  • Example
 const schema = bigint().custom(bigintMinExcluded(10n));
 parseOrFail(schema, 11n);  // Valid
 parseOrFail(schema, 10n); // Throws an error: 'The received value is less than or equal to expected'
 parseOrFail(schema, 9n);  // Throws an error: 'The received value is less than or equal to expected'
  • See Error Translation Key = 'bi:minExcluded'

date

Prerequisites

import { date } from 'bguard/date';
  • Description Creates a new schema for validating date values.
  • Example
 const schema = date();
 parseOrFail(schema, true); // Validates successfully
 parseOrFail(schema, 'true'); // Throws a validation error
dateMax
import { dateMax } from 'bguard/date/dateMax';
  • Description Asserts that a date value is not greater than a specified maximum value.
  • Param {Date | string} expected The maximum allowable value.
  • Throws {ValidationError} if the received value is greater than the expected maximum value.
  • Example
 const schema = date().custom(dateMax('2024-12-31'));
 parseOrFail(schema, new Date('2024-12-30'));  // Valid
 parseOrFail(schema, new Date('2024-12-31'));  // Valid
 parseOrFail(schema, new Date('2025-01-01'));  // Throws an error: 'The received value is greater than expected'
  • See Error Translation Key = 'dt:max'

dateMin
import { dateMin } from 'bguard/date/dateMin';
  • Description Asserts that a number value is not less than a specified minimum value.
  • Param {Date | string} expected The minimum allowable value.
  • Throws {ValidationError} if the received value is less than the expected minimum value.
  • Example
 const schema = date().custom(dateMin('2023-01-01'));
 parseOrFail(schema, new Date('2023-01-02'));  // Valid
 parseOrFail(schema, new Date('2023-01-01'));  // Valid
 parseOrFail(schema, new Date('2022-12-31'));  // Throws an error: 'The received value is less than expected'
  • See Error Translation Key = 'dt:min'

mix

Prerequisites

import { oneOfTypes } from 'bguard/mix';
  • Description Creates a new schema for validating values that can match any one of the specified primitive types.

  • Param {T} valueTypes - An array of primitive types that the value can match.

  • Example

 const schema = oneOfTypes(['string', 'number']);
 parseOrFail(schema, 'hello'); // Validates successfully
 parseOrFail(schema, 42); // Validates successfully
 parseOrFail(schema, true); // Throws a validation error
equalTo
import { equalTo } from 'bguard/mix/equalTo';
  • Description Creates a custom assertion that checks if a value is equal to the expected value.
  • Notice: It has already been implemented in the number, bigint and string schema. There is no need to use it as a custom assert.

  • Param {unknown} expected The value that the received value is expected to match.
  • Throws {ValidationError} If the received value does not match the expected value.
  • Example
 const schema = number().custom(equalTo(5)); // Define a schema with a custom assertion
 parseOrFail(schema, 5); // Valid
 parseOrFail(schema, 3); // Throws an error: 'The received value is not equal to expected'
  • See Error Translation Key = 'm:equalTo'

oneOfValues
import { oneOfValues } from 'bguard/mix/oneOfValues';
  • Description Creates a custom assertion that checks if a value is equal to the one of expected values.
  • Notice: It has already been implemented in the number, bigint and string schema. There is no need to use it as a custom assert.

  • Param {unknown} expected The value that the received value is expected to match.
  • Throws {ValidationError} If the received value does not match at least one of the expected values.
  • Example
 const schema = number().custom(oneOfValues([5, 4])); // Define a schema with a custom assertion
 parseOrFail(schema, 5); // Valid
 parseOrFail(schema, 4); // Valid
 parseOrFail(schema, 3); // Throws an error: 'The received value is not equal to expected'
  • See Error Translation Key = 'm:oneOfValues'

object

Prerequisites

import { object } from 'bguard/object';
  • Description Creates a new schema for validating objects where each property must match the specified schema.

  • Param {T} shapeSchema - The schema that each property of the object must match.

  • Example

 const schema = object({
   name: string(),
   age: number()
 });
 parseOrFail(schema, { name: 'John', age: 30 }); // Validates successfully
 parseOrFail(schema, { name: 'John', age: '30' }); // Throws a validation error
maxKeys
import { maxKeys } from 'bguard/object/maxKeys';
  • Description Ensures that the object has no more than the specified number of keys.
  • Param {number} expected - The maximum number of keys allowed in the object.
  • Throws {ValidationError} if the number of the received keys is greater than the expected value.
  • Example
 const schema = object({
   name: string(),
   email: string(),
 })
   .allowUnrecognized()
   .custom(maxKeys(2));

 // This will pass
 parseOrFail(schema, { name: 'John', email: '[email protected]' });

 // This will throw an error because there are 3 keys
 parseOrFail(schema, { name: 'John', email: '[email protected]', address: '123 Main St' });
  • See Error Translation Key = 'o:maxKeys'

Contributing

Contributions are welcome! Please open an issue or submit a pull request for any bugs or feature requests.