Skip to content

Commit a149236

Browse files
committed
feat: add after API call hooks and refactor handler
- Introduced `afterApiCall` and `afterPageRender` hooks for better control over API and page rendering processes. - Updated the handler to utilize these hooks, enhancing the request lifecycle management.
1 parent 3a89dd5 commit a149236

File tree

4 files changed

+86
-20
lines changed

4 files changed

+86
-20
lines changed

adex/runtime/handler.js

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,24 @@ export async function handler(req, res) {
3535
req.params = routeParams
3636
const modifiableContext = {
3737
req: req,
38+
res: res,
39+
}
40+
await emitToHooked(CONSTANTS.beforeApiCall, modifiableContext)
41+
const handlerFn =
42+
'default' in module ? module.default : (_, res) => res.end()
43+
const serverHandler = async (req, res) => {
44+
await handlerFn(req, res)
45+
await emitToHooked(CONSTANTS.afterApiCall, { req, res })
3846
}
39-
await emitToHooked(CONSTANTS.apiCall, modifiableContext)
4047
return {
41-
serverHandler:
42-
'default' in module ? module.default : (_, res) => res.end(),
48+
serverHandler,
4349
}
4450
}
4551
return {
46-
serverHandler: (_, res) => {
52+
serverHandler: async (_, res) => {
4753
res.statusCode = 404
4854
res.end('Not found')
55+
await emitToHooked(CONSTANTS.afterApiCall, { req, res })
4956
},
5057
}
5158
}
@@ -60,9 +67,17 @@ export async function handler(req, res) {
6067
// @ts-expect-error
6168
global.location = new URL(req.url, 'http://localhost')
6269

63-
const rendered = await renderToStringAsync(h(App, { url: req.url }), {})
70+
const modifiableContext = {
71+
req: req,
72+
}
73+
await emitToHooked(CONSTANTS.beforePageRender, modifiableContext)
74+
75+
const rendered = await renderToStringAsync(
76+
h(App, { url: modifiableContext.req.url }),
77+
{}
78+
)
6479

65-
const htmlString = HTMLTemplate({
80+
let htmlString = HTMLTemplate({
6681
metas,
6782
links,
6883
title,
@@ -73,13 +88,12 @@ export async function handler(req, res) {
7388
),
7489
body: rendered,
7590
})
76-
const modifiableContext = {
77-
req: req,
78-
html: htmlString,
79-
}
80-
await emitToHooked(CONSTANTS.pageRender, modifiableContext)
91+
92+
modifiableContext.html = htmlString
93+
await emitToHooked(CONSTANTS.afterPageRender, modifiableContext)
94+
htmlString = modifiableContext.html
8195
return {
82-
html: modifiableContext.html,
96+
html: htmlString,
8397
pageRoute: matchedInPages.route,
8498
}
8599
}

adex/src/hook.d.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ export type APIContext = {
1010
}
1111

1212
export declare const CONSTANTS: {
13-
pageRender: symbol
14-
apiCall: symbol
13+
beforePageRender: symbol
14+
afterPageRender: symbol
15+
beforeApiCall: symbol
16+
afterApiCall: symbol
1517
}
1618

1719
export declare function hook(
@@ -20,11 +22,19 @@ export declare function hook(
2022
): void
2123

2224
export declare function beforePageRender(
25+
fn: (ctx: Omit<Context, 'html'>) => void
26+
): Promise<void>
27+
28+
export declare function afterPageRender(
2329
fn: (ctx: Context) => void
2430
): Promise<void>
2531

2632
export declare function beforeAPICall(
2733
fn: (ctx: APIContext) => void
2834
): Promise<void>
2935

36+
export declare function afterAPICall(
37+
fn: (ctx: APIContext) => void
38+
): Promise<void>
39+
3040
export declare function emitToHooked(eventName: any, data: any): Promise<void>

adex/src/hook.js

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,60 @@
11
const hookListeners = new Map()
22

33
export const CONSTANTS = {
4-
pageRender: Symbol('page-render'),
5-
apiCall: Symbol('api-call'),
4+
beforePageRender: Symbol('before-page-render'),
5+
afterPageRender: Symbol('after-page-render'),
6+
beforeApiCall: Symbol('before-api-call'),
7+
afterApiCall: Symbol('after-api-call'),
68
}
79

10+
/**
11+
* Register a hook handler for a given event
12+
* @param {symbol} eventName
13+
* @param {(context: any) => any|Promise<any>} handler
14+
*/
815
export function hook(eventName, handler) {
916
const handlers = hookListeners.get(eventName) || []
1017
handlers.push(handler)
1118
hookListeners.set(eventName, handlers)
1219
}
1320

14-
export async function beforePageRender(fn) {
15-
hook(CONSTANTS.pageRender, fn)
21+
/**
22+
* Register a hook to run before page render
23+
* @param {(context: any) => any|Promise<any>} fn
24+
*/
25+
export function beforePageRender(fn) {
26+
hook(CONSTANTS.beforePageRender, fn)
1627
}
1728

18-
export async function beforeAPICall(fn) {
19-
hook(CONSTANTS.apiCall, fn)
29+
/**
30+
* Register a hook to run after page render
31+
* @param {(context: any) => any|Promise<any>} fn
32+
*/
33+
export function afterPageRender(fn) {
34+
hook(CONSTANTS.afterPageRender, fn)
2035
}
2136

37+
/**
38+
* Register a hook to run before API call
39+
* @param {(context: any) => any|Promise<any>} fn
40+
*/
41+
export function beforeAPICall(fn) {
42+
hook(CONSTANTS.beforeApiCall, fn)
43+
}
44+
45+
/**
46+
* Register a hook to run after API call
47+
* @param {(context: any) => any|Promise<any>} fn
48+
*/
49+
export function afterAPICall(fn) {
50+
hook(CONSTANTS.afterApiCall, fn)
51+
}
52+
53+
/**
54+
* Emit an event to all registered hooks
55+
* @param {symbol} eventName
56+
* @param {any} data
57+
*/
2258
export async function emitToHooked(eventName, data) {
2359
const handlers = hookListeners.get(eventName) || []
2460
for (let handler of handlers) {

playground/src/api/html.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
import { afterAPICall } from 'adex/hook'
2+
3+
afterAPICall(ctx => {
4+
console.log('called after api')
5+
})
6+
17
/**
28
* @param {import("adex/http").IncomingMessage} req
39
* @param {import("adex/http").ServerResponse} res

0 commit comments

Comments
 (0)