-
Notifications
You must be signed in to change notification settings - Fork 0
/
mod.ts
101 lines (93 loc) · 3.16 KB
/
mod.ts
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
import {
DanetApplication,
} from './deps.ts';
import { StartOptions } from "https://deno.land/x/[email protected]/src/server/types.ts";
import { ServerContext } from "https://deno.land/x/[email protected]/src/server/context.ts";
import { dirname, fromFileUrl } from "https://deno.land/[email protected]/path/mod.ts";
import { collect, generate } from "https://deno.land/x/[email protected]/src/dev/mod.ts";
import { HttpContext } from "../danet/src/router/router.ts";
interface ManifestData {
routes: string[];
islands: string[];
}
export class FreshModule {
static async enableFresh(app: DanetApplication, url: URL, prefix: string, freshOptions: StartOptions = {}) {
await generateFreshManifest(url);
const manifest = (await import(url + './fresh.gen.ts')).default;
const handler = (await ServerContext.fromManifest(manifest, freshOptions))
.handler();
app.use(async (ctx, next) => {
if (
!ctx.request.url.toString().includes(prefix) &&
!ctx.request.url.toString().includes('_frsh')
) {
return await next();
}
const req = createNewRequest(ctx, prefix);
// deno-lint-ignore no-explicit-any
const res = await handler(req, null as any);
ctx.response.body = res.body;
ctx.response.status = res.status;
ctx.response.headers = res.headers;
});
}
static async enableFreshOnRoot(
app: DanetApplication,
url: URL,
prefix: string,
freshOptions: StartOptions = {},
) {
await generateFreshManifest(url);
const manifest = (await import(url + './fresh.gen.ts')).default;
const handler = (await ServerContext.fromManifest(manifest, freshOptions))
.handler();
app.danetRouter.setPrefix(prefix);
app.use(async (ctx, next) => {
if (ctx.request.url.toString().includes(prefix)) {
return await next();
}
const req = createNewRequest(ctx, '');
// deno-lint-ignore no-explicit-any
const res = await handler(req, null as any);
ctx.response.body = res.body;
ctx.response.status = res.status;
ctx.response.headers = res.headers;
});
}
}
async function generateFreshManifest(url: URL) {
const fileUrl = fromFileUrl(url);
const dir = dirname(fileUrl + 'fakefile');
let currentManifest: ManifestData;
const prevManifest = Deno.env.get('FRSH_DEV_PREVIOUS_MANIFEST');
if (prevManifest) {
currentManifest = JSON.parse(prevManifest);
} else {
currentManifest = { islands: [], routes: [] };
}
const newManifest = await collect(dir);
Deno.env.set('FRSH_DEV_PREVIOUS_MANIFEST', JSON.stringify(newManifest));
const manifestChanged =
!arraysEqual(newManifest.routes, currentManifest.routes) ||
!arraysEqual(newManifest.islands, currentManifest.islands);
if (manifestChanged) await generate(dir, newManifest);
}
function createNewRequest<AS>(ctx: HttpContext, prefix: string) {
let newUrl = ctx.request.url.toString().replace(prefix, '');
if (newUrl.endsWith('/')) {
newUrl = newUrl.slice(0, -1);
}
const req = new Request(newUrl, {
body: ctx.request.originalRequest.getBody().body,
headers: ctx.request.headers,
method: ctx.request.method,
});
return req;
}
function arraysEqual<T>(a: T[], b: T[]): boolean {
if (a.length !== b.length) return false;
for (let i = 0; i < a.length; ++i) {
if (a[i] !== b[i]) return false;
}
return true;
}