juxscript 1.0.72 → 1.0.74

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.
@@ -367,7 +367,19 @@ function transformJuxToViewFunction(juxContent, functionName, pageName, relative
367
367
  }
368
368
  result = result.replace(/\.renderTo\(container\)/g, '.render("#app")').replace(/\.render\(\s*\)/g, '.render("#app")');
369
369
  const cleanName = functionName.replace(/[-_]/g, ' ').split(' ').map(w => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join('');
370
- return `\n// View: ${cleanName}\nfunction ${cleanName}() {\n${result}\n \n return document.getElementById('app');\n}`;
370
+
371
+ // ✅ Wrap View implementation in underscore function, then export Wrapped version
372
+ return `
373
+ // View: ${cleanName}
374
+ function _${cleanName}() {
375
+ ${result}
376
+
377
+ return document.getElementById('app');
378
+ }
379
+ const ${cleanName} = JuxError.wrap('${cleanName}', _${cleanName});
380
+ // Register Source
381
+ JuxError.register('${cleanName}', '${relativePath}');
382
+ `;
371
383
  }
372
384
 
373
385
  function resolveImportPath(importPath, currentFilePath) {
@@ -428,13 +440,85 @@ function generateRouterBundle(views, routes, sharedModules = new Map(), allImpor
428
440
  else if (parts.length > 0) filteredImports.push(`import ${parts.join(', ')} from '${source}';`);
429
441
  });
430
442
 
443
+ const juxDebugUtils = `
444
+ // ============================================
445
+ // JUX DEBUG UTILITIES
446
+ // ============================================
447
+ const JUX_DEBUG = true;
448
+
449
+ const JuxError = {
450
+ sourceMap: {},
451
+
452
+ register(viewName, sourceFile) {
453
+ this.sourceMap[viewName] = sourceFile;
454
+ },
455
+
456
+ // Global Error Handler Setup
457
+ init() {
458
+ window.addEventListener('error', (event) => {
459
+ JuxError.displayError('Uncaught Exception', event.error);
460
+ });
461
+ window.addEventListener('unhandledrejection', (event) => {
462
+ JuxError.displayError('Unhandled Promise Rejection', event.reason);
463
+ });
464
+ },
465
+
466
+ displayError(title, error) {
467
+ console.error(\`🚨 JUX \${title}\`, error);
468
+ const app = document.getElementById('app');
469
+ if (app) {
470
+ // Prevent multiple error overlays stacking
471
+ if (document.getElementById('jux-error-overlay')) return;
472
+
473
+ app.innerHTML = \`
474
+ <div id="jux-error-overlay" style="font-family: monospace; background: #1e1e1e; color: #ff6b6b; min-height: 100vh; padding: 2rem; position:fixed; top:0; left:0; width:100%; z-index:99999;">
475
+ <div style="display: flex; align-items: center; gap: 1rem; margin-bottom: 2rem;">
476
+ <div style="font-size: 2rem;">🚨</div>
477
+ <div>
478
+ <h1 style="margin:0; font-size: 1.5rem; color: #ff6b6b;">JUX Runtime Error</h1>
479
+ <div style="color: #888; margin-top: 4px;">\${title}</div>
480
+ </div>
481
+ </div>
482
+
483
+ <pre style="background: #2d2d2d; padding: 20px; border-radius: 8px; overflow-x: auto; color: #e0e0e0; border-left: 4px solid #ff6b6b; font-size: 14px; line-height: 1.5;">\${error?.stack || error?.message || String(error)}</pre>
484
+
485
+ <button onclick="window.location.reload()" style="margin-top:20px; padding: 10px 20px; background: #333; color: white; border: 1px solid #555; cursor: pointer; border-radius: 4px;">Reload Application</button>
486
+ </div>
487
+ \`;
488
+ }
489
+ },
490
+
491
+ wrap(viewName, viewFn) {
492
+ return function() {
493
+ const sourceFile = JuxError.sourceMap[viewName] || 'unknown';
494
+ if (JUX_DEBUG) console.log(\`🚀 [JUX] Rendering: \${viewName} (\${sourceFile})\`);
495
+
496
+ try {
497
+ return viewFn.apply(this, arguments);
498
+ } catch (error) {
499
+ // Enhance error object with view context if possible
500
+ error.message = \`[View: \${viewName}] \${error.message}\`;
501
+ JuxError.displayError('View Rendering Error', error);
502
+ // We do NOT rethrow here to prevent console noise, as we handled it UI-wise.
503
+ // However, stopping execution flow is implicitly handled by not returning valid DOM.
504
+ }
505
+ };
506
+ }
507
+ };
508
+
509
+ // Initialize Global Handlers
510
+ JuxError.init();
511
+ `;
512
+
431
513
  return `// Generated Jux Router Bundle
432
514
  ${filteredImports.join('\n')}
433
515
 
516
+ ${juxDebugUtils}
517
+
434
518
  // SHARED MODULES
435
519
  ${Array.from(sharedModules.values()).filter(c => c.trim()).join('\n\n')}
436
520
 
437
- // VIEWS
521
+ // VIEWS (Wrapped in JuxError)
438
522
  ${views.filter(v => v.trim()).join('\n\n')}
439
523
 
440
524
  function JuxNotFound() { jux.heading(1, { text: '404 - Page Not Found' }).render('#app'); return document.getElementById('app'); }
@@ -459,7 +543,7 @@ document.addEventListener('click', e => {
459
543
  const a = e.target.closest('a');
460
544
  if (!a || a.dataset.router === 'false' || new URL(a.href).origin !== location.origin) return;
461
545
  e.preventDefault();
462
- history.pushState({}, '', url.pathname);
546
+ history.pushState({}, '', a.href);
463
547
  render();
464
548
  });
465
549
  window.addEventListener('popstate', render);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "juxscript",
3
- "version": "1.0.72",
3
+ "version": "1.0.74",
4
4
  "type": "module",
5
5
  "description": "A JavaScript UX authorship platform",
6
6
  "main": "lib/jux.js",