@bobfrankston/msger 0.1.73 → 0.1.75

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 (134) hide show
  1. package/KNOWN-BUGS.md +121 -0
  2. package/MSGER-API-SUMMARY.md +162 -0
  3. package/MSGER-API.md +376 -0
  4. package/README.md +93 -0
  5. package/SESSION-2025-11-06.md +191 -0
  6. package/SESSION-NOTES.md +678 -0
  7. package/clihandler.d.ts.map +1 -1
  8. package/clihandler.js +62 -2
  9. package/clihandler.js.map +1 -1
  10. package/clihandler.ts +60 -2
  11. package/icon.png +0 -0
  12. package/icon1.png +0 -0
  13. package/msger-native/Cargo.toml +1 -0
  14. package/msger-native/bin/msgernative.exe +0 -0
  15. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Breadcrumbs +12 -118
  16. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/BrowserMetrics/{BrowserMetrics-690552AF-DCD4.pma → BrowserMetrics-690B9AD3-657C.pma} +0 -0
  17. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/BrowserMetrics/{BrowserMetrics-69055373-F88C.pma → BrowserMetrics-690BA05A-501C.pma} +0 -0
  18. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Crashpad/settings.dat +0 -0
  19. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/BrowsingTopicsState +1 -1
  20. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Cache/Cache_Data/data_0 +0 -0
  21. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Cache/Cache_Data/data_1 +0 -0
  22. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/{BrowserMetrics/BrowserMetrics-69055587-A65C.pma → Default/Cache/Cache_Data/data_2} +0 -0
  23. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Cache/Cache_Data/data_3 +0 -0
  24. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Cache/Cache_Data/f_000001 +383 -0
  25. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Cache/Cache_Data/f_000002 +1091 -0
  26. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Cache/Cache_Data/f_000003 +2153 -0
  27. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Cache/Cache_Data/f_000004 +0 -0
  28. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Cache/Cache_Data/f_000005 +626 -0
  29. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Cache/Cache_Data/f_000006 +393 -0
  30. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Cache/Cache_Data/index +0 -0
  31. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Code Cache/js/01241693cfdc32b9_0 +0 -0
  32. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Code Cache/js/0ba1eea781f3552c_0 +0 -0
  33. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Code Cache/js/323aa210eebefe2c_0 +0 -0
  34. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Code Cache/js/4608446ac118e77a_0 +0 -0
  35. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Code Cache/js/6938205dc2f77841_0 +0 -0
  36. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Code Cache/js/6de12299dc89e5f3_0 +0 -0
  37. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Code Cache/js/8f403c112eaa455b_0 +0 -0
  38. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Code Cache/js/9a3aceb491137f07_0 +0 -0
  39. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Code Cache/js/aedb266cbaf9c28f_0 +0 -0
  40. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Code Cache/js/ca526fdda86d0b9d_0 +0 -0
  41. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Code Cache/js/f5d11d783c9fdf69_0 +0 -0
  42. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Code Cache/js/index-dir/the-real-index +0 -0
  43. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Collections/collectionsSQLite +0 -0
  44. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Collections/collectionsSQLite-journal +0 -0
  45. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/DIPS +0 -0
  46. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/DawnGraphiteCache/data_1 +0 -0
  47. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/DawnGraphiteCache/index +0 -0
  48. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/DawnWebGPUCache/data_1 +0 -0
  49. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/DawnWebGPUCache/index +0 -0
  50. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Extension State/LOG +3 -3
  51. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Extension State/LOG.old +3 -3
  52. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Favicons +0 -0
  53. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/GPUCache/data_0 +0 -0
  54. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/GPUCache/data_1 +0 -0
  55. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/GPUCache/data_2 +0 -0
  56. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/GPUCache/index +0 -0
  57. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/History +0 -0
  58. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Local Storage/leveldb/000003.log +0 -0
  59. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Local Storage/leveldb/LOG +3 -3
  60. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Local Storage/leveldb/LOG.old +3 -3
  61. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/MediaDeviceSalts +0 -0
  62. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/MediaDeviceSalts-journal +0 -0
  63. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Network/Network Persistent State +1 -1
  64. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Network/TransportSecurity +1 -0
  65. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Preferences +1 -1
  66. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Service Worker/CacheStorage/14e849fa8522d406112ea607cf7fd6342b71b987/249ee9af-c3df-4a86-89a8-2c51f3370ee0/index +0 -0
  67. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Service Worker/CacheStorage/14e849fa8522d406112ea607cf7fd6342b71b987/249ee9af-c3df-4a86-89a8-2c51f3370ee0/index-dir/the-real-index +0 -0
  68. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Service Worker/CacheStorage/14e849fa8522d406112ea607cf7fd6342b71b987/index.txt +0 -0
  69. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Service Worker/Database/000003.log +0 -0
  70. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Service Worker/Database/CURRENT +1 -0
  71. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Service Worker/Database/LOCK +0 -0
  72. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Service Worker/Database/LOG +3 -0
  73. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Service Worker/Database/LOG.old +3 -0
  74. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Service Worker/Database/MANIFEST-000001 +0 -0
  75. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Service Worker/ScriptCache/2cc80dabc69f58b6_0 +0 -0
  76. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Service Worker/ScriptCache/2cc80dabc69f58b6_1 +0 -0
  77. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Service Worker/ScriptCache/index +0 -0
  78. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Service Worker/ScriptCache/index-dir/the-real-index +0 -0
  79. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Session Storage/000003.log +0 -0
  80. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Session Storage/LOG +3 -3
  81. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Session Storage/LOG.old +3 -3
  82. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Site Characteristics Database/000003.log +0 -0
  83. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Site Characteristics Database/LOG +3 -3
  84. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Site Characteristics Database/LOG.old +3 -3
  85. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Sync Data/LevelDB/LOG +3 -3
  86. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Sync Data/LevelDB/LOG.old +3 -3
  87. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/WebStorage/QuotaManager +0 -0
  88. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/WebStorage/QuotaManager-journal +0 -0
  89. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/favorites_diagnostic.log +27 -0
  90. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/shared_proto_db/000003.log +0 -0
  91. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/shared_proto_db/LOG +3 -3
  92. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/shared_proto_db/LOG.old +3 -3
  93. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/shared_proto_db/metadata/000003.log +0 -0
  94. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/shared_proto_db/metadata/LOG +3 -3
  95. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/shared_proto_db/metadata/LOG.old +3 -3
  96. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/GrShaderCache/data_0 +0 -0
  97. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/GrShaderCache/data_1 +0 -0
  98. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/GrShaderCache/data_3 +0 -0
  99. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/GrShaderCache/f_000003 +0 -0
  100. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/GrShaderCache/f_000004 +0 -0
  101. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/GrShaderCache/index +0 -0
  102. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/GraphiteDawnCache/data_1 +0 -0
  103. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/GraphiteDawnCache/index +0 -0
  104. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Local State +1 -1
  105. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/RevisitationBloomfilter +0 -0
  106. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/ShaderCache/data_1 +0 -0
  107. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/ShaderCache/index +0 -0
  108. package/msger-native/src/main.rs +343 -37
  109. package/msger-native/src/template.html +103 -28
  110. package/msger-storage-demo.html +290 -0
  111. package/msger.code-workspace +3 -0
  112. package/msgerdefs/README.md +122 -0
  113. package/msgerdefs/msgerdefs.d.ts +322 -0
  114. package/msgerdefs/msgerdefs.d.ts.map +1 -0
  115. package/msgerdefs/msgerdefs.js +110 -0
  116. package/msgerdefs/msgerdefs.js.map +1 -0
  117. package/msgerdefs/msgerdefs.ts +427 -0
  118. package/msgerdefs/package.json +38 -0
  119. package/msgerdefs/samples.html +431 -0
  120. package/msgerdefs/test1.cmd +1 -0
  121. package/msgerdefs/tsconfig.json +17 -0
  122. package/msgernative-linux-x64 +0 -0
  123. package/package.json +5 -1
  124. package/shower.d.ts +2 -0
  125. package/shower.d.ts.map +1 -1
  126. package/shower.js +17 -0
  127. package/shower.js.map +1 -1
  128. package/shower.ts +24 -0
  129. package/test-data-persistence.html +315 -0
  130. package/test-htmlfrom.html +29 -0
  131. package/test-ipc-reach.html +113 -0
  132. package/test-msger-api.html +120 -0
  133. package/test-msger-functions.html +325 -0
  134. package/msger-native/bin/msgernative.exe.WebView2/EBWebView/BrowserMetrics/BrowserMetrics-69055419-C8A0.pma +0 -0
@@ -72,6 +72,39 @@
72
72
  </div>
73
73
  <div id="countdown" style="position: fixed; top: 5px; right: 5px; background: rgba(255, 255, 0, 0.3); padding: 5px 10px; font-size: 14px; font-weight: bold; border-radius: 4px; display: none;"></div>
74
74
  <script>
75
+ // msger JavaScript API with error handling
76
+ (function() {
77
+ // Check if IPC is available
78
+ const hasIPC = typeof window.ipc !== 'undefined' && window.ipc.postMessage;
79
+
80
+ // Helper to safely send IPC messages
81
+ function safePostMessage(data) {
82
+ try {
83
+ if (!hasIPC) {
84
+ console.error('msger API: window.ipc not available');
85
+ return false;
86
+ }
87
+ window.ipc.postMessage(JSON.stringify(data));
88
+ return true;
89
+ } catch(e) {
90
+ console.error('msger API error:', e);
91
+ return false;
92
+ }
93
+ }
94
+
95
+ window.msger = {
96
+ // Check if running in msger environment
97
+ isAvailable: function() {
98
+ return true;
99
+ }
100
+ };
101
+
102
+ // NOTE: Use native browser APIs instead of msger wrappers:
103
+ // - localStorage (native)
104
+ // - window.close() (native)
105
+ // msger API is minimal by design - we're just a CLI window wrapper
106
+ })();
107
+
75
108
  // Countdown timer overlay
76
109
  try {
77
110
  const timeoutSeconds = {TIMEOUT_SECONDS};
@@ -104,30 +137,53 @@
104
137
  }
105
138
 
106
139
  function sendResult(button) {
107
- const result = { button: button };
140
+ console.log('Button clicked:', button);
108
141
 
109
- // Get input field value if present
110
- const inputField = document.getElementById('inputField');
111
- if (inputField) {
112
- result.value = inputField.value;
113
- }
142
+ // Try IPC first - maybe it works in template mode?
143
+ try {
144
+ const result = { button: button };
114
145
 
115
- // Get all form data if forms are present
116
- const forms = document.querySelectorAll('form');
117
- if (forms.length > 0) {
118
- const formData = {};
119
- forms.forEach(form => {
120
- const data = new FormData(form);
121
- data.forEach((value, key) => {
122
- formData[key] = value;
123
- });
124
- });
125
- if (Object.keys(formData).length > 0) {
126
- result.form = formData;
146
+ // Get input field value if present
147
+ const inputField = document.getElementById('inputField');
148
+ if (inputField) {
149
+ result.value = inputField.value;
127
150
  }
151
+
152
+ if (typeof window.ipc !== 'undefined' && window.ipc.postMessage) {
153
+ console.log('Attempting IPC postMessage with:', result);
154
+ window.ipc.postMessage(JSON.stringify(result));
155
+ console.log('IPC postMessage succeeded!');
156
+ return true;
157
+ } else {
158
+ console.error('window.ipc not available');
159
+ return false;
160
+ }
161
+ } catch(e) {
162
+ console.error('IPC failed:', e);
163
+ return false;
128
164
  }
129
165
 
130
- window.ipc.postMessage(JSON.stringify(result));
166
+ // const result = { button: button };
167
+ // // Get input field value if present
168
+ // const inputField = document.getElementById('inputField');
169
+ // if (inputField) {
170
+ // result.value = inputField.value;
171
+ // }
172
+ // // Get all form data if forms are present
173
+ // const forms = document.querySelectorAll('form');
174
+ // if (forms.length > 0) {
175
+ // const formData = {};
176
+ // forms.forEach(form => {
177
+ // const data = new FormData(form);
178
+ // data.forEach((value, key) => {
179
+ // formData[key] = value;
180
+ // });
181
+ // });
182
+ // if (Object.keys(formData).length > 0) {
183
+ // result.form = formData;
184
+ // }
185
+ // }
186
+ // window.ipc.postMessage(JSON.stringify(result));
131
187
  }
132
188
 
133
189
  // Auto-size window to content
@@ -168,15 +224,15 @@
168
224
  });
169
225
  }
170
226
 
227
+ // Zoom support with mouse wheel
228
+ let zoomLevel = 1.0;
229
+
171
230
  // Set initial zoom level if specified
172
231
  const initialZoom = {ZOOM_PERCENT};
173
232
  if (initialZoom) {
174
233
  zoomLevel = initialZoom / 100.0;
175
234
  document.body.style.zoom = zoomLevel;
176
235
  }
177
-
178
- // Zoom support with mouse wheel
179
- let zoomLevel = 1.0;
180
236
  document.addEventListener('wheel', function(e) {
181
237
  // Only zoom when Ctrl is held (or Cmd on Mac)
182
238
  if (e.ctrlKey || e.metaKey) {
@@ -197,17 +253,30 @@
197
253
  window.addEventListener('load', function() {
198
254
  document.body.focus();
199
255
  });
200
-
256
+
201
257
  // Also focus when window gets focus
202
258
  window.addEventListener('focus', function() {
203
259
  document.body.focus();
204
260
  });
205
-
261
+
206
262
  // And try again after a short delay
207
263
  setTimeout(() => {
208
264
  document.body.focus();
209
265
  }, 100);
210
266
 
267
+ // Auto-trigger fullscreen if requested
268
+ const startFullscreen = {FULLSCREEN};
269
+ if (startFullscreen) {
270
+ window.addEventListener('load', function() {
271
+ // Wait a bit for the window to be ready
272
+ setTimeout(() => {
273
+ document.documentElement.requestFullscreen().catch(err => {
274
+ console.error('Failed to enter fullscreen:', err);
275
+ });
276
+ }, 100);
277
+ });
278
+ }
279
+
211
280
  document.addEventListener('keydown', function(e) {
212
281
  if (e.key === 'Escape') {
213
282
  e.preventDefault();
@@ -215,14 +284,20 @@
215
284
  if (document.fullscreenElement) {
216
285
  document.exitFullscreen();
217
286
  } else {
218
- const result = { button: 'Cancel', dismissed: true };
219
- window.ipc.postMessage(JSON.stringify(result));
287
+ // CANNOT use IPC - it crashes!
288
+ // The Rust window handler should catch Esc key
289
+ console.error('Esc key: Cannot send via IPC (crashes). Close window with X button instead.');
290
+ // const result = { button: 'Cancel', dismissed: true };
291
+ // window.ipc.postMessage(JSON.stringify(result));
220
292
  }
221
293
  } else if (e.key === 'F11') {
222
- // Toggle fullscreen
294
+ // Note: This uses HTML5 fullscreen, not native window fullscreen
295
+ // The Rust window handler should catch F11 for native fullscreen
223
296
  e.preventDefault();
224
297
  if (!document.fullscreenElement) {
225
- document.documentElement.requestFullscreen();
298
+ document.documentElement.requestFullscreen().catch(err => {
299
+ console.warn('HTML5 fullscreen failed:', err);
300
+ });
226
301
  } else {
227
302
  document.exitFullscreen();
228
303
  }
@@ -0,0 +1,290 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>msger Storage API Demo</title>
6
+ <style>
7
+ body {
8
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
9
+ padding: 30px;
10
+ max-width: 800px;
11
+ margin: 0 auto;
12
+ background: #f5f5f5;
13
+ }
14
+ h1 { color: #333; }
15
+ .info {
16
+ background: #e3f2fd;
17
+ border-left: 4px solid #0066cc;
18
+ padding: 15px;
19
+ margin: 20px 0;
20
+ border-radius: 4px;
21
+ }
22
+ .warning {
23
+ background: #fff3cd;
24
+ border-left: 4px solid #ffc107;
25
+ padding: 15px;
26
+ margin: 20px 0;
27
+ border-radius: 4px;
28
+ }
29
+ .section {
30
+ background: white;
31
+ padding: 20px;
32
+ margin: 20px 0;
33
+ border-radius: 8px;
34
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
35
+ }
36
+ input, textarea {
37
+ width: 100%;
38
+ padding: 10px;
39
+ margin: 5px 0;
40
+ border: 1px solid #ddd;
41
+ border-radius: 4px;
42
+ font-family: inherit;
43
+ box-sizing: border-box;
44
+ }
45
+ button {
46
+ padding: 10px 20px;
47
+ margin: 5px;
48
+ background: #0066cc;
49
+ color: white;
50
+ border: none;
51
+ border-radius: 4px;
52
+ cursor: pointer;
53
+ font-size: 14px;
54
+ }
55
+ button:hover { background: #0052a3; }
56
+ button.secondary { background: #6c757d; }
57
+ button.secondary:hover { background: #5a6268; }
58
+ .output {
59
+ background: #f8f9fa;
60
+ border: 1px solid #dee2e6;
61
+ border-radius: 4px;
62
+ padding: 15px;
63
+ margin: 10px 0;
64
+ font-family: 'Courier New', monospace;
65
+ font-size: 13px;
66
+ white-space: pre-wrap;
67
+ min-height: 60px;
68
+ }
69
+ code {
70
+ background: #f4f4f4;
71
+ padding: 2px 6px;
72
+ border-radius: 3px;
73
+ font-family: 'Courier New', monospace;
74
+ }
75
+ </style>
76
+ </head>
77
+ <body>
78
+ <h1>msger Storage API Demo</h1>
79
+
80
+ <div class="info">
81
+ <strong>✅ What Works:</strong> localStorage-based persistence API<br>
82
+ <strong>❌ What's Broken:</strong> All window controls, buttons, F11 (IPC crashes)<br>
83
+ <strong>🔧 How to Close:</strong> Click the X button (top-right corner)
84
+ </div>
85
+
86
+ <div class="warning">
87
+ <strong>⚠️ Window Controls Disabled</strong><br>
88
+ Due to a wry library bug, all window operations via JavaScript crash the app.
89
+ Configure window at startup using CLI flags: <code>-size 800,600 -title "My App"</code>
90
+ </div>
91
+
92
+ <!-- Basic Storage -->
93
+ <div class="section">
94
+ <h2>Basic Storage (with Timestamps)</h2>
95
+ <input type="text" id="key" value="myData" placeholder="Storage key">
96
+ <textarea id="value" rows="3" placeholder="Enter any text...">Hello from msger!</textarea>
97
+ <div>
98
+ <button onclick="saveData()">Save Data</button>
99
+ <button onclick="loadData()">Load Data</button>
100
+ <button onclick="removeData()" class="secondary">Remove Data</button>
101
+ </div>
102
+ <div id="output1" class="output">Click Save to store data</div>
103
+ </div>
104
+
105
+ <!-- Complex Data -->
106
+ <div class="section">
107
+ <h2>Structured Data</h2>
108
+ <p>Save complex objects, arrays, and nested data</p>
109
+ <button onclick="saveUserSettings()">Save User Settings</button>
110
+ <button onclick="loadUserSettings()">Load User Settings</button>
111
+ <div id="output2" class="output">Click to save/load structured data</div>
112
+ </div>
113
+
114
+ <!-- List All Data -->
115
+ <div class="section">
116
+ <h2>Manage Storage</h2>
117
+ <button onclick="listAll()">List All Saved Data</button>
118
+ <button onclick="clearAll()" class="secondary">Clear All msger Data</button>
119
+ <div id="output3" class="output">Click to list or clear data</div>
120
+ </div>
121
+
122
+ <!-- File-Like Storage -->
123
+ <div class="section">
124
+ <h2>Virtual File Storage</h2>
125
+ <p>Store "files" in localStorage and export them</p>
126
+ <input type="text" id="filename" value="document.txt" placeholder="Filename">
127
+ <textarea id="filecontent" rows="5" placeholder="File content...">This is a virtual file stored in localStorage.</textarea>
128
+ <div>
129
+ <button onclick="saveFile()">Save Virtual File</button>
130
+ <button onclick="loadFile()">Load Virtual File</button>
131
+ <button onclick="downloadFile()">Export (Download)</button>
132
+ </div>
133
+ <div id="output4" class="output">Click to save/load/export files</div>
134
+ </div>
135
+
136
+ <script>
137
+ // Check if msger API is available
138
+ const hasMsger = typeof window.msger !== 'undefined';
139
+ if (!hasMsger) {
140
+ alert('WARNING: msger API not found! Are you running in msger?');
141
+ }
142
+
143
+ function log(id, msg, color = '#4ec9b0') {
144
+ document.getElementById(id).textContent = msg;
145
+ }
146
+
147
+ // Basic Storage
148
+ function saveData() {
149
+ const key = document.getElementById('key').value;
150
+ const value = document.getElementById('value').value;
151
+ const data = {
152
+ value: value,
153
+ savedAt: new Date().toISOString(),
154
+ savedTimestamp: Date.now()
155
+ };
156
+ const result = msger.saveData(key, data);
157
+ log('output1', `✅ Saved!\nKey: ${key}\nValue: ${value}\nTime: ${data.savedAt}\n\nData persists across restarts!`);
158
+ }
159
+
160
+ function loadData() {
161
+ const key = document.getElementById('key').value;
162
+ const data = msger.loadData(key, null);
163
+ if (data) {
164
+ const age = Math.floor((Date.now() - data.savedTimestamp) / 1000);
165
+ log('output1', `✅ Loaded!\nKey: ${key}\nValue: ${data.value}\nSaved: ${data.savedAt}\nAge: ${age} seconds ago\n\nThis proves persistence works!`);
166
+ document.getElementById('value').value = data.value;
167
+ } else {
168
+ log('output1', `❌ Key "${key}" not found`);
169
+ }
170
+ }
171
+
172
+ function removeData() {
173
+ const key = document.getElementById('key').value;
174
+ msger.removeData(key);
175
+ log('output1', `✅ Removed key: ${key}`);
176
+ }
177
+
178
+ // Structured Data
179
+ function saveUserSettings() {
180
+ const settings = {
181
+ theme: 'dark',
182
+ fontSize: 14,
183
+ language: 'en',
184
+ notifications: {
185
+ email: true,
186
+ push: false
187
+ },
188
+ recentFiles: [
189
+ 'document1.txt',
190
+ 'notes.md',
191
+ 'project.json'
192
+ ]
193
+ };
194
+ msger.saveData('userSettings', settings);
195
+ log('output2', `✅ Saved complex object:\n${JSON.stringify(settings, null, 2)}`);
196
+ }
197
+
198
+ function loadUserSettings() {
199
+ const settings = msger.loadData('userSettings', null);
200
+ if (settings) {
201
+ log('output2', `✅ Loaded settings:\n${JSON.stringify(settings, null, 2)}`);
202
+ } else {
203
+ log('output2', `❌ No settings found. Click "Save User Settings" first.`);
204
+ }
205
+ }
206
+
207
+ // List All
208
+ function listAll() {
209
+ const allKeys = Object.keys(localStorage);
210
+ const msgerKeys = allKeys.filter(k => k.startsWith('msger_'));
211
+ if (msgerKeys.length === 0) {
212
+ log('output3', `No msger data found. Save something first!`);
213
+ return;
214
+ }
215
+ let output = `Found ${msgerKeys.length} items:\n\n`;
216
+ msgerKeys.forEach(key => {
217
+ const displayKey = key.replace('msger_', '');
218
+ const data = msger.loadData(displayKey, null);
219
+ if (data && data.savedAt) {
220
+ const age = Math.floor((Date.now() - data.savedTimestamp) / 1000);
221
+ output += `📄 ${displayKey} (${age}s ago)\n`;
222
+ } else {
223
+ output += `📄 ${displayKey}\n`;
224
+ }
225
+ });
226
+ log('output3', output);
227
+ }
228
+
229
+ function clearAll() {
230
+ if (confirm('Clear all msger data?')) {
231
+ msger.clearData();
232
+ log('output3', `✅ All msger data cleared!`);
233
+ }
234
+ }
235
+
236
+ // Virtual Files
237
+ function saveFile() {
238
+ const filename = document.getElementById('filename').value;
239
+ const content = document.getElementById('filecontent').value;
240
+ const fileData = {
241
+ name: filename,
242
+ content: content,
243
+ size: content.length,
244
+ created: new Date().toISOString()
245
+ };
246
+ msger.saveData('file_' + filename, fileData);
247
+ log('output4', `✅ Saved virtual file:\nName: ${filename}\nSize: ${content.length} bytes\nCreated: ${fileData.created}`);
248
+ }
249
+
250
+ function loadFile() {
251
+ const filename = document.getElementById('filename').value;
252
+ const fileData = msger.loadData('file_' + filename, null);
253
+ if (fileData) {
254
+ document.getElementById('filecontent').value = fileData.content;
255
+ log('output4', `✅ Loaded file:\nName: ${fileData.name}\nSize: ${fileData.size} bytes\nCreated: ${fileData.created}`);
256
+ } else {
257
+ log('output4', `❌ File "${filename}" not found`);
258
+ }
259
+ }
260
+
261
+ function downloadFile() {
262
+ const filename = document.getElementById('filename').value;
263
+ const fileData = msger.loadData('file_' + filename, null);
264
+ if (fileData) {
265
+ const blob = new Blob([fileData.content], { type: 'text/plain' });
266
+ const url = URL.createObjectURL(blob);
267
+ const a = document.createElement('a');
268
+ a.href = url;
269
+ a.download = fileData.name;
270
+ a.click();
271
+ URL.revokeObjectURL(url);
272
+ log('output4', `✅ Downloaded: ${fileData.name}`);
273
+ } else {
274
+ log('output4', `❌ File "${filename}" not found. Save it first!`);
275
+ }
276
+ }
277
+
278
+ // Auto-load on startup
279
+ window.addEventListener('load', function() {
280
+ // Check for persisted data
281
+ const testKey = document.getElementById('key').value;
282
+ const data = msger.loadData(testKey, null);
283
+ if (data) {
284
+ log('output1', `✅ Found persisted data! Click "Load Data" to see it.`);
285
+ listAll();
286
+ }
287
+ });
288
+ </script>
289
+ </body>
290
+ </html>
@@ -2,6 +2,9 @@
2
2
  "folders": [
3
3
  {
4
4
  "path": "."
5
+ },
6
+ {
7
+ "path": "../msgview"
5
8
  }
6
9
  ],
7
10
  "settings": {
@@ -0,0 +1,122 @@
1
+ # @bobfrankston/msgerdefs
2
+
3
+ TypeScript definitions for the **msger** JavaScript API.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @bobfrankston/msgerdefs
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### TypeScript
14
+
15
+ ```typescript
16
+ import type { MsgerAPI } from '@bobfrankston/msgerdefs';
17
+ import { isMsger, getMsgerAPI } from '@bobfrankston/msgerdefs';
18
+
19
+ // Option 1: Type the global window.msger
20
+ declare global {
21
+ interface Window {
22
+ msger?: MsgerAPI;
23
+ }
24
+ }
25
+
26
+ // Check if running in msger
27
+ if (isMsger()) {
28
+ window.msger!.setTitle('My Application');
29
+ window.msger!.saveData('lastOpened', new Date().toISOString());
30
+ }
31
+
32
+ // Option 2: Use getMsgerAPI() for cross-platform compatibility
33
+ const msger = getMsgerAPI();
34
+ msger.saveData('userPrefs', { theme: 'dark' }); // Works in both msger and browser!
35
+ msger.setTitle('My App'); // Only works in msger, no-op in browser
36
+ ```
37
+
38
+ ### JavaScript
39
+
40
+ ```javascript
41
+ import { isMsger, getMsgerAPI } from '@bobfrankston/msgerdefs';
42
+
43
+ const msger = getMsgerAPI();
44
+
45
+ // Data persistence (works in both msger and browser)
46
+ msger.saveData('userSettings', { fontSize: 14, theme: 'dark' });
47
+ const settings = msger.loadData('userSettings', { fontSize: 12 });
48
+
49
+ // Window control (msger only, gracefully degrades in browser)
50
+ if (isMsger()) {
51
+ msger.toggleFullscreen();
52
+ msger.setAlwaysOnTop(true);
53
+ }
54
+ ```
55
+
56
+ ## API Reference
57
+
58
+ ### Window Control
59
+
60
+ - `toggleFullscreen()` - Toggle fullscreen mode
61
+ - `setFullscreen(enabled: boolean)` - Set fullscreen state
62
+ - `minimize()` - Minimize window
63
+ - `maximize()` - Toggle maximize/restore
64
+ - `setSize(width, height)` - Set window size
65
+ - `setPosition(x, y)` - Set window position
66
+ - `setAlwaysOnTop(enabled: boolean)` - Keep window on top
67
+ - `setTitle(title: string)` - Set window title
68
+ - `close(result?)` - Close window with optional result
69
+
70
+ ### Data Persistence
71
+
72
+ - `saveData(key, value)` - Save data to localStorage
73
+ - `loadData(key, defaultValue?)` - Load data from localStorage
74
+ - `removeData(key)` - Remove data
75
+ - `clearData()` - Clear all msger data
76
+
77
+ ### File System (Coming Soon)
78
+
79
+ - `fs.selectFile(options?)` - Open file picker
80
+ - `fs.selectFiles(options?)` - Open multi-file picker
81
+ - `fs.saveFileAs(content, filename?, options?)` - Save file dialog
82
+ - `fs.selectFolder(options?)` - Folder picker
83
+ - `fs.read(path)` - Read file (requires allowFs flag)
84
+ - `fs.write(path, content)` - Write file (requires allowFs flag)
85
+ - `fs.list(path)` - List directory (requires allowFs flag)
86
+ - `fs.exists(path)` - Check if file exists (requires allowFs flag)
87
+ - `fs.delete(path)` - Delete file (requires allowFs flag)
88
+
89
+ ## Examples
90
+
91
+ See [samples.html](samples.html) for interactive examples and demos of all API features!
92
+
93
+ **Test in msger:**
94
+ ```bash
95
+ msger -url "file:///path/to/node_modules/@bobfrankston/msgerdefs/samples.html"
96
+ ```
97
+
98
+ **Test in browser:**
99
+ ```bash
100
+ # Open samples.html in your browser to test browser compatibility
101
+ ```
102
+
103
+ The samples demonstrate:
104
+ - Window control (fullscreen, minimize, maximize, resize, position)
105
+ - Data persistence (save/load user preferences, session data, recent files)
106
+ - Presentation mode example
107
+ - Session management
108
+ - And more!
109
+
110
+ ## Browser Compatibility
111
+
112
+ The `getMsgerAPI()` function returns a browser-compatible implementation:
113
+
114
+ - **Data persistence**: Uses localStorage in both msger and browser
115
+ - **Window control**: No-op in browser (except `setTitle` updates document.title)
116
+ - **File system**: Not available in browser (`fs` is undefined)
117
+
118
+ This allows you to write code once that works in both environments!
119
+
120
+ ## License
121
+
122
+ ISC