Arrow keys: ← previous · → next 34 of 35
@nodedk/validate
0.4.2 stable

validate#

Validate JavaScript data with small, declarative rule objects.

Install#

npm i @nodedk/validate

Usage#

var validate = require('@nodedk/validate')

var schema = {
  name: {
    required: true,
    is: 'string'
  },
  age: {
    is: 'integer',
    gte: 18
  }
}

var data = {
  name: 'Kim',
  age: 32
}

var issues = validate(schema, data)
// null

validate(schema, data) is synchronous and leaves data unchanged. schema maps field paths to rule objects; data is the object to inspect. Unknown rule names are ignored. Validation returns null when the data is valid. Otherwise, it returns issues grouped by their concrete field paths:

var data = {
  age: 15
}

var issues = validate(schema, data)
// {
//   name: [{ rule: 'required' }],
//   age: [{ rule: 'gte', value: 18 }]
// }

Most rules skip missing fields. Use required: true when a field must exist. A present null value is not considered missing; is: 'null' requires an explicitly present null value.

Nested fields#

Use dotted paths for nested object fields:

var schema = {
  user: {
    required: true,
    is: 'object'
  },
  'user.profile.email': {
    required: true,
    is: 'email'
  }
}

var data = {
  user: {
    profile: {
      email: 'kim@example.com'
    }
  }
}

validate(schema, data)
// null

Known array indices use the same notation:

var schema = {
  'users.0.email': {
    required: true,
    is: 'email'
  }
}

Wildcards#

* matches every immediate child of an array or object.

Arrays#

Validate every item in an array:

var schema = {
  tags: {
    required: true,
    is: 'array',
    min: 1
  },
  'tags.*': {
    is: 'string'
  }
}

var data = {
  tags: ['node', 42, false]
}

var issues = validate(schema, data)
// {
//   'tags.1': [{ rule: 'is', value: 'string' }],
//   'tags.2': [{ rule: 'is', value: 'string' }]
// }

Objects#

Wildcards also validate every value in an object:

var schema = {
  'flags.*': {
    is: 'boolean'
  }
}

var data = {
  flags: {
    admin: true,
    editor: 'yes',
    beta: false
  }
}

var issues = validate(schema, data)
// {
//   'flags.editor': [{ rule: 'is', value: 'boolean' }]
// }

Arrays of objects#

var schema = {
  users: {
    is: 'array'
  },
  'users.*': {
    is: 'object'
  },
  'users.*.email': {
    required: true,
    is: 'email'
  }
}

var data = {
  users: [{ email: 'a@example.com' }, { email: 'invalid' }, {}]
}

var issues = validate(schema, data)
// {
//   'users.1.email': [{ rule: 'is', value: 'email' }],
//   'users.2.email': [{ rule: 'required' }]
// }

Nested arrays and objects#

Use multiple wildcards for data with several collection levels:

var schema = {
  'companies.*.teams.*.members.*.email': {
    required: true,
    is: 'email'
  }
}

var data = {
  companies: {
    nodedk: {
      teams: [
        {
          members: [{ email: 'ok@example.com' }, { email: 'invalid' }]
        }
      ]
    }
  }
}

var issues = validate(schema, data)
// {
//   'companies.nodedk.teams.0.members.1.email': [
//     { rule: 'is', value: 'email' }
//   ]
// }

Consecutive wildcards validate nested arrays:

var schema = {
  matrix: {
    is: 'array'
  },
  'matrix.*': {
    is: 'array'
  },
  'matrix.*.*': {
    is: 'number'
  }
}

An empty object or array has no wildcard matches. Use min, max, or length on the collection itself when its size matters.

Wildcard paths only validate branches that exist. Require each parent whose existence matters, and use min: 1 when a collection must contain an item:

var schema = {
  companies: {
    required: true,
    is: 'object'
  },
  'companies.*.teams': {
    required: true,
    is: 'array',
    min: 1
  },
  'companies.*.teams.*.email': {
    required: true,
    is: 'email'
  }
}

Fixed paths do not have this restriction. Requiring user.profile.email reports an issue at that path when any part of the fixed chain is missing.

Common rules#

Rules can be combined on the same field:

var schema = {
  username: {
    required: true,
    is: 'string',
    min: 3,
    max: 30,
    format: /^[a-z0-9-]+$/
  },
  score: {
    is: 'number',
    gte: 0,
    lte: 100
  },
  status: {
    in: ['active', 'disabled']
  }
}

Each rule’s value is its expected value or configuration:

  • required: true: reject undefined. Allows null and empty strings; combine with is and min when those should be rejected.
  • is: type or is: [type, ...]: accept any listed type. Unknown type names pass. Missing values are skipped unless the list contains null or undefined; null alone requires an explicit null value.
  • isnt: type or isnt: [type, ...]: inverse of is, including its handling of missing values.
  • eq: value, ne: value: strict equality or inequality; objects compare by identity, not contents.
  • gt: value, gte: value, lt: value, lte: value: direct JavaScript comparisons. Combine with is to constrain the value’s type.
  • in: values, nin: values: membership in an array using indexOf. nin allows null even if listed.
  • length: number: exact .length.
  • min: number, max: number: inclusive .length bounds. Use with strings and arrays; ordinary objects do not have a length.
  • format: regexp: call regexp.test(value). Use a RegExp without g or y when reusing a schema, since those flags advance its internal position.
  • dateformat: string: exact calendar/time representation; see Dates below.

Rules other than required, is, and isnt skip undefined. Comparison, length, and format rules reject null. All failing rules are collected in schema order. Issues have { rule, value }, except required, which has only { rule: 'required' }.

Types#

Use is to validate a value's type or format:

var schema = {
  email: {
    is: 'email'
  },
  count: {
    is: 'integer'
  },
  enabled: {
    is: 'boolean'
  }
}

Several types can be allowed:

var schema = {
  result: {
    is: ['string', 'null']
  }
}

Type reference#

  • array — an array, as determined by Array.isArray.
  • base64 — a standard padded Base64 string. URL-safe Base64 is not accepted.
  • boolean — true or false.
  • date — a valid JavaScript Date object. Date strings are not accepted.
  • datestring — a valid UTC timestamp ending in Z, with up to nine fractional-second digits.
  • decimal — a JavaScript number other than NaN that is not an integer.
  • domain — a string such as example.com or api.example.com.
  • email — a string with text before and after @ and a domain suffix.
  • hex — a non-empty hexadecimal string.
  • id — any string or integer. It does not require UUID syntax.
  • integer — a number accepted by Number.isInteger.
  • ip — an IPv4 or IPv6 address.
  • ipv4 — an IPv4 address.
  • ipv6 — an IPv6 address.
  • isodate — a valid calendar date in YYYY-MM-DD form.
  • null — exactly null.
  • number — any JavaScript number except NaN, including integers.
  • object — any non-null object that is not an array.
  • slug — lowercase letters and numbers separated by single hyphens, such as my-page-2.
  • string — any JavaScript string, including an empty string.
  • undefined — exactly undefined, including a missing fixed field.
  • url — an HTTP or HTTPS URL string.
  • uuid — any 8-4-4-4-12 hexadecimal UUID string, regardless of version.
  • uuidv7 — an 8-4-4-4-12 hexadecimal UUID string with version 7.

date and undefined describe JavaScript values that do not survive a JSON serialize-and-parse cycle in the same form.

Dates#

Use isodate for calendar dates without a time or timezone:

var schema = {
  birthday: {
    is: 'isodate'
  }
}

validate(schema, { birthday: '2026-07-19' })
// null

Use datestring for UTC timestamps:

var schema = {
  created: {
    is: 'datestring'
  }
}

validate(schema, { created: '2026-07-19T12:30:00.123456789Z' })
// null

datestring rejects local timestamps and numeric timezone offsets. It accepts seconds with an optional fraction containing one to nine digits.

Use dateformat for an exact custom representation:

var schema = {
  published: {
    dateformat: 'YYYY-MM-DD HH:mm:ss'
  }
}

validate(schema, { published: '2026-07-19 14:30:00' })
// null

dateformat supports YYYY, MM, DD, HH, mm, ss, and SSS. Other characters are treated as literals. Calendar dates and time ranges are validated after the format is matched.

Path conventions#

  • Dots separate path segments.
  • Numeric segments address known array indices.
  • * matches every immediate own child of an object or array.
  • Dots and literal * segments are not supported in data keys.
  • Extra fields that do not appear in the schema are ignored.

Created by Vidar Eldøy