@salesforce/webapp-experimental 1.22.1 → 1.24.0

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.
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ /**
7
+ * Returns the error page HTML template. Reads from dist/proxy/templates/ at runtime (after postbuild copy).
8
+ * Cached after first read.
9
+ */
10
+ export declare function getErrorPageTemplate(): string;
11
+ //# sourceMappingURL=error-page.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-page.d.ts","sourceRoot":"","sources":["../../src/proxy/error-page.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAK7C"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ import { readFileSync } from "node:fs";
7
+ import { dirname, join } from "node:path";
8
+ import { fileURLToPath } from "node:url";
9
+ const __dirname = dirname(fileURLToPath(import.meta.url));
10
+ let cached = null;
11
+ /**
12
+ * Returns the error page HTML template. Reads from dist/proxy/templates/ at runtime (after postbuild copy).
13
+ * Cached after first read.
14
+ */
15
+ export function getErrorPageTemplate() {
16
+ if (cached)
17
+ return cached;
18
+ const templatePath = join(__dirname, "templates", "error-page.html");
19
+ cached = readFileSync(templatePath, "utf-8");
20
+ return cached;
21
+ }
@@ -5,4 +5,5 @@
5
5
  */
6
6
  export type { ProxyOptions, ProxyHandler } from "./handler.js";
7
7
  export { createProxyHandler, WEBAPP_HEALTH_CHECK_PARAM, WEBAPP_PROXY_HEADER } from "./handler.js";
8
+ export { getErrorPageTemplate } from "./error-page.js";
8
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/proxy/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/proxy/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAClG,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -4,3 +4,4 @@
4
4
  * For full license text, see the LICENSE.txt file
5
5
  */
6
6
  export { createProxyHandler, WEBAPP_HEALTH_CHECK_PARAM, WEBAPP_PROXY_HEADER } from "./handler.js";
7
+ export { getErrorPageTemplate } from "./error-page.js";
@@ -0,0 +1,748 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>{{PAGE_TITLE}} - Salesforce Local Dev Proxy</title>
7
+ {{META_REFRESH}}
8
+ <style>
9
+ * {
10
+ margin: 0;
11
+ padding: 0;
12
+ box-sizing: border-box;
13
+ }
14
+
15
+ body {
16
+ font-family:
17
+ -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
18
+ background: linear-gradient(135deg, #1e2a47 0%, #2d3e5f 100%);
19
+ color: #333;
20
+ min-height: 100vh;
21
+ padding: 20px;
22
+ }
23
+
24
+ .main-container {
25
+ max-width: 1400px;
26
+ margin: 0 auto;
27
+ background: #e8e8e8;
28
+ border-radius: 16px;
29
+ box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);
30
+ overflow: hidden;
31
+ }
32
+
33
+ /* ============================================
34
+ TOP HEADER
35
+ ============================================ */
36
+ .top-header {
37
+ background: #e8e8e8;
38
+ padding: 30px 40px;
39
+ display: flex;
40
+ justify-content: space-between;
41
+ align-items: flex-start;
42
+ border-bottom: 1px solid #ccc;
43
+ }
44
+
45
+ .header-left h1 {
46
+ color: #1a1a1a;
47
+ font-size: 2.2em;
48
+ font-weight: 600;
49
+ margin-bottom: 8px;
50
+ }
51
+
52
+ .header-left .subtitle {
53
+ color: #666;
54
+ font-size: 1.05em;
55
+ }
56
+
57
+ .status-badge {
58
+ padding: 12px 24px;
59
+ border-radius: 8px;
60
+ font-weight: 600;
61
+ font-size: 0.95em;
62
+ }
63
+
64
+ .status-badge.critical {
65
+ background: #ffcdd2;
66
+ color: #b71c1c;
67
+ }
68
+
69
+ .status-badge.error {
70
+ background: #ffebee;
71
+ color: #c62828;
72
+ }
73
+
74
+ .status-badge.warning {
75
+ background: #fff3e0;
76
+ color: #e65100;
77
+ }
78
+
79
+ .status-badge.success {
80
+ background: #e8f5e9;
81
+ color: #2e7d32;
82
+ }
83
+
84
+ /* ============================================
85
+ TWO-COLUMN LAYOUT
86
+ ============================================ */
87
+ .content-wrapper {
88
+ display: grid;
89
+ grid-template-columns: 1fr 308px;
90
+ gap: 0;
91
+ background: #e8e8e8;
92
+ }
93
+
94
+ .main-content {
95
+ padding: 40px;
96
+ background: white;
97
+ border-right: 1px solid #ccc;
98
+ }
99
+
100
+ .diagnostics-panel {
101
+ padding: 40px 20px;
102
+ background: #f5f5f5;
103
+ }
104
+
105
+ /* ============================================
106
+ MAIN CONTENT SECTIONS
107
+ ============================================ */
108
+ .content-section {
109
+ margin-bottom: 30px;
110
+ }
111
+
112
+ .content-section h2 {
113
+ color: #1a1a1a;
114
+ font-size: 1.4em;
115
+ margin-bottom: 15px;
116
+ font-weight: 600;
117
+ }
118
+
119
+ .content-section h3 {
120
+ color: #1a1a1a;
121
+ font-size: 1.1em;
122
+ margin-bottom: 12px;
123
+ font-weight: 600;
124
+ }
125
+
126
+ .content-section p {
127
+ color: #555;
128
+ line-height: 1.6;
129
+ margin-bottom: 15px;
130
+ }
131
+
132
+ .content-section ul {
133
+ list-style: disc;
134
+ padding-left: 25px;
135
+ color: #555;
136
+ line-height: 1.8;
137
+ }
138
+
139
+ /* Message box for errors */
140
+ .message-box {
141
+ background: #fff3e0;
142
+ border-left: 4px solid #ff9800;
143
+ padding: 20px;
144
+ border-radius: 6px;
145
+ margin-bottom: 25px;
146
+ }
147
+
148
+ .message-box p {
149
+ color: #555;
150
+ margin: 0;
151
+ }
152
+
153
+ /* Stack trace and code outputs */
154
+ .code-output {
155
+ background: #1e1e1e;
156
+ border-radius: 8px;
157
+ padding: 20px;
158
+ max-height: 400px;
159
+ overflow-y: auto;
160
+ font-family: "Courier New", Consolas, Monaco, monospace;
161
+ font-size: 0.9em;
162
+ line-height: 1.5;
163
+ margin: 20px 0;
164
+ }
165
+
166
+ .code-output pre {
167
+ color: #ff6b6b;
168
+ margin: 0;
169
+ white-space: pre-wrap;
170
+ word-wrap: break-word;
171
+ }
172
+
173
+ .stack-trace-container {
174
+ background: #263238;
175
+ border-radius: 8px;
176
+ padding: 20px;
177
+ max-height: 350px;
178
+ overflow-y: auto;
179
+ font-family: "Courier New", Consolas, Monaco, monospace;
180
+ font-size: 0.9em;
181
+ line-height: 1.5;
182
+ }
183
+
184
+ /* Suggestions box */
185
+ .suggestions-box {
186
+ background: #e3f2fd;
187
+ border-left: 4px solid #2196f3;
188
+ padding: 20px;
189
+ border-radius: 6px;
190
+ margin: 20px 0;
191
+ }
192
+
193
+ .suggestions-box h3 {
194
+ color: #1a1a1a;
195
+ font-size: 1.1em;
196
+ margin-bottom: 15px;
197
+ }
198
+
199
+ .suggestions-box ul {
200
+ list-style: none;
201
+ padding: 0;
202
+ }
203
+
204
+ .suggestions-box li {
205
+ padding: 8px 0;
206
+ color: #555;
207
+ line-height: 1.6;
208
+ }
209
+
210
+ .suggestions-box li::before {
211
+ content: "💡";
212
+ margin-right: 10px;
213
+ }
214
+
215
+ /* ============================================
216
+ DIAGNOSTICS PANEL
217
+ ============================================ */
218
+ .diagnostics-panel h2 {
219
+ color: #1a1a1a;
220
+ font-size: 1.15em;
221
+ margin-bottom: 18px;
222
+ font-weight: 600;
223
+ }
224
+
225
+ .diagnostics-list {
226
+ list-style: none;
227
+ padding: 0;
228
+ margin-bottom: 20px;
229
+ }
230
+
231
+ .diagnostics-list li {
232
+ margin-bottom: 12px;
233
+ color: #555;
234
+ line-height: 1.4;
235
+ font-size: 0.9em;
236
+ }
237
+
238
+ .diagnostics-list .label {
239
+ display: block;
240
+ font-weight: 600;
241
+ color: #1a1a1a;
242
+ margin-bottom: 3px;
243
+ font-size: 0.85em;
244
+ }
245
+
246
+ .diagnostics-list .value {
247
+ font-family: "Courier New", monospace;
248
+ font-size: 0.85em;
249
+ color: #666;
250
+ word-break: break-word;
251
+ }
252
+
253
+ .diagnostics-list .value code {
254
+ background: #263238;
255
+ color: #aed581;
256
+ padding: 2px 5px;
257
+ border-radius: 3px;
258
+ font-size: 0.8em;
259
+ }
260
+
261
+ /* Live logs section */
262
+ .live-logs {
263
+ background: #1e1e1e;
264
+ border-radius: 4px;
265
+ padding: 12px;
266
+ margin-top: 18px;
267
+ font-family: "Courier New", monospace;
268
+ font-size: 0.75em;
269
+ color: #90a4ae;
270
+ max-height: 200px;
271
+ overflow-y: auto;
272
+ line-height: 1.6;
273
+ }
274
+
275
+ .live-logs .log-line {
276
+ margin-bottom: 3px;
277
+ white-space: nowrap;
278
+ overflow: hidden;
279
+ text-overflow: ellipsis;
280
+ }
281
+
282
+ .live-logs .timestamp {
283
+ color: #78909c;
284
+ font-size: 0.9em;
285
+ }
286
+
287
+ .live-logs .log-content {
288
+ color: #b0bec5;
289
+ }
290
+
291
+ /* Emergency exit commands */
292
+ .emergency-commands {
293
+ background: #fff3cd;
294
+ border: 1px solid #ffc107;
295
+ border-radius: 4px;
296
+ padding: 15px;
297
+ margin-top: 20px;
298
+ }
299
+
300
+ .emergency-commands h3 {
301
+ color: #856404;
302
+ font-size: 0.8em;
303
+ margin: 0 0 8px 0;
304
+ font-weight: 600;
305
+ }
306
+
307
+ .emergency-commands p {
308
+ color: #856404;
309
+ font-size: 0.75em;
310
+ margin: 0 0 8px 0;
311
+ }
312
+
313
+ .command-item {
314
+ margin-bottom: 10px;
315
+ }
316
+
317
+ .command-item:last-child {
318
+ margin-bottom: 0;
319
+ }
320
+
321
+ .command-comment {
322
+ color: #856404;
323
+ font-size: 0.7em;
324
+ margin-bottom: 3px;
325
+ font-style: italic;
326
+ }
327
+
328
+ .command-wrapper {
329
+ position: relative;
330
+ }
331
+
332
+ .command-box {
333
+ background: #263238;
334
+ color: #aed581;
335
+ padding: 10px 44px 10px 10px;
336
+ border-radius: 4px;
337
+ font-family: "Courier New", monospace;
338
+ font-size: 0.72em;
339
+ word-break: break-all;
340
+ position: relative;
341
+ min-height: 36px;
342
+ display: flex;
343
+ align-items: center;
344
+ }
345
+
346
+ .copy-button {
347
+ position: absolute;
348
+ right: 8px;
349
+ top: 50%;
350
+ transform: translateY(-50%);
351
+ background: #4caf50;
352
+ color: white;
353
+ border: none;
354
+ border-radius: 3px;
355
+ padding: 6px;
356
+ width: 28px;
357
+ height: 28px;
358
+ cursor: pointer;
359
+ transition: all 0.2s;
360
+ display: flex;
361
+ align-items: center;
362
+ justify-content: center;
363
+ flex-shrink: 0;
364
+ }
365
+
366
+ .copy-button:hover {
367
+ background: #45a049;
368
+ transform: translateY(-50%) scale(1.1);
369
+ }
370
+
371
+ .copy-button.copied {
372
+ background: #2196f3;
373
+ }
374
+
375
+ .copy-button svg {
376
+ width: 16px;
377
+ height: 16px;
378
+ fill: white;
379
+ }
380
+
381
+ /* ============================================
382
+ BOTTOM FOOTER
383
+ ============================================ */
384
+ .footer-section {
385
+ background: #e8e8e8;
386
+ padding: 20px 40px;
387
+ border-top: 1px solid #ccc;
388
+ text-align: center;
389
+ }
390
+
391
+ .help-text {
392
+ color: #666;
393
+ font-size: 0.9em;
394
+ line-height: 1.5;
395
+ }
396
+
397
+ .help-text strong {
398
+ color: #333;
399
+ }
400
+
401
+ /* ============================================
402
+ UTILITY CLASSES
403
+ ============================================ */
404
+ .hidden {
405
+ display: none;
406
+ }
407
+
408
+ .code {
409
+ background: #263238;
410
+ color: #aed581;
411
+ padding: 3px 8px;
412
+ border-radius: 4px;
413
+ font-family: "Courier New", Consolas, Monaco, monospace;
414
+ font-size: 0.9em;
415
+ }
416
+
417
+ .auto-refresh-indicator {
418
+ background: #e8f5e9;
419
+ border-left: 4px solid #4caf50;
420
+ padding: 12px 16px;
421
+ border-radius: 6px;
422
+ margin: 20px 0;
423
+ color: #2e7d32;
424
+ font-size: 0.9em;
425
+ }
426
+
427
+ .auto-refresh-indicator::before {
428
+ content: "🔄";
429
+ margin-right: 8px;
430
+ }
431
+
432
+ /* Error metadata cards */
433
+ .metadata-grid {
434
+ display: grid;
435
+ grid-template-columns: repeat(2, 1fr);
436
+ gap: 15px;
437
+ margin: 20px 0;
438
+ }
439
+
440
+ .metadata-card {
441
+ background: #f9f9f9;
442
+ padding: 15px;
443
+ border-radius: 6px;
444
+ border-left: 3px solid #2196f3;
445
+ }
446
+
447
+ .metadata-card .label {
448
+ font-weight: 600;
449
+ color: #1a1a1a;
450
+ font-size: 0.85em;
451
+ margin-bottom: 6px;
452
+ }
453
+
454
+ .metadata-card .value {
455
+ color: #666;
456
+ font-family: monospace;
457
+ font-size: 0.9em;
458
+ }
459
+
460
+ /* ============================================
461
+ SCROLLBARS
462
+ ============================================ */
463
+ .code-output::-webkit-scrollbar,
464
+ .stack-trace-container::-webkit-scrollbar,
465
+ .live-logs::-webkit-scrollbar {
466
+ width: 8px;
467
+ }
468
+
469
+ .code-output::-webkit-scrollbar-track,
470
+ .stack-trace-container::-webkit-scrollbar-track,
471
+ .live-logs::-webkit-scrollbar-track {
472
+ background: #1a1f2e;
473
+ border-radius: 4px;
474
+ }
475
+
476
+ .code-output::-webkit-scrollbar-thumb,
477
+ .stack-trace-container::-webkit-scrollbar-thumb,
478
+ .live-logs::-webkit-scrollbar-thumb {
479
+ background: #4a5568;
480
+ border-radius: 4px;
481
+ }
482
+
483
+ /* ============================================
484
+ RESPONSIVE DESIGN
485
+ ============================================ */
486
+ @media (max-width: 900px) {
487
+ .content-wrapper {
488
+ grid-template-columns: 1fr;
489
+ }
490
+
491
+ .main-content {
492
+ border-right: none;
493
+ border-bottom: 1px solid #ccc;
494
+ }
495
+
496
+ .diagnostics-panel {
497
+ padding: 30px 20px;
498
+ }
499
+
500
+ .metadata-grid {
501
+ grid-template-columns: 1fr;
502
+ }
503
+ }
504
+
505
+ @media (max-width: 768px) {
506
+ .top-header {
507
+ flex-direction: column;
508
+ gap: 15px;
509
+ padding: 20px;
510
+ }
511
+
512
+ .main-content {
513
+ padding: 25px;
514
+ }
515
+ }
516
+ </style>
517
+ </head>
518
+
519
+ <body>
520
+ <div class="main-container">
521
+ <!-- Top Header -->
522
+ <div class="top-header">
523
+ <div class="header-left">
524
+ <h1>Local Dev Proxy</h1>
525
+ <p class="subtitle">Salesforce preview → Proxy → Your dev server</p>
526
+ </div>
527
+ <div class="status-badge {{STATUS_CLASS}}">{{ERROR_STATUS}}</div>
528
+ </div>
529
+
530
+ <!-- Two-Column Content -->
531
+ <div class="content-wrapper">
532
+ <!-- Main Content (Left) -->
533
+ <div class="main-content">
534
+ <!-- SECTION 1: Simple Error (Dev Server Down) -->
535
+ <div id="simple-error-section" class="{{SIMPLE_SECTION_CLASS}}">
536
+ <div class="content-section">
537
+ <h2>{{ERROR_TITLE}}</h2>
538
+ {{MESSAGE_CONTENT}}
539
+ </div>
540
+
541
+ <div class="auto-refresh-indicator {{AUTO_REFRESH_CLASS}}">{{AUTO_REFRESH_TEXT}}</div>
542
+
543
+ <div class="suggestions-box">
544
+ <h3>What to do next</h3>
545
+ <ul>
546
+ <li>
547
+ Start your dev server using: <code>npm run dev</code> or <code>yarn dev</code>
548
+ </li>
549
+ <li>Verify your dev server is running on the correct port</li>
550
+ <li>Check webapplication.json for the correct dev server URL</li>
551
+ <li>This page will auto-refresh when the server is detected</li>
552
+ </ul>
553
+ </div>
554
+ </div>
555
+
556
+ <!-- SECTION 2: Runtime Error -->
557
+ <div id="runtime-error-section" class="{{RUNTIME_SECTION_CLASS}}">
558
+ <div class="content-section">
559
+ <h2>⚠️ Runtime Error: {{ERROR_TYPE}}</h2>
560
+ <div class="message-box">
561
+ <p>{{ERROR_MESSAGE_TEXT}}</p>
562
+ </div>
563
+ </div>
564
+
565
+ <div class="content-section">
566
+ <h3>Stack Trace</h3>
567
+ <div class="stack-trace-container">{{FORMATTED_STACK_HTML}}</div>
568
+ </div>
569
+
570
+ <div class="metadata-grid">
571
+ <div class="metadata-card">
572
+ <div class="label">Error Type</div>
573
+ <div class="value">{{ERROR_TYPE}}{{ERROR_CODE_BADGE}}</div>
574
+ </div>
575
+ <div class="metadata-card">
576
+ <div class="label">Severity</div>
577
+ <div class="value">{{SEVERITY_LABEL}}</div>
578
+ </div>
579
+ <div class="metadata-card">
580
+ <div class="label">Timestamp</div>
581
+ <div class="value">{{TIMESTAMP_FORMATTED}}</div>
582
+ </div>
583
+ <div class="metadata-card">
584
+ <div class="label">Process ID</div>
585
+ <div class="value">{{PID}}</div>
586
+ </div>
587
+ </div>
588
+
589
+ <div class="suggestions-box {{SUGGESTIONS_SECTION_CLASS}}">
590
+ <h3>{{SUGGESTIONS_TITLE}}</h3>
591
+ <ul>
592
+ {{SUGGESTIONS_LIST}}
593
+ </ul>
594
+ </div>
595
+ </div>
596
+
597
+ <!-- SECTION 3: Dev Server Error -->
598
+ <div id="dev-server-error-section" class="{{DEV_SERVER_SECTION_CLASS}}">
599
+ <div class="content-section">
600
+ <h2>⚠️ {{ERROR_TITLE}}</h2>
601
+ <div class="message-box">
602
+ <p>{{ERROR_MESSAGE_TEXT}}</p>
603
+ </div>
604
+ </div>
605
+
606
+ <div class="content-section">
607
+ <h3>Error Output</h3>
608
+ <div class="code-output">
609
+ <pre>{{STDERR_OUTPUT}}</pre>
610
+ </div>
611
+ </div>
612
+
613
+ <div class="auto-refresh-indicator {{AUTO_REFRESH_CLASS}}">{{AUTO_REFRESH_TEXT}}</div>
614
+
615
+ <div class="suggestions-box {{SUGGESTIONS_SECTION_CLASS}}">
616
+ <h3>{{SUGGESTIONS_TITLE}}</h3>
617
+ <ul>
618
+ {{SUGGESTIONS_LIST}}
619
+ </ul>
620
+ </div>
621
+ </div>
622
+ </div>
623
+
624
+ <!-- Diagnostics Panel (Right) -->
625
+ <div class="diagnostics-panel">
626
+ <h2>Diagnostics</h2>
627
+
628
+ <ul class="diagnostics-list">
629
+ <li class="{{SIMPLE_SECTION_CLASS}}">
630
+ <span class="label">Dev Server URL:</span>
631
+ <span class="value"><code>{{DEV_SERVER_URL}}</code></span>
632
+ </li>
633
+ <li class="{{SIMPLE_SECTION_CLASS}}">
634
+ <span class="label">Proxy URL:</span>
635
+ <span class="value"><code>{{PROXY_URL}}</code></span>
636
+ </li>
637
+ <li class="{{SIMPLE_SECTION_CLASS}}">
638
+ <span class="label">Workspace Script:</span>
639
+ <span class="value"><code>{{WORKSPACE_SCRIPT}}</code></span>
640
+ </li>
641
+ <li class="{{SIMPLE_SECTION_CLASS}}">
642
+ <span class="label">Target Org:</span>
643
+ <span class="value">{{ORG_TARGET}}</span>
644
+ </li>
645
+ <li class="{{SIMPLE_SECTION_CLASS}}">
646
+ <span class="label">Last Check:</span>
647
+ <span class="value">{{LAST_CHECK_TIME}}</span>
648
+ </li>
649
+
650
+ <li class="{{RUNTIME_SECTION_CLASS}}">
651
+ <span class="label">Node Version:</span>
652
+ <span class="value">{{NODE_VERSION}}</span>
653
+ </li>
654
+ <li class="{{RUNTIME_SECTION_CLASS}}">
655
+ <span class="label">Platform:</span>
656
+ <span class="value">{{PLATFORM}}</span>
657
+ </li>
658
+ <li class="{{RUNTIME_SECTION_CLASS}}">
659
+ <span class="label">Memory Usage:</span>
660
+ <span class="value">{{HEAP_USED_MB}} MB / {{HEAP_TOTAL_MB}} MB heap</span>
661
+ </li>
662
+ <li class="{{RUNTIME_SECTION_CLASS}}">
663
+ <span class="label">Process ID:</span>
664
+ <span class="value">{{PID}}</span>
665
+ </li>
666
+ </ul>
667
+
668
+ <div class="live-logs {{SIMPLE_SECTION_CLASS}}">
669
+ <div class="log-line">
670
+ <span class="timestamp">[{{LAST_CHECK_TIME}}]</span>
671
+ <span class="log-content">proxy ▶ waiting for backend...</span>
672
+ </div>
673
+ <div class="log-line">
674
+ <span class="timestamp">[{{LAST_CHECK_TIME}}]</span>
675
+ <span class="log-content">check {{DEV_SERVER_URL}} ▶ unreachable</span>
676
+ </div>
677
+ <div class="log-line">
678
+ <span class="timestamp">[{{LAST_CHECK_TIME}}]</span>
679
+ <span class="log-content">hint ▶ try "{{WORKSPACE_SCRIPT}}"</span>
680
+ </div>
681
+ </div>
682
+
683
+ <div class="live-logs {{RUNTIME_SECTION_CLASS}}">
684
+ <div class="log-line">
685
+ <span class="timestamp">[{{TIMESTAMP_FORMATTED}}]</span>
686
+ <span class="log-content">error ▶ {{ERROR_TYPE}} detected</span>
687
+ </div>
688
+ <div class="log-line">
689
+ <span class="log-content">severity ▶ {{SEVERITY_LABEL}}</span>
690
+ </div>
691
+ </div>
692
+
693
+ <!-- Emergency exit commands -->
694
+ <div class="emergency-commands">
695
+ <h3>⚠️ If Ctrl+C doesn't work</h3>
696
+ <p>Copy and run this command in a new terminal to force-stop the proxy:</p>
697
+
698
+ <div class="command-item">
699
+ <div class="command-comment">Kill all processes on port {{PROXY_PORT}}:</div>
700
+ <div class="command-wrapper">
701
+ <div class="command-box">lsof -ti:{{PROXY_PORT}} | xargs kill -9</div>
702
+ <button
703
+ class="copy-button"
704
+ onclick="copyCommand(this, 'lsof -ti:{{PROXY_PORT}} | xargs kill -9')"
705
+ >
706
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
707
+ <path
708
+ d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"
709
+ />
710
+ </svg>
711
+ </button>
712
+ </div>
713
+ </div>
714
+ </div>
715
+ </div>
716
+ </div>
717
+
718
+ <script>
719
+ function copyCommand(button, command) {
720
+ const textarea = document.createElement("textarea");
721
+ textarea.value = command;
722
+ textarea.style.position = "fixed";
723
+ textarea.style.opacity = "0";
724
+ document.body.appendChild(textarea);
725
+ textarea.select();
726
+ document.execCommand("copy");
727
+ document.body.removeChild(textarea);
728
+ const originalHTML = button.innerHTML;
729
+ button.innerHTML =
730
+ '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>';
731
+ button.classList.add("copied");
732
+ setTimeout(() => {
733
+ button.innerHTML = originalHTML;
734
+ button.classList.remove("copied");
735
+ }, 2000);
736
+ }
737
+ </script>
738
+
739
+ <!-- Footer -->
740
+ <div class="footer-section">
741
+ <p class="help-text">
742
+ Salesforce Web App Development Proxy &nbsp;•&nbsp; Press <strong>Ctrl+C</strong> in the
743
+ terminal to stop the proxy
744
+ </p>
745
+ </div>
746
+ </div>
747
+ </body>
748
+ </html>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@salesforce/webapp-experimental",
3
3
  "description": "[experimental] Core package for Salesforce Web Applications",
4
- "version": "1.22.1",
4
+ "version": "1.24.0",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "type": "module",
7
7
  "main": "./dist/index.js",
@@ -31,6 +31,7 @@
31
31
  ],
32
32
  "scripts": {
33
33
  "build": "tsc --build",
34
+ "postbuild": "node scripts/copy-templates.cjs",
34
35
  "clean": "rm -rf dist tsconfig.tsbuildinfo",
35
36
  "dev": "tsc --build --watch",
36
37
  "test": "vitest run",
@@ -54,5 +55,5 @@
54
55
  "publishConfig": {
55
56
  "access": "public"
56
57
  },
57
- "gitHead": "b07f50207ad2ffe2f2edf124fc373731d4101f51"
58
+ "gitHead": "7bb4b5adf5f2071b38ecf1c7b180f87ec9f71afc"
58
59
  }