@swissjs/swite 0.3.5 → 0.4.2

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.
Files changed (78) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/DIRECTIVE.md +57 -2
  3. package/__tests__/import-rewriter-bug.test.ts +100 -113
  4. package/__tests__/security-r001-r002.test.ts +190 -0
  5. package/dist/build-engine/builder.js +9 -9
  6. package/dist/cli.js +0 -0
  7. package/dist/config/config.d.ts +0 -5
  8. package/dist/config/config.d.ts.map +1 -1
  9. package/dist/dev-engine/handlers/base-handler.d.ts +6 -0
  10. package/dist/dev-engine/handlers/base-handler.d.ts.map +1 -1
  11. package/dist/dev-engine/handlers/base-handler.js +91 -0
  12. package/dist/dev-engine/handlers/ui-handler.d.ts +0 -1
  13. package/dist/dev-engine/handlers/ui-handler.d.ts.map +1 -1
  14. package/dist/dev-engine/handlers/ui-handler.js +2 -64
  15. package/dist/dev-engine/handlers/uix-handler.d.ts +0 -1
  16. package/dist/dev-engine/handlers/uix-handler.d.ts.map +1 -1
  17. package/dist/dev-engine/handlers/uix-handler.js +2 -58
  18. package/dist/dev-engine/hmr/hmr-client-template.js +111 -111
  19. package/dist/dev-engine/hmr/hmr.d.ts +10 -1
  20. package/dist/dev-engine/hmr/hmr.d.ts.map +1 -1
  21. package/dist/dev-engine/hmr/hmr.js +40 -2
  22. package/dist/dev-engine/middleware/middleware-setup.js +4 -3
  23. package/dist/dev-engine/middleware/static-files.d.ts.map +1 -1
  24. package/dist/dev-engine/middleware/static-files.js +145 -62
  25. package/dist/dev-engine/pythonDevManager.js +1 -1
  26. package/dist/dev-engine/router/file-router.d.ts.map +1 -1
  27. package/dist/dev-engine/router/file-router.js +2 -29
  28. package/dist/dev-engine/server.d.ts +7 -0
  29. package/dist/dev-engine/server.d.ts.map +1 -1
  30. package/dist/dev-engine/server.js +31 -3
  31. package/dist/kernel/package-finder.d.ts +0 -8
  32. package/dist/kernel/package-finder.d.ts.map +1 -1
  33. package/dist/kernel/package-finder.js +2 -2
  34. package/dist/kernel/package-registry.d.ts +6 -0
  35. package/dist/kernel/package-registry.d.ts.map +1 -1
  36. package/dist/kernel/package-registry.js +8 -0
  37. package/dist/kernel/workspace.d.ts.map +1 -1
  38. package/dist/kernel/workspace.js +12 -9
  39. package/docs/architecture/build-pipeline.md +97 -97
  40. package/docs/architecture/dev-server.md +87 -87
  41. package/docs/architecture/hmr.md +78 -78
  42. package/docs/architecture/import-rewriting.md +101 -101
  43. package/docs/architecture/index.md +16 -16
  44. package/docs/architecture/python-integration.md +93 -93
  45. package/docs/architecture/resolution.md +92 -92
  46. package/docs/cli/build.md +78 -78
  47. package/docs/cli/dev.md +90 -90
  48. package/docs/cli/index.md +15 -15
  49. package/docs/cli/start.md +45 -45
  50. package/docs/development/contributing.md +74 -74
  51. package/docs/development/index.md +12 -12
  52. package/docs/development/internals.md +101 -101
  53. package/docs/guide/configuration.md +89 -89
  54. package/docs/guide/index.md +13 -13
  55. package/docs/guide/project-structure.md +75 -75
  56. package/docs/guide/quickstart.md +113 -113
  57. package/docs/index.md +16 -16
  58. package/package.json +29 -16
  59. package/src/build-engine/builder.ts +9 -9
  60. package/src/config/config.ts +0 -5
  61. package/src/config/env.ts +98 -98
  62. package/src/dev-engine/handlers/base-handler.ts +109 -0
  63. package/src/dev-engine/handlers/ui-handler.ts +30 -110
  64. package/src/dev-engine/handlers/uix-handler.ts +21 -95
  65. package/src/dev-engine/hmr/hmr-client-template.ts +122 -122
  66. package/src/dev-engine/hmr/hmr.ts +46 -1
  67. package/src/dev-engine/middleware/middleware-setup.ts +354 -354
  68. package/src/dev-engine/middleware/static-files.ts +203 -121
  69. package/src/dev-engine/pythonDevManager.ts +1 -1
  70. package/src/dev-engine/router/file-router.ts +2 -45
  71. package/src/dev-engine/server.ts +33 -3
  72. package/src/kernel/package-finder.ts +2 -2
  73. package/src/kernel/package-registry.ts +9 -0
  74. package/src/kernel/workspace.ts +8 -10
  75. package/src/resolution/cdn/cdn-fallback.ts +40 -40
  76. package/src/resolution/path/path-fixup.ts +27 -27
  77. package/src/resolution/rewriting/import-rewriter.ts +237 -237
  78. package/src/resolution/symlink-registry.ts +114 -114
@@ -26,7 +26,8 @@ export async function setupStaticFiles(
26
26
  app: Express,
27
27
  config: StaticFilesConfig,
28
28
  ): Promise<void> {
29
- console.log(chalk.magenta(`[static-files] setupStaticFiles called with root: ${config.root}`));
29
+ const _debug = process.env["SWITE_DEBUG"] === "1";
30
+ if (_debug) console.log(chalk.magenta(`[static-files] ⚡ setupStaticFiles called with root: ${config.root}`));
30
31
 
31
32
  // Static file serving - ONLY serve public directory
32
33
  // Do NOT serve dist/ folder - it contains old build artifacts with bare imports
@@ -145,11 +146,13 @@ export async function setupStaticFiles(
145
146
 
146
147
  next();
147
148
  });
148
- console.log(
149
- chalk.gray(
150
- ` 📦 Serving workspace node_modules from ${workspaceNodeModules}`,
151
- ),
152
- );
149
+ if (_debug) {
150
+ console.log(
151
+ chalk.gray(
152
+ ` 📦 Serving workspace node_modules from ${workspaceNodeModules}`,
153
+ ),
154
+ );
155
+ }
153
156
  } catch {
154
157
  // Workspace node_modules doesn't exist, skip
155
158
  }
@@ -161,70 +164,94 @@ export async function setupStaticFiles(
161
164
  const workspaceRoot =
162
165
  workspaceRootForNodeModules || (await findWorkspaceRoot(config.root));
163
166
 
164
- console.log(
165
- chalk.blue(`[static-files] Workspace root: ${workspaceRoot}`),
166
- );
167
- console.log(
168
- chalk.blue(`[static-files] App root: ${config.root}`),
169
- );
167
+ if (_debug) {
168
+ console.log(
169
+ chalk.blue(`[static-files] Workspace root: ${workspaceRoot}`),
170
+ );
171
+ }
172
+ if (_debug) {
173
+ console.log(
174
+ chalk.blue(`[static-files] App root: ${config.root}`),
175
+ );
176
+ }
170
177
 
171
178
  // Try to serve lib/ directory - check both workspace root and app root parent
172
179
  let libPath: string | null = null;
173
180
 
174
- console.log(
175
- chalk.blue(`[static-files] Determining lib/ path... workspaceRoot: ${workspaceRoot}, config.root: ${config.root}`),
176
- );
181
+ if (_debug) {
182
+ console.log(
183
+ chalk.blue(`[static-files] Determining lib/ path... workspaceRoot: ${workspaceRoot}, config.root: ${config.root}`),
184
+ );
185
+ }
177
186
 
178
187
  // First, try workspace root
179
188
  if (workspaceRoot && workspaceRoot !== config.root) {
180
189
  libPath = path.join(workspaceRoot, "lib");
181
- console.log(
182
- chalk.blue(`[static-files] Trying workspace root lib/: ${libPath}`),
183
- );
190
+ if (_debug) {
191
+ console.log(
192
+ chalk.blue(`[static-files] Trying workspace root lib/: ${libPath}`),
193
+ );
194
+ }
184
195
  } else {
185
- console.log(
186
- chalk.yellow(`[static-files] Workspace root equals app root, trying parent directories...`),
187
- );
196
+ if (_debug) {
197
+ console.log(
198
+ chalk.yellow(`[static-files] Workspace root equals app root, trying parent directories...`),
199
+ );
200
+ }
188
201
  // If workspace root equals app root, try going up from app root
189
202
  const parentDir = path.dirname(config.root);
190
203
  const parentLibPath = path.join(parentDir, "lib");
191
- console.log(
192
- chalk.blue(`[static-files] Trying parent lib/: ${parentLibPath}`),
193
- );
204
+ if (_debug) {
205
+ console.log(
206
+ chalk.blue(`[static-files] Trying parent lib/: ${parentLibPath}`),
207
+ );
208
+ }
194
209
  try {
195
210
  await fs.access(parentLibPath);
196
211
  libPath = parentLibPath;
197
- console.log(
198
- chalk.blue(`[static-files] Using parent directory lib/: ${libPath}`),
199
- );
212
+ if (_debug) {
213
+ console.log(
214
+ chalk.blue(`[static-files] Using parent directory lib/: ${libPath}`),
215
+ );
216
+ }
200
217
  } catch (error) {
201
- console.log(
202
- chalk.yellow(`[static-files] Parent lib/ not found: ${error instanceof Error ? error.message : String(error)}`),
203
- );
218
+ if (_debug) {
219
+ console.log(
220
+ chalk.yellow(`[static-files] Parent lib/ not found: ${error instanceof Error ? error.message : String(error)}`),
221
+ );
222
+ }
204
223
  // Parent lib/ doesn't exist, try grandparent
205
224
  const grandparentDir = path.dirname(parentDir);
206
225
  const grandparentLibPath = path.join(grandparentDir, "lib");
207
- console.log(
208
- chalk.blue(`[static-files] Trying grandparent lib/: ${grandparentLibPath}`),
209
- );
226
+ if (_debug) {
227
+ console.log(
228
+ chalk.blue(`[static-files] Trying grandparent lib/: ${grandparentLibPath}`),
229
+ );
230
+ }
210
231
  try {
211
232
  await fs.access(grandparentLibPath);
212
233
  libPath = grandparentLibPath;
213
- console.log(
214
- chalk.blue(`[static-files] Using grandparent directory lib/: ${libPath}`),
215
- );
234
+ if (_debug) {
235
+ console.log(
236
+ chalk.blue(`[static-files] Using grandparent directory lib/: ${libPath}`),
237
+ );
238
+ }
216
239
  } catch (error2) {
217
- console.log(
218
- chalk.yellow(`[static-files] Grandparent lib/ not found: ${error2 instanceof Error ? error2.message : String(error2)}`),
219
- );
240
+ if (_debug) {
241
+ console.log(
242
+ chalk.yellow(`[static-files] Grandparent lib/ not found: ${error2 instanceof Error ? error2.message : String(error2)}`),
243
+ );
244
+ }
220
245
  }
221
246
  }
222
247
  }
223
248
 
224
249
  // Serve lib/ directory if found
225
- console.log(
226
- chalk.blue(`[static-files] Checking for lib/ directory... libPath: ${libPath}`),
227
- );
250
+ if (_debug) {
251
+ console.log(
252
+ chalk.blue(`[static-files] Checking for lib/ directory... libPath: ${libPath}`),
253
+ );
254
+ }
228
255
 
229
256
  // ALWAYS try to register /lib/ static serving
230
257
  // Calculate the lib path - prefer workspace root, fallback to parent of app root
@@ -239,49 +266,67 @@ export async function setupStaticFiles(
239
266
  finalLibPath = path.join(parentDir, "lib");
240
267
  }
241
268
 
242
- console.log(
243
- chalk.blue(`[static-files] Final lib path to check: ${finalLibPath}`),
244
- );
245
- console.log(
246
- chalk.blue(`[static-files] workspaceRoot: ${workspaceRoot}, config.root: ${config.root}`),
247
- );
269
+ if (_debug) {
270
+ console.log(
271
+ chalk.blue(`[static-files] Final lib path to check: ${finalLibPath}`),
272
+ );
273
+ }
274
+ if (_debug) {
275
+ console.log(
276
+ chalk.blue(`[static-files] workspaceRoot: ${workspaceRoot}, config.root: ${config.root}`),
277
+ );
278
+ }
248
279
 
249
280
  // Try to access the directory
250
281
  let libPathExists = false;
251
282
  try {
252
283
  await fs.access(finalLibPath);
253
284
  libPathExists = true;
254
- console.log(
255
- chalk.green(`[static-files] ✅ Found lib/ directory at: ${finalLibPath}`),
256
- );
285
+ if (_debug) {
286
+ console.log(
287
+ chalk.green(`[static-files] ✅ Found lib/ directory at: ${finalLibPath}`),
288
+ );
289
+ }
257
290
 
258
291
  // Verify the CSS file exists
259
292
  const testCssPath = path.join(finalLibPath, "skltn", "src", "css", "index.css");
260
293
  try {
261
294
  await fs.access(testCssPath);
262
- console.log(
263
- chalk.green(`[static-files] ✅ Test CSS file exists: ${testCssPath}`),
264
- );
295
+ if (_debug) {
296
+ console.log(
297
+ chalk.green(`[static-files] ✅ Test CSS file exists: ${testCssPath}`),
298
+ );
299
+ }
265
300
  } catch (error) {
301
+ if (_debug) {
302
+ console.error(
303
+ chalk.yellow(`[static-files] ⚠️ Test CSS file NOT found: ${testCssPath}`),
304
+ );
305
+ }
306
+ }
307
+ } catch (error) {
308
+ if (_debug) {
266
309
  console.error(
267
- chalk.yellow(`[static-files] ⚠️ Test CSS file NOT found: ${testCssPath}`),
310
+ chalk.red(`[static-files] lib/ directory not found at: ${finalLibPath}`),
311
+ );
312
+ }
313
+ if (_debug) {
314
+ console.error(
315
+ chalk.red(`[static-files] Error: ${error instanceof Error ? error.message : String(error)}`),
316
+ );
317
+ }
318
+ if (_debug) {
319
+ console.error(
320
+ chalk.red(`[static-files] ⚠️ /lib middleware will NOT be registered - CSS files will 404!`),
268
321
  );
269
322
  }
270
- } catch (error) {
271
- console.error(
272
- chalk.red(`[static-files] ❌ lib/ directory not found at: ${finalLibPath}`),
273
- );
274
- console.error(
275
- chalk.red(`[static-files] Error: ${error instanceof Error ? error.message : String(error)}`),
276
- );
277
- console.error(
278
- chalk.red(`[static-files] ⚠️ /lib middleware will NOT be registered - CSS files will 404!`),
279
- );
280
323
  }
281
324
 
282
325
  // Register static file middleware ONLY if directory exists
283
326
  if (libPathExists) {
284
- console.log(chalk.green(`[static-files] ✅ Registering /lib middleware with finalLibPath: ${finalLibPath}`));
327
+ if (_debug) {
328
+ console.log(chalk.green(`[static-files] ✅ Registering /lib middleware with finalLibPath: ${finalLibPath}`));
329
+ }
285
330
 
286
331
  // CRITICAL: First middleware to block source files BEFORE any express.static can serve them
287
332
  // This MUST run before express.static to prevent wrong MIME types
@@ -298,17 +343,21 @@ export async function setupStaticFiles(
298
343
  (path.endsWith(".js") && !path.includes("node_modules")) || path.endsWith(".mjs");
299
344
 
300
345
  if (isSourceFile) {
301
- console.log(
302
- chalk.red(
303
- `[static-files] ⚠️ FIRST BLOCK: Skipping source file: url=${url}, path=${path} - should be handled by module middleware`
304
- )
305
- );
346
+ if (_debug) {
347
+ console.log(
348
+ chalk.red(
349
+ `[static-files] ⚠️ FIRST BLOCK: Skipping source file: url=${url}, path=${path} - should be handled by module middleware`
350
+ )
351
+ );
352
+ }
306
353
  return next(); // Let module transformation middleware handle it
307
354
  }
308
355
 
309
- console.log(
310
- chalk.cyan(`[static-files] Request for /lib${path} (static file)`),
311
- );
356
+ if (_debug) {
357
+ console.log(
358
+ chalk.cyan(`[static-files] Request for /lib${path} (static file)`),
359
+ );
360
+ }
312
361
  next();
313
362
  });
314
363
 
@@ -324,7 +373,9 @@ export async function setupStaticFiles(
324
373
  res.setHeader("Pragma", "no-cache");
325
374
  res.setHeader("Expires", "0");
326
375
  } catch (error) {
327
- console.error(chalk.red(`[static-files] Error setting headers for ${filePath}:`), error);
376
+ if (_debug) {
377
+ console.error(chalk.red(`[static-files] Error setting headers for ${filePath}:`), error);
378
+ }
328
379
  }
329
380
  },
330
381
  });
@@ -344,11 +395,13 @@ export async function setupStaticFiles(
344
395
  (path.endsWith(".js") && !path.includes("node_modules")) || path.endsWith(".mjs");
345
396
 
346
397
  if (isSourceFile) {
347
- console.log(
348
- chalk.red(
349
- `[static-files /lib express.static] ⚠️ BLOCKING source file: url=${url}, path=${path} - should be handled by module transformation middleware`
350
- )
351
- );
398
+ if (_debug) {
399
+ console.log(
400
+ chalk.red(
401
+ `[static-files /lib express.static] ⚠️ BLOCKING source file: url=${url}, path=${path} - should be handled by module transformation middleware`
402
+ )
403
+ );
404
+ }
352
405
  // CRITICAL: Don't call libStatic - return next() to skip it
353
406
  return next(); // Let module transformation middleware handle it
354
407
  }
@@ -359,9 +412,11 @@ export async function setupStaticFiles(
359
412
  // Source files should be handled by module transformation middleware (registered before this)
360
413
  // Only static files (CSS, images) should be served, and they're handled by the custom handler above
361
414
  // If a file isn't found, let it 404 rather than serving with wrong MIME type
362
- console.log(
363
- chalk.gray(` 📦 Serving workspace lib/ from ${finalLibPath}`),
364
- );
415
+ if (_debug) {
416
+ console.log(
417
+ chalk.gray(` 📦 Serving workspace lib/ from ${finalLibPath}`),
418
+ );
419
+ }
365
420
  }
366
421
 
367
422
  // Continue with other workspace directories if workspaceRoot is different from app root
@@ -372,9 +427,11 @@ export async function setupStaticFiles(
372
427
  try {
373
428
  await fs.access(librariesPath);
374
429
  app.use("/libraries", express.static(librariesPath));
375
- console.log(
376
- chalk.gray(` 📦 Serving workspace libraries/ from ${librariesPath}`),
377
- );
430
+ if (_debug) {
431
+ console.log(
432
+ chalk.gray(` 📦 Serving workspace libraries/ from ${librariesPath}`),
433
+ );
434
+ }
378
435
  } catch {
379
436
  // libraries/ doesn't exist, skip
380
437
  }
@@ -404,9 +461,11 @@ export async function setupStaticFiles(
404
461
  }
405
462
  express.static(modulesPath)(req, res, next);
406
463
  });
407
- console.log(
408
- chalk.gray(` 📦 Serving workspace modules/ from ${modulesPath}`),
409
- );
464
+ if (_debug) {
465
+ console.log(
466
+ chalk.gray(` 📦 Serving workspace modules/ from ${modulesPath}`),
467
+ );
468
+ }
410
469
  } catch {
411
470
  // modules/ doesn't exist, skip
412
471
  }
@@ -425,7 +484,10 @@ export async function setupSPAFallback(
425
484
  app: Express,
426
485
  config: StaticFilesConfig,
427
486
  ): Promise<void> {
428
- console.log(chalk.magenta(`[SWITE] setupSPAFallback loaded - VERSION 3.0.0 (NO HARDCODED CSS)`));
487
+ const _debug = process.env["SWITE_DEBUG"] === "1";
488
+ if (_debug) {
489
+ console.log(chalk.magenta(`[SWITE] setupSPAFallback loaded - VERSION 0.3.5 (NO HARDCODED CSS)`));
490
+ }
429
491
  // Use app.all() to catch ALL HTTP methods, but only for non-source files
430
492
  app.all("*", async (req, res, next) => {
431
493
  const url = req.url.split("?")[0];
@@ -433,16 +495,11 @@ export async function setupSPAFallback(
433
495
  const accept = String(req.headers?.accept || "");
434
496
 
435
497
  // DEBUG: Verify handler is being called
436
- process.stderr.write(`[SPA FALLBACK] Handler called for: ${req.method} ${fullUrl}\n`);
437
- console.error(`[SWITE CSS DEBUG] ========== SPA FALLBACK HANDLER START ==========`);
438
- console.error(`[SWITE CSS DEBUG] URL: ${url}, Full URL: ${fullUrl}`);
439
498
 
440
499
  // --- CRITICAL SAFETY CHECK ---
441
500
  // NEVER serve HTML for /src/* requests - these are source files that must be handled by middleware
442
501
  // Even if middleware fails, we should return 404, not HTML
443
502
  if (req.path?.startsWith("/src/") || url.startsWith("/src/")) {
444
- console.error(chalk.red(`[SPA FALLBACK] ⚠️ BLOCKED: Attempt to serve HTML for source path: ${req.method} ${fullUrl}`));
445
- console.error(chalk.red(`[SPA FALLBACK] This should have been handled by /src middleware! Returning 404.`));
446
503
  res.status(404).setHeader("Content-Type", "text/plain");
447
504
  res.send(`File not found: ${url}`);
448
505
  return;
@@ -452,8 +509,6 @@ export async function setupSPAFallback(
452
509
  // NEVER serve HTML for /swiss-packages/* requests - these are SWISS framework packages
453
510
  // They should be handled by TS/JS handlers to rewrite imports
454
511
  if (req.path?.startsWith("/swiss-packages/") || url.startsWith("/swiss-packages/")) {
455
- console.error(chalk.red(`[SPA FALLBACK] ⚠️ BLOCKED: Attempt to serve HTML for SWISS package: ${req.method} ${fullUrl}`));
456
- console.error(chalk.red(`[SPA FALLBACK] This should have been handled by module transformation middleware! Returning 404.`));
457
512
  res.status(404).setHeader("Content-Type", "text/plain");
458
513
  res.send(`File not found: ${url}`);
459
514
  return;
@@ -463,21 +518,15 @@ export async function setupSPAFallback(
463
518
  // NEVER serve HTML for /lib/* requests - these are workspace library files
464
519
  // They should be handled by static file middleware
465
520
  if (req.path?.startsWith("/lib/") || url.startsWith("/lib/")) {
466
- console.error(chalk.red(`[SPA FALLBACK] ⚠️ BLOCKED: Attempt to serve HTML for /lib/ path: ${req.method} ${fullUrl}`));
467
- console.error(chalk.red(`[SPA FALLBACK] This should have been handled by static file middleware! Returning 404.`));
468
521
  res.status(404).setHeader("Content-Type", "text/plain");
469
522
  res.send(`File not found: ${url}`);
470
523
  return;
471
524
  }
472
525
 
473
526
  // Log every request that hits the fallback (for diagnostics)
474
- console.log(chalk.gray(`[SPA FALLBACK] Serving HTML for: ${req.method} ${fullUrl}`));
475
- process.stderr.write(`[SPA FALLBACK] About to read HTML file...\n`);
476
527
 
477
528
  // Log if SPA fallback is being hit for .ui files (this should NOT happen after /src check)
478
529
  if (url.endsWith(".ui")) {
479
- console.error(chalk.red(`[SPA FALLBACK] ⚠️ WARNING: SPA fallback intercepted .ui file: ${fullUrl}`));
480
- console.error(chalk.red(`[SPA FALLBACK] This should have been handled by module transformation middleware!`));
481
530
  }
482
531
 
483
532
  // DO NOT serve HTML for source files - they should be handled by handlers
@@ -494,7 +543,6 @@ export async function setupSPAFallback(
494
543
  ) {
495
544
  // These should have been handled by middleware handlers
496
545
  // If we reach here, the file wasn't found, return 404 with proper content type
497
- console.error(chalk.red(`[SPA FALLBACK] Returning 404 for ${url} - should have been handled earlier`));
498
546
  res.status(404).setHeader("Content-Type", "text/plain");
499
547
  res.send(`File not found: ${url}`);
500
548
  return;
@@ -548,12 +596,18 @@ export async function setupSPAFallback(
548
596
  // This dynamically discovers CSS files from the app's entry point
549
597
  // CRITICAL: This MUST run before import map injection
550
598
  // IMPORTANT: Only inject CSS files that actually exist in the app's directory
551
- console.log(chalk.magenta(`[SWITE CSS] ========== CSS EXTRACTION START (VERSION 3.0.0) ==========`));
552
- console.log(chalk.magenta(`[SWITE CSS] App root: ${config.root}`));
599
+ if (_debug) {
600
+ console.log(chalk.magenta(`[SWITE CSS] ========== CSS EXTRACTION START (VERSION 0.3.5) ==========`));
601
+ }
602
+ if (_debug) {
603
+ console.log(chalk.magenta(`[SWITE CSS] App root: ${config.root}`));
604
+ }
553
605
  try {
554
606
  const entryFile = config.entry ?? "src/index.ui";
555
607
  const entryPointPath = path.join(config.root, entryFile);
556
- console.log(chalk.blue(`[SWITE CSS] Checking entry point: ${entryPointPath}`));
608
+ if (_debug) {
609
+ console.log(chalk.blue(`[SWITE CSS] Checking entry point: ${entryPointPath}`));
610
+ }
557
611
  const entryPointContent = await fs.readFile(entryPointPath, "utf-8");
558
612
 
559
613
  // Extract CSS imports using regex
@@ -620,10 +674,14 @@ export async function setupSPAFallback(
620
674
  }
621
675
  }
622
676
 
623
- console.log(chalk.blue(`[SWITE CSS] Found ${cssImports.size} CSS import(s) in code`));
677
+ if (_debug) {
678
+ console.log(chalk.blue(`[SWITE CSS] Found ${cssImports.size} CSS import(s) in code`));
679
+ }
624
680
  if (cssImports.size > 0) {
625
681
  const cssArray = Array.from(cssImports);
626
- console.log(chalk.blue(`[SWITE CSS] CSS imports found: ${cssArray.join(", ")}`));
682
+ if (_debug) {
683
+ console.log(chalk.blue(`[SWITE CSS] CSS imports found: ${cssArray.join(", ")}`));
684
+ }
627
685
 
628
686
  // Verify CSS files exist before injecting them
629
687
  const existingCssFiles: string[] = [];
@@ -634,22 +692,32 @@ export async function setupSPAFallback(
634
692
  ? path.join(config.root, url.substring(1)) // Remove leading /
635
693
  : path.join(config.root, "src", cssPath);
636
694
 
637
- console.log(chalk.blue(`[SWITE CSS] Checking if CSS file exists: ${filePath} (url: ${url})`));
695
+ if (_debug) {
696
+ console.log(chalk.blue(`[SWITE CSS] Checking if CSS file exists: ${filePath} (url: ${url})`));
697
+ }
638
698
  try {
639
699
  await fs.access(filePath);
640
- console.log(chalk.green(`[SWITE CSS] ✅ CSS file exists: ${filePath}`));
700
+ if (_debug) {
701
+ console.log(chalk.green(`[SWITE CSS] ✅ CSS file exists: ${filePath}`));
702
+ }
641
703
  existingCssFiles.push(url);
642
704
  } catch {
643
705
  // CSS file doesn't exist, skip it
644
706
  // This allows different apps/websites to have different CSS files
645
- console.log(chalk.yellow(`[SWITE CSS] ⚠️ CSS file NOT found: ${filePath}, skipping`));
707
+ if (_debug) {
708
+ console.log(chalk.yellow(`[SWITE CSS] ⚠️ CSS file NOT found: ${filePath}, skipping`));
709
+ }
646
710
  }
647
711
  }
648
712
 
649
713
  // Only inject CSS files that actually exist
650
- console.log(chalk.blue(`[SWITE CSS] ${existingCssFiles.length} CSS file(s) exist out of ${cssArray.length} found`));
714
+ if (_debug) {
715
+ console.log(chalk.blue(`[SWITE CSS] ${existingCssFiles.length} CSS file(s) exist out of ${cssArray.length} found`));
716
+ }
651
717
  if (existingCssFiles.length === 0) {
652
- console.log(chalk.yellow(`[SWITE CSS] ⚠️ No CSS files exist, skipping injection`));
718
+ if (_debug) {
719
+ console.log(chalk.yellow(`[SWITE CSS] ⚠️ No CSS files exist, skipping injection`));
720
+ }
653
721
  } else if (existingCssFiles.length > 0) {
654
722
  const cssLinks = existingCssFiles
655
723
  .map(url => ` <link rel="stylesheet" href="${url}">`)
@@ -665,19 +733,27 @@ export async function setupSPAFallback(
665
733
  const beforeReplace = html;
666
734
  html = html.replace(/\s*<\/head>/i, `${cssLinks}\n </head>`);
667
735
  if (html === beforeReplace) {
668
- console.warn(chalk.yellow("[SWITE] Failed to inject CSS links - </head> not found"));
736
+ if (_debug) {
737
+ console.warn(chalk.yellow("[SWITE] Failed to inject CSS links - </head> not found"));
738
+ }
669
739
  } else {
670
- console.log(chalk.green(`[SWITE] ✅ Injected ${existingCssFiles.length} CSS link(s): ${existingCssFiles.join(", ")}`));
740
+ if (_debug) {
741
+ console.log(chalk.green(`[SWITE] ✅ Injected ${existingCssFiles.length} CSS link(s): ${existingCssFiles.join(", ")}`));
742
+ }
671
743
  }
672
744
  } else {
673
- console.log(chalk.blue(`[SWITE CSS] CSS links already in HTML, skipping injection`));
745
+ if (_debug) {
746
+ console.log(chalk.blue(`[SWITE CSS] CSS links already in HTML, skipping injection`));
747
+ }
674
748
  }
675
749
  }
676
750
  }
677
751
  } catch (error) {
678
752
  // If entry point doesn't exist or can't be read, continue without CSS injection
679
753
  // Silently continue - CSS injection is optional
680
- console.log(chalk.yellow(`[SWITE CSS] Could not extract CSS imports: ${error instanceof Error ? error.message : String(error)}`));
754
+ if (_debug) {
755
+ console.log(chalk.yellow(`[SWITE CSS] Could not extract CSS imports: ${error instanceof Error ? error.message : String(error)}`));
756
+ }
681
757
  }
682
758
 
683
759
  // Add/merge import map to help browser resolve bare module specifiers.
@@ -701,13 +777,19 @@ export async function setupSPAFallback(
701
777
  const beforeReplace = html;
702
778
  html = html.replace(/\s*<\/head>/i, `${importMap}\n </head>`);
703
779
  if (html === beforeReplace) {
704
- console.warn("[SWITE] Failed to add import map - </head> not found or already replaced");
780
+ if (_debug) {
781
+ console.warn("[SWITE] Failed to add import map - </head> not found or already replaced");
782
+ }
705
783
  } else {
706
- console.log(`[SWITE] Added import map with ${Object.keys(switeImports).length} entries`);
784
+ if (_debug) {
785
+ console.log(`[SWITE] Added import map with ${Object.keys(switeImports).length} entries`);
786
+ }
707
787
  }
708
788
  } else {
709
789
  // Importmap already in HTML — merge swite entries without overwriting existing ones
710
- console.log("[SWITE] Import map already exists in HTML — merging swite entries");
790
+ if (_debug) {
791
+ console.log("[SWITE] Import map already exists in HTML — merging swite entries");
792
+ }
711
793
  if (Object.keys(switeImports).length > 0) {
712
794
  html = html.replace(
713
795
  /(<script\s+type=["']importmap["'][^>]*>)\s*([\s\S]*?)(\s*<\/script>)/i,
@@ -5,7 +5,7 @@ import { initPythonProxy } from "../adapters/proxy/proxyToPython.js";
5
5
  import type { PythonServiceConfig } from "../config/config.js";
6
6
 
7
7
  const POLL_INTERVAL_MS = 500;
8
- const HEALTH_TIMEOUT_MS = 15_000;
8
+ const HEALTH_TIMEOUT_MS = 30_000;
9
9
  const BACKOFF_THRESHOLD = 5;
10
10
 
11
11
  let _child: ChildProcess | null = null;
@@ -11,7 +11,6 @@ import type { RouteDefinition } from "@swissjs/core";
11
11
  import { RouteScanner } from "@swissjs/plugin-file-router/core";
12
12
  import { createFileWatcher } from "@swissjs/plugin-file-router/dev";
13
13
  import { HMREngine } from "../hmr/hmr.js";
14
- import { findWorkspaceRoot } from "../../kernel/workspace.js";
15
14
 
16
15
  export interface FileRouterConfig {
17
16
  root: string;
@@ -38,7 +37,6 @@ export async function setupFileRouter(
38
37
  };
39
38
 
40
39
  try {
41
- const workspaceRoot = await findWorkspaceRoot(config.root);
42
40
  const appRoot = config.root;
43
41
 
44
42
  // Initialize route scanner
@@ -49,59 +47,18 @@ export async function setupFileRouter(
49
47
  lazyLoading: true,
50
48
  });
51
49
 
52
- // Scan routes from multiple locations:
53
- // 1. App's pages directory (apps/alpine/src/pages)
54
- // 2. SKLTN's pages directory (framework/skltn/src/pages) - for reusable auth pages
55
50
  const routesToScan: string[] = [];
56
51
 
57
- // App pages
52
+ // App pages directory
58
53
  const appPagesDir = path.join(appRoot, "src", "pages");
59
54
  try {
60
55
  await fs.access(appPagesDir);
61
56
  routesToScan.push(appPagesDir);
62
- console.log(chalk.gray(` 📄 Scanning app routes from ${appPagesDir}`));
57
+ console.log(chalk.gray(` Scanning app routes from ${appPagesDir}`));
63
58
  } catch {
64
59
  // pages directory doesn't exist, skip
65
60
  }
66
61
 
67
- // SKLTN pages (if workspace root exists)
68
- if (workspaceRoot && workspaceRoot !== appRoot) {
69
- // Try framework/skltn first (new location), then fallback to lib/skltn (legacy)
70
- const skltnPagesDir = path.join(
71
- workspaceRoot,
72
- "framework",
73
- "skltn",
74
- "src",
75
- "pages",
76
- );
77
- const legacySkltnPagesDir = path.join(
78
- workspaceRoot,
79
- "lib",
80
- "skltn",
81
- "src",
82
- "pages",
83
- );
84
-
85
- try {
86
- await fs.access(skltnPagesDir);
87
- routesToScan.push(skltnPagesDir);
88
- console.log(
89
- chalk.gray(` 📄 Scanning SKLTN routes from ${skltnPagesDir}`),
90
- );
91
- } catch {
92
- // Try legacy location
93
- try {
94
- await fs.access(legacySkltnPagesDir);
95
- routesToScan.push(legacySkltnPagesDir);
96
- console.log(
97
- chalk.gray(` 📄 Scanning SKLTN routes from ${legacySkltnPagesDir} (legacy)`),
98
- );
99
- } catch {
100
- // pages directory doesn't exist, skip
101
- }
102
- }
103
- }
104
-
105
62
  // Scan all route directories
106
63
  for (const pagesDir of routesToScan) {
107
64
  try {