Skip to content

Commit 8ddb575

Browse files
MrLeebodrwpow
authored andcommitted
Refactor sort into an --alphabetize flag and add test cases
1 parent 28b8651 commit 8ddb575

33 files changed

+120834
-15
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ npx openapi-typescript schema.yaml
155155
| `--support-array-length` | | `false` | (optional) Generate tuples using array minItems / maxItems |
156156
| `--make-paths-enum` | `-pe` | `false` | (optional) Generate an enum of endpoint paths |
157157
| `--path-params-as-types` | | `false` | (optional) Substitute path parameter names with their respective types |
158+
| `--alphabetized` | | `false` | (optional) Sort types alphabetically |
158159
| `--raw-schema` | | `false` | Generate TS types from partial schema (e.g. having `components.schema` at the top level) |
159160

160161
### 🐢 Node

bin/cli.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ Options
3030
--export-type (optional) Export type instead of interface
3131
--support-array-length (optional) Generate tuples using array minItems / maxItems
3232
--path-params-as-types (optional) Substitute path parameter names with their respective types
33+
--alphabetize (optional) Sort types alphabetically
3334
--version (optional) Force schema parsing version
3435
`;
3536

@@ -57,6 +58,7 @@ const flags = parser(args, {
5758
"supportArrayLength",
5859
"makePathsEnum",
5960
"pathParamsAsTypes",
61+
"alphabetize",
6062
],
6163
number: ["version"],
6264
string: ["auth", "header", "headersObject", "httpMethod", "prettierConfig"],
@@ -112,6 +114,7 @@ async function generateSchema(pathToSpec) {
112114
exportType: flags.exportType,
113115
supportArrayLength: flags.supportArrayLength,
114116
pathParamsAsTypes: flags.pathParamsAsTypes,
117+
alphabetize: flags.alphabetize,
115118
});
116119

117120
// output

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ async function openapiTS(
4646
contentNever: options.contentNever || false,
4747
makePathsEnum: options.makePathsEnum || false,
4848
pathParamsAsTypes: options.pathParamsAsTypes,
49+
alphabetize: options.alphabetize || false,
4950
rawSchema: options.rawSchema || false,
5051
supportArrayLength: options.supportArrayLength,
5152
version: options.version || 3,

src/transform/headers.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { GlobalContext, HeaderObject } from "../types.js";
2-
import { comment, tsReadonly } from "../utils.js";
2+
import { comment, getEntries, tsReadonly } from "../utils.js";
33
import { transformSchemaObj } from "./schema.js";
44

55
interface TransformHeadersOptions extends GlobalContext {
@@ -12,8 +12,7 @@ export function transformHeaderObjMap(
1212
): string {
1313
let output = "";
1414

15-
const sortedEntries = Object.entries(headerMap).sort(([a], [b]) => a.localeCompare(b, "en"));
16-
for (const [k, v] of sortedEntries) {
15+
for (const [k, v] of getEntries(headerMap, options)) {
1716
if (!v.schema) continue;
1817

1918
if (v.description) output += comment(v.description);

src/transform/paths.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { GlobalContext, OperationObject, ParameterObject, PathItemObject } from "../types.js";
2-
import { comment, tsReadonly, nodeType } from "../utils.js";
2+
import { comment, tsReadonly, nodeType, getEntries } from "../utils.js";
33
import { transformOperationObj } from "./operation.js";
44
import { transformParametersArray } from "./parameters.js";
55

@@ -33,8 +33,7 @@ export function transformPathsObj(paths: Record<string, PathItemObject>, options
3333

3434
let output = "";
3535

36-
const sortedEntries = Object.entries(paths).sort(([a], [b]) => a.localeCompare(b, "en"));
37-
for (const [url, pathItem] of sortedEntries) {
36+
for (const [url, pathItem] of getEntries(paths, options)) {
3837
if (pathItem.description) output += comment(pathItem.description); // add comment
3938

4039
if (pathItem.$ref) {

src/transform/request.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import type { GlobalContext, RequestBody } from "../types.js";
2-
import { comment, tsReadonly } from "../utils.js";
2+
import { comment, getEntries, tsReadonly } from "../utils.js";
33
import { transformSchemaObj } from "./schema.js";
44

55
export function transformRequestBodies(requestBodies: Record<string, RequestBody>, ctx: GlobalContext) {
66
let output = "";
77

8-
const sortedEntries = Object.entries(requestBodies).sort(([a], [b]) => a.localeCompare(b, "en"));
9-
for (const [name, requestBody] of sortedEntries) {
8+
for (const [name, requestBody] of getEntries(requestBodies, ctx)) {
109
if (requestBody && requestBody.description) output += ` ${comment(requestBody.description)}`;
1110
output += ` "${name}": {\n ${transformRequestBodyObj(requestBody, ctx)}\n }\n`;
1211
}

src/transform/responses.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { GlobalContext } from "../types.js";
2-
import { comment, tsReadonly } from "../utils.js";
2+
import { comment, getEntries, tsReadonly } from "../utils.js";
33
import { transformHeaderObjMap } from "./headers.js";
44
import { transformSchemaObj } from "./schema.js";
55

@@ -15,8 +15,7 @@ export function transformResponsesObj(responsesObj: Record<string, any>, ctx: Gl
1515

1616
let output = "";
1717

18-
const sortedEntries = Object.entries(responsesObj).sort(([a], [b]) => a.localeCompare(b, "en"));
19-
for (const [httpStatusCode, response] of sortedEntries) {
18+
for (const [httpStatusCode, response] of getEntries(responsesObj, ctx)) {
2019
const statusCode = Number(httpStatusCode) || `"${httpStatusCode}"`; // don’t surround w/ quotes if numeric status code
2120
if (response.description) output += comment(response.description);
2221

src/transform/schema.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
tsUnionOf,
1010
parseSingleSimpleValue,
1111
ParsedSimpleValue,
12+
getEntries,
1213
} from "../utils.js";
1314

1415
interface TransformSchemaObjOptions extends GlobalContext {
@@ -27,8 +28,7 @@ function hasDefaultValue(node: any): boolean {
2728
export function transformSchemaObjMap(obj: Record<string, any>, options: TransformSchemaObjOptions): string {
2829
let output = "";
2930

30-
const sortedEntries = Object.entries(obj).sort(([a], [b]) => a.localeCompare(b, "en"));
31-
for (const [k, v] of sortedEntries) {
31+
for (const [k, v] of getEntries(obj, options)) {
3232
// 1. Add comment in jsdoc notation
3333
const comment = prepareComment(v);
3434
if (comment) output += comment;

src/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ export interface SwaggerToTSOptions {
136136
rawSchema?: boolean;
137137
/** (optional) Generate an enum containing all API paths. **/
138138
makePathsEnum?: boolean;
139+
/** (optional) Sort types alphabetically. */
140+
alphabetize?: boolean;
139141
/** (optional) Should logging be suppressed? (necessary for STDOUT) */
140142
silent?: boolean;
141143
/** (optional) OpenAPI version. Must be present if parsing raw schema */
@@ -186,6 +188,7 @@ export interface GlobalContext {
186188
makePathsEnum: boolean;
187189
namespace?: string;
188190
pathParamsAsTypes?: boolean;
191+
alphabetize?: boolean;
189192
rawSchema: boolean;
190193
silent?: boolean;
191194
supportArrayLength?: boolean;

src/utils.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { OpenAPI2, OpenAPI3, ReferenceObject } from "./types.js";
1+
import type { GlobalContext, OpenAPI2, OpenAPI3, ReferenceObject } from "./types.js";
22

33
type CommentObject = {
44
const?: boolean; // jsdoc without value
@@ -292,3 +292,9 @@ export function replaceKeys(obj: Record<string, any>): Record<string, any> {
292292
return obj;
293293
}
294294
}
295+
296+
export function getEntries<Item>(obj: ArrayLike<Item> | Record<string, Item>, options: GlobalContext) {
297+
const entries = Object.entries(obj);
298+
if (options.alphabetize) entries.sort(([a], [b]) => a.localeCompare(b, "en"));
299+
return entries;
300+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**
2+
* This file was auto-generated by openapi-typescript.
3+
* Do not make direct changes to the file.
4+
*/
5+
6+
export interface paths {
7+
'/test': {
8+
get: {
9+
parameters: {
10+
query: {
11+
search: string
12+
}
13+
}
14+
responses: {
15+
200: unknown
16+
}
17+
}
18+
}
19+
}
20+
21+
export interface definitions {
22+
TestSchema: {
23+
/**
24+
* @default 0
25+
* @example 0
26+
*/
27+
count?: number
28+
/**
29+
* @default false
30+
* @example false
31+
*/
32+
isEnabled?: boolean
33+
}
34+
}
35+
36+
export interface operations {}
37+
38+
export interface external {}

0 commit comments

Comments
 (0)