-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
68 lines (58 loc) · 1.51 KB
/
index.js
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
async function invokeMiddleware(context) {
if (!context.middleware.length) return;
const mw = context.middleware[0];
return mw({
...context,
next: async () => {
await invokeMiddleware({
...context,
middleware: context.middleware.slice(1)
});
}
});
}
const DEFAULT_FALLBACK = new Response(null, {status: 404});
function initRoutes(routes) {
return routes.map(({
response,
middleware,
path
}) => ({
response: response,
middleware: middleware ?? [],
pattern: new URLPattern({
pathname: path,
search: '*',
hash: '*'
})
}))
}
function matchRoute(url, routes) {
for (const route of routes) {
const match = route.pattern.exec(url);
if(match) {
return {
...route,
params: match?.pathname?.groups ?? {},
};
}
}
}
const objectify = (acc, [k,v]) => ({...acc, [k]: v});
export function router({fallback, routes}) {
const r = initRoutes(routes);
return async (_, request) => {
const url = new URL(request.url);
const query = [...url.searchParams.entries()].reduce(objectify, {}) ?? {};
const headers = [...request.headers.entries()].reduce(objectify, {}) ?? {};
const route = matchRoute(url, r);
const { params, middleware } = route;
const context = {request, query, params, url, headers};
if(route) {
await invokeMiddleware({...context, middleware});
return await route.response(context);
} else {
return fallback ?? DEFAULT_FALLBACK;
}
}
}