forked from redwoodjs/graphql
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtriggerRouteHooks.ts
More file actions
114 lines (97 loc) · 2.9 KB
/
triggerRouteHooks.ts
File metadata and controls
114 lines (97 loc) · 2.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import { Request } from 'express'
import { ViteDevServer } from 'vite'
import { MetaHook, TagDescriptor } from '@redwoodjs/web'
import type { RouteHookEvent, RouteHookOutput } from '@redwoodjs/web'
interface RouteHooks {
meta?: MetaHook
}
interface TriggerRouteHooksParam {
routeHooks: RouteHooks
req: Request
parsedParams?: Record<string, any>
previousOutput?: RouteHookOutput
}
export const triggerRouteHooks = async ({
routeHooks,
req,
parsedParams = {},
previousOutput,
}: TriggerRouteHooksParam) => {
const event: RouteHookEvent = {
params: parsedParams,
headers: req.headers || {},
query: req.query as any, // TODO (STREAMING) we should parse query parameters the same way as RW router
// cookies: req.cookies || {}, // TODO (STREAMING) we probably need some sort of cookie parser
// TODO (STREAMING) called app routeHook, but its just the previous output
appRouteHook: previousOutput,
}
let meta: TagDescriptor[] = previousOutput?.meta || []
try {
const metaRouteHookOutput = (await routeHooks?.meta?.(event)) || []
// Convert it to an array, if it's not already
const currentMeta = Array.isArray(metaRouteHookOutput)
? metaRouteHookOutput
: [metaRouteHookOutput]
meta = [...meta, ...currentMeta]
} catch (e: any) {
throw new Error(`Error in meta hook: ${e.message}`)
}
return {
meta,
}
}
interface LoadAndRunRouteHooks {
paths: Array<string | null | undefined> // will run in order of the array
reqMeta: {
req: Request
parsedParams?: Record<string, any>
}
viteDevServer?: ViteDevServer
previousOutput?: RouteHookOutput
}
const defaultRouteHookOutput = {
meta: [],
}
export const loadAndRunRouteHooks = async ({
paths = [],
reqMeta,
viteDevServer,
previousOutput = defaultRouteHookOutput,
}: LoadAndRunRouteHooks): Promise<RouteHookOutput> => {
// Step 1, load the route hooks
const loadModule = async (path: string) => {
return viteDevServer ? viteDevServer.ssrLoadModule(path) : import(path)
}
let currentRouteHooks: RouteHooks
// Pull out the first path
// Remember shift will mutate the array
const routeHookPath = paths.shift()
if (!routeHookPath) {
return defaultRouteHookOutput
} else {
try {
currentRouteHooks = await loadModule(routeHookPath)
// Step 2, run the route hooks
const rhOutput = await triggerRouteHooks({
routeHooks: currentRouteHooks,
req: reqMeta.req,
parsedParams: reqMeta.parsedParams,
previousOutput,
})
if (paths.length > 0) {
// Step 3, recursively call this function
return loadAndRunRouteHooks({
paths,
reqMeta,
previousOutput: rhOutput,
viteDevServer,
})
} else {
return rhOutput
}
} catch (e) {
console.error(`Error loading route hooks in ${routeHookPath}}`)
throw new Error(e as any)
}
}
}