Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

61 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

validation-core

A lightweight, dependency-free schema validation library for TypeScript and JavaScript.

Unlike decorator-based or fluent API validators, this library validates plain JavaScript objects using a declarative schema definition. It supports nested objects, arrays, custom validation rules, localization, and asynchronous validation.


📦 Key Features

  • Data Type validation: string, Date, number, integer, boolean
  • Format validation (for string): email, phone number, URL, IP Address, RegExp
  • Nested Object Validation: Supports deep validation of nested structures
  • Array Validation: Validate array items with itemType, along with min and max constraints
  • Custom Rules:
    • rule: for simple synchronous logic
    • custom: for advanced validation (return error message with error code, error description)
  • Custom Error Messages: Fully localized/custom error support per field/rule.
  • Multi-language Friendly: Error messages can be defined in any language.
  • Form-friendly: Designed for both backend and frontend use.

⚙️ Detailed Features

String Number Date Boolean Nested Object Array
✅ Required ✅ Required ✅ Required ✅ Required ✅ Required ✅ Required
✅ Enum ✅ Enum ✅ Enum
✅ Min Length ✅ Min ✅ Min ✅ Min Length
✅ Max Length ✅ Max ✅ Max ✅ Max Length
✅ Email ✅ gt (greater than) ✅ gt (greater than)
✅ URL ✅ lt (less than) ✅ lt (less than)
✅ IP v4 ✅ Precision Relative date:
✅ IP v6 ✅ Scale now ✅
✅ Phone today ✅
✅ Fax tomorrow ✅
✅ Regex match ✅ Integer yesterday ✅

🛠️ Advantages

  • Rich Features: Yes (Look at below Feature Comparison)
  • JSON Schema Support: Yes
  • Performance: Fast, very lightweight, rule-by-rule
  • Typescript/Javascript Support: Yes
  • Custom Validators: Yes
  • Integration: node, express, react, angular, vue
  • Validation Output: Structured Errors (JSON)
  • Size: Small
  • Dependencies: No
  • Learning Curve: Fast (standard JSON Schema)

Installation

npm install validation-core

or

yarn add validation-core

Quick Example

import { validate, Attributes } from "validation-core"

const User: Attributes = {
    id: {
        type: "ObjectId",
        required: true
    },

    name: {
        type: "string",
        required: true,
        length: 100
    },

    age: {
        type: "integer",
        min: 18,
        max: 65
    },

    email: {
        type: "string",
        format: "email"
    }
}

const obj = {
    id: "507f1f77bcf86cd799439011",
    name: "John",
    age: 30,
    email: "john@example.com"
}

const errors = validate(obj, User)

console.log(errors)

If validation succeeds:

[]

Otherwise:

[
    {
        field: "email",
        code: "email",
        message: "Email is invalid"
    }
]

Schema Definition

A schema consists of an Attributes object.

const Product: Attributes = {
    id: {
        type: "string",
        required: true
    },

    price: {
        type: "number",
        min: 0
    }
}

Supported Types

Type Description
ObjectId MongoDB ObjectId string
string String
text Long text
integer Integer number
number Decimal number
boolean Boolean
date Date only
datetime Date & time
time Time
object Nested object
array Array of objects
strings Array of strings
numbers Array of numbers
integers Array of integers
dates Array of dates
datetimes Array of datetimes
primitives Array of primitive values
binary Binary data

String Validation

username: {
    type: "string",
    required: true,
    min: 3,
    length: 50
}

Supports

  • required
  • minimum length
  • maximum length
  • regex
  • enum
  • format

Number Validation

price: {
    type: "number",
    min: 0,
    max: 1000,
    precision: 8,
    scale: 2
}

Supports

  • min
  • max
  • gt
  • lt
  • precision
  • scale

Enum Validation

status: {
    type: "string",
    enum: [
        "NEW",
        "ACTIVE",
        "DISABLED"
    ]
}

Date Validation

birthday: {
    type: "date",
    min: "1900-01-01"
}

appointment: {
    type: "datetime",
    min: "today"
}

Supported keywords

  • today
  • tomorrow
  • yesterday
  • now

Supported Formats

email: {
    type: "string",
    format: "email"
}

Available formats

Format
email
url
phone
fax
ipv4
ipv6

Regular Expression

zipcode: {
    type: "string",
    exp: /^[0-9]{5}$/
}

or

zipcode: {
    type: "string",
    exp: "^[0-9]{5}$"
}

Nested Objects

const Address = {
    street: {
        type: "string",
        required: true
    },

    city: {
        type: "string"
    }
}

const User = {
    name: {
        type: "string"
    },

    address: {
        type: "object",
        typeof: Address
    }
}

Validation is recursive.


Arrays

Array of objects

orders: {
    type: "array",
    typeof: Order
}

Array of strings

tags: {
    type: "strings"
}

Array of numbers

scores: {
    type: "numbers"
}

Array of integers

ids: {
    type: "integers"
}

PATCH Validation

When validating HTTP PATCH requests, required fields can be ignored.

validate(
    obj,
    UserSchema,
    undefined,
    false,
    true
)

or

check(
    obj,
    UserSchema,
    undefined,
    true
)

Localization

Validation messages are generated from a resource map.

Example:

const resources = {
    error_required: "{0} is required",
    error_email: "{0} is not a valid email"
}

Produces

Email is required

Email is not a valid email

Supports parameter substitution.

"{0} must be greater than {1}"

becomes

Age must be greater than 18

Validator Class

Instead of calling validate() directly, a reusable validator can be created.

const validator = createValidator(User)

const errors = await validator.validate(user)

Useful in dependency injection or service layers.


Error Format

interface ErrorMessage {
    field: string
    code: string
    param?: any
    message?: string
}

Example

[
    {
        "field": "age",
        "code": "min",
        "param": 18,
        "message": "Age must be greater than 18"
    }
]

Utility Functions

The library also exposes useful helpers.

isEmail()

isPhone()

isIPv4()

isIPv6()

isUrl()

formatDate()

trimTime()

addDays()

getToday()

Design Philosophy

This library follows a schema-first design.

Instead of decorators

class User {}

or fluent builders

z.object({...})

validation rules are defined using plain JavaScript objects.

Advantages include

  • framework independent
  • serializable schemas
  • dynamic schema generation
  • recursive validation
  • minimal runtime overhead
  • suitable for backend services and REST APIs

Typical Use Cases

  • REST API validation
  • Database model validation
  • Configuration validation
  • CLI input validation
  • JSON payload validation
  • Microservices
  • Express
  • Fastify
  • NestJS
  • Koa
  • Serverless Functions

🧱 Real Samples

🚀 Benchmark

See the benchmark source code at data-validation-benchmark

Rank Library Ops/sec RME (%) Samples Size (min+gz) Relative Speed (vs fastest) Times Slower than Ajv Note
🥇 1 Ajv 6,091,923 0.76% 100 📦 ~114 KB 🏆 1.00× (fastest) 🏆 1× ⚡ Fastest + Heavier bundle
🥈 2 validation-core 1,246,188 1.29% 92 ⚡ ~3.8 KB ~20.46% of Ajv ~4.9× 🔥 Very Fast + Small
🥉 3 Zod 939,381 0.31% 96 🧱 ~25 KB ~15.42% of Ajv ~6.5× 🐇 Fast + Medium Size
4 Valibot 859,490 0.24% 95 ⚡ ~4 KB ~14.11% of Ajv ~7.1× 🐇 Fast + Small Size
5 Joi 344,710 0.37% 93 📦 ~80 KB ~5.56% of Ajv ~17.7× 🐢 Slow + Heavy Size
6 Yup 115,048 0.34% 91 🧱 ~28 KB ~1.89% of Ajv ~52.9× 🐢 Slowest + Medium Size + Frontend-oriented

🔍 Key Insights

✅ Ajv

  • Top performer with ~6.09 million ops/sec.
  • Best for JSON Schema validation, high-throughput services.
  • Ideal for performance-critical Node.js or edge runtimes.

✅ validation-core

  • ~4.9x slower than Ajv, but ~1.3x faster than Zod, and even faster than Valibot.
  • validation-core is focused on bundle small size + performance, good for frontend.
  • Excellent TypeScript inference, flexible custom rules.
  • Very good for internal tools, low-code platforms, or apps that require typed validation

⚖️ Zod vs. Valibot

  • Nearly similar in ops/sec, suggesting similar architecture or design trade-offs.
  • Good for TypeScript-first developer experience but noticeably slower than Ajv/validation-core.
  • Both offer great DX.
  • Valibot is focused on bundle size + performance, good for frontend.
  • Zod still preferred if you need ecosystem maturity and developer ergonomics.

❌ Joi and Yup

  • Significantly slower, not suited for performance-sensitive applications.
  • Useful in some backend contexts (Joi) or form validation (Yup), but not recommended when performance matters.

🏁 Recommendation by Use Case

Use Case Library Reason
High-throughput backend APIs Ajv Fastest JSON Schema validator
Minimal frontend apps with type-safe apps and custom rules validation-core Good speed, excellent TypeScript integration
Minimal frontend apps Valibot Lightweight and efficient
DX-focused development Zod Clean syntax, popular, ideal for prototypes
Legacy/enterprise backend apps Joi Powerful features, but low performance
Form validation in React (Formik) Yup Integrated with form tools, but slow

📌 Summary

  • If you need speed: → Ajv
  • If you want typescript + good speed + small: → validation-core
  • If you prefer a big community support over speed: → Zod or Valibot
  • If you already use Formik or legacy stack: → Yup or Joi

📊 Feature Comparison

Feature / Library Ajv validation-core Zod Valibot Joi Yup
Required
Object / Nested validation
Array validation
Email format: "email" format: "email" .email() string([email()]) .email() .email()
URL format: "uri" format: "url" .url() string([url()]) .uri() .url()
IPv4 check format: "ipv4" format: "ipv4" ⚠️ Regex only ⚠️ Regex only .ip({ version: ["ipv4"] }) ⚠️ Regex only
IPv6 check format: "ipv6" format: "ipv6" ⚠️ Regex only ⚠️ Regex only .ip({ version: ["ipv6"] }) ⚠️ Regex only
Phone number ⚠️ No built-in — regex only format: "phone" ⚠️ No built-in — regex only ⚠️ No built-in — regex only ⚠️ No built-in — use .pattern() or .custom() with phone regex ⚠️ No built-in — use .matches() with regex
Fax number ⚠️ No built-in — regex only format: "fax" ⚠️ No built-in — regex only ⚠️ No built-in — regex only ⚠️ No built-in — use .pattern() or .custom() with phone regex ⚠️ No built-in — use .matches() with regex
Regex match pattern pattern .regex() string([regex(...)]) .pattern() .matches()
Enum values enum enum z.enum([...]) enumType() .valid(a,b,c) .oneOf([...])
Min/Max length (string)
Number type
Min/Max value (number/date)
Precision (decimal places) ⚠️ multipleOf precision: n ⚠️ .multipleOf() / .refine() ⚠️ .refine() .precision(n) ⚠️ .test()
Scale (integer + fraction limits) ⚠️ Custom scale: n ⚠️ Custom ⚠️ Custom ⚠️ Partial via .precision() + .max() ⚠️ Custom
Date type format: "date" / "date-time" type: "date" | "datetime" z.date() / .datetime() date() .date() .date()
Relative date (now/today/tomorrow/yesterday) ⚠️ Custom keyword min: "now" | "today" | "tomorrow" | "yesterday" ⚠️ .refine() ⚠️ .refine() .min('now') / .max('now') + Date values ⚠️ Custom .min() / .max()
Performance ⚡ Fastest 🔥 Fast 🐇 Good 🐇 Good 🐢 Slower 🐢 Slower
Bundle size (browser) Large (~60KB+, tree-shakeable) Small (~4KB) Medium (~20KB) Small (~6–8KB) Large (~70KB+) Medium (~30KB)
Best use case API validation, JSON Schema compliance API validation, JSON Schema compliance, minimal frontend TS-safe runtime validation Lightweight TS-safe validation Rich backend business rules Frontend form validation

🧱 More Examples

Example 1

import { Attributes, StringMap, validate } from "validation-core"

interface Resources {
  [key: string]: StringMap
}

const enResource: StringMap = {
  error_undefined: "{0} is not allowed to exist.",
  error_exp: "{0} does not match the regular expression.",
  error_type: "Invalid datatype. Type of {0} cannot be {1}.",

  error_required: "{0} is required.",
  error_minlength: "{0} cannot be less than {1} characters.",
  error_maxlength: "{0} cannot be greater than {1} characters.",

  error_email: "{0} is not a valid email address.",
  error_integer: "{0} is not a valid integer.",
  error_number: "{0} is not a valid number.",
  error_precision: "{0} has a valid precision. Precision must be less than or equal to {1}",
  error_scale: "{0} has a valid scale. Scale must be less than or equal to {1}",
  error_phone: "{0} is not a valid phone number.",
  error_fax: "{0} is not a valid fax number.",
  error_url: "{0} is not a valid URL.",
  error_ipv4: "{0} is not a valid ipv4.",
  error_ipv6: "{0} is not a valid ipv6.",

  error_min: "{0} must be greater than or equal to {1}.",
  error_max: "{0} must be less than or equal to {1}.",
  error_date: "{0} is not a valid date.",
  error_enum: "{0} must be one of {1}.",

  username: "Username",
  date_of_birth: "Date Of Birth",
  telephone: "Telephone",
  email: "Email",
  website: "Website",
  status: "User Status",
  credit_limit: "Credit Limit",
}

const viResource = {
  error_undefined: "{0} không được phép tồn tại.",
  error_exp: "{0} không khớp với biểu thức chính quy.",
  error_type: "Kiểu dữ liệu không hợp lệ. Kiểu của {0} không thể là {1}.",

  error_required: "{0} là bắt buộc.",
  error_minlength: "{0} không được ít hơn {1} ký tự.",
  error_maxlength: "{0} không được nhiều hơn {1} ký tự.",

  error_email: "{0} không phải là địa chỉ email hợp lệ.",
  error_integer: "{0} không phải là số nguyên hợp lệ.",
  error_number: "{0} không phải là số hợp lệ.",
  error_precision: "{0} có độ chính xác không hợp lệ. Độ chính xác phải nhỏ hơn hoặc bằng {1}.",
  error_scale: "{0} có thang đo không hợp lệ. Thang đo phải nhỏ hơn hoặc bằng {1}.",
  error_phone: "{0} không phải là số điện thoại hợp lệ.",
  error_fax: "{0} không phải là số fax hợp lệ.",
  error_url: "{0} không phải là URL hợp lệ.",
  error_ipv4: "{0} không phải là địa chỉ IPv4 hợp lệ.",
  error_ipv6: "{0} không phải là địa chỉ IPv6 hợp lệ.",

  error_min: "{0} phải lớn hơn hoặc bằng {1}.",
  error_max: "{0} phải nhỏ hơn hoặc bằng {1}.",
  error_date: "{0} không phải là ngày hợp lệ.",
  error_enum: "{0} phải là một trong các giá trị sau: {1}.",

  username: "Tên người dùng",
  date_of_birth: "Ngày sinh",
  telephone: "Điện thoại",
  email: "Địa chỉ email",
  website: "Trang web",
  status: "Trạng thái người dùng",
  credit_limit: "Hạn mức tín dụng",
}

const resources: Resources = {
  en: enResource,
  vi: viResource,
}

function getResource(lang: string): StringMap {
  return resources[lang] || resources["en"]
}
const resource = getResource("en") // or "vi" for Vietnamese

interface User {
  id: string
  username: string
  email?: string
  phone?: string
  ip?: string
  dateOfBirth?: Date
  website?: string
  creditLimit?: number
  status?: string[]
}

const userSchema: Attributes = {
  id: {
    length: 40,
  },
  username: {
    required: true,
    length: 255,
    resource: "username",
  },
  email: {
    format: "email",
    required: true,
    length: 120,
    resource: "email",
  },
  phone: {
    format: "phone",
    required: true,
    length: 14,
    resource: "telephone",
  },
  ip: {
    format: "ipv4",
    length: 15,
  },
  website: {
    length: 255,
    format: "url",
    resource: "website",
  },
  dateOfBirth: {
    type: "datetime",
  },
  creditLimit: {
    type: "number",
    scale: 2,
    min: 1,
    max: 200000,
    resource: "credit_limit",
  },
  status: {
    type: "strings",
    enum: ["active", "inactive", "online", "offline", "away"],
    resource: "status",
  },
}

const invalidUser = {
  id: "12345678901234567890123456789012345678901", // 41 characters => maximum 40 => invalid
  // username: "james.howlett", // required => invalid
  email: "james.howlett@gmail", // invalid email
  phone: "abcd1234", // required => invalid
  ip: "abcd1234", // invalid => not required
  website: "invalid website",
  dateOfBirth: "1974-03-25", // valid date => the library will convert to date
  creditLimit: 10000000.255, // invalid precision and scale => precision must be less than or equal to 10 digits
  status: ["active", "busy"],
  age: 50, // does not exist in schema => invalid
}
let errors = validate(invalidUser, userSchema, resource)
console.log("Validate James Howlett: ", errors)

const user: User = {
  id: "1234567890123456789012345678901234567890",
  username: "tony.stark",
  email: "tony.stark@gmail.com",
  phone: "+1234567890",
  website: "/core-ts",
  dateOfBirth: new Date("1963-03-25"),
  creditLimit: 100000.25,
  status: ["active", "online"],
}
errors = validate(user, userSchema, resource, true)
console.log("Validate Tony Stark (no error): ", errors) // should be empty

Out put is:

Validate James Howlett:  [
  {
    field: 'id',
    code: 'maxlength',
    message: 'id cannot be greater than 40 characters.',
    param: 40
  },
  {
    field: 'email',
    code: 'email',
    message: 'Email is not a valid email address.'
  },
  {
    field: 'phone',
    code: 'phone',
    message: 'Telephone is not a valid phone number.'
  },
  { field: 'ip', code: 'ipv4', message: 'ip is not a valid ipv4.' },
  {
    field: 'website',
    code: 'url',
    message: 'Website is not a valid URL.'
  },
  {
    field: 'creditLimit',
    code: 'scale',
    message: 'Credit Limit has a valid scale. Scale must be less than or equal to 2'
  },
  {
    field: 'creditLimit',
    code: 'max',
    message: 'Credit Limit must be less than or equal to 200000.',
    param: 200000
  },
  {
    field: 'status',
    code: 'enum',
    message: 'User Status must be one of active, inactive, online, offline, away.',
    param: 'active, inactive, online, offline, away'
  },
  {
    field: 'age',
    code: 'undefined',
    message: 'age is not allowed to exist.'
  },
  {
    field: 'username',
    code: 'required',
    message: 'Username is required.'
  }
]
Validate Tony Stark (no error):  []

Example 2

import { Attributes, StringMap, validate } from "validation-core"

interface Resources {
  [key: string]: StringMap
}

const enResource: StringMap = {
  error_undefined: "{0} is not allowed to exist.",
  error_exp: "{0} does not match the regular expression.",
  error_type: "Invalid datatype. Type of {0} cannot be {1}.",

  error_boolean: "{0} cannot be boolean.",
  error_strings: "{0} must be an string array.",
  error_numbers: "{0} must be an number array.",
  error_integers: "{0} must be an number array.",
  error_datetimes: "{0} must be an date time array.",
  error_dates: "{0} must be an date array.",

  error_required: "{0} is required.",
  error_minlength: "{0} cannot be less than {1} characters.",
  error_maxlength: "{0} cannot be greater than {1} characters.",
  error_array_min: "Length of {0} cannot be less than {1}.",
  error_array_max: "Length of {0} cannot be greater than {1}.",

  error_email: "{0} is not a valid email address.",
  error_integer: "{0} is not a valid integer.",
  error_number: "{0} is not a valid number.",
  error_precision: "{0} has a valid precision. Precision must be less than or equal to {1}",
  error_scale: "{0} has a valid scale. Scale must be less than or equal to {1}",
  error_phone: "{0} is not a valid phone number.",
  error_fax: "{0} is not a valid fax number.",
  error_url: "{0} is not a valid URL.",
  error_ipv4: "{0} is not a valid ipv4.",
  error_ipv6: "{0} is not a valid ipv6.",

  error_min: "{0} must be greater than or equal to {1}.",
  error_max: "{0} must be less than or equal to {1}.",
  error_gt: "{0} must be greater than {1}.",
  error_lt: "{0} must be less than {1}.",
  error_date: "{0} is not a valid date.",
  error_enum: "{0} must be one of {1}.",

  date_of_birth: "Date Of Birth",
  telephone: "Telephone",
  email: "Email",
  website: "Website",
  status: "User Status",
  state: "State",
  zip: "Zip Code",
  zip_code: "Zip code is not valid.",
  quality: "Quality",
  level: "Level",
}

const viResource = {
  error_undefined: "{0} không được phép tồn tại.",
  error_exp: "{0} không khớp với biểu thức chính quy.",
  error_type: "Kiểu dữ liệu không hợp lệ. Kiểu của {0} không thể là {1}.",

  error_boolean: "{0} không thể là kiểu boolean.",
  error_strings: "{0} phải là một mảng chuỗi.",
  error_numbers: "{0} phải là một mảng số.",
  error_integers: "{0} phải là một mảng số nguyên.",
  error_datetimes: "{0} phải là một mảng ngày giờ.",
  error_dates: "{0} phải là một mảng ngày.",

  error_required: "{0} là bắt buộc.",
  error_minlength: "{0} không được ít hơn {1} ký tự.",
  error_maxlength: "{0} không được nhiều hơn {1} ký tự.",
  error_array_min: "Độ dài của {0} không được nhỏ hơn {1}.",
  error_array_max: "Độ dài của {0} không được lớn hơn {1}.",

  error_email: "{0} không phải là địa chỉ email hợp lệ.",
  error_integer: "{0} không phải là số nguyên hợp lệ.",
  error_number: "{0} không phải là số hợp lệ.",
  error_precision: "{0} có độ chính xác không hợp lệ. Độ chính xác phải nhỏ hơn hoặc bằng {1}.",
  error_scale: "{0} có thang đo không hợp lệ. Thang đo phải nhỏ hơn hoặc bằng {1}.",
  error_phone: "{0} không phải là số điện thoại hợp lệ.",
  error_fax: "{0} không phải là số fax hợp lệ.",
  error_url: "{0} không phải là URL hợp lệ.",
  error_ipv4: "{0} không phải là địa chỉ IPv4 hợp lệ.",
  error_ipv6: "{0} không phải là địa chỉ IPv6 hợp lệ.",

  error_min: "{0} phải lớn hơn hoặc bằng {1}.",
  error_max: "{0} phải nhỏ hơn hoặc bằng {1}.",
  error_gt: "{0} phải lớn hơn {1}.",
  error_lt: "{0} phải nhỏ hơn {1}.",
  error_date: "{0} không phải là ngày hợp lệ.",
  error_enum: "{0} phải là một trong các giá trị sau: {1}.",

  date_of_birth: "Ngày sinh",
  telephone: "Điện thoại",
  email: "Địa chỉ email",
  website: "Trang web",
  status: "Trạng thái người dùng",
  state: "Tiểu bang",
  zip: "Mã bưu điện",
  zip_code: "Mã bưu điện không hợp lệ.",
  quality: "Chất lượng",
  level: "Cấp độ",
}

const resources: Resources = {
  en: enResource,
  vi: viResource,
}

function getResource(lang: string): StringMap {
  return resources[lang] || resources["en"]
}
const resource = getResource("en")

interface Skill {
  skill: string
  level: number
}
interface Achievement {
  subject: string
  description: string
  quality: string
  skills?: Skill[]
}
interface Address {
  street: string
  city: string
  state: string
  zip: string
}
interface User {
  id: string
  username: string
  email?: string
  phone?: string
  dateOfBirth?: Date
  website?: string
  creditLimit?: number
  status?: string[]
  address?: Address
  achievements?: Achievement[]
}

const skillSchema: Attributes = {
  skill: {
    required: true,
    length: 15,
  },
  level: {
    required: true,
    type: "integer",
    enum: [1, 2, 3, 4, 5],
    resource: "level",
  },
}
const achievementSchema: Attributes = {
  subject: {
    required: true,
    length: 255,
  },
  description: {
    required: true,
    length: 255,
  },
  quality: {
    required: true,
    length: 255,
    enum: ["Excellent", "Good", "Average", "Poor", "Very Poor"],
    resource: "quality",
  },
  skills: {
    type: "array",
    typeof: skillSchema,
  },
}

const addressSchema: Attributes = {
  street: {
    required: true,
    length: 255,
  },
  city: {
    required: true,
    length: 255,
  },
  state: {
    length: 2,
    exp: /^[A-Z]{2}$/,
    // resource: "State is not valid.",
  },
  zip: {
    exp: /(^\d{5}$)|(^\d{5}-\d{4}$)/,
    resource: "zip_code",
  },
}
const userSchema: Attributes = {
  id: {
    length: 40,
  },
  username: {
    required: true,
    length: 255,
  },
  email: {
    format: "email",
    required: true,
    length: 120,
    resource: "email",
  },
  phone: {
    format: "phone",
    required: true,
    length: 14,
    resource: "telephone",
  },
  website: {
    length: 255,
    format: "url",
    resource: "website",
  },
  dateOfBirth: {
    type: "datetime",
  },
  creditLimit: {
    type: "number",
    precision: 10,
    scale: 2,
    min: 1,
  },
  status: {
    type: "strings",
    enum: ["active", "inactive", "online", "offline", "away"],
    resource: "status",
  },
  address: {
    type: "object",
    typeof: addressSchema,
  },
  achievements: {
    type: "array",
    typeof: achievementSchema,
  },
}

let errors = validate(
  {
    username: "james.howlett",
    email: "james.howlett@gmail", // invalid email
    phone: "", // required => invalid
    website: "https://james.howlett.com",
    dateOfBirth: "1974-03-25", // valid date => the library will convert to date
    age: 50, // does not exist in schema => invalid
  },
  userSchema,
  resource,
)
console.log("Validate James Howlett: ", errors)

const user: User = {
  id: "1234567890123456789012345678901234567890",
  username: "tony.stark",
  email: "tony.stark@gmail.com",
  phone: "+1234567890",
  website: "/core-ts",
  dateOfBirth: new Date("1963-03-25"),
  creditLimit: 100000.25,
  status: ["active", "online"],
  address: {
    street: "123 Stark Tower",
    city: "New York",
    state: "NY",
    zip: "07008",
  },
  achievements: [
    {
      subject: "Avengers",
      description: "Leader of the Avengers team",
      quality: "Excellent",
      skills: [
        {
          skill: "Leadership",
          level: 5,
        },
        {
          skill: "Technology",
          level: 4,
        },
        {
          skill: "Martial Arts",
          level: 3,
        },
      ],
    },
    {
      subject: "Iron Suite",
      description: "Iron Armor Suit",
      quality: "Excellent",
    },
  ],
}
errors = validate(user, userSchema, resource, true)
console.log("Validate Tony Stark (no error): ", errors) // should be empty

const invalidUser: User = {
  id: "12345678901234567890123456789012345678901", // 41 characters => maximum 40 => invalid
  username: "peter.parker",
  email: "test", // invalid email
  phone: "abcd1234", // invalid phone number
  website: "wrong url", // invalid URL
  dateOfBirth: new Date("1962-08-25"),
  creditLimit: 10000000.255, // invalid precision and scale => precision must be less than or equal to 10 digits
  status: ["active", "busy"],
  address: {
    street: "123 Stark Tower",
    city: "New York",
    state: "New York",
    zip: "999999", // invalid zip code, does not match regex
  },
  achievements: [
    {
      subject: "Avengers",
      description: "Member of the Avengers team",
      quality: "Normal", // invalid quality, must be one of ["Excellent", "Good", "Average", "Poor", "Very Poor"]
      skills: [
        {
          skill: "Technology",
          level: 5,
        },
        {
          skill: "Martial Arts",
          level: 6, // invalid level, must be be one of [1, 2, 3, 4, 5]
        },
      ],
    },
  ],
}

errors = validate(invalidUser, userSchema, resource, true)
console.log("Validate Peter Parker: ", errors)

Out put is:

Validate James Howlett:  [
  {
    field: 'email',
    code: 'email',
    message: 'Email is not a valid email address.'
  },
  {
    field: 'phone',
    code: 'required',
    message: 'Telephone is required.'
  },
  {
    field: 'age',
    code: 'undefined',
    message: 'age is not allowed to exist.'
  }
]
Validate Tony Stark (no error):  []
Validate Peter Parker:  [
  {
    field: 'id',
    code: 'maxlength',
    message: 'id cannot be greater than 40 characters.',
    param: 40
  },
  {
    field: 'email',
    code: 'email',
    message: 'Email is not a valid email address.'
  },
  {
    field: 'phone',
    code: 'phone',
    message: 'Telephone is not a valid phone number.'
  },
  {
    field: 'website',
    code: 'url',
    message: 'Website is not a valid URL.'
  },
  {
    field: 'creditLimit',
    code: 'precision',
    message: 'creditLimit has a valid precision. Precision must be less than or equal to 10'
  },
  {
    field: 'status',
    code: 'enum',
    message: 'User Status must be one of active, inactive, online, offline, away.',
    param: 'active, inactive, online, offline, away'
  },
  {
    field: 'address.state',
    code: 'maxlength',
    message: 'state cannot be greater than 2 characters.',
    param: 2
  },
  {
    field: 'address.state',
    code: 'exp',
    message: 'state does not match the regular expression.'
  },
  { field: 'address.zip', code: 'exp', message: 'zip_code' },
  {
    field: 'achievements[0].quality',
    code: 'enum',
    message: 'Quality must be one of Excellent, Good, Average, Poor, Very Poor.',
    param: 'Excellent, Good, Average, Poor, Very Poor'
  },
  {
    field: 'achievements[0].skills[1].level',
    code: 'enum',
    message: 'Level must be one of 1, 2, 3, 4, 5.',
    param: '1, 2, 3, 4, 5'
  }
]

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages