{"_id":"@alxandr/validated","_rev":"1-99c84644a136e6fd23e742ceaaa2622b","name":"@alxandr/validated","dist-tags":{"latest":"2.0.0"},"versions":{"2.0.0":{"name":"@alxandr/validated","version":"2.0.0","description":"JSON configuration utilities","bin":{"validated":"./lib/bin/validated.js"},"scripts":{"test":"make build lint check test","precommit":"npm run test","prepublishOnly":"npm run test"},"files":["lib/","json5.js","object.js","schema.js","repr.js"],"repository":{"type":"git","url":"git+https://github.com/andreypopp/validated.git"},"author":{"name":"Andrey Popp","email":"8mayday@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/andreypopp/validated/issues"},"homepage":"https://github.com/andreypopp/validated#readme","devDependencies":{"@babel/cli":"^7.0.0-beta.54","@babel/core":"^7.0.0-beta.54","@babel/plugin-proposal-class-properties":"^7.0.0-beta.54","@babel/preset-env":"^7.0.0-beta.54","@babel/preset-flow":"^7.0.0-beta.54","@babel/register":"^7.0.0-beta.54","babel-eslint":"^8.2.6","doctoc":"^1.3.1","eslint":"^5.1.0","eslint-config-prettier":"^2.9.0","eslint-plugin-flowtype":"^2.50.0","eslint-plugin-prettier":"^2.6.2","eslint-plugin-react":"^7.10.0","flow-bin":"^0.76.0","husky":"^0.14.3","mocha":"^5.2.0","mocha-doctest":"^0.3.4","prettier":"^1.13.7"},"dependencies":{"commander":"^2.16.0","custom-error-instance":"^2.1.1","indent-string":"^3.2.0","invariant":"^2.2.4","levenshtein-edit-distance":"^2.0.2"},"publishConfig":{"access":"public"},"gitHead":"7ae10668434afbc11167be663295ff8300a6744d","_id":"@alxandr/validated@2.0.0","_npmVersion":"6.1.0","_nodeVersion":"10.6.0","_npmUser":{"name":"alxandr","email":"alxandr@alxandr.me"},"dist":{"integrity":"sha512-vUbrbQ9O2xkjHcY5qkAB8A40c/wX/jViQ5omIwT7/VyYoGhOfQzeOo2oHK6lo4fDDNzapQJtUPK9Rh0MnGNnzg==","shasum":"dc1d755d0017d6411f22a77d6d42243820c43a9d","tarball":"https://registry.npmjs.org/@alxandr/validated/-/validated-2.0.0.tgz","fileCount":20,"unpackedSize":100687,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbTcvJCRA9TVsSAnZWagAAoUgQAJ6JEDhpx5NxFzsr/pS4\nOoDjUJDMWJH/h0Mx2MwXS3SrUW72OgOxd7/7U8I2vDtNwKmQysBorjE3mrNJ\nyJAJ6nioIOynHlaZxZFPsJWvTacSJtHyUhr7KfleAFgjbksn7o2NN6ACgo5Y\nNKTMiVxa91mCxxlhSY6vsafPDpFhchPt1wiLXtZtPQFKxtrRhYm+r9HCa029\n0k6xIjt9XXZ2d6ydrGawGwWxALZMK4bL2sT6pZ0Q7K6gQhVfD/QmcOnsHWh/\ncTlz6W6pxluTxbRtDd2iOdkjlEM/EIv9UgxNtgqScRk1n+YZcg+AhG43XBhV\nPy42NUDV0f5vPDlG+QHs7M4WkKFBmExSfoV1o5MKbcReI5CWIl6jKKUBmdEf\nO/Vaw4dn5vmrJxaP8u1qjF+9I2cWrDylcWfuLhTJuuRECxA94PhNnne35nwj\nfy6FAiWEohHKuqfVumydBF6pNPslvgcmca9aDQTBbmZTlnkcfnj09rZ6EUpm\n1qeeww3rP4gBX6SwnDMTw7+S3X8tGXFl+xPg/qhDMp74q2hWePJmx3/sgXEH\nkRLr29QcDDQlbSP6szRVikjZHePezM4konmQgkNt7GzsdJZxikWMvD6hDqsn\nVkdNsv3i0tKJR4GZHqT6Ow807YjCM+2oPiG8T8nj48G4MhJcitJs6Bf9BB2z\nT364\r\n=KR8N\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB8XOGs/kdthKeOHMe7NtgbjpOneeXhq+UucnBiKjH1fAiAQSLPPUekwhz2GIwenEdHSoa42IFSbn77syLnYspoleg=="}]},"maintainers":[{"name":"alxandr","email":"alxandr@alxandr.me"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/validated_2.0.0_1531825097199_0.545517309163519"},"_hasShrinkwrap":false}},"time":{"created":"2018-07-17T10:58:16.975Z","2.0.0":"2018-07-17T10:58:17.339Z","modified":"2022-04-04T13:42:09.256Z"},"maintainers":[{"name":"alxandr","email":"alxandr@alxandr.me"}],"description":"JSON configuration utilities","homepage":"https://github.com/andreypopp/validated#readme","repository":{"type":"git","url":"git+https://github.com/andreypopp/validated.git"},"author":{"name":"Andrey Popp","email":"8mayday@gmail.com"},"bugs":{"url":"https://github.com/andreypopp/validated/issues"},"license":"MIT","readme":"# validated\n\n[![Join the chat at https://gitter.im/andreypopp/sitegen](https://img.shields.io/badge/gitter-join%20chat-green.svg)](https://gitter.im/andreypopp/sitegen)\n[![Travis build status](https://img.shields.io/travis/andreypopp/validated/master.svg)](https://travis-ci.org/andreypopp/validated)\n[![Type System](https://img.shields.io/badge/typesystem-flowtype-green.svg)](http://flowtype.org/)\n\nValidate your configurations with precise error messages:\n\n* Define schema with validators which are agnostic to the actual representation\n  of data, be it a JSON string, object in memory or any other format.\n\n* Use schema with runners specific for formats (object and JSON5 runners are\n  included). Get error messages with precise info (line and column numbers for\n  example).\n\n* Get the result of a validation as an object: either a plain JSON or some\n  domain specific classes if schema is defined in that way.\n\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**\n\n- [Installation](#installation)\n- [Usage](#usage)\n  - [Schema](#schema)\n  - [List of schema primitives](#list-of-schema-primitives)\n      - [`any`](#any)\n      - [`string`, `number`, `boolean`](#string-number-boolean)\n      - [`enumeration`](#enumeration)\n      - [`mapping`](#mapping)\n      - [`arrayOf`](#arrayof)\n      - [`object`](#object)\n      - [`partialObject`](#partialobject)\n      - [`maybe`](#maybe)\n      - [`oneOf`](#oneof)\n      - [`recur`](#recur)\n  - [Refining validations](#refining-validations)\n  - [Defining new schema types](#defining-new-schema-types)\n  - [Integration with FlowType](#integration-with-flowtype)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## Installation\n\n```\n% npm install validated\n```\n\n## Usage\n\n### Schema\n\nSchema is defined with validators which are agnostic to the actual\nrepresentation of data, be it a JSON string or an object in memory:\n\n```js+test\nimport {\n  mapping, arrayOf, object, partialObject, oneOf, maybe, enumeration, recur,\n  any, string, number, boolean\n} from 'validated/schema'\n```\n\nThere's schema validator for JSON objects in memory:\n\n```js+test\nimport {\n  validate as validateObject\n} from 'validated/object'\n```\n\nAnd schema validator for strings with JSON/JSON5 encoded data:\n\n```js+test\nimport {\n  validate as validateJSON5\n} from 'validated/json5'\n```\n\nLet's define some schema first:\n```js+test\nlet person = object({\n  name: string,\n  age: number,\n})\n\nlet pet = object({\n  nickName: string,\n  age: number,\n})\n\nlet collection = arrayOf(oneOf(person, pet))\n\nvalidateJSON5(collection, '[{name: \"John\", age: 26}, {nickName: \"Tima\", age: 3}]')\n// => [ { name: 'John', age: 26 }, { nickName: 'Tima', age: 3 } ]\n\nvalidateObject(collection, [{name: \"John\", age: 26}, {nickName: \"Tima\", age: 3}])\n// => [ { name: 'John', age: 26 }, { nickName: 'Tima', age: 3 } ]\n```\n\n### List of schema primitives\n\n##### `any`\n\nValidates any value but not `undefined` or `null`:\n\n```js+test\nvalidateObject(any, 'ok')\n// => 'ok'\n\nvalidateObject(any, 42)\n// => 42\n\nvalidateObject(any, null)\n// ValidationError: Expected a value but got null\n\nvalidateObject(any, undefined)\n// ValidationError: Expected a value but got undefined\n```\n\nIf you want to validated any value and even an absence of one then wrap it in\n`maybe`:\n\n```js+test\nvalidateObject(maybe(any), null)\n// => null\n\nvalidateObject(maybe(any), undefined)\n// => undefined\n```\n\n##### `string`, `number`, `boolean`\n\nValidate strings, numbers and booleans correspondingly.\n\n```js+test\nvalidateObject(string, 'ok')\n// => 'ok'\n\nvalidateObject(number, 42)\n// => 42\n\nvalidateObject(boolean, true)\n// => true\n```\n\n##### `enumeration`\n\nValidate enumerations:\n\n```js+test\nvalidateObject(enumeration('yes', 'no'), 'yes')\n// => 'yes'\n\nvalidateObject(enumeration('yes', 'no'), 'no')\n// => 'no'\n\nvalidateObject(enumeration('yes', 'no'), 'oops')\n// ValidationError: Expected value to be one of \"yes\", \"no\" but got \"oops\"\n```\n\n##### `mapping`\n\nValidate mappings from string keys to values.\n\nUntyped values (value validator defaults to `any`):\n\n```js+test\nvalidateObject(mapping(), {})\n// => {}\n\nvalidateObject(mapping(), {a: 1, b: 'ok'})\n// => { a: 1, b: 'ok' }\n\nvalidateObject(mapping(), 'oops')\n// ValidationError: Expected a mapping but got string\n```\n\nTyped value:\n\n```js+test\nvalidateObject(mapping(number), {a: 1})\n// => { a: 1 }\n\nvalidateObject(mapping(number), {a: 1, b: 'ok'})\n// ValidationError: Expected value of type number but got string\n// While validating value at key \"b\"\n```\n\n##### `arrayOf`\n\nValidate arrays.\n\nUntyped values (value validator defaults to `any`):\n\n```js+test\nvalidateObject(arrayOf(any), [])\n// => []\n\nvalidateObject(arrayOf(any), [1, 2, 'ok'])\n// => [ 1, 2, 'ok' ]\n\nvalidateObject(arrayOf(any), 'oops')\n// ValidationError: Expected an array but got string\n```\n\nTyped value:\n\n```js+test\nvalidateObject(arrayOf(number), [1, 2])\n// => [ 1, 2 ]\n\nvalidateObject(arrayOf(number), [1, 2, 'ok'])\n// ValidationError: Expected value of type number but got string\n// While validating value at index 2\n```\n\n##### `object`\n\nValidate objects, objects must specify validator for each of its keys:\n\n```js+test\nlet person = object({\n  name: string,\n  age: number,\n})\n\nvalidateObject(person, {name: 'john', age: 27})\n// => { name: 'john', age: 27 }\n\nvalidateObject(person, {name: 'john'})\n// ValidationError: Expected value of type number but got undefined\n// While validating missing value for key \"age\"\n\nvalidateObject(person, {name: 'john', age: 'notok'})\n// ValidationError: Expected value of type number but got string\n// While validating value at key \"age\"\n\nvalidateObject(person, {name: 'john', age: 42, extra: 'oops'})\n// ValidationError: Unexpected key: \"extra\"\n// While validating key \"extra\"\n\nvalidateObject(person, {nam: 'john', age: 42})\n// ValidationError: Unexpected key: \"nam\", did you mean \"name\"?\n// While validating key \"nam\"\n```\n\nIf some key is optional, wrap its validator in `maybe`:\n\n```js+test\nlet person = object({\n  name: string,\n  age: number,\n  nickName: maybe(string),\n})\n\nvalidateObject(person, {name: 'john', age: 27})\n// => { name: 'john', age: 27 }\n\nvalidateObject(person, {name: 'john', age: 27, nickName: 'J'})\n// => { name: 'john', age: 27, nickName: 'J' }\n```\n\nYou can also specify default values for keys:\n\n```js+test\nlet person = object({\n  name: string,\n  age: number,\n  nickName: string,\n}, {\n  nickName: 'John Doe'\n})\n\nvalidateObject(person, {name: 'john', age: 27})\n// => { name: 'john', age: 27, nickName: 'John Doe' }\n\nvalidateObject(person, {name: 'john', age: 27, nickName: 'J'})\n// => { name: 'john', age: 27, nickName: 'J' }\n```\n\n##### `partialObject`\n\nValidate a subset of the keys from the object, passing all extra keys through:\n\n```js+test\nlet person = partialObject({\n  name: string,\n  age: number,\n})\n\nvalidateObject(person, {name: 'john', age: 27})\n// => { name: 'john', age: 27 }\n\nvalidateObject(person, {name: 'john', age: 42, extra: 'ok'})\n// => { name: 'john', age: 42, extra: 'ok' }\n```\n\n##### `maybe`\n\nValidates `null` and `undefined` but passes through any other value to the\nunderlying validator:\n\n```js+test\nvalidateObject(maybe(string), null)\n// => null\n\nvalidateObject(maybe(string), undefined)\n// => undefined\n\nvalidateObject(maybe(string), 'ok')\n// => 'ok'\n\nvalidateObject(maybe(string), 42)\n// ValidationError: Expected value of type string but got number\n```\n\n##### `oneOf`\n\nTries a multiple validators and choose the one which succeeds first:\n\n```js+test\nvalidateObject(oneOf(string, number), 'ok')\n// => 'ok'\n\nvalidateObject(oneOf(string, number), 42)\n// => 42\n\nvalidateObject(oneOf(string, number), true)\n// ValidationError: Either:\n//\n//   Expected value of type string but got boolean\n//\n//   Expected value of type number but got boolean\n//\n```\n\n##### `recur`\n\nAllows to define recursive validators:\n\n```js+test\nlet tree = recur(tree =>\n  object({\n    value: any,\n    children: maybe(arrayOf(tree))\n  })\n)\n\nvalidateObject(tree, {value: 'ok'})\n// => { value: 'ok' }\n\nvalidateObject(tree, {value: 'ok', children: [{value: 'child'}]})\n// => { value: 'ok', children: [ { value: 'child' } ] }\n```\n\n### Refining validations\n\nExample:\n\n```js+test\nclass Point {\n\n  constructor(x, y) {\n    this.x = x\n    this.y = y\n  }\n}\n\nlet point = arrayOf(number).andThen((value, error) => {\n  if (value.length !== 2) {\n    throw error('Expected an array of length 2 but got: ' + value.length)\n  }\n  return new Point(value[0], value[1])\n})\n\nvalidateObject(point, [1, 2])\n// => Point { x: 1, y: 2 }\n\nvalidateJSON5(point, '[1, 2]')\n// => Point { x: 1, y: 2 }\n\nvalidateJSON5(point, '[1]')\n// ValidationError: Expected an array of length 2 but got: 1 (line 1 column 1)\n```\n\n\n### Defining new schema types\n\nExample:\n\n```js+test\nimport {Node} from 'validated/schema'\n\nclass Point {\n\n  constructor(x, y) {\n    this.x = x\n    this.y = y\n  }\n}\n\nclass PointNode extends Node {\n\n  validate(context) {\n    // prevalidate value with primitive validators\n    let prevalidator = arrayOf(number)\n    let {value, context: nextContext} = prevalidator.validate(context)\n\n    // perform additional validations\n    if (value.length !== 2) {\n\n      // just report an error, context information such as line/column\n      // numbers will be injected automatically\n      throw context.error('Expected an array of length 2 but got: ' + value.length)\n    }\n\n    // construct a Point object, do whatever you want here\n    let [x, y] = value\n    let point = new Point(x, y)\n\n    // return constructed value and the next context\n    return {value: point, context: nextContext}\n  }\n}\n\nvalidateObject(new PointNode(), [1, 2])\n// => Point { x: 1, y: 2 }\n\nvalidateJSON5(new PointNode(), '[1, 2]')\n// => Point { x: 1, y: 2 }\n\nvalidateJSON5(new PointNode(), '[1]')\n// ValidationError: Expected an array of length 2 but got: 1 (line 1 column 1)\n```\n\n### Integration with FlowType\n\nValidated library uses [FlowType][] extensively. Its API is defined in a way\nwhich automatically infers types for produced values:\n\n```js\nimport {object, string, number} from 'validated/schema'\nimport {validate} from 'validated/json5'\n\nlet personSchema = object({\n  name: string,\n  age: number,\n})\n\nlet value: {name: string; age: number} = validate(\n  personSchema,\n  '{\"name\": \"Andrey\", age: 29}'\n)\n```\n\nNote that the type annotation isn't needed — FlowType infers the type\nautomatically based on a schema.\n\n[FlowType]: https://flowtype.org/\n","readmeFilename":"README.md"}