Skip to content

Commit 06b0455

Browse files
committed
feat: support router level middleware for express
1 parent 14285fc commit 06b0455

10 files changed

Lines changed: 124 additions & 37 deletions

File tree

e2e/src/generated/server/express/routes/escape-hatches.ts

Lines changed: 12 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

e2e/src/generated/server/express/routes/media-types.ts

Lines changed: 12 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

e2e/src/generated/server/express/routes/query-parameters.ts

Lines changed: 12 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

e2e/src/generated/server/express/routes/request-headers.ts

Lines changed: 12 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

e2e/src/generated/server/express/routes/route-matching.ts

Lines changed: 12 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

e2e/src/generated/server/express/routes/validation.ts

Lines changed: 12 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

e2e/src/index.fetch.spec.ts

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type {Server} from "node:http"
22
import {
33
afterAll,
4+
afterEach,
45
beforeAll,
56
beforeEach,
67
describe,
@@ -24,7 +25,6 @@ describe.each(
2425
}) => {
2526
let server: Server | undefined
2627
let client: ApiClient
27-
const logSpy = jest.spyOn(console, "log").mockImplementation(() => {})
2828

2929
beforeAll(async () => {
3030
const args = await startServer()
@@ -43,11 +43,6 @@ describe.each(
4343

4444
afterAll(async () => {
4545
server?.close()
46-
logSpy.mockRestore()
47-
})
48-
49-
beforeEach(() => {
50-
logSpy.mockClear()
5146
})
5247

5348
describe("CORS", () => {
@@ -539,20 +534,28 @@ describe.each(
539534
})
540535

541536
describe("route matching", () => {
537+
let logSpy: jest.SpiedFunction<typeof console.log>
538+
539+
beforeEach(() => {
540+
logSpy = jest.spyOn(console, "log").mockImplementation(() => {})
541+
})
542+
543+
afterEach(() => {
544+
logSpy.mockRestore()
545+
})
546+
542547
it("should match fixed field route over parameterized route", async () => {
543548
const res = await client.routeMatchingGetByFixedField()
544549

545550
expect(res.status).toBe(200)
546551
await expect(res.json()).resolves.toEqual({matched: "fixed-field"})
547552

548-
if (name === "koa") {
549-
expect(logSpy).toHaveBeenCalledWith(
550-
"Request started: GET /route-matching/fixed-field",
551-
)
552-
expect(logSpy).toHaveBeenCalledWith(
553-
"Request completed: [200] GET /route-matching/fixed-field [object Object]",
554-
)
555-
}
553+
expect(logSpy).toHaveBeenCalledWith(
554+
"Request started: GET /route-matching/fixed-field",
555+
)
556+
expect(logSpy).toHaveBeenCalledWith(
557+
"Request completed: [200] GET /route-matching/fixed-field",
558+
)
556559
})
557560

558561
it("should match parameterized route", async () => {
@@ -561,14 +564,12 @@ describe.each(
561564
expect(res.status).toBe(200)
562565
await expect(res.json()).resolves.toEqual({matched: "id", id: "123"})
563566

564-
if (name === "koa") {
565-
expect(logSpy).toHaveBeenCalledWith(
566-
"Request started: GET /route-matching/123",
567-
)
568-
expect(logSpy).toHaveBeenCalledWith(
569-
"Request completed: [200] GET /route-matching/123 [object Object]",
570-
)
571-
}
567+
expect(logSpy).toHaveBeenCalledWith(
568+
"Request started: GET /route-matching/123",
569+
)
570+
expect(logSpy).toHaveBeenCalledWith(
571+
"Request completed: [200] GET /route-matching/123",
572+
)
572573
})
573574
})
574575
})

e2e/src/routes/express/route-matching.ts

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,24 @@
1+
import type {RequestHandler} from "express"
12
import {
23
createRouter,
34
type RouteMatchingGetByFixedField,
45
type RouteMatchingGetById,
56
} from "../../generated/server/express/routes/route-matching.ts"
67

8+
export const routerMatchingLoggingMiddleware: RequestHandler = (
9+
req,
10+
res,
11+
next,
12+
) => {
13+
console.log(`Request started: ${req.method} ${req.path}`)
14+
res.on("finish", () => {
15+
console.log(
16+
`Request completed: [${res.statusCode}] ${req.method} ${req.path}`,
17+
)
18+
})
19+
next()
20+
}
21+
722
const routeMatchingGetByFixedField: RouteMatchingGetByFixedField = async (
823
_params,
924
respond,
@@ -19,8 +34,11 @@ const routeMatchingGetById: RouteMatchingGetById = async (
1934
}
2035

2136
export function createRouteMatchingRouter() {
22-
return createRouter({
23-
routeMatchingGetByFixedField,
24-
routeMatchingGetById,
25-
})
37+
return createRouter(
38+
{
39+
routeMatchingGetByFixedField,
40+
routeMatchingGetById,
41+
},
42+
{middleware: [routerMatchingLoggingMiddleware]},
43+
)
2644
}

e2e/src/routes/koa/route-matching.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@ export const routerMatchingLoggingMiddleware: RouterMiddleware = async (
1111
) => {
1212
console.log(`Request started: ${ctx.method} ${ctx.path}`)
1313
await next()
14-
console.log(
15-
`Request completed: [${ctx.status}] ${ctx.method} ${ctx.path} ${ctx.body}`,
16-
)
14+
console.log(`Request completed: [${ctx.status}] ${ctx.method} ${ctx.path}`)
1715
}
1816

1917
const routeMatchingGetByFixedField: RouteMatchingGetByFixedField = async (

packages/openapi-code-generator/src/typescript/server/typescript-express/typescript-express-router-builder.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export class ExpressRouterBuilder extends AbstractRouterBuilder {
3838
this.imports
3939
.from("express")
4040
.add("Router")
41-
.addType("Request", "Response", "NextFunction")
41+
.addType("Request", "Response", "NextFunction", "RequestHandler")
4242

4343
this.imports.from("express").all("express")
4444

@@ -209,9 +209,13 @@ ${this.operationTypes.flatMap((it) => it.statements).join("\n\n")}
209209
210210
${this.implementationExport(implementationExportName)}
211211
212-
export function ${createRouterExportName}(implementation: ${implementationExportName}): Router {
212+
export function ${createRouterExportName}(implementation: ${implementationExportName}, options: {middleware?: RequestHandler[]} = {}): Router {
213213
const router = Router()
214214
215+
if (options.middleware?.length) {
216+
router.use(...options.middleware)
217+
}
218+
215219
${statements.join("\n\n")}
216220
217221
return router

0 commit comments

Comments
 (0)