@gxp-dev/tools 2.0.63 → 2.0.65

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 (182) hide show
  1. package/README.md +32 -31
  2. package/bin/gx-devtools.js +74 -54
  3. package/bin/lib/cli.js +23 -21
  4. package/bin/lib/commands/add-dependency.js +366 -325
  5. package/bin/lib/commands/assets.js +137 -139
  6. package/bin/lib/commands/build.js +169 -174
  7. package/bin/lib/commands/datastore.js +181 -183
  8. package/bin/lib/commands/dev.js +127 -131
  9. package/bin/lib/commands/extensions.js +147 -149
  10. package/bin/lib/commands/extract-config.js +73 -67
  11. package/bin/lib/commands/index.js +12 -12
  12. package/bin/lib/commands/init.js +342 -240
  13. package/bin/lib/commands/publish.js +69 -75
  14. package/bin/lib/commands/socket.js +69 -69
  15. package/bin/lib/commands/ssl.js +14 -14
  16. package/bin/lib/constants.js +10 -24
  17. package/bin/lib/tui/App.tsx +761 -705
  18. package/bin/lib/tui/components/AIPanel.tsx +191 -171
  19. package/bin/lib/tui/components/CommandInput.tsx +394 -343
  20. package/bin/lib/tui/components/GeminiPanel.tsx +175 -151
  21. package/bin/lib/tui/components/Header.tsx +23 -21
  22. package/bin/lib/tui/components/LogPanel.tsx +244 -220
  23. package/bin/lib/tui/components/TabBar.tsx +50 -48
  24. package/bin/lib/tui/components/WelcomeScreen.tsx +126 -71
  25. package/bin/lib/tui/index.tsx +37 -39
  26. package/bin/lib/tui/services/AIService.ts +518 -462
  27. package/bin/lib/tui/services/ExtensionService.ts +140 -129
  28. package/bin/lib/tui/services/GeminiService.ts +367 -337
  29. package/bin/lib/tui/services/ServiceManager.ts +344 -322
  30. package/bin/lib/tui/services/SocketService.ts +168 -168
  31. package/bin/lib/tui/services/ViteService.ts +88 -88
  32. package/bin/lib/tui/services/index.ts +47 -22
  33. package/bin/lib/utils/ai-scaffold.js +291 -280
  34. package/bin/lib/utils/extract-config.js +157 -140
  35. package/bin/lib/utils/files.js +82 -86
  36. package/bin/lib/utils/index.js +7 -7
  37. package/bin/lib/utils/paths.js +34 -34
  38. package/bin/lib/utils/prompts.js +194 -169
  39. package/bin/lib/utils/ssl.js +79 -81
  40. package/browser-extensions/README.md +0 -1
  41. package/browser-extensions/chrome/background.js +244 -237
  42. package/browser-extensions/chrome/content.js +32 -29
  43. package/browser-extensions/chrome/devtools.html +7 -7
  44. package/browser-extensions/chrome/devtools.js +19 -19
  45. package/browser-extensions/chrome/inspector.js +802 -767
  46. package/browser-extensions/chrome/manifest.json +71 -63
  47. package/browser-extensions/chrome/panel.html +674 -636
  48. package/browser-extensions/chrome/panel.js +722 -712
  49. package/browser-extensions/chrome/popup.html +586 -543
  50. package/browser-extensions/chrome/popup.js +282 -244
  51. package/browser-extensions/chrome/rules.json +1 -1
  52. package/browser-extensions/chrome/test-chrome.html +216 -136
  53. package/browser-extensions/chrome/test-mixed-content.html +284 -189
  54. package/browser-extensions/chrome/test-uri-pattern.html +221 -198
  55. package/browser-extensions/firefox/README.md +9 -6
  56. package/browser-extensions/firefox/background.js +221 -218
  57. package/browser-extensions/firefox/content.js +55 -52
  58. package/browser-extensions/firefox/debug-errors.html +386 -228
  59. package/browser-extensions/firefox/debug-https.html +153 -105
  60. package/browser-extensions/firefox/devtools.html +7 -7
  61. package/browser-extensions/firefox/devtools.js +23 -20
  62. package/browser-extensions/firefox/inspector.js +802 -767
  63. package/browser-extensions/firefox/manifest.json +68 -68
  64. package/browser-extensions/firefox/panel.html +674 -636
  65. package/browser-extensions/firefox/panel.js +722 -712
  66. package/browser-extensions/firefox/popup.html +572 -535
  67. package/browser-extensions/firefox/popup.js +281 -236
  68. package/browser-extensions/firefox/test-gramercy.html +170 -125
  69. package/browser-extensions/firefox/test-imports.html +59 -55
  70. package/browser-extensions/firefox/test-masking.html +231 -140
  71. package/browser-extensions/firefox/test-uri-pattern.html +221 -198
  72. package/dist/tui/App.d.ts +1 -1
  73. package/dist/tui/App.d.ts.map +1 -1
  74. package/dist/tui/App.js +154 -150
  75. package/dist/tui/App.js.map +1 -1
  76. package/dist/tui/components/AIPanel.d.ts.map +1 -1
  77. package/dist/tui/components/AIPanel.js +42 -35
  78. package/dist/tui/components/AIPanel.js.map +1 -1
  79. package/dist/tui/components/CommandInput.d.ts +1 -1
  80. package/dist/tui/components/CommandInput.d.ts.map +1 -1
  81. package/dist/tui/components/CommandInput.js +92 -62
  82. package/dist/tui/components/CommandInput.js.map +1 -1
  83. package/dist/tui/components/GeminiPanel.d.ts.map +1 -1
  84. package/dist/tui/components/GeminiPanel.js +37 -30
  85. package/dist/tui/components/GeminiPanel.js.map +1 -1
  86. package/dist/tui/components/Header.d.ts.map +1 -1
  87. package/dist/tui/components/Header.js +1 -1
  88. package/dist/tui/components/Header.js.map +1 -1
  89. package/dist/tui/components/LogPanel.d.ts +1 -1
  90. package/dist/tui/components/LogPanel.d.ts.map +1 -1
  91. package/dist/tui/components/LogPanel.js +26 -24
  92. package/dist/tui/components/LogPanel.js.map +1 -1
  93. package/dist/tui/components/TabBar.d.ts +2 -2
  94. package/dist/tui/components/TabBar.d.ts.map +1 -1
  95. package/dist/tui/components/TabBar.js +11 -11
  96. package/dist/tui/components/TabBar.js.map +1 -1
  97. package/dist/tui/components/WelcomeScreen.d.ts.map +1 -1
  98. package/dist/tui/components/WelcomeScreen.js +6 -6
  99. package/dist/tui/components/WelcomeScreen.js.map +1 -1
  100. package/dist/tui/index.d.ts.map +1 -1
  101. package/dist/tui/index.js +8 -8
  102. package/dist/tui/index.js.map +1 -1
  103. package/dist/tui/services/AIService.d.ts +2 -2
  104. package/dist/tui/services/AIService.d.ts.map +1 -1
  105. package/dist/tui/services/AIService.js +165 -125
  106. package/dist/tui/services/AIService.js.map +1 -1
  107. package/dist/tui/services/ExtensionService.d.ts +1 -1
  108. package/dist/tui/services/ExtensionService.d.ts.map +1 -1
  109. package/dist/tui/services/ExtensionService.js +33 -26
  110. package/dist/tui/services/ExtensionService.js.map +1 -1
  111. package/dist/tui/services/GeminiService.d.ts +1 -1
  112. package/dist/tui/services/GeminiService.d.ts.map +1 -1
  113. package/dist/tui/services/GeminiService.js +87 -76
  114. package/dist/tui/services/GeminiService.js.map +1 -1
  115. package/dist/tui/services/ServiceManager.d.ts +3 -3
  116. package/dist/tui/services/ServiceManager.d.ts.map +1 -1
  117. package/dist/tui/services/ServiceManager.js +72 -58
  118. package/dist/tui/services/ServiceManager.js.map +1 -1
  119. package/dist/tui/services/SocketService.d.ts.map +1 -1
  120. package/dist/tui/services/SocketService.js +32 -32
  121. package/dist/tui/services/SocketService.js.map +1 -1
  122. package/dist/tui/services/ViteService.d.ts.map +1 -1
  123. package/dist/tui/services/ViteService.js +26 -28
  124. package/dist/tui/services/ViteService.js.map +1 -1
  125. package/dist/tui/services/index.d.ts +6 -6
  126. package/dist/tui/services/index.d.ts.map +1 -1
  127. package/dist/tui/services/index.js +6 -6
  128. package/dist/tui/services/index.js.map +1 -1
  129. package/mcp/gxp-api-server.js +83 -81
  130. package/package.json +109 -93
  131. package/runtime/PortalContainer.vue +258 -234
  132. package/runtime/dev-tools/DevToolsModal.vue +153 -155
  133. package/runtime/dev-tools/LayoutSwitcher.vue +144 -140
  134. package/runtime/dev-tools/MockDataEditor.vue +456 -433
  135. package/runtime/dev-tools/SocketSimulator.vue +379 -371
  136. package/runtime/dev-tools/StoreInspector.vue +517 -455
  137. package/runtime/dev-tools/index.js +5 -5
  138. package/runtime/fallback-layouts/PrivateLayout.vue +2 -2
  139. package/runtime/fallback-layouts/PublicLayout.vue +2 -2
  140. package/runtime/fallback-layouts/SystemLayout.vue +2 -2
  141. package/runtime/gxpStringsPlugin.js +159 -134
  142. package/runtime/index.html +17 -19
  143. package/runtime/main.js +24 -22
  144. package/runtime/mock-api/auth-middleware.js +15 -15
  145. package/runtime/mock-api/image-generator.js +46 -46
  146. package/runtime/mock-api/index.js +55 -55
  147. package/runtime/mock-api/response-generator.js +116 -105
  148. package/runtime/mock-api/route-generator.js +107 -84
  149. package/runtime/mock-api/socket-triggers.js +94 -93
  150. package/runtime/mock-api/spec-loader.js +79 -80
  151. package/runtime/package.json +3 -0
  152. package/runtime/server.js +68 -68
  153. package/runtime/stores/gxpPortalConfigStore.js +204 -186
  154. package/runtime/stores/index.js +2 -2
  155. package/runtime/vite-inspector-plugin.js +858 -707
  156. package/runtime/vite-source-tracker-plugin.js +132 -113
  157. package/runtime/vite.config.js +191 -139
  158. package/scripts/launch-chrome.js +41 -41
  159. package/scripts/pack-chrome.js +38 -39
  160. package/socket-events/AiSessionMessageCreated.json +17 -17
  161. package/socket-events/SocialStreamPostCreated.json +23 -23
  162. package/socket-events/SocialStreamPostVariantCompleted.json +22 -22
  163. package/template/.claude/agents/gxp-developer.md +100 -99
  164. package/template/.claude/settings.json +7 -7
  165. package/template/AGENTS.md +30 -23
  166. package/template/GEMINI.md +20 -20
  167. package/template/README.md +70 -53
  168. package/template/app-manifest.json +2 -4
  169. package/template/configuration.json +10 -10
  170. package/template/default-styling.css +1 -1
  171. package/template/index.html +18 -20
  172. package/template/main.js +24 -22
  173. package/template/src/DemoPage.vue +415 -362
  174. package/template/src/Plugin.vue +76 -85
  175. package/template/src/stores/index.js +3 -3
  176. package/template/src/stores/test-data.json +164 -172
  177. package/template/theme-layouts/AdditionalStyling.css +50 -50
  178. package/template/theme-layouts/PrivateLayout.vue +8 -12
  179. package/template/theme-layouts/PublicLayout.vue +8 -12
  180. package/template/theme-layouts/SystemLayout.vue +8 -12
  181. package/template/vite.extend.js +45 -0
  182. package/template/vite.config.js +0 -409
@@ -25,17 +25,17 @@ let config = {
25
25
  maskingMode: false,
26
26
  clearCacheOnEnable: true,
27
27
  disableCacheForRedirects: true,
28
- };
28
+ }
29
29
 
30
- let notificationTimeouts = new Map();
31
- let cacheBlacklist = new Set();
30
+ let notificationTimeouts = new Map()
31
+ let cacheBlacklist = new Set()
32
32
 
33
33
  // Initialize extension
34
- browser.runtime.onStartup.addListener(initializeExtension);
35
- browser.runtime.onInstalled.addListener(initializeExtension);
34
+ browser.runtime.onStartup.addListener(initializeExtension)
35
+ browser.runtime.onInstalled.addListener(initializeExtension)
36
36
 
37
37
  async function initializeExtension() {
38
- console.log("[JavaScript Proxy] Initializing extension...");
38
+ console.log("[JavaScript Proxy] Initializing extension...")
39
39
  try {
40
40
  // Load saved configuration
41
41
  const defaultConfig = {
@@ -66,22 +66,22 @@ async function initializeExtension() {
66
66
  maskingMode: false,
67
67
  clearCacheOnEnable: true,
68
68
  disableCacheForRedirects: true,
69
- };
69
+ }
70
70
 
71
- const result = await browser.storage.sync.get(defaultConfig);
72
- config = result;
71
+ const result = await browser.storage.sync.get(defaultConfig)
72
+ config = result
73
73
 
74
74
  // Migrate legacy configuration to new rules format
75
- config = migrateConfig(config);
75
+ config = migrateConfig(config)
76
76
 
77
- console.log("[JavaScript Proxy] Loaded configuration:", config);
77
+ console.log("[JavaScript Proxy] Loaded configuration:", config)
78
78
 
79
- updateIcon();
80
- updateRequestListener();
79
+ updateIcon()
80
+ updateRequestListener()
81
81
 
82
- console.log("[JavaScript Proxy] Extension initialized successfully");
82
+ console.log("[JavaScript Proxy] Extension initialized successfully")
83
83
  } catch (error) {
84
- console.error("[JavaScript Proxy] Failed to initialize:", error);
84
+ console.error("[JavaScript Proxy] Failed to initialize:", error)
85
85
  }
86
86
  }
87
87
 
@@ -107,7 +107,7 @@ function migrateConfig(config) {
107
107
  returnBlank: true,
108
108
  useCustomPattern: false,
109
109
  },
110
- };
110
+ }
111
111
  } else {
112
112
  // Ensure all required fields exist
113
113
  if (!config.rules.js) {
@@ -119,7 +119,7 @@ function migrateConfig(config) {
119
119
  redirectUrl:
120
120
  config.redirectUrl || "https://localhost:3060/src/Plugin.vue",
121
121
  useCustomPattern: config.useCustomPattern || false,
122
- };
122
+ }
123
123
  }
124
124
  if (!config.rules.css) {
125
125
  config.rules.css = {
@@ -129,16 +129,16 @@ function migrateConfig(config) {
129
129
  redirectUrl: "",
130
130
  returnBlank: true,
131
131
  useCustomPattern: false,
132
- };
132
+ }
133
133
  }
134
134
  }
135
135
 
136
- return config;
136
+ return config
137
137
  }
138
138
 
139
139
  // Update toolbar icon based on state
140
140
  function updateIcon() {
141
- const iconPath = config.enabled ? "icons/gx_on" : "icons/gx_off";
141
+ const iconPath = config.enabled ? "icons/gx_on" : "icons/gx_off"
142
142
  browser.browserAction.setIcon({
143
143
  path: {
144
144
  16: `${iconPath}_16.png`,
@@ -146,59 +146,59 @@ function updateIcon() {
146
146
  48: `${iconPath}_48.png`,
147
147
  128: `${iconPath}_128.png`,
148
148
  },
149
- });
149
+ })
150
150
 
151
151
  const title = config.enabled
152
152
  ? "JavaScript Proxy (ON)"
153
- : "JavaScript Proxy (OFF)";
154
- browser.browserAction.setTitle({ title });
153
+ : "JavaScript Proxy (OFF)"
154
+ browser.browserAction.setTitle({ title })
155
155
  }
156
156
 
157
157
  // Cache management functions
158
158
  async function clearCacheForPattern(urlPattern = null) {
159
159
  try {
160
160
  // Collect all patterns that need cache clearing
161
- const patterns = [];
161
+ const patterns = []
162
162
 
163
163
  if (urlPattern) {
164
- patterns.push(urlPattern);
164
+ patterns.push(urlPattern)
165
165
  } else {
166
166
  // Clear cache for all enabled rules
167
167
  for (const [ruleType, rule] of Object.entries(config.rules || {})) {
168
168
  if (rule.enabled && rule.pattern) {
169
- patterns.push(rule.pattern);
169
+ patterns.push(rule.pattern)
170
170
  }
171
171
  }
172
172
 
173
173
  // Include legacy pattern if exists
174
174
  if (config.urlPattern) {
175
- patterns.push(config.urlPattern);
175
+ patterns.push(config.urlPattern)
176
176
  }
177
177
  }
178
178
 
179
- console.log(`[JavaScript Proxy] Clearing cache for patterns:`, patterns);
179
+ console.log(`[JavaScript Proxy] Clearing cache for patterns:`, patterns)
180
180
 
181
181
  // Clear browser cache
182
182
  await browser.browsingData.removeCache({
183
183
  origins: [], // Empty array means all origins
184
184
  since: 0, // Clear all cache entries
185
- });
185
+ })
186
186
 
187
187
  // Clear service worker caches for each pattern
188
188
  for (const pattern of patterns) {
189
- await clearServiceWorkerCaches(pattern);
189
+ await clearServiceWorkerCaches(pattern)
190
190
  }
191
191
 
192
- console.log("[JavaScript Proxy] Cache cleared successfully");
192
+ console.log("[JavaScript Proxy] Cache cleared successfully")
193
193
  } catch (error) {
194
- console.error("[JavaScript Proxy] Error clearing cache:", error);
194
+ console.error("[JavaScript Proxy] Error clearing cache:", error)
195
195
  }
196
196
  }
197
197
 
198
198
  async function clearServiceWorkerCaches(urlPattern) {
199
199
  try {
200
200
  // Get all active tabs
201
- const tabs = await browser.tabs.query({});
201
+ const tabs = await browser.tabs.query({})
202
202
 
203
203
  // Script to clear service worker caches for matching URLs
204
204
  const clearCacheScript = `
@@ -232,7 +232,7 @@ async function clearServiceWorkerCaches(urlPattern) {
232
232
  console.error('[JavaScript Proxy] Error clearing service worker cache:', error);
233
233
  }
234
234
  })();
235
- `;
235
+ `
236
236
 
237
237
  // Inject the script into each tab
238
238
  for (const tab of tabs) {
@@ -244,77 +244,77 @@ async function clearServiceWorkerCaches(urlPattern) {
244
244
  ) {
245
245
  await browser.tabs.executeScript(tab.id, {
246
246
  code: clearCacheScript,
247
- });
247
+ })
248
248
  }
249
249
  } catch (error) {
250
250
  // Tab might not allow script injection, continue with others
251
251
  console.debug(
252
252
  `[JavaScript Proxy] Could not inject cache clear script into tab ${tab.id}:`,
253
- error
254
- );
253
+ error,
254
+ )
255
255
  }
256
256
  }
257
257
 
258
- console.log("[JavaScript Proxy] Service worker cache clearing attempted");
258
+ console.log("[JavaScript Proxy] Service worker cache clearing attempted")
259
259
  } catch (error) {
260
260
  console.error(
261
261
  "[JavaScript Proxy] Error clearing service worker caches:",
262
- error
263
- );
262
+ error,
263
+ )
264
264
  }
265
265
  }
266
266
 
267
267
  async function addToCacheBlacklist(url) {
268
268
  try {
269
- const urlObj = new URL(url);
270
- const origin = urlObj.origin;
271
- cacheBlacklist.add(origin);
272
- console.log(`[JavaScript Proxy] Added ${origin} to cache blacklist`);
269
+ const urlObj = new URL(url)
270
+ const origin = urlObj.origin
271
+ cacheBlacklist.add(origin)
272
+ console.log(`[JavaScript Proxy] Added ${origin} to cache blacklist`)
273
273
  } catch (error) {
274
- console.error("[JavaScript Proxy] Error adding to cache blacklist:", error);
274
+ console.error("[JavaScript Proxy] Error adding to cache blacklist:", error)
275
275
  }
276
276
  }
277
277
 
278
278
  function shouldDisableCache(url) {
279
- if (!config.disableCacheForRedirects) return false;
279
+ if (!config.disableCacheForRedirects) return false
280
280
 
281
281
  try {
282
282
  // Check against all enabled rules
283
283
  for (const [ruleType, rule] of Object.entries(config.rules || {})) {
284
284
  if (rule.enabled) {
285
285
  const pattern =
286
- rule.useCustomPattern && rule.pattern ? rule.pattern : rule.pattern;
287
- const regex = new RegExp(pattern, "i");
286
+ rule.useCustomPattern && rule.pattern ? rule.pattern : rule.pattern
287
+ const regex = new RegExp(pattern, "i")
288
288
  if (regex.test(url)) {
289
- return true;
289
+ return true
290
290
  }
291
291
  }
292
292
  }
293
293
 
294
294
  // Fallback to legacy pattern for backward compatibility
295
295
  if (config.urlPattern) {
296
- const regex = new RegExp(config.urlPattern, "i");
297
- return regex.test(url);
296
+ const regex = new RegExp(config.urlPattern, "i")
297
+ return regex.test(url)
298
298
  }
299
299
 
300
- return false;
300
+ return false
301
301
  } catch (error) {
302
302
  console.error(
303
303
  "[JavaScript Proxy] Error checking cache disable pattern:",
304
- error
305
- );
306
- return false;
304
+ error,
305
+ )
306
+ return false
307
307
  }
308
308
  }
309
309
 
310
310
  // Handle web requests
311
311
  function handleRequest(details) {
312
- if (!config.enabled) return {};
312
+ if (!config.enabled) return {}
313
313
 
314
314
  // Skip certain request types that commonly cause issues
315
- const skipTypes = ["ping", "csp_report", "beacon"];
315
+ const skipTypes = ["ping", "csp_report", "beacon"]
316
316
  if (skipTypes.includes(details.type)) {
317
- return {};
317
+ return {}
318
318
  }
319
319
 
320
320
  // Skip data URLs and blob URLs
@@ -324,78 +324,78 @@ function handleRequest(details) {
324
324
  details.url.startsWith("chrome:") ||
325
325
  details.url.startsWith("moz-extension:")
326
326
  ) {
327
- return {};
327
+ return {}
328
328
  }
329
329
 
330
330
  try {
331
331
  // Check each rule type
332
332
  for (const [ruleType, rule] of Object.entries(config.rules || {})) {
333
- if (!rule.enabled || !rule.pattern) continue;
333
+ if (!rule.enabled || !rule.pattern) continue
334
334
 
335
335
  // Check if this rule type matches the resource type
336
- if (ruleType === "js" && details.type !== "script") continue;
337
- if (ruleType === "css" && details.type !== "stylesheet") continue;
336
+ if (ruleType === "js" && details.type !== "script") continue
337
+ if (ruleType === "css" && details.type !== "stylesheet") continue
338
338
 
339
- const regex = new RegExp(rule.pattern, "i");
339
+ const regex = new RegExp(rule.pattern, "i")
340
340
 
341
341
  // Test the full URL against the pattern
342
342
  if (regex.test(details.url)) {
343
343
  // Handle blank return for CSS
344
344
  if (rule.returnBlank) {
345
345
  console.log(
346
- `[JavaScript Proxy] Returning blank for ${ruleType}: ${details.url}`
347
- );
346
+ `[JavaScript Proxy] Returning blank for ${ruleType}: ${details.url}`,
347
+ )
348
348
  // Return a data URL with empty content
349
349
  const blankUrl =
350
350
  ruleType === "css"
351
351
  ? "data:text/css;charset=utf-8,"
352
- : "data:text/javascript;charset=utf-8,";
353
- return { redirectUrl: blankUrl };
352
+ : "data:text/javascript;charset=utf-8,"
353
+ return { redirectUrl: blankUrl }
354
354
  }
355
355
 
356
356
  if (rule.redirectUrl) {
357
- let newUrl = rule.redirectUrl;
357
+ let newUrl = rule.redirectUrl
358
358
 
359
359
  // Ensure URL has protocol
360
360
  if (!newUrl.includes("://")) {
361
- newUrl = "https://" + newUrl;
361
+ newUrl = "https://" + newUrl
362
362
  }
363
363
 
364
- const requestType = getRequestTypeDescription(details.type);
364
+ const requestType = getRequestTypeDescription(details.type)
365
365
 
366
366
  // Check if this would create a redirect loop
367
367
  if (details.url === newUrl || details.url.includes("localhost")) {
368
368
  console.log(
369
- `[JavaScript Proxy] Skipping redirect loop: ${details.url}`
370
- );
371
- return {};
369
+ `[JavaScript Proxy] Skipping redirect loop: ${details.url}`,
370
+ )
371
+ return {}
372
372
  }
373
373
 
374
374
  // Check if this rule should use URL masking
375
375
  if (config.maskingMode) {
376
376
  // Store original URL for header modification
377
- storeOriginalUrl(details.requestId, details.url, newUrl);
377
+ storeOriginalUrl(details.requestId, details.url, newUrl)
378
378
 
379
379
  console.log(
380
- `[JavaScript Proxy] Masking ${ruleType}: ${details.url} (routing to ${newUrl})`
381
- );
380
+ `[JavaScript Proxy] Masking ${ruleType}: ${details.url} (routing to ${newUrl})`,
381
+ )
382
382
 
383
383
  // Don't redirect - we'll modify headers instead
384
- return {};
384
+ return {}
385
385
  } else {
386
386
  // Clear cache if enabled (for traditional redirect)
387
387
  if (config.clearCacheOnEnable) {
388
- clearCacheForPattern(rule.pattern);
388
+ clearCacheForPattern(rule.pattern)
389
389
  }
390
390
 
391
391
  // Traditional redirect approach
392
- showProxyNotification(details.url, newUrl, requestType);
392
+ showProxyNotification(details.url, newUrl, requestType)
393
393
 
394
394
  console.log(
395
- `[JavaScript Proxy] Redirecting ${ruleType}: ${details.url} → ${newUrl}`
396
- );
395
+ `[JavaScript Proxy] Redirecting ${ruleType}: ${details.url} → ${newUrl}`,
396
+ )
397
397
 
398
- return { redirectUrl: newUrl };
398
+ return { redirectUrl: newUrl }
399
399
  }
400
400
  }
401
401
  }
@@ -403,64 +403,64 @@ function handleRequest(details) {
403
403
 
404
404
  // Fallback to legacy pattern for backward compatibility
405
405
  if (config.urlPattern && details.type === "script") {
406
- const regex = new RegExp(config.urlPattern, "i");
406
+ const regex = new RegExp(config.urlPattern, "i")
407
407
 
408
408
  if (regex.test(details.url)) {
409
- let newUrl = config.redirectUrl;
409
+ let newUrl = config.redirectUrl
410
410
 
411
411
  if (!newUrl.includes("://")) {
412
- newUrl = "https://" + newUrl;
412
+ newUrl = "https://" + newUrl
413
413
  }
414
414
 
415
- const requestType = getRequestTypeDescription(details.type);
415
+ const requestType = getRequestTypeDescription(details.type)
416
416
 
417
417
  if (details.url === newUrl || details.url.includes("localhost")) {
418
418
  console.log(
419
- `[JavaScript Proxy] Skipping redirect loop: ${details.url}`
420
- );
421
- return {};
419
+ `[JavaScript Proxy] Skipping redirect loop: ${details.url}`,
420
+ )
421
+ return {}
422
422
  }
423
423
 
424
424
  if (config.maskingMode) {
425
- storeOriginalUrl(details.requestId, details.url, newUrl);
425
+ storeOriginalUrl(details.requestId, details.url, newUrl)
426
426
  console.log(
427
- `[JavaScript Proxy] Legacy masking: ${details.url} (routing to ${newUrl})`
428
- );
429
- return {};
427
+ `[JavaScript Proxy] Legacy masking: ${details.url} (routing to ${newUrl})`,
428
+ )
429
+ return {}
430
430
  } else {
431
431
  if (config.clearCacheOnEnable) {
432
- clearCacheForPattern(config.urlPattern);
432
+ clearCacheForPattern(config.urlPattern)
433
433
  }
434
434
 
435
- showProxyNotification(details.url, newUrl, requestType);
435
+ showProxyNotification(details.url, newUrl, requestType)
436
436
  console.log(
437
- `[JavaScript Proxy] Legacy redirecting: ${details.url} → ${newUrl}`
438
- );
439
- return { redirectUrl: newUrl };
437
+ `[JavaScript Proxy] Legacy redirecting: ${details.url} → ${newUrl}`,
438
+ )
439
+ return { redirectUrl: newUrl }
440
440
  }
441
441
  }
442
442
  }
443
443
  } catch (error) {
444
- console.error("[JavaScript Proxy] Error processing request:", error);
444
+ console.error("[JavaScript Proxy] Error processing request:", error)
445
445
  }
446
446
 
447
- return {};
447
+ return {}
448
448
  }
449
449
 
450
450
  // Store mapping of request IDs to proxy info for header modification
451
- const pendingProxyRequests = new Map();
451
+ const pendingProxyRequests = new Map()
452
452
 
453
453
  function storeOriginalUrl(requestId, originalUrl, redirectUrl) {
454
454
  pendingProxyRequests.set(requestId, {
455
455
  originalUrl,
456
456
  redirectUrl,
457
457
  timestamp: Date.now(),
458
- });
458
+ })
459
459
 
460
460
  // Clean up old entries after 30 seconds
461
461
  setTimeout(() => {
462
- pendingProxyRequests.delete(requestId);
463
- }, 30000);
462
+ pendingProxyRequests.delete(requestId)
463
+ }, 30000)
464
464
  }
465
465
 
466
466
  // Get human-readable description of request type
@@ -479,61 +479,61 @@ function getRequestTypeDescription(type) {
479
479
  media: "Media",
480
480
  websocket: "WebSocket",
481
481
  other: "Other",
482
- };
483
- return typeMap[type] || type;
482
+ }
483
+ return typeMap[type] || type
484
484
  }
485
485
 
486
486
  // Show desktop notification for proxy activity
487
487
  function showProxyNotification(from, to, requestType = "") {
488
- const shortFrom = from.length > 50 ? from.substring(0, 47) + "..." : from;
489
- const shortTo = to.length > 30 ? to.substring(0, 27) + "..." : to;
488
+ const shortFrom = from.length > 50 ? from.substring(0, 47) + "..." : from
489
+ const shortTo = to.length > 30 ? to.substring(0, 27) + "..." : to
490
490
 
491
- const notificationId = `proxy-${Date.now()}`;
491
+ const notificationId = `proxy-${Date.now()}`
492
492
 
493
493
  browser.notifications.create(notificationId, {
494
494
  type: "basic",
495
495
  iconUrl: "icons/gx_on_48.png",
496
496
  title: "JavaScript Proxy Active",
497
497
  message: `${requestType}\n${shortFrom}\n→ ${shortTo}`,
498
- });
498
+ })
499
499
 
500
500
  // Clear existing timeout for this type
501
501
  if (notificationTimeouts.has("proxy")) {
502
- clearTimeout(notificationTimeouts.get("proxy"));
502
+ clearTimeout(notificationTimeouts.get("proxy"))
503
503
  }
504
504
 
505
505
  // Auto-dismiss after 3 seconds
506
506
  const timeoutId = setTimeout(() => {
507
- browser.notifications.clear(notificationId);
508
- notificationTimeouts.delete("proxy");
509
- }, 3000);
507
+ browser.notifications.clear(notificationId)
508
+ notificationTimeouts.delete("proxy")
509
+ }, 3000)
510
510
 
511
- notificationTimeouts.set("proxy", timeoutId);
511
+ notificationTimeouts.set("proxy", timeoutId)
512
512
  }
513
513
 
514
514
  // Handle request headers for masking mode and cache control
515
515
  function handleRequestHeaders(details) {
516
- if (!config.enabled) return {};
516
+ if (!config.enabled) return {}
517
517
 
518
518
  // Initialize modifications
519
- const modifications = { requestHeaders: details.requestHeaders };
520
- let hasModifications = false;
519
+ const modifications = { requestHeaders: details.requestHeaders }
520
+ let hasModifications = false
521
521
 
522
522
  // Handle masking mode
523
523
  if (config.maskingMode) {
524
- const proxyInfo = pendingProxyRequests.get(details.requestId);
524
+ const proxyInfo = pendingProxyRequests.get(details.requestId)
525
525
  if (proxyInfo) {
526
526
  // Add/modify headers to properly route to localhost
527
527
  const hostHeader = modifications.requestHeaders.find(
528
- (h) => h.name.toLowerCase() === "host"
529
- );
528
+ (h) => h.name.toLowerCase() === "host",
529
+ )
530
530
  if (hostHeader) {
531
531
  try {
532
- const proxyUrl = new URL(proxyInfo.redirectUrl);
533
- hostHeader.value = proxyUrl.host;
534
- hasModifications = true;
532
+ const proxyUrl = new URL(proxyInfo.redirectUrl)
533
+ hostHeader.value = proxyUrl.host
534
+ hasModifications = true
535
535
  } catch (error) {
536
- console.error("[JavaScript Proxy] Error parsing proxy URL:", error);
536
+ console.error("[JavaScript Proxy] Error parsing proxy URL:", error)
537
537
  }
538
538
  }
539
539
  }
@@ -546,39 +546,39 @@ function handleRequestHeaders(details) {
546
546
  { name: "Cache-Control", value: "no-cache, no-store, must-revalidate" },
547
547
  { name: "Pragma", value: "no-cache" },
548
548
  { name: "Expires", value: "0" },
549
- ];
549
+ ]
550
550
 
551
551
  cacheHeaders.forEach((cacheHeader) => {
552
552
  const existingHeader = modifications.requestHeaders.find(
553
- (h) => h.name.toLowerCase() === cacheHeader.name.toLowerCase()
554
- );
553
+ (h) => h.name.toLowerCase() === cacheHeader.name.toLowerCase(),
554
+ )
555
555
  if (existingHeader) {
556
- existingHeader.value = cacheHeader.value;
556
+ existingHeader.value = cacheHeader.value
557
557
  } else {
558
- modifications.requestHeaders.push(cacheHeader);
558
+ modifications.requestHeaders.push(cacheHeader)
559
559
  }
560
- hasModifications = true;
561
- });
560
+ hasModifications = true
561
+ })
562
562
 
563
563
  console.log(
564
- `[JavaScript Proxy] Added cache-busting headers for: ${details.url}`
565
- );
564
+ `[JavaScript Proxy] Added cache-busting headers for: ${details.url}`,
565
+ )
566
566
  }
567
567
 
568
- return hasModifications ? modifications : {};
568
+ return hasModifications ? modifications : {}
569
569
  }
570
570
 
571
571
  // Handle response headers for masking mode and cache control
572
572
  function handleResponseHeaders(details) {
573
- if (!config.enabled) return {};
573
+ if (!config.enabled) return {}
574
574
 
575
575
  // Initialize modifications
576
- const modifications = { responseHeaders: details.responseHeaders };
577
- let hasModifications = false;
576
+ const modifications = { responseHeaders: details.responseHeaders }
577
+ let hasModifications = false
578
578
 
579
579
  // Handle masking mode
580
580
  if (config.maskingMode) {
581
- const proxyInfo = pendingProxyRequests.get(details.requestId);
581
+ const proxyInfo = pendingProxyRequests.get(details.requestId)
582
582
  if (proxyInfo) {
583
583
  // Add CORS headers if needed
584
584
  const corsHeaders = [
@@ -591,19 +591,19 @@ function handleResponseHeaders(details) {
591
591
  name: "Access-Control-Allow-Headers",
592
592
  value: "Content-Type, Authorization",
593
593
  },
594
- ];
594
+ ]
595
595
 
596
596
  corsHeaders.forEach((corsHeader) => {
597
597
  const existingHeader = modifications.responseHeaders.find(
598
- (h) => h.name.toLowerCase() === corsHeader.name.toLowerCase()
599
- );
598
+ (h) => h.name.toLowerCase() === corsHeader.name.toLowerCase(),
599
+ )
600
600
  if (existingHeader) {
601
- existingHeader.value = corsHeader.value;
601
+ existingHeader.value = corsHeader.value
602
602
  } else {
603
- modifications.responseHeaders.push(corsHeader);
603
+ modifications.responseHeaders.push(corsHeader)
604
604
  }
605
- hasModifications = true;
606
- });
605
+ hasModifications = true
606
+ })
607
607
  }
608
608
  }
609
609
 
@@ -616,47 +616,47 @@ function handleResponseHeaders(details) {
616
616
  { name: "Expires", value: "0" },
617
617
  { name: "Last-Modified", value: new Date().toUTCString() },
618
618
  { name: "ETag", value: `"${Date.now()}"` },
619
- ];
619
+ ]
620
620
 
621
621
  cacheHeaders.forEach((cacheHeader) => {
622
622
  const existingHeader = modifications.responseHeaders.find(
623
- (h) => h.name.toLowerCase() === cacheHeader.name.toLowerCase()
624
- );
623
+ (h) => h.name.toLowerCase() === cacheHeader.name.toLowerCase(),
624
+ )
625
625
  if (existingHeader) {
626
- existingHeader.value = cacheHeader.value;
626
+ existingHeader.value = cacheHeader.value
627
627
  } else {
628
- modifications.responseHeaders.push(cacheHeader);
628
+ modifications.responseHeaders.push(cacheHeader)
629
629
  }
630
- hasModifications = true;
631
- });
630
+ hasModifications = true
631
+ })
632
632
 
633
633
  console.log(
634
- `[JavaScript Proxy] Added response cache-busting headers for: ${details.url}`
635
- );
634
+ `[JavaScript Proxy] Added response cache-busting headers for: ${details.url}`,
635
+ )
636
636
  }
637
637
 
638
638
  if (hasModifications) {
639
639
  console.log(
640
- `[JavaScript Proxy] Modified response headers for: ${details.url}`
641
- );
640
+ `[JavaScript Proxy] Modified response headers for: ${details.url}`,
641
+ )
642
642
  }
643
643
 
644
- return hasModifications ? modifications : {};
644
+ return hasModifications ? modifications : {}
645
645
  }
646
646
 
647
647
  // Update request listener based on current state
648
648
  function updateRequestListener() {
649
649
  // Remove existing listeners
650
650
  if (browser.webRequest.onBeforeRequest.hasListener(handleRequest)) {
651
- browser.webRequest.onBeforeRequest.removeListener(handleRequest);
651
+ browser.webRequest.onBeforeRequest.removeListener(handleRequest)
652
652
  }
653
653
  if (
654
654
  browser.webRequest.onBeforeSendHeaders.hasListener(handleRequestHeaders)
655
655
  ) {
656
- browser.webRequest.onBeforeSendHeaders.removeListener(handleRequestHeaders);
656
+ browser.webRequest.onBeforeSendHeaders.removeListener(handleRequestHeaders)
657
657
  }
658
658
  if (browser.webRequest.onHeadersReceived.hasListener(handleResponseHeaders)) {
659
- browser.webRequest.onHeadersReceived.removeListener(handleResponseHeaders);
659
+ browser.webRequest.onHeadersReceived.removeListener(handleResponseHeaders)
660
660
  }
661
661
 
662
662
  if (config.enabled) {
@@ -664,27 +664,27 @@ function updateRequestListener() {
664
664
  browser.webRequest.onBeforeRequest.addListener(
665
665
  handleRequest,
666
666
  { urls: ["<all_urls>"] },
667
- ["blocking"]
668
- );
667
+ ["blocking"],
668
+ )
669
669
 
670
670
  // Add header modification listeners for masking mode OR cache control
671
671
  if (config.maskingMode || config.disableCacheForRedirects) {
672
672
  browser.webRequest.onBeforeSendHeaders.addListener(
673
673
  handleRequestHeaders,
674
674
  { urls: ["<all_urls>"] },
675
- ["blocking", "requestHeaders"]
676
- );
675
+ ["blocking", "requestHeaders"],
676
+ )
677
677
 
678
678
  browser.webRequest.onHeadersReceived.addListener(
679
679
  handleResponseHeaders,
680
680
  { urls: ["<all_urls>"] },
681
- ["blocking", "responseHeaders"]
682
- );
681
+ ["blocking", "responseHeaders"],
682
+ )
683
683
  }
684
684
 
685
- console.log("[JavaScript Proxy] Request listener enabled");
685
+ console.log("[JavaScript Proxy] Request listener enabled")
686
686
  } else {
687
- console.log("[JavaScript Proxy] Request listener disabled");
687
+ console.log("[JavaScript Proxy] Request listener disabled")
688
688
  }
689
689
  }
690
690
 
@@ -692,113 +692,116 @@ function updateRequestListener() {
692
692
  // DevTools Panel Communication
693
693
  // ============================================================
694
694
 
695
- const devtoolsConnections = new Map();
695
+ const devtoolsConnections = new Map()
696
696
 
697
697
  browser.runtime.onConnect.addListener((port) => {
698
- if (port.name === 'gxp-devtools-panel') {
698
+ if (port.name === "gxp-devtools-panel") {
699
699
  const extensionListener = (message, port) => {
700
- if (message.name === 'init') {
701
- devtoolsConnections.set(message.tabId, port);
702
- console.log('[GxP DevTools] Panel connected for tab:', message.tabId);
700
+ if (message.name === "init") {
701
+ devtoolsConnections.set(message.tabId, port)
702
+ console.log("[GxP DevTools] Panel connected for tab:", message.tabId)
703
703
  }
704
704
 
705
705
  // Forward messages to content script
706
706
  if (message.tabId && message.action) {
707
- browser.tabs.sendMessage(message.tabId, message).then((response) => {
708
- port.postMessage(response);
709
- }).catch(console.error);
707
+ browser.tabs
708
+ .sendMessage(message.tabId, message)
709
+ .then((response) => {
710
+ port.postMessage(response)
711
+ })
712
+ .catch(console.error)
710
713
  }
711
- };
714
+ }
712
715
 
713
- port.onMessage.addListener(extensionListener);
716
+ port.onMessage.addListener(extensionListener)
714
717
 
715
718
  port.onDisconnect.addListener(() => {
716
719
  // Remove the connection when panel is closed
717
720
  for (const [tabId, connectedPort] of devtoolsConnections.entries()) {
718
721
  if (connectedPort === port) {
719
- devtoolsConnections.delete(tabId);
720
- console.log('[GxP DevTools] Panel disconnected for tab:', tabId);
721
- break;
722
+ devtoolsConnections.delete(tabId)
723
+ console.log("[GxP DevTools] Panel disconnected for tab:", tabId)
724
+ break
722
725
  }
723
726
  }
724
- });
727
+ })
725
728
  }
726
- });
729
+ })
727
730
 
728
731
  // Forward messages from content script to DevTools panel
729
732
  function forwardToDevTools(tabId, message) {
730
- const port = devtoolsConnections.get(tabId);
733
+ const port = devtoolsConnections.get(tabId)
731
734
  if (port) {
732
735
  try {
733
- port.postMessage(message);
736
+ port.postMessage(message)
734
737
  } catch (error) {
735
- console.error('[GxP DevTools] Error forwarding to panel:', error);
738
+ console.error("[GxP DevTools] Error forwarding to panel:", error)
736
739
  }
737
740
  }
738
741
  }
739
742
 
740
743
  // Handle messages from popup
741
744
  browser.runtime.onMessage.addListener((request, sender, sendResponse) => {
742
- console.log("[JavaScript Proxy] Received message:", request);
745
+ console.log("[JavaScript Proxy] Received message:", request)
743
746
 
744
747
  // Handle messages from content script about element selection
745
- if (request.type === 'elementSelected' && sender.tab) {
746
- forwardToDevTools(sender.tab.id, request);
747
- return;
748
+ if (request.type === "elementSelected" && sender.tab) {
749
+ forwardToDevTools(sender.tab.id, request)
750
+ return
748
751
  }
749
752
 
750
753
  switch (request.action) {
751
754
  case "toggleProxy":
752
- config.enabled = request.enabled;
753
- browser.storage.sync.set({ enabled: config.enabled });
754
- updateIcon();
755
- updateRequestListener();
755
+ config.enabled = request.enabled
756
+ browser.storage.sync.set({ enabled: config.enabled })
757
+ updateIcon()
758
+ updateRequestListener()
756
759
  // Clear cache when enabling the proxy
757
760
  if (config.enabled && config.clearCacheOnEnable) {
758
- clearCacheForPattern(); // Clear cache for all enabled patterns
761
+ clearCacheForPattern() // Clear cache for all enabled patterns
759
762
  }
760
- sendResponse({ success: true, enabled: config.enabled });
761
- break;
763
+ sendResponse({ success: true, enabled: config.enabled })
764
+ break
762
765
 
763
766
  case "updateConfig":
764
- config = { ...config, ...request.config };
765
- browser.storage.sync.set(config);
766
- updateIcon();
767
- updateRequestListener();
768
- sendResponse({ success: true });
769
- break;
767
+ config = { ...config, ...request.config }
768
+ browser.storage.sync.set(config)
769
+ updateIcon()
770
+ updateRequestListener()
771
+ sendResponse({ success: true })
772
+ break
770
773
 
771
774
  case "getConfig":
772
- sendResponse(config);
773
- break;
775
+ sendResponse(config)
776
+ break
774
777
 
775
778
  case "clearCache":
776
779
  clearCacheForPattern() // Clear cache for all enabled patterns
777
780
  .then(() => {
778
- sendResponse({ success: true });
781
+ sendResponse({ success: true })
779
782
  })
780
783
  .catch((error) => {
781
- sendResponse({ success: false, error: error.message });
782
- });
783
- break;
784
+ sendResponse({ success: false, error: error.message })
785
+ })
786
+ break
784
787
 
785
788
  default:
786
- console.warn("[JavaScript Proxy] Unknown action:", request.action);
787
- sendResponse({ success: false, error: "Unknown action" });
789
+ console.warn("[JavaScript Proxy] Unknown action:", request.action)
790
+ sendResponse({ success: false, error: "Unknown action" })
788
791
  }
789
792
 
790
- return true; // Keep message channel open for async response
791
- });
793
+ return true // Keep message channel open for async response
794
+ })
792
795
 
793
796
  // Clear expired proxy requests periodically
794
797
  setInterval(() => {
795
- const now = Date.now();
798
+ const now = Date.now()
796
799
  for (const [requestId, info] of pendingProxyRequests.entries()) {
797
800
  if (now - info.timestamp > 30000) {
798
- pendingProxyRequests.delete(requestId);
801
+ pendingProxyRequests.delete(requestId)
799
802
  }
800
803
  }
801
- }, 10000);
804
+ }, 10000)
802
805
 
803
806
  // Initialize on startup
804
- initializeExtension();
807
+ initializeExtension()