apiwork 0.0.0 → 0.0.2
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 +311 -0
- package/dist/bin/apiwork.js +59 -0
- package/dist/chunk-4AJOYIJC.js +37 -0
- package/dist/chunk-7NDS6XB6.js +57 -0
- package/dist/chunk-MWFEILAW.js +28 -0
- package/dist/chunk-NQPUJJ3O.js +37 -0
- package/dist/chunk-QGKZLUZR.js +1151 -0
- package/dist/chunk-ZP6ZWEPI.js +127 -0
- package/dist/index.js +9 -0
- package/dist/sorbus/index.js +8 -0
- package/dist/typescript/index.js +8 -0
- package/dist/zod/index.js +8 -0
- package/package.json +57 -4
package/README.md
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
# apiwork-js
|
|
2
|
+
|
|
3
|
+
JavaScript toolkit for [Apiwork](https://apiwork.dev).
|
|
4
|
+
|
|
5
|
+
Provides a parser, TypeScript types, and code generators for TypeScript, [Zod](https://zod.dev), and [Sorbus](https://sorbus.dev).
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install apiwork
|
|
11
|
+
# or
|
|
12
|
+
pnpm add apiwork
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Schema
|
|
16
|
+
|
|
17
|
+
The [Apiwork schema](https://apiwork.dev/guide/exports/apiwork) is a portable JSON description of your API. Parse it and work with typed, camelCased objects:
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { parse } from 'apiwork';
|
|
21
|
+
import type { Schema, Resource, Action, Param } from 'apiwork';
|
|
22
|
+
|
|
23
|
+
// From raw JSON data
|
|
24
|
+
const schema = parse(data);
|
|
25
|
+
|
|
26
|
+
// From a URL
|
|
27
|
+
const schema = await parse.url('http://localhost:3000/api/v1/.apiwork');
|
|
28
|
+
|
|
29
|
+
// From a file
|
|
30
|
+
const schema = await parse.file('./apiwork.json');
|
|
31
|
+
|
|
32
|
+
for (const resource of schema.resources) {
|
|
33
|
+
console.log(resource.identifier);
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
> `parse.url()` and `parse.file()` throw `ParseError` on failure, with the underlying error preserved on `error.cause`.
|
|
38
|
+
|
|
39
|
+
## CLI
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
apiwork typescript ./apiwork.json --outdir src/api/sorbus
|
|
43
|
+
apiwork zod ./apiwork.json --outdir src/api/sorbus
|
|
44
|
+
apiwork sorbus ./apiwork.json --outdir src/api/sorbus
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The source can be a local file or a URL:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
apiwork sorbus http://localhost:3000/api/v1/.apiwork --outdir src/api/sorbus
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Generators
|
|
54
|
+
|
|
55
|
+
### TypeScript
|
|
56
|
+
|
|
57
|
+
Generates pure TypeScript types from representations and enums. Use this if you only need types without runtime validation.
|
|
58
|
+
|
|
59
|
+
### Zod
|
|
60
|
+
|
|
61
|
+
Generates Zod validation schemas alongside TypeScript types. Use this if you need runtime validation without a typed HTTP client.
|
|
62
|
+
|
|
63
|
+
### Sorbus
|
|
64
|
+
|
|
65
|
+
Generates a typed [Sorbus](https://sorbus.dev) client with operations, schemas, and endpoints. Includes everything from the TypeScript and Zod generators.
|
|
66
|
+
|
|
67
|
+
## Options
|
|
68
|
+
|
|
69
|
+
All three generators share common options (`fileCase`, `importExtension`, `transformIdentifier`) plus their own `version` for the output they produce:
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
import { generate } from 'apiwork/sorbus';
|
|
73
|
+
|
|
74
|
+
const files = generate(schema, {
|
|
75
|
+
version: 1, // Sorbus major version (default: 1)
|
|
76
|
+
zod: { version: 4 }, // Zod inline-schemas (default: 4)
|
|
77
|
+
typescript: { version: 5 }, // TypeScript types (default: 5)
|
|
78
|
+
fileCase: 'kebab',
|
|
79
|
+
importExtension: '.js',
|
|
80
|
+
transformIdentifier: (identifier, source) => {
|
|
81
|
+
if (source === 'api') return `Api${identifier}`;
|
|
82
|
+
if (source === 'client' && identifier === 'Client') return 'MyClient';
|
|
83
|
+
return identifier;
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### `version`
|
|
89
|
+
|
|
90
|
+
Each generator targets a specific major version of its output:
|
|
91
|
+
|
|
92
|
+
| Generator | `version` | Default |
|
|
93
|
+
|---|---|---|
|
|
94
|
+
| `apiwork/typescript` | TypeScript major | `5` |
|
|
95
|
+
| `apiwork/zod` | Zod major | `4` |
|
|
96
|
+
| `apiwork/sorbus` | Sorbus major | `1` |
|
|
97
|
+
|
|
98
|
+
Generators that produce output for multiple libraries take nested configuration:
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
// apiwork/typescript — just TS version
|
|
102
|
+
generate(schema, { version: 5 });
|
|
103
|
+
|
|
104
|
+
// apiwork/zod — Zod version + TS version for exported types
|
|
105
|
+
generate(schema, {
|
|
106
|
+
version: 4,
|
|
107
|
+
typescript: { version: 5 },
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// apiwork/sorbus — Sorbus version + Zod + TS
|
|
111
|
+
generate(schema, {
|
|
112
|
+
version: 1,
|
|
113
|
+
zod: { version: 4 },
|
|
114
|
+
typescript: { version: 5 },
|
|
115
|
+
});
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### `fileCase`
|
|
119
|
+
|
|
120
|
+
The file name case format. Accepts `'kebab'` (default), `'camel'`, `'pascal'`, or `'snake'`.
|
|
121
|
+
|
|
122
|
+
| Value | Example |
|
|
123
|
+
|---|---|
|
|
124
|
+
| `'kebab'` | `invoice-line-item.ts` |
|
|
125
|
+
| `'camel'` | `invoiceLineItem.ts` |
|
|
126
|
+
| `'pascal'` | `InvoiceLineItem.ts` |
|
|
127
|
+
| `'snake'` | `invoice_line_item.ts` |
|
|
128
|
+
|
|
129
|
+
### `importExtension`
|
|
130
|
+
|
|
131
|
+
The extension appended to relative import paths. Accepts `''` (default), `'.js'`, or `'.ts'`. Use `'.js'` for Node ESM or Deno.
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
// importExtension: '' → from '../api'
|
|
135
|
+
// importExtension: '.js' → from '../api.js'
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### `transformIdentifier`
|
|
139
|
+
|
|
140
|
+
A callback invoked for every identifier the generator emits. Return the name unchanged to keep the default, or return a new name to rename it.
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
transformIdentifier?: (identifier: string, source: IdentifierSource) => string;
|
|
144
|
+
|
|
145
|
+
type IdentifierSource = 'domain' | 'api' | 'endpoint' | 'client';
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
| `source` | Covers |
|
|
149
|
+
|---|---|
|
|
150
|
+
| `'domain'` | Types and schemas in `domains/*` (scoped domain types). |
|
|
151
|
+
| `'api'` | Types and schemas in `api.ts` (global domain types — highest collision risk). |
|
|
152
|
+
| `'endpoint'` | Types and schemas in `endpoints/*` (request, response, definition). |
|
|
153
|
+
| `'client'` | Sorbus-specific symbols: `Client`, `createClient`, `contract`. |
|
|
154
|
+
|
|
155
|
+
Example — prefix all global types and rename the Sorbus client:
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
transformIdentifier: (identifier, source) => {
|
|
159
|
+
if (source === 'api') return `Api${identifier}`;
|
|
160
|
+
if (source === 'client' && identifier === 'Client') return 'SkiftleClient';
|
|
161
|
+
if (source === 'client' && identifier === 'createClient') return 'createSkiftleClient';
|
|
162
|
+
return identifier;
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Generated output
|
|
167
|
+
|
|
168
|
+
Given this Apiwork schema:
|
|
169
|
+
|
|
170
|
+
```json
|
|
171
|
+
{
|
|
172
|
+
"enums": [
|
|
173
|
+
{ "name": "invoice_status", "values": ["draft", "sent", "paid"] }
|
|
174
|
+
],
|
|
175
|
+
"types": [
|
|
176
|
+
{
|
|
177
|
+
"name": "invoice",
|
|
178
|
+
"type": "object",
|
|
179
|
+
"shape": [
|
|
180
|
+
{ "name": "id", "type": "string" },
|
|
181
|
+
{ "name": "number", "type": "string" },
|
|
182
|
+
{ "name": "status", "type": "string", "enum": "invoice_status" },
|
|
183
|
+
{ "name": "issuedOn", "type": "date", "nullable": true },
|
|
184
|
+
{ "name": "createdAt", "type": "datetime" },
|
|
185
|
+
{ "name": "updatedAt", "type": "datetime" }
|
|
186
|
+
]
|
|
187
|
+
}
|
|
188
|
+
],
|
|
189
|
+
"resources": [
|
|
190
|
+
{
|
|
191
|
+
"identifier": "invoices",
|
|
192
|
+
"path": "invoices",
|
|
193
|
+
"actions": [
|
|
194
|
+
{ "name": "invoices.index", "method": "get", "path": "/invoices" },
|
|
195
|
+
{ "name": "invoices.show", "method": "get", "path": "/invoices/:id" },
|
|
196
|
+
{ "name": "invoices.create", "method": "post", "path": "/invoices" },
|
|
197
|
+
{ "name": "invoices.destroy", "method": "delete", "path": "/invoices/:id" }
|
|
198
|
+
]
|
|
199
|
+
}
|
|
200
|
+
]
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
`apiwork sorbus` generates:
|
|
205
|
+
|
|
206
|
+
```
|
|
207
|
+
api.ts
|
|
208
|
+
domains/
|
|
209
|
+
index.ts
|
|
210
|
+
endpoints/
|
|
211
|
+
invoices.ts
|
|
212
|
+
index.ts
|
|
213
|
+
contract.ts
|
|
214
|
+
client.ts
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
See the [full generated output](https://apiwork.dev/examples/representations#codegen) for a complete example.
|
|
218
|
+
|
|
219
|
+
## Frontend integration
|
|
220
|
+
|
|
221
|
+
Add a script to generate the client from your API:
|
|
222
|
+
|
|
223
|
+
```json
|
|
224
|
+
{
|
|
225
|
+
"scripts": {
|
|
226
|
+
"sorbus": "apiwork sorbus http://localhost:3000/api/v1/.apiwork --outdir src/api/sorbus"
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
pnpm sorbus
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Optionally, format the generated output:
|
|
236
|
+
|
|
237
|
+
```json
|
|
238
|
+
{
|
|
239
|
+
"scripts": {
|
|
240
|
+
"sorbus": "apiwork sorbus http://localhost:3000/api/v1/.apiwork --outdir src/api/sorbus && biome check --write src/api/sorbus"
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Using Prettier or Oxfmt? Replace `biome check --write` with `prettier --write` or `oxfmt`.
|
|
246
|
+
|
|
247
|
+
Use the generated client:
|
|
248
|
+
|
|
249
|
+
```ts
|
|
250
|
+
import { createClient } from './sorbus/client';
|
|
251
|
+
|
|
252
|
+
const api = createClient('http://localhost:3000/api/v1');
|
|
253
|
+
|
|
254
|
+
const { invoices } = await api.invoices.index();
|
|
255
|
+
|
|
256
|
+
const { invoice } = await api.invoices.show({ id: '1' });
|
|
257
|
+
|
|
258
|
+
const result = await api.invoices.create(
|
|
259
|
+
{ invoice: { number: 'INV-001', customerId: '1' } },
|
|
260
|
+
{ catch: [422] },
|
|
261
|
+
);
|
|
262
|
+
|
|
263
|
+
if (!result.ok) {
|
|
264
|
+
console.log(result.data);
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
## API Reference
|
|
269
|
+
|
|
270
|
+
### `apiwork`
|
|
271
|
+
|
|
272
|
+
Parser and schema types.
|
|
273
|
+
|
|
274
|
+
**Values:**
|
|
275
|
+
- `parse(data)` — parse raw JSON data into a `Schema`
|
|
276
|
+
- `parse.url(url)` — fetch and parse from a URL
|
|
277
|
+
- `parse.file(path)` — read and parse from a file
|
|
278
|
+
- `ParseError` — thrown on parse failures, with `cause` on `error.cause`
|
|
279
|
+
|
|
280
|
+
**Types:**
|
|
281
|
+
|
|
282
|
+
`Action`, `ActionMethod`, `ActionRequest`, `ActionResponse`, `ArrayParam`, `BinaryParam`, `BooleanParam`, `DateParam`, `DatetimeParam`, `DecimalParam`, `Enum`, `ErrorCode`, `FileCase`, `GenerateOptions`, `IdentifierSource`, `Info`, `InfoContact`, `InfoLicense`, `InfoServer`, `IntegerParam`, `LiteralParam`, `NumberParam`, `ObjectParam`, `ObjectType`, `Param`, `RecordParam`, `ReferenceParam`, `Resource`, `Schema`, `StringParam`, `TimeParam`, `Type`, `UnionParam`, `UnionType`, `UnknownParam`, `UuidParam`
|
|
283
|
+
|
|
284
|
+
### `apiwork/typescript`
|
|
285
|
+
|
|
286
|
+
TypeScript code generator — produces pure TypeScript types from the schema.
|
|
287
|
+
|
|
288
|
+
- `generate(schema, options?)` — returns a `Map<string, string>` of file paths to file contents
|
|
289
|
+
- `TypescriptGenerateOptions` — options type
|
|
290
|
+
|
|
291
|
+
### `apiwork/zod`
|
|
292
|
+
|
|
293
|
+
Zod code generator — produces Zod schemas plus TypeScript types.
|
|
294
|
+
|
|
295
|
+
- `generate(schema, options?)` — returns a `Map<string, string>` of file paths to file contents
|
|
296
|
+
- `ZodGenerateOptions` — options type
|
|
297
|
+
|
|
298
|
+
### `apiwork/sorbus`
|
|
299
|
+
|
|
300
|
+
Sorbus code generator — produces a typed Sorbus client, contract, Zod schemas, and TypeScript types.
|
|
301
|
+
|
|
302
|
+
- `generate(schema, options?)` — returns a `Map<string, string>` of file paths to file contents
|
|
303
|
+
- `SorbusGenerateOptions` — options type
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
All exported symbols carry full TSDoc. Hover over any import in your IDE to see descriptions, parameter docs, and examples.
|
|
308
|
+
|
|
309
|
+
## License
|
|
310
|
+
|
|
311
|
+
MIT
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
parse
|
|
4
|
+
} from "../chunk-7NDS6XB6.js";
|
|
5
|
+
import {
|
|
6
|
+
generate
|
|
7
|
+
} from "../chunk-ZP6ZWEPI.js";
|
|
8
|
+
import {
|
|
9
|
+
generate as generate2
|
|
10
|
+
} from "../chunk-4AJOYIJC.js";
|
|
11
|
+
import {
|
|
12
|
+
generate as generate3
|
|
13
|
+
} from "../chunk-NQPUJJ3O.js";
|
|
14
|
+
import {
|
|
15
|
+
writeFiles
|
|
16
|
+
} from "../chunk-QGKZLUZR.js";
|
|
17
|
+
import "../chunk-MWFEILAW.js";
|
|
18
|
+
|
|
19
|
+
// src/cli.ts
|
|
20
|
+
import { parseArgs } from "util";
|
|
21
|
+
var generators = {
|
|
22
|
+
sorbus: generate,
|
|
23
|
+
typescript: generate2,
|
|
24
|
+
zod: generate3
|
|
25
|
+
};
|
|
26
|
+
async function run(args) {
|
|
27
|
+
const { positionals, values } = parseArgs({
|
|
28
|
+
allowPositionals: true,
|
|
29
|
+
args,
|
|
30
|
+
options: {
|
|
31
|
+
outdir: {
|
|
32
|
+
short: "o",
|
|
33
|
+
type: "string"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
const [command, url] = positionals;
|
|
38
|
+
if (!command || !url) {
|
|
39
|
+
console.error("Usage: apiwork <generator> <url> --outdir <dir>");
|
|
40
|
+
console.error("Generators: typescript, zod, sorbus");
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
const generator = generators[command];
|
|
44
|
+
if (!generator) {
|
|
45
|
+
console.error(`Unknown generator: ${command}`);
|
|
46
|
+
console.error(`Available: ${Object.keys(generators).join(", ")}`);
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
const outdir = values.outdir ?? ".";
|
|
50
|
+
const schema = url.startsWith("http://") || url.startsWith("https://") ? await parse.url(url) : await parse.file(url);
|
|
51
|
+
const files = generator(schema);
|
|
52
|
+
await writeFiles(outdir, files);
|
|
53
|
+
for (const filename of files.keys()) {
|
|
54
|
+
console.log(` ${filename}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// src/bin/apiwork.ts
|
|
59
|
+
run(process.argv.slice(2));
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildEndpoints,
|
|
3
|
+
buildSchemas,
|
|
4
|
+
buildScopeIndex,
|
|
5
|
+
resolveGenerateOptions
|
|
6
|
+
} from "./chunk-QGKZLUZR.js";
|
|
7
|
+
|
|
8
|
+
// src/typescript/generate.ts
|
|
9
|
+
function generate(schema, options = {}) {
|
|
10
|
+
const resolvedOptions = resolveGenerateOptions(options);
|
|
11
|
+
const scopeIndex = buildScopeIndex(schema);
|
|
12
|
+
const files = /* @__PURE__ */ new Map();
|
|
13
|
+
for (const [filename, content] of buildSchemas(
|
|
14
|
+
schema,
|
|
15
|
+
{ zod: false },
|
|
16
|
+
resolvedOptions
|
|
17
|
+
)) {
|
|
18
|
+
files.set(filename, content);
|
|
19
|
+
}
|
|
20
|
+
for (const [filename, content] of buildEndpoints(
|
|
21
|
+
schema,
|
|
22
|
+
scopeIndex,
|
|
23
|
+
{
|
|
24
|
+
endpoints: false,
|
|
25
|
+
reexportChildren: false,
|
|
26
|
+
zod: false
|
|
27
|
+
},
|
|
28
|
+
resolvedOptions
|
|
29
|
+
)) {
|
|
30
|
+
files.set(filename, content);
|
|
31
|
+
}
|
|
32
|
+
return files;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export {
|
|
36
|
+
generate
|
|
37
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import {
|
|
2
|
+
camelCaseKeys
|
|
3
|
+
} from "./chunk-MWFEILAW.js";
|
|
4
|
+
|
|
5
|
+
// src/parse.ts
|
|
6
|
+
import { readFile } from "fs/promises";
|
|
7
|
+
var ParseError = class extends Error {
|
|
8
|
+
constructor(message, options) {
|
|
9
|
+
super(message, options);
|
|
10
|
+
this.name = "ParseError";
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
function parseData(data) {
|
|
14
|
+
return camelCaseKeys(data);
|
|
15
|
+
}
|
|
16
|
+
async function parseUrl(url) {
|
|
17
|
+
let response;
|
|
18
|
+
try {
|
|
19
|
+
response = await fetch(url);
|
|
20
|
+
} catch (cause) {
|
|
21
|
+
throw new ParseError(`Failed to fetch schema from ${url}`, { cause });
|
|
22
|
+
}
|
|
23
|
+
if (!response.ok) {
|
|
24
|
+
throw new ParseError(
|
|
25
|
+
`Failed to fetch schema from ${url}: ${response.status} ${response.statusText}`
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
let data;
|
|
29
|
+
try {
|
|
30
|
+
data = await response.json();
|
|
31
|
+
} catch (cause) {
|
|
32
|
+
throw new ParseError(`Schema at ${url} is not valid JSON`, { cause });
|
|
33
|
+
}
|
|
34
|
+
return parseData(data);
|
|
35
|
+
}
|
|
36
|
+
async function parseFile(path) {
|
|
37
|
+
let content;
|
|
38
|
+
try {
|
|
39
|
+
content = await readFile(path, "utf-8");
|
|
40
|
+
} catch (cause) {
|
|
41
|
+
throw new ParseError(`Failed to read schema from ${path}`, { cause });
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
return parseData(JSON.parse(content));
|
|
45
|
+
} catch (cause) {
|
|
46
|
+
throw new ParseError(`Schema at ${path} is not valid JSON`, { cause });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
var parse = Object.assign(parseData, {
|
|
50
|
+
file: parseFile,
|
|
51
|
+
url: parseUrl
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
export {
|
|
55
|
+
ParseError,
|
|
56
|
+
parse
|
|
57
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// src/utils/camel-case.ts
|
|
2
|
+
function camelCase(name) {
|
|
3
|
+
const leading = /^_+/.exec(name)?.[0] ?? "";
|
|
4
|
+
return leading + name.slice(leading.length).replace(
|
|
5
|
+
/[-_]([a-z])/g,
|
|
6
|
+
(_match, character) => character.toUpperCase()
|
|
7
|
+
);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// src/utils/camel-case-keys.ts
|
|
11
|
+
function camelCaseKeys(value) {
|
|
12
|
+
if (Array.isArray(value)) {
|
|
13
|
+
return value.map(camelCaseKeys);
|
|
14
|
+
}
|
|
15
|
+
if (value !== null && typeof value === "object") {
|
|
16
|
+
const result = {};
|
|
17
|
+
for (const [key, entryValue] of Object.entries(value)) {
|
|
18
|
+
result[camelCase(key)] = camelCaseKeys(entryValue);
|
|
19
|
+
}
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
return value;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export {
|
|
26
|
+
camelCase,
|
|
27
|
+
camelCaseKeys
|
|
28
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildEndpoints,
|
|
3
|
+
buildSchemas,
|
|
4
|
+
buildScopeIndex,
|
|
5
|
+
resolveGenerateOptions
|
|
6
|
+
} from "./chunk-QGKZLUZR.js";
|
|
7
|
+
|
|
8
|
+
// src/zod/generate.ts
|
|
9
|
+
function generate(schema, options = {}) {
|
|
10
|
+
const resolvedOptions = resolveGenerateOptions(options);
|
|
11
|
+
const scopeIndex = buildScopeIndex(schema);
|
|
12
|
+
const files = /* @__PURE__ */ new Map();
|
|
13
|
+
for (const [filename, content] of buildSchemas(
|
|
14
|
+
schema,
|
|
15
|
+
{ zod: true },
|
|
16
|
+
resolvedOptions
|
|
17
|
+
)) {
|
|
18
|
+
files.set(filename, content);
|
|
19
|
+
}
|
|
20
|
+
for (const [filename, content] of buildEndpoints(
|
|
21
|
+
schema,
|
|
22
|
+
scopeIndex,
|
|
23
|
+
{
|
|
24
|
+
endpoints: false,
|
|
25
|
+
reexportChildren: false,
|
|
26
|
+
zod: true
|
|
27
|
+
},
|
|
28
|
+
resolvedOptions
|
|
29
|
+
)) {
|
|
30
|
+
files.set(filename, content);
|
|
31
|
+
}
|
|
32
|
+
return files;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export {
|
|
36
|
+
generate
|
|
37
|
+
};
|