Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/azu/create-validator-ts
Create JSON Schema validator from TypeScript.
https://github.com/azu/create-validator-ts
check json-schema runtime typescript validator
Last synced: about 1 month ago
JSON representation
Create JSON Schema validator from TypeScript.
- Host: GitHub
- URL: https://github.com/azu/create-validator-ts
- Owner: azu
- License: mit
- Created: 2021-02-09T15:29:25.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2024-05-29T07:53:15.000Z (4 months ago)
- Last Synced: 2024-05-29T12:50:28.913Z (4 months ago)
- Topics: check, json-schema, runtime, typescript, validator
- Language: TypeScript
- Size: 497 KB
- Stars: 90
- Watchers: 3
- Forks: 4
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# create-validator-ts
Create JSON Schema validator from TypeScript.
## Motivation
- Generate JSON Schema Validator functions from TypeScript code
- Make TypeScript the [Single source of truth](https://en.wikipedia.org/wiki/Single_source_of_truth)### Structure
```
.
└── src/
├── hello/
│ ├── api-types.ts
│ ├── api-types.validator.ts <- Generated
│ └── index.ts
└── status/
├── api-types.ts
├── api-types.validator.ts <- Generated
└── index.ts
```## Install
Install with [npm](https://www.npmjs.com/):
npm install create-validator-ts
## Usage
Usage
$ create-validator-ts [file|glob*]
Options
--watch [Boolean] If set the flag, start watch mode
--check [Boolean] If set the flag, start test mode
--cwd [Path:String] current working directory
--tsconfigFilePath [Path:String] path to tsconfig.json
--generatorScript [Path:String] A JavaScript file path that customize validator code generator
--verbose [Boolean] If set the flag, show progressing logs
ts-json-schema-generator options
--sortProps [Boolean] Enable sortProps
--no-sortProps
--strictTuples [Boolean] Enable strictTuples
--no-strictTuples
--encodeRefs [Boolean] Enable encodeRefs
--no-encodeRefs
--skipTypeCheck [Boolean] Enable skipTypeCheck. true by default
--no-skipTypeCheck
--additionalProperties [Boolean] Enable additionalProperties. false by default
--no-additionalProperties
Examples
$ create-validator-ts "src/**/api-types.ts"
# use cache
$ create-validator-ts --cache "src/**/api-types.ts"
# custom tsconfig.json
$ create-validator-ts "src/**/api-types.ts" --tsconfigFilePath ./tsconfig.app.json
# custom validator code
$ create-validator-ts "src/**/api-types.ts" --generatorScript ./custom.js## Example
You can generate validator code via following command
$ create-validator-ts "src/**/api-types.ts"
Default validator require [ajv](https://github.com/ajv-validator/ajv), and you need to install ajv into your project.
$ npm install ajv
Structure:
```
.
├ tsconfig.json
└── src/
└─── api/
├── api-types.ts
└─── api-types.validator.ts <- Generated
````api-types.ts`:
```ts
// Example api-types
// GET /api
export type GetAPIRequestQuery = {
id: string;
};
export type GetAPIResponseBody = {
ok: boolean;
};
````api-types.validator.ts` (generated):
```ts
// @ts-nocheck
// eslint-disable
// This file is generated by create-validator-ts
import Ajv from 'ajv';
import * as apiTypes from './api-types';const SCHEMA = {
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"GetAPIRequestQuery": {
"type": "object",
"properties": {
"id": {
"type": "string"
}
},
"required": [
"id"
],
"additionalProperties": false
},
"GetAPIResponseBody": {
"type": "object",
"properties": {
"ok": {
"type": "boolean"
}
},
"required": [
"ok"
],
"additionalProperties": false
}
}
};
const ajv = new Ajv({ removeAdditional: true }).addSchema(SCHEMA, "SCHEMA");
export function validateGetAPIRequestQuery(payload: unknown): apiTypes.GetAPIRequestQuery {
if (!isGetAPIRequestQuery(payload)) {
const error = new Error('invalid payload: GetAPIRequestQuery');
error.name = "ValidatorError";
throw error;
}
return payload;
}export function isGetAPIRequestQuery(payload: unknown): payload is apiTypes.GetAPIRequestQuery {
/** Schema is defined in {@link SCHEMA.definitions.GetAPIRequestQuery } **/
const ajvValidate = ajv.compile({ "$ref": "SCHEMA#/definitions/GetAPIRequestQuery" });
return ajvValidate(payload);
}export function validateGetAPIResponseBody(payload: unknown): apiTypes.GetAPIResponseBody {
if (!isGetAPIResponseBody(payload)) {
const error = new Error('invalid payload: GetAPIResponseBody');
error.name = "ValidatorError";
throw error;
}
return payload;
}export function isGetAPIResponseBody(payload: unknown): payload is apiTypes.GetAPIResponseBody {
/** Schema is defined in {@link SCHEMA.definitions.GetAPIResponseBody } **/
const ajvValidate = ajv.compile({ "$ref": "SCHEMA#/definitions/GetAPIResponseBody" });
return ajvValidate(payload);
}
```## Check generated code
When You can check if your generated codes are match with `api-types.ts`, you can run it via `--check` flag.
$ create-validator-ts "src/**/api-types.ts"
# $? → 0 or 1It is useful for testing on CI.
## Custom Validator
You can create custom validator using `--generatorScript` flag.
$ create-validator-ts "src/**/api-types.ts" --generatorScript ./custom.js
`custom.js`
```js
"use strict";
const path = require("path");
const generator = ({ apiFilePath, apiFileCode, schema }) => {
const apiFileName = path.basename(apiFilePath, ".ts");
const isExportedTypeInApiTypes = (apiName) => {
return (apiFileCode.includes(`export type ${apiName} =`) ||
apiFileCode.includes(`export interface ${apiName} {`));
};
const banner = `// @ts-nocheck
// eslint-disable
// This file is generated by create-validator-ts
import Ajv from 'ajv';
import logger from 'logger';
import * as apiTypes from './${apiFileName}';
`;
// define SCHEMA to top, and we can refer it as "SCHEMA".
// Note: { "$ref": "SCHEMA#/definitions/${apiName}" }
const schemaDefinition = `const SCHEMA = ${JSON.stringify(schema, null, 4)};
const ajv = new Ajv({ removeAdditional: true }).addSchema(SCHEMA, "SCHEMA");`;
const code = Object.entries(schema.definitions || {})
.filter(([apiName]) => {
return isExportedTypeInApiTypes(apiName);
})
.map(([apiName, _schema]) => {
return `export function validate${apiName}(payload: unknown): apiTypes.${apiName} {
if (!is${apiName}(payload)) {
const error = new Error('invalid payload: ${apiName}');
error.name = "ValidatorError";
throw error;
}
return payload;
}export function is${apiName}(payload: unknown): payload is apiTypes.${apiName} {
/** Schema is defined in {@link SCHEMA.definitions.${apiName} } **/
const ajvValidate = ajv.compile({ "$ref": "SCHEMA#/definitions/${apiName}" });
return ajvValidate(payload);
}`;
})
.join("\n\n");
return `${banner}
${schemaDefinition}
${code}
`;
};
exports.generator = generator;
exports.generatorOptions = {
extraTags: [""] // optional
};
```## Ignore generated Code
If you have used [Prettier](https://prettier.io/), you should add `*.validator.ts` to `.prettierignore`
```
*.validator.ts
```- [Ignoring Code · Prettier](https://prettier.io/docs/en/ignore.html)
## Compares
- create-validator-ts
- It generate TypeScript validator from TypeScript types
- [ts-to-zod](https://github.com/fabien0102/ts-to-zod) uses same approach
- OpenAPI
- It generate TypeScript validator from Schema file
- TypeScript Validation library like [Zod](https://github.com/colinhacks/zod)
- Is allow to share TypeScript code and types, but it need to use builder function## FAQ
### Can not parse new TypeScript syntax
It related to [vega/ts-json-schema-generator](https://github.com/vega/ts-json-schema-generator).
Please report the issue to [vega/ts-json-schema-generator](https://github.com/vega/ts-json-schema-generator).## Changelog
See [Releases page](https://github.com/azu/create-validator-ts/releases).
## Running tests
Install devDependencies and Run `npm test`:
npm test
## Contributing
Pull requests and stars are always welcome.
For bugs and feature requests, [please create an issue](https://github.com/azu/create-validator-ts/issues).
1. Fork it!
2. Create your feature branch: `git checkout -b my-new-feature`
3. Commit your changes: `git commit -am 'Add some feature'`
4. Push to the branch: `git push origin my-new-feature`
5. Submit a pull request :D## Author
- azu: [GitHub](https://github.com/azu), [Twitter](https://twitter.com/azu_re)
## License
MIT © azu
## Prior art
- [ForbesLindesay/typescript-json-validator](https://github.com/ForbesLindesay/typescript-json-validator)
Differences:
- `create-validator-ts` support multiple types in a single file
- `create-validator-ts` support more TypeScript that includes Utility types like `Pick`
- `typescript-json-validator` uses [YousefED/typescript-json-schema](https://github.com/YousefED/typescript-json-schema)
- `create-validator-ts` uses [vega/ts-json-schema-generator](https://github.com/vega/ts-json-schema-generator)
- See also [Future of schema generators · Issue #101 · vega/ts-json-schema-generator](https://github.com/vega/ts-json-schema-generator/issues/101)
- `create-validator-ts` is minimal and support customization of validation code using `--generatorScript`