alabjs 0.2.6 → 0.4.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/analytics/handler.d.ts +5 -1
- package/dist/analytics/handler.d.ts.map +1 -1
- package/dist/analytics/handler.js +14 -10
- package/dist/analytics/handler.js.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/client/hooks.d.ts +9 -1
- package/dist/client/hooks.d.ts.map +1 -1
- package/dist/client/hooks.js +26 -2
- package/dist/client/hooks.js.map +1 -1
- package/dist/commands/build.d.ts.map +1 -1
- package/dist/commands/build.js +279 -65
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +225 -2
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/start.js +1 -1
- package/dist/commands/start.js.map +1 -1
- package/dist/components/Image.d.ts +0 -12
- package/dist/components/Image.d.ts.map +1 -1
- package/dist/components/Image.js +2 -29
- package/dist/components/Image.js.map +1 -1
- package/dist/components/ImageServer.d.ts +20 -0
- package/dist/components/ImageServer.d.ts.map +1 -0
- package/dist/components/ImageServer.js +37 -0
- package/dist/components/ImageServer.js.map +1 -0
- package/dist/components/Link.d.ts +16 -0
- package/dist/components/Link.d.ts.map +1 -1
- package/dist/components/Link.js +10 -0
- package/dist/components/Link.js.map +1 -1
- package/dist/components/index.d.ts +3 -3
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +2 -2
- package/dist/components/index.js.map +1 -1
- package/dist/live/broadcaster.d.ts +64 -0
- package/dist/live/broadcaster.d.ts.map +1 -0
- package/dist/live/broadcaster.js +78 -0
- package/dist/live/broadcaster.js.map +1 -0
- package/dist/live/registry.d.ts +34 -0
- package/dist/live/registry.d.ts.map +1 -0
- package/dist/live/registry.js +33 -0
- package/dist/live/registry.js.map +1 -0
- package/dist/live/renderer.d.ts +22 -0
- package/dist/live/renderer.d.ts.map +1 -0
- package/dist/live/renderer.js +45 -0
- package/dist/live/renderer.js.map +1 -0
- package/dist/router/manifest.d.ts +1 -1
- package/dist/router/manifest.d.ts.map +1 -1
- package/dist/server/app.d.ts.map +1 -1
- package/dist/server/app.js +339 -43
- package/dist/server/app.js.map +1 -1
- package/dist/server/cache.d.ts.map +1 -1
- package/dist/server/cache.js +23 -1
- package/dist/server/cache.js.map +1 -1
- package/dist/server/csrf.d.ts.map +1 -1
- package/dist/server/csrf.js +5 -0
- package/dist/server/csrf.js.map +1 -1
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/revalidate.d.ts.map +1 -1
- package/dist/server/revalidate.js +3 -0
- package/dist/server/revalidate.js.map +1 -1
- package/dist/ssr/html.d.ts.map +1 -1
- package/dist/ssr/html.js +15 -0
- package/dist/ssr/html.js.map +1 -1
- package/dist/ssr/ppr.d.ts.map +1 -1
- package/dist/ssr/ppr.js +2 -1
- package/dist/ssr/ppr.js.map +1 -1
- package/package.json +8 -3
- package/src/analytics/handler.ts +15 -10
- package/src/cli.ts +3 -1
- package/src/client/hooks.ts +30 -2
- package/src/commands/build.ts +316 -69
- package/src/commands/dev.ts +246 -3
- package/src/commands/start.ts +1 -1
- package/src/components/Image.tsx +2 -35
- package/src/components/ImageServer.ts +43 -0
- package/src/components/Link.tsx +20 -0
- package/src/components/index.ts +3 -3
- package/src/live/broadcaster.ts +83 -0
- package/src/live/registry.ts +56 -0
- package/src/live/renderer.ts +54 -0
- package/src/router/manifest.ts +1 -1
- package/src/server/app.ts +369 -44
- package/src/server/cache.ts +23 -1
- package/src/server/csrf.ts +5 -0
- package/src/server/index.ts +1 -0
- package/src/server/revalidate.ts +3 -0
- package/src/ssr/html.ts +15 -0
- package/src/ssr/ppr.ts +2 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -17,8 +17,12 @@ export declare function handleVitalsBeacon(req: IncomingMessage, res: ServerResp
|
|
|
17
17
|
* GET /_alabjs/analytics
|
|
18
18
|
*
|
|
19
19
|
* Returns a JSON snapshot of all collected metrics.
|
|
20
|
-
*
|
|
20
|
+
* Always requires Authorization: Bearer <ALAB_ANALYTICS_SECRET>.
|
|
21
21
|
* Falls back to ALAB_REVALIDATE_SECRET if ALAB_ANALYTICS_SECRET is unset.
|
|
22
|
+
*
|
|
23
|
+
* If neither env var is set the endpoint returns 401 — the endpoint is
|
|
24
|
+
* intentionally closed by default to prevent information leaks in production
|
|
25
|
+
* deployments that forget to set an analytics secret.
|
|
22
26
|
*/
|
|
23
27
|
export declare function handleAnalyticsDashboard(req: IncomingMessage, res: ServerResponse): void;
|
|
24
28
|
//# sourceMappingURL=handler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/analytics/handler.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAejE;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,IAAI,CAAC,CA6Cf;AAED
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/analytics/handler.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAejE;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,IAAI,CAAC,CA6Cf;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,GAClB,IAAI,CAqBN"}
|
|
@@ -63,21 +63,25 @@ export async function handleVitalsBeacon(req, res) {
|
|
|
63
63
|
* GET /_alabjs/analytics
|
|
64
64
|
*
|
|
65
65
|
* Returns a JSON snapshot of all collected metrics.
|
|
66
|
-
*
|
|
66
|
+
* Always requires Authorization: Bearer <ALAB_ANALYTICS_SECRET>.
|
|
67
67
|
* Falls back to ALAB_REVALIDATE_SECRET if ALAB_ANALYTICS_SECRET is unset.
|
|
68
|
+
*
|
|
69
|
+
* If neither env var is set the endpoint returns 401 — the endpoint is
|
|
70
|
+
* intentionally closed by default to prevent information leaks in production
|
|
71
|
+
* deployments that forget to set an analytics secret.
|
|
68
72
|
*/
|
|
69
73
|
export function handleAnalyticsDashboard(req, res) {
|
|
70
74
|
const secret = process.env["ALAB_ANALYTICS_SECRET"] ??
|
|
71
75
|
process.env["ALAB_REVALIDATE_SECRET"];
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
76
|
+
const auth = req.headers["authorization"] ?? "";
|
|
77
|
+
const token = auth.startsWith("Bearer ") ? auth.slice(7) : "";
|
|
78
|
+
if (!secret || token !== secret) {
|
|
79
|
+
res.statusCode = 401;
|
|
80
|
+
res.setHeader("content-type", "application/json");
|
|
81
|
+
res.end(JSON.stringify({
|
|
82
|
+
error: "Unauthorized. Set ALAB_ANALYTICS_SECRET and pass Authorization: Bearer <secret>.",
|
|
83
|
+
}));
|
|
84
|
+
return;
|
|
81
85
|
}
|
|
82
86
|
res.statusCode = 200;
|
|
83
87
|
res.setHeader("content-type", "application/json; charset=utf-8");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../src/analytics/handler.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,YAAY,EAAE,WAAW,EAAmB,MAAM,YAAY,CAAC;AAExE,MAAM,YAAY,GAAG,IAAI,GAAG,CAAS,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;AAE3E,mDAAmD;AACnD,SAAS,QAAQ,CAAC,GAAoB;IACpC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9C,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACrE,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,GAAoB,EACpB,GAAmB;IAEnB,GAAG,CAAC,SAAS,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;IAElD,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC7B,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,eAAe,CAAC,CAAC;QAC/D,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,cAAc,CAAC,CAAC;QAC9D,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;QACrB,GAAG,CAAC,GAAG,EAAE,CAAC;QACV,OAAO;IACT,CAAC;IAED,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QAC1B,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;QACrB,GAAG,CAAC,GAAG,EAAE,CAAC;QACV,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC;QAChC,yEAAyE;QACzE,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACxC,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QAEzD,KAAK,MAAM,EAAE,IAAI,MAAM,EAAE,CAAC;YACxB,IACE,EAAE,KAAK,IAAI;gBACX,OAAO,EAAE,KAAK,QAAQ;gBACtB,MAAM,IAAI,EAAE,IAAI,OAAO,EAAE,CAAC,IAAI,KAAK,QAAQ;gBAC3C,OAAO,IAAI,EAAE,IAAI,OAAO,EAAE,CAAC,KAAK,KAAK,QAAQ;gBAC7C,OAAO,IAAI,EAAE,IAAI,OAAO,EAAE,CAAC,KAAK,KAAK,QAAQ;gBAC7C,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EACzB,CAAC;gBACD,YAAY,CACV,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAS,wBAAwB;gBACvD,EAAE,CAAC,IAAkB,EACrB,EAAE,CAAC,KAAK,CACT,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,yDAAyD;IAC3D,CAAC;IAED,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;IACrB,GAAG,CAAC,GAAG,EAAE,CAAC;AACZ,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../src/analytics/handler.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -42,7 +42,7 @@ switch (command) {
|
|
|
42
42
|
break;
|
|
43
43
|
}
|
|
44
44
|
case "start":
|
|
45
|
-
await import("./commands/start.js").then((m) => m.start({ cwd }));
|
|
45
|
+
await import("./commands/start.js").then((m) => m.start({ cwd, port: Number(values["port"]) }));
|
|
46
46
|
break;
|
|
47
47
|
case "info":
|
|
48
48
|
await import("./commands/info.js").then((m) => m.info({ cwd }));
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;GAOG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACxC,gBAAgB,EAAE,IAAI;IACtB,OAAO,EAAE;QACP,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE;QACrD,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE;QAC9C,gBAAgB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE;QACrD,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACxB,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE;QAC5C,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE;QAC1C,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE;QACvC,yFAAyF;QACzF,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;KACpC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,OAAO,GAAG,KAAK,CAAC,GAAG,WAAW,CAAC;AACtC,0DAA0D;AAC1D,4EAA4E;AAC5E,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;AAElF,QAAQ,OAAO,EAAE,CAAC;IAChB,KAAK,KAAK;QACR,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;QAC9D,MAAM;IACR,KAAK,OAAO,CAAC,CAAC,CAAC;QACb,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QACjC,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAC7C,CAAC,CAAC,KAAK,CAAC;YACN,GAAG;YACH,aAAa,EAAE,MAAM,CAAC,gBAAgB,CAAC;YACvC,IAAI,EAAE,SAAS,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK;YACzC,OAAO,EAAE,MAAM,CAAC,SAAS,CAAC;SAC3B,CAAC,CACH,CAAC;QACF,MAAM;IACR,CAAC;IACD,KAAK,OAAO;QACV,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/client/hooks.d.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import type { ServerFn, InferServerOutput, RouteParams, InferServerPath } from "../types/index.js";
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* Clear the server-side promise cache between SSR renders.
|
|
4
|
+
*
|
|
5
|
+
* @internal — Called by Alab's dev and production SSR entry points before each
|
|
6
|
+
* `renderToPipeableStream` call. If you build a custom SSR integration, you
|
|
7
|
+
* MUST call this before rendering each page; failing to do so causes stale
|
|
8
|
+
* promises from a previous request to be returned by `useServerData`, resulting
|
|
9
|
+
* in wrong data being served to subsequent visitors.
|
|
10
|
+
*/
|
|
3
11
|
export declare function _clearALabSSRCache(): void;
|
|
4
12
|
/**
|
|
5
13
|
* Fetch server data with full type inference from a `ServerFn`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/client/hooks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAoBnG
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/client/hooks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAoBnG;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAC7D,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,WAAW,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,GACvC,iBAAiB,CAAC,CAAC,CAAC,CAkCtB;AAiCD,MAAM,WAAW,kBAAkB,CAAC,MAAM,EAAE,KAAK;IAC/C;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/C,kEAAkE;IAClE,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;CACtD;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAC3D,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,kBAAkB,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,QAAQ,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;6CAG/D,CAAC,4BAkBI,IAAI;UAyDzB,uBAAS,SAAS;IACtC,4EAA4E;;;WAGtD,KAAK,GAAG,SAAS;IACvC,mFAAmF;;;;;;EAOtF;AAID,qFAAqF;AACrF,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE7D,MAAM,WAAW,aAAa;IAC5B,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,oDAAoD;IACpD,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,sFAAsF;IACtF,IAAI,EAAE,CAAC,GAAG,SAAS,CAAC;IACpB,2DAA2D;IAC3D,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,aAAa,CAAC;IAC1B,gDAAgD;IAChD,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,MAAM,CAAC,CAAC,GAAG,OAAO,EAChC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,aAAkB,GAC1B,YAAY,CAAC,CAAC,CAAC,CA4DjB"}
|
package/dist/client/hooks.js
CHANGED
|
@@ -15,7 +15,15 @@ function _cacheSet(key, value) {
|
|
|
15
15
|
}
|
|
16
16
|
_promiseCache.set(key, value);
|
|
17
17
|
}
|
|
18
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* Clear the server-side promise cache between SSR renders.
|
|
20
|
+
*
|
|
21
|
+
* @internal — Called by Alab's dev and production SSR entry points before each
|
|
22
|
+
* `renderToPipeableStream` call. If you build a custom SSR integration, you
|
|
23
|
+
* MUST call this before rendering each page; failing to do so causes stale
|
|
24
|
+
* promises from a previous request to be returned by `useServerData`, resulting
|
|
25
|
+
* in wrong data being served to subsequent visitors.
|
|
26
|
+
*/
|
|
19
27
|
export function _clearALabSSRCache() {
|
|
20
28
|
_promiseCache.clear();
|
|
21
29
|
}
|
|
@@ -40,6 +48,14 @@ export function _clearALabSSRCache() {
|
|
|
40
48
|
* ```
|
|
41
49
|
*/
|
|
42
50
|
export function useServerData(fnName, params) {
|
|
51
|
+
// During PPR build-time pre-rendering there is no server running, so we
|
|
52
|
+
// must not make network calls. Return an empty array so the component can
|
|
53
|
+
// render its static shell; data-dependent children should be inside
|
|
54
|
+
// <Dynamic> which renders a placeholder hole in PPR mode anyway.
|
|
55
|
+
if (typeof process !== "undefined" &&
|
|
56
|
+
process.env["ALAB_PPR_PRERENDER"] === "1") {
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
43
59
|
const searchParams = params
|
|
44
60
|
? new URLSearchParams(params).toString()
|
|
45
61
|
: "";
|
|
@@ -106,9 +122,17 @@ export function useMutation(fnName, options) {
|
|
|
106
122
|
startTransition(() => {
|
|
107
123
|
void (async () => {
|
|
108
124
|
try {
|
|
125
|
+
// Read the CSRF token from the cookie (set by the server on any SSR
|
|
126
|
+
// page response) and echo it as x-csrf-token for double-submit protection.
|
|
127
|
+
const csrfToken = typeof document !== "undefined"
|
|
128
|
+
? document.cookie.match(/alab-csrf=([^;]+)/)?.[1] ?? ""
|
|
129
|
+
: "";
|
|
109
130
|
const r = await fetch(`/_alabjs/fn/${fnName}`, {
|
|
110
131
|
method: "POST",
|
|
111
|
-
headers: {
|
|
132
|
+
headers: {
|
|
133
|
+
"content-type": "application/json",
|
|
134
|
+
...(csrfToken ? { "x-csrf-token": csrfToken } : {}),
|
|
135
|
+
},
|
|
112
136
|
body: JSON.stringify(input),
|
|
113
137
|
});
|
|
114
138
|
// Zod validation error from server
|
package/dist/client/hooks.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/client/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,aAAa,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAGjG,8BAA8B;AAC9B,+EAA+E;AAC/E,+EAA+E;AAC/E,0EAA0E;AAC1E,6EAA6E;AAC7E,8EAA8E;AAC9E,oDAAoD;AACpD,MAAM,UAAU,GAAG,GAAG,CAAC;AACvB,MAAM,aAAa,GAAG,IAAI,GAAG,EAA4B,CAAC;AAE1D,SAAS,SAAS,CAAC,GAAW,EAAE,KAAuB;IACrD,IAAI,aAAa,CAAC,IAAI,IAAI,UAAU,EAAE,CAAC;QACrC,2DAA2D;QAC3D,aAAa,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAM,CAAC,CAAC;IAC3D,CAAC;IACD,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AAChC,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/client/hooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAUA,UAAU,YAAY;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,6DAA6D;IAC7D,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IACrB,yEAAyE;IACzE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAsED,wBAAsB,KAAK,CAAC,EAAE,GAAG,EAAE,aAAqB,EAAE,IAAY,EAAE,OAAe,EAAE,EAAE,YAAY,iBAiHtG"}
|
package/dist/commands/build.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { build as viteBuild } from "vite";
|
|
2
|
-
import { resolve } from "node:path";
|
|
2
|
+
import { resolve, relative, isAbsolute } from "node:path";
|
|
3
|
+
import { pathToFileURL } from "node:url";
|
|
3
4
|
import { spawn, execSync } from "node:child_process";
|
|
4
5
|
import { existsSync, writeFileSync, readFileSync, mkdirSync } from "node:fs";
|
|
5
6
|
import { loadUserConfig } from "../config.js";
|
|
@@ -72,12 +73,13 @@ async function buildSpa(cwd) {
|
|
|
72
73
|
export async function build({ cwd, skipTypecheck = false, mode = "ssr", analyze = false }) {
|
|
73
74
|
if (mode === "spa") {
|
|
74
75
|
console.log(" alab building SPA (client-only)...\n");
|
|
75
|
-
|
|
76
|
+
await buildSpa(cwd);
|
|
77
|
+
// SPA has no route manifest, but still type-check after the build so any
|
|
78
|
+
// generated types from the Vite plugin are available to tsc.
|
|
76
79
|
if (!skipTypecheck) {
|
|
77
80
|
console.log(" alab type-checking...");
|
|
78
|
-
|
|
81
|
+
await runTypecheck(cwd);
|
|
79
82
|
}
|
|
80
|
-
await Promise.all(tasks);
|
|
81
83
|
return;
|
|
82
84
|
}
|
|
83
85
|
console.log(" alab building for production...\n");
|
|
@@ -116,32 +118,46 @@ export async function build({ cwd, skipTypecheck = false, mode = "ssr", analyze
|
|
|
116
118
|
console.warn(" alab warning: install rolldown-plugin-visualizer or rollup-plugin-visualizer to enable --analyze.");
|
|
117
119
|
}
|
|
118
120
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
121
|
+
await viteBuild({
|
|
122
|
+
root: cwd,
|
|
123
|
+
plugins: [
|
|
124
|
+
(await import("alabjs-vite-plugin")).alabPlugin({ mode: "build" }),
|
|
125
|
+
...(visualizerPlugin ? [visualizerPlugin] : []),
|
|
126
|
+
],
|
|
127
|
+
build: {
|
|
128
|
+
// Output client assets to .alabjs/dist/client/ so the production server's
|
|
129
|
+
// static handler (which serves from distDir/client/) can find them.
|
|
130
|
+
outDir: resolve(cwd, ".alabjs/dist/client"),
|
|
131
|
+
manifest: true,
|
|
132
|
+
ssrManifest: true,
|
|
133
|
+
rolldownOptions: {
|
|
134
|
+
// In SSR mode, we don't use an index.html as the entry point.
|
|
135
|
+
// Instead, we bundle the virtual client module as the main browser asset.
|
|
136
|
+
input: "/@alabjs/client",
|
|
134
137
|
},
|
|
135
|
-
}
|
|
136
|
-
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
const distDir = resolve(cwd, ".alabjs/dist");
|
|
141
|
+
// Scan the app/ directory with the Rust router, normalize paths, and write
|
|
142
|
+
// route-manifest.json. Must run before writeBuildId (hash) and buildPPRShells.
|
|
143
|
+
// Also writes .alabjs/routes.d.ts — type-checking runs AFTER this so tsc can
|
|
144
|
+
// resolve the AlabRoutes union that routes.d.ts exports.
|
|
145
|
+
const manifest = await buildRouteManifest(cwd, distDir);
|
|
146
|
+
// Type-check after route types are written so `AlabRoutes` is resolvable.
|
|
137
147
|
if (!skipTypecheck) {
|
|
138
148
|
console.log(" alab type-checking...");
|
|
139
|
-
|
|
149
|
+
await runTypecheck(cwd);
|
|
140
150
|
}
|
|
141
|
-
|
|
142
|
-
//
|
|
143
|
-
//
|
|
144
|
-
|
|
151
|
+
// Validate all RouteLink/Link/navigate path references against the manifest.
|
|
152
|
+
// Runs after manifest generation but before the SSR bundle so type-safe route
|
|
153
|
+
// errors abort the build early with clear file + offset info.
|
|
154
|
+
await checkRouteReferences(cwd, manifest);
|
|
155
|
+
// Compile all app pages, layouts, and server functions to .alabjs/dist/server/.
|
|
156
|
+
// Must run after buildRouteManifest so we have the entry list, and before
|
|
157
|
+
// buildPPRShells which imports the compiled modules.
|
|
158
|
+
await buildSsrBundle(cwd, distDir, manifest);
|
|
159
|
+
// Write a stable build ID for skew protection (must run after the route
|
|
160
|
+
// manifest is in place for the content-hash fallback path).
|
|
145
161
|
await writeBuildId(distDir, cwd);
|
|
146
162
|
await buildPPRShells(distDir, cwd);
|
|
147
163
|
// Bundle the offline service worker as a separate iife chunk.
|
|
@@ -206,46 +222,58 @@ async function buildPPRShells(distDir, cwd) {
|
|
|
206
222
|
const pageRoutes = manifest.routes.filter((r) => r.kind === "page");
|
|
207
223
|
const pprCacheDir = resolve(cwd, PPR_CACHE_SUBDIR);
|
|
208
224
|
let count = 0;
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
225
|
+
// Signal to useServerData that it must not make network calls — return
|
|
226
|
+
// empty placeholders instead so components can render their static shell.
|
|
227
|
+
process.env["ALAB_PPR_PRERENDER"] = "1";
|
|
228
|
+
try {
|
|
229
|
+
for (const route of pageRoutes) {
|
|
230
|
+
// esbuild compiles .tsx/.ts → .js; use the compiled path.
|
|
231
|
+
const modulePath = resolve(distDir, "server", route.file.replace(/\.(tsx?)$/, ".js"));
|
|
232
|
+
if (!existsSync(modulePath))
|
|
233
|
+
continue;
|
|
234
|
+
// Dynamic import — on Windows absolute paths need a file:// URL.
|
|
235
|
+
const mod = await import(pathToFileURL(modulePath).href);
|
|
236
|
+
if (mod.ppr !== true)
|
|
237
|
+
continue;
|
|
238
|
+
if (typeof mod.default !== "function") {
|
|
239
|
+
console.warn(` alab ppr: ${route.file} has no default export — skipping.`);
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
// Load layout modules (outermost → innermost).
|
|
243
|
+
const layoutPaths = findBuildLayoutFiles(route.file, distDir);
|
|
244
|
+
const layoutMods = await Promise.all(layoutPaths.map((p) => import(pathToFileURL(resolve(distDir, "server", p)).href)));
|
|
245
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
246
|
+
const layouts = layoutMods.map((m) => m.default).filter((c) => typeof c === "function");
|
|
247
|
+
try {
|
|
248
|
+
await preRenderPPRShell({
|
|
249
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
250
|
+
Page: mod.default,
|
|
251
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
252
|
+
layouts: layouts,
|
|
253
|
+
shellOpts: {
|
|
254
|
+
metadata: mod.metadata ?? {},
|
|
255
|
+
paramsJson: "{}",
|
|
256
|
+
searchParamsJson: "{}",
|
|
257
|
+
routeFile: route.file,
|
|
258
|
+
// PPR shells are static snapshots — client mounts via CSR (createRoot)
|
|
259
|
+
// rather than hydration to avoid mismatches with the pre-rendered HTML.
|
|
260
|
+
ssr: false,
|
|
261
|
+
layoutsJson: JSON.stringify(layoutPaths.map(p => p.replace(/\.js$/, ".tsx"))),
|
|
262
|
+
},
|
|
263
|
+
pprCacheDir,
|
|
264
|
+
routePath: route.path,
|
|
265
|
+
});
|
|
266
|
+
count++;
|
|
267
|
+
}
|
|
268
|
+
catch (err) {
|
|
269
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
270
|
+
console.warn(` alab ppr: failed to pre-render ${route.path}: ${msg}`);
|
|
271
|
+
}
|
|
247
272
|
}
|
|
248
273
|
}
|
|
274
|
+
finally {
|
|
275
|
+
delete process.env["ALAB_PPR_PRERENDER"];
|
|
276
|
+
}
|
|
249
277
|
if (count > 0) {
|
|
250
278
|
console.log(` alab ppr → ${count} shell${count === 1 ? "" : "s"} written to ${PPR_CACHE_SUBDIR}`);
|
|
251
279
|
}
|
|
@@ -363,6 +391,189 @@ async function buildFederationExposes(cwd, distClientAlab, appName, exposes, sha
|
|
|
363
391
|
};
|
|
364
392
|
writeFileSync(resolve(distClientAlab, "federation-manifest.json"), JSON.stringify(manifest, null, 2), "utf8");
|
|
365
393
|
}
|
|
394
|
+
/**
|
|
395
|
+
* Validate all `<RouteLink to>`, `<Link href>`, and `navigate()` path
|
|
396
|
+
* references in `app/` against the compiled route manifest.
|
|
397
|
+
*
|
|
398
|
+
* Fails the build with a formatted error list when unknown paths or literal
|
|
399
|
+
* bracket segments are found. Gracefully skips when the napi binary is absent.
|
|
400
|
+
*/
|
|
401
|
+
async function checkRouteReferences(cwd, manifest) {
|
|
402
|
+
const appDir = resolve(cwd, "app");
|
|
403
|
+
let napi;
|
|
404
|
+
try {
|
|
405
|
+
const mod = await import("@alabjs/compiler");
|
|
406
|
+
napi = (mod.default ?? mod);
|
|
407
|
+
if (typeof napi.checkRouteRefs !== "function")
|
|
408
|
+
return; // napi binary predates route checker
|
|
409
|
+
}
|
|
410
|
+
catch {
|
|
411
|
+
return; // napi binary not available — skip silently
|
|
412
|
+
}
|
|
413
|
+
const manifestJson = JSON.stringify(manifest);
|
|
414
|
+
const violationsJson = napi.checkRouteRefs(appDir, manifestJson);
|
|
415
|
+
const violations = JSON.parse(violationsJson);
|
|
416
|
+
if (violations.length === 0)
|
|
417
|
+
return;
|
|
418
|
+
const lines = [
|
|
419
|
+
`\n alab ${violations.length} route violation${violations.length === 1 ? "" : "s"} found:\n`,
|
|
420
|
+
];
|
|
421
|
+
for (const v of violations) {
|
|
422
|
+
const relFile = relative(cwd, v.file);
|
|
423
|
+
const kindLabel = v.kind === "unknown_path"
|
|
424
|
+
? "unknown path"
|
|
425
|
+
: "literal bracket — use params prop";
|
|
426
|
+
lines.push(` ✗ ${relFile} "${v.path}" (${kindLabel})`);
|
|
427
|
+
if (v.suggestion) {
|
|
428
|
+
lines.push(` → suggestion: ${v.suggestion}`);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
lines.push("");
|
|
432
|
+
console.error(lines.join("\n"));
|
|
433
|
+
throw new Error(`[alabjs] Build failed: ${violations.length} route violation(s). Fix the paths above.`);
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Scan `app/` with the Rust router napi, normalize absolute file paths to
|
|
437
|
+
* cwd-relative, and write `route-manifest.json` to `distDir`.
|
|
438
|
+
*
|
|
439
|
+
* Returns the in-memory manifest so callers can use it immediately without
|
|
440
|
+
* reading the file back from disk.
|
|
441
|
+
*/
|
|
442
|
+
async function buildRouteManifest(cwd, distDir) {
|
|
443
|
+
const appDir = resolve(cwd, "app");
|
|
444
|
+
let manifest = { routes: [] };
|
|
445
|
+
try {
|
|
446
|
+
const mod = await import("@alabjs/compiler");
|
|
447
|
+
const napi = (mod.default ?? mod);
|
|
448
|
+
const json = napi.buildRoutes(appDir);
|
|
449
|
+
manifest = JSON.parse(json);
|
|
450
|
+
// The Rust scanner stores absolute paths; normalize to cwd-relative so the
|
|
451
|
+
// production server can construct `distDir/server/<file>` paths correctly.
|
|
452
|
+
for (const route of manifest.routes) {
|
|
453
|
+
if (isAbsolute(route.file)) {
|
|
454
|
+
route.file = relative(cwd, route.file);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
catch {
|
|
459
|
+
console.warn(" alab warning: Rust compiler unavailable — route manifest will be empty.\n" +
|
|
460
|
+
" Run `cargo build --release -p alab-napi && bash scripts/copy-napi-binary.sh`.");
|
|
461
|
+
}
|
|
462
|
+
mkdirSync(distDir, { recursive: true });
|
|
463
|
+
writeFileSync(resolve(distDir, "route-manifest.json"), JSON.stringify(manifest, null, 2), "utf8");
|
|
464
|
+
const pages = manifest.routes.filter((r) => r.kind === "page").length;
|
|
465
|
+
const apis = manifest.routes.filter((r) => r.kind === "api").length;
|
|
466
|
+
console.log(` alab routes → ${pages} page(s), ${apis} api route(s)`);
|
|
467
|
+
// Emit auto-generated route types so <RouteLink to="..."> and navigate() are
|
|
468
|
+
// type-safe without any manual setup. Written to .alabjs/routes.d.ts.
|
|
469
|
+
writeRouteTypes(manifest, distDir);
|
|
470
|
+
return manifest;
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Write `.alabjs/routes.d.ts` containing the `AlabRoutes` union type and
|
|
474
|
+
* a typed `navigate` overload, auto-derived from the route manifest.
|
|
475
|
+
*
|
|
476
|
+
* Example output:
|
|
477
|
+
* ```ts
|
|
478
|
+
* export type AlabRoutes = "/" | "/about" | `/users/${string}`;
|
|
479
|
+
* ```
|
|
480
|
+
*
|
|
481
|
+
* Add `".alabjs/routes.d.ts"` to `tsconfig.json` `include` to enable
|
|
482
|
+
* type-checking on `<RouteLink to>`, `<Link href>`, and `navigate()`.
|
|
483
|
+
*/
|
|
484
|
+
function writeRouteTypes(manifest, distDir) {
|
|
485
|
+
const pageRoutes = manifest.routes.filter((r) => r.kind === "page");
|
|
486
|
+
// Convert alab `[param]` syntax → TypeScript template literal `${string}`.
|
|
487
|
+
const routeTypes = pageRoutes.map((r) => {
|
|
488
|
+
const tsPath = r.path.replace(/\[([^\]]+)\]/g, "${string}");
|
|
489
|
+
// Static path → plain string literal; dynamic path → template literal.
|
|
490
|
+
return tsPath.includes("${") ? `\`${tsPath}\`` : JSON.stringify(tsPath);
|
|
491
|
+
});
|
|
492
|
+
const unionType = routeTypes.length > 0 ? routeTypes.join(" | ") : "string";
|
|
493
|
+
const content = [
|
|
494
|
+
"// AUTO-GENERATED by `alab build` — do not edit manually.",
|
|
495
|
+
"// Add \".alabjs/routes.d.ts\" to your tsconfig.json `include` array to enable",
|
|
496
|
+
"// type-checking on <RouteLink to>, <Link href>, and navigate().",
|
|
497
|
+
"",
|
|
498
|
+
`export type AlabRoutes = ${unionType};`,
|
|
499
|
+
"",
|
|
500
|
+
"declare module \"alabjs/router\" {",
|
|
501
|
+
" export function navigate(path: AlabRoutes, opts?: { replace?: boolean }): void;",
|
|
502
|
+
"}",
|
|
503
|
+
"",
|
|
504
|
+
"declare module \"alabjs/components\" {",
|
|
505
|
+
" import type { ComponentProps } from \"react\";",
|
|
506
|
+
" interface RouteLinkProps extends Omit<ComponentProps<\"a\">, \"href\"> {",
|
|
507
|
+
" to: AlabRoutes;",
|
|
508
|
+
" replace?: boolean;",
|
|
509
|
+
" }",
|
|
510
|
+
" export function RouteLink(props: RouteLinkProps): JSX.Element;",
|
|
511
|
+
" export function Link(props: RouteLinkProps): JSX.Element;",
|
|
512
|
+
"}",
|
|
513
|
+
"",
|
|
514
|
+
].join("\n");
|
|
515
|
+
writeFileSync(resolve(distDir, "routes.d.ts"), content, "utf8");
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* Compile all SSR route files to `distDir/server/` using esbuild's per-file
|
|
519
|
+
* transpilation mode.
|
|
520
|
+
*
|
|
521
|
+
* We use esbuild directly (bundled with Vite) rather than a second viteBuild
|
|
522
|
+
* call because:
|
|
523
|
+
* 1. Preserves directory structure via `outbase` without needing
|
|
524
|
+
* `preserveModules` (which hangs with some Rolldown versions).
|
|
525
|
+
* 2. `packages: "external"` externalizes all npm specifiers while inlining
|
|
526
|
+
* local relative imports — avoids Node ESM extensionless-import failures.
|
|
527
|
+
* 3. Much faster: no second Vite startup overhead.
|
|
528
|
+
*/
|
|
529
|
+
async function buildSsrBundle(cwd, distDir, manifest) {
|
|
530
|
+
const entryFiles = manifest.routes.map((r) => resolve(cwd, r.file));
|
|
531
|
+
// Include top-level middleware.ts if present.
|
|
532
|
+
const middlewarePath = resolve(cwd, "middleware.ts");
|
|
533
|
+
if (existsSync(middlewarePath))
|
|
534
|
+
entryFiles.push(middlewarePath);
|
|
535
|
+
if (entryFiles.length === 0)
|
|
536
|
+
return;
|
|
537
|
+
// Build the import.meta.env replacement object for esbuild.
|
|
538
|
+
// Node.js never defines import.meta.env (it's a Vite-only concept), so if
|
|
539
|
+
// we leave it undefined the compiled server modules throw at runtime on any
|
|
540
|
+
// reference to import.meta.env.*. We mirror exactly what Vite inlines for
|
|
541
|
+
// the client build: standard constants + ALAB_PUBLIC_* / VITE_* vars.
|
|
542
|
+
const publicEnv = {};
|
|
543
|
+
for (const [key, val] of Object.entries(process.env)) {
|
|
544
|
+
if (key.startsWith("ALAB_PUBLIC_") || key.startsWith("VITE_")) {
|
|
545
|
+
publicEnv[key] = val ?? "";
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
const metaEnv = {
|
|
549
|
+
PROD: true,
|
|
550
|
+
DEV: false,
|
|
551
|
+
SSR: true,
|
|
552
|
+
MODE: "production",
|
|
553
|
+
BASE_URL: "/",
|
|
554
|
+
...publicEnv,
|
|
555
|
+
};
|
|
556
|
+
const { build: esbuild } = await import("esbuild");
|
|
557
|
+
await esbuild({
|
|
558
|
+
entryPoints: entryFiles,
|
|
559
|
+
outbase: cwd, // preserve directory structure: app/page.tsx → server/app/page.js
|
|
560
|
+
outdir: resolve(distDir, "server"),
|
|
561
|
+
format: "esm",
|
|
562
|
+
platform: "node",
|
|
563
|
+
target: "node22",
|
|
564
|
+
bundle: true, // bundle local imports (resolves extensionless paths)
|
|
565
|
+
packages: "external", // keep all npm specifiers (react, alabjs/*…) as-is
|
|
566
|
+
jsx: "automatic",
|
|
567
|
+
jsxImportSource: "react",
|
|
568
|
+
logLevel: "warning",
|
|
569
|
+
define: {
|
|
570
|
+
// Replace the entire import.meta.env expression so property accesses,
|
|
571
|
+
// destructuring, and optional-chaining all resolve correctly at runtime.
|
|
572
|
+
"import.meta.env": JSON.stringify(metaEnv),
|
|
573
|
+
},
|
|
574
|
+
});
|
|
575
|
+
console.log(" alab SSR bundle → .alabjs/dist/server");
|
|
576
|
+
}
|
|
366
577
|
/** Compile the offline service worker to a standalone iife bundle. */
|
|
367
578
|
async function buildOfflineSw(cwd) {
|
|
368
579
|
const swEntry = new URL("../client/offline-sw.js", import.meta.url).pathname;
|
|
@@ -381,7 +592,10 @@ async function buildOfflineSw(cwd) {
|
|
|
381
592
|
fileName: () => "offline-sw.js",
|
|
382
593
|
},
|
|
383
594
|
minify: true,
|
|
384
|
-
|
|
595
|
+
// Note: do NOT set rolldownOptions.output.inlineDynamicImports here.
|
|
596
|
+
// iife format sets codeSplitting:false which already implies
|
|
597
|
+
// inlineDynamicImports:true in Rolldown. Setting it explicitly
|
|
598
|
+
// produces a warning that can cause the build to stall in Rolldown/Vite 8+.
|
|
385
599
|
},
|
|
386
600
|
});
|
|
387
601
|
}
|