@noego/app 0.0.22 → 0.0.23

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noego/app",
3
- "version": "0.0.22",
3
+ "version": "0.0.23",
4
4
  "description": "Production build tool for Dinner/Forge apps.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -33,6 +33,7 @@
33
33
  "license": "MIT",
34
34
  "author": "App Build CLI",
35
35
  "dependencies": {
36
+ "@noego/logger": "file:../logger",
36
37
  "deepmerge": "^4.3.1",
37
38
  "glob-parent": "^6.0.2",
38
39
  "http-proxy": "^1.18.1",
@@ -1,10 +1,13 @@
1
1
  import fs from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
  // No URL utilities needed when not vendoring Forge
4
+ import { getLogger } from '@noego/logger';
4
5
 
5
6
  import { runCommand } from '../utils/command.js';
6
7
  import { fixImportExtensions } from './fix-imports.js';
7
8
 
9
+ const log = getLogger('app');
10
+
8
11
  export async function buildServer(context, discovery) {
9
12
  const { logger } = context;
10
13
  logger.info('Building server bundle');
@@ -182,7 +185,7 @@ async function mirrorUiModules(context) {
182
185
 
183
186
  // Overlay compiled UI outputs from tsc emit so .ts becomes .js under mirrored UI root
184
187
  if (config.verbose) {
185
- console.log('[server] overlayUi called:', {
188
+ log.debug('overlayUi called:', {
186
189
  'config.ui': config.ui,
187
190
  'config.ui.rootDir': config.ui?.rootDir,
188
191
  'config.rootDir': config.rootDir
package/src/build/ssr.js CHANGED
@@ -1,11 +1,14 @@
1
1
  import fs from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
  import { pathToFileURL } from 'node:url';
4
+ import { getLogger } from '@noego/logger';
4
5
 
5
6
  import { buildWithVite } from './vite.js';
6
7
  import { createUiBuildConfig } from './ui-common.js';
7
8
  import { resolveClientEntry } from './client.js';
8
9
 
10
+ const log = getLogger('app');
11
+
9
12
  export async function resolveSsrBuildConfig(context, discovery) {
10
13
  const { config } = context;
11
14
  const { entryAbsolute } = await resolveClientEntry(context);
@@ -352,7 +355,7 @@ function buildSsrManifest(config, discovery) {
352
355
 
353
356
  function componentToSsrPath(componentPath, config) {
354
357
  if (config.verbose) {
355
- console.log('[ssr] componentToSsrPath called:', {
358
+ log.debug('componentToSsrPath called:', {
356
359
  componentPath,
357
360
  'config.ui': config.ui,
358
361
  'config.ui.rootDir': config.ui?.rootDir,
package/src/cli.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { readFile } from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
  import process from 'node:process';
4
+ import { getLogger } from '@noego/logger';
4
5
 
5
6
  import { parseCliArgs, printHelpAndExit } from './args.js';
6
7
  import { loadBuildConfig } from './config.js';
@@ -9,6 +10,8 @@ import { runServe } from './commands/serve.js';
9
10
  import { runPreview } from './commands/preview.js';
10
11
  import { runDev } from './commands/dev.js';
11
12
 
13
+ const log = getLogger('app');
14
+
12
15
  export async function runCli(argv = process.argv.slice(2)) {
13
16
  try {
14
17
  const { command, options } = parseCliArgs(argv);
@@ -56,7 +59,7 @@ export async function runCli(argv = process.argv.slice(2)) {
56
59
 
57
60
  process.stderr.write(`[app] ${error?.message || error}\n`);
58
61
  if (process.env.APP_DEBUG || process.env.HAMMER_DEBUG) {
59
- console.error(error);
62
+ log.error(error);
60
63
  }
61
64
  process.exitCode = 1;
62
65
  }
@@ -11,8 +11,10 @@ import { waitForPortFree } from '../utils/port.js';
11
11
  import { stopProcess, killProcessTree as killProcessTreeUtil } from '../utils/process-observable.js';
12
12
  import { watcherToObservable, FileEventType } from '../utils/file-watcher-observable.js';
13
13
  import treeKill from 'tree-kill';
14
+ import { getLogger } from '@noego/logger';
14
15
 
15
16
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
17
+ const log = getLogger('app');
16
18
 
17
19
  /**
18
20
  * Kill a process and all its descendants (entire process tree)
@@ -287,12 +289,12 @@ async function runSplitServeNoWatch(tsxExecutable, tsxArgs, baseEnv, routerPort,
287
289
  logger.info(`Starting frontend on port ${frontendPort}...`);
288
290
  logger.info(`Starting backend on port ${backendPort}...`);
289
291
 
290
- console.log('[dev.js] Port assignments:');
291
- console.log(' routerPort:', routerPort);
292
- console.log(' frontendPort:', frontendPort);
293
- console.log(' backendPort:', backendPort);
294
- console.log('[dev.js] baseEnv NOEGO_PORT:', baseEnv.NOEGO_PORT);
295
- console.log('[dev.js] baseEnv NOEGO_BACKEND_PORT:', baseEnv.NOEGO_BACKEND_PORT);
292
+ log.debug('Port assignments:');
293
+ log.debug(' routerPort:', routerPort);
294
+ log.debug(' frontendPort:', frontendPort);
295
+ log.debug(' backendPort:', backendPort);
296
+ log.debug('baseEnv NOEGO_PORT:', baseEnv.NOEGO_PORT);
297
+ log.debug('baseEnv NOEGO_BACKEND_PORT:', baseEnv.NOEGO_BACKEND_PORT);
296
298
 
297
299
  // Spawn backend process
298
300
  const backendEnv = {
@@ -301,7 +303,7 @@ async function runSplitServeNoWatch(tsxExecutable, tsxArgs, baseEnv, routerPort,
301
303
  NOEGO_PORT: String(backendPort)
302
304
  };
303
305
 
304
- console.log('[dev.js] Backend env NOEGO_PORT:', backendEnv.NOEGO_PORT);
306
+ log.debug('Backend env NOEGO_PORT:', backendEnv.NOEGO_PORT);
305
307
 
306
308
  const backendProc = spawn(tsxExecutable, tsxArgs, {
307
309
  cwd: rootDir,
@@ -318,7 +320,7 @@ async function runSplitServeNoWatch(tsxExecutable, tsxArgs, baseEnv, routerPort,
318
320
  // Frontend doesn't proxy to backend anymore - router handles that
319
321
  };
320
322
 
321
- console.log('[dev.js] Frontend env NOEGO_PORT:', frontendEnv.NOEGO_PORT);
323
+ log.debug('Frontend env NOEGO_PORT:', frontendEnv.NOEGO_PORT);
322
324
 
323
325
  const frontendProc = spawn(tsxExecutable, tsxArgs, {
324
326
  cwd: rootDir,
@@ -1,4 +1,5 @@
1
1
  import util from 'node:util';
2
+ import { getLogger } from '@noego/logger';
2
3
 
3
4
  import { createBuildContext } from '../build/context.js';
4
5
  import { discoverProject } from '../build/openapi.js';
@@ -9,12 +10,13 @@ import {
9
10
  resolveRecursiveRendererBuildConfig
10
11
  } from '../build/ssr.js';
11
12
 
13
+ const log = getLogger('app');
12
14
  const INSPECT_OPTIONS = { depth: null, colors: false };
13
15
 
14
16
  function printSection(heading, payload) {
15
- console.log(`========== ${heading} ==========`);
16
- console.log(util.inspect(payload, INSPECT_OPTIONS));
17
- console.log();
17
+ log.info(`========== ${heading} ==========`);
18
+ log.info(util.inspect(payload, INSPECT_OPTIONS));
19
+ log.info('');
18
20
  }
19
21
 
20
22
  export async function runPreview(config) {
@@ -1,16 +1,19 @@
1
1
  import { runRuntime } from '../runtime/runtime.js';
2
+ import { getLogger } from '@noego/logger';
3
+
4
+ const log = getLogger('app');
2
5
 
3
6
  // This file is run via tsx, so it can import TypeScript files
4
7
  const configFilePath = process.env.NOEGO_CONFIG_FILE;
5
8
  const cliRoot = process.env.NOEGO_CLI_ROOT;
6
9
 
7
10
  if (!configFilePath) {
8
- console.error('NOEGO_CONFIG_FILE environment variable is required');
11
+ log.error('NOEGO_CONFIG_FILE environment variable is required');
9
12
  process.exit(1);
10
13
  }
11
14
 
12
15
  runRuntime(configFilePath, cliRoot || undefined).catch((error) => {
13
- console.error('Runtime error:', error);
16
+ log.error('Runtime error:', error);
14
17
  process.exit(1);
15
18
  });
16
19
 
package/src/config.js CHANGED
@@ -48,7 +48,7 @@ export async function loadBuildConfig(cliOptions = {}, { cwd = process.cwd() } =
48
48
  const uiRelRoot = uiRootDir ? path.relative(config.root, uiRootDir) : null;
49
49
 
50
50
  if (cliOptions.verbose) {
51
- console.log('[config] uiRootDir calculation:', {
51
+ log.debug('uiRootDir calculation:', {
52
52
  'config.client': config.client,
53
53
  'config.client.main_abs': config.client?.main_abs,
54
54
  'uiRootDir': uiRootDir,
package/src/logger.js CHANGED
@@ -1,16 +1,5 @@
1
- import process from 'node:process';
1
+ import { getLogger } from '@noego/logger';
2
2
 
3
- export function createLogger({ verbose = false } = {}) {
4
- const debugEnabled = verbose || Boolean(process.env.APP_DEBUG || process.env.HAMMER_DEBUG);
5
-
6
- return {
7
- info: (...args) => console.log('[app]', ...args),
8
- warn: (...args) => console.warn('[app]', ...args),
9
- error: (...args) => console.error('[app]', ...args),
10
- debug: (...args) => {
11
- if (debugEnabled) {
12
- console.log('[app:debug]', ...args);
13
- }
14
- }
15
- };
3
+ export function createLogger() {
4
+ return getLogger('app');
16
5
  }
@@ -4,9 +4,16 @@ import { fileURLToPath } from 'node:url';
4
4
  import { createRequire } from 'node:module';
5
5
  import { loadConfig } from './config-loader.js';
6
6
  import { setContext } from '../client.js';
7
+ import { getLogger } from '@noego/logger';
7
8
 
8
9
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
10
 
11
+ const log = getLogger('app');
12
+ const proxyLog = getLogger('app:proxy');
13
+ const routerLog = getLogger('app:router');
14
+ const frontendLog = getLogger('app:frontend');
15
+ const backendLog = getLogger('app:backend');
16
+
10
17
  function toFileUrl(filePath) {
11
18
  return `file://${filePath}`;
12
19
  }
@@ -148,7 +155,7 @@ async function setupProxyFirst(app, backendPort, config) {
148
155
  logLevel: 'silent', // We'll do our own logging
149
156
  onProxyReq: (proxyReq, req, res) => {
150
157
  if (config.mode !== 'production') {
151
- console.log(`[proxy] ${req.method} ${req.url} -> backend:${backendPort}`);
158
+ proxyLog.debug(`${req.method} ${req.url} -> backend:${backendPort}`);
152
159
  }
153
160
  }
154
161
  });
@@ -175,18 +182,18 @@ async function setupProxyFirst(app, backendPort, config) {
175
182
  }
176
183
  } catch (err) {
177
184
  // On any error, fall back to Vite/Forge
178
- console.error('[proxy] Error checking backend:', err);
185
+ proxyLog.error('Error checking backend:', err);
179
186
  next();
180
187
  }
181
188
  });
182
189
 
183
- console.log(`[app] Dynamic proxy configured: checking backend at http://localhost:${backendPort} for non-asset routes`);
190
+ log.info(`Dynamic proxy configured: checking backend at http://localhost:${backendPort} for non-asset routes`);
184
191
  return;
185
192
  } catch {
186
- console.warn('http-proxy-middleware not available, skipping proxy setup');
193
+ log.warn('http-proxy-middleware not available, skipping proxy setup');
187
194
  }
188
195
  } catch (error) {
189
- console.error('[app] Failed to setup proxy:', error);
196
+ log.error('Failed to setup proxy:', error);
190
197
  }
191
198
  }
192
199
 
@@ -257,12 +264,12 @@ async function setupProxy(app, backendPort, config) {
257
264
  logLevel: config.mode === 'production' ? 'error' : 'info',
258
265
  onProxyReq: (proxyReq, req, res) => {
259
266
  if (config.mode !== 'production') {
260
- console.log(`[proxy] ${req.method} ${req.url} -> backend:${backendPort}`);
267
+ proxyLog.debug(`${req.method} ${req.url} -> backend:${backendPort}`);
261
268
  }
262
269
  }
263
270
  });
264
271
  installFallback(proxyMiddleware);
265
- console.log(`[app] Proxy fallback configured: unhandled requests will be forwarded to http://localhost:${backendPort}`);
272
+ log.info(`Proxy fallback configured: unhandled requests will be forwarded to http://localhost:${backendPort}`);
266
273
  return;
267
274
  } catch {
268
275
  // Fallback to express-http-proxy if http-proxy-middleware not available
@@ -281,13 +288,13 @@ async function setupProxy(app, backendPort, config) {
281
288
  installFallback(proxyMiddleware);
282
289
  return;
283
290
  } catch {
284
- console.warn('Proxy dependencies not found; falling back to built-in proxy handler.');
291
+ log.warn('Proxy dependencies not found; falling back to built-in proxy handler.');
285
292
  }
286
293
 
287
294
  const nativeProxy = (req, res, next) => {
288
295
  const targetPath = req.originalUrl || req.url || '/';
289
296
  if (config.mode !== 'production') {
290
- console.log(`[app][proxy] Forwarding ${req.method} ${targetPath} -> http://localhost:${backendPort}`);
297
+ proxyLog.debug(`Forwarding ${req.method} ${targetPath} -> http://localhost:${backendPort}`);
291
298
  }
292
299
  const requestHeaders = {
293
300
  ...req.headers,
@@ -312,7 +319,7 @@ async function setupProxy(app, backendPort, config) {
312
319
  }
313
320
  }
314
321
  backendResponse.on('error', (err) => {
315
- console.error('[app][proxy] Response error:', err.message);
322
+ proxyLog.error('Response error:', err.message);
316
323
  if (!res.headersSent) {
317
324
  res.status(502).end();
318
325
  }
@@ -322,7 +329,7 @@ async function setupProxy(app, backendPort, config) {
322
329
  );
323
330
 
324
331
  backendRequest.on('error', (err) => {
325
- console.error('[app][proxy] Request error:', err.message);
332
+ proxyLog.error('Request error:', err.message);
326
333
  if (!res.headersSent) {
327
334
  res.status(502).end();
328
335
  }
@@ -362,7 +369,7 @@ async function setupProxy(app, backendPort, config) {
362
369
  installFallback(nativeProxy);
363
370
  return;
364
371
  } catch (err) {
365
- console.error(`Failed to setup proxy: ${err.message}`);
372
+ log.error(`Failed to setup proxy: ${err.message}`);
366
373
  throw err;
367
374
  }
368
375
  }
@@ -385,26 +392,26 @@ async function runBackendService(config) {
385
392
  const backendPort = process.env.NOEGO_SERVICE === 'backend' ?
386
393
  parseInt(process.env.NOEGO_PORT) : config.dev.backendPort;
387
394
 
388
- console.log('[backend] NOEGO_SERVICE:', process.env.NOEGO_SERVICE);
389
- console.log('[backend] NOEGO_PORT:', process.env.NOEGO_PORT);
390
- console.log('[backend] config.dev.backendPort:', config.dev.backendPort);
391
- console.log('[backend] Using port:', backendPort);
395
+ backendLog.debug('NOEGO_SERVICE:', process.env.NOEGO_SERVICE);
396
+ backendLog.debug('NOEGO_PORT:', process.env.NOEGO_PORT);
397
+ backendLog.debug('config.dev.backendPort:', config.dev.backendPort);
398
+ backendLog.debug('Using port:', backendPort);
392
399
 
393
400
  const httpServer = http.createServer(backendApp);
394
401
 
395
402
  httpServer.on('error', (err) => {
396
403
  if (err.code === 'EADDRINUSE') {
397
- console.error(`[ERROR] Port ${backendPort} is already in use (EADDRINUSE)`);
398
- console.error(`[ERROR] This likely means a stale process is still running.`);
399
- console.error(`[ERROR] The dev server will attempt to recover...`);
404
+ backendLog.error(`Port ${backendPort} is already in use (EADDRINUSE)`);
405
+ backendLog.error(`This likely means a stale process is still running.`);
406
+ backendLog.error(`The dev server will attempt to recover...`);
400
407
  } else {
401
- console.error(`[ERROR] Server error on port ${backendPort}:`, err.message);
408
+ backendLog.error(`Server error on port ${backendPort}:`, err.message);
402
409
  }
403
410
  process.exit(1);
404
411
  });
405
412
 
406
413
  httpServer.listen(backendPort, '0.0.0.0', () => {
407
- console.log(`Backend server running on http://localhost:${backendPort}`);
414
+ backendLog.info(`Backend server running on http://localhost:${backendPort}`);
408
415
  });
409
416
 
410
417
  return backendApp;
@@ -449,24 +456,24 @@ async function runFrontendService(config) {
449
456
  const frontendPort = process.env.NOEGO_SERVICE === 'frontend' ?
450
457
  parseInt(process.env.NOEGO_PORT) : config.dev.port;
451
458
 
452
- console.log('[frontend] NOEGO_SERVICE:', process.env.NOEGO_SERVICE);
453
- console.log('[frontend] NOEGO_PORT:', process.env.NOEGO_PORT);
454
- console.log('[frontend] config.dev.port:', config.dev.port);
455
- console.log('[frontend] Using port:', frontendPort);
459
+ frontendLog.debug('NOEGO_SERVICE:', process.env.NOEGO_SERVICE);
460
+ frontendLog.debug('NOEGO_PORT:', process.env.NOEGO_PORT);
461
+ frontendLog.debug('config.dev.port:', config.dev.port);
462
+ frontendLog.debug('Using port:', frontendPort);
456
463
 
457
464
  httpServer.on('error', (err) => {
458
465
  if (err.code === 'EADDRINUSE') {
459
- console.error(`[ERROR] Port ${frontendPort} is already in use (EADDRINUSE)`);
460
- console.error(`[ERROR] This likely means a stale process is still running.`);
461
- console.error(`[ERROR] The dev server will attempt to recover...`);
466
+ frontendLog.error(`Port ${frontendPort} is already in use (EADDRINUSE)`);
467
+ frontendLog.error(`This likely means a stale process is still running.`);
468
+ frontendLog.error(`The dev server will attempt to recover...`);
462
469
  } else {
463
- console.error(`[ERROR] Server error on port ${frontendPort}:`, err.message);
470
+ frontendLog.error(`Server error on port ${frontendPort}:`, err.message);
464
471
  }
465
472
  process.exit(1);
466
473
  });
467
474
 
468
475
  httpServer.listen(frontendPort, '0.0.0.0', () => {
469
- console.log(`Frontend server running on http://localhost:${frontendPort}`);
476
+ frontendLog.info(`Frontend server running on http://localhost:${frontendPort}`);
470
477
  });
471
478
 
472
479
  return frontendApp;
@@ -546,7 +553,7 @@ async function runRouterService(config) {
546
553
 
547
554
  // Debug logging for authentication-related headers
548
555
  if (headers.cookie || headers.authorization) {
549
- console.log(`[router] Forwarding auth headers to ${serviceName}:`, {
556
+ routerLog.debug(`Forwarding auth headers to ${serviceName}:`, {
550
557
  cookie: headers.cookie ? 'present' : 'absent',
551
558
  authorization: headers.authorization ? 'present' : 'absent'
552
559
  });
@@ -565,7 +572,7 @@ async function runRouterService(config) {
565
572
 
566
573
  // Debug logging for authentication response headers
567
574
  if (proxyRes.headers['set-cookie'] || proxyRes.statusCode === 401 || proxyRes.statusCode === 403) {
568
- console.log(`[router] Response from ${serviceName}:`, {
575
+ routerLog.debug(`Response from ${serviceName}:`, {
569
576
  status: proxyRes.statusCode,
570
577
  'set-cookie': proxyRes.headers['set-cookie'] ? 'present' : 'absent'
571
578
  });
@@ -583,7 +590,7 @@ async function runRouterService(config) {
583
590
  });
584
591
 
585
592
  proxyReq.on('error', (err) => {
586
- console.error(`[router] Error proxying to ${serviceName}: ${err.message}`);
593
+ routerLog.error(`Error proxying to ${serviceName}: ${err.message}`);
587
594
  resolve({ statusCode: 502, error: err, serviceName });
588
595
  });
589
596
 
@@ -634,7 +641,7 @@ async function runRouterService(config) {
634
641
 
635
642
  if (frontendResult.statusCode === 404) {
636
643
  // Frontend returned 404, try backend
637
- console.log(`[router] Frontend returned 404 for ${method} ${originalUrl}, trying backend...`);
644
+ routerLog.info(`Frontend returned 404 for ${method} ${originalUrl}, trying backend...`);
638
645
  const backendResult = await tryService(backendPort, 'backend');
639
646
 
640
647
  // Send backend response
@@ -679,36 +686,36 @@ async function runRouterService(config) {
679
686
  // Only route to backend if explicitly needed (currently none)
680
687
  const target = `ws://localhost:${frontendPort}`;
681
688
 
682
- console.log(`[router][ws] Routing WebSocket ${url} to ${target}`);
689
+ routerLog.debug(`[ws] Routing WebSocket ${url} to ${target}`);
683
690
 
684
691
  wsProxy.ws(req, socket, head, { target }, (err) => {
685
- console.error('[router][ws] proxy error:', err?.message);
692
+ routerLog.error('[ws] proxy error:', err?.message);
686
693
  try { socket.destroy(); } catch {}
687
694
  });
688
695
  });
689
696
 
690
697
  // Optional: observe proxy-level errors
691
698
  wsProxy.on('error', (err, req, socket) => {
692
- console.error('[router][ws] proxy error (global):', err?.message);
699
+ routerLog.error('[ws] proxy error (global):', err?.message);
693
700
  try { socket?.destroy?.(); } catch {}
694
701
  });
695
702
 
696
703
  httpServer.on('error', (err) => {
697
704
  if (err.code === 'EADDRINUSE') {
698
- console.error(`[ERROR] Port ${routerPort} is already in use (EADDRINUSE)`);
699
- console.error(`[ERROR] This likely means a stale process is still running.`);
700
- console.error(`[ERROR] The dev server will attempt to recover...`);
705
+ routerLog.error(`Port ${routerPort} is already in use (EADDRINUSE)`);
706
+ routerLog.error(`This likely means a stale process is still running.`);
707
+ routerLog.error(`The dev server will attempt to recover...`);
701
708
  } else {
702
- console.error(`[ERROR] Server error on port ${routerPort}:`, err.message);
709
+ routerLog.error(`Server error on port ${routerPort}:`, err.message);
703
710
  }
704
711
  process.exit(1);
705
712
  });
706
713
 
707
714
  httpServer.listen(routerPort, '0.0.0.0', () => {
708
- console.log(`Router server running on http://localhost:${routerPort}`);
709
- console.log(` Proxying to frontend on port ${frontendPort}`);
710
- console.log(` Proxying to backend on port ${backendPort}`);
711
- console.log(` WebSocket support enabled via http-proxy`);
715
+ routerLog.info(`Router server running on http://localhost:${routerPort}`);
716
+ routerLog.info(` Proxying to frontend on port ${frontendPort}`);
717
+ routerLog.info(` Proxying to backend on port ${backendPort}`);
718
+ routerLog.info(` WebSocket support enabled via http-proxy`);
712
719
  });
713
720
 
714
721
  return routerApp;
@@ -762,11 +769,11 @@ export async function runCombinedServices(config, options = {}) {
762
769
 
763
770
  httpServer.on('error', (err) => {
764
771
  if (err.code === 'EADDRINUSE') {
765
- console.error(`[ERROR] Port ${port} is already in use (EADDRINUSE)`);
766
- console.error(`[ERROR] This likely means a stale process is still running.`);
767
- console.error(`[ERROR] The dev server will attempt to recover...`);
772
+ log.error(`Port ${port} is already in use (EADDRINUSE)`);
773
+ log.error(`This likely means a stale process is still running.`);
774
+ log.error(`The dev server will attempt to recover...`);
768
775
  } else {
769
- console.error(`[ERROR] Server error on port ${port}:`, err.message);
776
+ log.error(`Server error on port ${port}:`, err.message);
770
777
  }
771
778
  process.exit(1);
772
779
  });
@@ -776,7 +783,7 @@ export async function runCombinedServices(config, options = {}) {
776
783
  if (hasBackend && config.server?.main_abs) services.push('Backend');
777
784
  if (hasFrontend && config.client?.main_abs) services.push('Frontend');
778
785
  const servicesStr = services.length > 0 ? ` (${services.join(' + ')})` : '';
779
- console.log(`Server running on http://localhost:${port}${servicesStr}`);
786
+ log.info(`Server running on http://localhost:${port}${servicesStr}`);
780
787
  });
781
788
 
782
789
  return app;
package/src/utils/port.js CHANGED
@@ -1,6 +1,9 @@
1
1
  import { Observable, interval, of, throwError } from 'rxjs';
2
2
  import { map, switchMap, filter, take, timeout, catchError } from 'rxjs/operators';
3
3
  import net from 'node:net';
4
+ import { getLogger } from '@noego/logger';
5
+
6
+ const log = getLogger('app');
4
7
 
5
8
  /**
6
9
  * Check if a port is currently free (available for binding)
@@ -67,7 +70,7 @@ export function waitForPortFree(port, timeoutMs = 5000, pollInterval = 50) {
67
70
  }),
68
71
  // Provide graceful fallback on timeout (continue anyway but log warning)
69
72
  catchError((err) => {
70
- console.warn(`[port.js] Warning: ${err.message}. Proceeding anyway.`);
73
+ log.warn(`Warning: ${err.message}. Proceeding anyway.`);
71
74
  return of(undefined);
72
75
  })
73
76
  );
@@ -97,7 +100,7 @@ export function waitForPortInUse(port, timeoutMs = 10000, pollInterval = 100) {
97
100
  }),
98
101
  // Provide graceful fallback on timeout
99
102
  catchError((err) => {
100
- console.warn(`[port.js] Warning: ${err.message}. Proceeding anyway.`);
103
+ log.warn(`Warning: ${err.message}. Proceeding anyway.`);
101
104
  return of(undefined);
102
105
  })
103
106
  );
@@ -1,6 +1,9 @@
1
1
  import { Observable, of, timer, race, EMPTY } from 'rxjs';
2
2
  import { map, switchMap, take, catchError, finalize, tap } from 'rxjs/operators';
3
3
  import { spawn, execSync } from 'node:child_process';
4
+ import { getLogger } from '@noego/logger';
5
+
6
+ const log = getLogger('app');
4
7
 
5
8
  /**
6
9
  * Process event types emitted by spawnProcess observable
@@ -149,7 +152,7 @@ export function stopProcess(proc, gracefulTimeout = 5000, killTreeFn = killProce
149
152
  // Set up force kill timer
150
153
  forceKillTimer = setTimeout(() => {
151
154
  if (!exited && pid) {
152
- console.warn(`[process-observable] Process ${pid} didn't exit gracefully, force killing...`);
155
+ log.warn(`Process ${pid} didn't exit gracefully, force killing...`);
153
156
  killTreeFn(pid, 'SIGKILL');
154
157
  }
155
158
  }, gracefulTimeout);
@@ -211,7 +214,7 @@ export function stopProcessAndVerify(proc, gracefulTimeout = 5000, killTreeFn =
211
214
  switchMap(() => timer(50)),
212
215
  map(() => undefined),
213
216
  catchError((err) => {
214
- console.warn(`[process-observable] Error stopping process: ${err.message}`);
217
+ log.warn(`Error stopping process: ${err.message}`);
215
218
  return of(undefined);
216
219
  })
217
220
  );