Skip to content

Commit bc8ef34

Browse files
committed
Merge branch 'main' into fix-requestBodies
2 parents e671542 + 69f0628 commit bc8ef34

File tree

12 files changed

+236
-9
lines changed

12 files changed

+236
-9
lines changed

docs/advanced.md

+2
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ enum ErrorCode {
6868

6969
:::
7070

71+
To generate in this fashion, `--enum` needs to be specified on the [command line](cli.md#flags).
72+
7173
Alternatively you can use `x-enumNames` and `x-enumDescriptions` ([NSwag/NJsonSchema](https://github.com/RicoSuter/NJsonSchema/wiki/Enums#enum-names-and-descriptions)).
7274

7375
## Styleguide

docs/node.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ By default, openapiTS will generate `updated_at?: string;` because it’s not su
116116
import openapiTS from "openapi-typescript";
117117
import ts from "typescript";
118118
119-
const DATE = ts.factory.createIdentifier("Date"); // `Date`
119+
const DATE = ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("Date")); // `Date`
120120
const NULL = ts.factory.createLiteralTypeNode(ts.factory.createNull()); // `null`
121121

122122
const ast = await openapiTS(mySchema, {
@@ -168,7 +168,7 @@ Use the same pattern to transform the types:
168168
import openapiTS from "openapi-typescript";
169169
import ts from "typescript";
170170
171-
const BLOB = ts.factory.createIdentifier("Blob"); // `Blob`
171+
const BLOB = ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("Blob")); // `Blob`
172172
const NULL = ts.factory.createLiteralTypeNode(ts.factory.createNull()); // `null`
173173

174174
const ast = await openapiTS(mySchema, {
@@ -221,7 +221,7 @@ Here we return an object with a schema property, which is the same as the above
221221
import openapiTS from "openapi-typescript";
222222
import ts from "typescript";
223223
224-
const BLOB = ts.factory.createIdentifier("Blob"); // `Blob`
224+
const BLOB = ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("Blob")); // `Blob`
225225
const NULL = ts.factory.createLiteralTypeNode(ts.factory.createNull()); // `null`
226226

227227
const ast = await openapiTS(mySchema, {

docs/zh/openapi-fetch/middleware-auth.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ import type { paths } from "./my-openapi-3-schema"; // 由openapi-typescript生
123123
let accessToken: string | undefined = undefined;
124124

125125
const authMiddleware: Middleware = {
126-
async onRequest(req) {
126+
async onRequest({ request }) {
127127
// 获取令牌,如果不存在
128128
if (!accessToken) {
129129
const authRes = await someAuthFunc();
@@ -137,8 +137,8 @@ const authMiddleware: Middleware = {
137137
// (可选) 在此添加逻辑以在令牌过期时刷新令牌
138138

139139
// 在每个请求中添加 Authorization 标头
140-
req.headers.set("Authorization", `Bearer ${accessToken}`);
141-
return req;
140+
request.headers.set("Authorization", `Bearer ${accessToken}`);
141+
return request;
142142
},
143143
};
144144

packages/openapi-typescript/CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# openapi-typescript
22

3+
## 7.0.2
4+
5+
### Patch Changes
6+
7+
- [#1743](https://github.com/openapi-ts/openapi-typescript/pull/1743) [`8f6ec20`](https://github.com/openapi-ts/openapi-typescript/commit/8f6ec20d5d26396c1745690f0e42675776e1a691) Thanks [@avaly](https://github.com/avaly)! - Generate valid types for referenced nested properties
8+
39
## 7.0.1
410

511
### Patch Changes

packages/openapi-typescript/bin/cli.js

+14-2
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,18 @@ const flags = parser(args, {
7878
},
7979
});
8080

81+
/**
82+
* Normalize the output path into a file URL.
83+
* @param {string} output - The output path to be transformed.
84+
* @returns {URL} The transformed file URL.
85+
*/
86+
function normalizeOutput(output) {
87+
if (path.isAbsolute(output)) {
88+
return new URL(`file://${output}}`);
89+
}
90+
return new URL(output, CWD);
91+
}
92+
8193
/**
8294
* @param {string | URL} schema
8395
* @param {@type import('@redocly/openapi-core').Config} redocly
@@ -179,7 +191,7 @@ async function main() {
179191
// if stdout, (still) don’t log anything to console!
180192
process.stdout.write(result);
181193
} else {
182-
const outFile = new URL(flags.output, CWD);
194+
const outFile = normalizeOutput(flags.output);
183195
fs.mkdirSync(new URL(".", outFile), { recursive: true });
184196
fs.writeFileSync(outFile, result, "utf8");
185197
done("stdin", flags.output, performance.now() - timeStart);
@@ -202,7 +214,7 @@ async function main() {
202214
// if stdout, (still) don’t log anything to console!
203215
process.stdout.write(result);
204216
} else {
205-
const outFile = new URL(flags.output, CWD);
217+
const outFile = normalizeOutput(flags.output);
206218
fs.mkdirSync(new URL(".", outFile), { recursive: true });
207219
fs.writeFileSync(outFile, result, "utf8");
208220
done(input, flags.output, performance.now() - timeStart);

packages/openapi-typescript/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "openapi-typescript",
33
"description": "Convert OpenAPI 3.0 & 3.1 schemas to TypeScript",
4-
"version": "7.0.1",
4+
"version": "7.0.2",
55
"author": {
66
"name": "Drew Powers",
77
"email": "[email protected]"

packages/openapi-typescript/src/lib/ts.ts

+5
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,11 @@ export function oapiRef(path: string): ts.TypeNode {
122122
);
123123
if (pointer.length > 1) {
124124
for (let i = 1; i < pointer.length; i++) {
125+
// Skip `properties` items when in the middle of the pointer
126+
// See: https://github.com/openapi-ts/openapi-typescript/issues/1742
127+
if (i > 2 && i < pointer.length - 1 && pointer[i] === "properties") {
128+
continue;
129+
}
125130
t = ts.factory.createIndexedAccessTypeNode(
126131
t,
127132
ts.factory.createLiteralTypeNode(

packages/openapi-typescript/src/transform/paths-object.ts

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export default function transformPathsObject(pathsObject: PathsObject, ctx: Glob
3535
/* type */ oapiRef(pathItemObject.$ref),
3636
);
3737
addJSDocComment(pathItemObject, property);
38+
type.push(property);
3839
} else {
3940
const pathItemType = transformPathItemObject(pathItemObject, {
4041
path: createRef(["paths", url]),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
openapi: 3.1.0
2+
3+
info:
4+
title: Path Items
5+
version: 1.0.0
6+
license:
7+
name: MIT
8+
url: https://opensource.org/licenses/MIT
9+
10+
servers:
11+
- url: https://my-example-server
12+
13+
paths:
14+
/users:
15+
$ref: '#/components/pathItems/users'
16+
17+
security:
18+
- bearerAuth: []
19+
20+
components:
21+
pathItems:
22+
users:
23+
post:
24+
summary: Create user
25+
operationId: createUser
26+
27+
requestBody:
28+
description: The user to create
29+
content:
30+
application/json:
31+
schema:
32+
type: object
33+
properties:
34+
name:
35+
type: string
36+
37+
responses:
38+
200:
39+
description: The user was created successfully
40+
content:
41+
application/json:
42+
schema:
43+
type: object
44+
properties:
45+
id:
46+
type: string
47+
name:
48+
type: string
49+
400:
50+
description: Bad request
51+
52+
securitySchemes:
53+
bearerAuth:
54+
type: http
55+
scheme: bearer
56+
bearerFormat: JWT

packages/openapi-typescript/test/lib/ts.test.ts

+10
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,16 @@ describe("oapiRef", () => {
6464
test("multiple parts", () => {
6565
expect(astToString(oapiRef("#/components/schemas/User")).trim()).toBe(`components["schemas"]["User"]`);
6666
});
67+
68+
test("removes inner `properties`", () => {
69+
expect(astToString(oapiRef("#/components/schemas/User/properties/username")).trim()).toBe(
70+
`components["schemas"]["User"]["username"]`,
71+
);
72+
});
73+
74+
test("leaves final `properties` intact", () => {
75+
expect(astToString(oapiRef("#/components/schemas/properties")).trim()).toBe(`components["schemas"]["properties"]`);
76+
});
6777
});
6878

6979
describe("tsEnum", () => {

packages/openapi-typescript/test/transform/components-object.test.ts

+54
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,60 @@ describe("transformComponentsObject", () => {
503503
},
504504
},
505505
],
506+
[
507+
"$ref nested properties",
508+
{
509+
given: {
510+
parameters: {
511+
direct: {
512+
name: "direct",
513+
in: "query",
514+
required: true,
515+
schema: {
516+
$ref: "#/components/aaa",
517+
},
518+
},
519+
nested: {
520+
name: "nested",
521+
in: "query",
522+
required: true,
523+
schema: {
524+
$ref: "#/components/schemas/bbb/properties/ccc",
525+
},
526+
},
527+
},
528+
schemas: {
529+
aaa: {
530+
type: "string",
531+
},
532+
bbb: {
533+
type: "object",
534+
properties: {
535+
ccc: {
536+
type: "string",
537+
},
538+
},
539+
},
540+
},
541+
},
542+
want: `{
543+
schemas: {
544+
aaa: string;
545+
bbb: {
546+
ccc?: string;
547+
};
548+
};
549+
responses: never;
550+
parameters: {
551+
direct: components["aaa"];
552+
nested: components["schemas"]["bbb"]["ccc"];
553+
};
554+
requestBodies: never;
555+
headers: never;
556+
pathItems: never;
557+
}`,
558+
},
559+
],
506560
];
507561

508562
for (const [testName, { given, want, options = DEFAULT_OPTIONS, ci }] of tests) {

packages/openapi-typescript/test/yaml.test.ts

+81
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,87 @@ export interface operations {
8383
};
8484
};
8585
};
86+
}`);
87+
});
88+
89+
test("not ignore path item components in paths", async () => {
90+
const result = await execa(cmd, ["./test/fixtures/path-item-components.yaml"], {
91+
cwd,
92+
});
93+
expect(result.stdout).toBe(`/**
94+
* This file was auto-generated by openapi-typescript.
95+
* Do not make direct changes to the file.
96+
*/
97+
98+
export interface paths {
99+
"/users": components["pathItems"]["users"];
100+
}
101+
export type webhooks = Record<string, never>;
102+
export interface components {
103+
schemas: never;
104+
responses: never;
105+
parameters: never;
106+
requestBodies: never;
107+
headers: never;
108+
pathItems: {
109+
users: {
110+
parameters: {
111+
query?: never;
112+
header?: never;
113+
path?: never;
114+
cookie?: never;
115+
};
116+
get?: never;
117+
put?: never;
118+
/** Create user */
119+
post: operations["createUser"];
120+
delete?: never;
121+
options?: never;
122+
head?: never;
123+
patch?: never;
124+
trace?: never;
125+
};
126+
};
127+
}
128+
export type $defs = Record<string, never>;
129+
export interface operations {
130+
createUser: {
131+
parameters: {
132+
query?: never;
133+
header?: never;
134+
path?: never;
135+
cookie?: never;
136+
};
137+
/** @description The user to create */
138+
requestBody?: {
139+
content: {
140+
"application/json": {
141+
name?: string;
142+
};
143+
};
144+
};
145+
responses: {
146+
/** @description The user was created successfully */
147+
200: {
148+
headers: {
149+
[name: string]: unknown;
150+
};
151+
content: {
152+
"application/json": {
153+
id?: string;
154+
name?: string;
155+
};
156+
};
157+
};
158+
/** @description Bad request */
159+
400: {
160+
headers: {
161+
[name: string]: unknown;
162+
};
163+
content?: never;
164+
};
165+
};
166+
};
86167
}`);
87168
});
88169
});

0 commit comments

Comments
 (0)