@myop/cli 0.1.6 → 0.1.8

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.
@@ -1,5 +1,101 @@
1
1
  const SVG_NS = 'http://www.w3.org/2000/svg';
2
2
 
3
+ // Storage keys
4
+ const STORAGE_KEYS = {
5
+ REQUEST_LOG: 'myop_dev_request_log',
6
+ ORIGINS: 'myop_dev_origins',
7
+ COMPONENT_LINES: 'myop_dev_component_lines',
8
+ NODE_POSITIONS: 'myop_dev_node_positions',
9
+ EXPANDED_LABELS: 'myop_dev_expanded_labels',
10
+ ZOOM_LEVEL: 'myop_dev_zoom_level',
11
+ PAN_X: 'myop_dev_pan_x',
12
+ PAN_Y: 'myop_dev_pan_y'
13
+ };
14
+
15
+ // Load data from localStorage
16
+ function loadFromStorage() {
17
+ try {
18
+ // Load request log
19
+ const savedRequestLog = localStorage.getItem(STORAGE_KEYS.REQUEST_LOG);
20
+ if (savedRequestLog) {
21
+ requestLog = JSON.parse(savedRequestLog);
22
+ }
23
+
24
+ // Load origins
25
+ const savedOrigins = localStorage.getItem(STORAGE_KEYS.ORIGINS);
26
+ if (savedOrigins) {
27
+ origins = JSON.parse(savedOrigins);
28
+ }
29
+
30
+ // Load component lines
31
+ const savedComponentLines = localStorage.getItem(STORAGE_KEYS.COMPONENT_LINES);
32
+ if (savedComponentLines) {
33
+ const parsed = JSON.parse(savedComponentLines);
34
+ componentLines = new Map(Object.entries(parsed));
35
+ }
36
+
37
+ // Load node positions
38
+ const savedNodePositions = localStorage.getItem(STORAGE_KEYS.NODE_POSITIONS);
39
+ if (savedNodePositions) {
40
+ const parsed = JSON.parse(savedNodePositions);
41
+ nodePositions = new Map(Object.entries(parsed));
42
+ }
43
+
44
+ // Load expanded labels
45
+ const savedExpandedLabels = localStorage.getItem(STORAGE_KEYS.EXPANDED_LABELS);
46
+ if (savedExpandedLabels) {
47
+ expandedLabels = new Set(JSON.parse(savedExpandedLabels));
48
+ }
49
+
50
+ // Load zoom and pan state
51
+ const savedZoomLevel = localStorage.getItem(STORAGE_KEYS.ZOOM_LEVEL);
52
+ if (savedZoomLevel) {
53
+ zoomLevel = parseFloat(savedZoomLevel);
54
+ }
55
+
56
+ const savedPanX = localStorage.getItem(STORAGE_KEYS.PAN_X);
57
+ if (savedPanX) {
58
+ panX = parseFloat(savedPanX);
59
+ }
60
+
61
+ const savedPanY = localStorage.getItem(STORAGE_KEYS.PAN_Y);
62
+ if (savedPanY) {
63
+ panY = parseFloat(savedPanY);
64
+ }
65
+ } catch (error) {
66
+ console.error('Error loading from localStorage:', error);
67
+ }
68
+ }
69
+
70
+ // Save data to localStorage
71
+ function saveToStorage() {
72
+ try {
73
+ // Save request log
74
+ localStorage.setItem(STORAGE_KEYS.REQUEST_LOG, JSON.stringify(requestLog));
75
+
76
+ // Save origins
77
+ localStorage.setItem(STORAGE_KEYS.ORIGINS, JSON.stringify(origins));
78
+
79
+ // Save component lines (convert Map to object)
80
+ const componentLinesObj = Object.fromEntries(componentLines);
81
+ localStorage.setItem(STORAGE_KEYS.COMPONENT_LINES, JSON.stringify(componentLinesObj));
82
+
83
+ // Save node positions (convert Map to object)
84
+ const nodePositionsObj = Object.fromEntries(nodePositions);
85
+ localStorage.setItem(STORAGE_KEYS.NODE_POSITIONS, JSON.stringify(nodePositionsObj));
86
+
87
+ // Save expanded labels (convert Set to array)
88
+ localStorage.setItem(STORAGE_KEYS.EXPANDED_LABELS, JSON.stringify(Array.from(expandedLabels)));
89
+
90
+ // Save zoom and pan state
91
+ localStorage.setItem(STORAGE_KEYS.ZOOM_LEVEL, zoomLevel.toString());
92
+ localStorage.setItem(STORAGE_KEYS.PAN_X, panX.toString());
93
+ localStorage.setItem(STORAGE_KEYS.PAN_Y, panY.toString());
94
+ } catch (error) {
95
+ console.error('Error saving to localStorage:', error);
96
+ }
97
+ }
98
+
3
99
  // Initialize data
4
100
  let components = []; // Array of {id, path, name}
5
101
  let origins = [];
@@ -22,6 +118,9 @@ let panY = 0;
22
118
  let isPanning = false;
23
119
  let panStart = { x: 0, y: 0 };
24
120
 
121
+ // Load persisted data on startup
122
+ loadFromStorage();
123
+
25
124
  // Connect to SSE
26
125
  const eventSource = new EventSource('/events');
27
126
 
@@ -32,13 +131,36 @@ eventSource.onmessage = (event) => {
32
131
  components = data.components;
33
132
  updateComponentsList();
34
133
  renderArchitecture();
134
+ saveToStorage();
35
135
  } else if (data.type === 'origins') {
36
- origins = data.origins;
136
+ // Merge new origins with existing ones from localStorage
137
+ const existingOriginsMap = new Map(origins.map(o => [o.url, o]));
138
+ data.origins.forEach(newOrigin => {
139
+ const existing = existingOriginsMap.get(newOrigin.url);
140
+ if (existing) {
141
+ // Keep the higher request count
142
+ newOrigin.requestCount = Math.max(existing.requestCount, newOrigin.requestCount);
143
+ }
144
+ existingOriginsMap.set(newOrigin.url, newOrigin);
145
+ });
146
+ origins = Array.from(existingOriginsMap.values());
37
147
  renderArchitecture();
148
+ saveToStorage();
38
149
  } else if (data.type === 'requestLog') {
39
- requestLog = data.log;
150
+ // Merge server log with existing log from localStorage
151
+ const existingTimestamps = new Set(requestLog.map(r => r.timestamp));
152
+ data.log.forEach(entry => {
153
+ if (!existingTimestamps.has(entry.timestamp)) {
154
+ requestLog.push(entry);
155
+ }
156
+ });
157
+ // Keep only the most recent entries
158
+ if (requestLog.length > 100) {
159
+ requestLog = requestLog.slice(-100);
160
+ }
40
161
  updateActivityLog();
41
162
  updateStats();
163
+ saveToStorage();
42
164
  } else if (data.type === 'request') {
43
165
  handleNewRequest(data);
44
166
  }
@@ -91,6 +213,9 @@ function drag(evt) {
91
213
  }
92
214
 
93
215
  function endDrag(evt) {
216
+ if (draggedElement) {
217
+ saveToStorage(); // Save node positions after drag
218
+ }
94
219
  draggedElement = null;
95
220
  evt.preventDefault();
96
221
  }
@@ -140,11 +265,13 @@ function updateViewBox() {
140
265
  function zoomIn() {
141
266
  zoomLevel = Math.min(zoomLevel * 1.2, 5);
142
267
  updateViewBox();
268
+ saveToStorage();
143
269
  }
144
270
 
145
271
  function zoomOut() {
146
272
  zoomLevel = Math.max(zoomLevel / 1.2, 0.5);
147
273
  updateViewBox();
274
+ saveToStorage();
148
275
  }
149
276
 
150
277
  function resetZoom() {
@@ -152,6 +279,7 @@ function resetZoom() {
152
279
  panX = 0;
153
280
  panY = 0;
154
281
  updateViewBox();
282
+ saveToStorage();
155
283
  }
156
284
 
157
285
  function handleWheel(e) {
@@ -159,6 +287,7 @@ function handleWheel(e) {
159
287
  const delta = e.deltaY > 0 ? 0.9 : 1.1;
160
288
  zoomLevel = Math.max(0.5, Math.min(5, zoomLevel * delta));
161
289
  updateViewBox();
290
+ saveToStorage();
162
291
  }
163
292
 
164
293
  function startPan(e) {
@@ -182,6 +311,7 @@ function endPan() {
182
311
  isPanning = false;
183
312
  const svg = document.getElementById('architecture-svg');
184
313
  svg.classList.remove('panning');
314
+ saveToStorage(); // Save pan position after panning
185
315
  }
186
316
  }
187
317
 
@@ -602,6 +732,7 @@ function redrawRequestLines() {
602
732
  expandedLabels.add(labelKey);
603
733
  }
604
734
  redrawRequestLines();
735
+ saveToStorage();
605
736
  };
606
737
 
607
738
  const labelBg = document.createElementNS(SVG_NS, 'rect');
@@ -669,6 +800,7 @@ function redrawRequestLines() {
669
800
  expandedLabels.add(labelKey2);
670
801
  }
671
802
  redrawRequestLines();
803
+ saveToStorage();
672
804
  };
673
805
 
674
806
  const labelBg2 = document.createElementNS(SVG_NS, 'rect');
@@ -760,6 +892,12 @@ function updateStats() {
760
892
 
761
893
  function handleNewRequest(data) {
762
894
  requestLog.push(data);
895
+
896
+ // Keep log size limited
897
+ if (requestLog.length > 100) {
898
+ requestLog.shift();
899
+ }
900
+
763
901
  updateActivityLog();
764
902
  updateStats();
765
903
 
@@ -780,8 +918,48 @@ function handleNewRequest(data) {
780
918
 
781
919
  // Redraw lines
782
920
  redrawRequestLines();
921
+
922
+ // Save to localStorage
923
+ saveToStorage();
924
+ }
925
+
926
+ // Add clear data button functionality
927
+ function clearStoredData() {
928
+ if (confirm('Clear all stored data (request logs, origins, positions)?')) {
929
+ // Clear localStorage
930
+ Object.values(STORAGE_KEYS).forEach(key => localStorage.removeItem(key));
931
+
932
+ // Reset in-memory data structures
933
+ requestLog.length = 0;
934
+ origins.length = 0;
935
+ componentLines.clear();
936
+ nodePositions.clear();
937
+ expandedLabels.clear();
938
+
939
+ // Reset zoom and pan
940
+ zoomLevel = 1;
941
+ panX = 0;
942
+ panY = 0;
943
+
944
+ // Reset stats
945
+ totalRequests = 0;
946
+ localRequests = 0;
947
+ proxiedRequests = 0;
948
+
949
+ // Re-render everything
950
+ renderArchitecture();
951
+ updateComponentsList();
952
+ updateActivityLog();
953
+ updateStats();
954
+ updateViewBox();
955
+
956
+ console.log('🗑️ All stored data cleared');
957
+ }
783
958
  }
784
959
 
960
+ // Export function for use in HTML
961
+ window.clearStoredData = clearStoredData;
962
+
785
963
  // Initial render
786
964
  renderArchitecture();
787
965
  updateComponentsList();
@@ -32,6 +32,7 @@ ${styles}
32
32
  <div class="tab active">Network Architecture</div>
33
33
  <div class="tab">Performance</div>
34
34
  <div class="tab">Console</div>
35
+ <button class="clear-data-btn" onclick="clearStoredData()" title="Clear all stored data">🗑️ Clear Data</button>
35
36
  </div>
36
37
 
37
38
  <div class="main-content">
@@ -85,6 +85,33 @@ body {
85
85
  border-bottom: 2px solid #007acc;
86
86
  }
87
87
 
88
+ .clear-data-btn {
89
+ margin-left: auto;
90
+ margin-right: 10px;
91
+ padding: 5px 12px;
92
+ background: #3e3e42;
93
+ border: 1px solid #5a5a5f;
94
+ color: #cccccc;
95
+ font-size: 11px;
96
+ font-family: inherit;
97
+ cursor: pointer;
98
+ border-radius: 3px;
99
+ display: flex;
100
+ align-items: center;
101
+ gap: 4px;
102
+ transition: all 0.2s;
103
+ }
104
+
105
+ .clear-data-btn:hover {
106
+ background: #4e4e52;
107
+ border-color: #007acc;
108
+ color: #ffffff;
109
+ }
110
+
111
+ .clear-data-btn:active {
112
+ background: #2e2e32;
113
+ }
114
+
88
115
  .main-content {
89
116
  display: flex;
90
117
  flex: 1;