Skip to content

Commit e125ba1

Browse files
Remove XML and urlencoded support, replace mixedContentTypes with listUsers
- Removed application/xml and application/x-www-form-urlencoded content types from updatePetWithForm endpoint - Replaced mixedContentTypes untagged route with listUsers route - Removed XML and urlencoded tests from app.test.ts - Removed json2xml import and xmlparser middleware (no longer needed) - Added User schema to openapi.yaml components - Updated api.ts to implement listUsers instead of mixedContentTypes - Updated tests for new listUsers endpoint Co-authored-by: jasonblanchard <1238532+jasonblanchard@users.noreply.github.com>
1 parent 0ac958f commit e125ba1

File tree

6 files changed

+69
-203
lines changed

6 files changed

+69
-203
lines changed

examples/tags/api.ts

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -108,36 +108,15 @@ export const storeService: ServerTypes.ServerForStore<Request, Response> = {
108108
// Service implementation for untagged operations
109109
export const untaggedService: ServerTypes.ServerForUntagged<Request, Response> =
110110
{
111-
mixedContentTypes: async ({
112-
parameters,
113-
requestBody,
114-
contentType,
115-
}): ServerTypes.MixedContentTypesResult => {
116-
const { petId } = parameters.path;
117-
let status: "available" | "pending" | "sold" | undefined;
118-
119-
// Since each content type has different structures,
120-
// use the request content type and requestBody discriminator to narrow the type in each case.
121-
122-
if (
123-
contentType === "application/json" &&
124-
requestBody.mediaType === "application/json"
125-
) {
126-
status = requestBody.content.jsonstatus;
127-
}
128-
129-
if (
130-
contentType == "application/xml" &&
131-
requestBody.mediaType === "application/xml"
132-
) {
133-
status = requestBody.content.xmlstatus;
134-
}
135-
111+
listUsers: async (): ServerTypes.ListUsersResult => {
136112
return {
137113
content: {
138114
200: {
139115
"application/json": {
140-
pet: { id: petId, name: "dog", status },
116+
users: [
117+
{ id: 1, username: "john_doe", email: "john@example.com" },
118+
{ id: 2, username: "jane_smith", email: "jane@example.com" },
119+
],
141120
},
142121
},
143122
},

examples/tags/app.test.ts

Lines changed: 8 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { describe, it } from "node:test";
22
import assert from "node:assert";
33
import makeApp from "./app.ts";
44
import request from "supertest";
5-
import { json2xml } from "xml-js";
65

76
const app = makeApp();
87

@@ -49,81 +48,20 @@ describe("updatePetWithForm", async () => {
4948
},
5049
});
5150
});
52-
53-
it("accepts xml input", async () => {
54-
const xmlData = json2xml(JSON.stringify({ status: "sold" }), {
55-
compact: true,
56-
ignoreComment: true,
57-
spaces: 4,
58-
});
59-
60-
const response = await request(app)
61-
.post("/api/v3/pet/123?name=cat")
62-
.set("Content-Type", "application/xml")
63-
.send(xmlData);
64-
65-
assert.equal(response.status, 200);
66-
assert.deepEqual(response.body, {
67-
pet: {
68-
id: 123,
69-
name: "cat",
70-
status: "sold",
71-
},
72-
});
73-
});
74-
75-
it("accepts form-urlencoded input", async () => {
76-
const response = await request(app)
77-
.post("/api/v3/pet/123?name=cat")
78-
.set("Content-Type", "application/x-www-form-urlencoded")
79-
.send("status=sold");
80-
81-
assert.equal(response.status, 200);
82-
assert.deepEqual(response.body, {
83-
pet: {
84-
id: 123,
85-
name: "cat",
86-
status: "sold",
87-
},
88-
});
89-
});
9051
});
9152

92-
describe("mixed content types with different structures", async () => {
93-
it("handles json by default", async () => {
94-
const response = await request(app)
95-
.post("/api/v3/pet/123/mixed-content-types")
96-
.send({ jsonstatus: "sold" });
97-
98-
assert.equal(response.status, 200);
99-
assert.deepEqual(response.body, {
100-
pet: {
101-
id: 123,
102-
name: "dog",
103-
status: "sold",
104-
},
105-
});
106-
});
107-
108-
it("handles xml", async () => {
109-
const xmlData = json2xml(JSON.stringify({ xmlstatus: "sold" }), {
110-
compact: true,
111-
ignoreComment: true,
112-
spaces: 4,
113-
});
114-
53+
describe("listUsers", async () => {
54+
it("returns 200", async () => {
11555
const response = await request(app)
116-
.post("/api/v3/pet/123/mixed-content-types")
117-
.set("Content-Type", "application/xml")
118-
.send(xmlData);
56+
.get("/api/v3/users")
57+
.set("Accept", "application/json");
11958

12059
assert.equal(response.status, 200);
12160
assert.deepEqual(response.body, {
122-
pet: {
123-
id: 123,
124-
name: "dog",
125-
status: "sold",
126-
},
61+
users: [
62+
{ id: 1, username: "john_doe", email: "john@example.com" },
63+
{ id: 2, username: "jane_smith", email: "jane@example.com" },
64+
],
12765
});
12866
});
12967
});

examples/tags/app.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import registerRoutes from "openapi-typescript-server-express";
55
import { petsService, storeService, untaggedService } from "./api.ts";
66
import OpenApiValidator from "express-openapi-validator";
77
import { NotImplementedError } from "openapi-typescript-server-runtime";
8-
import xmlparser from "express-xml-bodyparser";
98

109
export default function makeApp() {
1110
const app = express();
@@ -15,7 +14,6 @@ export default function makeApp() {
1514
});
1615

1716
app.use(express.json());
18-
app.use(xmlparser());
1917
app.use(express.urlencoded({ extended: true }));
2018

2119
const apiRouter = express();

examples/tags/gen/schema.d.ts

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,17 @@ export interface paths {
3737
patch?: never;
3838
trace?: never;
3939
};
40-
"/pet/{petId}/mixed-content-types": {
40+
"/users": {
4141
parameters: {
4242
query?: never;
4343
header?: never;
4444
path?: never;
4545
cookie?: never;
4646
};
47-
get?: never;
47+
/** Returns all users from the system */
48+
get: operations["listUsers"];
4849
put?: never;
49-
post: operations["mixedContentTypes"];
50+
post?: never;
5051
delete?: never;
5152
options?: never;
5253
head?: never;
@@ -132,6 +133,12 @@ export interface components {
132133
*/
133134
status?: "placed" | "approved" | "delivered";
134135
};
136+
User: {
137+
/** Format: int64 */
138+
id: number;
139+
username: string;
140+
email?: string;
141+
};
135142
};
136143
responses: never;
137144
parameters: never;
@@ -222,8 +229,6 @@ export interface operations {
222229
requestBody: {
223230
content: {
224231
"application/json": components["schemas"]["UpdatePetInput"];
225-
"application/xml": components["schemas"]["UpdatePetInput"];
226-
"application/x-www-form-urlencoded": components["schemas"]["UpdatePetInput"];
227232
};
228233
};
229234
responses: {
@@ -249,37 +254,23 @@ export interface operations {
249254
};
250255
};
251256
};
252-
mixedContentTypes: {
257+
listUsers: {
253258
parameters: {
254259
query?: never;
255260
header?: never;
256-
path: {
257-
/** @description ID of pet that needs to be updated */
258-
petId: number;
259-
};
261+
path?: never;
260262
cookie?: never;
261263
};
262-
requestBody: {
263-
content: {
264-
"application/json": {
265-
/** @enum {string} */
266-
jsonstatus: "available" | "pending" | "sold";
267-
};
268-
"application/xml": {
269-
/** @enum {string} */
270-
xmlstatus: "available" | "pending" | "sold";
271-
};
272-
};
273-
};
264+
requestBody?: never;
274265
responses: {
275-
/** @description successful operation */
266+
/** @description A list of users. */
276267
200: {
277268
headers: {
278269
[name: string]: unknown;
279270
};
280271
content: {
281272
"application/json": {
282-
pet?: components["schemas"]["Pet"];
273+
users?: components["schemas"]["User"][];
283274
};
284275
};
285276
};

examples/tags/gen/server.ts

Lines changed: 19 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,6 @@ export interface UpdatePetWithFormArgs<Req, Res> {
6464
mediaType: "application/json";
6565
content: paths['/pet/{petId}']['post']['requestBody']['content']['application/json']
6666
}
67-
| {
68-
mediaType: "application/xml";
69-
content: paths['/pet/{petId}']['post']['requestBody']['content']['application/xml']
70-
}
71-
| {
72-
mediaType: "application/x-www-form-urlencoded";
73-
content: paths['/pet/{petId}']['post']['requestBody']['content']['application/x-www-form-urlencoded']
74-
}
7567
;
7668
}
7769

@@ -92,36 +84,27 @@ export async function updatePetWithFormUnimplemented(): UpdatePetWithFormResult
9284
throw new NotImplementedError()
9385
}
9486

95-
export interface MixedContentTypesArgs<Req, Res> {
96-
parameters: paths['/pet/{petId}/mixed-content-types']['post']['parameters'];
87+
export interface ListUsersArgs<Req, Res> {
88+
parameters: paths['/users']['get']['parameters'];
9789
contentType: string;
9890
req: Req;
9991
res: Res;
100-
requestBody: {
101-
mediaType: "application/json";
102-
content: paths['/pet/{petId}/mixed-content-types']['post']['requestBody']['content']['application/json']
103-
}
104-
| {
105-
mediaType: "application/xml";
106-
content: paths['/pet/{petId}/mixed-content-types']['post']['requestBody']['content']['application/xml']
107-
}
108-
;
10992
}
11093

111-
interface MixedContentTypesResult200 {
112-
content: { 200: paths['/pet/{petId}/mixed-content-types']['post']['responses']['200']['content'] };
94+
interface ListUsersResult200 {
95+
content: { 200: paths['/users']['get']['responses']['200']['content'] };
11396
headers?: { [name: string]: any };
11497
}
11598

116-
interface MixedContentTypesResultDefault {
117-
content: { default: paths['/pet/{petId}/mixed-content-types']['post']['responses']['default']['content'] };
99+
interface ListUsersResultDefault {
100+
content: { default: paths['/users']['get']['responses']['default']['content'] };
118101
headers?: { [name: string]: any };
119102
status: number;
120103
}
121104

122-
export type MixedContentTypesResult = Promise<MixedContentTypesResult200 | MixedContentTypesResultDefault>;
105+
export type ListUsersResult = Promise<ListUsersResult200 | ListUsersResultDefault>;
123106

124-
export async function mixedContentTypesUnimplemented(): MixedContentTypesResult {
107+
export async function listUsersUnimplemented(): ListUsersResult {
125108
throw new NotImplementedError()
126109
}
127110

@@ -189,9 +172,10 @@ export interface Server<Req = unknown, Res = unknown> {
189172
updatePetWithForm: (
190173
args: UpdatePetWithFormArgs<Req, Res>
191174
) => UpdatePetWithFormResult;
192-
mixedContentTypes: (
193-
args: MixedContentTypesArgs<Req, Res>
194-
) => MixedContentTypesResult;
175+
/** Returns all users from the system */
176+
listUsers: (
177+
args: ListUsersArgs<Req, Res>
178+
) => ListUsersResult;
195179
getInventory: (
196180
args: GetInventoryArgs<Req, Res>
197181
) => GetInventoryResult;
@@ -218,9 +202,9 @@ export function registerRouteHandlers<Req, Res>(server: Server<Req, Res>): Route
218202
handler: server.updatePetWithForm as Route["handler"],
219203
},
220204
{
221-
method: "post",
222-
path: "/pet/{petId}/mixed-content-types",
223-
handler: server.mixedContentTypes as Route["handler"],
205+
method: "get",
206+
path: "/users",
207+
handler: server.listUsers as Route["handler"],
224208
},
225209
{
226210
method: "get",
@@ -244,7 +228,7 @@ export interface ServerForPets<Req = unknown, Res = unknown> {
244228
}
245229

246230
export interface ServerForUntagged<Req = unknown, Res = unknown> {
247-
mixedContentTypes: (args: MixedContentTypesArgs<Req, Res>) => MixedContentTypesResult;
231+
listUsers: (args: ListUsersArgs<Req, Res>) => ListUsersResult;
248232
}
249233

250234
export interface ServerForStore<Req = unknown, Res = unknown> {
@@ -278,9 +262,9 @@ export function registerRouteHandlersByTag<Req, Res>(tag: Tag, server: Partial<S
278262
break;
279263
case null:
280264
routes.push({
281-
method: "post",
282-
path: "/pet/{petId}/mixed-content-types",
283-
handler: server.mixedContentTypes as Route["handler"],
265+
method: "get",
266+
path: "/users",
267+
handler: server.listUsers as Route["handler"],
284268
});
285269
break;
286270
case "store":

0 commit comments

Comments
 (0)