Skip to content

simple, easy-to-use, and declarative input validator; supports Node.js, TypeScript, Deno, and Bun

License

Notifications You must be signed in to change notification settings

shimataro/value-schema

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

value-schema

Build Status (Windows) Build Status (macOS) Build Status (Linux) Code Coverage Release Node.js version TypeScript version Deno version Bun version License

simple, easy-to-use, and declarative input validator

supports Node.js, TypeScript, Deno, and Bun

Table of Contents


Introduction

All of web applications need handling input parameters, consists of following steps:

  1. existence check
    • all required parameters exist?
    • fill omittable parameters with default values
  2. type check
    • e.g., typeof age === "number"
    • cast them if needed; "20"(string) to 20(number)
  3. domain check
    • e.g., 1 <= limit && limit <= 100
    • revise them if needed; 0 to 1

value-schema does all of them, by compact and highly readable code!

example

import vs from "value-schema";

const schemaObject = { // schema for input
    id: vs.number({ // number, >=1
        minValue: 1,
    }),
    name: vs.string({ // string, max 16 characters (trims if over)
        maxLength: {
            length: 16,
            trims: true,
        },
    }),
    birthday: vs.date(), // Date
    age: vs.number({ // number, integer (rounds down toward zero), >=0
        integer: vs.NUMBER.INTEGER.FLOOR_RZ,
        minValue: 0,
    }),
    email: vs.email(), // email
    state: vs.string({ // string, accepts only "active" and "inactive"
        only: ["active", "inactive"],
    }),
    classes: vs.array({ // array of number, separated by ",", ignores errors
        separatedBy: ",",
        each: {
            schema: vs.number(),
            ignoresErrors: true,
        },
    }),
    skills: vs.array({ // array of string, separated by ",", ignores errors
        separatedBy: ",",
        each: {
            schema: vs.string(),
            ignoresErrors: true,
        },
    }),
    creditCard: vs.numericString({ // numeric string, separated by "-", checks by Luhn algorithm
        separatedBy: "-",
        checksum: vs.NUMERIC_STRING.CHECKSUM_ALGORITHM.CREDIT_CARD,
    }),
    remoteAddr: vs.string({ // IPv4
        pattern: vs.STRING.PATTERN.IPV4,
    }),
    remoteAddrIpv6: vs.string({ // IPv6
        pattern: vs.STRING.PATTERN.IPV6,
    }),
    limit: vs.number({ // number, integer, omittable (sets 10 if omitted), >=1 (sets 1 if less), <=100 (sets 100 if greater)
        ifUndefined: 10,
        integer: true,
        minValue: {
            value: 1,
            adjusts: true,
        },
        maxValue: {
            value: 100,
            adjusts: true,
        },
    }),
    offset: vs.number({ // number, integer, omittable (sets 0 if omitted), >=0 (sets 0 if less)
        ifUndefined: 0,
        integer: true,
        minValue: {
            value: 0,
            adjusts: true,
        },
    }),
};
const input = { // input values
    id: "1",
    name: "Pablo Diego José Francisco de Paula Juan Nepomuceno María de los Remedios Ciprin Cipriano de la Santísima Trinidad Ruiz y Picasso",
    birthday: "2000-01-02T03:04:05.678Z",
    age: 20.5,
    email: "picasso@example.com",
    state: "active",
    classes: "1,3,abc,4",
    skills: "c,c++,javascript,python,,swift,kotlin",
    creditCard: "4111-1111-1111-1111",
    remoteAddr: "127.0.0.1",
    remoteAddrIpv6: "::1",
    limit: "0",
};
const expected = { // should be transformed to this
    id: 1,
    name: "Pablo Diego José",
    birthday: new Date("2000-01-02T03:04:05.678Z"),
    age: 20,
    email: "picasso@example.com",
    state: "active",
    classes: [1, 3, 4],
    skills: ["c", "c++", "javascript", "python", "swift", "kotlin"],
    creditCard: "4111111111111111",
    remoteAddr: "127.0.0.1",
    remoteAddrIpv6: "::1",
    limit: 1,
    offset: 0,
};

// Let's apply!
const actual = vs.applySchemaObject(schemaObject, input);

// verification
assert.deepStrictEqual(actual, expected);

That's all! No control flows! Isn't it cool?

For details, see reference.

Install

install from npm registry.

npm install -S value-schema

Loading

CommonJS

// foo.js
var vs = require("value-schema");

ES Modules / Babel / TypeScript

// foo.mjs (ES Modules) / foo.js (Babel) / foo.ts (TypeScript)
import vs from "value-schema";

ES Modules has been supported as of Node.js v8.5.0. In Windows, Node.js v8.6.0 is recommended due to ERR_INVALID_PROTOCOL.

To execute "foo.mjs", --experimental-modules flag is required. (the flag is dropped as of Node.js v13.2.0)

$ node --experimental-modules foo.mjs
(node:25508) ExperimentalWarning: The ESM module loader is experimental.

TypeScript auto-completion and type-checking works perfectly on Visual Studio Code and IntelliJ IDEA!

Deno has been supported as of v3.

// use latest version
import vs from "https://deno.land/x/value_schema/mod.ts";
// use specific version
import vs from "https://deno.land/x/value_schema@v4.0.0-rc.2/mod.ts";

CAUTION: specify value_schema (underscore) NOT value-schema (hyphen) because deno.land module database does not support name with hyphen!

Bun has been supported as of v4, but might work v3 or earlier.

Use just like a npm module.

import vs from "value-schema";

Changelog

See CHANGELOG.md.