@anaemia/core 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/runtime/context.d.ts.map +1 -1
- package/dist/runtime/context.js +4 -3
- package/dist/runtime/entry-client.jsx +2 -1
- package/dist/runtime/entry-server.d.ts +1 -2
- package/dist/runtime/entry-server.d.ts.map +1 -1
- package/dist/runtime/entry-server.jsx +18 -331
- package/dist/runtime/resources.d.ts.map +1 -1
- package/dist/runtime/resources.js +2 -1
- package/dist/runtime/route-data.d.ts.map +1 -1
- package/dist/runtime/route-data.js +4 -3
- package/dist/runtime/route-request.d.ts.map +1 -1
- package/dist/runtime/route-request.js +2 -1
- package/dist/runtime/rpc-client.d.ts.map +1 -1
- package/dist/runtime/rpc-client.js +7 -6
- package/dist/runtime/server/app.d.ts +22 -0
- package/dist/runtime/server/app.d.ts.map +1 -0
- package/dist/runtime/server/app.js +21 -0
- package/dist/runtime/server/assets.d.ts +5 -0
- package/dist/runtime/server/assets.d.ts.map +1 -0
- package/dist/runtime/server/assets.js +48 -0
- package/dist/runtime/server/boot.d.ts +4 -0
- package/dist/runtime/server/boot.d.ts.map +1 -0
- package/dist/runtime/server/boot.js +6 -0
- package/dist/runtime/server/env.d.ts +3 -0
- package/dist/runtime/server/env.d.ts.map +1 -0
- package/dist/runtime/server/env.js +14 -0
- package/dist/runtime/server/guards.d.ts +29 -0
- package/dist/runtime/server/guards.d.ts.map +1 -0
- package/dist/runtime/server/guards.js +12 -0
- package/dist/runtime/server/html.d.ts +15 -0
- package/dist/runtime/server/html.d.ts.map +1 -0
- package/dist/runtime/server/html.js +62 -0
- package/dist/runtime/server/hydration.d.ts +3 -0
- package/dist/runtime/server/hydration.d.ts.map +1 -0
- package/dist/runtime/server/hydration.js +20 -0
- package/dist/runtime/server/manifest.d.ts +14 -0
- package/dist/runtime/server/manifest.d.ts.map +1 -0
- package/dist/runtime/server/manifest.js +59 -0
- package/dist/runtime/server/render-request.d.ts +21 -0
- package/dist/runtime/server/render-request.d.ts.map +1 -0
- package/dist/runtime/server/render-request.jsx +170 -0
- package/dist/runtime/server/route-match.d.ts +14 -0
- package/dist/runtime/server/route-match.d.ts.map +1 -0
- package/dist/runtime/server/route-match.js +35 -0
- package/dist/runtime/server/rpc.d.ts +3 -0
- package/dist/runtime/server/rpc.d.ts.map +1 -0
- package/dist/runtime/server/rpc.js +32 -0
- package/dist/runtime/server/types.d.ts +33 -0
- package/dist/runtime/server/types.d.ts.map +1 -0
- package/dist/runtime/server/types.js +1 -0
- package/dist/runtime/shared/constants.d.ts +8 -0
- package/dist/runtime/shared/constants.d.ts.map +1 -0
- package/dist/runtime/shared/constants.js +7 -0
- package/package.json +5 -2
- package/src/runtime/context.ts +4 -6
- package/src/runtime/entry-client.tsx +2 -1
- package/src/runtime/entry-server.tsx +19 -397
- package/src/runtime/resources.ts +2 -1
- package/src/runtime/route-data.ts +5 -4
- package/src/runtime/route-request.ts +2 -1
- package/src/runtime/rpc-client.ts +8 -7
- package/src/runtime/server/app.ts +44 -0
- package/src/runtime/server/assets.ts +69 -0
- package/src/runtime/server/boot.ts +9 -0
- package/src/runtime/server/env.ts +17 -0
- package/src/runtime/server/guards.ts +26 -0
- package/src/runtime/server/html.ts +84 -0
- package/src/runtime/server/hydration.ts +26 -0
- package/src/runtime/server/manifest.ts +69 -0
- package/src/runtime/server/render-request.tsx +230 -0
- package/src/runtime/server/route-match.ts +45 -0
- package/src/runtime/server/rpc.ts +34 -0
- package/src/runtime/server/types.ts +36 -0
- package/src/runtime/shared/constants.ts +7 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/runtime/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/runtime/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAGrD,KAAK,KAAK,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC;AAE7C,eAAO,MAAM,uBAAuB,oBAA2B,CAAC;AAChE,eAAO,MAAM,UAAU,yCAAgD,CAAC;AAGxE,wBAAgB,WAAW,CAAC,CAAC,SAAS,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAsB1F"}
|
package/dist/runtime/context.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
+
import { SERVER_FUNCTION_DATA_KEY } from "./shared/constants.js";
|
|
2
3
|
export const serverFunctionsRegistry = new Map();
|
|
3
4
|
export const ssrStorage = new AsyncLocalStorage();
|
|
4
5
|
globalThis.__ANAEMIA_SERVER_STORAGE__ = ssrStorage;
|
|
@@ -9,10 +10,10 @@ export function runOnServer(backendFn, id) {
|
|
|
9
10
|
const result = await backendFn(...args);
|
|
10
11
|
const store = ssrStorage.getStore();
|
|
11
12
|
if (store && hashId) {
|
|
12
|
-
if (!store.has(
|
|
13
|
-
store.set(
|
|
13
|
+
if (!store.has(SERVER_FUNCTION_DATA_KEY)) {
|
|
14
|
+
store.set(SERVER_FUNCTION_DATA_KEY, {});
|
|
14
15
|
}
|
|
15
|
-
const functionCache = store.get(
|
|
16
|
+
const functionCache = store.get(SERVER_FUNCTION_DATA_KEY);
|
|
16
17
|
if (!functionCache[hashId]) {
|
|
17
18
|
functionCache[hashId] = {};
|
|
18
19
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { hydrate, render } from "solid-js/web";
|
|
2
2
|
import { Router } from "@solidjs/router";
|
|
3
|
+
import { ENTRY_SELECTOR } from "./shared/constants.js";
|
|
3
4
|
// @ts-expect-error - resolved by Rspack
|
|
4
5
|
import App, { preloadActiveClientRoute } from "anaemia-user-app";
|
|
5
|
-
const mountTarget = document.querySelector(
|
|
6
|
+
const mountTarget = document.querySelector(ENTRY_SELECTOR);
|
|
6
7
|
if (!mountTarget) {
|
|
7
8
|
throw new Error("[anaemia] missing mount target");
|
|
8
9
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
declare const app: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
|
|
1
|
+
declare const app: import("hono").Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
|
|
3
2
|
export default app;
|
|
4
3
|
//# sourceMappingURL=entry-server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry-server.d.ts","sourceRoot":"","sources":["../../src/runtime/entry-server.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"entry-server.d.ts","sourceRoot":"","sources":["../../src/runtime/entry-server.tsx"],"names":[],"mappings":"AAiBA,QAAA,MAAM,GAAG,2FASP,CAAC;AAYH,eAAe,GAAG,CAAC"}
|
|
@@ -1,342 +1,29 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { renderToStringAsync, generateHydrationScript } from "solid-js/web";
|
|
6
|
-
import { Router } from "@solidjs/router";
|
|
7
|
-
import { ssrStorage, serverFunctionsRegistry } from "./context.js";
|
|
8
|
-
import fs from "node:fs";
|
|
9
|
-
import path from "node:path";
|
|
1
|
+
import { createServerApp } from "./server/app.js";
|
|
2
|
+
import { serveServer } from "./server/boot.js";
|
|
3
|
+
import { createRuntimeEnv } from "./server/env.js";
|
|
4
|
+
import { createManifestStore } from "./server/manifest.js";
|
|
10
5
|
// @ts-expect-error - resolved by Rspack
|
|
11
6
|
import App from "anaemia-user-app";
|
|
12
7
|
// @ts-expect-error - resolved by Rspack
|
|
13
8
|
import { preloadActiveClientRoute, serverLoaderRegistry, serverGuardRegistry } from "anaemia-user-app";
|
|
14
9
|
// @ts-expect-error - resolved by Rspack
|
|
15
10
|
import { registerServerRoutes } from "__anaemia_server_routes__";
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return await ssrStorage.run(store, next);
|
|
11
|
+
const env = createRuntimeEnv();
|
|
12
|
+
const manifestStore = createManifestStore(env);
|
|
13
|
+
const app = createServerApp({
|
|
14
|
+
App,
|
|
15
|
+
env,
|
|
16
|
+
preloadActiveClientRoute,
|
|
17
|
+
serverLoaderRegistry,
|
|
18
|
+
serverGuardRegistry,
|
|
19
|
+
registerServerRoutes,
|
|
20
|
+
getManifestSnapshot: manifestStore.getSnapshot,
|
|
21
|
+
loadManifestAndTemplate: manifestStore.load,
|
|
28
22
|
});
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const targetUrl = `${devServerUrl}${c.req.path}`;
|
|
32
|
-
try {
|
|
33
|
-
const response = await fetch(targetUrl);
|
|
34
|
-
if (!response.ok)
|
|
35
|
-
return c.text("asset not found in Rspack memory", 404);
|
|
36
|
-
const contentType = response.headers.get("content-type");
|
|
37
|
-
if (contentType)
|
|
38
|
-
c.header("content-type", contentType);
|
|
39
|
-
c.header("Cache-Control", "no-cache, no-store, must-revalidate");
|
|
40
|
-
c.header("Pragma", "no-cache");
|
|
41
|
-
c.header("Expires", "0");
|
|
42
|
-
return c.body(await response.arrayBuffer());
|
|
43
|
-
}
|
|
44
|
-
catch {
|
|
45
|
-
return c.text("failed to connect to Rspack dev server asset bridge", 500);
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
app.get("/assets/*", devAssetProxy);
|
|
49
|
-
}
|
|
50
|
-
else {
|
|
51
|
-
app.use("/assets/*", async (c, next) => {
|
|
52
|
-
await next();
|
|
53
|
-
if (c.res.ok)
|
|
54
|
-
c.res.headers.set("Cache-Control", "public, max-age=31536000, immutable");
|
|
55
|
-
});
|
|
56
|
-
app.use("/assets/*", serveStatic({
|
|
57
|
-
root: path.resolve(process.cwd(), "./dist/client"),
|
|
58
|
-
}));
|
|
59
|
-
}
|
|
60
|
-
app.post("/_rpc", async (c) => {
|
|
61
|
-
const functionId = c.req.query("id");
|
|
62
|
-
if (!functionId || !serverFunctionsRegistry.has(functionId)) {
|
|
63
|
-
return c.json({ error: "RPC function not found" }, 404);
|
|
64
|
-
}
|
|
65
|
-
const contentLength = Number(c.req.header("content-length") ?? 0);
|
|
66
|
-
if (contentLength > 512_000) {
|
|
67
|
-
return c.json({ error: "Payload too large" }, 413);
|
|
68
|
-
}
|
|
69
|
-
let argumentsArray;
|
|
70
|
-
try {
|
|
71
|
-
const body = await c.req.json();
|
|
72
|
-
if (!Array.isArray(body))
|
|
73
|
-
throw new Error("Expected array");
|
|
74
|
-
argumentsArray = body;
|
|
75
|
-
}
|
|
76
|
-
catch {
|
|
77
|
-
return c.json({ error: "Invalid request body" }, 400);
|
|
78
|
-
}
|
|
79
|
-
try {
|
|
80
|
-
const result = await serverFunctionsRegistry.get(functionId)(...argumentsArray);
|
|
81
|
-
return c.json(result);
|
|
82
|
-
}
|
|
83
|
-
catch (error) {
|
|
84
|
-
const message = error instanceof Error ? error.message : "Internal server error";
|
|
85
|
-
return c.json({ error: message }, 500);
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
app.use(async (c, next) => {
|
|
89
|
-
const p = c.req.path;
|
|
90
|
-
if (isDev && p.includes(".hot-update.")) {
|
|
91
|
-
const targetUrl = `${devServerUrl}${p}`;
|
|
92
|
-
try {
|
|
93
|
-
const response = await fetch(targetUrl);
|
|
94
|
-
if (!response.ok)
|
|
95
|
-
return c.text("hot update not found", 404);
|
|
96
|
-
const contentType = response.headers.get("content-type");
|
|
97
|
-
if (contentType)
|
|
98
|
-
c.header("content-type", contentType);
|
|
99
|
-
c.header("Cache-Control", "no-cache, no-store, must-revalidate");
|
|
100
|
-
return c.body(await response.arrayBuffer());
|
|
101
|
-
}
|
|
102
|
-
catch {
|
|
103
|
-
return c.text("failed to fetch hot update", 500);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
await next();
|
|
107
|
-
});
|
|
108
|
-
registerServerRoutes(app);
|
|
109
|
-
let memoizedHtmlTemplate = "";
|
|
110
|
-
let memoizedManifest = null;
|
|
111
|
-
const templatePath = path.resolve(process.cwd(), "./dist/client/index.html");
|
|
112
|
-
const manifestPath = path.resolve(process.cwd(), "./dist/route-manifest.json");
|
|
113
|
-
const loadManifestAndTemplate = async () => {
|
|
114
|
-
if (isDev) {
|
|
115
|
-
try {
|
|
116
|
-
memoizedHtmlTemplate = await fetch(`${devServerUrl}/index.html`).then((r) => {
|
|
117
|
-
if (!r.ok)
|
|
118
|
-
throw new Error(`index.html fetch failed: ${r.status}`);
|
|
119
|
-
return r.text();
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
catch (err) {
|
|
123
|
-
console.error("[anaemia engine sync error - HTML fetch failed]:", err);
|
|
124
|
-
memoizedHtmlTemplate = "";
|
|
125
|
-
}
|
|
126
|
-
try {
|
|
127
|
-
if (fs.existsSync(manifestPath)) {
|
|
128
|
-
memoizedManifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
|
|
129
|
-
}
|
|
130
|
-
else {
|
|
131
|
-
memoizedManifest = { routes: [], chunks: {}, errors: {} };
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
catch (err) {
|
|
135
|
-
console.error("[anaemia engine sync error - manifest read failed]:", err);
|
|
136
|
-
memoizedManifest = { routes: [], chunks: {}, errors: {} };
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
else {
|
|
140
|
-
try {
|
|
141
|
-
if (fs.existsSync(templatePath))
|
|
142
|
-
memoizedHtmlTemplate = fs.readFileSync(templatePath, "utf-8");
|
|
143
|
-
if (fs.existsSync(manifestPath))
|
|
144
|
-
memoizedManifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
|
|
145
|
-
}
|
|
146
|
-
catch {
|
|
147
|
-
console.warn("build assets not fully initialized during bootstrapping cycle.");
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
sortedRoutes = null;
|
|
151
|
-
};
|
|
152
|
-
const normalizeAssetUrl = (url) => {
|
|
153
|
-
if (!url || typeof url !== "string")
|
|
154
|
-
return "";
|
|
155
|
-
if (url.startsWith("http://") || url.startsWith("https://"))
|
|
156
|
-
return url;
|
|
157
|
-
return url.startsWith("/") ? url : `/${url}`;
|
|
158
|
-
};
|
|
159
|
-
async function runGuards(pattern, ctx) {
|
|
160
|
-
const chain = serverGuardRegistry.get(pattern) ?? [];
|
|
161
|
-
for (const loadGuards of chain) {
|
|
162
|
-
const guards = await loadGuards();
|
|
163
|
-
for (const guard of guards) {
|
|
164
|
-
const result = await guard(ctx);
|
|
165
|
-
if (result && ("redirect" in result || "status" in result))
|
|
166
|
-
return result;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
return null;
|
|
170
|
-
}
|
|
171
|
-
function matchRoute(manifest, reqPath) {
|
|
172
|
-
if (!sortedRoutes) {
|
|
173
|
-
sortedRoutes = [...manifest.routes].sort((a, b) => {
|
|
174
|
-
const score = (pattern) => {
|
|
175
|
-
const segments = pattern.split("/").filter(Boolean);
|
|
176
|
-
return segments.reduce((acc, s) => {
|
|
177
|
-
if (s.startsWith(":"))
|
|
178
|
-
return acc - 1;
|
|
179
|
-
if (s === "*" || s.startsWith("*"))
|
|
180
|
-
return acc - 2;
|
|
181
|
-
return acc;
|
|
182
|
-
}, segments.length * 10);
|
|
183
|
-
};
|
|
184
|
-
return score(b.urlPattern) - score(a.urlPattern);
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
for (const route of sortedRoutes) {
|
|
188
|
-
const regexStr = route.urlPattern
|
|
189
|
-
.replace(/:([a-zA-Z0-9_-]+)/g, "(?<$1>[^/]+)")
|
|
190
|
-
.replace(/\*([a-zA-Z0-9_-]*)/g, "(?<catchall>.*)");
|
|
191
|
-
const match = new RegExp(`^${regexStr}$`).exec(reqPath);
|
|
192
|
-
if (match) {
|
|
193
|
-
return {
|
|
194
|
-
activeChunk: route.chunkName,
|
|
195
|
-
targetPattern: route.urlPattern,
|
|
196
|
-
statusCode: 200,
|
|
197
|
-
params: match.groups ? { ...match.groups } : {},
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
return {
|
|
202
|
-
activeChunk: "route-404",
|
|
203
|
-
targetPattern: manifest.errors?.["404"] || "",
|
|
204
|
-
statusCode: 404,
|
|
205
|
-
params: {},
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
app.get("*", async (c) => {
|
|
209
|
-
if (isDev)
|
|
210
|
-
await loadManifestAndTemplate();
|
|
211
|
-
const template = memoizedHtmlTemplate;
|
|
212
|
-
const manifest = memoizedManifest;
|
|
213
|
-
if (!template || !manifest) {
|
|
214
|
-
return c.text("anaemia engine error: build assets are missing", 500);
|
|
215
|
-
}
|
|
216
|
-
const reqPath = c.req.path;
|
|
217
|
-
const { activeChunk, targetPattern, statusCode: matchedStatus, params } = matchRoute(manifest, reqPath);
|
|
218
|
-
let statusCode = matchedStatus;
|
|
219
|
-
const loaderArgs = { params, request: c.req.raw };
|
|
220
|
-
const store = ssrStorage.getStore() || new Map();
|
|
221
|
-
let htmlPayload;
|
|
222
|
-
if (targetPattern) {
|
|
223
|
-
try {
|
|
224
|
-
const guardResult = await runGuards(targetPattern, {
|
|
225
|
-
params,
|
|
226
|
-
request: c.req.raw,
|
|
227
|
-
url: reqPath,
|
|
228
|
-
});
|
|
229
|
-
if (guardResult) {
|
|
230
|
-
if ("redirect" in guardResult)
|
|
231
|
-
return c.redirect(guardResult.redirect, (guardResult.status ?? 302));
|
|
232
|
-
if ("status" in guardResult)
|
|
233
|
-
statusCode = guardResult.status;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
catch (err) {
|
|
237
|
-
console.error("[anaemia] guard threw unexpectedly:", err);
|
|
238
|
-
return c.text("Internal Server Error", 500);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
try {
|
|
242
|
-
htmlPayload = await ssrStorage.run(store, async () => {
|
|
243
|
-
if (targetPattern) {
|
|
244
|
-
const executableLoader = serverLoaderRegistry.get(targetPattern);
|
|
245
|
-
if (executableLoader) {
|
|
246
|
-
const initialLoaderData = await executableLoader(loaderArgs);
|
|
247
|
-
store.set("__LOADER_DATA__", initialLoaderData);
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
await preloadActiveClientRoute(reqPath);
|
|
251
|
-
return await renderToStringAsync(() => (<Router url={reqPath}>
|
|
252
|
-
<App />
|
|
253
|
-
</Router>));
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
catch (err) {
|
|
257
|
-
statusCode = 500;
|
|
258
|
-
console.error("[anaemia framework] runtime execution crash handled:", err);
|
|
259
|
-
const error500Pattern = manifest.errors?.["500"];
|
|
260
|
-
const error500Loader = error500Pattern ? serverLoaderRegistry.get(error500Pattern) : null;
|
|
261
|
-
if (error500Loader) {
|
|
262
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
263
|
-
const stack = err instanceof Error ? err.stack : undefined;
|
|
264
|
-
const runtimeContextPayload = { message, stack: isDev ? stack : undefined };
|
|
265
|
-
store.set("__LOADER_DATA__", runtimeContextPayload);
|
|
266
|
-
try {
|
|
267
|
-
htmlPayload = await ssrStorage.run(store, async () => {
|
|
268
|
-
return await renderToStringAsync(() => (<Router url={error500Pattern}>
|
|
269
|
-
<App />
|
|
270
|
-
</Router>));
|
|
271
|
-
});
|
|
272
|
-
}
|
|
273
|
-
catch {
|
|
274
|
-
htmlPayload = `<h1>500 Internal Server Error</h1>`;
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
else {
|
|
278
|
-
const stack = err instanceof Error ? err.stack : String(err);
|
|
279
|
-
htmlPayload = `<h1>500 Internal Server Error</h1><pre>${isDev ? stack : ""}</pre>`;
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
let assetScripts = "";
|
|
283
|
-
let assetStyles = "";
|
|
284
|
-
const processChunkAssets = (chunk) => {
|
|
285
|
-
if (!chunk)
|
|
286
|
-
return;
|
|
287
|
-
if (chunk.js) {
|
|
288
|
-
const jsSpecs = Array.isArray(chunk.js) ? chunk.js : [chunk.js];
|
|
289
|
-
for (const jsFile of jsSpecs) {
|
|
290
|
-
assetScripts += `<script type="module" src="${normalizeAssetUrl(jsFile)}"></script>\n`;
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
if (chunk.css) {
|
|
294
|
-
const cssSpecs = Array.isArray(chunk.css) ? chunk.css : [chunk.css];
|
|
295
|
-
for (const cssFile of cssSpecs) {
|
|
296
|
-
assetStyles += `<link rel="stylesheet" href="${normalizeAssetUrl(cssFile)}">\n`;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
};
|
|
300
|
-
processChunkAssets(manifest.chunks["client"]);
|
|
301
|
-
processChunkAssets(manifest.chunks["commons"]);
|
|
302
|
-
processChunkAssets(manifest.chunks["vendors"]);
|
|
303
|
-
if (activeChunk && activeChunk !== "client")
|
|
304
|
-
processChunkAssets(manifest.chunks[activeChunk]);
|
|
305
|
-
const hydrationScript = generateHydrationScript();
|
|
306
|
-
const rawStorePayload = Object.fromEntries(store);
|
|
307
|
-
const finalHydrationStatePayload = {
|
|
308
|
-
__LOADER_DATA__: rawStorePayload.__LOADER_DATA__ || {},
|
|
309
|
-
__SERVER_FUNCTION_DATA__: rawStorePayload.__SERVER_FUNCTION_DATA__ || {},
|
|
310
|
-
};
|
|
311
|
-
const serializedData = JSON.stringify(finalHydrationStatePayload)
|
|
312
|
-
.replace(/&/g, "\\u0026")
|
|
313
|
-
.replace(/</g, "\\u003c")
|
|
314
|
-
.replace(/>/g, "\\u003e")
|
|
315
|
-
.replace(/\//g, "\\u002f");
|
|
316
|
-
const dataScript = `<script id="__ANAEMIA_DATA__" type="application/json">${serializedData}</script>\n`;
|
|
317
|
-
const devNoCacheTag = isDev
|
|
318
|
-
? `<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">\n<meta http-equiv="Pragma" content="no-cache">\n<meta http-equiv="Expires" content="0">\n`
|
|
319
|
-
: "";
|
|
320
|
-
const combinedHeadInjections = `${devNoCacheTag}${assetStyles}${dataScript}${hydrationScript}`;
|
|
321
|
-
const sanitizedPayload = htmlPayload.trim();
|
|
322
|
-
let completeHtmlOutput = ENTRY_TAG_REGEX.test(template)
|
|
323
|
-
? template.replace(ENTRY_TAG_REGEX, (_, open, _tag, _inner, close) => `${open}${sanitizedPayload}${close}`)
|
|
324
|
-
: template.replace("</body>", () => `<div anaemia-entry>${sanitizedPayload}</div></body>`);
|
|
325
|
-
completeHtmlOutput = completeHtmlOutput.replace("<head>", `<head>${combinedHeadInjections}`);
|
|
326
|
-
completeHtmlOutput = completeHtmlOutput.replace("</body>", `${assetScripts}</body>`);
|
|
327
|
-
if (isDev) {
|
|
328
|
-
c.header("Cache-Control", "no-cache, no-store, must-revalidate");
|
|
329
|
-
c.header("Pragma", "no-cache");
|
|
330
|
-
c.header("Expires", "0");
|
|
331
|
-
}
|
|
332
|
-
c.status(statusCode);
|
|
333
|
-
return c.html(completeHtmlOutput);
|
|
334
|
-
});
|
|
335
|
-
loadManifestAndTemplate()
|
|
23
|
+
manifestStore
|
|
24
|
+
.load()
|
|
336
25
|
.then(() => {
|
|
337
|
-
|
|
338
|
-
console.log(`[anaemia framework] server live at http://localhost:${info.port}`);
|
|
339
|
-
});
|
|
26
|
+
serveServer(app, env);
|
|
340
27
|
})
|
|
341
28
|
.catch((err) => {
|
|
342
29
|
console.error("[anaemia] failed to initialize:", err);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../../src/runtime/resources.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../../src/runtime/resources.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,UAAU,CAAC;AAerF,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EACjD,MAAM,EAAE,MAAM,MAAM,EACpB,QAAQ,EAAE,CAAC,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG;IACpD,kBAAkB,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACvD,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,EACD,OAAO,CAAC,EAAE,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,GACxC,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAuCjC"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { createResource } from "solid-js";
|
|
2
2
|
import { isServer } from "solid-js/web";
|
|
3
|
+
import { SERVER_FUNCTION_DATA_KEY } from "./shared/constants.js";
|
|
3
4
|
export function createServerResource(source, serverFn, options) {
|
|
4
5
|
if (isServer) {
|
|
5
6
|
let ssrInitialValue = undefined;
|
|
6
7
|
const store = globalThis.__ANAEMIA_SERVER_STORAGE__?.getStore?.();
|
|
7
8
|
if (store && serverFn.id) {
|
|
8
|
-
const fnData = store.get(
|
|
9
|
+
const fnData = store.get(SERVER_FUNCTION_DATA_KEY);
|
|
9
10
|
const fnCache = fnData?.[serverFn.id];
|
|
10
11
|
if (fnCache) {
|
|
11
12
|
const sourceValue = source();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-data.d.ts","sourceRoot":"","sources":["../../src/runtime/route-data.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8D,KAAK,GAAG,EAAE,MAAM,UAAU,CAAC;AAEhG,OAAO,EAA0B,KAAK,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"route-data.d.ts","sourceRoot":"","sources":["../../src/runtime/route-data.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8D,KAAK,GAAG,EAAE,MAAM,UAAU,CAAC;AAEhG,OAAO,EAA0B,KAAK,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAKhD,KAAK,UAAU,CAAC,OAAO,SAAS,MAAM,IAAI;IACxC,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,KAAK,wBAAwB,CAAC,OAAO,SAAS,MAAM,GAAG,MAAM,IAAI;IAC/D,MAAM,EAAE,CAAC,IAAI,EAAE,UAAU,CAAC,OAAO,CAAC,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAClE,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC;CACvB,CAAC;AA6BF,wBAAgB,mBAAmB,CAAC,OAAO,SAAS,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,wBAAwB,CAAC,OAAO,CAAC,eA2B5G;AAED,wBAAgB,YAAY,CAAC,CAAC,GAAG,OAAO,KAAK,MAAM,CAAC,CAMnD"}
|
|
@@ -3,20 +3,21 @@ import { isServer } from "solid-js/web";
|
|
|
3
3
|
import { useParams, useLocation } from "@solidjs/router";
|
|
4
4
|
import { ssrStorage } from "./context.js";
|
|
5
5
|
import { createRouteRequest } from "./route-request.js";
|
|
6
|
+
import { ANAEMIA_DATA_SCRIPT_ID, LOADER_DATA_KEY } from "./shared/constants.js";
|
|
6
7
|
const RouteDataContext = createContext();
|
|
7
8
|
let hasReadClientHydrationData = false;
|
|
8
9
|
function readSSRData() {
|
|
9
10
|
if (isServer) {
|
|
10
|
-
return ssrStorage.getStore()?.get(
|
|
11
|
+
return ssrStorage.getStore()?.get(LOADER_DATA_KEY);
|
|
11
12
|
}
|
|
12
13
|
if (hasReadClientHydrationData)
|
|
13
14
|
return undefined;
|
|
14
15
|
hasReadClientHydrationData = true;
|
|
15
|
-
const el = document.getElementById(
|
|
16
|
+
const el = document.getElementById(ANAEMIA_DATA_SCRIPT_ID);
|
|
16
17
|
if (!el?.textContent)
|
|
17
18
|
return undefined;
|
|
18
19
|
try {
|
|
19
|
-
return JSON.parse(el.textContent)
|
|
20
|
+
return JSON.parse(el.textContent)[LOADER_DATA_KEY];
|
|
20
21
|
}
|
|
21
22
|
catch {
|
|
22
23
|
return undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-request.d.ts","sourceRoot":"","sources":["../../src/runtime/route-request.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"route-request.d.ts","sourceRoot":"","sources":["../../src/runtime/route-request.ts"],"names":[],"mappings":"AAKA,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAQ5D"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { isServer } from "solid-js/web";
|
|
2
2
|
import { ssrStorage } from "./context.js";
|
|
3
|
+
import { HONO_CONTEXT_KEY } from "./shared/constants.js";
|
|
3
4
|
export function createRouteRequest(pathname) {
|
|
4
5
|
if (isServer) {
|
|
5
|
-
const honoContext = ssrStorage.getStore()?.get(
|
|
6
|
+
const honoContext = ssrStorage.getStore()?.get(HONO_CONTEXT_KEY);
|
|
6
7
|
const request = honoContext?.req.raw;
|
|
7
8
|
if (request)
|
|
8
9
|
return request;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rpc-client.d.ts","sourceRoot":"","sources":["../../src/runtime/rpc-client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"rpc-client.d.ts","sourceRoot":"","sources":["../../src/runtime/rpc-client.ts"],"names":[],"mappings":"AAsDA,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM;cACD,OAAO,EAAE;;gCAgCF,OAAO,EAAE;EAoB/D"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { isServer } from "solid-js/web";
|
|
2
|
+
import { ANAEMIA_DATA_SCRIPT_ID, RPC_PATH, SERVER_FUNCTION_DATA_KEY } from "./shared/constants.js";
|
|
2
3
|
let _clientCache = null;
|
|
3
4
|
function ensureCacheInitialized() {
|
|
4
5
|
if (isServer || _clientCache)
|
|
5
6
|
return;
|
|
6
|
-
const script = document.getElementById(
|
|
7
|
+
const script = document.getElementById(ANAEMIA_DATA_SCRIPT_ID);
|
|
7
8
|
try {
|
|
8
9
|
_clientCache = JSON.parse(script?.textContent || "{}");
|
|
9
10
|
}
|
|
@@ -30,7 +31,7 @@ export function $$executeClientRpc(hashId) {
|
|
|
30
31
|
if (isServer) {
|
|
31
32
|
const store = getServerStore();
|
|
32
33
|
if (store) {
|
|
33
|
-
const functionCache = store.get(
|
|
34
|
+
const functionCache = store.get(SERVER_FUNCTION_DATA_KEY);
|
|
34
35
|
if (functionCache?.[hashId]) {
|
|
35
36
|
const match = findLooseCacheMatch(functionCache[hashId], args[0]);
|
|
36
37
|
if (match)
|
|
@@ -40,14 +41,14 @@ export function $$executeClientRpc(hashId) {
|
|
|
40
41
|
return;
|
|
41
42
|
}
|
|
42
43
|
ensureCacheInitialized();
|
|
43
|
-
const serverFunctionData = _clientCache?.
|
|
44
|
+
const serverFunctionData = _clientCache?.[SERVER_FUNCTION_DATA_KEY]?.[hashId];
|
|
44
45
|
const match = findLooseCacheMatch(serverFunctionData ?? {}, args[0]);
|
|
45
46
|
if (match) {
|
|
46
47
|
const { matchingKey, data } = match;
|
|
47
48
|
delete serverFunctionData[matchingKey];
|
|
48
49
|
return data;
|
|
49
50
|
}
|
|
50
|
-
const response = await fetch(
|
|
51
|
+
const response = await fetch(`${RPC_PATH}?id=${hashId}`, {
|
|
51
52
|
method: "POST",
|
|
52
53
|
headers: { "Content-Type": "application/json" },
|
|
53
54
|
body: JSON.stringify(args),
|
|
@@ -61,7 +62,7 @@ export function $$executeClientRpc(hashId) {
|
|
|
61
62
|
if (isServer) {
|
|
62
63
|
const store = getServerStore();
|
|
63
64
|
if (store) {
|
|
64
|
-
const functionCache = store.get(
|
|
65
|
+
const functionCache = store.get(SERVER_FUNCTION_DATA_KEY);
|
|
65
66
|
if (functionCache?.[hashId]) {
|
|
66
67
|
const match = findLooseCacheMatch(functionCache[hashId], args[0]);
|
|
67
68
|
if (match)
|
|
@@ -71,7 +72,7 @@ export function $$executeClientRpc(hashId) {
|
|
|
71
72
|
return;
|
|
72
73
|
}
|
|
73
74
|
ensureCacheInitialized();
|
|
74
|
-
const serverFunctionData = _clientCache?.
|
|
75
|
+
const serverFunctionData = _clientCache?.[SERVER_FUNCTION_DATA_KEY]?.[hashId];
|
|
75
76
|
const match = findLooseCacheMatch(serverFunctionData ?? {}, args[0]);
|
|
76
77
|
return match ? match.data : undefined;
|
|
77
78
|
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
import type { Component } from "solid-js";
|
|
3
|
+
import type { RuntimeEnv } from "./types.js";
|
|
4
|
+
import type { GuardFn } from "./guards.js";
|
|
5
|
+
import type { ManifestSnapshot } from "./manifest.js";
|
|
6
|
+
type ServerLoader = (args: {
|
|
7
|
+
params: Record<string, string>;
|
|
8
|
+
request: Request;
|
|
9
|
+
}) => unknown | Promise<unknown>;
|
|
10
|
+
type CreateServerAppOptions = {
|
|
11
|
+
App: Component;
|
|
12
|
+
env: RuntimeEnv;
|
|
13
|
+
preloadActiveClientRoute: (path: string) => unknown | Promise<unknown>;
|
|
14
|
+
serverLoaderRegistry: Map<string, ServerLoader>;
|
|
15
|
+
serverGuardRegistry: Map<string, (() => Promise<GuardFn[]>)[]>;
|
|
16
|
+
registerServerRoutes: (app: Hono) => void;
|
|
17
|
+
getManifestSnapshot: () => ManifestSnapshot;
|
|
18
|
+
loadManifestAndTemplate: () => Promise<void>;
|
|
19
|
+
};
|
|
20
|
+
export declare function createServerApp(options: CreateServerAppOptions): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=app.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../../src/runtime/server/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAM1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtD,KAAK,YAAY,GAAG,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAE/G,KAAK,sBAAsB,GAAG;IAC5B,GAAG,EAAE,SAAS,CAAC;IACf,GAAG,EAAE,UAAU,CAAC;IAChB,wBAAwB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACvE,oBAAoB,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAChD,mBAAmB,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IAC/D,oBAAoB,EAAE,CAAC,GAAG,EAAE,IAAI,KAAK,IAAI,CAAC;IAC1C,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;IAC5C,uBAAuB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9C,CAAC;AAEF,wBAAgB,eAAe,CAAC,OAAO,EAAE,sBAAsB,8EAkB9D"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
import { compress } from "hono/compress";
|
|
3
|
+
import { ssrStorage } from "../context.js";
|
|
4
|
+
import { HONO_CONTEXT_KEY } from "../shared/constants.js";
|
|
5
|
+
import { registerAssetRoutes } from "./assets.js";
|
|
6
|
+
import { registerRpcRoute } from "./rpc.js";
|
|
7
|
+
import { createRenderRequestHandler } from "./render-request.jsx";
|
|
8
|
+
export function createServerApp(options) {
|
|
9
|
+
const app = new Hono();
|
|
10
|
+
app.use("*", compress());
|
|
11
|
+
app.use("*", async (c, next) => {
|
|
12
|
+
const store = new Map();
|
|
13
|
+
store.set(HONO_CONTEXT_KEY, c);
|
|
14
|
+
return await ssrStorage.run(store, next);
|
|
15
|
+
});
|
|
16
|
+
registerAssetRoutes(app, options.env);
|
|
17
|
+
registerRpcRoute(app);
|
|
18
|
+
options.registerServerRoutes(app);
|
|
19
|
+
app.get("*", createRenderRequestHandler(options));
|
|
20
|
+
return app;
|
|
21
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Context, Hono } from "hono";
|
|
2
|
+
import type { RuntimeEnv } from "./types.js";
|
|
3
|
+
export declare function registerAssetRoutes(app: Hono, env: RuntimeEnv): void;
|
|
4
|
+
export declare function setDevResponseCacheHeaders(c: Context, env: RuntimeEnv): void;
|
|
5
|
+
//# sourceMappingURL=assets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../../src/runtime/server/assets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAwB7C,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,QAqC7D;AAED,wBAAgB,0BAA0B,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,QAGrE"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { serveStatic } from "@hono/node-server/serve-static";
|
|
2
|
+
function setNoCacheHeaders(c) {
|
|
3
|
+
c.header("Cache-Control", "no-cache, no-store, must-revalidate");
|
|
4
|
+
c.header("Pragma", "no-cache");
|
|
5
|
+
c.header("Expires", "0");
|
|
6
|
+
}
|
|
7
|
+
async function proxyDevAsset(c, targetUrl, notFoundMessage, failureMessage) {
|
|
8
|
+
try {
|
|
9
|
+
const response = await fetch(targetUrl);
|
|
10
|
+
if (!response.ok)
|
|
11
|
+
return c.text(notFoundMessage, 404);
|
|
12
|
+
const contentType = response.headers.get("content-type");
|
|
13
|
+
if (contentType)
|
|
14
|
+
c.header("content-type", contentType);
|
|
15
|
+
setNoCacheHeaders(c);
|
|
16
|
+
return c.body(await response.arrayBuffer());
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return c.text(failureMessage, 500);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export function registerAssetRoutes(app, env) {
|
|
23
|
+
if (env.isDev) {
|
|
24
|
+
app.get("/assets/*", (c) => proxyDevAsset(c, `${env.devServerUrl}${c.req.path}`, "asset not found in Rspack memory", "failed to connect to Rspack dev server asset bridge"));
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
app.use("/assets/*", async (c, next) => {
|
|
28
|
+
await next();
|
|
29
|
+
if (c.res.ok)
|
|
30
|
+
c.res.headers.set("Cache-Control", "public, max-age=31536000, immutable");
|
|
31
|
+
});
|
|
32
|
+
app.use("/assets/*", serveStatic({
|
|
33
|
+
root: env.clientDistPath,
|
|
34
|
+
}));
|
|
35
|
+
}
|
|
36
|
+
app.use(async (c, next) => {
|
|
37
|
+
const requestPath = c.req.path;
|
|
38
|
+
if (env.isDev && requestPath.includes(".hot-update.")) {
|
|
39
|
+
return proxyDevAsset(c, `${env.devServerUrl}${requestPath}`, "hot update not found", "failed to fetch hot update");
|
|
40
|
+
}
|
|
41
|
+
await next();
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
export function setDevResponseCacheHeaders(c, env) {
|
|
45
|
+
if (!env.isDev)
|
|
46
|
+
return;
|
|
47
|
+
setNoCacheHeaders(c);
|
|
48
|
+
}
|