cloudfrontize 1.1.7 → 1.3.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.
Files changed (33) hide show
  1. package/README.md +141 -83
  2. package/dist/cli.js +36 -32
  3. package/dist/ui/app.js +399 -0
  4. package/dist/ui/favicons/android-icon-144x144.png +0 -0
  5. package/dist/ui/favicons/android-icon-192x192.png +0 -0
  6. package/dist/ui/favicons/android-icon-36x36.png +0 -0
  7. package/dist/ui/favicons/android-icon-48x48.png +0 -0
  8. package/dist/ui/favicons/android-icon-72x72.png +0 -0
  9. package/dist/ui/favicons/android-icon-96x96.png +0 -0
  10. package/dist/ui/favicons/apple-icon-114x114.png +0 -0
  11. package/dist/ui/favicons/apple-icon-120x120.png +0 -0
  12. package/dist/ui/favicons/apple-icon-144x144.png +0 -0
  13. package/dist/ui/favicons/apple-icon-152x152.png +0 -0
  14. package/dist/ui/favicons/apple-icon-180x180.png +0 -0
  15. package/dist/ui/favicons/apple-icon-57x57.png +0 -0
  16. package/dist/ui/favicons/apple-icon-60x60.png +0 -0
  17. package/dist/ui/favicons/apple-icon-72x72.png +0 -0
  18. package/dist/ui/favicons/apple-icon-76x76.png +0 -0
  19. package/dist/ui/favicons/apple-icon-precomposed.png +0 -0
  20. package/dist/ui/favicons/apple-icon.png +0 -0
  21. package/dist/ui/favicons/browserconfig.xml +11 -0
  22. package/dist/ui/favicons/favicon-16x16.png +0 -0
  23. package/dist/ui/favicons/favicon-32x32.png +0 -0
  24. package/dist/ui/favicons/favicon-96x96.png +0 -0
  25. package/dist/ui/favicons/favicon.ico +0 -0
  26. package/dist/ui/favicons/manifest.json +41 -0
  27. package/dist/ui/favicons/ms-icon-144x144.png +0 -0
  28. package/dist/ui/favicons/ms-icon-150x150.png +0 -0
  29. package/dist/ui/favicons/ms-icon-310x310.png +0 -0
  30. package/dist/ui/favicons/ms-icon-70x70.png +0 -0
  31. package/dist/ui/index.html +102 -0
  32. package/dist/ui/style.css +639 -0
  33. package/package.json +1 -1
@@ -0,0 +1,639 @@
1
+ :root {
2
+ --bg-dark: #0f172a;
3
+ --bg-card: #1e293b;
4
+ --bg-header: #1e293b80;
5
+ --primary: #f97316; /* CloudFront Orange */
6
+ --primary-glow: #f9731640;
7
+ --secondary: #3b82f6; /* AWS Blue */
8
+ --text-main: #f8fafc;
9
+ --text-muted: #94a3b8;
10
+ --success: #22c55e;
11
+ --warning: #eab308;
12
+ --error: #ef4444;
13
+ --border: #334155;
14
+ --glass: rgba(255, 255, 255, 0.03);
15
+ }
16
+
17
+ * {
18
+ box-sizing: border-box;
19
+ margin: 0;
20
+ padding: 0;
21
+ }
22
+
23
+ body {
24
+ background-color: var(--bg-dark);
25
+ color: var(--text-main);
26
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
27
+ height: 100vh;
28
+ display: flex;
29
+ flex-direction: column;
30
+ overflow: hidden;
31
+ }
32
+
33
+ /* Header */
34
+ header {
35
+ background: var(--bg-header);
36
+ backdrop-filter: blur(12px);
37
+ border-bottom: 1px solid var(--border);
38
+ padding: 0.75rem 1.5rem;
39
+ display: flex;
40
+ justify-content: space-between;
41
+ align-items: center;
42
+ z-index: 100;
43
+ }
44
+
45
+ .logo {
46
+ display: flex;
47
+ align-items: center;
48
+ gap: 0.75rem;
49
+ }
50
+
51
+ .logo h1 {
52
+ font-size: 1.25rem;
53
+ font-weight: 700;
54
+ letter-spacing: -0.02em;
55
+ }
56
+
57
+ .badge {
58
+ font-size: 0.65rem;
59
+ background: var(--primary);
60
+ color: white;
61
+ padding: 0.1rem 0.4rem;
62
+ border-radius: 4px;
63
+ vertical-align: middle;
64
+ }
65
+
66
+ .status-bar {
67
+ display: flex;
68
+ gap: 1.5rem;
69
+ font-size: 0.85rem;
70
+ }
71
+
72
+ .status-item {
73
+ display: flex;
74
+ gap: 0.5rem;
75
+ }
76
+
77
+ .label { color: var(--text-muted); }
78
+ .success { color: var(--success); }
79
+
80
+ /* Main Layout */
81
+ main {
82
+ display: flex;
83
+ flex: 1;
84
+ overflow: hidden;
85
+ min-height: 0; /* Constraint for children */
86
+ }
87
+
88
+ /* Sidebar */
89
+ .sidebar {
90
+ width: 350px;
91
+ background: var(--bg-card);
92
+ border-right: 1px solid var(--border);
93
+ overflow-y: auto;
94
+ padding: 1.5rem;
95
+ }
96
+
97
+ .sidebar h2 {
98
+ font-size: 0.9rem;
99
+ text-transform: uppercase;
100
+ letter-spacing: 0.05em;
101
+ color: var(--text-muted);
102
+ margin-bottom: 1.5rem;
103
+ }
104
+
105
+ .control-group {
106
+ margin-bottom: 2rem;
107
+ }
108
+
109
+ .control-group h3 {
110
+ font-size: 0.75rem;
111
+ color: var(--text-muted);
112
+ margin-bottom: 0.75rem;
113
+ }
114
+
115
+ /* Presets */
116
+ .preset-grid {
117
+ display: grid;
118
+ grid-template-columns: 1fr 1fr;
119
+ gap: 0.5rem;
120
+ }
121
+
122
+ .btn-preset {
123
+ background: var(--glass);
124
+ border: 1px solid var(--border);
125
+ color: var(--text-main);
126
+ padding: 0.5rem;
127
+ font-size: 0.75rem;
128
+ border-radius: 6px;
129
+ cursor: pointer;
130
+ transition: all 0.2s;
131
+ text-align: left;
132
+ }
133
+
134
+ .btn-preset:hover {
135
+ border-color: var(--primary);
136
+ background: var(--primary-glow);
137
+ }
138
+
139
+ /* Tabs */
140
+ .tabs {
141
+ display: flex;
142
+ border-bottom: 1px solid var(--border);
143
+ margin-bottom: 1rem;
144
+ }
145
+
146
+ .tab-btn {
147
+ flex: 1;
148
+ background: none;
149
+ border: none;
150
+ color: var(--text-muted);
151
+ padding: 0.5rem;
152
+ font-size: 0.8rem;
153
+ cursor: pointer;
154
+ border-bottom: 2px solid transparent;
155
+ }
156
+
157
+ .tab-btn.active {
158
+ color: var(--primary);
159
+ border-bottom-color: var(--primary);
160
+ }
161
+
162
+ .tab-content {
163
+ display: none;
164
+ }
165
+
166
+ .tab-content.active {
167
+ display: block;
168
+ }
169
+
170
+ /* Header List */
171
+ .header-row {
172
+ display: flex;
173
+ flex-direction: column;
174
+ gap: 0.5rem;
175
+ padding: 0.75rem;
176
+ background: rgba(255,255,255,0.03);
177
+ border: 1px solid var(--border);
178
+ border-radius: 8px;
179
+ margin-bottom: 0.75rem;
180
+ transition: all 0.2s;
181
+ }
182
+
183
+ .header-row:hover {
184
+ border-color: rgba(255,255,255,0.1);
185
+ background: rgba(255,255,255,0.05);
186
+ }
187
+
188
+ .header-row.suppressed {
189
+ opacity: 0.7;
190
+ border-style: dashed;
191
+ background: rgba(239, 68, 68, 0.05);
192
+ }
193
+
194
+ .header-row.suppressed .hdr-key {
195
+ text-decoration: line-through;
196
+ color: var(--error);
197
+ }
198
+
199
+ .row-main {
200
+ display: flex;
201
+ gap: 0.5rem;
202
+ }
203
+
204
+ .row-actions {
205
+ display: flex;
206
+ justify-content: flex-end;
207
+ gap: 0.5rem;
208
+ border-top: 1px solid rgba(255,255,255,0.05);
209
+ padding-top: 0.5rem;
210
+ }
211
+
212
+ .header-row input {
213
+ background: #0f172a;
214
+ border: 1px solid var(--border);
215
+ color: var(--text-main);
216
+ padding: 0.4rem 0.6rem;
217
+ border-radius: 4px;
218
+ font-size: 0.8rem;
219
+ flex: 1;
220
+ min-width: 0;
221
+ width: 100%;
222
+ box-sizing: border-box;
223
+ }
224
+
225
+ .header-row input.input-error {
226
+ border-color: var(--error);
227
+ background: rgba(239, 68, 68, 0.05);
228
+ }
229
+
230
+ .hdr-val:disabled {
231
+ color: var(--text-muted);
232
+ font-style: italic;
233
+ cursor: not-allowed;
234
+ }
235
+
236
+ .btn-toggle-action, .btn-remove {
237
+ background: none;
238
+ border: none;
239
+ color: var(--text-muted);
240
+ cursor: pointer;
241
+ display: flex;
242
+ align-items: center;
243
+ justify-content: center;
244
+ padding: 0.2rem;
245
+ border-radius: 4px;
246
+ transition: all 0.2s;
247
+ }
248
+
249
+ .btn-toggle-action:hover { color: var(--primary); background: rgba(59, 130, 246, 0.1); }
250
+ .btn-toggle-action.active { color: var(--error); }
251
+ .btn-toggle-action.active:hover { background: rgba(239, 68, 68, 0.1); }
252
+
253
+ .btn-remove:hover { color: var(--error); background: rgba(239, 68, 68, 0.1); }
254
+
255
+ .btn-remove .material-icons, .btn-toggle-action .material-icons {
256
+ font-size: 1.1rem;
257
+ }
258
+
259
+ .btn-add {
260
+ background: none;
261
+ border: 1px dashed var(--border);
262
+ color: var(--text-muted);
263
+ width: 100%;
264
+ padding: 0.5rem;
265
+ font-size: 0.75rem;
266
+ border-radius: 4px;
267
+ cursor: pointer;
268
+ margin-top: 0.5rem;
269
+ }
270
+
271
+ .btn-add:hover {
272
+ border-color: var(--primary);
273
+ color: var(--primary);
274
+ }
275
+
276
+ .btn-primary.success {
277
+ background: var(--success);
278
+ border-color: var(--success);
279
+ }
280
+
281
+ /* Sidebar Actions */
282
+ .actions {
283
+ display: flex;
284
+ flex-direction: column;
285
+ gap: 0.75rem;
286
+ padding-top: 1rem;
287
+ }
288
+
289
+ .btn-primary {
290
+ background: rgba(255, 255, 255, 0.05);
291
+ color: var(--text-muted);
292
+ border: 1px solid var(--border);
293
+ padding: 0.75rem;
294
+ border-radius: 8px;
295
+ font-weight: 600;
296
+ cursor: pointer;
297
+ transition: all 0.2s;
298
+ display: flex;
299
+ align-items: center;
300
+ justify-content: center;
301
+ gap: 0.5rem;
302
+ }
303
+
304
+ .btn-primary:hover {
305
+ background: rgba(255, 255, 255, 0.1);
306
+ border-color: var(--text-muted);
307
+ }
308
+
309
+ .btn-primary.dirty {
310
+ background: var(--primary);
311
+ color: white;
312
+ border-color: var(--primary);
313
+ box-shadow: 0 4px 12px var(--primary-glow);
314
+ }
315
+
316
+ .btn-primary.dirty::before {
317
+ content: '●';
318
+ font-size: 0.6rem;
319
+ color: white;
320
+ animation: fadeIn 0.3s;
321
+ }
322
+
323
+ .btn-primary.success {
324
+ background: var(--success);
325
+ border-color: var(--success);
326
+ color: white;
327
+ }
328
+
329
+ .btn-primary.error-pulse {
330
+ background: var(--error);
331
+ border-color: var(--error);
332
+ color: white;
333
+ animation: shake 0.4s ease-in-out;
334
+ }
335
+
336
+ @keyframes shake {
337
+ 0%, 100% { transform: translateX(0); }
338
+ 25% { transform: translateX(-4px); }
339
+ 75% { transform: translateX(4px); }
340
+ }
341
+
342
+ .btn-secondary {
343
+ background: none;
344
+ border: 1px solid var(--border);
345
+ color: var(--text-muted);
346
+ padding: 0.6rem;
347
+ border-radius: 8px;
348
+ cursor: pointer;
349
+ }
350
+
351
+ /* Content Area */
352
+ .content {
353
+ flex: 1;
354
+ display: flex;
355
+ flex-direction: column;
356
+ background: #050505;
357
+ min-height: 0; /* Constraint for children */
358
+ }
359
+
360
+ .feed-header {
361
+ padding: 1rem 1.5rem;
362
+ display: flex;
363
+ align-items: center;
364
+ gap: 1.5rem;
365
+ border-bottom: 1px solid var(--border);
366
+ }
367
+
368
+ .filters {
369
+ display: flex;
370
+ gap: 0.5rem;
371
+ }
372
+
373
+ .btn-filter, .btn-clear {
374
+ background: var(--glass);
375
+ border: 1px solid var(--border);
376
+ color: var(--text-muted);
377
+ padding: 0.4rem 0.8rem;
378
+ font-size: 0.75rem;
379
+ border-radius: 20px;
380
+ cursor: pointer;
381
+ }
382
+
383
+ .btn-filter.active {
384
+ background: var(--primary);
385
+ border-color: var(--primary);
386
+ color: white;
387
+ }
388
+
389
+ .btn-clear {
390
+ margin-left: auto;
391
+ }
392
+
393
+ /* Request Feed */
394
+ .request-feed {
395
+ flex: 1;
396
+ overflow-y: auto;
397
+ padding: 1.5rem;
398
+ display: flex;
399
+ flex-direction: column;
400
+ gap: 1rem;
401
+ min-height: 0; /* Critical for scrollability */
402
+ }
403
+
404
+ .empty-state {
405
+ text-align: center;
406
+ color: var(--text-muted);
407
+ padding: 4rem;
408
+ }
409
+
410
+ /* Request Cards */
411
+ .request-card {
412
+ background: var(--bg-card);
413
+ border: 1px solid var(--border);
414
+ border-radius: 12px;
415
+ overflow: hidden;
416
+ transition: all 0.2s;
417
+ animation: slideIn 0.3s ease-out;
418
+ cursor: pointer;
419
+ flex-shrink: 0; /* Prevent squishing */
420
+ height: auto;
421
+ }
422
+
423
+ .request-card:hover {
424
+ border-color: var(--secondary);
425
+ background: #252e42;
426
+ }
427
+
428
+ .request-card.expanded {
429
+ border-color: var(--primary);
430
+ background: #1a2234;
431
+ }
432
+
433
+ @keyframes slideIn {
434
+ from { opacity: 0; transform: translateY(10px); }
435
+ to { opacity: 1; transform: translateY(0); }
436
+ }
437
+
438
+ .card-header {
439
+ padding: 0.75rem 1rem;
440
+ background: rgba(0,0,0,0.2);
441
+ display: flex;
442
+ justify-content: space-between;
443
+ align-items: center;
444
+ }
445
+
446
+ .card-id {
447
+ font-family: 'JetBrains Mono', monospace;
448
+ font-size: 0.65rem;
449
+ color: var(--text-muted);
450
+ background: rgba(255,255,255,0.05);
451
+ padding: 2px 4px;
452
+ border-radius: 3px;
453
+ opacity: 0.6;
454
+ }
455
+
456
+ .card-method {
457
+ font-weight: 800;
458
+ color: var(--secondary);
459
+ margin-right: 0.5rem;
460
+ font-family: 'JetBrains Mono', monospace;
461
+ }
462
+
463
+ .card-uri {
464
+ font-family: 'JetBrains Mono', monospace;
465
+ font-size: 0.85rem;
466
+ color: var(--text-main);
467
+ }
468
+
469
+ .card-status {
470
+ padding: 0.1rem 0.6rem;
471
+ border-radius: 4px;
472
+ font-weight: 700;
473
+ font-size: 0.8rem;
474
+ font-family: 'Inter', sans-serif;
475
+ }
476
+
477
+ .status-ok { background: #22c55e20; color: #22c55e; }
478
+ .status-error { background: #ef444420; color: #ef4444; }
479
+ .status-warn { background: #eab30820; color: #eab308; }
480
+
481
+ .expand-icon {
482
+ font-family: 'Material Icons';
483
+ font-size: 1.2rem;
484
+ color: var(--text-muted);
485
+ transition: transform 0.2s;
486
+ user-select: none;
487
+ }
488
+
489
+ .expanded .expand-icon {
490
+ transform: rotate(180deg);
491
+ }
492
+
493
+ .card-body-mini {
494
+ padding: 0.5rem 1rem;
495
+ display: flex;
496
+ justify-content: space-between;
497
+ align-items: center;
498
+ font-size: 0.75rem;
499
+ color: var(--text-muted);
500
+ }
501
+
502
+ .rewrite-path {
503
+ font-style: italic;
504
+ opacity: 0.8;
505
+ }
506
+
507
+ .performance-mini {
508
+ background: rgba(255,255,255,0.05);
509
+ padding: 2px 6px;
510
+ border-radius: 4px;
511
+ font-family: 'JetBrains Mono', monospace;
512
+ }
513
+
514
+ .card-details {
515
+ padding: 1rem;
516
+ border-top: 1px solid var(--border);
517
+ background: rgba(0,0,0,0.1);
518
+ animation: fadeIn 0.3s ease-in;
519
+ /* Remove fixed height to prevent nested scroll confusion */
520
+ padding-bottom: 2rem;
521
+ }
522
+
523
+ /* Internal Tabs (Breadcrumbs) */
524
+ .detail-nav {
525
+ display: flex;
526
+ gap: 1rem;
527
+ margin-bottom: 1rem;
528
+ border-bottom: 1px solid var(--border);
529
+ padding-bottom: 0.5rem;
530
+ }
531
+
532
+ .nav-item {
533
+ font-size: 0.75rem;
534
+ color: var(--text-muted);
535
+ cursor: pointer;
536
+ text-transform: uppercase;
537
+ font-weight: 700;
538
+ transition: color 0.2s;
539
+ }
540
+
541
+ .nav-item:hover { color: var(--secondary); }
542
+ .nav-item.active { color: var(--primary); position: relative; }
543
+ .nav-item.active::after {
544
+ content: '';
545
+ position: absolute;
546
+ bottom: -0.6rem;
547
+ left: 0;
548
+ width: 100%;
549
+ height: 2px;
550
+ background: var(--primary);
551
+ }
552
+
553
+ .detail-pane { display: none; }
554
+ .detail-pane.active { display: block; }
555
+
556
+ .header-lifecycle {
557
+ display: grid;
558
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
559
+ gap: 1.5rem;
560
+ margin-top: 1rem;
561
+ }
562
+
563
+ .lifecycle-col h5 {
564
+ font-size: 0.65rem;
565
+ color: var(--text-muted);
566
+ margin-bottom: 0.4rem;
567
+ text-transform: uppercase;
568
+ }
569
+
570
+ @keyframes fadeIn {
571
+ from { opacity: 0; transform: translateY(-5px); }
572
+ to { opacity: 1; transform: translateY(0); }
573
+ }
574
+
575
+ .detail-grid {
576
+ display: grid;
577
+ grid-template-columns: 1fr 1fr;
578
+ gap: 1.5rem;
579
+ }
580
+
581
+ .header-diff {
582
+ margin-top: 0.5rem;
583
+ background: #0f172a;
584
+ border-radius: 6px;
585
+ overflow: hidden;
586
+ }
587
+
588
+ .diff-table {
589
+ width: 100%;
590
+ border-collapse: collapse;
591
+ font-size: 0.75rem;
592
+ font-family: 'JetBrains Mono', monospace;
593
+ }
594
+
595
+ .diff-table td {
596
+ padding: 4px 10px;
597
+ border-bottom: 1px solid #1e293b;
598
+ }
599
+
600
+ .h-key { color: var(--secondary); width: 35%; }
601
+ .h-val { color: var(--text-main); word-break: break-all; }
602
+
603
+ .h-added { background: rgba(34, 197, 94, 0.1); }
604
+ .h-removed { background: rgba(239, 68, 68, 0.1); opacity: 0.6; }
605
+ .h-modified { background: rgba(59, 130, 246, 0.1); }
606
+
607
+ .deleted { color: var(--error); text-decoration: line-through; }
608
+
609
+ .body-snippet {
610
+ background: #0f172a;
611
+ padding: 1rem;
612
+ border-radius: 6px;
613
+ font-size: 0.7rem;
614
+ color: var(--text-muted);
615
+ margin-top: 0.5rem;
616
+ white-space: pre-wrap;
617
+ max-height: 200px;
618
+ overflow-y: auto;
619
+ }
620
+
621
+ .performance-gauge {
622
+ display: flex;
623
+ align-items: center;
624
+ gap: 0.5rem;
625
+ }
626
+
627
+ .gauge-bar {
628
+ flex: 1;
629
+ height: 6px;
630
+ background: #0f172a;
631
+ border-radius: 3px;
632
+ position: relative;
633
+ }
634
+
635
+ .gauge-fill {
636
+ height: 100%;
637
+ border-radius: 3px;
638
+ background: var(--primary);
639
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "cloudfrontize",
3
3
  "description": "High-performance, high-fidelity local emulator for AWS Lambda@Edge and CloudFront Functions. Validate edge logic, catch illegal header mutations, and execute production-grade runtimes on a specialized local static server.",
4
- "version": "1.1.7",
4
+ "version": "1.3.0",
5
5
  "type": "commonjs",
6
6
  "main": "dist/cli.js",
7
7
  "bin": {