@zodapi/codegen 0.2.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/LICENSE +21 -0
- package/README.md +96 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +56 -0
- package/dist/cli.js.map +1 -0
- package/dist/generate.d.ts +26 -0
- package/dist/generate.d.ts.map +1 -0
- package/dist/generate.js +378 -0
- package/dist/generate.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/names.d.ts +10 -0
- package/dist/names.d.ts.map +1 -0
- package/dist/names.js +86 -0
- package/dist/names.js.map +1 -0
- package/dist/schema-to-zod.d.ts +47 -0
- package/dist/schema-to-zod.d.ts.map +1 -0
- package/dist/schema-to-zod.js +350 -0
- package/dist/schema-to-zod.js.map +1 -0
- package/package.json +36 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Alan Christensen
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# @zodapi/codegen
|
|
2
|
+
|
|
3
|
+
Generates a [zodapi](https://github.com/christensena/zodapi) contract — zod schemas plus plain
|
|
4
|
+
`RouteDef` route objects — from an OpenAPI 3.1 document. For backends not written in TypeScript:
|
|
5
|
+
point it at the spec your Python/Go/.NET/... framework emits and consume the result with
|
|
6
|
+
`@zodapi/client`.
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
zodapi-codegen openapi.json -o contract.ts
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
or programmatically:
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import { generateContract } from '@zodapi/codegen'
|
|
16
|
+
|
|
17
|
+
const source = generateContract(JSON.parse(await readFile('openapi.json', 'utf8')))
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## What it generates
|
|
21
|
+
|
|
22
|
+
One file, importing only `zod` and `@zodapi/core`:
|
|
23
|
+
|
|
24
|
+
- an exported const per `components/schemas` entry — component name = const name, registered via
|
|
25
|
+
`.meta({ id })` so the schemas re-serialize as the same `$ref` components; recursive schemas use
|
|
26
|
+
zod 4 shape getters
|
|
27
|
+
- an exported const per operation, a plain object `satisfies RouteDef` — `operationId` becomes the
|
|
28
|
+
client `alias` (no alias without one); the spec's declared responses are taken verbatim, nothing
|
|
29
|
+
(like the zodapi `400`) is injected
|
|
30
|
+
- a `routes` tuple ready for `createClient(routes)` from `@zodapi/client`
|
|
31
|
+
- a `problemFlavor` const (`'zodapi' | 'problem-details' | undefined`, detected from the spec's
|
|
32
|
+
error responses — zodapi's `urn:zodapi:validation` problem type, or an ASP.NET-style
|
|
33
|
+
`ValidationProblemDetails`) to feed `decodersFor(problemFlavor)` when creating the client
|
|
34
|
+
- with `exportTypes: true` (CLI `--export-types`), a `type <Name> = z.infer<typeof <Name>>` alias
|
|
35
|
+
alongside each component const (the zodios codegen convention). `z.infer` is the output side —
|
|
36
|
+
use `z.input<typeof <Name>>` where the wire form differs (e.g. date codecs)
|
|
37
|
+
|
|
38
|
+
Query parameters typed `array` are declared with `queryArray(item)` from `@zodapi/core`, matching
|
|
39
|
+
the zodapi `a[]=` convention.
|
|
40
|
+
|
|
41
|
+
Output is unformatted; run your formatter over it.
|
|
42
|
+
|
|
43
|
+
## Date conversion
|
|
44
|
+
|
|
45
|
+
By default ISO strings stay strings (`z.iso.datetime()` / `z.iso.date()`). Opt in to `Date`
|
|
46
|
+
conversion per format:
|
|
47
|
+
|
|
48
|
+
```sh
|
|
49
|
+
zodapi-codegen openapi.json -o contract.ts --dates-datetime --dates-date --dates-offset
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
generateContract(doc, { dates: { datetime: true, date: true, offset: true } })
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
- `datetime` / `--dates-datetime`: `format: date-time` fields become a bidirectional
|
|
57
|
+
`z.codec(z.iso.datetime(), z.date(), ...)` — responses parse to `Date`, requests encode back to
|
|
58
|
+
the wire string
|
|
59
|
+
- `date` / `--dates-date`: `format: date` fields become a codec decoding to `Date` at UTC midnight
|
|
60
|
+
and encoding back to `YYYY-MM-DD`
|
|
61
|
+
- `offset` / `--dates-offset`: accept UTC offsets in date-time values
|
|
62
|
+
(`z.iso.datetime({ offset: true })`)
|
|
63
|
+
|
|
64
|
+
The codecs are emitted once as shared `isoDatetimeToDate` / `isoDateToDate` consts; a field with
|
|
65
|
+
extra wire-side constraints or a `default` inlines the codec with those applied to its input side.
|
|
66
|
+
|
|
67
|
+
Because codecs change parsed values, `@zodapi/client` refuses calls whose validation mode would
|
|
68
|
+
skip a codec-bearing schema (see the client README); pair a dates contract with
|
|
69
|
+
`validate: 'response'` (the default) or `'both'`, and optionally `encodeRequests: true` to pass
|
|
70
|
+
`Date` objects in requests too.
|
|
71
|
+
|
|
72
|
+
## Fidelity
|
|
73
|
+
|
|
74
|
+
The converter covers the JSON Schema subset OpenAPI 3.1 uses: objects (required/optional,
|
|
75
|
+
`additionalProperties` as loose objects, catchalls, and records), arrays and tuples, unions
|
|
76
|
+
(`oneOf` is treated as `anyOf`), intersections (`allOf`), nullability in both encodings, enums and
|
|
77
|
+
consts, string formats (`email`, `uuid`, `uri`, `date-time`, ...), numeric/string/array
|
|
78
|
+
constraints, defaults, and `description`/`title`/`examples` metadata.
|
|
79
|
+
|
|
80
|
+
It is enforced by a round-trip test: a comprehensive hand-written contract is serialized to
|
|
81
|
+
OpenAPI, fed through the generator, and the document emitted from the generated contract must
|
|
82
|
+
deep-equal the original.
|
|
83
|
+
|
|
84
|
+
## Not covered
|
|
85
|
+
|
|
86
|
+
`webhooks`, refs outside `#/components/schemas` (component parameters/responses), response headers,
|
|
87
|
+
and OpenAPI 3.0 documents (3.1 only — 3.1 schemas are real JSON Schema, 3.0's `nullable` dialect is
|
|
88
|
+
not).
|
|
89
|
+
|
|
90
|
+
## Install
|
|
91
|
+
|
|
92
|
+
```sh
|
|
93
|
+
pnpm add -D @zodapi/codegen
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
The generated file needs `zod` and `@zodapi/core` at runtime.
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { generateContract } from './generate.js';
|
|
4
|
+
function fail(message) {
|
|
5
|
+
console.error(message);
|
|
6
|
+
process.exit(1);
|
|
7
|
+
}
|
|
8
|
+
const USAGE = 'Usage: zodapi-codegen <openapi.json> [-o contract.ts] [--export-types] [--dates-datetime] [--dates-date] [--dates-offset]';
|
|
9
|
+
const args = process.argv.slice(2);
|
|
10
|
+
let input;
|
|
11
|
+
let output;
|
|
12
|
+
let exportTypes = false;
|
|
13
|
+
const dates = {};
|
|
14
|
+
for (let i = 0; i < args.length; i++) {
|
|
15
|
+
const arg = args[i];
|
|
16
|
+
if (arg === '-o' || arg === '--output') {
|
|
17
|
+
output = args[++i] ?? fail(`${arg} requires a value`);
|
|
18
|
+
}
|
|
19
|
+
else if (arg === '--export-types') {
|
|
20
|
+
exportTypes = true;
|
|
21
|
+
}
|
|
22
|
+
else if (arg === '--dates-datetime') {
|
|
23
|
+
dates.datetime = true;
|
|
24
|
+
}
|
|
25
|
+
else if (arg === '--dates-date') {
|
|
26
|
+
dates.date = true;
|
|
27
|
+
}
|
|
28
|
+
else if (arg === '--dates-offset') {
|
|
29
|
+
dates.offset = true;
|
|
30
|
+
}
|
|
31
|
+
else if (arg === '-h' || arg === '--help') {
|
|
32
|
+
console.log(USAGE);
|
|
33
|
+
process.exit(0);
|
|
34
|
+
}
|
|
35
|
+
else if (input === undefined) {
|
|
36
|
+
input = arg;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
fail(`unexpected argument: ${arg}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (input === undefined)
|
|
43
|
+
fail(USAGE);
|
|
44
|
+
const options = {
|
|
45
|
+
...(Object.keys(dates).length > 0 && { dates }),
|
|
46
|
+
...(exportTypes && { exportTypes: true }),
|
|
47
|
+
};
|
|
48
|
+
const doc = JSON.parse(readFileSync(input, 'utf8'));
|
|
49
|
+
const source = generateContract(doc, options);
|
|
50
|
+
if (output === undefined) {
|
|
51
|
+
process.stdout.write(source);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
writeFileSync(output, source);
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAErD,OAAO,EAAE,gBAAgB,EAAwB,MAAM,eAAe,CAAA;AAGtE,SAAS,IAAI,CAAC,OAAe;IAC3B,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IACtB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC;AAED,MAAM,KAAK,GACT,2HAA2H,CAAA;AAE7H,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;AAClC,IAAI,KAAyB,CAAA;AAC7B,IAAI,MAA0B,CAAA;AAC9B,IAAI,WAAW,GAAG,KAAK,CAAA;AACvB,MAAM,KAAK,GAAiB,EAAE,CAAA;AAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;IACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;IACnB,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,UAAU,EAAE,CAAC;QACvC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,GAAG,mBAAmB,CAAC,CAAA;IACvD,CAAC;SAAM,IAAI,GAAG,KAAK,gBAAgB,EAAE,CAAC;QACpC,WAAW,GAAG,IAAI,CAAA;IACpB,CAAC;SAAM,IAAI,GAAG,KAAK,kBAAkB,EAAE,CAAC;QACtC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAA;IACvB,CAAC;SAAM,IAAI,GAAG,KAAK,cAAc,EAAE,CAAC;QAClC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAA;IACnB,CAAC;SAAM,IAAI,GAAG,KAAK,gBAAgB,EAAE,CAAC;QACpC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAA;IACrB,CAAC;SAAM,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QAClB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;SAAM,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC/B,KAAK,GAAG,GAAG,CAAA;IACb,CAAC;SAAM,CAAC;QACN,IAAI,CAAC,wBAAwB,GAAG,EAAE,CAAC,CAAA;IACrC,CAAC;AACH,CAAC;AACD,IAAI,KAAK,KAAK,SAAS;IAAE,IAAI,CAAC,KAAK,CAAC,CAAA;AAEpC,MAAM,OAAO,GAAoB;IAC/B,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;IAC/C,GAAG,CAAC,WAAW,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;CAC1C,CAAA;AACD,MAAM,GAAG,GAAY,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAA;AAC5D,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;AAC7C,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;IACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;AAC9B,CAAC;KAAM,CAAC;IACN,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAC/B,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type DatesOptions } from './schema-to-zod.js';
|
|
2
|
+
export type ProblemFlavor = 'zodapi' | 'problem-details';
|
|
3
|
+
/**
|
|
4
|
+
* Detect which problem-details flavor a spec's error responses use, so
|
|
5
|
+
* generated contracts can carry a `problemFlavor` hint for
|
|
6
|
+
* `decodersFor(...)` on the client.
|
|
7
|
+
*/
|
|
8
|
+
export declare function detectProblemFlavor(doc: unknown): ProblemFlavor | undefined;
|
|
9
|
+
export interface GenerateOptions {
|
|
10
|
+
/** Convert ISO date/time strings to `Date` objects via `z.codec`s. */
|
|
11
|
+
dates?: DatesOptions | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* Also export a `type <Name> = z.infer<typeof <Name>>` alias per component
|
|
14
|
+
* schema (the zodios codegen convention). `z.infer` is the output side; use
|
|
15
|
+
* `z.input<typeof <Name>>` where the wire form differs (e.g. date codecs).
|
|
16
|
+
*/
|
|
17
|
+
exportTypes?: boolean | undefined;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Generate zodapi contract source (zod schemas + `RouteDef` route objects) from
|
|
21
|
+
* a parsed OpenAPI 3.1 document. The result imports only `zod` and
|
|
22
|
+
* `@zodapi/core`, and exports one const per component schema, one per
|
|
23
|
+
* operation, and a `routes` tuple for `createClient(routes)`.
|
|
24
|
+
*/
|
|
25
|
+
export declare function generateContract(doc: unknown, options?: GenerateOptions): string;
|
|
26
|
+
//# sourceMappingURL=generate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../src/generate.ts"],"names":[],"mappings":"AACA,OAAO,EAML,KAAK,YAAY,EAElB,MAAM,oBAAoB,CAAA;AAuD3B,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,iBAAiB,CAAA;AA2BxD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,aAAa,GAAG,SAAS,CAkC3E;AAUD,MAAM,WAAW,eAAe;IAC9B,sEAAsE;IACtE,KAAK,CAAC,EAAE,YAAY,GAAG,SAAS,CAAA;IAChC;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAClC;AAyQD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,MAAM,CAGhF"}
|
package/dist/generate.js
ADDED
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
import { NameAllocator, routeNameFromPath } from './names.js';
|
|
2
|
+
import { DATE_CODEC_FNS, convertSchema, dateCodecInput, } from './schema-to-zod.js';
|
|
3
|
+
const METHODS = ['get', 'put', 'post', 'delete', 'options', 'head', 'patch', 'trace'];
|
|
4
|
+
const REF_PREFIX = '#/components/schemas/';
|
|
5
|
+
function isObject(value) {
|
|
6
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
7
|
+
}
|
|
8
|
+
function json(value) {
|
|
9
|
+
return JSON.stringify(value);
|
|
10
|
+
}
|
|
11
|
+
/** All `#/components/schemas/*` names referenced anywhere inside `value`. */
|
|
12
|
+
function collectRefs(value, into) {
|
|
13
|
+
if (Array.isArray(value)) {
|
|
14
|
+
for (const item of value)
|
|
15
|
+
collectRefs(item, into);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (!isObject(value))
|
|
19
|
+
return;
|
|
20
|
+
const ref = value['$ref'];
|
|
21
|
+
if (typeof ref === 'string' && ref.startsWith(REF_PREFIX)) {
|
|
22
|
+
into.add(ref.slice(REF_PREFIX.length));
|
|
23
|
+
}
|
|
24
|
+
for (const item of Object.values(value))
|
|
25
|
+
collectRefs(item, into);
|
|
26
|
+
}
|
|
27
|
+
/** DFS postorder so dependencies come before dependents; cycles resolve via object getters. */
|
|
28
|
+
function orderComponents(schemas) {
|
|
29
|
+
const order = [];
|
|
30
|
+
const visited = new Set();
|
|
31
|
+
const visit = (name) => {
|
|
32
|
+
if (visited.has(name) || !(name in schemas))
|
|
33
|
+
return;
|
|
34
|
+
visited.add(name);
|
|
35
|
+
const deps = new Set();
|
|
36
|
+
collectRefs(schemas[name], deps);
|
|
37
|
+
for (const dep of deps)
|
|
38
|
+
visit(dep);
|
|
39
|
+
order.push(name);
|
|
40
|
+
};
|
|
41
|
+
for (const name of Object.keys(schemas))
|
|
42
|
+
visit(name);
|
|
43
|
+
return order;
|
|
44
|
+
}
|
|
45
|
+
/** Splices extra entries into a trailing `.meta({ ... })` call, or appends one. */
|
|
46
|
+
function withMeta(code, entries) {
|
|
47
|
+
if (entries.length === 0)
|
|
48
|
+
return code;
|
|
49
|
+
const tail = /^([\s\S]*)\.meta\(\{ ([\s\S]*) \}\)$/.exec(code);
|
|
50
|
+
if (tail)
|
|
51
|
+
return `${tail[1]}.meta({ ${entries.join(', ')}, ${tail[2]} })`;
|
|
52
|
+
return `${code}.meta({ ${entries.join(', ')} })`;
|
|
53
|
+
}
|
|
54
|
+
// Mirrors ZODAPI_VALIDATION_TYPE from @zodapi/core (codegen only reads specs).
|
|
55
|
+
const ZODAPI_VALIDATION_TYPE = 'urn:zodapi:validation';
|
|
56
|
+
function isZodapiValidationSchema(schema) {
|
|
57
|
+
const properties = isObject(schema['properties']) ? schema['properties'] : {};
|
|
58
|
+
const type = properties['type'];
|
|
59
|
+
if (!isObject(type))
|
|
60
|
+
return false;
|
|
61
|
+
// zod literals serialize as one-element enums; accept const too.
|
|
62
|
+
const values = Array.isArray(type['enum']) ? type['enum'] : [type['const']];
|
|
63
|
+
return values.includes(ZODAPI_VALIDATION_TYPE);
|
|
64
|
+
}
|
|
65
|
+
/** ASP.NET-style `ValidationProblemDetails`: an `errors` map of string arrays plus problem members. */
|
|
66
|
+
function isValidationProblemSchema(schema) {
|
|
67
|
+
const properties = isObject(schema['properties']) ? schema['properties'] : {};
|
|
68
|
+
const errors = properties['errors'];
|
|
69
|
+
if (!isObject(errors))
|
|
70
|
+
return false;
|
|
71
|
+
const additional = errors['additionalProperties'];
|
|
72
|
+
const items = isObject(additional) ? additional['items'] : undefined;
|
|
73
|
+
const errorsAreStringArrays = isObject(additional) &&
|
|
74
|
+
additional['type'] === 'array' &&
|
|
75
|
+
isObject(items) &&
|
|
76
|
+
items['type'] === 'string';
|
|
77
|
+
const hasProblemMember = ['type', 'title', 'status', 'detail'].some((m) => m in properties);
|
|
78
|
+
return errorsAreStringArrays && hasProblemMember;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Detect which problem-details flavor a spec's error responses use, so
|
|
82
|
+
* generated contracts can carry a `problemFlavor` hint for
|
|
83
|
+
* `decodersFor(...)` on the client.
|
|
84
|
+
*/
|
|
85
|
+
export function detectProblemFlavor(doc) {
|
|
86
|
+
if (!isObject(doc))
|
|
87
|
+
return undefined;
|
|
88
|
+
const components = isObject(doc['components']) ? doc['components'] : {};
|
|
89
|
+
const schemas = isObject(components['schemas']) ? components['schemas'] : {};
|
|
90
|
+
const resolve = (schema) => {
|
|
91
|
+
if (!isObject(schema))
|
|
92
|
+
return undefined;
|
|
93
|
+
const ref = schema['$ref'];
|
|
94
|
+
if (typeof ref === 'string' && ref.startsWith(REF_PREFIX)) {
|
|
95
|
+
const target = schemas[ref.slice(REF_PREFIX.length)];
|
|
96
|
+
return isObject(target) ? target : undefined;
|
|
97
|
+
}
|
|
98
|
+
return schema;
|
|
99
|
+
};
|
|
100
|
+
let flavor;
|
|
101
|
+
const paths = isObject(doc['paths']) ? doc['paths'] : {};
|
|
102
|
+
for (const pathItem of Object.values(paths)) {
|
|
103
|
+
if (!isObject(pathItem))
|
|
104
|
+
continue;
|
|
105
|
+
for (const method of METHODS) {
|
|
106
|
+
const op = pathItem[method];
|
|
107
|
+
if (!isObject(op) || !isObject(op['responses']))
|
|
108
|
+
continue;
|
|
109
|
+
for (const [status, response] of Object.entries(op['responses'])) {
|
|
110
|
+
if (!/^[45]|^default$/.test(status))
|
|
111
|
+
continue;
|
|
112
|
+
if (!isObject(response) || !isObject(response['content']))
|
|
113
|
+
continue;
|
|
114
|
+
for (const mediaDef of Object.values(response['content'])) {
|
|
115
|
+
const schema = resolve(isObject(mediaDef) ? mediaDef['schema'] : undefined);
|
|
116
|
+
if (!schema)
|
|
117
|
+
continue;
|
|
118
|
+
if (isZodapiValidationSchema(schema))
|
|
119
|
+
return 'zodapi';
|
|
120
|
+
if (isValidationProblemSchema(schema))
|
|
121
|
+
flavor = 'problem-details';
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return flavor;
|
|
127
|
+
}
|
|
128
|
+
const DATE_CODEC_NAMES = {
|
|
129
|
+
datetime: 'isoDatetimeToDate',
|
|
130
|
+
date: 'isoDateToDate',
|
|
131
|
+
};
|
|
132
|
+
class Generator {
|
|
133
|
+
doc;
|
|
134
|
+
names = new NameAllocator();
|
|
135
|
+
declared = new Set();
|
|
136
|
+
usesQueryArray = false;
|
|
137
|
+
dateCodecs = new Map();
|
|
138
|
+
schemas;
|
|
139
|
+
ctx = {
|
|
140
|
+
dates: undefined,
|
|
141
|
+
dateCodec: (kind) => {
|
|
142
|
+
const existing = this.dateCodecs.get(kind);
|
|
143
|
+
if (existing !== undefined)
|
|
144
|
+
return existing;
|
|
145
|
+
// Distinct allocator key so a component named like the helper still wins its name.
|
|
146
|
+
const ident = this.names.allocate(`date-codec:${kind}`, DATE_CODEC_NAMES[kind]);
|
|
147
|
+
this.dateCodecs.set(kind, ident);
|
|
148
|
+
return ident;
|
|
149
|
+
},
|
|
150
|
+
resolveRef: (ref) => {
|
|
151
|
+
if (!ref.startsWith(REF_PREFIX))
|
|
152
|
+
throw new Error(`unsupported $ref: ${ref}`);
|
|
153
|
+
const original = ref.slice(REF_PREFIX.length);
|
|
154
|
+
const ident = this.names.lookup(original);
|
|
155
|
+
if (ident === undefined)
|
|
156
|
+
throw new Error(`$ref to unknown component: ${ref}`);
|
|
157
|
+
return { ident, forward: !this.declared.has(original) };
|
|
158
|
+
},
|
|
159
|
+
resolveComponentSchema: (ref) => {
|
|
160
|
+
if (!ref.startsWith(REF_PREFIX))
|
|
161
|
+
return undefined;
|
|
162
|
+
const target = this.schemas[ref.slice(REF_PREFIX.length)];
|
|
163
|
+
return isObject(target) ? target : undefined;
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
exportTypes;
|
|
167
|
+
constructor(doc, options) {
|
|
168
|
+
this.doc = doc;
|
|
169
|
+
const components = isObject(doc['components']) ? doc['components'] : {};
|
|
170
|
+
this.schemas = isObject(components['schemas']) ? components['schemas'] : {};
|
|
171
|
+
this.ctx.dates = options?.dates;
|
|
172
|
+
this.exportTypes = options?.exportTypes === true;
|
|
173
|
+
}
|
|
174
|
+
generate() {
|
|
175
|
+
const openapi = this.doc['openapi'];
|
|
176
|
+
if (typeof openapi !== 'string' || !openapi.startsWith('3.1')) {
|
|
177
|
+
throw new Error(`expected an OpenAPI 3.1 document, got openapi: ${json(openapi)}`);
|
|
178
|
+
}
|
|
179
|
+
const schemas = this.schemas;
|
|
180
|
+
const order = orderComponents(schemas);
|
|
181
|
+
// Allocate all component names first so refs resolve regardless of order.
|
|
182
|
+
for (const name of Object.keys(schemas))
|
|
183
|
+
this.names.allocate(name);
|
|
184
|
+
const componentDecls = order.map((name) => {
|
|
185
|
+
const expr = convertSchema(schemas[name], this.ctx);
|
|
186
|
+
const code = withMeta(expr.code, [`id: ${json(name)}`]);
|
|
187
|
+
this.declared.add(name);
|
|
188
|
+
const ident = this.names.lookup(name);
|
|
189
|
+
const constDecl = `export const ${ident} = ${code}\n`;
|
|
190
|
+
return this.exportTypes
|
|
191
|
+
? `${constDecl}export type ${ident} = z.infer<typeof ${ident}>\n`
|
|
192
|
+
: constDecl;
|
|
193
|
+
});
|
|
194
|
+
const routeDecls = [];
|
|
195
|
+
const routeIdents = [];
|
|
196
|
+
const paths = isObject(this.doc['paths']) ? this.doc['paths'] : {};
|
|
197
|
+
for (const [path, pathItem] of Object.entries(paths)) {
|
|
198
|
+
if (!isObject(pathItem))
|
|
199
|
+
continue;
|
|
200
|
+
for (const method of METHODS) {
|
|
201
|
+
const op = pathItem[method];
|
|
202
|
+
if (!isObject(op))
|
|
203
|
+
continue;
|
|
204
|
+
const ident = this.emitRoute(method, path, op, pathItem, routeDecls);
|
|
205
|
+
routeIdents.push(ident);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
const imports = [
|
|
209
|
+
`import type { RouteDef } from '@zodapi/core'`,
|
|
210
|
+
...(this.usesQueryArray ? [`import { queryArray } from '@zodapi/core'`] : []),
|
|
211
|
+
`import { z } from 'zod'`,
|
|
212
|
+
];
|
|
213
|
+
// RouteDef plus the documentation fields OpenAPI operations carry.
|
|
214
|
+
const routeType = 'type GeneratedRoute = RouteDef & {\n' +
|
|
215
|
+
' operationId?: string\n' +
|
|
216
|
+
' summary?: string\n' +
|
|
217
|
+
' description?: string\n' +
|
|
218
|
+
' tags?: readonly string[]\n' +
|
|
219
|
+
'}\n';
|
|
220
|
+
const routesArray = routeIdents.length === 0
|
|
221
|
+
? 'export const routes = [] as const\n'
|
|
222
|
+
: `export const routes = [\n${routeIdents.map((r) => ` ${r},`).join('\n')}\n] as const\n`;
|
|
223
|
+
// Problem flavor of the spec's error responses; pair with decodersFor()
|
|
224
|
+
// from @zodapi/client when creating a client for this contract.
|
|
225
|
+
const flavor = detectProblemFlavor(this.doc);
|
|
226
|
+
const flavorDecl = `export const problemFlavor: 'zodapi' | 'problem-details' | undefined = ${flavor === undefined ? 'undefined' : json(flavor)}\n`;
|
|
227
|
+
const dateCodecDecls = [...this.dateCodecs.entries()].map(([kind, ident]) => {
|
|
228
|
+
const fns = DATE_CODEC_FNS[kind];
|
|
229
|
+
const input = dateCodecInput(kind, this.ctx.dates ?? {});
|
|
230
|
+
return (`export const ${ident} = z.codec(${input}, z.date(), {\n` +
|
|
231
|
+
` decode: ${fns.decode},\n` +
|
|
232
|
+
` encode: ${fns.encode},\n` +
|
|
233
|
+
`})\n`);
|
|
234
|
+
});
|
|
235
|
+
return [
|
|
236
|
+
'// Generated by @zodapi/codegen. Do not edit.',
|
|
237
|
+
imports.join('\n'),
|
|
238
|
+
...(routeDecls.length > 0 ? [routeType] : []),
|
|
239
|
+
...dateCodecDecls,
|
|
240
|
+
...componentDecls,
|
|
241
|
+
...routeDecls,
|
|
242
|
+
routesArray,
|
|
243
|
+
flavorDecl,
|
|
244
|
+
].join('\n');
|
|
245
|
+
}
|
|
246
|
+
emitRoute(method, path, op, pathItem, out) {
|
|
247
|
+
const operationId = typeof op['operationId'] === 'string' ? op['operationId'] : undefined;
|
|
248
|
+
const ident = this.names.allocate(operationId ?? routeNameFromPath(method, path));
|
|
249
|
+
const lines = [`export const ${ident} = {`];
|
|
250
|
+
lines.push(` method: ${json(method)},`);
|
|
251
|
+
lines.push(` path: ${json(path)},`);
|
|
252
|
+
if (operationId !== undefined) {
|
|
253
|
+
lines.push(` alias: ${json(operationId)},`);
|
|
254
|
+
lines.push(` operationId: ${json(operationId)},`);
|
|
255
|
+
}
|
|
256
|
+
if (typeof op['summary'] === 'string')
|
|
257
|
+
lines.push(` summary: ${json(op['summary'])},`);
|
|
258
|
+
if (typeof op['description'] === 'string') {
|
|
259
|
+
lines.push(` description: ${json(op['description'])},`);
|
|
260
|
+
}
|
|
261
|
+
if (Array.isArray(op['tags']))
|
|
262
|
+
lines.push(` tags: ${json(op['tags'])},`);
|
|
263
|
+
const requestLines = this.requestLines(op, pathItem);
|
|
264
|
+
if (requestLines.length > 0) {
|
|
265
|
+
lines.push(' request: {', ...requestLines, ' },');
|
|
266
|
+
}
|
|
267
|
+
lines.push(' responses: {');
|
|
268
|
+
const responses = isObject(op['responses']) ? op['responses'] : {};
|
|
269
|
+
for (const [status, response] of Object.entries(responses)) {
|
|
270
|
+
if (!isObject(response))
|
|
271
|
+
continue;
|
|
272
|
+
const key = /^[0-9]+$/.test(status) ? status : json(status);
|
|
273
|
+
lines.push(` ${key}: {`);
|
|
274
|
+
if (typeof response['description'] === 'string') {
|
|
275
|
+
lines.push(` description: ${json(response['description'])},`);
|
|
276
|
+
}
|
|
277
|
+
if (isObject(response['content'])) {
|
|
278
|
+
lines.push(...this.contentLines(response['content'], ' '));
|
|
279
|
+
}
|
|
280
|
+
lines.push(' },');
|
|
281
|
+
}
|
|
282
|
+
lines.push(' },');
|
|
283
|
+
lines.push('} as const satisfies GeneratedRoute');
|
|
284
|
+
out.push(`${lines.join('\n')}\n`);
|
|
285
|
+
return ident;
|
|
286
|
+
}
|
|
287
|
+
requestLines(op, pathItem) {
|
|
288
|
+
const lines = [];
|
|
289
|
+
const parameters = [
|
|
290
|
+
...(Array.isArray(pathItem['parameters']) ? pathItem['parameters'] : []),
|
|
291
|
+
...(Array.isArray(op['parameters']) ? op['parameters'] : []),
|
|
292
|
+
].filter((p) => {
|
|
293
|
+
if (!isObject(p))
|
|
294
|
+
return false;
|
|
295
|
+
if (typeof p['$ref'] === 'string')
|
|
296
|
+
throw new Error(`unsupported $ref parameter: ${p['$ref']}`);
|
|
297
|
+
return typeof p['name'] === 'string' && typeof p['in'] === 'string';
|
|
298
|
+
});
|
|
299
|
+
const groups = [
|
|
300
|
+
{ key: 'params', in: 'path' },
|
|
301
|
+
{ key: 'query', in: 'query' },
|
|
302
|
+
{ key: 'headers', in: 'header' },
|
|
303
|
+
{ key: 'cookies', in: 'cookie' },
|
|
304
|
+
];
|
|
305
|
+
for (const group of groups) {
|
|
306
|
+
const members = parameters.filter((p) => p.in === group.in);
|
|
307
|
+
if (members.length === 0)
|
|
308
|
+
continue;
|
|
309
|
+
const entries = members.map((p) => {
|
|
310
|
+
let code = this.parameterExpr(p);
|
|
311
|
+
if (p.required !== true && group.in !== 'path')
|
|
312
|
+
code += '.optional()';
|
|
313
|
+
const name = /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(p.name) ? p.name : json(p.name);
|
|
314
|
+
return ` ${name}: ${code},`;
|
|
315
|
+
});
|
|
316
|
+
lines.push(` ${group.key}: z.object({`, ...entries, ' }),');
|
|
317
|
+
}
|
|
318
|
+
const body = op['requestBody'];
|
|
319
|
+
if (isObject(body)) {
|
|
320
|
+
lines.push(' body: {');
|
|
321
|
+
if (typeof body['description'] === 'string') {
|
|
322
|
+
lines.push(` description: ${json(body['description'])},`);
|
|
323
|
+
}
|
|
324
|
+
if (isObject(body['content']))
|
|
325
|
+
lines.push(...this.contentLines(body['content'], ' '));
|
|
326
|
+
if (typeof body['required'] === 'boolean') {
|
|
327
|
+
lines.push(` required: ${body['required']},`);
|
|
328
|
+
}
|
|
329
|
+
lines.push(' },');
|
|
330
|
+
}
|
|
331
|
+
return lines;
|
|
332
|
+
}
|
|
333
|
+
parameterExpr(p) {
|
|
334
|
+
const schema = p.schema ?? {};
|
|
335
|
+
if (p.in === 'query' && isObject(schema) && schema['type'] === 'array') {
|
|
336
|
+
this.usesQueryArray = true;
|
|
337
|
+
const items = schema['items'] === undefined ? 'z.unknown()' : this.expr(schema['items'], ' ');
|
|
338
|
+
const description = typeof p.description === 'string' ? `.meta({ description: ${json(p.description)} })` : '';
|
|
339
|
+
return `queryArray(${items})${description}`;
|
|
340
|
+
}
|
|
341
|
+
let code = this.expr(schema, ' ');
|
|
342
|
+
if (typeof p.description === 'string' && !(isObject(schema) && 'description' in schema)) {
|
|
343
|
+
code = withMeta(code, [`description: ${json(p.description)}`]);
|
|
344
|
+
}
|
|
345
|
+
return code;
|
|
346
|
+
}
|
|
347
|
+
contentLines(content, indent) {
|
|
348
|
+
const lines = [`${indent}content: {`];
|
|
349
|
+
for (const [media, mediaDef] of Object.entries(content)) {
|
|
350
|
+
if (!isObject(mediaDef))
|
|
351
|
+
continue;
|
|
352
|
+
if (mediaDef['schema'] === undefined) {
|
|
353
|
+
lines.push(`${indent} ${json(media)}: {},`);
|
|
354
|
+
}
|
|
355
|
+
else {
|
|
356
|
+
const schema = this.expr(mediaDef['schema'], `${indent} `);
|
|
357
|
+
lines.push(`${indent} ${json(media)}: {`, `${indent} schema: ${schema},`, `${indent} },`);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
lines.push(`${indent}},`);
|
|
361
|
+
return lines;
|
|
362
|
+
}
|
|
363
|
+
expr(schema, indent) {
|
|
364
|
+
return convertSchema(schema, this.ctx, indent).code;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Generate zodapi contract source (zod schemas + `RouteDef` route objects) from
|
|
369
|
+
* a parsed OpenAPI 3.1 document. The result imports only `zod` and
|
|
370
|
+
* `@zodapi/core`, and exports one const per component schema, one per
|
|
371
|
+
* operation, and a `routes` tuple for `createClient(routes)`.
|
|
372
|
+
*/
|
|
373
|
+
export function generateContract(doc, options) {
|
|
374
|
+
if (!isObject(doc))
|
|
375
|
+
throw new Error('expected a parsed OpenAPI document object');
|
|
376
|
+
return new Generator(doc, options).generate();
|
|
377
|
+
}
|
|
378
|
+
//# sourceMappingURL=generate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../src/generate.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { detectProblemFlavor, generateContract, type GenerateOptions, type ProblemFlavor, } from './generate.js';
|
|
2
|
+
export { convertSchema, type ConvertContext, type DateCodecKind, type DatesOptions, type Expr, type JsonSchema, } from './schema-to-zod.js';
|
|
3
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,KAAK,eAAe,EACpB,KAAK,aAAa,GACnB,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,aAAa,EACb,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,IAAI,EACT,KAAK,UAAU,GAChB,MAAM,oBAAoB,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,gBAAgB,GAGjB,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,aAAa,GAMd,MAAM,oBAAoB,CAAA"}
|
package/dist/names.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Allocates unique, valid TS identifiers, remembering the mapping from original names. */
|
|
2
|
+
export declare class NameAllocator {
|
|
3
|
+
private readonly used;
|
|
4
|
+
private readonly byOriginal;
|
|
5
|
+
allocate(original: string, preferred?: string): string;
|
|
6
|
+
lookup(original: string): string | undefined;
|
|
7
|
+
}
|
|
8
|
+
/** `get` + '/things/{id}' → 'getThingsId' — fallback route name when there is no operationId. */
|
|
9
|
+
export declare function routeNameFromPath(method: string, path: string): string;
|
|
10
|
+
//# sourceMappingURL=names.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"names.d.ts","sourceRoot":"","sources":["../src/names.ts"],"names":[],"mappings":"AAwDA,2FAA2F;AAC3F,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA4B;IACjD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA4B;IAEvD,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,SAAW,GAAG,MAAM,CAWvD;IAED,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE3C;CACF;AAED,iGAAiG;AACjG,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAQtE"}
|
package/dist/names.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
const RESERVED = new Set([
|
|
2
|
+
// generated-file imports and exports
|
|
3
|
+
'z',
|
|
4
|
+
'RouteDef',
|
|
5
|
+
'GeneratedRoute',
|
|
6
|
+
'queryArray',
|
|
7
|
+
'routes',
|
|
8
|
+
// JS reserved words that survive sanitization
|
|
9
|
+
'break',
|
|
10
|
+
'case',
|
|
11
|
+
'catch',
|
|
12
|
+
'class',
|
|
13
|
+
'const',
|
|
14
|
+
'continue',
|
|
15
|
+
'debugger',
|
|
16
|
+
'default',
|
|
17
|
+
'delete',
|
|
18
|
+
'do',
|
|
19
|
+
'else',
|
|
20
|
+
'enum',
|
|
21
|
+
'export',
|
|
22
|
+
'extends',
|
|
23
|
+
'false',
|
|
24
|
+
'finally',
|
|
25
|
+
'for',
|
|
26
|
+
'function',
|
|
27
|
+
'if',
|
|
28
|
+
'import',
|
|
29
|
+
'in',
|
|
30
|
+
'instanceof',
|
|
31
|
+
'new',
|
|
32
|
+
'null',
|
|
33
|
+
'return',
|
|
34
|
+
'super',
|
|
35
|
+
'switch',
|
|
36
|
+
'this',
|
|
37
|
+
'throw',
|
|
38
|
+
'true',
|
|
39
|
+
'try',
|
|
40
|
+
'typeof',
|
|
41
|
+
'var',
|
|
42
|
+
'void',
|
|
43
|
+
'while',
|
|
44
|
+
'with',
|
|
45
|
+
'yield',
|
|
46
|
+
'let',
|
|
47
|
+
'static',
|
|
48
|
+
'await',
|
|
49
|
+
]);
|
|
50
|
+
function sanitize(name) {
|
|
51
|
+
const cleaned = name.replace(/[^A-Za-z0-9_$]/g, '_');
|
|
52
|
+
const prefixed = /^[0-9]/.test(cleaned) ? `_${cleaned}` : cleaned;
|
|
53
|
+
return prefixed === '' ? '_' : prefixed;
|
|
54
|
+
}
|
|
55
|
+
/** Allocates unique, valid TS identifiers, remembering the mapping from original names. */
|
|
56
|
+
export class NameAllocator {
|
|
57
|
+
used = new Set(RESERVED);
|
|
58
|
+
byOriginal = new Map();
|
|
59
|
+
allocate(original, preferred = original) {
|
|
60
|
+
const existing = this.byOriginal.get(original);
|
|
61
|
+
if (existing !== undefined)
|
|
62
|
+
return existing;
|
|
63
|
+
const base = sanitize(preferred);
|
|
64
|
+
let candidate = base;
|
|
65
|
+
for (let i = 2; this.used.has(candidate); i++) {
|
|
66
|
+
candidate = `${base}${i}`;
|
|
67
|
+
}
|
|
68
|
+
this.used.add(candidate);
|
|
69
|
+
this.byOriginal.set(original, candidate);
|
|
70
|
+
return candidate;
|
|
71
|
+
}
|
|
72
|
+
lookup(original) {
|
|
73
|
+
return this.byOriginal.get(original);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/** `get` + '/things/{id}' → 'getThingsId' — fallback route name when there is no operationId. */
|
|
77
|
+
export function routeNameFromPath(method, path) {
|
|
78
|
+
const segments = path
|
|
79
|
+
.split('/')
|
|
80
|
+
.map((s) => s.replace(/[{}]/g, ''))
|
|
81
|
+
.flatMap((s) => s.split(/[^A-Za-z0-9]+/))
|
|
82
|
+
.filter(Boolean);
|
|
83
|
+
const camel = segments.map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join('');
|
|
84
|
+
return `${method}${camel || 'Root'}`;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=names.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"names.js","sourceRoot":"","sources":["../src/names.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts an OpenAPI 3.1 (JSON Schema) subschema into zod source code.
|
|
3
|
+
*
|
|
4
|
+
* Coverage is deliberately the subset zod itself can express and re-serialize
|
|
5
|
+
* via `z.toJSONSchema` — the round-trip test in this package is the contract:
|
|
6
|
+
* fixture zod → OpenAPI → this converter → zod → OpenAPI must be identical.
|
|
7
|
+
*/
|
|
8
|
+
export type JsonSchema = Record<string, unknown>;
|
|
9
|
+
/** Convert ISO date/time strings to `Date` objects via bidirectional `z.codec`s. */
|
|
10
|
+
export interface DatesOptions {
|
|
11
|
+
/** `format: date-time` → `z.codec(z.iso.datetime(), z.date(), ...)`. */
|
|
12
|
+
datetime?: boolean;
|
|
13
|
+
/** `format: date` → a codec decoding to `Date` at UTC midnight. */
|
|
14
|
+
date?: boolean;
|
|
15
|
+
/** Accept UTC offsets in date-time values (`z.iso.datetime({ offset: true })`). */
|
|
16
|
+
offset?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export type DateCodecKind = 'datetime' | 'date';
|
|
19
|
+
export interface ConvertContext {
|
|
20
|
+
/** Resolve a `$ref` to a generated identifier; `forward` when the target is not yet declared. */
|
|
21
|
+
resolveRef(ref: string): {
|
|
22
|
+
ident: string;
|
|
23
|
+
forward: boolean;
|
|
24
|
+
};
|
|
25
|
+
/** Resolve a `$ref` to its raw component schema, for structural checks; `undefined` when unknown. */
|
|
26
|
+
resolveComponentSchema(ref: string): JsonSchema | undefined;
|
|
27
|
+
/** Date-codec conversion options; absent → ISO strings stay strings. */
|
|
28
|
+
dates?: DatesOptions | undefined;
|
|
29
|
+
/** Identifier of the shared date codec for `kind`, registering it as used. */
|
|
30
|
+
dateCodec?: ((kind: DateCodecKind) => string) | undefined;
|
|
31
|
+
}
|
|
32
|
+
/** A zod expression plus whether it references an identifier declared later in the file. */
|
|
33
|
+
export interface Expr {
|
|
34
|
+
code: string;
|
|
35
|
+
forward: boolean;
|
|
36
|
+
/** Set when the schema's `default` was folded into the expression already. */
|
|
37
|
+
defaultHandled?: boolean;
|
|
38
|
+
}
|
|
39
|
+
/** The input-side (wire) schema of a date codec. */
|
|
40
|
+
export declare function dateCodecInput(kind: DateCodecKind, dates: DatesOptions): string;
|
|
41
|
+
/** decode/encode function source for each date codec kind. */
|
|
42
|
+
export declare const DATE_CODEC_FNS: Record<DateCodecKind, {
|
|
43
|
+
decode: string;
|
|
44
|
+
encode: string;
|
|
45
|
+
}>;
|
|
46
|
+
export declare function convertSchema(schema: unknown, ctx: ConvertContext, indent?: string): Expr;
|
|
47
|
+
//# sourceMappingURL=schema-to-zod.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-to-zod.d.ts","sourceRoot":"","sources":["../src/schema-to-zod.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAEhD,oFAAoF;AACpF,MAAM,WAAW,YAAY;IAC3B,wEAAwE;IACxE,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,mEAAmE;IACnE,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,mFAAmF;IACnF,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,MAAM,CAAA;AAE/C,MAAM,WAAW,cAAc;IAC7B,iGAAiG;IACjG,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAA;IAC5D,qGAAqG;IACrG,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAA;IAC3D,wEAAwE;IACxE,KAAK,CAAC,EAAE,YAAY,GAAG,SAAS,CAAA;IAChC,8EAA8E;IAC9E,SAAS,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,aAAa,KAAK,MAAM,CAAC,GAAG,SAAS,CAAA;CAC1D;AAED,4FAA4F;AAC5F,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,OAAO,CAAA;IAChB,8EAA8E;IAC9E,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AA2BD,oDAAoD;AACpD,wBAAgB,cAAc,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,GAAG,MAAM,CAI/E;AAED,8DAA8D;AAC9D,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,aAAa,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CASpF,CAAA;AAmSD,wBAAgB,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,EAAE,MAAM,SAAK,GAAG,IAAI,CASrF"}
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts an OpenAPI 3.1 (JSON Schema) subschema into zod source code.
|
|
3
|
+
*
|
|
4
|
+
* Coverage is deliberately the subset zod itself can express and re-serialize
|
|
5
|
+
* via `z.toJSONSchema` — the round-trip test in this package is the contract:
|
|
6
|
+
* fixture zod → OpenAPI → this converter → zod → OpenAPI must be identical.
|
|
7
|
+
*/
|
|
8
|
+
function lit(code) {
|
|
9
|
+
return { code, forward: false };
|
|
10
|
+
}
|
|
11
|
+
function isSchemaObject(s) {
|
|
12
|
+
return typeof s === 'object' && s !== null && !Array.isArray(s);
|
|
13
|
+
}
|
|
14
|
+
function json(value) {
|
|
15
|
+
return JSON.stringify(value);
|
|
16
|
+
}
|
|
17
|
+
const STRING_FORMATS = {
|
|
18
|
+
email: 'z.email()',
|
|
19
|
+
uuid: 'z.uuid()',
|
|
20
|
+
url: 'z.url()',
|
|
21
|
+
uri: 'z.url()',
|
|
22
|
+
'date-time': 'z.iso.datetime()',
|
|
23
|
+
date: 'z.iso.date()',
|
|
24
|
+
time: 'z.iso.time()',
|
|
25
|
+
duration: 'z.iso.duration()',
|
|
26
|
+
ipv4: 'z.ipv4()',
|
|
27
|
+
ipv6: 'z.ipv6()',
|
|
28
|
+
};
|
|
29
|
+
/** The input-side (wire) schema of a date codec. */
|
|
30
|
+
export function dateCodecInput(kind, dates) {
|
|
31
|
+
return kind === 'datetime'
|
|
32
|
+
? `z.iso.datetime(${dates.offset ? '{ offset: true }' : ''})`
|
|
33
|
+
: 'z.iso.date()';
|
|
34
|
+
}
|
|
35
|
+
/** decode/encode function source for each date codec kind. */
|
|
36
|
+
export const DATE_CODEC_FNS = {
|
|
37
|
+
datetime: {
|
|
38
|
+
decode: '(value) => new Date(value)',
|
|
39
|
+
encode: '(date) => date.toISOString()',
|
|
40
|
+
},
|
|
41
|
+
date: {
|
|
42
|
+
decode: '(value) => new Date(`${value}T00:00:00Z`)',
|
|
43
|
+
encode: '(date) => date.toISOString().slice(0, 10)',
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
function dateCodecExpr(kind, input) {
|
|
47
|
+
const fns = DATE_CODEC_FNS[kind];
|
|
48
|
+
return `z.codec(${input}, z.date(), { decode: ${fns.decode}, encode: ${fns.encode} })`;
|
|
49
|
+
}
|
|
50
|
+
function stringExpr(schema, ctx) {
|
|
51
|
+
const format = typeof schema['format'] === 'string' ? schema['format'] : undefined;
|
|
52
|
+
const kind = format === 'date-time' && ctx.dates?.datetime === true
|
|
53
|
+
? 'datetime'
|
|
54
|
+
: format === 'date' && ctx.dates?.date === true
|
|
55
|
+
? 'date'
|
|
56
|
+
: undefined;
|
|
57
|
+
if (kind !== undefined && ctx.dateCodec !== undefined) {
|
|
58
|
+
// Constraints and `default` belong to the codec's input (wire) side; the
|
|
59
|
+
// shared helper covers the bare case, anything else inlines the codec.
|
|
60
|
+
const bare = dateCodecInput(kind, ctx.dates ?? {});
|
|
61
|
+
let input = bare;
|
|
62
|
+
if (typeof schema['minLength'] === 'number')
|
|
63
|
+
input += `.min(${schema['minLength']})`;
|
|
64
|
+
if (typeof schema['maxLength'] === 'number')
|
|
65
|
+
input += `.max(${schema['maxLength']})`;
|
|
66
|
+
let defaultHandled = false;
|
|
67
|
+
if ('default' in schema) {
|
|
68
|
+
input += `.default(${json(schema['default'])})`;
|
|
69
|
+
defaultHandled = true;
|
|
70
|
+
}
|
|
71
|
+
if (input === bare)
|
|
72
|
+
return { code: ctx.dateCodec(kind), forward: false };
|
|
73
|
+
return { code: dateCodecExpr(kind, input), forward: false, defaultHandled };
|
|
74
|
+
}
|
|
75
|
+
let code = (format !== undefined && STRING_FORMATS[format]) || 'z.string()';
|
|
76
|
+
if (typeof schema['minLength'] === 'number')
|
|
77
|
+
code += `.min(${schema['minLength']})`;
|
|
78
|
+
if (typeof schema['maxLength'] === 'number')
|
|
79
|
+
code += `.max(${schema['maxLength']})`;
|
|
80
|
+
if (typeof schema['pattern'] === 'string' && (format === undefined || !STRING_FORMATS[format])) {
|
|
81
|
+
code += `.regex(new RegExp(${json(schema['pattern'])}))`;
|
|
82
|
+
}
|
|
83
|
+
return lit(code);
|
|
84
|
+
}
|
|
85
|
+
function numberExpr(schema, integer) {
|
|
86
|
+
let code = integer ? 'z.int()' : 'z.number()';
|
|
87
|
+
if (typeof schema['minimum'] === 'number')
|
|
88
|
+
code += `.min(${schema['minimum']})`;
|
|
89
|
+
if (typeof schema['maximum'] === 'number')
|
|
90
|
+
code += `.max(${schema['maximum']})`;
|
|
91
|
+
if (typeof schema['exclusiveMinimum'] === 'number')
|
|
92
|
+
code += `.gt(${schema['exclusiveMinimum']})`;
|
|
93
|
+
if (typeof schema['exclusiveMaximum'] === 'number')
|
|
94
|
+
code += `.lt(${schema['exclusiveMaximum']})`;
|
|
95
|
+
if (typeof schema['multipleOf'] === 'number')
|
|
96
|
+
code += `.multipleOf(${schema['multipleOf']})`;
|
|
97
|
+
return code;
|
|
98
|
+
}
|
|
99
|
+
function enumExpr(values) {
|
|
100
|
+
if (values.length > 0 && values.every((v) => typeof v === 'string')) {
|
|
101
|
+
return `z.enum([${values.map(json).join(', ')}])`;
|
|
102
|
+
}
|
|
103
|
+
if (values.length === 1)
|
|
104
|
+
return `z.literal(${json(values[0])})`;
|
|
105
|
+
return `z.union([${values.map((v) => `z.literal(${json(v)})`).join(', ')}])`;
|
|
106
|
+
}
|
|
107
|
+
function objectExpr(schema, ctx, indent) {
|
|
108
|
+
const properties = isSchemaObject(schema['properties']) ? schema['properties'] : undefined;
|
|
109
|
+
const required = new Set(Array.isArray(schema['required']) ? schema['required'] : []);
|
|
110
|
+
const additional = schema['additionalProperties'];
|
|
111
|
+
// A pure map type: no declared properties, values constrained by additionalProperties.
|
|
112
|
+
if (properties === undefined && isSchemaObject(additional)) {
|
|
113
|
+
const value = convertSchema(additional, ctx, indent);
|
|
114
|
+
return { code: `z.record(z.string(), ${value.code})`, forward: value.forward };
|
|
115
|
+
}
|
|
116
|
+
const inner = `${indent} `;
|
|
117
|
+
const entries = [];
|
|
118
|
+
let forward = false;
|
|
119
|
+
for (const [key, propSchema] of Object.entries(properties ?? {})) {
|
|
120
|
+
const prop = convertSchema(propSchema, ctx, inner);
|
|
121
|
+
const withOptional = required.has(key) ? prop.code : `${prop.code}.optional()`;
|
|
122
|
+
const name = /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key) ? key : json(key);
|
|
123
|
+
// Forward references must be deferred; zod object shapes support getters for this.
|
|
124
|
+
entries.push(prop.forward
|
|
125
|
+
? `${inner}get ${name}() {\n${inner} return ${withOptional}\n${inner}},`
|
|
126
|
+
: `${inner}${name}: ${withOptional},`);
|
|
127
|
+
forward ||= prop.forward;
|
|
128
|
+
}
|
|
129
|
+
const shape = entries.length === 0 ? '{}' : `{\n${entries.join('\n')}\n${indent}}`;
|
|
130
|
+
let code;
|
|
131
|
+
if (additional === true || (isSchemaObject(additional) && Object.keys(additional).length === 0)) {
|
|
132
|
+
code = `z.looseObject(${shape})`;
|
|
133
|
+
}
|
|
134
|
+
else if (isSchemaObject(additional)) {
|
|
135
|
+
const catchall = convertSchema(additional, ctx, indent);
|
|
136
|
+
forward ||= catchall.forward;
|
|
137
|
+
code = `z.object(${shape}).catchall(${catchall.code})`;
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
code = `z.object(${shape})`;
|
|
141
|
+
}
|
|
142
|
+
return { code, forward };
|
|
143
|
+
}
|
|
144
|
+
function arrayExpr(schema, ctx, indent) {
|
|
145
|
+
const prefixItems = schema['prefixItems'];
|
|
146
|
+
if (Array.isArray(prefixItems)) {
|
|
147
|
+
const members = prefixItems.map((m) => convertSchema(m, ctx, indent));
|
|
148
|
+
const rest = isSchemaObject(schema['items'])
|
|
149
|
+
? convertSchema(schema['items'], ctx, indent)
|
|
150
|
+
: undefined;
|
|
151
|
+
const args = `[${members.map((m) => m.code).join(', ')}]${rest ? `, ${rest.code}` : ''}`;
|
|
152
|
+
return {
|
|
153
|
+
code: `z.tuple(${args})`,
|
|
154
|
+
forward: members.some((m) => m.forward) || (rest?.forward ?? false),
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
const items = schema['items'] === undefined ? lit('z.unknown()') : convertSchema(schema['items'], ctx, indent);
|
|
158
|
+
let code = `z.array(${items.code})`;
|
|
159
|
+
if (typeof schema['minItems'] === 'number')
|
|
160
|
+
code += `.min(${schema['minItems']})`;
|
|
161
|
+
if (typeof schema['maxItems'] === 'number')
|
|
162
|
+
code += `.max(${schema['maxItems']})`;
|
|
163
|
+
return { code, forward: items.forward };
|
|
164
|
+
}
|
|
165
|
+
function unionExpr(members, ctx, indent) {
|
|
166
|
+
// X | null → X.nullable()
|
|
167
|
+
if (members.length === 2) {
|
|
168
|
+
const nullIdx = members.findIndex((m) => isSchemaObject(m) && m['type'] === 'null');
|
|
169
|
+
if (nullIdx !== -1) {
|
|
170
|
+
const other = convertSchema(members[1 - nullIdx], ctx, indent);
|
|
171
|
+
return { code: `${other.code}.nullable()`, forward: other.forward };
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
const exprs = members.map((m) => convertSchema(m, ctx, indent));
|
|
175
|
+
return {
|
|
176
|
+
code: `z.union([${exprs.map((e) => e.code).join(', ')}])`,
|
|
177
|
+
forward: exprs.some((e) => e.forward),
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
/** The string values `properties[propertyName]` pins a member to, or `undefined` if unusable. */
|
|
181
|
+
function discriminatorValues(component, propertyName) {
|
|
182
|
+
const properties = isSchemaObject(component['properties']) ? component['properties'] : undefined;
|
|
183
|
+
const property = properties?.[propertyName];
|
|
184
|
+
if (!isSchemaObject(property))
|
|
185
|
+
return undefined;
|
|
186
|
+
if (typeof property['const'] === 'string')
|
|
187
|
+
return [property['const']];
|
|
188
|
+
const values = property['enum'];
|
|
189
|
+
if (Array.isArray(values) && values.length > 0 && values.every((v) => typeof v === 'string')) {
|
|
190
|
+
return values;
|
|
191
|
+
}
|
|
192
|
+
return undefined;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* `oneOf`/`anyOf` with a `discriminator` → `z.discriminatedUnion(...)`, or `undefined` to fall
|
|
196
|
+
* back to a plain union. zod validates lazily at parse time, so a member the guards cannot prove
|
|
197
|
+
* safe (non-`$ref`, forward reference, or no `const`/string-enum discriminator property) would
|
|
198
|
+
* make the generated contract throw in userland — fall back instead. A `{type: "null"}` member is
|
|
199
|
+
* excluded from the union and restored with `.nullable()`.
|
|
200
|
+
*/
|
|
201
|
+
function discriminatedUnionExpr(schema, members, ctx) {
|
|
202
|
+
const discriminator = schema['discriminator'];
|
|
203
|
+
if (!isSchemaObject(discriminator))
|
|
204
|
+
return undefined;
|
|
205
|
+
const propertyName = discriminator['propertyName'];
|
|
206
|
+
if (typeof propertyName !== 'string')
|
|
207
|
+
return undefined;
|
|
208
|
+
const refs = [];
|
|
209
|
+
let nullable = false;
|
|
210
|
+
for (const member of members) {
|
|
211
|
+
if (!isSchemaObject(member))
|
|
212
|
+
return undefined;
|
|
213
|
+
if (member['type'] === 'null') {
|
|
214
|
+
nullable = true;
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
if (typeof member['$ref'] !== 'string' || Object.keys(member).length !== 1)
|
|
218
|
+
return undefined;
|
|
219
|
+
refs.push(member['$ref']);
|
|
220
|
+
}
|
|
221
|
+
if (refs.length < 2)
|
|
222
|
+
return undefined;
|
|
223
|
+
const idents = [];
|
|
224
|
+
const valuesByRef = new Map();
|
|
225
|
+
for (const ref of refs) {
|
|
226
|
+
const component = ctx.resolveComponentSchema(ref);
|
|
227
|
+
if (component === undefined)
|
|
228
|
+
return undefined;
|
|
229
|
+
const values = discriminatorValues(component, propertyName);
|
|
230
|
+
if (values === undefined)
|
|
231
|
+
return undefined;
|
|
232
|
+
const { ident, forward } = ctx.resolveRef(ref);
|
|
233
|
+
if (forward)
|
|
234
|
+
return undefined;
|
|
235
|
+
idents.push(ident);
|
|
236
|
+
valuesByRef.set(ref, values);
|
|
237
|
+
}
|
|
238
|
+
// `mapping` is redundant (zod reads the values off each member) but when present it must agree
|
|
239
|
+
// with the members: every entry must target a member whose discriminator values include the key.
|
|
240
|
+
const mapping = discriminator['mapping'];
|
|
241
|
+
if (mapping !== undefined) {
|
|
242
|
+
if (!isSchemaObject(mapping))
|
|
243
|
+
return undefined;
|
|
244
|
+
for (const [value, target] of Object.entries(mapping)) {
|
|
245
|
+
if (typeof target !== 'string')
|
|
246
|
+
return undefined;
|
|
247
|
+
// Mapping values may be a full `$ref` or a bare component name.
|
|
248
|
+
const ref = refs.find((r) => r === target || r.endsWith(`/${target}`));
|
|
249
|
+
if (ref === undefined || !valuesByRef.get(ref)?.includes(value))
|
|
250
|
+
return undefined;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
let code = `z.discriminatedUnion(${json(propertyName)}, [${idents.join(', ')}])`;
|
|
254
|
+
if (nullable)
|
|
255
|
+
code += '.nullable()';
|
|
256
|
+
return { code, forward: false };
|
|
257
|
+
}
|
|
258
|
+
function baseExpr(schema, ctx, indent) {
|
|
259
|
+
const ref = schema['$ref'];
|
|
260
|
+
if (typeof ref === 'string') {
|
|
261
|
+
const { ident, forward } = ctx.resolveRef(ref);
|
|
262
|
+
return { code: ident, forward };
|
|
263
|
+
}
|
|
264
|
+
if ('const' in schema)
|
|
265
|
+
return lit(`z.literal(${json(schema['const'])})`);
|
|
266
|
+
if (Array.isArray(schema['enum']))
|
|
267
|
+
return lit(enumExpr(schema['enum']));
|
|
268
|
+
const anyOf = schema['anyOf'] ?? schema['oneOf'];
|
|
269
|
+
if (Array.isArray(anyOf)) {
|
|
270
|
+
return discriminatedUnionExpr(schema, anyOf, ctx) ?? unionExpr(anyOf, ctx, indent);
|
|
271
|
+
}
|
|
272
|
+
if (Array.isArray(schema['allOf'])) {
|
|
273
|
+
const members = schema['allOf'].map((m) => convertSchema(m, ctx, indent));
|
|
274
|
+
const code = members
|
|
275
|
+
.map((m) => m.code)
|
|
276
|
+
.reduce((acc, next) => (acc === '' ? next : `z.intersection(${acc}, ${next})`), '');
|
|
277
|
+
return { code: code || 'z.unknown()', forward: members.some((m) => m.forward) };
|
|
278
|
+
}
|
|
279
|
+
const type = schema['type'];
|
|
280
|
+
if (Array.isArray(type)) {
|
|
281
|
+
if (type.length === 2 && type.includes('null')) {
|
|
282
|
+
const other = baseExpr({ ...schema, type: type.find((t) => t !== 'null') }, ctx, indent);
|
|
283
|
+
return {
|
|
284
|
+
code: `${other.code}.nullable()`,
|
|
285
|
+
forward: other.forward,
|
|
286
|
+
...(other.defaultHandled !== undefined && { defaultHandled: other.defaultHandled }),
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
return unionExpr(type.map((t) => ({ ...schema, type: t })), ctx, indent);
|
|
290
|
+
}
|
|
291
|
+
switch (type) {
|
|
292
|
+
case 'string':
|
|
293
|
+
return stringExpr(schema, ctx);
|
|
294
|
+
case 'number':
|
|
295
|
+
return lit(numberExpr(schema, false));
|
|
296
|
+
case 'integer':
|
|
297
|
+
return lit(numberExpr(schema, true));
|
|
298
|
+
case 'boolean':
|
|
299
|
+
return lit('z.boolean()');
|
|
300
|
+
case 'null':
|
|
301
|
+
return lit('z.null()');
|
|
302
|
+
case 'object':
|
|
303
|
+
return objectExpr(schema, ctx, indent);
|
|
304
|
+
case 'array':
|
|
305
|
+
return arrayExpr(schema, ctx, indent);
|
|
306
|
+
case undefined:
|
|
307
|
+
// Untyped but with object/array keywords still convert structurally.
|
|
308
|
+
if ('properties' in schema || 'additionalProperties' in schema) {
|
|
309
|
+
return objectExpr(schema, ctx, indent);
|
|
310
|
+
}
|
|
311
|
+
if ('items' in schema || 'prefixItems' in schema)
|
|
312
|
+
return arrayExpr(schema, ctx, indent);
|
|
313
|
+
return lit('z.unknown()');
|
|
314
|
+
default:
|
|
315
|
+
throw new Error(`unsupported schema type: ${json(type)}`);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
/** Metadata keywords carried through `.meta()` / `.default()` rather than validation. */
|
|
319
|
+
function metaSuffix(schema, skipDefault) {
|
|
320
|
+
let code = '';
|
|
321
|
+
if (!skipDefault && 'default' in schema)
|
|
322
|
+
code += `.default(${json(schema['default'])})`;
|
|
323
|
+
const meta = [];
|
|
324
|
+
if (typeof schema['title'] === 'string')
|
|
325
|
+
meta.push(`title: ${json(schema['title'])}`);
|
|
326
|
+
if (typeof schema['description'] === 'string') {
|
|
327
|
+
meta.push(`description: ${json(schema['description'])}`);
|
|
328
|
+
}
|
|
329
|
+
if (Array.isArray(schema['examples']))
|
|
330
|
+
meta.push(`examples: ${json(schema['examples'])}`);
|
|
331
|
+
if (schema['deprecated'] === true)
|
|
332
|
+
meta.push('deprecated: true');
|
|
333
|
+
if (meta.length > 0)
|
|
334
|
+
code += `.meta({ ${meta.join(', ')} })`;
|
|
335
|
+
return code;
|
|
336
|
+
}
|
|
337
|
+
export function convertSchema(schema, ctx, indent = '') {
|
|
338
|
+
if (schema === true)
|
|
339
|
+
return lit('z.unknown()');
|
|
340
|
+
if (schema === false)
|
|
341
|
+
return lit('z.never()');
|
|
342
|
+
if (!isSchemaObject(schema))
|
|
343
|
+
throw new Error(`expected a schema object, got ${json(schema)}`);
|
|
344
|
+
const base = baseExpr(schema, ctx, indent);
|
|
345
|
+
return {
|
|
346
|
+
code: base.code + metaSuffix(schema, base.defaultHandled === true),
|
|
347
|
+
forward: base.forward,
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
//# sourceMappingURL=schema-to-zod.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-to-zod.js","sourceRoot":"","sources":["../src/schema-to-zod.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAmCH,SAAS,GAAG,CAAC,IAAY;IACvB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAA;AACjC,CAAC;AAED,SAAS,cAAc,CAAC,CAAU;IAChC,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;AACjE,CAAC;AAED,SAAS,IAAI,CAAC,KAAc;IAC1B,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;AAC9B,CAAC;AAED,MAAM,cAAc,GAA2B;IAC7C,KAAK,EAAE,WAAW;IAClB,IAAI,EAAE,UAAU;IAChB,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,SAAS;IACd,WAAW,EAAE,kBAAkB;IAC/B,IAAI,EAAE,cAAc;IACpB,IAAI,EAAE,cAAc;IACpB,QAAQ,EAAE,kBAAkB;IAC5B,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,UAAU;CACjB,CAAA;AAED,oDAAoD;AACpD,MAAM,UAAU,cAAc,CAAC,IAAmB,EAAE,KAAmB;IACrE,OAAO,IAAI,KAAK,UAAU;QACxB,CAAC,CAAC,kBAAkB,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,GAAG;QAC7D,CAAC,CAAC,cAAc,CAAA;AACpB,CAAC;AAED,8DAA8D;AAC9D,MAAM,CAAC,MAAM,cAAc,GAA8D;IACvF,QAAQ,EAAE;QACR,MAAM,EAAE,4BAA4B;QACpC,MAAM,EAAE,8BAA8B;KACvC;IACD,IAAI,EAAE;QACJ,MAAM,EAAE,2CAA2C;QACnD,MAAM,EAAE,2CAA2C;KACpD;CACF,CAAA;AAED,SAAS,aAAa,CAAC,IAAmB,EAAE,KAAa;IACvD,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,CAAC,CAAA;IAChC,OAAO,WAAW,KAAK,yBAAyB,GAAG,CAAC,MAAM,aAAa,GAAG,CAAC,MAAM,KAAK,CAAA;AACxF,CAAC;AAED,SAAS,UAAU,CAAC,MAAkB,EAAE,GAAmB;IACzD,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IAClF,MAAM,IAAI,GACR,MAAM,KAAK,WAAW,IAAI,GAAG,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI;QACpD,CAAC,CAAC,UAAU;QACZ,CAAC,CAAC,MAAM,KAAK,MAAM,IAAI,GAAG,CAAC,KAAK,EAAE,IAAI,KAAK,IAAI;YAC7C,CAAC,CAAC,MAAM;YACR,CAAC,CAAC,SAAS,CAAA;IACjB,IAAI,IAAI,KAAK,SAAS,IAAI,GAAG,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QACtD,yEAAyE;QACzE,uEAAuE;QACvE,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAA;QAClD,IAAI,KAAK,GAAG,IAAI,CAAA;QAChB,IAAI,OAAO,MAAM,CAAC,WAAW,CAAC,KAAK,QAAQ;YAAE,KAAK,IAAI,QAAQ,MAAM,CAAC,WAAW,CAAC,GAAG,CAAA;QACpF,IAAI,OAAO,MAAM,CAAC,WAAW,CAAC,KAAK,QAAQ;YAAE,KAAK,IAAI,QAAQ,MAAM,CAAC,WAAW,CAAC,GAAG,CAAA;QACpF,IAAI,cAAc,GAAG,KAAK,CAAA;QAC1B,IAAI,SAAS,IAAI,MAAM,EAAE,CAAC;YACxB,KAAK,IAAI,YAAY,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,CAAA;YAC/C,cAAc,GAAG,IAAI,CAAA;QACvB,CAAC;QACD,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAA;QACxE,OAAO,EAAE,IAAI,EAAE,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,CAAA;IAC7E,CAAC;IAED,IAAI,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC,IAAI,YAAY,CAAA;IAC3E,IAAI,OAAO,MAAM,CAAC,WAAW,CAAC,KAAK,QAAQ;QAAE,IAAI,IAAI,QAAQ,MAAM,CAAC,WAAW,CAAC,GAAG,CAAA;IACnF,IAAI,OAAO,MAAM,CAAC,WAAW,CAAC,KAAK,QAAQ;QAAE,IAAI,IAAI,QAAQ,MAAM,CAAC,WAAW,CAAC,GAAG,CAAA;IACnF,IAAI,OAAO,MAAM,CAAC,SAAS,CAAC,KAAK,QAAQ,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;QAC/F,IAAI,IAAI,qBAAqB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAA;IAC1D,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,CAAC,CAAA;AAClB,CAAC;AAED,SAAS,UAAU,CAAC,MAAkB,EAAE,OAAgB;IACtD,IAAI,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,CAAA;IAC7C,IAAI,OAAO,MAAM,CAAC,SAAS,CAAC,KAAK,QAAQ;QAAE,IAAI,IAAI,QAAQ,MAAM,CAAC,SAAS,CAAC,GAAG,CAAA;IAC/E,IAAI,OAAO,MAAM,CAAC,SAAS,CAAC,KAAK,QAAQ;QAAE,IAAI,IAAI,QAAQ,MAAM,CAAC,SAAS,CAAC,GAAG,CAAA;IAC/E,IAAI,OAAO,MAAM,CAAC,kBAAkB,CAAC,KAAK,QAAQ;QAAE,IAAI,IAAI,OAAO,MAAM,CAAC,kBAAkB,CAAC,GAAG,CAAA;IAChG,IAAI,OAAO,MAAM,CAAC,kBAAkB,CAAC,KAAK,QAAQ;QAAE,IAAI,IAAI,OAAO,MAAM,CAAC,kBAAkB,CAAC,GAAG,CAAA;IAChG,IAAI,OAAO,MAAM,CAAC,YAAY,CAAC,KAAK,QAAQ;QAAE,IAAI,IAAI,eAAe,MAAM,CAAC,YAAY,CAAC,GAAG,CAAA;IAC5F,OAAO,IAAI,CAAA;AACb,CAAC;AAED,SAAS,QAAQ,CAAC,MAAiB;IACjC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,EAAE,CAAC;QACpE,OAAO,WAAW,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAA;IACnD,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,aAAa,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;IAC/D,OAAO,YAAY,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAA;AAC9E,CAAC;AAED,SAAS,UAAU,CAAC,MAAkB,EAAE,GAAmB,EAAE,MAAc;IACzE,MAAM,UAAU,GAAG,cAAc,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IAC1F,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;IACrF,MAAM,UAAU,GAAG,MAAM,CAAC,sBAAsB,CAAC,CAAA;IAEjD,uFAAuF;IACvF,IAAI,UAAU,KAAK,SAAS,IAAI,cAAc,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3D,MAAM,KAAK,GAAG,aAAa,CAAC,UAAU,EAAE,GAAG,EAAE,MAAM,CAAC,CAAA;QACpD,OAAO,EAAE,IAAI,EAAE,wBAAwB,KAAK,CAAC,IAAI,GAAG,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAA;IAChF,CAAC;IAED,MAAM,KAAK,GAAG,GAAG,MAAM,IAAI,CAAA;IAC3B,MAAM,OAAO,GAAa,EAAE,CAAA;IAC5B,IAAI,OAAO,GAAG,KAAK,CAAA;IACnB,KAAK,MAAM,CAAC,GAAG,EAAE,UAAU,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,IAAI,EAAE,CAAC,EAAE,CAAC;QACjE,MAAM,IAAI,GAAG,aAAa,CAAC,UAAU,EAAE,GAAG,EAAE,KAAK,CAAC,CAAA;QAClD,MAAM,YAAY,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,aAAa,CAAA;QAC9E,MAAM,IAAI,GAAG,4BAA4B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACrE,mFAAmF;QACnF,OAAO,CAAC,IAAI,CACV,IAAI,CAAC,OAAO;YACV,CAAC,CAAC,GAAG,KAAK,OAAO,IAAI,SAAS,KAAK,YAAY,YAAY,KAAK,KAAK,IAAI;YACzE,CAAC,CAAC,GAAG,KAAK,GAAG,IAAI,KAAK,YAAY,GAAG,CACxC,CAAA;QACD,OAAO,KAAK,IAAI,CAAC,OAAO,CAAA;IAC1B,CAAC;IACD,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,MAAM,GAAG,CAAA;IAElF,IAAI,IAAY,CAAA;IAChB,IAAI,UAAU,KAAK,IAAI,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;QAChG,IAAI,GAAG,iBAAiB,KAAK,GAAG,CAAA;IAClC,CAAC;SAAM,IAAI,cAAc,CAAC,UAAU,CAAC,EAAE,CAAC;QACtC,MAAM,QAAQ,GAAG,aAAa,CAAC,UAAU,EAAE,GAAG,EAAE,MAAM,CAAC,CAAA;QACvD,OAAO,KAAK,QAAQ,CAAC,OAAO,CAAA;QAC5B,IAAI,GAAG,YAAY,KAAK,cAAc,QAAQ,CAAC,IAAI,GAAG,CAAA;IACxD,CAAC;SAAM,CAAC;QACN,IAAI,GAAG,YAAY,KAAK,GAAG,CAAA;IAC7B,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA;AAC1B,CAAC;AAED,SAAS,SAAS,CAAC,MAAkB,EAAE,GAAmB,EAAE,MAAc;IACxE,MAAM,WAAW,GAAG,MAAM,CAAC,aAAa,CAAC,CAAA;IACzC,IAAI,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC,CAAA;QACrE,MAAM,IAAI,GAAG,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAC1C,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;YAC7C,CAAC,CAAC,SAAS,CAAA;QACb,MAAM,IAAI,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAA;QACxF,OAAO;YACL,IAAI,EAAE,WAAW,IAAI,GAAG;YACxB,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,IAAI,KAAK,CAAC;SACpE,CAAA;IACH,CAAC;IACD,MAAM,KAAK,GACT,MAAM,CAAC,OAAO,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,CAAA;IAClG,IAAI,IAAI,GAAG,WAAW,KAAK,CAAC,IAAI,GAAG,CAAA;IACnC,IAAI,OAAO,MAAM,CAAC,UAAU,CAAC,KAAK,QAAQ;QAAE,IAAI,IAAI,QAAQ,MAAM,CAAC,UAAU,CAAC,GAAG,CAAA;IACjF,IAAI,OAAO,MAAM,CAAC,UAAU,CAAC,KAAK,QAAQ;QAAE,IAAI,IAAI,QAAQ,MAAM,CAAC,UAAU,CAAC,GAAG,CAAA;IACjF,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAA;AACzC,CAAC;AAED,SAAS,SAAS,CAAC,OAAkB,EAAE,GAAmB,EAAE,MAAc;IACxE,0BAA0B;IAC1B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,MAAM,CAAC,CAAA;QACnF,IAAI,OAAO,KAAK,CAAC,CAAC,EAAE,CAAC;YACnB,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,CAAA;YAC9D,OAAO,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC,IAAI,aAAa,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAA;QACrE,CAAC;IACH,CAAC;IACD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC,CAAA;IAC/D,OAAO;QACL,IAAI,EAAE,YAAY,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;QACzD,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;KACtC,CAAA;AACH,CAAC;AAED,iGAAiG;AACjG,SAAS,mBAAmB,CAAC,SAAqB,EAAE,YAAoB;IACtE,MAAM,UAAU,GAAG,cAAc,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IAChG,MAAM,QAAQ,GAAG,UAAU,EAAE,CAAC,YAAY,CAAC,CAAA;IAC3C,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC;QAAE,OAAO,SAAS,CAAA;IAC/C,IAAI,OAAO,QAAQ,CAAC,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAA;IACrE,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAA;IAC/B,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,EAAE,CAAC;QAC7F,OAAO,MAAM,CAAA;IACf,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;;;;;GAMG;AACH,SAAS,sBAAsB,CAC7B,MAAkB,EAClB,OAAkB,EAClB,GAAmB;IAEnB,MAAM,aAAa,GAAG,MAAM,CAAC,eAAe,CAAC,CAAA;IAC7C,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC;QAAE,OAAO,SAAS,CAAA;IACpD,MAAM,YAAY,GAAG,aAAa,CAAC,cAAc,CAAC,CAAA;IAClD,IAAI,OAAO,YAAY,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAA;IAEtD,MAAM,IAAI,GAAa,EAAE,CAAA;IACzB,IAAI,QAAQ,GAAG,KAAK,CAAA;IACpB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC;YAAE,OAAO,SAAS,CAAA;QAC7C,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,MAAM,EAAE,CAAC;YAC9B,QAAQ,GAAG,IAAI,CAAA;YACf,SAAQ;QACV,CAAC;QACD,IAAI,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,SAAS,CAAA;QAC5F,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAA;IAC3B,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,SAAS,CAAA;IAErC,MAAM,MAAM,GAAa,EAAE,CAAA;IAC3B,MAAM,WAAW,GAAG,IAAI,GAAG,EAAoB,CAAA;IAC/C,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,SAAS,GAAG,GAAG,CAAC,sBAAsB,CAAC,GAAG,CAAC,CAAA;QACjD,IAAI,SAAS,KAAK,SAAS;YAAE,OAAO,SAAS,CAAA;QAC7C,MAAM,MAAM,GAAG,mBAAmB,CAAC,SAAS,EAAE,YAAY,CAAC,CAAA;QAC3D,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,SAAS,CAAA;QAC1C,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;QAC9C,IAAI,OAAO;YAAE,OAAO,SAAS,CAAA;QAC7B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAClB,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;IAC9B,CAAC;IAED,+FAA+F;IAC/F,iGAAiG;IACjG,MAAM,OAAO,GAAG,aAAa,CAAC,SAAS,CAAC,CAAA;IACxC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC;YAAE,OAAO,SAAS,CAAA;QAC9C,KAAK,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACtD,IAAI,OAAO,MAAM,KAAK,QAAQ;gBAAE,OAAO,SAAS,CAAA;YAChD,gEAAgE;YAChE,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,MAAM,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,MAAM,EAAE,CAAC,CAAC,CAAA;YACtE,IAAI,GAAG,KAAK,SAAS,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC;gBAAE,OAAO,SAAS,CAAA;QACnF,CAAC;IACH,CAAC;IAED,IAAI,IAAI,GAAG,wBAAwB,IAAI,CAAC,YAAY,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAA;IAChF,IAAI,QAAQ;QAAE,IAAI,IAAI,aAAa,CAAA;IACnC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAA;AACjC,CAAC;AAED,SAAS,QAAQ,CAAC,MAAkB,EAAE,GAAmB,EAAE,MAAc;IACvE,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAA;IAC1B,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;QAC9C,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAA;IACjC,CAAC;IAED,IAAI,OAAO,IAAI,MAAM;QAAE,OAAO,GAAG,CAAC,aAAa,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAA;IACxE,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAAE,OAAO,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;IAEvE,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,CAAA;IAChD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,sBAAsB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,IAAI,SAAS,CAAC,KAAK,EAAE,GAAG,EAAE,MAAM,CAAC,CAAA;IACpF,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC,CAAA;QACzE,MAAM,IAAI,GAAG,OAAO;aACjB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;aAClB,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,kBAAkB,GAAG,KAAK,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC,CAAA;QACrF,OAAO,EAAE,IAAI,EAAE,IAAI,IAAI,aAAa,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAA;IACjF,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAA;IAC3B,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC/C,MAAM,KAAK,GAAG,QAAQ,CAAC,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,CAAA;YACxF,OAAO;gBACL,IAAI,EAAE,GAAG,KAAK,CAAC,IAAI,aAAa;gBAChC,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,GAAG,CAAC,KAAK,CAAC,cAAc,KAAK,SAAS,IAAI,EAAE,cAAc,EAAE,KAAK,CAAC,cAAc,EAAE,CAAC;aACpF,CAAA;QACH,CAAC;QACD,OAAO,SAAS,CACd,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,EACzC,GAAG,EACH,MAAM,CACP,CAAA;IACH,CAAC;IAED,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,QAAQ;YACX,OAAO,UAAU,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;QAChC,KAAK,QAAQ;YACX,OAAO,GAAG,CAAC,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAA;QACvC,KAAK,SAAS;YACZ,OAAO,GAAG,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAA;QACtC,KAAK,SAAS;YACZ,OAAO,GAAG,CAAC,aAAa,CAAC,CAAA;QAC3B,KAAK,MAAM;YACT,OAAO,GAAG,CAAC,UAAU,CAAC,CAAA;QACxB,KAAK,QAAQ;YACX,OAAO,UAAU,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAA;QACxC,KAAK,OAAO;YACV,OAAO,SAAS,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAA;QACvC,KAAK,SAAS;YACZ,qEAAqE;YACrE,IAAI,YAAY,IAAI,MAAM,IAAI,sBAAsB,IAAI,MAAM,EAAE,CAAC;gBAC/D,OAAO,UAAU,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAA;YACxC,CAAC;YACD,IAAI,OAAO,IAAI,MAAM,IAAI,aAAa,IAAI,MAAM;gBAAE,OAAO,SAAS,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAA;YACvF,OAAO,GAAG,CAAC,aAAa,CAAC,CAAA;QAC3B;YACE,MAAM,IAAI,KAAK,CAAC,4BAA4B,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAC7D,CAAC;AACH,CAAC;AAED,yFAAyF;AACzF,SAAS,UAAU,CAAC,MAAkB,EAAE,WAAoB;IAC1D,IAAI,IAAI,GAAG,EAAE,CAAA;IACb,IAAI,CAAC,WAAW,IAAI,SAAS,IAAI,MAAM;QAAE,IAAI,IAAI,YAAY,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,CAAA;IACvF,MAAM,IAAI,GAAa,EAAE,CAAA;IACzB,IAAI,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,QAAQ;QAAE,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAA;IACrF,IAAI,OAAO,MAAM,CAAC,aAAa,CAAC,KAAK,QAAQ,EAAE,CAAC;QAC9C,IAAI,CAAC,IAAI,CAAC,gBAAgB,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,CAAA;IAC1D,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAAE,IAAI,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAA;IACzF,IAAI,MAAM,CAAC,YAAY,CAAC,KAAK,IAAI;QAAE,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAA;IAChE,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,IAAI,IAAI,WAAW,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAA;IAC5D,OAAO,IAAI,CAAA;AACb,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAe,EAAE,GAAmB,EAAE,MAAM,GAAG,EAAE;IAC7E,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,GAAG,CAAC,aAAa,CAAC,CAAA;IAC9C,IAAI,MAAM,KAAK,KAAK;QAAE,OAAO,GAAG,CAAC,WAAW,CAAC,CAAA;IAC7C,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IAC7F,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAA;IAC1C,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,cAAc,KAAK,IAAI,CAAC;QAClE,OAAO,EAAE,IAAI,CAAC,OAAO;KACtB,CAAA;AACH,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zodapi/codegen",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Generate a zodapi contract (zod schemas + route defs) from an OpenAPI 3.1 document",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"bin": {
|
|
7
|
+
"zodapi-codegen": "./dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"type": "module",
|
|
13
|
+
"sideEffects": false,
|
|
14
|
+
"main": "./dist/index.js",
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"default": "./dist/index.js"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@hono/zod-openapi": "^1.6.1",
|
|
24
|
+
"@types/node": "^26.4.0",
|
|
25
|
+
"@zodapi/core": "0.2.0",
|
|
26
|
+
"@zodapi/hono": "0.2.0",
|
|
27
|
+
"hono": "^4.13.5",
|
|
28
|
+
"tsx": "^4.23.12",
|
|
29
|
+
"zod": "^4.4.3"
|
|
30
|
+
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsc -p tsconfig.build.json",
|
|
33
|
+
"typecheck": "tsc --noEmit",
|
|
34
|
+
"generate:fixture": "tsx scripts/generate-fixture.ts"
|
|
35
|
+
}
|
|
36
|
+
}
|