0.0.8 • Published 3 years ago

shape-validate v0.0.8

Weekly downloads
4
License
ISC
Repository
github
Last release
3 years ago

Shape Validate

A library to validate data, based on ajv, inspired by joi and superstruct.

Features

  • Use ajv to compile validate function, so it's fast
  • Provides joi-like api, easy to use
  • Provides TypeScript types, useful for inferring type of validated data.
  • Deep clone data before validation, which can be turned off.
  • Use user-defined functions to customize validation
  • Use before/after methods to control validation order
  • Define new shape directly from JSON Schema

Quick Start

import { object, string, number } from "@xuanxiaodi/shape";

const shape = object({
  name: string(),
  age: number(),
});

shape.validateSync({ name: "Tom", age: "18" });
// { name: 'Tom', age: 18 }

await shape.validateAsync({ name: "Tom", age: "18" });
// { name: 'Tom', age: 18 }

Introduction

"Shape"

"Shape" is a wrapper for JSON Schema, with some options for combining into other shapes.

Usage

Validation

import { validateSync, validateAsync } from "shape-validate";

// use validate functions in this package
const validatedValue = validateSync(shape, inputValue);
const validatedValue = validateSync(shape, inputValue, false); // turn off deep clone
const validatedValue = await validateAsync(shape, inputValue);
const validatedValue = await validateAsync(shape, inputValue, false); // turn off deep clone

// use validate methods of shapes
const validatedValue = shape.validateSync(inputValue);
const validatedValue = shape.validateSync(inputValue, false); // turn off deep clone
const validatedValue = await shape.validateAsync(inputValue);
const validatedValue = await shape.validateAsync(inputValue, false); // turn off deep clone

Validate functions/methods will return the value after validate (value could be modified), or throw a validation error.

Basically, you can use validation functions if shape is an input value, use methods if shape is surely an instance of shape class.

Basic Shapes

import { any, boolean, date } from "shape-validate";

any(); // A shape with no limit
any().optional(); // Indicate value can be omitted in object
any().nullable(); // Indicate value can be null (if limited by type)
any().default("a"); // Set value to default value if it was undefined or null or empty string

String Shape

import { string } from "shape-validate";

string(); // A shape indicating value should be string
string().minLength(5); // Indicate string length limit
string().maxLength(20); // Indicate string length limit
string().pattern(/^\p{sc=Han}$/u); // Indicate string should match an regex.
string().format("email"); // Indicate string should in specific format.
string().trim().lowercase(); // Transform string before other validation

Number Shapes

import { number, integer } from "shape-validate";

number(); // A shape indicating value should be number
integer(); // A shape indicating value should be integer

number().range(5, 20); // Indicate value should between two values (inclusive)
number().min(5).max(20); // Equivalent
number().range(5, 20, true); // Indicate value should between two values (exclusive)
number().min(5, true).max(20, true); // Equivalent

Other Basic Shapes

import { boolean, date, enumerate, constant } from "shape-validate";

boolean();
date(); // A shape indicating value should be number or string for valid date
enumerate([1, 2, 3]);
constant(1);

Object Shape

import { object, number, string } from "shape-validate";

// Each property is required by default
object({ name: string(), age: number().optional() });

// Unknown properties will be striped, use keepUnknown() to keep them
object({ name: string() }).keepUnknown();

Array Shape

import { array, integer, string } from "shape-validate";

array(integer());
array(integer()).minSize(10);
array(integer()).maxSize(10);
array(integer()).unique();

Tuple Shape

import { tuple, integer } from "shape-validate";

const point2d = tuple(integer(), integer()); // (x, y)
const point3d = tuple(integer(), integer(), integer()); // (x, y, z)

const latlng = tuple(number().range(-90, 90), number().range(0, 360));

Custom Shape and Logic

import { custom } from "shape-validate";

const shape = custom<string>({ type: "string", minLength: 1 });

// these before/after methods is for any shape.
shape.beforeSync((value) => value + 1);
shape.afterSync((value) => value + 1);
shape.beforeAsync(async (value) => await findReference(value));
shape.afterAsync(async (value) => await findResult(value));

custom() return a shape object instead of shape instance, means you cannot use shape.validateSync(value) (but you can use this in validateSync(shape, value)).

Customize Error Messages

import { number, setKeywordMessage, setStaticMessage } from "shape-validate";

// Override error message for current field and any sub fields
number().message("验证失败");

// Override keyword error messages for current field only
number().range(1, 10).message({
  minimum: "必须大于等于1",
  maximum: "必须小于等于10",
  // "_" is for any other keywords, this will override sub field default error messages
  _: "验证失败",
});

// Override global default error messages
setStaticMessage("fallback", "验证失败");
setStaticMessage("rootRequired", "数据不能为空");

// Override global keyword error messages
setKeywordMessage("minimum", (path, params, schema) => {
  const name = schema.title || path || "值";
  return `${name}必须${params.exclusive ? "大于" : "大于等于"} ${params.limit}`;
});

i18n

import { setLocale } from "shape-validate";

// Set global error messages for Simplified Chinese
setLocale("zh-CN");

Built-in configurations:

  • en(English, the default one)
  • zh-CN(Simplified Chinese)

Type Coercing

These shape can be coerced from other values:

shapefrom
boolean()'true', 'false', 1, 0, '1', '0'
number()12.34, 1234, 12.3e4
integer()1234
date()ISO8601 Date-Time String

Other conversion can be defined by beforeSync() or beforeAsync()

0.0.8

3 years ago

0.0.7

3 years ago

0.0.6

3 years ago

0.0.5

4 years ago

0.0.4

4 years ago

0.0.3

4 years ago

0.0.1

4 years ago

0.0.2

4 years ago

0.0.1-alpha

4 years ago