@powerduck/openapi-codegen 0.5.2 → 0.5.3

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 (2) hide show
  1. package/README.md +98 -293
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,17 +1,23 @@
1
1
  # @powerduck/openapi-codegen
2
2
 
3
- Generate runnable HTTP request examples from OpenAPI documents. Supports 21 languages and 41 language/client combinations. Browser-compatible, zero runtime dependencies.
4
-
5
3
  [![npm version](https://img.shields.io/npm/v/@powerduck/openapi-codegen)](https://www.npmjs.com/package/@powerduck/openapi-codegen)
6
4
  [![license](https://img.shields.io/npm/l/@powerduck/openapi-codegen)](https://github.com/PowerDuckie/openapi-codegen/blob/main/LICENSE)
5
+ [![downloads](https://img.shields.io/npm/dm/@powerduck/openapi-codegen)](https://www.npmjs.com/package/@powerduck/openapi-codegen)
7
6
 
8
- ## Links
7
+ Generate runnable HTTP request examples from OpenAPI documents. Supports 21 languages and 41 language/client combinations. Browser-compatible, zero runtime dependencies.
9
8
 
10
- - [Official Website](https://www.powerduck.com/opensource/openapi-codegen.html)
11
- - [Documentation](https://www.powerduck.com/docs/openapi-codegen/introduction)
12
- - [Live Demo](https://www.powerduck.com/demo/openapi-codegen.html)
13
- - [GitHub](https://github.com/PowerDuckie/openapi-codegen)
14
- - [npm](https://www.npmjs.com/package/@powerduck/openapi-codegen)
9
+ ---
10
+
11
+ Powerduck is an open-source developer tooling platform for teams building modern API workflows.
12
+
13
+ - **21 Languages** — JavaScript, TypeScript, Python, Go, Rust, Java, PHP, Ruby, C#, Kotlin, Swift, Dart, and more
14
+ - **41 Client Combinations** — fetch, axios, requests, httpx, http.client, Faraday, Guzzle, RestSharp, and more
15
+ - **OpenAPI 3.0/3.1/3.2** — Full support for modern OpenAPI specifications
16
+ - **Security Schemes** — Bearer tokens, API keys, Basic auth, OAuth2, and custom headers
17
+ - **Parameter Handling** — Path, query, header, and cookie parameters with proper encoding
18
+ - **Request Bodies** — JSON, form-data, x-www-form-urlencoded, and raw payloads
19
+ - **Browser Compatible** — Pure TypeScript, no Node.js dependencies, works in any modern browser
20
+ - **Dual ESM/CJS** — Works with `import` and `require`, with bundled TypeScript declarations
15
21
 
16
22
  ---
17
23
 
@@ -39,25 +45,6 @@ const code = generate({
39
45
  console.log(code);
40
46
  ```
41
47
 
42
- ### CommonJS equivalent
43
-
44
- ```javascript
45
- const { generate } = require("@powerduck/openapi-codegen");
46
- const fs = require("node:fs");
47
-
48
- const document = JSON.parse(fs.readFileSync("./openapi.json", "utf8"));
49
-
50
- const code = generate({
51
- document,
52
- path: "/pets",
53
- method: "post",
54
- language: "python",
55
- client: "requests",
56
- });
57
-
58
- console.log(code);
59
- ```
60
-
61
48
  ### List available generators
62
49
 
63
50
  ```typescript
@@ -78,326 +65,144 @@ const code = generate({
78
65
  language: "javascript",
79
66
  client: "fetch",
80
67
  securityValues: {
81
- bearerAuth: "YOUR_ACCESS_TOKEN",
82
- apiKey: "YOUR_API_KEY",
68
+ bearerAuth: "your-token-here",
69
+ apiKey: "your-api-key",
83
70
  },
84
71
  });
85
72
  ```
86
73
 
87
- ### Override the server URL
88
-
89
- ```typescript
90
- const code = generate({
91
- document,
92
- path: "/pets",
93
- method: "get",
94
- language: "shell",
95
- client: "curl",
96
- serverUrl: "https://staging.example.com/v1",
97
- });
98
- ```
99
-
100
74
  ---
101
75
 
102
- ## Features
103
-
104
- - **21 languages, 41 clients** — JavaScript, Python, Go, Java, Ruby, PHP, C#, Rust, Swift, Kotlin, Dart, and more
105
- - **Full OpenAPI parameter serialization** — path, query, header, cookie parameters with style/explode rules (form, spaceDelimited, pipeDelimited, label, matrix, simple, deepObject)
106
- - **All body types** — JSON, form-urlencoded, multipart/form-data (text + file fields), XML, text, binary
107
- - **Security resolution** — Bearer, Basic, API key (header/query/cookie), with `securityValues` for credentials
108
- - **`$ref` resolution** — in-document JSON Pointer resolution with soft mode for broken/circular refs
109
- - **Example generation** — generates realistic example values from JSON Schema (respects `example`, `enum`, `const`, `default`, `oneOf`/`anyOf`/`allOf`, types, formats, constraints)
110
- - **Plugin system** — register custom generators through a simple plugin API
111
- - **Direct RequestIR** — skip normalization entirely by building a `RequestIR` yourself
112
- - **Browser-compatible** — zero Node.js dependencies, works in browsers, Edge Functions, and Node.js
113
- - **Dual ESM/CJS builds** — works with `import` and `require`, with bundled TypeScript declarations
114
-
115
- ---
116
-
117
- ## GenerateOptions
118
-
119
- ```typescript
120
- interface GenerateOptions {
121
- language: string; // Target language identifier (case-sensitive)
122
- client: string; // Target HTTP client identifier
123
- request?: RequestIR; // Pre-normalized request; skips normalize
124
- document?: unknown; // A parsed OpenAPI document object
125
- path?: string; // Exact OpenAPI path template, e.g. "/pets/{id}"
126
- method?: string; // HTTP method, e.g. "get" / "post"
127
- serverUrl?: string; // Override the server URL from the document
128
- securityValues?: Record<string, string>; // Credentials keyed by security scheme name
129
- softRefMode?: boolean; // Do not throw on broken/circular $refs
130
- }
131
- ```
132
-
133
- > Either `request` alone, or `document` + `path` + `method`, must be provided. When `request` is supplied, `document`, `path`, `method`, `serverUrl`, `securityValues`, and `softRefMode` are ignored.
134
-
135
- ### Input validation errors
136
-
137
- `generate()` throws when required input is missing:
76
+ ## Links
138
77
 
139
- - `TypeError: generate() requires an options object`
140
- - `Error: Unsupported generator: <language>/<client>`
141
- - `TypeError: generate() requires either a 'request' or a 'document' option`
142
- - `TypeError: generate() requires a 'path' option when using 'document'`
143
- - `TypeError: generate() requires a 'method' option when using 'document'`
78
+ - [Official Website](https://www.powerduck.com/opensource/openapi-codegen.html)
79
+ - [Documentation](https://www.powerduck.com/docs/openapi-codegen/introduction)
80
+ - [Live Demo](https://www.powerduck.com/demo/openapi-codegen)
81
+ - [GitHub](https://github.com/PowerDuckie/openapi-codegen)
82
+ - [npm](https://www.npmjs.com/package/@powerduck/openapi-codegen)
144
83
 
145
84
  ---
146
85
 
147
- ## Top-level API
148
-
149
- | Export | Signature | Description |
150
- |---|---|---|
151
- | `generate` | `(options: GenerateOptions) => string` | Generate runnable source code for one operation |
152
- | `register` | `(generator: Generator) => void` | Register a custom generator |
153
- | `get` | `(language: string, client: string) => Generator \| undefined` | Look up a generator |
154
- | `list` | `() => Array<{ language: string; client: string }>` | List all registered generators |
155
- | `use` | `(plugin: Plugin) => void` | Apply a plugin that registers generators |
156
- | `registerBuiltins` | `() => void` | Register all built-in generators (auto-called on import) |
157
- | `normalize` | `(options) => NormalizedRequest` | Turn a document + path + method into a normalized request |
158
- | `builtinGenerators` | `Generator[]` | The raw array of all built-in generator definitions |
159
-
160
- Built-ins are registered automatically when the module loads, so calling `registerBuiltins()` manually is optional.
86
+ ## Supported Languages & Clients
87
+
88
+ | Language | Clients |
89
+ | ---------- | -------------------------------------------------- |
90
+ | JavaScript | fetch, axios, XMLHttpRequest, jQuery, Node.js http |
91
+ | TypeScript | fetch, axios |
92
+ | Python | requests, httpx, http.client, aiohttp |
93
+ | Go | net/http, resty, fasthttp |
94
+ | Rust | reqwest, hyper |
95
+ | Java | OkHttp, HttpClient, Unirest, Retrofit |
96
+ | PHP | cURL, Guzzle, HTTP_Request2 |
97
+ | Ruby | Net::HTTP, Faraday, RestClient |
98
+ | C# | HttpClient, RestSharp, WebRequest |
99
+ | Kotlin | OkHttp, Fuel |
100
+ | Swift | URLSession, Alamofire |
101
+ | Dart | http, Dio |
102
+ | Shell | cURL, wget, HTTPie |
103
+ | PowerShell | Invoke-RestMethod, Invoke-WebRequest |
104
+ | R | httr, RCurl |
105
+ | MATLAB | webread, urlwrite |
106
+ | Elixir | HTTPoison, Tesla |
107
+ | Haskell | http-conduit, wreq |
108
+ | Clojure | clj-http, http-kit |
109
+ | Scala | sttp, akka-http |
161
110
 
162
111
  ---
163
112
 
164
- ## Built-in Generators (21 languages, 41 clients)
165
-
166
- | Language | `language` | `client` values |
167
- |---|---|---|
168
- | C | `c` | `libcurl` |
169
- | C# | `csharp` | `httpclient`, `restsharp` |
170
- | Clojure | `clojure` | `clj-http` |
171
- | Dart | `dart` | `http` |
172
- | F# | `fsharp` | `httpclient` |
173
- | Go | `go` | `new-request` |
174
- | HTTP request file | `http` | `http1` |
175
- | Java | `java` | `asynchttp`, `java-net-http`, `okhttp`, `unirest` |
176
- | JavaScript | `javascript` | `axios`, `fetch`, `jquery`, `ofetch`, `xhr` |
177
- | Kotlin | `kotlin` | `okhttp` |
178
- | Node.js | `node` | `axios`, `fetch`, `ofetch`, `undici` |
179
- | Objective-C | `objc` | `nsurlsession` |
180
- | OCaml | `ocaml` | `cohttp` |
181
- | PHP | `php` | `curl`, `guzzle`, `laravel-http` |
182
- | PowerShell | `powershell` | `invoke-restmethod`, `invoke-webrequest` |
183
- | Python | `python` | `aiohttp`, `http-client`, `httpx-async`, `httpx-sync`, `requests` |
184
- | R | `r` | `httr2` |
185
- | Ruby | `ruby` | `net-http` |
186
- | Rust | `rust` | `reqwest` |
187
- | Shell | `shell` | `curl`, `httpie`, `wget` |
188
- | Swift | `swift` | `nsurlsession` |
189
-
190
- > Generator availability does not mean every client can represent every operation. For example, `shell/wget` cannot safely build arbitrary `multipart/form-data` requests; use `shell/curl` or `shell/httpie` instead.
191
-
192
- ---
113
+ ## API Reference
193
114
 
194
- ## Custom Generator
115
+ ### `generate(options)`
195
116
 
196
- Implement the `Generator` interface and call `register`:
117
+ Generate HTTP request code from an OpenAPI document.
197
118
 
198
119
  ```typescript
199
- import { register, generate } from "@powerduck/openapi-codegen";
200
- import type { RequestIR } from "@powerduck/openapi-codegen";
201
-
202
- register({
203
- language: "mylang",
204
- client: "my-client",
205
- generate(request: RequestIR): string {
206
- return [
207
- `// ${request.method} ${request.baseUrl}${request.path}`,
208
- `mylang.request(${JSON.stringify({
209
- method: request.method,
210
- url: request.baseUrl + request.path,
211
- })})`,
212
- ].join("\n");
213
- },
214
- });
120
+ import { generate } from "@powerduck/openapi-codegen";
215
121
 
216
122
  const code = generate({
217
- document,
123
+ document: openApiDocument,
218
124
  path: "/pets",
219
- method: "get",
220
- language: "mylang",
221
- client: "my-client",
125
+ method: "post",
126
+ language: "python",
127
+ client: "requests",
128
+ securityValues: { bearerAuth: "token" },
129
+ parameterValues: { limit: 10, offset: 0 },
222
130
  });
223
131
  ```
224
132
 
225
- ---
133
+ #### Options
134
+
135
+ | Option | Type | Required | Description |
136
+ | ----------------- | ------------------------- | -------- | ---------------------------------------------------------- |
137
+ | `document` | `OpenAPIDocument` | Yes | Parsed OpenAPI document object |
138
+ | `path` | `string` | Yes | API path (e.g., `/pets/{id}`) |
139
+ | `method` | `string` | Yes | HTTP method (get, post, put, delete, patch, head, options) |
140
+ | `language` | `string` | Yes | Target language |
141
+ | `client` | `string` | Yes | HTTP client library |
142
+ | `securityValues` | `Record<string, string>` | No | Security scheme values |
143
+ | `parameterValues` | `Record<string, unknown>` | No | Parameter values |
144
+ | `requestBody` | `unknown` | No | Request body value |
145
+ | `headers` | `Record<string, string>` | No | Additional headers |
146
+ | `timeout` | `number` | No | Request timeout in ms |
147
+ | `indent` | `string` | No | Indentation string (default: 2 spaces) |
148
+ | `quote` | `"single" \| "double"` | No | Quote style (default: language-specific) |
226
149
 
227
- ## Plugin
150
+ ### `list()`
228
151
 
229
- A plugin bundles one or more generator registrations through `use()`:
152
+ List all available language/client combinations.
230
153
 
231
154
  ```typescript
232
- import { use, generate } from "@powerduck/openapi-codegen";
233
-
234
- use({
235
- name: "internal-generators",
236
- register(api) {
237
- api.register({
238
- language: "go",
239
- client: "our-wrapper",
240
- generate(request) {
241
- return `// go wrapper for ${request.method} ${request.path}`;
242
- },
243
- });
244
- api.register({
245
- language: "ruby",
246
- client: "our-wrapper",
247
- generate(request) {
248
- return `# ruby wrapper for ${request.method} ${request.path}`;
249
- },
250
- });
251
- },
252
- });
155
+ import { list } from "@powerduck/openapi-codegen";
253
156
 
254
- const code = generate({
255
- document,
256
- path: "/pets",
257
- method: "get",
258
- language: "go",
259
- client: "our-wrapper",
260
- });
157
+ const generators = list();
158
+ // [{ language: "javascript", client: "fetch" }, ...]
261
159
  ```
262
160
 
263
- ---
264
-
265
- ## Generate from a Direct RequestIR
161
+ ### `normalize(document)`
266
162
 
267
- Skip `normalize` entirely by building a `RequestIR` yourself:
163
+ Normalize and validate an OpenAPI document.
268
164
 
269
165
  ```typescript
270
- import { generate } from "@powerduck/openapi-codegen";
271
- import type { RequestIR } from "@powerduck/openapi-codegen";
272
-
273
- const request: RequestIR = {
274
- method: "GET",
275
- baseUrl: "https://api.example.com",
276
- path: "/users/{id}",
277
- parameters: [
278
- { name: "id", in: "path", value: 123 },
279
- { name: "limit", in: "query", value: 10, style: "form", explode: true },
280
- ],
281
- headers: [
282
- { name: "Accept", in: "header", value: "application/json" },
283
- ],
284
- body: undefined,
285
- security: [],
286
- };
166
+ import { normalize } from "@powerduck/openapi-codegen";
287
167
 
288
- const code = generate({
289
- request,
290
- language: "python",
291
- client: "requests",
292
- });
168
+ const normalized = normalize(rawDocument);
293
169
  ```
294
170
 
295
171
  ---
296
172
 
297
- ## Core Types
173
+ ## TypeScript Types
298
174
 
299
175
  ```typescript
300
- type ParameterLocation = "path" | "query" | "querystring" | "header" | "cookie";
301
-
302
- interface Parameter {
303
- name: string;
304
- in: ParameterLocation;
305
- value: unknown;
306
- style?: string;
307
- explode?: boolean;
308
- allowReserved?: boolean;
309
- }
310
-
311
- interface Body {
312
- mediaType: string;
313
- value: unknown;
314
- encoding?: Record<string, unknown>;
315
- }
316
-
317
- interface Security {
318
- name: string;
319
- type: string;
320
- scheme?: string;
321
- in?: string;
322
- paramName?: string;
323
- value: string;
324
- }
325
-
326
- interface RequestIR {
327
- method: string;
328
- baseUrl: string;
329
- path: string;
330
- parameters: Parameter[];
331
- headers: Parameter[];
332
- body?: Body;
333
- security: Security[];
334
- }
335
-
336
- interface Generator {
337
- language: string;
338
- client: string;
339
- generate(request: RequestIR): string;
340
- }
341
-
342
- interface Plugin {
343
- name: string;
344
- register(api: { register(generator: Generator): void }): void;
345
- }
176
+ import type {
177
+ GenerateOptions,
178
+ GeneratorInfo,
179
+ OpenAPIDocument,
180
+ SecurityScheme,
181
+ Parameter,
182
+ RequestBody,
183
+ } from "@powerduck/openapi-codegen";
346
184
  ```
347
185
 
348
186
  ---
349
187
 
350
- ## Error Handling
188
+ ## Browser Usage
351
189
 
352
- `generate()` throws for missing input or unsupported generators. Wrap calls when processing untrusted documents:
190
+ ```html
191
+ <script type="module">
192
+ import { generate, list } from "https://esm.sh/@powerduck/openapi-codegen";
353
193
 
354
- ```typescript
355
- try {
356
194
  const code = generate({
357
- document,
358
- path: "/pets/{id}",
195
+ document: openApiDoc,
196
+ path: "/users",
359
197
  method: "get",
360
198
  language: "javascript",
361
199
  client: "fetch",
362
200
  });
363
- console.log(code);
364
- } catch (error) {
365
- console.error("Generation failed:", error instanceof Error ? error.message : error);
366
- }
367
- ```
368
-
369
- ---
370
-
371
- ## Development
372
-
373
- ```bash
374
- # Install dependencies
375
- npm install
376
-
377
- # Type check
378
- npm run typecheck
379
-
380
- # Build (ESM + CJS + type declarations)
381
- npm run build
382
-
383
- # Run tests
384
- npm test
385
-
386
- # Watch mode
387
- npx vitest watch
201
+ </script>
388
202
  ```
389
203
 
390
204
  ---
391
205
 
392
- ## Related Packages
393
-
394
- - [`@powerduck/openapi-parser`](https://www.npmjs.com/package/@powerduck/openapi-parser) — OpenAPI 3.2 parser, validator, and upgrader
395
- - [`@powerduck/openapi-request`](https://www.npmjs.com/package/@powerduck/openapi-request) — Execute OpenAPI operations with full parameter serialization
396
- - [`@powerduck/openapi-cli`](https://www.npmjs.com/package/@powerduck/openapi-cli) — CI-ready batch testing for OpenAPI documents
397
- - [`@powerduck/x-to-openapi`](https://www.npmjs.com/package/@powerduck/x-to-openapi) — Convert curl commands and Postman Collections to OpenAPI 3.2
398
-
399
- ---
400
-
401
206
  ## License
402
207
 
403
- MIT
208
+ MIT © [POWERDUCK LIMITED](https://www.powerduck.com)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@powerduck/openapi-codegen",
3
- "version": "0.5.2",
3
+ "version": "0.5.3",
4
4
  "description": "Generate runnable HTTP request examples from OpenAPI documents. 21 languages, 41 clients, browser-compatible, zero runtime dependencies.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",