@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/cli.cjs CHANGED
@@ -169,7 +169,7 @@ function loadLayoutsForDir(pageDir, appDir) {
169
169
  };
170
170
  }
171
171
 
172
- // modules/router/loader.ts
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 loadLoaderForDir(currentDir) {
185
- const loaderTs = import_path2.default.join(currentDir, `${NAMING.SERVER_HOOK}.ts`);
186
- const loaderJs = import_path2.default.join(currentDir, `${NAMING.SERVER_HOOK}.js`);
187
- const file = import_fs2.default.existsSync(loaderTs) ? loaderTs : import_fs2.default.existsSync(loaderJs) ? loaderJs : null;
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
- loader: null,
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][loader] Error loading server hook from ${file}:`,
209
+ `[framework][server-hook] Error loading server hook from ${file}:`,
208
210
  error
209
211
  );
210
212
  return {
211
213
  middlewares: [],
212
- loader: null,
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 loader = typeof mod?.[NAMING.GET_SERVER_DATA_FN] === "function" ? mod[NAMING.GET_SERVER_DATA_FN] : null;
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
- loader,
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 { middlewares, loader, dynamic, generateStaticParams } = loadLoaderForDir(currentDir);
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 { middlewares, loader, dynamic, generateStaticParams } = loadLoaderForDir(pageDir);
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 { middlewares, loader, dynamic, generateStaticParams } = loadLoaderForDir(notFoundDir);
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 { middlewares, loader, dynamic, generateStaticParams } = loadLoaderForDir(appDir);
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/loader.ts
4341
- async function runRouteLoader(route, ctx) {
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
- let loaderResult2 = await runRouteLoader(notFoundPage, ctx2);
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 initialData2 = buildInitialData(urlPath, {}, loaderResult2);
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: loaderResult2.metadata ?? null,
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 reqLogger = getRequestLogger(req);
4530
- reqLogger.error("SSR shell error", err, { route: "not-found" });
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 reqLogger = getRequestLogger(req);
4543
- reqLogger.error("SSR error", err, { route: "not-found" });
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 runRouteLoader(route, ctx);
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, loaderResult, theme);
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, loaderResult);
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: loaderResult.metadata,
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 reqLogger = getRequestLogger(req);
4640
- reqLogger.error("SSR shell error", err, { route: matched?.route?.pattern || "unknown" });
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 reqLogger = getRequestLogger(req);
4653
- reqLogger.error("SSR error", err, { route: matched?.route?.pattern || "unknown" });
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
- let loaderResult = await runRouteLoader(errorPage, ctx);
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 initialData = buildInitialData(req.path, { error: String(error) }, loaderResult);
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: loaderResult.metadata ?? null,
4685
- theme: loaderResult.theme ?? theme ?? null
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: loaderResult.metadata ?? null,
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 reqLogger = getRequestLogger(req);
4729
- reqLogger.error("Error rendering error page", err, { type: "shellError" });
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 reqLogger = getRequestLogger(req);
4740
- reqLogger.error("Error in error page", err);
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
- logger3.info("\u{1F680} Dev server running", {
5113
- url: `http://${host}:${port}`,
5114
- appDir
5115
- });
5116
- logger3.info("\u{1F9ED} Reading routes from", { appDir });
5117
- logger3.info("\u{1F4E6} Client served from /static/client.js");
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 buildDir = config.directories.build;
5120
- logger3.info("\u{1F680} Prod server running", {
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
  }