@lolyjs/core 0.2.0-alpha.13 → 0.2.0-alpha.15
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/README.md +99 -12
- package/dist/cli.cjs +207 -69
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +207 -69
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +207 -69
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +207 -69
- package/dist/index.js.map +1 -1
- package/dist/react/hooks.cjs +16 -6
- package/dist/react/hooks.cjs.map +1 -1
- package/dist/react/hooks.js +23 -13
- package/dist/react/hooks.js.map +1 -1
- package/dist/react/themes.cjs +61 -18
- package/dist/react/themes.cjs.map +1 -1
- package/dist/react/themes.js +63 -20
- package/dist/react/themes.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -164,7 +164,7 @@ function loadLayoutsForDir(pageDir, appDir) {
|
|
|
164
164
|
};
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
-
// modules/router/
|
|
167
|
+
// modules/router/server-hook.ts
|
|
168
168
|
import fs2 from "fs";
|
|
169
169
|
import path2 from "path";
|
|
170
170
|
var NAMING = {
|
|
@@ -176,14 +176,16 @@ var NAMING = {
|
|
|
176
176
|
// Files
|
|
177
177
|
SERVER_HOOK: "server.hook"
|
|
178
178
|
};
|
|
179
|
-
function
|
|
180
|
-
const
|
|
181
|
-
const
|
|
182
|
-
const
|
|
179
|
+
function loadServerHookForDir(currentDir) {
|
|
180
|
+
const pageServerHookTs = path2.join(currentDir, `page.server.hook.ts`);
|
|
181
|
+
const pageServerHookJs = path2.join(currentDir, `page.server.hook.js`);
|
|
182
|
+
const serverHookTs = path2.join(currentDir, `${NAMING.SERVER_HOOK}.ts`);
|
|
183
|
+
const serverHookJs = path2.join(currentDir, `${NAMING.SERVER_HOOK}.js`);
|
|
184
|
+
const file = fs2.existsSync(pageServerHookTs) ? pageServerHookTs : fs2.existsSync(pageServerHookJs) ? pageServerHookJs : fs2.existsSync(serverHookTs) ? serverHookTs : fs2.existsSync(serverHookJs) ? serverHookJs : null;
|
|
183
185
|
if (!file) {
|
|
184
186
|
return {
|
|
185
187
|
middlewares: [],
|
|
186
|
-
|
|
188
|
+
serverHook: null,
|
|
187
189
|
dynamic: "auto",
|
|
188
190
|
generateStaticParams: null
|
|
189
191
|
};
|
|
@@ -199,12 +201,12 @@ function loadLoaderForDir(currentDir) {
|
|
|
199
201
|
mod = __require(file);
|
|
200
202
|
} catch (error) {
|
|
201
203
|
console.error(
|
|
202
|
-
`[framework][
|
|
204
|
+
`[framework][server-hook] Error loading server hook from ${file}:`,
|
|
203
205
|
error
|
|
204
206
|
);
|
|
205
207
|
return {
|
|
206
208
|
middlewares: [],
|
|
207
|
-
|
|
209
|
+
serverHook: null,
|
|
208
210
|
dynamic: "auto",
|
|
209
211
|
generateStaticParams: null
|
|
210
212
|
};
|
|
@@ -212,16 +214,43 @@ function loadLoaderForDir(currentDir) {
|
|
|
212
214
|
const middlewares = Array.isArray(
|
|
213
215
|
mod?.[NAMING.BEFORE_MIDDLEWARES]
|
|
214
216
|
) ? mod[NAMING.BEFORE_MIDDLEWARES] : [];
|
|
215
|
-
const
|
|
217
|
+
const serverHook = typeof mod?.[NAMING.GET_SERVER_DATA_FN] === "function" ? mod[NAMING.GET_SERVER_DATA_FN] : null;
|
|
216
218
|
const dynamic = mod?.[NAMING.RENDER_TYPE_CONST] === "force-static" || mod?.[NAMING.RENDER_TYPE_CONST] === "force-dynamic" ? mod.dynamic : "auto";
|
|
217
219
|
const generateStaticParams = typeof mod?.[NAMING.GENERATE_SSG_PARAMS] === "function" ? mod[NAMING.GENERATE_SSG_PARAMS] : null;
|
|
218
220
|
return {
|
|
219
221
|
middlewares,
|
|
220
|
-
|
|
222
|
+
serverHook,
|
|
221
223
|
dynamic,
|
|
222
224
|
generateStaticParams
|
|
223
225
|
};
|
|
224
226
|
}
|
|
227
|
+
function loadLayoutServerHook(layoutFile) {
|
|
228
|
+
const layoutDir = path2.dirname(layoutFile);
|
|
229
|
+
const layoutBasename = path2.basename(layoutFile, path2.extname(layoutFile));
|
|
230
|
+
const serverHookTs = path2.join(layoutDir, `${layoutBasename}.server.hook.ts`);
|
|
231
|
+
const serverHookJs = path2.join(layoutDir, `${layoutBasename}.server.hook.js`);
|
|
232
|
+
const file = fs2.existsSync(serverHookTs) ? serverHookTs : fs2.existsSync(serverHookJs) ? serverHookJs : null;
|
|
233
|
+
if (!file) {
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
if (file.endsWith(".ts") || file.endsWith(".tsx")) {
|
|
237
|
+
try {
|
|
238
|
+
__require("tsx/cjs");
|
|
239
|
+
} catch (e) {
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
try {
|
|
243
|
+
const mod = __require(file);
|
|
244
|
+
const serverHook = typeof mod?.getServerSideProps === "function" ? mod.getServerSideProps : null;
|
|
245
|
+
return serverHook;
|
|
246
|
+
} catch (error) {
|
|
247
|
+
console.error(
|
|
248
|
+
`[framework][server-hook] Error loading layout server hook from ${file}:`,
|
|
249
|
+
error
|
|
250
|
+
);
|
|
251
|
+
return null;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
225
254
|
|
|
226
255
|
// modules/router/loader-pages.ts
|
|
227
256
|
function loadRoutes(appDir) {
|
|
@@ -253,7 +282,12 @@ function loadRoutes(appDir) {
|
|
|
253
282
|
currentDir,
|
|
254
283
|
appDir
|
|
255
284
|
);
|
|
256
|
-
const
|
|
285
|
+
const layoutServerHooks = [];
|
|
286
|
+
for (const layoutFile of layoutFiles) {
|
|
287
|
+
const layoutServerHook = loadLayoutServerHook(layoutFile);
|
|
288
|
+
layoutServerHooks.push(layoutServerHook);
|
|
289
|
+
}
|
|
290
|
+
const { middlewares, serverHook, dynamic, generateStaticParams } = loadServerHookForDir(currentDir);
|
|
257
291
|
routes.push({
|
|
258
292
|
pattern: routePath,
|
|
259
293
|
regex,
|
|
@@ -263,7 +297,10 @@ function loadRoutes(appDir) {
|
|
|
263
297
|
pageFile: fullPath,
|
|
264
298
|
layoutFiles,
|
|
265
299
|
middlewares,
|
|
266
|
-
loader,
|
|
300
|
+
loader: serverHook,
|
|
301
|
+
// Keep 'loader' field name for backward compatibility
|
|
302
|
+
layoutServerHooks,
|
|
303
|
+
// Server hooks for each layout (same order as layouts)
|
|
267
304
|
dynamic,
|
|
268
305
|
generateStaticParams
|
|
269
306
|
});
|
|
@@ -782,7 +819,12 @@ function loadRoutesFromManifest(projectRoot) {
|
|
|
782
819
|
(f) => path7.join(projectRoot, f)
|
|
783
820
|
);
|
|
784
821
|
const pageDir = path7.dirname(pageFile);
|
|
785
|
-
const
|
|
822
|
+
const layoutServerHooks = [];
|
|
823
|
+
for (const layoutFile of layoutFiles) {
|
|
824
|
+
const layoutServerHook = loadLayoutServerHook(layoutFile);
|
|
825
|
+
layoutServerHooks.push(layoutServerHook);
|
|
826
|
+
}
|
|
827
|
+
const { middlewares, serverHook, dynamic, generateStaticParams } = loadServerHookForDir(pageDir);
|
|
786
828
|
pageRoutes.push({
|
|
787
829
|
pattern: entry.pattern,
|
|
788
830
|
regex,
|
|
@@ -792,7 +834,10 @@ function loadRoutesFromManifest(projectRoot) {
|
|
|
792
834
|
pageFile,
|
|
793
835
|
layoutFiles,
|
|
794
836
|
middlewares,
|
|
795
|
-
loader,
|
|
837
|
+
loader: serverHook,
|
|
838
|
+
// Keep 'loader' field name for backward compatibility
|
|
839
|
+
layoutServerHooks,
|
|
840
|
+
// Server hooks for each layout (same order as layouts)
|
|
796
841
|
dynamic: entry.dynamic ?? dynamic,
|
|
797
842
|
generateStaticParams
|
|
798
843
|
});
|
|
@@ -1046,7 +1091,12 @@ function loadNotFoundRouteFromFilesystem(appDir) {
|
|
|
1046
1091
|
notFoundDir,
|
|
1047
1092
|
appDir
|
|
1048
1093
|
);
|
|
1049
|
-
const
|
|
1094
|
+
const layoutServerHooks = [];
|
|
1095
|
+
for (const layoutFile of layoutFiles) {
|
|
1096
|
+
const layoutServerHook = loadLayoutServerHook(layoutFile);
|
|
1097
|
+
layoutServerHooks.push(layoutServerHook);
|
|
1098
|
+
}
|
|
1099
|
+
const { middlewares, serverHook, dynamic, generateStaticParams } = loadServerHookForDir(notFoundDir);
|
|
1050
1100
|
return {
|
|
1051
1101
|
pattern: NOT_FOUND_PATTERN,
|
|
1052
1102
|
regex: new RegExp(`^${NOT_FOUND_PATTERN}/?$`),
|
|
@@ -1056,7 +1106,10 @@ function loadNotFoundRouteFromFilesystem(appDir) {
|
|
|
1056
1106
|
pageFile: notFoundFile,
|
|
1057
1107
|
layoutFiles,
|
|
1058
1108
|
middlewares,
|
|
1059
|
-
loader,
|
|
1109
|
+
loader: serverHook,
|
|
1110
|
+
// Keep 'loader' field name for backward compatibility
|
|
1111
|
+
layoutServerHooks,
|
|
1112
|
+
// Server hooks for each layout (same order as layouts)
|
|
1060
1113
|
dynamic,
|
|
1061
1114
|
generateStaticParams
|
|
1062
1115
|
};
|
|
@@ -1087,7 +1140,12 @@ function loadErrorRouteFromFilesystem(appDir) {
|
|
|
1087
1140
|
appDir,
|
|
1088
1141
|
appDir
|
|
1089
1142
|
);
|
|
1090
|
-
const
|
|
1143
|
+
const layoutServerHooks = [];
|
|
1144
|
+
for (const layoutFile of layoutFiles) {
|
|
1145
|
+
const layoutServerHook = loadLayoutServerHook(layoutFile);
|
|
1146
|
+
layoutServerHooks.push(layoutServerHook);
|
|
1147
|
+
}
|
|
1148
|
+
const { middlewares, serverHook, dynamic, generateStaticParams } = loadServerHookForDir(appDir);
|
|
1091
1149
|
return {
|
|
1092
1150
|
pattern: ERROR_PATTERN,
|
|
1093
1151
|
regex: new RegExp(`^${ERROR_PATTERN}/?$`),
|
|
@@ -1097,7 +1155,10 @@ function loadErrorRouteFromFilesystem(appDir) {
|
|
|
1097
1155
|
pageFile: errorFile,
|
|
1098
1156
|
layoutFiles,
|
|
1099
1157
|
middlewares,
|
|
1100
|
-
loader,
|
|
1158
|
+
loader: serverHook,
|
|
1159
|
+
// Keep 'loader' field name for backward compatibility
|
|
1160
|
+
layoutServerHooks,
|
|
1161
|
+
// Server hooks for each layout (same order as layouts)
|
|
1101
1162
|
dynamic,
|
|
1102
1163
|
generateStaticParams
|
|
1103
1164
|
};
|
|
@@ -4208,7 +4269,6 @@ function requestLoggerMiddleware(options = {}) {
|
|
|
4208
4269
|
const startTime = Date.now();
|
|
4209
4270
|
res.on("finish", () => {
|
|
4210
4271
|
const duration = Date.now() - startTime;
|
|
4211
|
-
const shouldLogSuccess = logRequests === true;
|
|
4212
4272
|
if (res.statusCode >= 500) {
|
|
4213
4273
|
reqLogger.error(`${req.method} ${req.path} ${res.statusCode}`, {
|
|
4214
4274
|
statusCode: res.statusCode,
|
|
@@ -4219,11 +4279,6 @@ function requestLoggerMiddleware(options = {}) {
|
|
|
4219
4279
|
statusCode: res.statusCode,
|
|
4220
4280
|
duration: `${duration}ms`
|
|
4221
4281
|
});
|
|
4222
|
-
} else if (shouldLogSuccess) {
|
|
4223
|
-
reqLogger.debug(`${req.method} ${req.path} ${res.statusCode}`, {
|
|
4224
|
-
statusCode: res.statusCode,
|
|
4225
|
-
duration: `${duration}ms`
|
|
4226
|
-
});
|
|
4227
4282
|
}
|
|
4228
4283
|
});
|
|
4229
4284
|
}
|
|
@@ -4332,8 +4387,8 @@ async function runRouteMiddlewares(route, ctx) {
|
|
|
4332
4387
|
}
|
|
4333
4388
|
}
|
|
4334
4389
|
|
|
4335
|
-
// modules/server/handlers/
|
|
4336
|
-
async function
|
|
4390
|
+
// modules/server/handlers/server-hook.ts
|
|
4391
|
+
async function runRouteServerHook(route, ctx) {
|
|
4337
4392
|
if (!route.loader) {
|
|
4338
4393
|
return { props: {} };
|
|
4339
4394
|
}
|
|
@@ -4490,11 +4545,39 @@ async function handlePageRequestInternal(options) {
|
|
|
4490
4545
|
pathname: urlPath,
|
|
4491
4546
|
locals: {}
|
|
4492
4547
|
};
|
|
4493
|
-
|
|
4548
|
+
const layoutProps2 = {};
|
|
4549
|
+
if (notFoundPage.layoutServerHooks && notFoundPage.layoutServerHooks.length > 0) {
|
|
4550
|
+
for (let i = 0; i < notFoundPage.layoutServerHooks.length; i++) {
|
|
4551
|
+
const layoutServerHook = notFoundPage.layoutServerHooks[i];
|
|
4552
|
+
if (layoutServerHook) {
|
|
4553
|
+
try {
|
|
4554
|
+
const layoutResult = await layoutServerHook(ctx2);
|
|
4555
|
+
if (layoutResult.props) {
|
|
4556
|
+
Object.assign(layoutProps2, layoutResult.props);
|
|
4557
|
+
}
|
|
4558
|
+
} catch (error) {
|
|
4559
|
+
const reqLogger2 = getRequestLogger(req);
|
|
4560
|
+
reqLogger2.warn(`Layout server hook ${i} failed for not-found`, {
|
|
4561
|
+
error,
|
|
4562
|
+
layoutFile: notFoundPage.layoutFiles[i]
|
|
4563
|
+
});
|
|
4564
|
+
}
|
|
4565
|
+
}
|
|
4566
|
+
}
|
|
4567
|
+
}
|
|
4568
|
+
let loaderResult2 = await runRouteServerHook(notFoundPage, ctx2);
|
|
4494
4569
|
if (!loaderResult2.theme) {
|
|
4495
4570
|
loaderResult2.theme = theme;
|
|
4496
4571
|
}
|
|
4497
|
-
const
|
|
4572
|
+
const combinedProps2 = {
|
|
4573
|
+
...layoutProps2,
|
|
4574
|
+
...loaderResult2.props || {}
|
|
4575
|
+
};
|
|
4576
|
+
const combinedLoaderResult2 = {
|
|
4577
|
+
...loaderResult2,
|
|
4578
|
+
props: combinedProps2
|
|
4579
|
+
};
|
|
4580
|
+
const initialData2 = buildInitialData(urlPath, {}, combinedLoaderResult2);
|
|
4498
4581
|
const appTree2 = buildAppTree(notFoundPage, {}, initialData2.props);
|
|
4499
4582
|
initialData2.notFound = true;
|
|
4500
4583
|
const nonce2 = res.locals.nonce || void 0;
|
|
@@ -4502,7 +4585,7 @@ async function handlePageRequestInternal(options) {
|
|
|
4502
4585
|
appTree: appTree2,
|
|
4503
4586
|
initialData: initialData2,
|
|
4504
4587
|
routerData,
|
|
4505
|
-
meta:
|
|
4588
|
+
meta: combinedLoaderResult2.metadata ?? null,
|
|
4506
4589
|
titleFallback: "Not found",
|
|
4507
4590
|
descriptionFallback: "Loly demo",
|
|
4508
4591
|
chunkHref: null,
|
|
@@ -4521,8 +4604,8 @@ async function handlePageRequestInternal(options) {
|
|
|
4521
4604
|
},
|
|
4522
4605
|
onShellError(err) {
|
|
4523
4606
|
didError2 = true;
|
|
4524
|
-
const
|
|
4525
|
-
|
|
4607
|
+
const reqLogger2 = getRequestLogger(req);
|
|
4608
|
+
reqLogger2.error("SSR shell error", err, { route: "not-found" });
|
|
4526
4609
|
if (!res.headersSent && errorPage) {
|
|
4527
4610
|
renderErrorPageWithStream(errorPage, req, res, err, routeChunks, theme, projectRoot, env);
|
|
4528
4611
|
} else if (!res.headersSent) {
|
|
@@ -4534,8 +4617,8 @@ async function handlePageRequestInternal(options) {
|
|
|
4534
4617
|
},
|
|
4535
4618
|
onError(err) {
|
|
4536
4619
|
didError2 = true;
|
|
4537
|
-
const
|
|
4538
|
-
|
|
4620
|
+
const reqLogger2 = getRequestLogger(req);
|
|
4621
|
+
reqLogger2.error("SSR error", err, { route: "not-found" });
|
|
4539
4622
|
}
|
|
4540
4623
|
});
|
|
4541
4624
|
req.on("close", () => abort2());
|
|
@@ -4557,9 +4640,30 @@ async function handlePageRequestInternal(options) {
|
|
|
4557
4640
|
if (res.headersSent) {
|
|
4558
4641
|
return;
|
|
4559
4642
|
}
|
|
4643
|
+
const layoutProps = {};
|
|
4644
|
+
const reqLogger = getRequestLogger(req);
|
|
4645
|
+
if (route.layoutServerHooks && route.layoutServerHooks.length > 0) {
|
|
4646
|
+
for (let i = 0; i < route.layoutServerHooks.length; i++) {
|
|
4647
|
+
const layoutServerHook = route.layoutServerHooks[i];
|
|
4648
|
+
if (layoutServerHook) {
|
|
4649
|
+
try {
|
|
4650
|
+
const layoutResult = await layoutServerHook(ctx);
|
|
4651
|
+
if (layoutResult.props) {
|
|
4652
|
+
Object.assign(layoutProps, layoutResult.props);
|
|
4653
|
+
}
|
|
4654
|
+
} catch (error) {
|
|
4655
|
+
reqLogger.warn(`Layout server hook ${i} failed`, {
|
|
4656
|
+
error,
|
|
4657
|
+
layoutFile: route.layoutFiles[i],
|
|
4658
|
+
route: route.pattern
|
|
4659
|
+
});
|
|
4660
|
+
}
|
|
4661
|
+
}
|
|
4662
|
+
}
|
|
4663
|
+
}
|
|
4560
4664
|
let loaderResult;
|
|
4561
4665
|
try {
|
|
4562
|
-
loaderResult = await
|
|
4666
|
+
loaderResult = await runRouteServerHook(route, ctx);
|
|
4563
4667
|
if (!loaderResult.theme) {
|
|
4564
4668
|
loaderResult.theme = theme;
|
|
4565
4669
|
}
|
|
@@ -4578,8 +4682,18 @@ async function handlePageRequestInternal(options) {
|
|
|
4578
4682
|
}
|
|
4579
4683
|
}
|
|
4580
4684
|
}
|
|
4685
|
+
const combinedProps = {
|
|
4686
|
+
...layoutProps,
|
|
4687
|
+
// Props from layouts (stable)
|
|
4688
|
+
...loaderResult.props || {}
|
|
4689
|
+
// Props from page (overrides layout)
|
|
4690
|
+
};
|
|
4691
|
+
const combinedLoaderResult = {
|
|
4692
|
+
...loaderResult,
|
|
4693
|
+
props: combinedProps
|
|
4694
|
+
};
|
|
4581
4695
|
if (isDataReq) {
|
|
4582
|
-
handleDataResponse(res,
|
|
4696
|
+
handleDataResponse(res, combinedLoaderResult, theme);
|
|
4583
4697
|
return;
|
|
4584
4698
|
}
|
|
4585
4699
|
if (loaderResult.redirect) {
|
|
@@ -4594,7 +4708,7 @@ async function handlePageRequestInternal(options) {
|
|
|
4594
4708
|
}
|
|
4595
4709
|
return;
|
|
4596
4710
|
}
|
|
4597
|
-
const initialData = buildInitialData(urlPath, params,
|
|
4711
|
+
const initialData = buildInitialData(urlPath, params, combinedLoaderResult);
|
|
4598
4712
|
const appTree = buildAppTree(route, params, initialData.props);
|
|
4599
4713
|
const chunkName = routeChunks[route.pattern];
|
|
4600
4714
|
let chunkHref = null;
|
|
@@ -4610,7 +4724,7 @@ async function handlePageRequestInternal(options) {
|
|
|
4610
4724
|
appTree,
|
|
4611
4725
|
initialData,
|
|
4612
4726
|
routerData,
|
|
4613
|
-
meta:
|
|
4727
|
+
meta: combinedLoaderResult.metadata,
|
|
4614
4728
|
titleFallback: "Loly framework",
|
|
4615
4729
|
descriptionFallback: "Loly demo",
|
|
4616
4730
|
chunkHref,
|
|
@@ -4631,8 +4745,8 @@ async function handlePageRequestInternal(options) {
|
|
|
4631
4745
|
},
|
|
4632
4746
|
onShellError(err) {
|
|
4633
4747
|
didError = true;
|
|
4634
|
-
const
|
|
4635
|
-
|
|
4748
|
+
const reqLogger2 = getRequestLogger(req);
|
|
4749
|
+
reqLogger2.error("SSR shell error", err, { route: matched?.route?.pattern || "unknown" });
|
|
4636
4750
|
if (!res.headersSent && errorPage) {
|
|
4637
4751
|
renderErrorPageWithStream(errorPage, req, res, err, routeChunks, theme, projectRoot, env);
|
|
4638
4752
|
} else if (!res.headersSent) {
|
|
@@ -4644,8 +4758,8 @@ async function handlePageRequestInternal(options) {
|
|
|
4644
4758
|
},
|
|
4645
4759
|
onError(err) {
|
|
4646
4760
|
didError = true;
|
|
4647
|
-
const
|
|
4648
|
-
|
|
4761
|
+
const reqLogger2 = getRequestLogger(req);
|
|
4762
|
+
reqLogger2.error("SSR error", err, { route: matched?.route?.pattern || "unknown" });
|
|
4649
4763
|
}
|
|
4650
4764
|
});
|
|
4651
4765
|
req.on("close", () => {
|
|
@@ -4662,11 +4776,39 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
|
|
|
4662
4776
|
pathname: req.path,
|
|
4663
4777
|
locals: { error }
|
|
4664
4778
|
};
|
|
4665
|
-
|
|
4779
|
+
const layoutProps = {};
|
|
4780
|
+
const reqLogger = getRequestLogger(req);
|
|
4781
|
+
if (errorPage.layoutServerHooks && errorPage.layoutServerHooks.length > 0) {
|
|
4782
|
+
for (let i = 0; i < errorPage.layoutServerHooks.length; i++) {
|
|
4783
|
+
const layoutServerHook = errorPage.layoutServerHooks[i];
|
|
4784
|
+
if (layoutServerHook) {
|
|
4785
|
+
try {
|
|
4786
|
+
const layoutResult = await layoutServerHook(ctx);
|
|
4787
|
+
if (layoutResult.props) {
|
|
4788
|
+
Object.assign(layoutProps, layoutResult.props);
|
|
4789
|
+
}
|
|
4790
|
+
} catch (err) {
|
|
4791
|
+
reqLogger.warn(`Layout server hook ${i} failed for error page`, {
|
|
4792
|
+
error: err,
|
|
4793
|
+
layoutFile: errorPage.layoutFiles[i]
|
|
4794
|
+
});
|
|
4795
|
+
}
|
|
4796
|
+
}
|
|
4797
|
+
}
|
|
4798
|
+
}
|
|
4799
|
+
let loaderResult = await runRouteServerHook(errorPage, ctx);
|
|
4666
4800
|
if (!loaderResult.theme && theme) {
|
|
4667
4801
|
loaderResult.theme = theme;
|
|
4668
4802
|
}
|
|
4669
|
-
const
|
|
4803
|
+
const combinedProps = {
|
|
4804
|
+
...layoutProps,
|
|
4805
|
+
...loaderResult.props || {}
|
|
4806
|
+
};
|
|
4807
|
+
const combinedLoaderResult = {
|
|
4808
|
+
...loaderResult,
|
|
4809
|
+
props: combinedProps
|
|
4810
|
+
};
|
|
4811
|
+
const initialData = buildInitialData(req.path, { error: String(error) }, combinedLoaderResult);
|
|
4670
4812
|
const routerData = buildRouterData(req);
|
|
4671
4813
|
initialData.error = true;
|
|
4672
4814
|
if (isDataReq) {
|
|
@@ -4676,8 +4818,8 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
|
|
|
4676
4818
|
error: true,
|
|
4677
4819
|
message: String(error),
|
|
4678
4820
|
props: initialData.props,
|
|
4679
|
-
metadata:
|
|
4680
|
-
theme:
|
|
4821
|
+
metadata: combinedLoaderResult.metadata ?? null,
|
|
4822
|
+
theme: combinedLoaderResult.theme ?? theme ?? null
|
|
4681
4823
|
}));
|
|
4682
4824
|
return;
|
|
4683
4825
|
}
|
|
@@ -4699,7 +4841,7 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
|
|
|
4699
4841
|
appTree,
|
|
4700
4842
|
initialData,
|
|
4701
4843
|
routerData,
|
|
4702
|
-
meta:
|
|
4844
|
+
meta: combinedLoaderResult.metadata ?? null,
|
|
4703
4845
|
titleFallback: "Error",
|
|
4704
4846
|
descriptionFallback: "An error occurred",
|
|
4705
4847
|
chunkHref,
|
|
@@ -4720,8 +4862,8 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
|
|
|
4720
4862
|
},
|
|
4721
4863
|
onShellError(err) {
|
|
4722
4864
|
didError = true;
|
|
4723
|
-
const
|
|
4724
|
-
|
|
4865
|
+
const reqLogger2 = getRequestLogger(req);
|
|
4866
|
+
reqLogger2.error("Error rendering error page", err, { type: "shellError" });
|
|
4725
4867
|
if (!res.headersSent) {
|
|
4726
4868
|
res.statusCode = 500;
|
|
4727
4869
|
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
@@ -4731,8 +4873,8 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
|
|
|
4731
4873
|
},
|
|
4732
4874
|
onError(err) {
|
|
4733
4875
|
didError = true;
|
|
4734
|
-
const
|
|
4735
|
-
|
|
4876
|
+
const reqLogger2 = getRequestLogger(req);
|
|
4877
|
+
reqLogger2.error("Error in error page", err);
|
|
4736
4878
|
}
|
|
4737
4879
|
});
|
|
4738
4880
|
req.on("close", () => {
|
|
@@ -5104,26 +5246,22 @@ async function startServer(options = {}) {
|
|
|
5104
5246
|
});
|
|
5105
5247
|
httpServer.listen(port, host, () => {
|
|
5106
5248
|
if (isDev) {
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5249
|
+
const reset = "\x1B[0m";
|
|
5250
|
+
const cyan = "\x1B[36m";
|
|
5251
|
+
const green = "\x1B[32m";
|
|
5252
|
+
const dim = "\x1B[2m";
|
|
5253
|
+
const bold = "\x1B[1m";
|
|
5254
|
+
const url = `http://${host === "0.0.0.0" ? "localhost" : host}:${port}`;
|
|
5255
|
+
console.log();
|
|
5256
|
+
console.log(`${bold}${green}\u2713${reset} ${bold}Dev server ready${reset}`);
|
|
5257
|
+
console.log(`${dim} Local:${reset} ${cyan}${url}${reset}`);
|
|
5258
|
+
if (routes.length > 0 || apiRoutes.length > 0 || wssRoutes.length > 0) {
|
|
5259
|
+
console.log(`${dim} Routes:${reset} ${routes.length} pages, ${apiRoutes.length} API, ${wssRoutes.length} WSS`);
|
|
5260
|
+
}
|
|
5261
|
+
console.log();
|
|
5113
5262
|
} else {
|
|
5114
|
-
const
|
|
5115
|
-
|
|
5116
|
-
url: `http://${host}:${port}`,
|
|
5117
|
-
appDir,
|
|
5118
|
-
buildDir
|
|
5119
|
-
});
|
|
5120
|
-
logger3.info("\u{1F9ED} Reading compiled routes from", { appDir });
|
|
5121
|
-
logger3.info("\u{1F4E6} Client served from", {
|
|
5122
|
-
path: `/static (${buildDir}/client)`
|
|
5123
|
-
});
|
|
5124
|
-
logger3.info("\u{1F4C4} SSG served from", {
|
|
5125
|
-
path: `${buildDir}/ssg (if exists)`
|
|
5126
|
-
});
|
|
5263
|
+
const url = `http://${host}:${port}`;
|
|
5264
|
+
console.log(`\u{1F680} Server running on ${url}`);
|
|
5127
5265
|
}
|
|
5128
5266
|
});
|
|
5129
5267
|
}
|