@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/dist/index.cjs CHANGED
@@ -246,7 +246,7 @@ function loadLayoutsForDir(pageDir, appDir) {
246
246
  };
247
247
  }
248
248
 
249
- // modules/router/loader.ts
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 loadLoaderForDir(currentDir) {
262
- const loaderTs = import_path3.default.join(currentDir, `${NAMING.SERVER_HOOK}.ts`);
263
- const loaderJs = import_path3.default.join(currentDir, `${NAMING.SERVER_HOOK}.js`);
264
- const file = import_fs3.default.existsSync(loaderTs) ? loaderTs : import_fs3.default.existsSync(loaderJs) ? loaderJs : null;
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
- loader: null,
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][loader] Error loading server hook from ${file}:`,
286
+ `[framework][server-hook] Error loading server hook from ${file}:`,
285
287
  error
286
288
  );
287
289
  return {
288
290
  middlewares: [],
289
- loader: null,
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 loader = typeof mod?.[NAMING.GET_SERVER_DATA_FN] === "function" ? mod[NAMING.GET_SERVER_DATA_FN] : null;
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
- loader,
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 { middlewares, loader, dynamic, generateStaticParams } = loadLoaderForDir(currentDir);
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 { middlewares, loader, dynamic, generateStaticParams } = loadLoaderForDir(pageDir);
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 { middlewares, loader, dynamic, generateStaticParams } = loadLoaderForDir(notFoundDir);
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 { middlewares, loader, dynamic, generateStaticParams } = loadLoaderForDir(appDir);
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/loader.ts
4029
- async function runRouteLoader(route, ctx) {
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
- let loaderResult2 = await runRouteLoader(notFoundPage, ctx2);
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 initialData2 = buildInitialData(urlPath, {}, loaderResult2);
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: loaderResult2.metadata ?? null,
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 reqLogger = getRequestLogger(req);
4218
- reqLogger.error("SSR shell error", err, { route: "not-found" });
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 reqLogger = getRequestLogger(req);
4231
- reqLogger.error("SSR error", err, { route: "not-found" });
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 runRouteLoader(route, ctx);
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, loaderResult, theme);
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, loaderResult);
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: loaderResult.metadata,
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 reqLogger = getRequestLogger(req);
4328
- reqLogger.error("SSR shell error", err, { route: matched?.route?.pattern || "unknown" });
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 reqLogger = getRequestLogger(req);
4341
- reqLogger.error("SSR error", err, { route: matched?.route?.pattern || "unknown" });
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
- let loaderResult = await runRouteLoader(errorPage, ctx);
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 initialData = buildInitialData(req.path, { error: String(error) }, loaderResult);
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: loaderResult.metadata ?? null,
4373
- theme: loaderResult.theme ?? theme ?? null
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: loaderResult.metadata ?? null,
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 reqLogger = getRequestLogger(req);
4417
- reqLogger.error("Error rendering error page", err, { type: "shellError" });
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 reqLogger = getRequestLogger(req);
4428
- reqLogger.error("Error in error page", err);
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
- logger3.info("\u{1F680} Dev server running", {
4870
- url: `http://${host}:${port}`,
4871
- appDir
4872
- });
4873
- logger3.info("\u{1F9ED} Reading routes from", { appDir });
4874
- logger3.info("\u{1F4E6} Client served from /static/client.js");
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 buildDir = config.directories.build;
4877
- logger3.info("\u{1F680} Prod server running", {
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
  }