@powerduck/openapi-codegen 0.4.3 → 0.5.1
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 +195 -72
- package/dist/index.cjs +1 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +271 -0
- package/dist/index.d.ts +271 -0
- package/dist/index.js +1 -6785
- package/dist/index.js.map +1 -0
- package/package.json +35 -25
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Powerduck limited
|
|
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
CHANGED
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
# @powerduck/openapi-codegen
|
|
2
2
|
|
|
3
|
-
Generate runnable HTTP request examples from
|
|
3
|
+
Generate runnable HTTP request examples from OpenAPI documents for **21 languages** and **41 language/client combinations**.
|
|
4
4
|
|
|
5
|
-
`@powerduck/openapi-codegen` is
|
|
5
|
+
`@powerduck/openapi-codegen` is a high-performance, browser-compatible TypeScript library for API documentation systems, developer portals, API explorers, command-line tools, and build-time code generation.
|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
- Ships as an ECMAScript module
|
|
9
|
+
- **Zero runtime dependencies** — works in browser, Node.js, Electron, and edge environments
|
|
10
|
+
- **Dual module support** — native ESM and CommonJS (`require()`)
|
|
11
|
+
- **OpenAPI 3.0, 3.1, and 3.2** support
|
|
12
|
+
- **41 built-in generators** across 21 languages
|
|
13
|
+
- **Parameter serialization** — path, query, header, cookie with full OpenAPI style support
|
|
14
|
+
- **Security schemes** — API key, HTTP bearer, HTTP basic
|
|
15
|
+
- **Body types** — JSON, plain-text, URL-encoded form, multipart form-data
|
|
16
|
+
- **$ref resolution** — in-document JSON Pointer references with circular detection
|
|
17
|
+
- **Example generation** — automatic example values from JSON Schema
|
|
18
|
+
- **TypeScript declarations** — full type safety
|
|
19
|
+
- **Highly optimized** — no `JSON.parse`/`JSON.stringify` deep cloning, structured reference handling
|
|
21
20
|
|
|
22
21
|
## Supported Languages and Clients
|
|
23
22
|
|
|
@@ -51,9 +50,9 @@ Use the exact `language` and `client` identifiers shown below when calling `gene
|
|
|
51
50
|
|
|
52
51
|
## Requirements
|
|
53
52
|
|
|
54
|
-
- Node.js
|
|
55
|
-
- A parsed OpenAPI document
|
|
56
|
-
-
|
|
53
|
+
- Node.js 18 or later (for Node.js usage)
|
|
54
|
+
- A parsed OpenAPI document (JavaScript object)
|
|
55
|
+
- Modern browser with Fetch API (for browser usage)
|
|
57
56
|
|
|
58
57
|
## Installation
|
|
59
58
|
|
|
@@ -77,7 +76,9 @@ yarn add @powerduck/openapi-codegen
|
|
|
77
76
|
|
|
78
77
|
## Quick Start
|
|
79
78
|
|
|
80
|
-
|
|
79
|
+
### ESM (import)
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
81
82
|
import { generate } from "@powerduck/openapi-codegen";
|
|
82
83
|
import document from "./openapi.json" with { type: "json" };
|
|
83
84
|
|
|
@@ -92,15 +93,33 @@ const code = generate({
|
|
|
92
93
|
console.log(code);
|
|
93
94
|
```
|
|
94
95
|
|
|
96
|
+
### CommonJS (require)
|
|
97
|
+
|
|
98
|
+
```javascript
|
|
99
|
+
const { generate } = require("@powerduck/openapi-codegen");
|
|
100
|
+
const fs = require("node:fs");
|
|
101
|
+
|
|
102
|
+
const document = JSON.parse(fs.readFileSync("./openapi.json", "utf8"));
|
|
103
|
+
|
|
104
|
+
const code = generate({
|
|
105
|
+
document,
|
|
106
|
+
path: "/users/{id}",
|
|
107
|
+
method: "get",
|
|
108
|
+
language: "python",
|
|
109
|
+
client: "requests",
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
console.log(code);
|
|
113
|
+
```
|
|
114
|
+
|
|
95
115
|
`generate()` returns the generated source code as a string.
|
|
96
116
|
|
|
97
117
|
## Authentication
|
|
98
118
|
|
|
99
119
|
Provide credentials through `securityValues`:
|
|
100
120
|
|
|
101
|
-
```
|
|
121
|
+
```typescript
|
|
102
122
|
import { generate } from "@powerduck/openapi-codegen";
|
|
103
|
-
import document from "./openapi.json" with { type: "json" };
|
|
104
123
|
|
|
105
124
|
const code = generate({
|
|
106
125
|
document,
|
|
@@ -109,7 +128,7 @@ const code = generate({
|
|
|
109
128
|
language: "javascript",
|
|
110
129
|
client: "fetch",
|
|
111
130
|
securityValues: {
|
|
112
|
-
|
|
131
|
+
bearerAuth: "YOUR_ACCESS_TOKEN",
|
|
113
132
|
apiKey: "YOUR_API_KEY",
|
|
114
133
|
},
|
|
115
134
|
});
|
|
@@ -119,13 +138,12 @@ console.log(code);
|
|
|
119
138
|
|
|
120
139
|
The keys in `securityValues` must match the security scheme names defined in the OpenAPI document.
|
|
121
140
|
|
|
122
|
-
Do not commit real credentials to source control.
|
|
141
|
+
**Security note:** Do not commit real credentials to source control.
|
|
123
142
|
|
|
124
143
|
## Multipart Uploads
|
|
125
144
|
|
|
126
|
-
```
|
|
145
|
+
```typescript
|
|
127
146
|
import { generate } from "@powerduck/openapi-codegen";
|
|
128
|
-
import document from "./openapi.json" with { type: "json" };
|
|
129
147
|
|
|
130
148
|
const code = generate({
|
|
131
149
|
document,
|
|
@@ -134,7 +152,7 @@ const code = generate({
|
|
|
134
152
|
language: "shell",
|
|
135
153
|
client: "curl",
|
|
136
154
|
securityValues: {
|
|
137
|
-
|
|
155
|
+
bearerAuth: "YOUR_ACCESS_TOKEN",
|
|
138
156
|
},
|
|
139
157
|
});
|
|
140
158
|
|
|
@@ -157,7 +175,7 @@ For example, `shell/wget` does not support arbitrary multipart generation. Use `
|
|
|
157
175
|
|
|
158
176
|
Use `list()` to inspect every installed language/client combination:
|
|
159
177
|
|
|
160
|
-
```
|
|
178
|
+
```typescript
|
|
161
179
|
import { list } from "@powerduck/openapi-codegen";
|
|
162
180
|
|
|
163
181
|
for (const { language, client } of list()) {
|
|
@@ -167,9 +185,8 @@ for (const { language, client } of list()) {
|
|
|
167
185
|
|
|
168
186
|
You can also select a generator programmatically:
|
|
169
187
|
|
|
170
|
-
```
|
|
188
|
+
```typescript
|
|
171
189
|
import { generate, list } from "@powerduck/openapi-codegen";
|
|
172
|
-
import document from "./openapi.json" with { type: "json" };
|
|
173
190
|
|
|
174
191
|
const generator = list().find(
|
|
175
192
|
({ language, client }) => language === "javascript" && client === "fetch",
|
|
@@ -190,13 +207,28 @@ const code = generate({
|
|
|
190
207
|
console.log(code);
|
|
191
208
|
```
|
|
192
209
|
|
|
210
|
+
## Custom Server URL
|
|
211
|
+
|
|
212
|
+
Override the server URL from the OpenAPI document:
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
const code = generate({
|
|
216
|
+
document,
|
|
217
|
+
path: "/users",
|
|
218
|
+
method: "get",
|
|
219
|
+
language: "shell",
|
|
220
|
+
client: "curl",
|
|
221
|
+
serverUrl: "https://staging.example.com/v1",
|
|
222
|
+
});
|
|
223
|
+
```
|
|
224
|
+
|
|
193
225
|
## API Reference
|
|
194
226
|
|
|
195
227
|
### `generate(options)`
|
|
196
228
|
|
|
197
229
|
Generates an HTTP request example for an OpenAPI operation.
|
|
198
230
|
|
|
199
|
-
```
|
|
231
|
+
```typescript
|
|
200
232
|
const code = generate({
|
|
201
233
|
document,
|
|
202
234
|
path,
|
|
@@ -204,19 +236,26 @@ const code = generate({
|
|
|
204
236
|
language,
|
|
205
237
|
client,
|
|
206
238
|
securityValues,
|
|
239
|
+
serverUrl,
|
|
240
|
+
softRefMode,
|
|
207
241
|
});
|
|
208
242
|
```
|
|
209
243
|
|
|
210
244
|
#### Options
|
|
211
245
|
|
|
212
|
-
| Option | Type
|
|
213
|
-
| ---------------- |
|
|
214
|
-
| `document` | `unknown`
|
|
215
|
-
| `path` | `string`
|
|
216
|
-
| `method` | `string`
|
|
217
|
-
| `language` | `string`
|
|
218
|
-
| `client` | `string`
|
|
219
|
-
| `securityValues` | `Record<string, string>`
|
|
246
|
+
| Option | Type | Required | Description |
|
|
247
|
+
| ---------------- | ----------------------------- | -------: | -------------------------------------------- |
|
|
248
|
+
| `document` | `unknown` (OpenAPI object) | Yes* | Parsed OpenAPI document |
|
|
249
|
+
| `path` | `string` | Yes* | Exact OpenAPI path template |
|
|
250
|
+
| `method` | `string` | Yes* | HTTP operation method |
|
|
251
|
+
| `language` | `string` | Yes | Target language identifier |
|
|
252
|
+
| `client` | `string` | Yes | Target HTTP client identifier |
|
|
253
|
+
| `securityValues` | `Record<string, string>` | No | Credentials for named security schemes |
|
|
254
|
+
| `serverUrl` | `string` | No | Override server URL from document |
|
|
255
|
+
| `softRefMode` | `boolean` | No | Soft mode for $ref resolution (no throws) |
|
|
256
|
+
| `request` | `RequestIR` | Yes* | Pre-normalized request (alternative to doc) |
|
|
257
|
+
|
|
258
|
+
\* Either `document` + `path` + `method` OR `request` must be provided.
|
|
220
259
|
|
|
221
260
|
#### Return Value
|
|
222
261
|
|
|
@@ -231,10 +270,11 @@ Generation can throw when:
|
|
|
231
270
|
- The OpenAPI document is invalid or unsupported
|
|
232
271
|
- Required generation data cannot be resolved
|
|
233
272
|
- The selected client cannot safely represent the request
|
|
273
|
+
- A circular $ref is detected (unless `softRefMode` is enabled)
|
|
234
274
|
|
|
235
275
|
Handle errors when processing untrusted documents or user-selected generators:
|
|
236
276
|
|
|
237
|
-
```
|
|
277
|
+
```typescript
|
|
238
278
|
try {
|
|
239
279
|
const code = generate({
|
|
240
280
|
document,
|
|
@@ -257,25 +297,51 @@ try {
|
|
|
257
297
|
|
|
258
298
|
Returns the available generator descriptors:
|
|
259
299
|
|
|
260
|
-
```
|
|
300
|
+
```typescript
|
|
261
301
|
const generators = list();
|
|
262
302
|
```
|
|
263
303
|
|
|
264
|
-
Each descriptor contains
|
|
304
|
+
Each descriptor contains:
|
|
265
305
|
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
|
|
306
|
+
```typescript
|
|
307
|
+
interface GeneratorDescriptor {
|
|
308
|
+
language: string;
|
|
309
|
+
client: string;
|
|
269
310
|
}
|
|
270
311
|
```
|
|
271
312
|
|
|
313
|
+
### `get(language, client)`
|
|
314
|
+
|
|
315
|
+
Returns a specific generator by language and client, or `undefined` if not found:
|
|
316
|
+
|
|
317
|
+
```typescript
|
|
318
|
+
const generator = get("javascript", "fetch");
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### `register(generator)`
|
|
322
|
+
|
|
323
|
+
Register a custom generator:
|
|
324
|
+
|
|
325
|
+
```typescript
|
|
326
|
+
import { register } from "@powerduck/openapi-codegen";
|
|
327
|
+
|
|
328
|
+
register({
|
|
329
|
+
language: "custom",
|
|
330
|
+
client: "my-client",
|
|
331
|
+
generate: (request) => {
|
|
332
|
+
// Custom generation logic
|
|
333
|
+
return "// Custom generated code";
|
|
334
|
+
},
|
|
335
|
+
});
|
|
336
|
+
```
|
|
337
|
+
|
|
272
338
|
## OpenAPI Document Input
|
|
273
339
|
|
|
274
340
|
Pass a parsed JavaScript object rather than a JSON or YAML source string.
|
|
275
341
|
|
|
276
342
|
### JSON
|
|
277
343
|
|
|
278
|
-
```
|
|
344
|
+
```typescript
|
|
279
345
|
import { readFile } from "node:fs/promises";
|
|
280
346
|
import { generate } from "@powerduck/openapi-codegen";
|
|
281
347
|
|
|
@@ -303,7 +369,7 @@ npm install yaml
|
|
|
303
369
|
|
|
304
370
|
Parse the document before passing it to `generate()`:
|
|
305
371
|
|
|
306
|
-
```
|
|
372
|
+
```typescript
|
|
307
373
|
import { readFile } from "node:fs/promises";
|
|
308
374
|
import YAML from "yaml";
|
|
309
375
|
import { generate } from "@powerduck/openapi-codegen";
|
|
@@ -322,6 +388,46 @@ const code = generate({
|
|
|
322
388
|
console.log(code);
|
|
323
389
|
```
|
|
324
390
|
|
|
391
|
+
## Browser Usage
|
|
392
|
+
|
|
393
|
+
The library is fully browser-compatible with zero Node.js dependencies:
|
|
394
|
+
|
|
395
|
+
```html
|
|
396
|
+
<!DOCTYPE html>
|
|
397
|
+
<html>
|
|
398
|
+
<head>
|
|
399
|
+
<title>API Code Generator</title>
|
|
400
|
+
</head>
|
|
401
|
+
<body>
|
|
402
|
+
<script type="module">
|
|
403
|
+
import { generate, list } from "https://esm.sh/@powerduck/openapi-codegen";
|
|
404
|
+
|
|
405
|
+
const document = {
|
|
406
|
+
openapi: "3.1.0",
|
|
407
|
+
info: { title: "Demo API", version: "1.0.0" },
|
|
408
|
+
paths: {
|
|
409
|
+
"/hello": {
|
|
410
|
+
get: {
|
|
411
|
+
responses: { "200": { description: "OK" } },
|
|
412
|
+
},
|
|
413
|
+
},
|
|
414
|
+
},
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
const code = generate({
|
|
418
|
+
document,
|
|
419
|
+
path: "/hello",
|
|
420
|
+
method: "get",
|
|
421
|
+
language: "javascript",
|
|
422
|
+
client: "fetch",
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
console.log(code);
|
|
426
|
+
</script>
|
|
427
|
+
</body>
|
|
428
|
+
</html>
|
|
429
|
+
```
|
|
430
|
+
|
|
325
431
|
## Generated Code
|
|
326
432
|
|
|
327
433
|
Generated examples are intended to be readable, runnable starting points. Depending on the selected language and client, they may include:
|
|
@@ -345,13 +451,23 @@ Review generated code before using it in production. You may need to:
|
|
|
345
451
|
- Adjust timeout and redirect policies
|
|
346
452
|
- Add application-specific response parsing
|
|
347
453
|
|
|
454
|
+
## Performance
|
|
455
|
+
|
|
456
|
+
The library is optimized for high performance:
|
|
457
|
+
|
|
458
|
+
- **No deep cloning via `JSON.parse(JSON.stringify())`** — uses structured reference handling
|
|
459
|
+
- **Efficient $ref resolution** with caching and circular detection
|
|
460
|
+
- **Lazy example generation** — only generates examples when needed
|
|
461
|
+
- **Zero runtime dependencies** — minimal bundle size (~130KB minified)
|
|
462
|
+
- **Tree-shakeable** — ESM build supports tree-shaking
|
|
463
|
+
|
|
348
464
|
## Development
|
|
349
465
|
|
|
350
466
|
Clone the repository and install dependencies:
|
|
351
467
|
|
|
352
468
|
```bash
|
|
353
|
-
git clone https://github.com/PowerDuckie
|
|
354
|
-
cd
|
|
469
|
+
git clone https://github.com/PowerDuckie/openapi-codegen.git
|
|
470
|
+
cd openapi-codegen
|
|
355
471
|
npm install
|
|
356
472
|
```
|
|
357
473
|
|
|
@@ -361,10 +477,10 @@ Run the test suite:
|
|
|
361
477
|
npm test
|
|
362
478
|
```
|
|
363
479
|
|
|
364
|
-
Run
|
|
480
|
+
Run tests with coverage:
|
|
365
481
|
|
|
366
482
|
```bash
|
|
367
|
-
npm run
|
|
483
|
+
npm run test:coverage
|
|
368
484
|
```
|
|
369
485
|
|
|
370
486
|
Build the package:
|
|
@@ -373,6 +489,12 @@ Build the package:
|
|
|
373
489
|
npm run build
|
|
374
490
|
```
|
|
375
491
|
|
|
492
|
+
Run type checking:
|
|
493
|
+
|
|
494
|
+
```bash
|
|
495
|
+
npm run typecheck
|
|
496
|
+
```
|
|
497
|
+
|
|
376
498
|
Run all release checks:
|
|
377
499
|
|
|
378
500
|
```bash
|
|
@@ -389,8 +511,9 @@ npm run demo
|
|
|
389
511
|
|
|
390
512
|
The project uses:
|
|
391
513
|
|
|
392
|
-
- [Vitest](https://vitest.dev/) for unit and
|
|
393
|
-
-
|
|
514
|
+
- [Vitest](https://vitest.dev/) for unit and integration tests
|
|
515
|
+
- 270+ tests covering all core modules
|
|
516
|
+
- Full branch coverage for core logic
|
|
394
517
|
|
|
395
518
|
Run all tests:
|
|
396
519
|
|
|
@@ -398,22 +521,29 @@ Run all tests:
|
|
|
398
521
|
npm test
|
|
399
522
|
```
|
|
400
523
|
|
|
401
|
-
|
|
524
|
+
## Project Structure
|
|
402
525
|
|
|
403
|
-
```bash
|
|
404
|
-
npx vitest run -u
|
|
405
526
|
```
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
527
|
+
src/
|
|
528
|
+
├── index.ts # Main entry point
|
|
529
|
+
├── types.ts # TypeScript type definitions
|
|
530
|
+
├── core/
|
|
531
|
+
│ ├── generator.ts # Generator factory
|
|
532
|
+
│ ├── helpers.ts # Utility functions (escaping, indentation, etc.)
|
|
533
|
+
│ ├── normalize.ts # OpenAPI document → RequestIR normalization
|
|
534
|
+
│ ├── refs.ts # JSON Pointer $ref resolver
|
|
535
|
+
│ ├── registry.ts # Generator registry (Map-based)
|
|
536
|
+
│ ├── request.ts # RequestIR → compiled request
|
|
537
|
+
│ ├── serialize.ts # Parameter serialization (path/query/header/cookie)
|
|
538
|
+
│ ├── example.ts # JSON Schema → example value generation
|
|
539
|
+
│ └── plugin.ts # Plugin system
|
|
540
|
+
└── emitters/
|
|
541
|
+
├── index.ts # Unified emitter registry (41 generators)
|
|
542
|
+
├── c/ # C (libcurl)
|
|
543
|
+
├── csharp/ # C# (httpclient, restsharp)
|
|
544
|
+
├── javascript/ # JavaScript (fetch, axios, ofetch, jquery, xhr)
|
|
545
|
+
├── python/ # Python (requests, aiohttp, httpx, http-client)
|
|
546
|
+
└── ... # 17 more languages
|
|
417
547
|
```
|
|
418
548
|
|
|
419
549
|
## Security
|
|
@@ -449,13 +579,6 @@ git commit -m "feat: describe the change"
|
|
|
449
579
|
git push -u origin feature/my-change
|
|
450
580
|
```
|
|
451
581
|
|
|
452
|
-
When changing generated output, update and review the affected snapshots:
|
|
453
|
-
|
|
454
|
-
```bash
|
|
455
|
-
npx vitest run -u
|
|
456
|
-
git diff
|
|
457
|
-
```
|
|
458
|
-
|
|
459
582
|
## License
|
|
460
583
|
|
|
461
584
|
[MIT](LICENSE)
|