Skip to content

Commit 0fe9d36

Browse files
committed
feat(@angular/ssr): add defineNodeNextHandler utility
Introduced the `defineNodeNextHandler` utility to expose middleware functions from the `server.ts` entry point for use with Vite. This provides flexibility in integrating different server frameworks, including Express, Hono, and Fastify, with Angular SSR. Examples: **Express** ``` export default defineNodeNextHandler(app); ``` **Hono** ``` export default defineNodeNextHandler(async (req, res, next) => { try { const webRes = await app.fetch(createWebRequestFromNodeRequest(req)); if (webRes) { await writeResponseToNodeResponse(webRes, res); } else { next(); } } catch (error) { next(error); } }); ``` **Fastify** ```ts export default defineNodeNextHandler(async (req, res) => { await app.ready(); app.server.emit('request', req, res); }); ```
1 parent 6e4981e commit 0fe9d36

File tree

3 files changed

+79
-0
lines changed

3 files changed

+79
-0
lines changed

goldens/public-api/angular/ssr/node/index.api.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ export interface CommonEngineRenderOptions {
4646
// @public
4747
export function createWebRequestFromNodeRequest(nodeRequest: IncomingMessage): Request;
4848

49+
// @public
50+
export function defineNodeNextHandler<T = NextHandleFunction>(handler: T): T;
51+
4952
// @public
5053
export function isMainModule(url: string): boolean;
5154

packages/angular/ssr/node/public_api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export {
1414

1515
export { AngularNodeAppEngine } from './src/app-engine';
1616

17+
export { defineNodeNextHandler } from './src/handler';
1718
export { writeResponseToNodeResponse } from './src/response';
1819
export { createWebRequestFromNodeRequest } from './src/request';
1920
export { isMainModule } from './src/module';
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.dev/license
7+
*/
8+
9+
import type { IncomingMessage, ServerResponse } from 'node:http';
10+
11+
/**
12+
* Represents a middleware function for handling HTTP requests in a Node.js environment.
13+
*
14+
* @param req - The incoming HTTP request object.
15+
* @param res - The outgoing HTTP response object.
16+
* @param next - A callback function that signals the completion of the middleware or forwards the error if provided.
17+
*
18+
* @returns A Promise that resolves to void or simply void. The handler can be asynchronous.
19+
*/
20+
type NextHandleFunction = (
21+
req: IncomingMessage,
22+
res: ServerResponse,
23+
next: (err?: unknown) => void,
24+
) => Promise<void> | void;
25+
26+
/**
27+
* Attaches metadata to the handler function to mark it as a special handler for Node.js environments.
28+
*
29+
* @typeParam T - The type of the handler function, which defaults to `NextHandleFunction`.
30+
* @param handler - The handler function to be defined and annotated.
31+
* @returns The same handler function passed as an argument, with metadata attached.
32+
*
33+
* @example
34+
* Usage in an Express application:
35+
* ```ts
36+
* const app = express();
37+
* export default defineNodeNextHandler(app);
38+
* ```
39+
*
40+
* @example
41+
* Usage in a Hono application:
42+
* ```ts
43+
* const app = new Hono();
44+
* export default defineNodeNextHandler(async (req, res, next) => {
45+
* try {
46+
* const webRes = await app.fetch(createWebRequestFromNodeRequest(req));
47+
* if (webRes) {
48+
* await writeResponseToNodeResponse(webRes, res);
49+
* } else {
50+
* next();
51+
* }
52+
* } catch (error) {
53+
* next(error);
54+
* }
55+
* }));
56+
* ```
57+
*
58+
* @example
59+
* Usage in a Fastify application:
60+
* ```ts
61+
* const app = Fastify();
62+
* export default defineNodeNextHandler(async (req, res) => {
63+
* await app.ready();
64+
* app.server.emit('request', req, res);
65+
* res.send('Hello from Fastify with Node Next Handler!');
66+
* }));
67+
* ```
68+
* @developerPreview
69+
*/
70+
export function defineNodeNextHandler<T = NextHandleFunction>(handler: T): T {
71+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
72+
(handler as any)['__ng_node_next_handler__'] = true;
73+
74+
return handler;
75+
}

0 commit comments

Comments
 (0)