@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/index.cjs
CHANGED
|
@@ -246,7 +246,7 @@ function loadLayoutsForDir(pageDir, appDir) {
|
|
|
246
246
|
};
|
|
247
247
|
}
|
|
248
248
|
|
|
249
|
-
// modules/router/
|
|
249
|
+
// modules/router/server-hook.ts
|
|
250
250
|
var import_fs3 = __toESM(require("fs"));
|
|
251
251
|
var import_path3 = __toESM(require("path"));
|
|
252
252
|
var NAMING = {
|
|
@@ -258,14 +258,16 @@ var NAMING = {
|
|
|
258
258
|
// Files
|
|
259
259
|
SERVER_HOOK: "server.hook"
|
|
260
260
|
};
|
|
261
|
-
function
|
|
262
|
-
const
|
|
263
|
-
const
|
|
264
|
-
const
|
|
261
|
+
function loadServerHookForDir(currentDir) {
|
|
262
|
+
const pageServerHookTs = import_path3.default.join(currentDir, `page.server.hook.ts`);
|
|
263
|
+
const pageServerHookJs = import_path3.default.join(currentDir, `page.server.hook.js`);
|
|
264
|
+
const serverHookTs = import_path3.default.join(currentDir, `${NAMING.SERVER_HOOK}.ts`);
|
|
265
|
+
const serverHookJs = import_path3.default.join(currentDir, `${NAMING.SERVER_HOOK}.js`);
|
|
266
|
+
const file = import_fs3.default.existsSync(pageServerHookTs) ? pageServerHookTs : import_fs3.default.existsSync(pageServerHookJs) ? pageServerHookJs : import_fs3.default.existsSync(serverHookTs) ? serverHookTs : import_fs3.default.existsSync(serverHookJs) ? serverHookJs : null;
|
|
265
267
|
if (!file) {
|
|
266
268
|
return {
|
|
267
269
|
middlewares: [],
|
|
268
|
-
|
|
270
|
+
serverHook: null,
|
|
269
271
|
dynamic: "auto",
|
|
270
272
|
generateStaticParams: null
|
|
271
273
|
};
|
|
@@ -281,12 +283,12 @@ function loadLoaderForDir(currentDir) {
|
|
|
281
283
|
mod = require(file);
|
|
282
284
|
} catch (error) {
|
|
283
285
|
console.error(
|
|
284
|
-
`[framework][
|
|
286
|
+
`[framework][server-hook] Error loading server hook from ${file}:`,
|
|
285
287
|
error
|
|
286
288
|
);
|
|
287
289
|
return {
|
|
288
290
|
middlewares: [],
|
|
289
|
-
|
|
291
|
+
serverHook: null,
|
|
290
292
|
dynamic: "auto",
|
|
291
293
|
generateStaticParams: null
|
|
292
294
|
};
|
|
@@ -294,16 +296,43 @@ function loadLoaderForDir(currentDir) {
|
|
|
294
296
|
const middlewares = Array.isArray(
|
|
295
297
|
mod?.[NAMING.BEFORE_MIDDLEWARES]
|
|
296
298
|
) ? mod[NAMING.BEFORE_MIDDLEWARES] : [];
|
|
297
|
-
const
|
|
299
|
+
const serverHook = typeof mod?.[NAMING.GET_SERVER_DATA_FN] === "function" ? mod[NAMING.GET_SERVER_DATA_FN] : null;
|
|
298
300
|
const dynamic = mod?.[NAMING.RENDER_TYPE_CONST] === "force-static" || mod?.[NAMING.RENDER_TYPE_CONST] === "force-dynamic" ? mod.dynamic : "auto";
|
|
299
301
|
const generateStaticParams = typeof mod?.[NAMING.GENERATE_SSG_PARAMS] === "function" ? mod[NAMING.GENERATE_SSG_PARAMS] : null;
|
|
300
302
|
return {
|
|
301
303
|
middlewares,
|
|
302
|
-
|
|
304
|
+
serverHook,
|
|
303
305
|
dynamic,
|
|
304
306
|
generateStaticParams
|
|
305
307
|
};
|
|
306
308
|
}
|
|
309
|
+
function loadLayoutServerHook(layoutFile) {
|
|
310
|
+
const layoutDir = import_path3.default.dirname(layoutFile);
|
|
311
|
+
const layoutBasename = import_path3.default.basename(layoutFile, import_path3.default.extname(layoutFile));
|
|
312
|
+
const serverHookTs = import_path3.default.join(layoutDir, `${layoutBasename}.server.hook.ts`);
|
|
313
|
+
const serverHookJs = import_path3.default.join(layoutDir, `${layoutBasename}.server.hook.js`);
|
|
314
|
+
const file = import_fs3.default.existsSync(serverHookTs) ? serverHookTs : import_fs3.default.existsSync(serverHookJs) ? serverHookJs : null;
|
|
315
|
+
if (!file) {
|
|
316
|
+
return null;
|
|
317
|
+
}
|
|
318
|
+
if (file.endsWith(".ts") || file.endsWith(".tsx")) {
|
|
319
|
+
try {
|
|
320
|
+
require("tsx/cjs");
|
|
321
|
+
} catch (e) {
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
try {
|
|
325
|
+
const mod = require(file);
|
|
326
|
+
const serverHook = typeof mod?.getServerSideProps === "function" ? mod.getServerSideProps : null;
|
|
327
|
+
return serverHook;
|
|
328
|
+
} catch (error) {
|
|
329
|
+
console.error(
|
|
330
|
+
`[framework][server-hook] Error loading layout server hook from ${file}:`,
|
|
331
|
+
error
|
|
332
|
+
);
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
307
336
|
|
|
308
337
|
// modules/router/loader-pages.ts
|
|
309
338
|
function loadRoutes(appDir) {
|
|
@@ -335,7 +364,12 @@ function loadRoutes(appDir) {
|
|
|
335
364
|
currentDir,
|
|
336
365
|
appDir
|
|
337
366
|
);
|
|
338
|
-
const
|
|
367
|
+
const layoutServerHooks = [];
|
|
368
|
+
for (const layoutFile of layoutFiles) {
|
|
369
|
+
const layoutServerHook = loadLayoutServerHook(layoutFile);
|
|
370
|
+
layoutServerHooks.push(layoutServerHook);
|
|
371
|
+
}
|
|
372
|
+
const { middlewares, serverHook, dynamic, generateStaticParams } = loadServerHookForDir(currentDir);
|
|
339
373
|
routes.push({
|
|
340
374
|
pattern: routePath,
|
|
341
375
|
regex,
|
|
@@ -345,7 +379,10 @@ function loadRoutes(appDir) {
|
|
|
345
379
|
pageFile: fullPath,
|
|
346
380
|
layoutFiles,
|
|
347
381
|
middlewares,
|
|
348
|
-
loader,
|
|
382
|
+
loader: serverHook,
|
|
383
|
+
// Keep 'loader' field name for backward compatibility
|
|
384
|
+
layoutServerHooks,
|
|
385
|
+
// Server hooks for each layout (same order as layouts)
|
|
349
386
|
dynamic,
|
|
350
387
|
generateStaticParams
|
|
351
388
|
});
|
|
@@ -864,7 +901,12 @@ function loadRoutesFromManifest(projectRoot) {
|
|
|
864
901
|
(f) => import_path10.default.join(projectRoot, f)
|
|
865
902
|
);
|
|
866
903
|
const pageDir = import_path10.default.dirname(pageFile);
|
|
867
|
-
const
|
|
904
|
+
const layoutServerHooks = [];
|
|
905
|
+
for (const layoutFile of layoutFiles) {
|
|
906
|
+
const layoutServerHook = loadLayoutServerHook(layoutFile);
|
|
907
|
+
layoutServerHooks.push(layoutServerHook);
|
|
908
|
+
}
|
|
909
|
+
const { middlewares, serverHook, dynamic, generateStaticParams } = loadServerHookForDir(pageDir);
|
|
868
910
|
pageRoutes.push({
|
|
869
911
|
pattern: entry.pattern,
|
|
870
912
|
regex,
|
|
@@ -874,7 +916,10 @@ function loadRoutesFromManifest(projectRoot) {
|
|
|
874
916
|
pageFile,
|
|
875
917
|
layoutFiles,
|
|
876
918
|
middlewares,
|
|
877
|
-
loader,
|
|
919
|
+
loader: serverHook,
|
|
920
|
+
// Keep 'loader' field name for backward compatibility
|
|
921
|
+
layoutServerHooks,
|
|
922
|
+
// Server hooks for each layout (same order as layouts)
|
|
878
923
|
dynamic: entry.dynamic ?? dynamic,
|
|
879
924
|
generateStaticParams
|
|
880
925
|
});
|
|
@@ -1128,7 +1173,12 @@ function loadNotFoundRouteFromFilesystem(appDir) {
|
|
|
1128
1173
|
notFoundDir,
|
|
1129
1174
|
appDir
|
|
1130
1175
|
);
|
|
1131
|
-
const
|
|
1176
|
+
const layoutServerHooks = [];
|
|
1177
|
+
for (const layoutFile of layoutFiles) {
|
|
1178
|
+
const layoutServerHook = loadLayoutServerHook(layoutFile);
|
|
1179
|
+
layoutServerHooks.push(layoutServerHook);
|
|
1180
|
+
}
|
|
1181
|
+
const { middlewares, serverHook, dynamic, generateStaticParams } = loadServerHookForDir(notFoundDir);
|
|
1132
1182
|
return {
|
|
1133
1183
|
pattern: NOT_FOUND_PATTERN,
|
|
1134
1184
|
regex: new RegExp(`^${NOT_FOUND_PATTERN}/?$`),
|
|
@@ -1138,7 +1188,10 @@ function loadNotFoundRouteFromFilesystem(appDir) {
|
|
|
1138
1188
|
pageFile: notFoundFile,
|
|
1139
1189
|
layoutFiles,
|
|
1140
1190
|
middlewares,
|
|
1141
|
-
loader,
|
|
1191
|
+
loader: serverHook,
|
|
1192
|
+
// Keep 'loader' field name for backward compatibility
|
|
1193
|
+
layoutServerHooks,
|
|
1194
|
+
// Server hooks for each layout (same order as layouts)
|
|
1142
1195
|
dynamic,
|
|
1143
1196
|
generateStaticParams
|
|
1144
1197
|
};
|
|
@@ -1169,7 +1222,12 @@ function loadErrorRouteFromFilesystem(appDir) {
|
|
|
1169
1222
|
appDir,
|
|
1170
1223
|
appDir
|
|
1171
1224
|
);
|
|
1172
|
-
const
|
|
1225
|
+
const layoutServerHooks = [];
|
|
1226
|
+
for (const layoutFile of layoutFiles) {
|
|
1227
|
+
const layoutServerHook = loadLayoutServerHook(layoutFile);
|
|
1228
|
+
layoutServerHooks.push(layoutServerHook);
|
|
1229
|
+
}
|
|
1230
|
+
const { middlewares, serverHook, dynamic, generateStaticParams } = loadServerHookForDir(appDir);
|
|
1173
1231
|
return {
|
|
1174
1232
|
pattern: ERROR_PATTERN,
|
|
1175
1233
|
regex: new RegExp(`^${ERROR_PATTERN}/?$`),
|
|
@@ -1179,7 +1237,10 @@ function loadErrorRouteFromFilesystem(appDir) {
|
|
|
1179
1237
|
pageFile: errorFile,
|
|
1180
1238
|
layoutFiles,
|
|
1181
1239
|
middlewares,
|
|
1182
|
-
loader,
|
|
1240
|
+
loader: serverHook,
|
|
1241
|
+
// Keep 'loader' field name for backward compatibility
|
|
1242
|
+
layoutServerHooks,
|
|
1243
|
+
// Server hooks for each layout (same order as layouts)
|
|
1183
1244
|
dynamic,
|
|
1184
1245
|
generateStaticParams
|
|
1185
1246
|
};
|
|
@@ -3753,7 +3814,6 @@ function requestLoggerMiddleware(options = {}) {
|
|
|
3753
3814
|
const startTime = Date.now();
|
|
3754
3815
|
res.on("finish", () => {
|
|
3755
3816
|
const duration = Date.now() - startTime;
|
|
3756
|
-
const shouldLogSuccess = logRequests === true;
|
|
3757
3817
|
if (res.statusCode >= 500) {
|
|
3758
3818
|
reqLogger.error(`${req.method} ${req.path} ${res.statusCode}`, {
|
|
3759
3819
|
statusCode: res.statusCode,
|
|
@@ -3764,11 +3824,6 @@ function requestLoggerMiddleware(options = {}) {
|
|
|
3764
3824
|
statusCode: res.statusCode,
|
|
3765
3825
|
duration: `${duration}ms`
|
|
3766
3826
|
});
|
|
3767
|
-
} else if (shouldLogSuccess) {
|
|
3768
|
-
reqLogger.debug(`${req.method} ${req.path} ${res.statusCode}`, {
|
|
3769
|
-
statusCode: res.statusCode,
|
|
3770
|
-
duration: `${duration}ms`
|
|
3771
|
-
});
|
|
3772
3827
|
}
|
|
3773
3828
|
});
|
|
3774
3829
|
}
|
|
@@ -4025,8 +4080,8 @@ async function runRouteMiddlewares(route, ctx) {
|
|
|
4025
4080
|
}
|
|
4026
4081
|
}
|
|
4027
4082
|
|
|
4028
|
-
// modules/server/handlers/
|
|
4029
|
-
async function
|
|
4083
|
+
// modules/server/handlers/server-hook.ts
|
|
4084
|
+
async function runRouteServerHook(route, ctx) {
|
|
4030
4085
|
if (!route.loader) {
|
|
4031
4086
|
return { props: {} };
|
|
4032
4087
|
}
|
|
@@ -4183,11 +4238,39 @@ async function handlePageRequestInternal(options) {
|
|
|
4183
4238
|
pathname: urlPath,
|
|
4184
4239
|
locals: {}
|
|
4185
4240
|
};
|
|
4186
|
-
|
|
4241
|
+
const layoutProps2 = {};
|
|
4242
|
+
if (notFoundPage.layoutServerHooks && notFoundPage.layoutServerHooks.length > 0) {
|
|
4243
|
+
for (let i = 0; i < notFoundPage.layoutServerHooks.length; i++) {
|
|
4244
|
+
const layoutServerHook = notFoundPage.layoutServerHooks[i];
|
|
4245
|
+
if (layoutServerHook) {
|
|
4246
|
+
try {
|
|
4247
|
+
const layoutResult = await layoutServerHook(ctx2);
|
|
4248
|
+
if (layoutResult.props) {
|
|
4249
|
+
Object.assign(layoutProps2, layoutResult.props);
|
|
4250
|
+
}
|
|
4251
|
+
} catch (error) {
|
|
4252
|
+
const reqLogger2 = getRequestLogger(req);
|
|
4253
|
+
reqLogger2.warn(`Layout server hook ${i} failed for not-found`, {
|
|
4254
|
+
error,
|
|
4255
|
+
layoutFile: notFoundPage.layoutFiles[i]
|
|
4256
|
+
});
|
|
4257
|
+
}
|
|
4258
|
+
}
|
|
4259
|
+
}
|
|
4260
|
+
}
|
|
4261
|
+
let loaderResult2 = await runRouteServerHook(notFoundPage, ctx2);
|
|
4187
4262
|
if (!loaderResult2.theme) {
|
|
4188
4263
|
loaderResult2.theme = theme;
|
|
4189
4264
|
}
|
|
4190
|
-
const
|
|
4265
|
+
const combinedProps2 = {
|
|
4266
|
+
...layoutProps2,
|
|
4267
|
+
...loaderResult2.props || {}
|
|
4268
|
+
};
|
|
4269
|
+
const combinedLoaderResult2 = {
|
|
4270
|
+
...loaderResult2,
|
|
4271
|
+
props: combinedProps2
|
|
4272
|
+
};
|
|
4273
|
+
const initialData2 = buildInitialData(urlPath, {}, combinedLoaderResult2);
|
|
4191
4274
|
const appTree2 = buildAppTree(notFoundPage, {}, initialData2.props);
|
|
4192
4275
|
initialData2.notFound = true;
|
|
4193
4276
|
const nonce2 = res.locals.nonce || void 0;
|
|
@@ -4195,7 +4278,7 @@ async function handlePageRequestInternal(options) {
|
|
|
4195
4278
|
appTree: appTree2,
|
|
4196
4279
|
initialData: initialData2,
|
|
4197
4280
|
routerData,
|
|
4198
|
-
meta:
|
|
4281
|
+
meta: combinedLoaderResult2.metadata ?? null,
|
|
4199
4282
|
titleFallback: "Not found",
|
|
4200
4283
|
descriptionFallback: "Loly demo",
|
|
4201
4284
|
chunkHref: null,
|
|
@@ -4214,8 +4297,8 @@ async function handlePageRequestInternal(options) {
|
|
|
4214
4297
|
},
|
|
4215
4298
|
onShellError(err) {
|
|
4216
4299
|
didError2 = true;
|
|
4217
|
-
const
|
|
4218
|
-
|
|
4300
|
+
const reqLogger2 = getRequestLogger(req);
|
|
4301
|
+
reqLogger2.error("SSR shell error", err, { route: "not-found" });
|
|
4219
4302
|
if (!res.headersSent && errorPage) {
|
|
4220
4303
|
renderErrorPageWithStream(errorPage, req, res, err, routeChunks, theme, projectRoot, env);
|
|
4221
4304
|
} else if (!res.headersSent) {
|
|
@@ -4227,8 +4310,8 @@ async function handlePageRequestInternal(options) {
|
|
|
4227
4310
|
},
|
|
4228
4311
|
onError(err) {
|
|
4229
4312
|
didError2 = true;
|
|
4230
|
-
const
|
|
4231
|
-
|
|
4313
|
+
const reqLogger2 = getRequestLogger(req);
|
|
4314
|
+
reqLogger2.error("SSR error", err, { route: "not-found" });
|
|
4232
4315
|
}
|
|
4233
4316
|
});
|
|
4234
4317
|
req.on("close", () => abort2());
|
|
@@ -4250,9 +4333,30 @@ async function handlePageRequestInternal(options) {
|
|
|
4250
4333
|
if (res.headersSent) {
|
|
4251
4334
|
return;
|
|
4252
4335
|
}
|
|
4336
|
+
const layoutProps = {};
|
|
4337
|
+
const reqLogger = getRequestLogger(req);
|
|
4338
|
+
if (route.layoutServerHooks && route.layoutServerHooks.length > 0) {
|
|
4339
|
+
for (let i = 0; i < route.layoutServerHooks.length; i++) {
|
|
4340
|
+
const layoutServerHook = route.layoutServerHooks[i];
|
|
4341
|
+
if (layoutServerHook) {
|
|
4342
|
+
try {
|
|
4343
|
+
const layoutResult = await layoutServerHook(ctx);
|
|
4344
|
+
if (layoutResult.props) {
|
|
4345
|
+
Object.assign(layoutProps, layoutResult.props);
|
|
4346
|
+
}
|
|
4347
|
+
} catch (error) {
|
|
4348
|
+
reqLogger.warn(`Layout server hook ${i} failed`, {
|
|
4349
|
+
error,
|
|
4350
|
+
layoutFile: route.layoutFiles[i],
|
|
4351
|
+
route: route.pattern
|
|
4352
|
+
});
|
|
4353
|
+
}
|
|
4354
|
+
}
|
|
4355
|
+
}
|
|
4356
|
+
}
|
|
4253
4357
|
let loaderResult;
|
|
4254
4358
|
try {
|
|
4255
|
-
loaderResult = await
|
|
4359
|
+
loaderResult = await runRouteServerHook(route, ctx);
|
|
4256
4360
|
if (!loaderResult.theme) {
|
|
4257
4361
|
loaderResult.theme = theme;
|
|
4258
4362
|
}
|
|
@@ -4271,8 +4375,18 @@ async function handlePageRequestInternal(options) {
|
|
|
4271
4375
|
}
|
|
4272
4376
|
}
|
|
4273
4377
|
}
|
|
4378
|
+
const combinedProps = {
|
|
4379
|
+
...layoutProps,
|
|
4380
|
+
// Props from layouts (stable)
|
|
4381
|
+
...loaderResult.props || {}
|
|
4382
|
+
// Props from page (overrides layout)
|
|
4383
|
+
};
|
|
4384
|
+
const combinedLoaderResult = {
|
|
4385
|
+
...loaderResult,
|
|
4386
|
+
props: combinedProps
|
|
4387
|
+
};
|
|
4274
4388
|
if (isDataReq) {
|
|
4275
|
-
handleDataResponse(res,
|
|
4389
|
+
handleDataResponse(res, combinedLoaderResult, theme);
|
|
4276
4390
|
return;
|
|
4277
4391
|
}
|
|
4278
4392
|
if (loaderResult.redirect) {
|
|
@@ -4287,7 +4401,7 @@ async function handlePageRequestInternal(options) {
|
|
|
4287
4401
|
}
|
|
4288
4402
|
return;
|
|
4289
4403
|
}
|
|
4290
|
-
const initialData = buildInitialData(urlPath, params,
|
|
4404
|
+
const initialData = buildInitialData(urlPath, params, combinedLoaderResult);
|
|
4291
4405
|
const appTree = buildAppTree(route, params, initialData.props);
|
|
4292
4406
|
const chunkName = routeChunks[route.pattern];
|
|
4293
4407
|
let chunkHref = null;
|
|
@@ -4303,7 +4417,7 @@ async function handlePageRequestInternal(options) {
|
|
|
4303
4417
|
appTree,
|
|
4304
4418
|
initialData,
|
|
4305
4419
|
routerData,
|
|
4306
|
-
meta:
|
|
4420
|
+
meta: combinedLoaderResult.metadata,
|
|
4307
4421
|
titleFallback: "Loly framework",
|
|
4308
4422
|
descriptionFallback: "Loly demo",
|
|
4309
4423
|
chunkHref,
|
|
@@ -4324,8 +4438,8 @@ async function handlePageRequestInternal(options) {
|
|
|
4324
4438
|
},
|
|
4325
4439
|
onShellError(err) {
|
|
4326
4440
|
didError = true;
|
|
4327
|
-
const
|
|
4328
|
-
|
|
4441
|
+
const reqLogger2 = getRequestLogger(req);
|
|
4442
|
+
reqLogger2.error("SSR shell error", err, { route: matched?.route?.pattern || "unknown" });
|
|
4329
4443
|
if (!res.headersSent && errorPage) {
|
|
4330
4444
|
renderErrorPageWithStream(errorPage, req, res, err, routeChunks, theme, projectRoot, env);
|
|
4331
4445
|
} else if (!res.headersSent) {
|
|
@@ -4337,8 +4451,8 @@ async function handlePageRequestInternal(options) {
|
|
|
4337
4451
|
},
|
|
4338
4452
|
onError(err) {
|
|
4339
4453
|
didError = true;
|
|
4340
|
-
const
|
|
4341
|
-
|
|
4454
|
+
const reqLogger2 = getRequestLogger(req);
|
|
4455
|
+
reqLogger2.error("SSR error", err, { route: matched?.route?.pattern || "unknown" });
|
|
4342
4456
|
}
|
|
4343
4457
|
});
|
|
4344
4458
|
req.on("close", () => {
|
|
@@ -4355,11 +4469,39 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
|
|
|
4355
4469
|
pathname: req.path,
|
|
4356
4470
|
locals: { error }
|
|
4357
4471
|
};
|
|
4358
|
-
|
|
4472
|
+
const layoutProps = {};
|
|
4473
|
+
const reqLogger = getRequestLogger(req);
|
|
4474
|
+
if (errorPage.layoutServerHooks && errorPage.layoutServerHooks.length > 0) {
|
|
4475
|
+
for (let i = 0; i < errorPage.layoutServerHooks.length; i++) {
|
|
4476
|
+
const layoutServerHook = errorPage.layoutServerHooks[i];
|
|
4477
|
+
if (layoutServerHook) {
|
|
4478
|
+
try {
|
|
4479
|
+
const layoutResult = await layoutServerHook(ctx);
|
|
4480
|
+
if (layoutResult.props) {
|
|
4481
|
+
Object.assign(layoutProps, layoutResult.props);
|
|
4482
|
+
}
|
|
4483
|
+
} catch (err) {
|
|
4484
|
+
reqLogger.warn(`Layout server hook ${i} failed for error page`, {
|
|
4485
|
+
error: err,
|
|
4486
|
+
layoutFile: errorPage.layoutFiles[i]
|
|
4487
|
+
});
|
|
4488
|
+
}
|
|
4489
|
+
}
|
|
4490
|
+
}
|
|
4491
|
+
}
|
|
4492
|
+
let loaderResult = await runRouteServerHook(errorPage, ctx);
|
|
4359
4493
|
if (!loaderResult.theme && theme) {
|
|
4360
4494
|
loaderResult.theme = theme;
|
|
4361
4495
|
}
|
|
4362
|
-
const
|
|
4496
|
+
const combinedProps = {
|
|
4497
|
+
...layoutProps,
|
|
4498
|
+
...loaderResult.props || {}
|
|
4499
|
+
};
|
|
4500
|
+
const combinedLoaderResult = {
|
|
4501
|
+
...loaderResult,
|
|
4502
|
+
props: combinedProps
|
|
4503
|
+
};
|
|
4504
|
+
const initialData = buildInitialData(req.path, { error: String(error) }, combinedLoaderResult);
|
|
4363
4505
|
const routerData = buildRouterData(req);
|
|
4364
4506
|
initialData.error = true;
|
|
4365
4507
|
if (isDataReq) {
|
|
@@ -4369,8 +4511,8 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
|
|
|
4369
4511
|
error: true,
|
|
4370
4512
|
message: String(error),
|
|
4371
4513
|
props: initialData.props,
|
|
4372
|
-
metadata:
|
|
4373
|
-
theme:
|
|
4514
|
+
metadata: combinedLoaderResult.metadata ?? null,
|
|
4515
|
+
theme: combinedLoaderResult.theme ?? theme ?? null
|
|
4374
4516
|
}));
|
|
4375
4517
|
return;
|
|
4376
4518
|
}
|
|
@@ -4392,7 +4534,7 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
|
|
|
4392
4534
|
appTree,
|
|
4393
4535
|
initialData,
|
|
4394
4536
|
routerData,
|
|
4395
|
-
meta:
|
|
4537
|
+
meta: combinedLoaderResult.metadata ?? null,
|
|
4396
4538
|
titleFallback: "Error",
|
|
4397
4539
|
descriptionFallback: "An error occurred",
|
|
4398
4540
|
chunkHref,
|
|
@@ -4413,8 +4555,8 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
|
|
|
4413
4555
|
},
|
|
4414
4556
|
onShellError(err) {
|
|
4415
4557
|
didError = true;
|
|
4416
|
-
const
|
|
4417
|
-
|
|
4558
|
+
const reqLogger2 = getRequestLogger(req);
|
|
4559
|
+
reqLogger2.error("Error rendering error page", err, { type: "shellError" });
|
|
4418
4560
|
if (!res.headersSent) {
|
|
4419
4561
|
res.statusCode = 500;
|
|
4420
4562
|
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
@@ -4424,8 +4566,8 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
|
|
|
4424
4566
|
},
|
|
4425
4567
|
onError(err) {
|
|
4426
4568
|
didError = true;
|
|
4427
|
-
const
|
|
4428
|
-
|
|
4569
|
+
const reqLogger2 = getRequestLogger(req);
|
|
4570
|
+
reqLogger2.error("Error in error page", err);
|
|
4429
4571
|
}
|
|
4430
4572
|
});
|
|
4431
4573
|
req.on("close", () => {
|
|
@@ -4866,26 +5008,22 @@ async function startServer(options = {}) {
|
|
|
4866
5008
|
});
|
|
4867
5009
|
httpServer.listen(port, host, () => {
|
|
4868
5010
|
if (isDev) {
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
5011
|
+
const reset = "\x1B[0m";
|
|
5012
|
+
const cyan = "\x1B[36m";
|
|
5013
|
+
const green = "\x1B[32m";
|
|
5014
|
+
const dim = "\x1B[2m";
|
|
5015
|
+
const bold = "\x1B[1m";
|
|
5016
|
+
const url = `http://${host === "0.0.0.0" ? "localhost" : host}:${port}`;
|
|
5017
|
+
console.log();
|
|
5018
|
+
console.log(`${bold}${green}\u2713${reset} ${bold}Dev server ready${reset}`);
|
|
5019
|
+
console.log(`${dim} Local:${reset} ${cyan}${url}${reset}`);
|
|
5020
|
+
if (routes.length > 0 || apiRoutes.length > 0 || wssRoutes.length > 0) {
|
|
5021
|
+
console.log(`${dim} Routes:${reset} ${routes.length} pages, ${apiRoutes.length} API, ${wssRoutes.length} WSS`);
|
|
5022
|
+
}
|
|
5023
|
+
console.log();
|
|
4875
5024
|
} else {
|
|
4876
|
-
const
|
|
4877
|
-
|
|
4878
|
-
url: `http://${host}:${port}`,
|
|
4879
|
-
appDir,
|
|
4880
|
-
buildDir
|
|
4881
|
-
});
|
|
4882
|
-
logger3.info("\u{1F9ED} Reading compiled routes from", { appDir });
|
|
4883
|
-
logger3.info("\u{1F4E6} Client served from", {
|
|
4884
|
-
path: `/static (${buildDir}/client)`
|
|
4885
|
-
});
|
|
4886
|
-
logger3.info("\u{1F4C4} SSG served from", {
|
|
4887
|
-
path: `${buildDir}/ssg (if exists)`
|
|
4888
|
-
});
|
|
5025
|
+
const url = `http://${host}:${port}`;
|
|
5026
|
+
console.log(`\u{1F680} Server running on ${url}`);
|
|
4889
5027
|
}
|
|
4890
5028
|
});
|
|
4891
5029
|
}
|