Skip to content

Commit 1473cec

Browse files
committed
Refactor
1 parent b2ddda8 commit 1473cec

File tree

195 files changed

+58986
-887513
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

195 files changed

+58986
-887513
lines changed

.gitignore

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,5 @@
1-
.dccache
2-
.cache
31
.DS_Store
4-
.idea/
5-
.nyc_output/
6-
**/generated/
7-
**/__snapshots__/
2+
test/fixtures/*.yaml
83
coverage/
94
dist
105
node_modules
11-
yarn.lock
12-
yarn-error.log

.npmrc

Lines changed: 0 additions & 1 deletion
This file was deleted.

README.md

Lines changed: 95 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@
88

99
# 📘️ openapi-typescript
1010

11-
🚀 Convert [OpenAPI](https://spec.openapis.org/oas/latest.html) schemas to TypeScript interfaces painlessly using pure Node.js. No Java, node-gyp, or running OpenAPI servers necessary. Uses [Prettier](https://npmjs.com/prettier) to format the output.
11+
🚀 Convert static [OpenAPI](https://spec.openapis.org/oas/latest.html) schemas to TypeScript types quickly using pure Node.js. Fast, lightweight, (almost) dependency-free, and no Java/node-gyp/running OpenAPI servers necessary.
1212

1313
**Features**
1414

15-
- ✅ Supports YAML and JSON
15+
- ✅ Supports YAML and JSON formats
16+
- ✅ Supports advanced OpenAPI 3.1 features like [discriminators](https://spec.openapis.org/oas/v3.1.0#discriminator-object)
1617
- ✅ Supports loading via remote URL (simple authentication supported with the `--auth` flag)
1718
- ✅ Supports remote references: `$ref: "external.yaml#components/schemas/User"`
18-
-Prettier formatting is fully customizable to match your existing code style.
19+
-Fetches remote schemas quickly using [undici](https://www.npmjs.com/package/undici)
1920

2021
**Examples**
2122

@@ -43,9 +44,7 @@ npx openapi-typescript "specs/**/*.yaml" --output schemas/
4344
# 🚀 specs/three.yaml -> schemas/specs/three.ts [250ms]
4445
```
4546

46-
_Note: if generating a single schema, `--output` must be a file (preferably `*.ts`). If using globs, `--output` must be a directory._
47-
48-
_Thanks to [@sharmarajdaksh](https://github.com/sharmarajdaksh) for the glob feature!_
47+
_Thanks, [@sharmarajdaksh](https://github.com/sharmarajdaksh)!_
4948

5049
#### ☁️ Reading specs from remote resource
5150

@@ -56,9 +55,9 @@ npx openapi-typescript https://petstore3.swagger.io/api/v3/openapi.yaml --output
5655
# 🚀 https://petstore3.swagger.io/api/v3/openapi.yaml -> petstore.d.ts [650ms]
5756
```
5857

59-
_Thanks to [@psmyrdek](https://github.com/psmyrdek) for the remote spec feature!_
58+
_Thanks, [@psmyrdek](https://github.com/psmyrdek)!_
6059

61-
#### Using in TypeScript
60+
#### 🟦 Using in TypeScript
6261

6362
Import any top-level item from the generated spec to use it. It works best if you also alias types to save on typing:
6463

@@ -70,7 +69,7 @@ type APIResponse = components["schemas"]["APIResponse"];
7069

7170
Because OpenAPI schemas may have invalid TypeScript characters as names, the square brackets are a safe way to access every property.
7271

73-
##### Operations
72+
##### 🏗️ Operations
7473

7574
Operations can be imported directly by their [operationId](https://spec.openapis.org/oas/latest.html#operation-object):
7675

@@ -80,9 +79,9 @@ import { operations } from "./generated-schema.ts";
8079
type getUsersById = operations["getUsersById"];
8180
```
8281

83-
_Thanks to [@gr2m](https://github.com/gr2m) for the operations feature!_
82+
_Thanks, [@gr2m](https://github.com/gr2m)!_
8483

85-
#### openapi-typescript-fetch
84+
#### openapi-typescript-fetch
8685

8786
The generated spec can also be used with [openapi-typescript-fetch](https://www.npmjs.com/package/openapi-typescript-fetch) which implements a typed fetch client for openapi-typescript.
8887

@@ -132,31 +131,96 @@ try {
132131

133132
#### Outputting to stdout
134133

135-
Simply omit the `--output` flag to return to stdout:
134+
Omit the `--output` flag to return to stdout:
136135

137136
```bash
138137
npx openapi-typescript schema.yaml
139138
```
140139

141-
#### CLI Options
142-
143-
| Option | Alias | Default | Description |
144-
| :----------------------------- | :---- | :------: | :-------------------------------------------------------------------------------------------------------------------------------------- |
145-
| `--output [location]` | `-o` | (stdout) | Where should the output file be saved? |
146-
| `--auth [token]` | | | (optional) Provide an auth token to be passed along in the request (only if accessing a private schema) |
147-
| `--header` | `-x` | | (optional) Provide an array of or singular headers as an alternative to a JSON object. Each header must follow the `key: value` pattern |
148-
| `--headersObject` | `-h` | | (optional) Provide a JSON object as string of HTTP headers for remote schema request. This will take priority over `--header` |
149-
| `--httpMethod` | `-m` | `GET` | (optional) Provide the HTTP Verb/Method for fetching a schema from a remote URL |
150-
| `--immutable-types` | `-it` | `false` | (optional) Generates immutable types (readonly properties and readonly array) |
151-
| `--additional-properties` | `-ap` | `false` | (optional) Allow arbitrary properties for all schema objects without `additionalProperties: false` |
152-
| `--default-non-nullable` | | `false` | (optional) Treat schema objects with default values as non-nullable |
153-
| `--prettier-config [location]` | `-c` | | (optional) Path to your custom Prettier configuration for output |
154-
| `--export-type` | | `false` | (optional) Export `type` instead of `interface` |
155-
| `--support-array-length` | | `false` | (optional) Generate tuples using array minItems / maxItems |
156-
| `--make-paths-enum` | `-pe` | `false` | (optional) Generate an enum of endpoint paths |
157-
| `--path-params-as-types` | | `false` | (optional) Substitute path parameter names with their respective types |
158-
| `--alphabetize` | | `false` | (optional) Sort types alphabetically |
159-
| `--raw-schema` | | `false` | Generate TS types from partial schema (e.g. having `components.schema` at the top level) |
140+
### Options
141+
142+
The following flags can be appended to the CLI command.
143+
144+
| Option | Alias | Default | Description |
145+
| :----------------------------- | :---- | :------: | :--------------------------------------------------------------------------------------------------------------------------- |
146+
| `--output [location]` | `-o` | (stdout) | Where should the output file be saved? |
147+
| `--auth [token]` | | | Provide an auth token to be passed along in the request (only if accessing a private schema) |
148+
| `--header` | `-x` | | Provide an array of or singular headers as an alternative to a JSON object. Each header must follow the `key: value` pattern |
149+
| `--headersObject` | `-h` | | Provide a JSON object as string of HTTP headers for remote schema request. This will take priority over `--header` |
150+
| `--httpMethod` | `-m` | `GET` | Provide the HTTP Verb/Method for fetching a schema from a remote URL |
151+
| `--immutable-types` | | `false` | Generates immutable types (readonly properties and readonly array) |
152+
| `--additional-properties` | | `false` | Allow arbitrary properties for all schema objects without `additionalProperties: false` |
153+
| `--default-non-nullable` | | `false` | Treat schema objects with default values as non-nullable |
154+
| `--export-type` | `-t` | `false` | Export `type` instead of `interface` |
155+
| `--path-params-as-types` | | `false` | Allow dynamic string lookups on the `paths` object |
156+
| `--support-array-length` | | `false` | Generate tuples using array `minItems` / `maxItems` |
157+
| `--alphabetize` | | `false` | Sort types alphabetically |
158+
159+
#### `--path-params-as-types`
160+
161+
By default, your URLs are preserved exactly as-written in your schema:
162+
163+
```ts
164+
export interface paths {
165+
'/user/{user_id}': components["schemas"]["User"];
166+
}
167+
```
168+
169+
Which means your type lookups also have to match the exact URL:
170+
171+
```ts
172+
import { paths } from './my-schema';
173+
174+
const url = `/user/${id}`;
175+
type UserResponses = paths['/user/{user_id}']['responses'];
176+
```
177+
178+
But when `--path-params-as-types` is enabled, you can take advantage of dynamic lookups like so:
179+
180+
```ts
181+
import { paths } from './my-schema';
182+
183+
const url = `/user/${id}`;
184+
type UserResponses = paths[url]['responses']; // automatically matches `paths['/user/{user_id}']`
185+
```
186+
187+
Though this is a contrived example, you could use this feature to automatically infer typing based on the URL in a fetch client or in some other useful place in your application.
188+
189+
_Thanks, [@Powell-v2](https://github.com/Powell-v2)!_
190+
191+
#### `--support-array-length`
192+
193+
This option is useful for generating tuples if an array type specifies `minItems` or `maxItems`.
194+
195+
For example, given the following schema:
196+
197+
```yaml
198+
components:
199+
schemas:
200+
TupleType
201+
type: array
202+
items:
203+
type: string
204+
minItems: 1
205+
maxItems: 2
206+
```
207+
208+
Enabling `--support-array-length` would change the typing like so:
209+
210+
```diff
211+
export interface components {
212+
schemas: {
213+
- TupleType: string[];
214+
+ TupleType: [string] | [string, string];
215+
};
216+
}
217+
```
218+
219+
This results in more explicit typechecking of array lengths.
220+
221+
_Note: this has a reasonable limit, so for example `maxItems: 100` would simply flatten back down to `string[];`_
222+
223+
_Thanks, [@kgtkr](https://github.com/kgtkr)!_
160224

161225
### 🐢 Node
162226

bin/cli.js

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ Options
2424
--content-never (optional) If supplied, an omitted reponse \`content\` property will be generated as \`never\` instead of \`unknown\`
2525
--additional-properties, -ap (optional) Allow arbitrary properties for all schema objects without "additionalProperties: false"
2626
--default-non-nullable (optional) If a schema object has a default value set, don’t mark it as nullable
27-
--prettier-config, -c (optional) specify path to Prettier config file
2827
--raw-schema (optional) Parse as partial schema (raw components)
2928
--paths-enum, -pe (optional) Generate an enum containing all API paths.
3029
--export-type (optional) Export type instead of interface
@@ -38,6 +37,7 @@ const OUTPUT_FILE = "FILE";
3837
const OUTPUT_STDOUT = "STDOUT";
3938
const CWD = new URL(`file://${process.cwd()}/`);
4039
const EXT_RE = /\.[^.]+$/i;
40+
const HTTP_RE = /^https?:\/\//;
4141

4242
const timeStart = process.hrtime();
4343

@@ -53,24 +53,20 @@ const flags = parser(args, {
5353
"defaultNonNullable",
5454
"immutableTypes",
5555
"contentNever",
56-
"rawSchema",
5756
"exportType",
5857
"supportArrayLength",
59-
"makePathsEnum",
6058
"pathParamsAsTypes",
6159
"alphabetize",
6260
],
6361
number: ["version"],
64-
string: ["auth", "header", "headersObject", "httpMethod", "prettierConfig"],
62+
string: ["auth", "header", "headersObject", "httpMethod"],
6563
alias: {
6664
additionalProperties: ["ap"],
6765
header: ["x"],
6866
headersObject: ["h"],
6967
httpMethod: ["m"],
7068
immutableTypes: ["it"],
7169
output: ["o"],
72-
prettierConfig: ["c"],
73-
makePathsEnum: ["pe"],
7470
},
7571
default: {
7672
httpMethod: "GET",
@@ -103,9 +99,6 @@ async function generateSchema(pathToSpec) {
10399
auth: flags.auth,
104100
defaultNonNullable: flags.defaultNonNullable,
105101
immutableTypes: flags.immutableTypes,
106-
prettierConfig: flags.prettierConfig,
107-
rawSchema: flags.rawSchema,
108-
makePathsEnum: flags.makePathsEnum,
109102
contentNever: flags.contentNever,
110103
silent: output === OUTPUT_STDOUT,
111104
version: flags.version,
@@ -156,13 +149,8 @@ async function main() {
156149
console.info(`✨ ${BOLD}openapi-typescript ${packageJSON.version}${RESET}`); // only log if we’re NOT writing to stdout
157150
}
158151

159-
// error: --raw-schema
160-
if (flags.rawSchema && !flags.version) {
161-
throw new Error(`--raw-schema requires --version flag`);
162-
}
163-
164152
// handle remote schema, exit
165-
if (/^https?:\/\//.test(pathToSpec)) {
153+
if (HTTP_RE.test(pathToSpec)) {
166154
if (output !== "." && output === OUTPUT_FILE) fs.mkdirSync(outputDir, { recursive: true });
167155
await generateSchema(pathToSpec);
168156
return;

0 commit comments

Comments
 (0)