@lukoweb/apitogo 0.2.52 → 0.2.54

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.
@@ -1,118 +1,132 @@
1
- import fs from "node:fs/promises";
2
- import path from "node:path";
3
- import Piscina from "piscina";
4
- import { matchPath } from "react-router";
5
- import { ProtectedRoutesSchema } from "../../config/validators/ProtectedRoutesSchema.js";
6
- import type { ZudokuConfig } from "../../config/validators/ZudokuConfig.js";
7
- import { runPluginTransformConfig } from "../../lib/core/transform-config.js";
8
- import { joinUrl } from "../../lib/util/joinUrl.js";
9
- import type { WorkerResult } from "./prerender.js";
10
-
11
- type EntryServer = typeof import("../../app/entry.server.js");
12
-
13
- export type StaticWorkerData = {
14
- template: string;
15
- distDir: string;
16
- serverConfigPath: string;
17
- entryServerPath: string;
18
- writeRedirects: boolean;
19
- };
20
-
21
- export type WorkerData = { urlPath: string };
22
-
23
- const { template, distDir, serverConfigPath, entryServerPath, writeRedirects } =
24
- Piscina.workerData as StaticWorkerData;
25
-
26
- const server: EntryServer = await import(entryServerPath);
27
- const rawConfig: ZudokuConfig = await import(serverConfigPath).then(
28
- (m) => m.default,
29
- );
30
- const config = await runPluginTransformConfig(rawConfig);
31
-
32
- const routes = server.getRoutesByConfig(config);
33
- const { basePath } = config;
34
-
35
- const renderPage = async ({ urlPath }: WorkerData): Promise<WorkerResult> => {
36
- const filename = urlPath === "/" ? "/index.html" : `${urlPath}.html`;
37
- const pathname = joinUrl(basePath, urlPath);
38
- const url = joinUrl("http://localhost", pathname);
39
- const outputPath = path.join(distDir, filename);
40
-
41
- const request = new Request(url);
42
-
43
- const protectedRoutes = ProtectedRoutesSchema.parse(config.protectedRoutes);
44
- const isProtectedRoute = protectedRoutes
45
- ? Object.keys(protectedRoutes).some((route) =>
46
- matchPath({ path: route, end: true }, urlPath),
47
- )
48
- : false;
49
-
50
- // Get the main response
51
- const response = await server.handleRequest({
52
- template,
53
- request,
54
- routes,
55
- basePath,
56
- });
57
-
58
- // Check for redirects
59
- if ([301, 302, 303, 307, 308].includes(response.status)) {
60
- const redirectTo = response.headers.get("Location") ?? "";
61
-
62
- if (writeRedirects) {
63
- const redirectHtml = `<!doctype html><script>window.location.href=${JSON.stringify(redirectTo)};</script>`;
64
- await fs.mkdir(path.dirname(outputPath), { recursive: true });
65
- await fs.writeFile(outputPath, redirectHtml);
66
- }
67
-
68
- return {
69
- outputPath,
70
- redirect: { from: pathname, to: redirectTo },
71
- statusCode: response.status,
72
- html: "",
73
- };
74
- }
75
-
76
- if (response.status >= 500) {
77
- throw new Error(
78
- `SSR failed with status ${response.status} for path: ${urlPath}`,
79
- );
80
- }
81
-
82
- // Get HTML content for file write
83
- const fileContent = response.body ? await response.text() : "";
84
-
85
- // For protected routes, do a second render with protection bypassed for search index
86
- let html = fileContent;
87
- if (isProtectedRoute) {
88
- const bypassRequest = new Request(url);
89
- const bypassResponse = await server.handleRequest({
90
- template,
91
- request: bypassRequest,
92
- routes,
93
- basePath,
94
- bypassProtection: true,
95
- });
96
-
97
- if (bypassResponse.status >= 500) {
98
- throw new Error(
99
- `SSR failed (bypass render) with status ${bypassResponse.status} for path: ${urlPath}`,
100
- );
101
- }
102
-
103
- html = bypassResponse.body ? await bypassResponse.text() : "";
104
- }
105
-
106
- // Write the file
107
- await fs.mkdir(path.dirname(outputPath), { recursive: true });
108
- await fs.writeFile(outputPath, fileContent);
109
-
110
- return {
111
- outputPath,
112
- statusCode: response.status,
113
- redirect: undefined,
114
- html,
115
- };
116
- };
117
-
118
- export default renderPage;
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import Piscina from "piscina";
4
+ import { matchPath } from "react-router";
5
+ import { ProtectedRoutesSchema } from "../../config/validators/ProtectedRoutesSchema.js";
6
+ import type { ZudokuConfig } from "../../config/validators/ZudokuConfig.js";
7
+ import { runPluginTransformConfig } from "../../lib/core/transform-config.js";
8
+ import { joinUrl } from "../../lib/util/joinUrl.js";
9
+ import type { WorkerResult } from "./prerender.js";
10
+
11
+ type EntryServer = typeof import("../../app/entry.server.js");
12
+
13
+ export type StaticWorkerData = {
14
+ template: string;
15
+ distDir: string;
16
+ serverConfigPath: string;
17
+ entryServerPath: string;
18
+ writeRedirects: boolean;
19
+ };
20
+
21
+ export type WorkerData = { urlPath: string };
22
+
23
+ const { template, distDir, serverConfigPath, entryServerPath, writeRedirects } =
24
+ Piscina.workerData as StaticWorkerData;
25
+
26
+ /**
27
+ * Pages that redirect (the account pages before sign-in, for example) render a `<Navigate>`. In a static render it
28
+ * does nothing, and React Router says so on every build; the browser does the redirect when the page loads. The
29
+ * warning only worried tenants in the deploy output (API-126), so this one message is dropped.
30
+ */
31
+ export const isStaticNavigateWarning = (args: unknown[]): boolean =>
32
+ typeof args[0] === "string" &&
33
+ args[0].includes("<Navigate> must not be used on the initial render");
34
+ // biome-ignore lint/suspicious/noConsole: this filters React Router's own console warning, it does not log.
35
+ const warn = console.warn.bind(console);
36
+ console.warn = (...args: unknown[]) => {
37
+ if (!isStaticNavigateWarning(args)) warn(...args);
38
+ };
39
+
40
+ const server: EntryServer = await import(entryServerPath);
41
+ const rawConfig: ZudokuConfig = await import(serverConfigPath).then(
42
+ (m) => m.default,
43
+ );
44
+ const config = await runPluginTransformConfig(rawConfig);
45
+
46
+ const routes = server.getRoutesByConfig(config);
47
+ const { basePath } = config;
48
+
49
+ const renderPage = async ({ urlPath }: WorkerData): Promise<WorkerResult> => {
50
+ const filename = urlPath === "/" ? "/index.html" : `${urlPath}.html`;
51
+ const pathname = joinUrl(basePath, urlPath);
52
+ const url = joinUrl("http://localhost", pathname);
53
+ const outputPath = path.join(distDir, filename);
54
+
55
+ const request = new Request(url);
56
+
57
+ const protectedRoutes = ProtectedRoutesSchema.parse(config.protectedRoutes);
58
+ const isProtectedRoute = protectedRoutes
59
+ ? Object.keys(protectedRoutes).some((route) =>
60
+ matchPath({ path: route, end: true }, urlPath),
61
+ )
62
+ : false;
63
+
64
+ // Get the main response
65
+ const response = await server.handleRequest({
66
+ template,
67
+ request,
68
+ routes,
69
+ basePath,
70
+ });
71
+
72
+ // Check for redirects
73
+ if ([301, 302, 303, 307, 308].includes(response.status)) {
74
+ const redirectTo = response.headers.get("Location") ?? "";
75
+
76
+ if (writeRedirects) {
77
+ const redirectHtml = `<!doctype html><script>window.location.href=${JSON.stringify(redirectTo)};</script>`;
78
+ await fs.mkdir(path.dirname(outputPath), { recursive: true });
79
+ await fs.writeFile(outputPath, redirectHtml);
80
+ }
81
+
82
+ return {
83
+ outputPath,
84
+ redirect: { from: pathname, to: redirectTo },
85
+ statusCode: response.status,
86
+ html: "",
87
+ };
88
+ }
89
+
90
+ if (response.status >= 500) {
91
+ throw new Error(
92
+ `SSR failed with status ${response.status} for path: ${urlPath}`,
93
+ );
94
+ }
95
+
96
+ // Get HTML content for file write
97
+ const fileContent = response.body ? await response.text() : "";
98
+
99
+ // For protected routes, do a second render with protection bypassed for search index
100
+ let html = fileContent;
101
+ if (isProtectedRoute) {
102
+ const bypassRequest = new Request(url);
103
+ const bypassResponse = await server.handleRequest({
104
+ template,
105
+ request: bypassRequest,
106
+ routes,
107
+ basePath,
108
+ bypassProtection: true,
109
+ });
110
+
111
+ if (bypassResponse.status >= 500) {
112
+ throw new Error(
113
+ `SSR failed (bypass render) with status ${bypassResponse.status} for path: ${urlPath}`,
114
+ );
115
+ }
116
+
117
+ html = bypassResponse.body ? await bypassResponse.text() : "";
118
+ }
119
+
120
+ // Write the file
121
+ await fs.mkdir(path.dirname(outputPath), { recursive: true });
122
+ await fs.writeFile(outputPath, fileContent);
123
+
124
+ return {
125
+ outputPath,
126
+ statusCode: response.status,
127
+ redirect: undefined,
128
+ html,
129
+ };
130
+ };
131
+
132
+ export default renderPage;