@amritk/generate-validators 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +105 -0
- package/dist/generators/build-schema.d.ts +30 -0
- package/dist/generators/collect-validator-imports.d.ts +29 -0
- package/dist/generators/generate-files.d.ts +39 -0
- package/dist/generators/generate-validator-function.d.ts +24 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1300 -0
- package/package.json +51 -0
package/README.md
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# @amritk/generate-validators
|
|
4
|
+
|
|
5
|
+
**Programmatic API for generating predicate-style TypeScript validators from JSON Schemas.**
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+

|
|
9
|
+

|
|
10
|
+

|
|
11
|
+

|
|
12
|
+

|
|
13
|
+
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Overview
|
|
19
|
+
|
|
20
|
+
`@amritk/generate-validators` produces lightweight runtime **validators** from a JSON Schema. Where [`@amritk/generate-parsers`](../generate-parsers) coerces and parses unknown input into a typed value, this package emits cheaper predicate-style functions that simply tell you whether a value matches a schema (and where it doesn't).
|
|
21
|
+
|
|
22
|
+
Each generated file exports:
|
|
23
|
+
|
|
24
|
+
- A TypeScript `type` definition for the schema
|
|
25
|
+
- A `validateFoo(input: unknown, _path?: string): ValidationResult` function
|
|
26
|
+
|
|
27
|
+
A shared `validation-result.ts` template and an `index.ts` barrel are emitted alongside the generated files.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Installation
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install @amritk/generate-validators
|
|
35
|
+
# or
|
|
36
|
+
pnpm add @amritk/generate-validators
|
|
37
|
+
# or
|
|
38
|
+
yarn add @amritk/generate-validators
|
|
39
|
+
# or
|
|
40
|
+
bun add @amritk/generate-validators
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Usage
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
import { buildValidatorSchema } from '@amritk/generate-validators'
|
|
49
|
+
import type { JSONSchema } from 'json-schema-typed/draft-2020-12'
|
|
50
|
+
|
|
51
|
+
const schema: JSONSchema = {
|
|
52
|
+
type: 'object',
|
|
53
|
+
properties: {
|
|
54
|
+
info: { $ref: '#/$defs/info' },
|
|
55
|
+
},
|
|
56
|
+
$defs: {
|
|
57
|
+
info: {
|
|
58
|
+
type: 'object',
|
|
59
|
+
properties: { title: { type: 'string' } },
|
|
60
|
+
required: ['title'],
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const files = await buildValidatorSchema(schema, 'Document')
|
|
66
|
+
// → [{ filename: 'document.ts', content: '...' }, { filename: 'info.ts', ... }, { filename: 'validation-result.ts', ... }, { filename: 'index.ts', ... }]
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Write the resulting files to disk and import the validators where you need them:
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
import { validateDocument } from './generated'
|
|
73
|
+
|
|
74
|
+
const result = validateDocument(input)
|
|
75
|
+
if (!result.valid) {
|
|
76
|
+
console.error(result.errors)
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## API
|
|
83
|
+
|
|
84
|
+
### `buildValidatorSchema(rootSchema, rootTypeName)`
|
|
85
|
+
|
|
86
|
+
| Parameter | Type | Description |
|
|
87
|
+
|:---|:---|:---|
|
|
88
|
+
| `rootSchema` | `JSONSchema` | The root schema to traverse. `$ref` and `$dynamicRef` are resolved recursively. Draft-07 schemas are upgraded to 2020-12 automatically. |
|
|
89
|
+
| `rootTypeName` | `string` | Name used for the root type (e.g. `"Document"`). |
|
|
90
|
+
|
|
91
|
+
Returns: `Promise<GeneratedFile[]>` where `GeneratedFile = { filename: string; content: string }`.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Related packages
|
|
96
|
+
|
|
97
|
+
- [`@amritk/generate-parsers`](../generate-parsers) — type definitions plus parsers that coerce input
|
|
98
|
+
- [`@amritk/mjst`](../cli) — CLI wrapper around the generators
|
|
99
|
+
- [`@amritk/helpers`](../helpers) — shared schema-traversal utilities
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## License
|
|
104
|
+
|
|
105
|
+
[MIT](../../LICENSE)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { JSONSchema } from 'json-schema-typed/draft-2020-12';
|
|
2
|
+
/**
|
|
3
|
+
* Represents a generated TypeScript file with its filename and content.
|
|
4
|
+
*/
|
|
5
|
+
export type GeneratedFile = {
|
|
6
|
+
filename: string;
|
|
7
|
+
content: string;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Builds all TypeScript validator files from a JSON Schema by traversing
|
|
11
|
+
* all $ref references recursively, mirroring the generate-parsers pipeline.
|
|
12
|
+
*
|
|
13
|
+
* Each generated file exports:
|
|
14
|
+
* - A TypeScript type definition
|
|
15
|
+
* - A `validateFoo(input: unknown, _path?: string): ValidationResult` function
|
|
16
|
+
*
|
|
17
|
+
* A `validation-result.ts` file containing the `ValidationResult` and `ValidationError`
|
|
18
|
+
* runtime contract is always emitted. An `index.ts` re-exports everything.
|
|
19
|
+
*
|
|
20
|
+
* @param rootSchema - The root JSON Schema to build from
|
|
21
|
+
* @param rootTypeName - The name for the root type (e.g. "Document")
|
|
22
|
+
* @returns An array of generated TypeScript files
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const files = await buildValidatorSchema(schema, 'Document')
|
|
27
|
+
* // files → [{ filename: 'document.ts', content: '...' }, { filename: 'info.ts', ... }, ...]
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare const buildValidatorSchema: (rootSchema: JSONSchema, rootTypeName: string) => Promise<GeneratedFile[]>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { JSONSchema } from 'json-schema-typed/draft-2020-12';
|
|
2
|
+
/**
|
|
3
|
+
* Options for controlling how validator imports are collected.
|
|
4
|
+
*/
|
|
5
|
+
type CollectValidatorImportsOptions = {
|
|
6
|
+
/**
|
|
7
|
+
* The $ref path of the schema being generated (e.g. `#/$defs/encoding`).
|
|
8
|
+
* Prevents a file from importing itself.
|
|
9
|
+
*/
|
|
10
|
+
readonly selfRef?: string | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* The root schema document. URI refs that cannot be resolved within it
|
|
13
|
+
* are excluded from the import list (they were never generated as files).
|
|
14
|
+
*/
|
|
15
|
+
readonly rootSchema?: Record<string, unknown> | undefined;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Collects import statements for all $ref dependencies of a schema.
|
|
19
|
+
* Each import brings in both the generated TypeScript type and validator function.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const schema = { properties: { contact: { $ref: '#/$defs/contact' } } }
|
|
24
|
+
* collectValidatorImports(schema)
|
|
25
|
+
* // ["import { type ContactObject, validateContactObject } from './contact-object'"]
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare const collectValidatorImports: (schema: JSONSchema, options?: CollectValidatorImportsOptions) => string[];
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { JSONSchema } from 'json-schema-typed/draft-2020-12';
|
|
2
|
+
/**
|
|
3
|
+
* Options for controlling what gets generated in a validator file.
|
|
4
|
+
*/
|
|
5
|
+
type GenerateValidatorFileOptions = {
|
|
6
|
+
/**
|
|
7
|
+
* The $ref path of the schema being generated (e.g. `#/$defs/info`).
|
|
8
|
+
* Prevents the file from importing itself.
|
|
9
|
+
*/
|
|
10
|
+
readonly selfRef?: string;
|
|
11
|
+
/**
|
|
12
|
+
* The root schema document. Used to filter out unresolvable refs.
|
|
13
|
+
*/
|
|
14
|
+
readonly rootSchema?: Record<string, unknown>;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Generates a complete TypeScript validator file from a JSON Schema.
|
|
18
|
+
*
|
|
19
|
+
* The file contains:
|
|
20
|
+
* - Imports for the ValidationResult/ValidationError types
|
|
21
|
+
* - Imports for any $ref types and their validator functions
|
|
22
|
+
* - The exported TypeScript type definition
|
|
23
|
+
* - The exported validator function
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* const schema = {
|
|
28
|
+
* type: 'object',
|
|
29
|
+
* properties: { title: { type: 'string' } },
|
|
30
|
+
* required: ['title'],
|
|
31
|
+
* }
|
|
32
|
+
* generateValidatorFile(schema, 'Info')
|
|
33
|
+
* // import type { ValidationResult, ValidationError } from './validation-result'
|
|
34
|
+
* // export type Info = { title: string }
|
|
35
|
+
* // export const validateInfo = (input: unknown, _path = ''): ValidationResult => { ... }
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare const generateValidatorFile: (schema: JSONSchema, typeName: string, options?: GenerateValidatorFileOptions) => string;
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { JSONSchema } from 'json-schema-typed/draft-2020-12';
|
|
2
|
+
/**
|
|
3
|
+
* Generates a TypeScript validator function from a JSON Schema.
|
|
4
|
+
*
|
|
5
|
+
* The generated function accepts `unknown` input and returns `true` if valid,
|
|
6
|
+
* or `{ valid: false, errors }` with a list of errors if not.
|
|
7
|
+
*
|
|
8
|
+
* Object schemas check that required properties are present and that all
|
|
9
|
+
* provided properties match their declared types. Non-object schemas (strings,
|
|
10
|
+
* numbers, enums, $refs) emit an inline type check.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* generateValidatorFunction({ type: 'object', properties: { name: { type: 'string' } }, required: ['name'] }, 'Info')
|
|
15
|
+
* // export const validateInfo = (input: unknown, _path = ''): ValidationResult => {
|
|
16
|
+
* // if (typeof input !== 'object' || ...) return { valid: false, ... }
|
|
17
|
+
* // const errors: ValidationError[] = []
|
|
18
|
+
* // const obj = input as Record<string, unknown>
|
|
19
|
+
* // if (!('name' in obj)) { errors.push(...) } else if (typeof obj['name'] !== 'string') { errors.push(...) }
|
|
20
|
+
* // return errors.length > 0 ? { valid: false, errors } : true
|
|
21
|
+
* // }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare const generateValidatorFunction: (schema: JSONSchema, typeName: string) => string;
|
package/dist/index.d.ts
ADDED