@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.cjs
CHANGED
|
@@ -169,7 +169,7 @@ function loadLayoutsForDir(pageDir, appDir) {
|
|
|
169
169
|
};
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
-
// modules/router/
|
|
172
|
+
// modules/router/server-hook.ts
|
|
173
173
|
var import_fs2 = __toESM(require("fs"));
|
|
174
174
|
var import_path2 = __toESM(require("path"));
|
|
175
175
|
var NAMING = {
|
|
@@ -181,14 +181,16 @@ var NAMING = {
|
|
|
181
181
|
// Files
|
|
182
182
|
SERVER_HOOK: "server.hook"
|
|
183
183
|
};
|
|
184
|
-
function
|
|
185
|
-
const
|
|
186
|
-
const
|
|
187
|
-
const
|
|
184
|
+
function loadServerHookForDir(currentDir) {
|
|
185
|
+
const pageServerHookTs = import_path2.default.join(currentDir, `page.server.hook.ts`);
|
|
186
|
+
const pageServerHookJs = import_path2.default.join(currentDir, `page.server.hook.js`);
|
|
187
|
+
const serverHookTs = import_path2.default.join(currentDir, `${NAMING.SERVER_HOOK}.ts`);
|
|
188
|
+
const serverHookJs = import_path2.default.join(currentDir, `${NAMING.SERVER_HOOK}.js`);
|
|
189
|
+
const file = import_fs2.default.existsSync(pageServerHookTs) ? pageServerHookTs : import_fs2.default.existsSync(pageServerHookJs) ? pageServerHookJs : import_fs2.default.existsSync(serverHookTs) ? serverHookTs : import_fs2.default.existsSync(serverHookJs) ? serverHookJs : null;
|
|
188
190
|
if (!file) {
|
|
189
191
|
return {
|
|
190
192
|
middlewares: [],
|
|
191
|
-
|
|
193
|
+
serverHook: null,
|
|
192
194
|
dynamic: "auto",
|
|
193
195
|
generateStaticParams: null
|
|
194
196
|
};
|
|
@@ -204,12 +206,12 @@ function loadLoaderForDir(currentDir) {
|
|
|
204
206
|
mod = require(file);
|
|
205
207
|
} catch (error) {
|
|
206
208
|
console.error(
|
|
207
|
-
`[framework][
|
|
209
|
+
`[framework][server-hook] Error loading server hook from ${file}:`,
|
|
208
210
|
error
|
|
209
211
|
);
|
|
210
212
|
return {
|
|
211
213
|
middlewares: [],
|
|
212
|
-
|
|
214
|
+
serverHook: null,
|
|
213
215
|
dynamic: "auto",
|
|
214
216
|
generateStaticParams: null
|
|
215
217
|
};
|
|
@@ -217,16 +219,43 @@ function loadLoaderForDir(currentDir) {
|
|
|
217
219
|
const middlewares = Array.isArray(
|
|
218
220
|
mod?.[NAMING.BEFORE_MIDDLEWARES]
|
|
219
221
|
) ? mod[NAMING.BEFORE_MIDDLEWARES] : [];
|
|
220
|
-
const
|
|
222
|
+
const serverHook = typeof mod?.[NAMING.GET_SERVER_DATA_FN] === "function" ? mod[NAMING.GET_SERVER_DATA_FN] : null;
|
|
221
223
|
const dynamic = mod?.[NAMING.RENDER_TYPE_CONST] === "force-static" || mod?.[NAMING.RENDER_TYPE_CONST] === "force-dynamic" ? mod.dynamic : "auto";
|
|
222
224
|
const generateStaticParams = typeof mod?.[NAMING.GENERATE_SSG_PARAMS] === "function" ? mod[NAMING.GENERATE_SSG_PARAMS] : null;
|
|
223
225
|
return {
|
|
224
226
|
middlewares,
|
|
225
|
-
|
|
227
|
+
serverHook,
|
|
226
228
|
dynamic,
|
|
227
229
|
generateStaticParams
|
|
228
230
|
};
|
|
229
231
|
}
|
|
232
|
+
function loadLayoutServerHook(layoutFile) {
|
|
233
|
+
const layoutDir = import_path2.default.dirname(layoutFile);
|
|
234
|
+
const layoutBasename = import_path2.default.basename(layoutFile, import_path2.default.extname(layoutFile));
|
|
235
|
+
const serverHookTs = import_path2.default.join(layoutDir, `${layoutBasename}.server.hook.ts`);
|
|
236
|
+
const serverHookJs = import_path2.default.join(layoutDir, `${layoutBasename}.server.hook.js`);
|
|
237
|
+
const file = import_fs2.default.existsSync(serverHookTs) ? serverHookTs : import_fs2.default.existsSync(serverHookJs) ? serverHookJs : null;
|
|
238
|
+
if (!file) {
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
if (file.endsWith(".ts") || file.endsWith(".tsx")) {
|
|
242
|
+
try {
|
|
243
|
+
require("tsx/cjs");
|
|
244
|
+
} catch (e) {
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
try {
|
|
248
|
+
const mod = require(file);
|
|
249
|
+
const serverHook = typeof mod?.getServerSideProps === "function" ? mod.getServerSideProps : null;
|
|
250
|
+
return serverHook;
|
|
251
|
+
} catch (error) {
|
|
252
|
+
console.error(
|
|
253
|
+
`[framework][server-hook] Error loading layout server hook from ${file}:`,
|
|
254
|
+
error
|
|
255
|
+
);
|
|
256
|
+
return null;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
230
259
|
|
|
231
260
|
// modules/router/loader-pages.ts
|
|
232
261
|
function loadRoutes(appDir) {
|
|
@@ -258,7 +287,12 @@ function loadRoutes(appDir) {
|
|
|
258
287
|
currentDir,
|
|
259
288
|
appDir
|
|
260
289
|
);
|
|
261
|
-
const
|
|
290
|
+
const layoutServerHooks = [];
|
|
291
|
+
for (const layoutFile of layoutFiles) {
|
|
292
|
+
const layoutServerHook = loadLayoutServerHook(layoutFile);
|
|
293
|
+
layoutServerHooks.push(layoutServerHook);
|
|
294
|
+
}
|
|
295
|
+
const { middlewares, serverHook, dynamic, generateStaticParams } = loadServerHookForDir(currentDir);
|
|
262
296
|
routes.push({
|
|
263
297
|
pattern: routePath,
|
|
264
298
|
regex,
|
|
@@ -268,7 +302,10 @@ function loadRoutes(appDir) {
|
|
|
268
302
|
pageFile: fullPath,
|
|
269
303
|
layoutFiles,
|
|
270
304
|
middlewares,
|
|
271
|
-
loader,
|
|
305
|
+
loader: serverHook,
|
|
306
|
+
// Keep 'loader' field name for backward compatibility
|
|
307
|
+
layoutServerHooks,
|
|
308
|
+
// Server hooks for each layout (same order as layouts)
|
|
272
309
|
dynamic,
|
|
273
310
|
generateStaticParams
|
|
274
311
|
});
|
|
@@ -787,7 +824,12 @@ function loadRoutesFromManifest(projectRoot) {
|
|
|
787
824
|
(f) => import_path9.default.join(projectRoot, f)
|
|
788
825
|
);
|
|
789
826
|
const pageDir = import_path9.default.dirname(pageFile);
|
|
790
|
-
const
|
|
827
|
+
const layoutServerHooks = [];
|
|
828
|
+
for (const layoutFile of layoutFiles) {
|
|
829
|
+
const layoutServerHook = loadLayoutServerHook(layoutFile);
|
|
830
|
+
layoutServerHooks.push(layoutServerHook);
|
|
831
|
+
}
|
|
832
|
+
const { middlewares, serverHook, dynamic, generateStaticParams } = loadServerHookForDir(pageDir);
|
|
791
833
|
pageRoutes.push({
|
|
792
834
|
pattern: entry.pattern,
|
|
793
835
|
regex,
|
|
@@ -797,7 +839,10 @@ function loadRoutesFromManifest(projectRoot) {
|
|
|
797
839
|
pageFile,
|
|
798
840
|
layoutFiles,
|
|
799
841
|
middlewares,
|
|
800
|
-
loader,
|
|
842
|
+
loader: serverHook,
|
|
843
|
+
// Keep 'loader' field name for backward compatibility
|
|
844
|
+
layoutServerHooks,
|
|
845
|
+
// Server hooks for each layout (same order as layouts)
|
|
801
846
|
dynamic: entry.dynamic ?? dynamic,
|
|
802
847
|
generateStaticParams
|
|
803
848
|
});
|
|
@@ -1051,7 +1096,12 @@ function loadNotFoundRouteFromFilesystem(appDir) {
|
|
|
1051
1096
|
notFoundDir,
|
|
1052
1097
|
appDir
|
|
1053
1098
|
);
|
|
1054
|
-
const
|
|
1099
|
+
const layoutServerHooks = [];
|
|
1100
|
+
for (const layoutFile of layoutFiles) {
|
|
1101
|
+
const layoutServerHook = loadLayoutServerHook(layoutFile);
|
|
1102
|
+
layoutServerHooks.push(layoutServerHook);
|
|
1103
|
+
}
|
|
1104
|
+
const { middlewares, serverHook, dynamic, generateStaticParams } = loadServerHookForDir(notFoundDir);
|
|
1055
1105
|
return {
|
|
1056
1106
|
pattern: NOT_FOUND_PATTERN,
|
|
1057
1107
|
regex: new RegExp(`^${NOT_FOUND_PATTERN}/?$`),
|
|
@@ -1061,7 +1111,10 @@ function loadNotFoundRouteFromFilesystem(appDir) {
|
|
|
1061
1111
|
pageFile: notFoundFile,
|
|
1062
1112
|
layoutFiles,
|
|
1063
1113
|
middlewares,
|
|
1064
|
-
loader,
|
|
1114
|
+
loader: serverHook,
|
|
1115
|
+
// Keep 'loader' field name for backward compatibility
|
|
1116
|
+
layoutServerHooks,
|
|
1117
|
+
// Server hooks for each layout (same order as layouts)
|
|
1065
1118
|
dynamic,
|
|
1066
1119
|
generateStaticParams
|
|
1067
1120
|
};
|
|
@@ -1092,7 +1145,12 @@ function loadErrorRouteFromFilesystem(appDir) {
|
|
|
1092
1145
|
appDir,
|
|
1093
1146
|
appDir
|
|
1094
1147
|
);
|
|
1095
|
-
const
|
|
1148
|
+
const layoutServerHooks = [];
|
|
1149
|
+
for (const layoutFile of layoutFiles) {
|
|
1150
|
+
const layoutServerHook = loadLayoutServerHook(layoutFile);
|
|
1151
|
+
layoutServerHooks.push(layoutServerHook);
|
|
1152
|
+
}
|
|
1153
|
+
const { middlewares, serverHook, dynamic, generateStaticParams } = loadServerHookForDir(appDir);
|
|
1096
1154
|
return {
|
|
1097
1155
|
pattern: ERROR_PATTERN,
|
|
1098
1156
|
regex: new RegExp(`^${ERROR_PATTERN}/?$`),
|
|
@@ -1102,7 +1160,10 @@ function loadErrorRouteFromFilesystem(appDir) {
|
|
|
1102
1160
|
pageFile: errorFile,
|
|
1103
1161
|
layoutFiles,
|
|
1104
1162
|
middlewares,
|
|
1105
|
-
loader,
|
|
1163
|
+
loader: serverHook,
|
|
1164
|
+
// Keep 'loader' field name for backward compatibility
|
|
1165
|
+
layoutServerHooks,
|
|
1166
|
+
// Server hooks for each layout (same order as layouts)
|
|
1106
1167
|
dynamic,
|
|
1107
1168
|
generateStaticParams
|
|
1108
1169
|
};
|
|
@@ -4213,7 +4274,6 @@ function requestLoggerMiddleware(options = {}) {
|
|
|
4213
4274
|
const startTime = Date.now();
|
|
4214
4275
|
res.on("finish", () => {
|
|
4215
4276
|
const duration = Date.now() - startTime;
|
|
4216
|
-
const shouldLogSuccess = logRequests === true;
|
|
4217
4277
|
if (res.statusCode >= 500) {
|
|
4218
4278
|
reqLogger.error(`${req.method} ${req.path} ${res.statusCode}`, {
|
|
4219
4279
|
statusCode: res.statusCode,
|
|
@@ -4224,11 +4284,6 @@ function requestLoggerMiddleware(options = {}) {
|
|
|
4224
4284
|
statusCode: res.statusCode,
|
|
4225
4285
|
duration: `${duration}ms`
|
|
4226
4286
|
});
|
|
4227
|
-
} else if (shouldLogSuccess) {
|
|
4228
|
-
reqLogger.debug(`${req.method} ${req.path} ${res.statusCode}`, {
|
|
4229
|
-
statusCode: res.statusCode,
|
|
4230
|
-
duration: `${duration}ms`
|
|
4231
|
-
});
|
|
4232
4287
|
}
|
|
4233
4288
|
});
|
|
4234
4289
|
}
|
|
@@ -4337,8 +4392,8 @@ async function runRouteMiddlewares(route, ctx) {
|
|
|
4337
4392
|
}
|
|
4338
4393
|
}
|
|
4339
4394
|
|
|
4340
|
-
// modules/server/handlers/
|
|
4341
|
-
async function
|
|
4395
|
+
// modules/server/handlers/server-hook.ts
|
|
4396
|
+
async function runRouteServerHook(route, ctx) {
|
|
4342
4397
|
if (!route.loader) {
|
|
4343
4398
|
return { props: {} };
|
|
4344
4399
|
}
|
|
@@ -4495,11 +4550,39 @@ async function handlePageRequestInternal(options) {
|
|
|
4495
4550
|
pathname: urlPath,
|
|
4496
4551
|
locals: {}
|
|
4497
4552
|
};
|
|
4498
|
-
|
|
4553
|
+
const layoutProps2 = {};
|
|
4554
|
+
if (notFoundPage.layoutServerHooks && notFoundPage.layoutServerHooks.length > 0) {
|
|
4555
|
+
for (let i = 0; i < notFoundPage.layoutServerHooks.length; i++) {
|
|
4556
|
+
const layoutServerHook = notFoundPage.layoutServerHooks[i];
|
|
4557
|
+
if (layoutServerHook) {
|
|
4558
|
+
try {
|
|
4559
|
+
const layoutResult = await layoutServerHook(ctx2);
|
|
4560
|
+
if (layoutResult.props) {
|
|
4561
|
+
Object.assign(layoutProps2, layoutResult.props);
|
|
4562
|
+
}
|
|
4563
|
+
} catch (error) {
|
|
4564
|
+
const reqLogger2 = getRequestLogger(req);
|
|
4565
|
+
reqLogger2.warn(`Layout server hook ${i} failed for not-found`, {
|
|
4566
|
+
error,
|
|
4567
|
+
layoutFile: notFoundPage.layoutFiles[i]
|
|
4568
|
+
});
|
|
4569
|
+
}
|
|
4570
|
+
}
|
|
4571
|
+
}
|
|
4572
|
+
}
|
|
4573
|
+
let loaderResult2 = await runRouteServerHook(notFoundPage, ctx2);
|
|
4499
4574
|
if (!loaderResult2.theme) {
|
|
4500
4575
|
loaderResult2.theme = theme;
|
|
4501
4576
|
}
|
|
4502
|
-
const
|
|
4577
|
+
const combinedProps2 = {
|
|
4578
|
+
...layoutProps2,
|
|
4579
|
+
...loaderResult2.props || {}
|
|
4580
|
+
};
|
|
4581
|
+
const combinedLoaderResult2 = {
|
|
4582
|
+
...loaderResult2,
|
|
4583
|
+
props: combinedProps2
|
|
4584
|
+
};
|
|
4585
|
+
const initialData2 = buildInitialData(urlPath, {}, combinedLoaderResult2);
|
|
4503
4586
|
const appTree2 = buildAppTree(notFoundPage, {}, initialData2.props);
|
|
4504
4587
|
initialData2.notFound = true;
|
|
4505
4588
|
const nonce2 = res.locals.nonce || void 0;
|
|
@@ -4507,7 +4590,7 @@ async function handlePageRequestInternal(options) {
|
|
|
4507
4590
|
appTree: appTree2,
|
|
4508
4591
|
initialData: initialData2,
|
|
4509
4592
|
routerData,
|
|
4510
|
-
meta:
|
|
4593
|
+
meta: combinedLoaderResult2.metadata ?? null,
|
|
4511
4594
|
titleFallback: "Not found",
|
|
4512
4595
|
descriptionFallback: "Loly demo",
|
|
4513
4596
|
chunkHref: null,
|
|
@@ -4526,8 +4609,8 @@ async function handlePageRequestInternal(options) {
|
|
|
4526
4609
|
},
|
|
4527
4610
|
onShellError(err) {
|
|
4528
4611
|
didError2 = true;
|
|
4529
|
-
const
|
|
4530
|
-
|
|
4612
|
+
const reqLogger2 = getRequestLogger(req);
|
|
4613
|
+
reqLogger2.error("SSR shell error", err, { route: "not-found" });
|
|
4531
4614
|
if (!res.headersSent && errorPage) {
|
|
4532
4615
|
renderErrorPageWithStream(errorPage, req, res, err, routeChunks, theme, projectRoot, env);
|
|
4533
4616
|
} else if (!res.headersSent) {
|
|
@@ -4539,8 +4622,8 @@ async function handlePageRequestInternal(options) {
|
|
|
4539
4622
|
},
|
|
4540
4623
|
onError(err) {
|
|
4541
4624
|
didError2 = true;
|
|
4542
|
-
const
|
|
4543
|
-
|
|
4625
|
+
const reqLogger2 = getRequestLogger(req);
|
|
4626
|
+
reqLogger2.error("SSR error", err, { route: "not-found" });
|
|
4544
4627
|
}
|
|
4545
4628
|
});
|
|
4546
4629
|
req.on("close", () => abort2());
|
|
@@ -4562,9 +4645,30 @@ async function handlePageRequestInternal(options) {
|
|
|
4562
4645
|
if (res.headersSent) {
|
|
4563
4646
|
return;
|
|
4564
4647
|
}
|
|
4648
|
+
const layoutProps = {};
|
|
4649
|
+
const reqLogger = getRequestLogger(req);
|
|
4650
|
+
if (route.layoutServerHooks && route.layoutServerHooks.length > 0) {
|
|
4651
|
+
for (let i = 0; i < route.layoutServerHooks.length; i++) {
|
|
4652
|
+
const layoutServerHook = route.layoutServerHooks[i];
|
|
4653
|
+
if (layoutServerHook) {
|
|
4654
|
+
try {
|
|
4655
|
+
const layoutResult = await layoutServerHook(ctx);
|
|
4656
|
+
if (layoutResult.props) {
|
|
4657
|
+
Object.assign(layoutProps, layoutResult.props);
|
|
4658
|
+
}
|
|
4659
|
+
} catch (error) {
|
|
4660
|
+
reqLogger.warn(`Layout server hook ${i} failed`, {
|
|
4661
|
+
error,
|
|
4662
|
+
layoutFile: route.layoutFiles[i],
|
|
4663
|
+
route: route.pattern
|
|
4664
|
+
});
|
|
4665
|
+
}
|
|
4666
|
+
}
|
|
4667
|
+
}
|
|
4668
|
+
}
|
|
4565
4669
|
let loaderResult;
|
|
4566
4670
|
try {
|
|
4567
|
-
loaderResult = await
|
|
4671
|
+
loaderResult = await runRouteServerHook(route, ctx);
|
|
4568
4672
|
if (!loaderResult.theme) {
|
|
4569
4673
|
loaderResult.theme = theme;
|
|
4570
4674
|
}
|
|
@@ -4583,8 +4687,18 @@ async function handlePageRequestInternal(options) {
|
|
|
4583
4687
|
}
|
|
4584
4688
|
}
|
|
4585
4689
|
}
|
|
4690
|
+
const combinedProps = {
|
|
4691
|
+
...layoutProps,
|
|
4692
|
+
// Props from layouts (stable)
|
|
4693
|
+
...loaderResult.props || {}
|
|
4694
|
+
// Props from page (overrides layout)
|
|
4695
|
+
};
|
|
4696
|
+
const combinedLoaderResult = {
|
|
4697
|
+
...loaderResult,
|
|
4698
|
+
props: combinedProps
|
|
4699
|
+
};
|
|
4586
4700
|
if (isDataReq) {
|
|
4587
|
-
handleDataResponse(res,
|
|
4701
|
+
handleDataResponse(res, combinedLoaderResult, theme);
|
|
4588
4702
|
return;
|
|
4589
4703
|
}
|
|
4590
4704
|
if (loaderResult.redirect) {
|
|
@@ -4599,7 +4713,7 @@ async function handlePageRequestInternal(options) {
|
|
|
4599
4713
|
}
|
|
4600
4714
|
return;
|
|
4601
4715
|
}
|
|
4602
|
-
const initialData = buildInitialData(urlPath, params,
|
|
4716
|
+
const initialData = buildInitialData(urlPath, params, combinedLoaderResult);
|
|
4603
4717
|
const appTree = buildAppTree(route, params, initialData.props);
|
|
4604
4718
|
const chunkName = routeChunks[route.pattern];
|
|
4605
4719
|
let chunkHref = null;
|
|
@@ -4615,7 +4729,7 @@ async function handlePageRequestInternal(options) {
|
|
|
4615
4729
|
appTree,
|
|
4616
4730
|
initialData,
|
|
4617
4731
|
routerData,
|
|
4618
|
-
meta:
|
|
4732
|
+
meta: combinedLoaderResult.metadata,
|
|
4619
4733
|
titleFallback: "Loly framework",
|
|
4620
4734
|
descriptionFallback: "Loly demo",
|
|
4621
4735
|
chunkHref,
|
|
@@ -4636,8 +4750,8 @@ async function handlePageRequestInternal(options) {
|
|
|
4636
4750
|
},
|
|
4637
4751
|
onShellError(err) {
|
|
4638
4752
|
didError = true;
|
|
4639
|
-
const
|
|
4640
|
-
|
|
4753
|
+
const reqLogger2 = getRequestLogger(req);
|
|
4754
|
+
reqLogger2.error("SSR shell error", err, { route: matched?.route?.pattern || "unknown" });
|
|
4641
4755
|
if (!res.headersSent && errorPage) {
|
|
4642
4756
|
renderErrorPageWithStream(errorPage, req, res, err, routeChunks, theme, projectRoot, env);
|
|
4643
4757
|
} else if (!res.headersSent) {
|
|
@@ -4649,8 +4763,8 @@ async function handlePageRequestInternal(options) {
|
|
|
4649
4763
|
},
|
|
4650
4764
|
onError(err) {
|
|
4651
4765
|
didError = true;
|
|
4652
|
-
const
|
|
4653
|
-
|
|
4766
|
+
const reqLogger2 = getRequestLogger(req);
|
|
4767
|
+
reqLogger2.error("SSR error", err, { route: matched?.route?.pattern || "unknown" });
|
|
4654
4768
|
}
|
|
4655
4769
|
});
|
|
4656
4770
|
req.on("close", () => {
|
|
@@ -4667,11 +4781,39 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
|
|
|
4667
4781
|
pathname: req.path,
|
|
4668
4782
|
locals: { error }
|
|
4669
4783
|
};
|
|
4670
|
-
|
|
4784
|
+
const layoutProps = {};
|
|
4785
|
+
const reqLogger = getRequestLogger(req);
|
|
4786
|
+
if (errorPage.layoutServerHooks && errorPage.layoutServerHooks.length > 0) {
|
|
4787
|
+
for (let i = 0; i < errorPage.layoutServerHooks.length; i++) {
|
|
4788
|
+
const layoutServerHook = errorPage.layoutServerHooks[i];
|
|
4789
|
+
if (layoutServerHook) {
|
|
4790
|
+
try {
|
|
4791
|
+
const layoutResult = await layoutServerHook(ctx);
|
|
4792
|
+
if (layoutResult.props) {
|
|
4793
|
+
Object.assign(layoutProps, layoutResult.props);
|
|
4794
|
+
}
|
|
4795
|
+
} catch (err) {
|
|
4796
|
+
reqLogger.warn(`Layout server hook ${i} failed for error page`, {
|
|
4797
|
+
error: err,
|
|
4798
|
+
layoutFile: errorPage.layoutFiles[i]
|
|
4799
|
+
});
|
|
4800
|
+
}
|
|
4801
|
+
}
|
|
4802
|
+
}
|
|
4803
|
+
}
|
|
4804
|
+
let loaderResult = await runRouteServerHook(errorPage, ctx);
|
|
4671
4805
|
if (!loaderResult.theme && theme) {
|
|
4672
4806
|
loaderResult.theme = theme;
|
|
4673
4807
|
}
|
|
4674
|
-
const
|
|
4808
|
+
const combinedProps = {
|
|
4809
|
+
...layoutProps,
|
|
4810
|
+
...loaderResult.props || {}
|
|
4811
|
+
};
|
|
4812
|
+
const combinedLoaderResult = {
|
|
4813
|
+
...loaderResult,
|
|
4814
|
+
props: combinedProps
|
|
4815
|
+
};
|
|
4816
|
+
const initialData = buildInitialData(req.path, { error: String(error) }, combinedLoaderResult);
|
|
4675
4817
|
const routerData = buildRouterData(req);
|
|
4676
4818
|
initialData.error = true;
|
|
4677
4819
|
if (isDataReq) {
|
|
@@ -4681,8 +4823,8 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
|
|
|
4681
4823
|
error: true,
|
|
4682
4824
|
message: String(error),
|
|
4683
4825
|
props: initialData.props,
|
|
4684
|
-
metadata:
|
|
4685
|
-
theme:
|
|
4826
|
+
metadata: combinedLoaderResult.metadata ?? null,
|
|
4827
|
+
theme: combinedLoaderResult.theme ?? theme ?? null
|
|
4686
4828
|
}));
|
|
4687
4829
|
return;
|
|
4688
4830
|
}
|
|
@@ -4704,7 +4846,7 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
|
|
|
4704
4846
|
appTree,
|
|
4705
4847
|
initialData,
|
|
4706
4848
|
routerData,
|
|
4707
|
-
meta:
|
|
4849
|
+
meta: combinedLoaderResult.metadata ?? null,
|
|
4708
4850
|
titleFallback: "Error",
|
|
4709
4851
|
descriptionFallback: "An error occurred",
|
|
4710
4852
|
chunkHref,
|
|
@@ -4725,8 +4867,8 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
|
|
|
4725
4867
|
},
|
|
4726
4868
|
onShellError(err) {
|
|
4727
4869
|
didError = true;
|
|
4728
|
-
const
|
|
4729
|
-
|
|
4870
|
+
const reqLogger2 = getRequestLogger(req);
|
|
4871
|
+
reqLogger2.error("Error rendering error page", err, { type: "shellError" });
|
|
4730
4872
|
if (!res.headersSent) {
|
|
4731
4873
|
res.statusCode = 500;
|
|
4732
4874
|
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
@@ -4736,8 +4878,8 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
|
|
|
4736
4878
|
},
|
|
4737
4879
|
onError(err) {
|
|
4738
4880
|
didError = true;
|
|
4739
|
-
const
|
|
4740
|
-
|
|
4881
|
+
const reqLogger2 = getRequestLogger(req);
|
|
4882
|
+
reqLogger2.error("Error in error page", err);
|
|
4741
4883
|
}
|
|
4742
4884
|
});
|
|
4743
4885
|
req.on("close", () => {
|
|
@@ -5109,26 +5251,22 @@ async function startServer(options = {}) {
|
|
|
5109
5251
|
});
|
|
5110
5252
|
httpServer.listen(port, host, () => {
|
|
5111
5253
|
if (isDev) {
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
|
|
5117
|
-
|
|
5254
|
+
const reset = "\x1B[0m";
|
|
5255
|
+
const cyan = "\x1B[36m";
|
|
5256
|
+
const green = "\x1B[32m";
|
|
5257
|
+
const dim = "\x1B[2m";
|
|
5258
|
+
const bold = "\x1B[1m";
|
|
5259
|
+
const url = `http://${host === "0.0.0.0" ? "localhost" : host}:${port}`;
|
|
5260
|
+
console.log();
|
|
5261
|
+
console.log(`${bold}${green}\u2713${reset} ${bold}Dev server ready${reset}`);
|
|
5262
|
+
console.log(`${dim} Local:${reset} ${cyan}${url}${reset}`);
|
|
5263
|
+
if (routes.length > 0 || apiRoutes.length > 0 || wssRoutes.length > 0) {
|
|
5264
|
+
console.log(`${dim} Routes:${reset} ${routes.length} pages, ${apiRoutes.length} API, ${wssRoutes.length} WSS`);
|
|
5265
|
+
}
|
|
5266
|
+
console.log();
|
|
5118
5267
|
} else {
|
|
5119
|
-
const
|
|
5120
|
-
|
|
5121
|
-
url: `http://${host}:${port}`,
|
|
5122
|
-
appDir,
|
|
5123
|
-
buildDir
|
|
5124
|
-
});
|
|
5125
|
-
logger3.info("\u{1F9ED} Reading compiled routes from", { appDir });
|
|
5126
|
-
logger3.info("\u{1F4E6} Client served from", {
|
|
5127
|
-
path: `/static (${buildDir}/client)`
|
|
5128
|
-
});
|
|
5129
|
-
logger3.info("\u{1F4C4} SSG served from", {
|
|
5130
|
-
path: `${buildDir}/ssg (if exists)`
|
|
5131
|
-
});
|
|
5268
|
+
const url = `http://${host}:${port}`;
|
|
5269
|
+
console.log(`\u{1F680} Server running on ${url}`);
|
|
5132
5270
|
}
|
|
5133
5271
|
});
|
|
5134
5272
|
}
|