Skip to content

Commit 0ee494d

Browse files
Fix parameter schema. Fixes #71 (#77)
1 parent 00da262 commit 0ee494d

File tree

6 files changed

+168
-24
lines changed

6 files changed

+168
-24
lines changed

examples/kitchensink/api.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ const API: ServerTypes.Server<Request, Response> = {
9595

9696
listPets: server.listPetsUnimplemented,
9797

98+
listPetsBySize: server.listPetsBySizeUnimplemented,
99+
98100
getPetImage: async (): ServerTypes.GetPetImageResult => {
99101
const image = await fs.readFile(join(__dirname, `./cat.jpeg`), {
100102
encoding: "base64",

examples/kitchensink/app.test.ts

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -137,30 +137,53 @@ describe("listPets", async () => {
137137
assert.equal(response.status, 501);
138138
assert.equal(response.body.message, "Not Implemented");
139139
});
140+
});
140141

141-
describe("getPetImage", async () => {
142-
it("returns 200", async () => {
143-
const response = await request(app)
144-
.get("/api/v3/pet/123/image")
145-
.set("Accept", "image/jpeg");
142+
describe("listPetsBySize", async () => {
143+
it("propagates unimplemented error", async () => {
144+
const response = await request(app)
145+
.get("/api/v3/pets/small")
146+
.set("Accept", "application/json");
146147

147-
assert.equal(response.status, 200);
148-
assert(response.body);
149-
assert.equal(response.headers["content-type"], "image/jpeg");
150-
});
148+
assert.equal(response.status, 501);
149+
assert.equal(response.body.message, "Not Implemented");
151150
});
152151

153-
describe("getPetWebpage", async () => {
154-
it("returns 200", async () => {
155-
const response = await request(app)
156-
.get("/api/v3/pet/123/webpage")
157-
.set("Accept", "text/html");
158-
159-
assert.equal(response.status, 200);
160-
assert.equal(
161-
response.text,
162-
"<html><body><h1>Hello, pet 123!</h1></body></html>",
163-
);
164-
});
152+
it("fails with unknown enums", async () => {
153+
const response = await request(app)
154+
.get("/api/v3/pets/blarge")
155+
.set("Accept", "application/json");
156+
157+
assert.equal(response.status, 400);
158+
assert.equal(
159+
response.body.message,
160+
"request/params/size must be equal to one of the allowed values: small, medium, large",
161+
);
162+
});
163+
});
164+
165+
describe("getPetImage", async () => {
166+
it("returns 200", async () => {
167+
const response = await request(app)
168+
.get("/api/v3/pet/123/image")
169+
.set("Accept", "image/jpeg");
170+
171+
assert.equal(response.status, 200);
172+
assert(response.body);
173+
assert.equal(response.headers["content-type"], "image/jpeg");
174+
});
175+
});
176+
177+
describe("getPetWebpage", async () => {
178+
it("returns 200", async () => {
179+
const response = await request(app)
180+
.get("/api/v3/pet/123/webpage")
181+
.set("Accept", "text/html");
182+
183+
assert.equal(response.status, 200);
184+
assert.equal(
185+
response.text,
186+
"<html><body><h1>Hello, pet 123!</h1></body></html>",
187+
);
165188
});
166189
});

examples/kitchensink/gen/schema.d.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,23 @@ export interface paths {
2121
patch?: never;
2222
trace?: never;
2323
};
24+
"/pets/{size}": {
25+
parameters: {
26+
query?: never;
27+
header?: never;
28+
path?: never;
29+
cookie?: never;
30+
};
31+
/** Returns all pets with a specific size */
32+
get: operations["listPetsBySize"];
33+
put?: never;
34+
post?: never;
35+
delete?: never;
36+
options?: never;
37+
head?: never;
38+
patch?: never;
39+
trace?: never;
40+
};
2441
"/pet/{petId}": {
2542
parameters: {
2643
query?: never;
@@ -89,6 +106,8 @@ export interface paths {
89106
export type webhooks = Record<string, never>;
90107
export interface components {
91108
schemas: {
109+
/** @enum {string} */
110+
PetSize: "small" | "medium" | "large";
92111
ErrorResponse: {
93112
message?: string;
94113
};
@@ -159,6 +178,40 @@ export interface operations {
159178
};
160179
};
161180
};
181+
listPetsBySize: {
182+
parameters: {
183+
query?: never;
184+
header?: never;
185+
path: {
186+
/** @description Size of the pets to return */
187+
size: components["schemas"]["PetSize"];
188+
};
189+
cookie?: never;
190+
};
191+
requestBody?: never;
192+
responses: {
193+
/** @description A list of pets. */
194+
200: {
195+
headers: {
196+
[name: string]: unknown;
197+
};
198+
content: {
199+
"application/json": {
200+
pets?: components["schemas"]["Pet"][];
201+
};
202+
};
203+
};
204+
/** @description unexpected error */
205+
default: {
206+
headers: {
207+
[name: string]: unknown;
208+
};
209+
content: {
210+
"application/json": components["schemas"]["ErrorResponse"];
211+
};
212+
};
213+
};
214+
};
162215
getPetById: {
163216
parameters: {
164217
query?: never;

examples/kitchensink/gen/server.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,30 @@ export async function listPetsUnimplemented(): ListPetsResult {
3131
throw new NotImplementedError()
3232
}
3333

34+
export interface ListPetsBySizeArgs<Req, Res> {
35+
parameters: paths['/pets/{size}']['get']['parameters'];
36+
contentType: string;
37+
req: Req;
38+
res: Res;
39+
}
40+
41+
interface ListPetsBySizeResult200 {
42+
content: { 200: paths['/pets/{size}']['get']['responses']['200']['content'] };
43+
headers?: { [name: string]: any };
44+
}
45+
46+
interface ListPetsBySizeResultDefault {
47+
content: { default: paths['/pets/{size}']['get']['responses']['default']['content'] };
48+
headers?: { [name: string]: any };
49+
status: number;
50+
}
51+
52+
export type ListPetsBySizeResult = Promise<ListPetsBySizeResult200 | ListPetsBySizeResultDefault>;
53+
54+
export async function listPetsBySizeUnimplemented(): ListPetsBySizeResult {
55+
throw new NotImplementedError()
56+
}
57+
3458
export interface GetPetByIdArgs<Req, Res> {
3559
parameters: paths['/pet/{petId}']['get']['parameters'];
3660
contentType: string;
@@ -166,6 +190,10 @@ export interface Server<Req = unknown, Res = unknown> {
166190
listPets: (
167191
args: ListPetsArgs<Req, Res>
168192
) => ListPetsResult;
193+
/** Returns all pets with a specific size */
194+
listPetsBySize: (
195+
args: ListPetsBySizeArgs<Req, Res>
196+
) => ListPetsBySizeResult;
169197
getPetById: (
170198
args: GetPetByIdArgs<Req, Res>
171199
) => GetPetByIdResult;
@@ -190,6 +218,11 @@ export function registerRouteHandlers<Req, Res>(server: Server<Req, Res>): Route
190218
path: "/pets",
191219
handler: server.listPets as Route["handler"],
192220
},
221+
{
222+
method: "get",
223+
path: "/pets/{size}",
224+
handler: server.listPetsBySize as Route["handler"],
225+
},
193226
{
194227
method: "get",
195228
path: "/pet/{petId}",

examples/kitchensink/openapi.yaml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,35 @@ paths:
2727
application/json:
2828
schema:
2929
$ref: "#/components/schemas/ErrorResponse"
30+
/pets/{size}:
31+
get:
32+
operationId: listPetsBySize
33+
summary: Returns all pets with a specific size
34+
parameters:
35+
- name: size
36+
in: path
37+
description: Size of the pets to return
38+
required: true
39+
schema:
40+
$ref: "#/components/schemas/PetSize"
41+
responses:
42+
"200":
43+
description: A list of pets.
44+
content:
45+
application/json:
46+
schema:
47+
type: object
48+
properties:
49+
pets:
50+
type: array
51+
items:
52+
$ref: "#/components/schemas/Pet"
53+
"default":
54+
description: unexpected error
55+
content:
56+
application/json:
57+
schema:
58+
$ref: "#/components/schemas/ErrorResponse"
3059
/pet/{petId}:
3160
get:
3261
operationId: getPetById
@@ -188,6 +217,12 @@ paths:
188217
type: string
189218
components:
190219
schemas:
220+
PetSize:
221+
type: string
222+
enum:
223+
- small
224+
- medium
225+
- large
191226
ErrorResponse:
192227
type: object
193228
properties:

packages/openapi-typescript-server-runtime/src/schema.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,7 @@ export const OpenAPISpec = z.object({
3535
name: z.string(),
3636
in: z.string(),
3737
required: z.boolean().optional(),
38-
schema: z.object({
39-
type: z.string(),
40-
}),
38+
schema: Schema,
4139
}),
4240
)
4341
.optional(),

0 commit comments

Comments
 (0)