{"id":13527364,"url":"https://github.com/ExodusMovement/schemasafe","last_synced_at":"2025-04-01T09:31:30.468Z","repository":{"id":41544667,"uuid":"271425023","full_name":"ExodusMovement/schemasafe","owner":"ExodusMovement","description":"A reasonably safe JSON Schema validator with draft-04/06/07/2019-09/2020-12 support.","archived":false,"fork":false,"pushed_at":"2024-07-16T08:46:27.000Z","size":1702,"stargazers_count":167,"open_issues_count":18,"forks_count":12,"subscribers_count":25,"default_branch":"master","last_synced_at":"2025-03-25T11:04:43.889Z","etag":null,"topics":["json","json-schema","schemasafe","validation","validator"],"latest_commit_sha":null,"homepage":"https://npmjs.com/@exodus/schemasafe","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ExodusMovement.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-06-11T01:42:06.000Z","updated_at":"2025-03-23T17:48:08.000Z","dependencies_parsed_at":"2024-01-13T21:41:03.731Z","dependency_job_id":"e74c9299-fde3-43fb-ab84-f6302a779f3f","html_url":"https://github.com/ExodusMovement/schemasafe","commit_stats":{"total_commits":895,"total_committers":36,"mean_commits":24.86111111111111,"dds":"0.24357541899441337","last_synced_commit":"6f1343c98a75e4d1d155bc7f7073b11027156c9f"},"previous_names":[],"tags_count":30,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ExodusMovement%2Fschemasafe","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ExodusMovement%2Fschemasafe/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ExodusMovement%2Fschemasafe/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ExodusMovement%2Fschemasafe/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ExodusMovement","download_url":"https://codeload.github.com/ExodusMovement/schemasafe/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246563953,"owners_count":20797554,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["json","json-schema","schemasafe","validation","validator"],"created_at":"2024-08-01T06:01:46.461Z","updated_at":"2025-04-01T09:31:28.625Z","avatar_url":"https://github.com/ExodusMovement.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# `@exodus/schemasafe`\n\nA code-generating [JSON Schema](https://json-schema.org/) validator that attempts to be reasonably secure.\n\nSupports [draft-04/06/07/2019-09/2020-12](doc/Specification-support.md) and the\n[`discriminator` OpenAPI keyword](./doc/Discriminator-support.md).\n\n[![Node CI Status](https://github.com/ExodusMovement/schemasafe/workflows/Node%20CI/badge.svg)](https://github.com/ExodusMovement/schemasafe/actions)\n[![npm](https://img.shields.io/npm/v/@exodus/schemasafe.svg)](https://www.npmjs.com/package/@exodus/schemasafe)\n[![codecov](https://codecov.io/gh/ExodusMovement/schemasafe/branch/master/graph/badge.svg)](https://codecov.io/gh/ExodusMovement/schemasafe)\n\n## Features\n\n* [Converts schemas to self-contained JavaScript files](#generate-modules), can be used in the build process.\\\n  _Integrates nicely with bundlers, so one won't need to generate code in runtime, and that works with CSP._\n* Optional `requireValidation: true` mode enforces full validation of the input object.\\\n  **Using [`mode: \"strong\"`](./doc/Strong-mode.md) is recommended, — it combines that option with additional schema safety checks.**\n* Does not fail open on unknown or unprocessed keywords — instead throws at build time if schema was not fully understood.\n  _That is implemented by tracking processed keywords and ensuring that none remain uncovered._\n* Does not fail open on schema problems — instead throws at build time.\\\n  _E.g. it will detect mistakes like `{type: \"array\", \"maxLength\": 2}`._\n* [About 2000 lines of code](./doc/Auditable.md), non-minified.\n* Uses [secure code generation](./doc/Secure-code-generation.md) approach to prevent data from schema from leaking into\n  the generated code without being JSON-wrapped.\n* [0 dependencies](./doc/Auditable.md)\n* [Very fast](./doc/Performance.md)\n* Supports JSON Schema [draft-04/06/07/2019-09/2020-12](./doc/Specification-support.md) and a strict subset of the\n  [`discriminator` OpenAPI keyword](./doc/Discriminator-support.md).\n* Can assign defaults and/or remove additional properties when schema allows to do that safely.\n  Throws at build time if those options are used with schemas that don't allow to do that safely.\n* Can be used as a [schema linter](./doc/Linter.md).\n\n## Installation\n\n```sh\nnpm install --save @exodus/schemasafe\n```\n\n## Usage\n\nSimply pass a schema to compile it:\n\n```js\nconst { validator } = require('@exodus/schemasafe')\n\nconst validate = validator({\n  type: 'object',\n  required: ['hello'],\n  properties: {\n    hello: {\n      type: 'string'\n    }\n  }\n})\n\nconsole.log('should be valid', validate({ hello: 'world' }))\nconsole.log('should not be valid', validate({}))\n```\n\nOr use the [parser API](./doc/Parser-not-validator.md) (running in\n[strong mode](./doc/Strong-mode.md) by default):\n\n```js\nconst { parser } = require('@exodus/schemasafe')\n\nconst parse = parser({\n  $schema: 'https://json-schema.org/draft/2019-09/schema',\n  type: 'object',\n  required: ['hello'],\n  properties: {\n    hello: {\n      pattern: '^[a-z]+$',\n      type: 'string'\n    }\n  },\n  additionalProperties: false\n})\n\nconsole.log(parse('{\"hello\": \"world\" }')) // { valid: true, value: { hello: 'world' } }\nconsole.log(parse('{}')) // { valid: false }\n```\n\nParser API is recommended, because this way you can avoid handling unvalidated JSON objects in\nnon-string form at all in your code.\n\n## Options\n\nSee [options documentation](./doc/Options.md) for the full list of supported options.\n\n## Custom formats\n\n`@exodus/schemasafe` supports the formats specified in JSON schema v4 (such as date-time).\nIf you want to add your own custom formats pass them as the formats options to the validator:\n\n```js\nconst validate = validator({\n  type: 'string',\n  format: 'no-foo'\n}, {\n  formats: {\n    'no-foo': (str) =\u003e !str.includes('foo'),\n  }\n})\nconsole.log(validate('test')) // true\nconsole.log(validate('foo')) // false\n\nconst parse = parser({\n  $schema: 'https://json-schema.org/draft/2019-09/schema',\n  type: 'string',\n  format: 'only-a'\n}, {\n  formats: {\n    'only-a': /^a+$/,\n  }\n})\nconsole.log(parse('\"aa\"')) // { valid: true, value: 'aa' }\nconsole.log(parse('\"ab\"')) // { valid: false }\n```\n\n## External schemas\n\nYou can pass in external schemas that you reference using the `$ref` attribute as the `schemas` option\n\n```js\nconst ext = {\n  type: 'string'\n}\n\nconst schema = {\n  $ref: 'ext#' // references another schema called ext\n}\n\n// pass the external schemas as an option\nconst validate = validator(schema, { schemas: { ext: ext }})\n\nconsole.log(validate('hello')) // true\nconsole.log(validate(42)) // false\n```\n\n`schemas` can be either an object as shown above, a `Map`, or plain array of schemas (given that\nthose have corresponding `$id` set at top level inside schemas themselves).\n\n## Enabling errors shows information about the source of the error\n\nWhen the `includeErrors` option is set to `true`, `@exodus/schemasafe` also outputs:\n\n- `keywordLocation`: a JSON pointer string as an URI fragment indicating which sub-schema failed, e.g.\n  `#/properties/item/type`\n- `instanceLocation`: a JSON pointer string as an URI fragment indicating which property of the object\n  failed validation, e.g. `#/item`\n\n```js\nconst schema = {\n  type: 'object',\n  required: ['hello'],\n  properties: {\n    hello: {\n      type: 'string'\n    }\n  }\n}\nconst validate = validator(schema, { includeErrors: true })\n\nvalidate({ hello: 100 });\nconsole.log(validate.errors)\n// [ { keywordLocation: '#/properties/hello/type', instanceLocation: '#/hello' } ]\n```\n\nOr, similarly, with parser API:\n\n```js\nconst schema = {\n  $schema: 'https://json-schema.org/draft/2019-09/schema',\n  type: 'object',\n  required: ['hello'],\n  properties: {\n    hello: {\n      type: 'string',\n      pattern: '^[a-z]+$',\n    }\n  },\n  additionalProperties: false,\n}\nconst parse = parser(schema, { includeErrors: true })\n\nconsole.log(parse('{ \"hello\": 100 }'));\n// { valid: false,\n//   error: 'JSON validation failed for type at #/hello',\n//   errors: [ { keywordLocation: '#/properties/hello/type', instanceLocation: '#/hello' } ]\n// }\n```\n\nOnly the first error is reported by default unless `allErrors` option is also set to `true` in\naddition to `includeErrors`.\n\nSee [Error handling](./doc/Error-handling.md) for more information.\n\n## Generate Modules\n\nSee the [doc/samples](./doc/samples/) directory to see how `@exodus/schemasafe` compiles\nsupported test suites.\n\nTo compile a validator function to an IIFE, call `validate.toModule()`:\n\n```js\nconst { validator } = require('@exodus/schemasafe')\n\nconst schema = {\n  type: 'string',\n  format: 'hex'\n}\n\n// This works with custom formats as well.\nconst formats = {\n  hex: (value) =\u003e /^0x[0-9A-Fa-f]*$/.test(value),\n}\n\nconst validate = validator(schema, { formats })\n\nconsole.log(validate.toModule())\n/** Prints:\n * (function() {\n * 'use strict'\n * const format0 = (value) =\u003e /^0x[0-9A-Fa-f]*$/.test(value);\n * return (function validate(data) {\n *   if (data === undefined) data = null\n *   if (!(typeof data === \"string\")) return false\n *   if (!format0(data)) return false\n *   return true\n * })})();\n */\n```\n\n## Performance\n\n`@exodus/schemasafe` uses code generation to turn a JSON schema into javascript code that is easily\noptimizeable by v8 and [extremely fast](https://github.com/ebdrup/json-schema-benchmark).\n\nSee [Performance](./doc/Performance.md) for information on options that might affect performance\nboth ways.\n\n## Contributing\n\nGet a fully set up development environment with:\n\n```sh\ngit clone https://github.com/ExodusMovement/schemasafe\ncd schemasafe\n\ngit submodule update --init --recursive\nyarn\nyarn lint\nyarn test\n```\n\n## Previous work\n\nThis is based on a heavily rewritten version of the amazing (but outdated)\n[is-my-json-valid](https://github.com/mafintosh/is-my-json-valid) by\n[@mafintosh](https://github.com/mafintosh/is-my-json-valid).\n\nCompared to `is-my-json-valid`, `@exodus/schemasafe` adds security-first design, many new features,\nnewer spec versions support, slimmer and more maintainable code, 0 dependencies, self-contained JS\nmodule generation, fixes bugs and adds better test coverage, and drops support for outdated Node.js\nversions.\n## License\n\n[MIT](./LICENSE)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FExodusMovement%2Fschemasafe","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FExodusMovement%2Fschemasafe","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FExodusMovement%2Fschemasafe/lists"}