@powerduck/openapi-codegen 0.4.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.
Files changed (3) hide show
  1. package/README.md +583 -0
  2. package/dist/index.js +6711 -0
  3. package/package.json +65 -0
package/README.md ADDED
@@ -0,0 +1,583 @@
1
+ # @powerduck/openapi-codegen
2
+
3
+ Generate runnable HTTP request examples from parsed OpenAPI documents for **21 language targets** and **41 language/client combinations**.
4
+
5
+ `@powerduck/openapi-codegen` is an ESM-first TypeScript library for API documentation systems, developer portals, API explorers, command-line tools, and build-time code generation.
6
+
7
+ ## Features
8
+
9
+ - Supports parsed OpenAPI documents, including OpenAPI 3.2
10
+ - Generates readable HTTP request examples across 41 generators
11
+ - Resolves path, query, header, and cookie parameters
12
+ - Supports API key, HTTP bearer, and other security schemes
13
+ - Supports JSON, plain-text, URL-encoded form, and multipart bodies
14
+ - Generates multipart file-upload examples with placeholder paths
15
+ - Preserves request bodies that have already been serialized
16
+ - Adds timeouts, HTTP status checks, and resource cleanup where supported
17
+ - Exposes generator discovery through `list()`
18
+ - Includes TypeScript declarations
19
+ - Ships as an ECMAScript module
20
+
21
+ ## Supported Languages and Clients
22
+
23
+ Use the exact `language` and `client` identifiers shown below when calling `generate()`. Identifiers are case-sensitive.
24
+
25
+ | Language | `language` | Supported `client` values |
26
+ | ----------------- | ------------ | ----------------------------------------------------------------- |
27
+ | C | `c` | `libcurl` |
28
+ | C# | `csharp` | `httpclient`, `restsharp` |
29
+ | Clojure | `clojure` | `clj-http` |
30
+ | Dart | `dart` | `http` |
31
+ | F# | `fsharp` | `httpclient` |
32
+ | Go | `go` | `new-request` |
33
+ | HTTP request file | `http` | `http1` |
34
+ | Java | `java` | `asynchttp`, `java-net-http`, `okhttp`, `unirest` |
35
+ | JavaScript | `javascript` | `fetch`, `axios`, `ofetch`, `jquery`, `xhr` |
36
+ | Kotlin | `kotlin` | `okhttp` |
37
+ | Node.js | `node` | `fetch`, `axios`, `ofetch`, `undici` |
38
+ | Objective-C | `objc` | `nsurlsession` |
39
+ | OCaml | `ocaml` | `cohttp` |
40
+ | PHP | `php` | `curl`, `guzzle`, `laravel-http` |
41
+ | PowerShell | `powershell` | `invoke-webrequest`, `invoke-restmethod` |
42
+ | Python | `python` | `http-client`, `requests`, `aiohttp`, `httpx-sync`, `httpx-async` |
43
+ | R | `r` | `httr2` |
44
+ | Ruby | `ruby` | `net-http` |
45
+ | Rust | `rust` | `reqwest` |
46
+ | Shell | `shell` | `curl`, `wget`, `httpie` |
47
+ | Swift | `swift` | `nsurlsession` |
48
+
49
+ > Generator availability does not imply that every client can represent every OpenAPI operation. For example, GNU Wget cannot safely construct arbitrary `multipart/form-data` requests. Use `shell/curl` or `shell/httpie` for multipart uploads.
50
+
51
+ ## Requirements
52
+
53
+ - Node.js 20 or later
54
+ - A parsed OpenAPI document
55
+ - The runtime and dependencies required by the selected generated client
56
+
57
+ ## Installation
58
+
59
+ Using npm:
60
+
61
+ ```bash
62
+ npm install @powerduck/openapi-codegen
63
+ ```
64
+
65
+ Using pnpm:
66
+
67
+ ```bash
68
+ pnpm add @powerduck/openapi-codegen
69
+ ```
70
+
71
+ Using Yarn:
72
+
73
+ ```bash
74
+ yarn add @powerduck/openapi-codegen
75
+ ```
76
+
77
+ ## Quick Start
78
+
79
+ ```ts
80
+ import { generate } from "@powerduck/openapi-codegen";
81
+ import document from "./openapi.json" with { type: "json" };
82
+
83
+ const code = generate({
84
+ document,
85
+ path: "/users/{id}",
86
+ method: "get",
87
+ language: "javascript",
88
+ client: "fetch",
89
+ });
90
+
91
+ console.log(code);
92
+ ```
93
+
94
+ `generate()` returns the generated source code as a string.
95
+
96
+ ## Authentication
97
+
98
+ Provide credentials through `securityValues`:
99
+
100
+ ```ts
101
+ import { generate } from "@powerduck/openapi-codegen";
102
+ import document from "./openapi.json" with { type: "json" };
103
+
104
+ const code = generate({
105
+ document,
106
+ path: "/users/{id}",
107
+ method: "get",
108
+ language: "javascript",
109
+ client: "fetch",
110
+ securityValues: {
111
+ bearer: "YOUR_ACCESS_TOKEN",
112
+ apiKey: "YOUR_API_KEY",
113
+ },
114
+ });
115
+
116
+ console.log(code);
117
+ ```
118
+
119
+ The keys in `securityValues` must match the security scheme names defined in the OpenAPI document.
120
+
121
+ Do not commit real credentials to source control.
122
+
123
+ ## Multipart Uploads
124
+
125
+ ```ts
126
+ import { generate } from "@powerduck/openapi-codegen";
127
+ import document from "./openapi.json" with { type: "json" };
128
+
129
+ const code = generate({
130
+ document,
131
+ path: "/upload/{id}",
132
+ method: "post",
133
+ language: "shell",
134
+ client: "curl",
135
+ securityValues: {
136
+ bearer: "YOUR_ACCESS_TOKEN",
137
+ },
138
+ });
139
+
140
+ console.log(code);
141
+ ```
142
+
143
+ Generated multipart examples may include placeholder file paths:
144
+
145
+ ```text
146
+ /tmp/file.bin
147
+ ```
148
+
149
+ Replace all placeholder paths before running the generated code.
150
+
151
+ Some clients cannot safely represent every OpenAPI request. Generation may throw a descriptive error when the selected client is incompatible with an operation.
152
+
153
+ For example, `shell/wget` does not support arbitrary multipart generation. Use `shell/curl` or `shell/httpie` instead.
154
+
155
+ ## Discover Available Generators
156
+
157
+ Use `list()` to inspect every installed language/client combination:
158
+
159
+ ```ts
160
+ import { list } from "@powerduck/openapi-codegen";
161
+
162
+ for (const { language, client } of list()) {
163
+ console.log(`${language}/${client}`);
164
+ }
165
+ ```
166
+
167
+ You can also select a generator programmatically:
168
+
169
+ ```ts
170
+ import { generate, list } from "@powerduck/openapi-codegen";
171
+ import document from "./openapi.json" with { type: "json" };
172
+
173
+ const generator = list().find(
174
+ ({ language, client }) => language === "javascript" && client === "fetch",
175
+ );
176
+
177
+ if (!generator) {
178
+ throw new Error("The requested generator is not available");
179
+ }
180
+
181
+ const code = generate({
182
+ document,
183
+ path: "/users",
184
+ method: "get",
185
+ language: generator.language,
186
+ client: generator.client,
187
+ });
188
+
189
+ console.log(code);
190
+ ```
191
+
192
+ ## API Reference
193
+
194
+ ### `generate(options)`
195
+
196
+ Generates an HTTP request example for an OpenAPI operation.
197
+
198
+ ```ts
199
+ const code = generate({
200
+ document,
201
+ path,
202
+ method,
203
+ language,
204
+ client,
205
+ securityValues,
206
+ });
207
+ ```
208
+
209
+ #### Options
210
+
211
+ | Option | Type | Required | Description |
212
+ | ---------------- | ------------------------ | -------: | -------------------------------------- |
213
+ | `document` | `unknown` | Yes | Parsed OpenAPI document |
214
+ | `path` | `string` | Yes | Exact OpenAPI path template |
215
+ | `method` | `string` | Yes | HTTP operation method |
216
+ | `language` | `string` | Yes | Target language identifier |
217
+ | `client` | `string` | Yes | Target HTTP client identifier |
218
+ | `securityValues` | `Record<string, string>` | No | Credentials for named security schemes |
219
+
220
+ #### Return Value
221
+
222
+ Returns the generated source code as a `string`.
223
+
224
+ #### Errors
225
+
226
+ Generation can throw when:
227
+
228
+ - The requested path or operation does not exist
229
+ - The language/client combination is unknown
230
+ - The OpenAPI document is invalid or unsupported
231
+ - Required generation data cannot be resolved
232
+ - The selected client cannot safely represent the request
233
+
234
+ Handle errors when processing untrusted documents or user-selected generators:
235
+
236
+ ```ts
237
+ try {
238
+ const code = generate({
239
+ document,
240
+ path: "/users/{id}",
241
+ method: "get",
242
+ language: "javascript",
243
+ client: "fetch",
244
+ });
245
+
246
+ console.log(code);
247
+ } catch (error) {
248
+ const message = error instanceof Error ? error.message : String(error);
249
+
250
+ console.error(`Generation failed: ${message}`);
251
+ process.exitCode = 1;
252
+ }
253
+ ```
254
+
255
+ ### `list()`
256
+
257
+ Returns the available generator descriptors:
258
+
259
+ ```ts
260
+ const generators = list();
261
+ ```
262
+
263
+ Each descriptor contains the identifiers required by `generate()`:
264
+
265
+ ```ts
266
+ for (const { language, client } of generators) {
267
+ console.log(language, client);
268
+ }
269
+ ```
270
+
271
+ ## OpenAPI Document Input
272
+
273
+ Pass a parsed JavaScript object rather than a JSON or YAML source string.
274
+
275
+ ### JSON
276
+
277
+ ```ts
278
+ import { readFile } from "node:fs/promises";
279
+ import { generate } from "@powerduck/openapi-codegen";
280
+
281
+ const source = await readFile("./openapi.json", "utf8");
282
+ const document = JSON.parse(source);
283
+
284
+ const code = generate({
285
+ document,
286
+ path: "/pets/{petId}",
287
+ method: "get",
288
+ language: "javascript",
289
+ client: "fetch",
290
+ });
291
+
292
+ console.log(code);
293
+ ```
294
+
295
+ ### YAML
296
+
297
+ Install a YAML parser separately:
298
+
299
+ ```bash
300
+ npm install yaml
301
+ ```
302
+
303
+ Parse the document before passing it to `generate()`:
304
+
305
+ ```ts
306
+ import { readFile } from "node:fs/promises";
307
+ import YAML from "yaml";
308
+ import { generate } from "@powerduck/openapi-codegen";
309
+
310
+ const source = await readFile("./openapi.yaml", "utf8");
311
+ const document = YAML.parse(source);
312
+
313
+ const code = generate({
314
+ document,
315
+ path: "/pets/{petId}",
316
+ method: "get",
317
+ language: "javascript",
318
+ client: "fetch",
319
+ });
320
+
321
+ console.log(code);
322
+ ```
323
+
324
+ ## Generated Code
325
+
326
+ Generated examples are intended to be readable, runnable starting points. Depending on the selected language and client, they may include:
327
+
328
+ - A 30-second connection or request timeout
329
+ - HTTP status validation
330
+ - Response body output
331
+ - Resource cleanup
332
+ - Runtime and dependency notes
333
+ - Placeholder multipart file paths
334
+ - Environment-specific proxy or TLS behavior
335
+
336
+ Review generated code before using it in production. You may need to:
337
+
338
+ - Install dependencies for the selected client
339
+ - Replace placeholder parameter values
340
+ - Replace multipart file paths
341
+ - Supply authentication credentials securely
342
+ - Configure certificate trust
343
+ - Configure proxies
344
+ - Adjust timeout and redirect policies
345
+ - Add application-specific response parsing
346
+
347
+ ## Development
348
+
349
+ Clone the repository and install dependencies:
350
+
351
+ ```bash
352
+ git clone https://github.com/PowerDuckie/-powerduck-openapi-codegen.git
353
+ cd ./-powerduck-openapi-codegen
354
+ npm install
355
+ ```
356
+
357
+ Run the test suite:
358
+
359
+ ```bash
360
+ npm test
361
+ ```
362
+
363
+ Run property-based fuzz tests:
364
+
365
+ ```bash
366
+ npm run fuzz
367
+ ```
368
+
369
+ Build the package:
370
+
371
+ ```bash
372
+ npm run build
373
+ ```
374
+
375
+ Run all release checks:
376
+
377
+ ```bash
378
+ npm run check
379
+ ```
380
+
381
+ Run the demo:
382
+
383
+ ```bash
384
+ npm run demo
385
+ ```
386
+
387
+ ## Testing
388
+
389
+ The project uses:
390
+
391
+ - [Vitest](https://vitest.dev/) for unit and snapshot tests
392
+ - [fast-check](https://fast-check.dev/) for property-based fuzz testing
393
+
394
+ Run all tests:
395
+
396
+ ```bash
397
+ npm test
398
+ ```
399
+
400
+ Update snapshots after intentionally changing generated output:
401
+
402
+ ```bash
403
+ npx vitest run -u
404
+ ```
405
+
406
+ Run only the fuzz test suite:
407
+
408
+ ```bash
409
+ npm run fuzz
410
+ ```
411
+
412
+ Before committing snapshot changes, inspect the diff:
413
+
414
+ ```bash
415
+ git diff
416
+ ```
417
+
418
+ ## Releasing
419
+
420
+ Before releasing, verify that:
421
+
422
+ - The working tree is clean
423
+ - You are on the intended branch
424
+ - The full validation suite passes
425
+ - You are authenticated with npm
426
+ - The package is owned by your npm account or organization
427
+ - The Git remote points to the intended repository
428
+
429
+ Check the repository state:
430
+
431
+ ```bash
432
+ git status
433
+ git remote -v
434
+ ```
435
+
436
+ Sign in to npm:
437
+
438
+ ```bash
439
+ npm login
440
+ ```
441
+
442
+ Inspect the package contents without publishing:
443
+
444
+ ```bash
445
+ npm pack --dry-run
446
+ ```
447
+
448
+ ### Patch Release
449
+
450
+ Use a patch release for backward-compatible bug fixes:
451
+
452
+ ```bash
453
+ npm run release:patch
454
+ ```
455
+
456
+ Example:
457
+
458
+ ```text
459
+ 0.4.0 → 0.4.1
460
+ ```
461
+
462
+ ### Minor Release
463
+
464
+ Use a minor release for backward-compatible features:
465
+
466
+ ```bash
467
+ npm run release:minor
468
+ ```
469
+
470
+ Example:
471
+
472
+ ```text
473
+ 0.4.0 → 0.5.0
474
+ ```
475
+
476
+ ### Major Release
477
+
478
+ Use a major release for breaking changes:
479
+
480
+ ```bash
481
+ npm run release:major
482
+ ```
483
+
484
+ Example:
485
+
486
+ ```text
487
+ 0.4.0 → 1.0.0
488
+ ```
489
+
490
+ The release scripts run the configured checks, update the package version, create a Git commit and tag, and push the commit and tags.
491
+
492
+ Publish the public scoped package:
493
+
494
+ ```bash
495
+ npm publish --access public
496
+ ```
497
+
498
+ ## Initial GitHub Setup
499
+
500
+ Initialize the repository and push it to GitHub:
501
+
502
+ ```bash
503
+ git init
504
+ git branch -M main
505
+ git remote add origin https://github.com/PowerDuckie/-powerduck-openapi-codegen.git
506
+ git add .
507
+ git commit -m "feat: initialize OpenAPI code generator"
508
+ git push -u origin main
509
+ ```
510
+
511
+ If `origin` already exists, update it:
512
+
513
+ ```bash
514
+ git remote set-url origin https://github.com/PowerDuckie/-powerduck-openapi-codegen.git
515
+ git push -u origin main
516
+ ```
517
+
518
+ ## Project Structure
519
+
520
+ A typical project layout is:
521
+
522
+ ```text
523
+ .
524
+ ├── demo/
525
+ ├── src/
526
+ │ ├── core/
527
+ │ ├── emitters/
528
+ │ ├── generators/
529
+ │ ├── common.ts
530
+ │ ├── index.ts
531
+ │ └── types.ts
532
+ ├── tests/
533
+ │ ├── fixtures/
534
+ │ ├── fuzz.test.ts
535
+ │ └── snapshot.test.ts
536
+ ├── package.json
537
+ ├── README.md
538
+ └── tsconfig.json
539
+ ```
540
+
541
+ ## Security
542
+
543
+ Generated source code can contain request URLs, headers, parameter values, and credentials supplied to the generator.
544
+
545
+ Avoid:
546
+
547
+ - Committing generated examples that contain real credentials
548
+ - Logging secrets in CI output
549
+ - Running unreviewed generated commands in production
550
+ - Passing untrusted file paths directly to generated upload code
551
+
552
+ Report security issues privately to the repository owner instead of opening a public issue.
553
+
554
+ ## Contributing
555
+
556
+ Contributions are welcome.
557
+
558
+ 1. Fork the repository.
559
+ 2. Create a feature branch.
560
+ 3. Add or update tests.
561
+ 4. Run the full validation suite.
562
+ 5. Commit the changes.
563
+ 6. Open a pull request.
564
+
565
+ ```bash
566
+ git checkout -b feature/my-change
567
+ npm install
568
+ npm run check
569
+ git add .
570
+ git commit -m "feat: describe the change"
571
+ git push -u origin feature/my-change
572
+ ```
573
+
574
+ When changing generated output, update and review the affected snapshots:
575
+
576
+ ```bash
577
+ npx vitest run -u
578
+ git diff
579
+ ```
580
+
581
+ ## License
582
+
583
+ [MIT](LICENSE)