@buoy-gg/network 7.0.41 → 7.0.42

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 (272) hide show
  1. package/README.md +11 -85
  2. package/lib/commonjs/index.js +1 -332
  3. package/lib/commonjs/index.web.js +1 -420
  4. package/lib/commonjs/network/components/DataViewer.web.js +1 -879
  5. package/lib/commonjs/network/components/NetworkCopyScreen.web.js +1 -48
  6. package/lib/commonjs/network/components/NetworkCopySettingsView.js +27 -755
  7. package/lib/commonjs/network/components/NetworkCopySettingsView.web.js +14 -1242
  8. package/lib/commonjs/network/components/NetworkDetailScreen.web.js +1 -101
  9. package/lib/commonjs/network/components/NetworkDetailStepper.js +1 -108
  10. package/lib/commonjs/network/components/NetworkDetailStepper.web.js +1 -298
  11. package/lib/commonjs/network/components/NetworkEventDetailView.js +15 -1130
  12. package/lib/commonjs/network/components/NetworkEventDetailView.web.js +15 -1484
  13. package/lib/commonjs/network/components/NetworkEventItemCompact.js +2 -401
  14. package/lib/commonjs/network/components/NetworkEventItemCompact.web.js +2 -820
  15. package/lib/commonjs/network/components/NetworkFilterScreen.web.js +1 -55
  16. package/lib/commonjs/network/components/NetworkFilterViewV3.js +1 -442
  17. package/lib/commonjs/network/components/NetworkFilterViewV3.web.js +1 -1310
  18. package/lib/commonjs/network/components/NetworkHeaderLive.js +1 -375
  19. package/lib/commonjs/network/components/NetworkHeaderLive.web.js +1 -623
  20. package/lib/commonjs/network/components/NetworkHeaderMenu.js +1 -190
  21. package/lib/commonjs/network/components/NetworkListScreen.js +1 -403
  22. package/lib/commonjs/network/components/NetworkListScreen.web.js +1 -624
  23. package/lib/commonjs/network/components/NetworkModal.js +1 -786
  24. package/lib/commonjs/network/components/NetworkNumberPrompt.js +1 -178
  25. package/lib/commonjs/network/components/NetworkNumberPrompt.web.js +1 -232
  26. package/lib/commonjs/network/components/NetworkOverrideEditor.js +1 -814
  27. package/lib/commonjs/network/components/NetworkOverrideEditor.web.js +1 -942
  28. package/lib/commonjs/network/components/NetworkOverrideHeaderButton.js +1 -107
  29. package/lib/commonjs/network/components/NetworkOverrideHeaderButton.web.js +1 -133
  30. package/lib/commonjs/network/components/NetworkOverridesButton.js +1 -90
  31. package/lib/commonjs/network/components/NetworkOverridesButton.web.js +1 -143
  32. package/lib/commonjs/network/components/NetworkOverridesScreen.js +1 -543
  33. package/lib/commonjs/network/components/NetworkOverridesScreen.web.js +1 -830
  34. package/lib/commonjs/network/components/NetworkSavedScreen.js +1 -226
  35. package/lib/commonjs/network/components/NetworkSavedScreen.web.js +1 -463
  36. package/lib/commonjs/network/components/NetworkUpgradeBanner.js +1 -76
  37. package/lib/commonjs/network/components/response-editor/Explorer.js +1 -973
  38. package/lib/commonjs/network/components/response-editor/Explorer.web.js +1 -1136
  39. package/lib/commonjs/network/components/response-editor/deleteNestedDataByPath.js +1 -56
  40. package/lib/commonjs/network/components/response-editor/editorContext.js +1 -33
  41. package/lib/commonjs/network/components/response-editor/updateNestedDataByPath.js +1 -61
  42. package/lib/commonjs/network/conditions/NetworkConditionsControl.js +1 -235
  43. package/lib/commonjs/network/conditions/NetworkConditionsControl.test.js +1 -136
  44. package/lib/commonjs/network/conditions/NetworkConditionsIcon.js +1 -33
  45. package/lib/commonjs/network/conditions/NetworkFloatingTool.js +1 -310
  46. package/lib/commonjs/network/conditions/NetworkFloatingTool.test.js +1 -219
  47. package/lib/commonjs/network/conditions/store.js +1 -75
  48. package/lib/commonjs/network/conditions/wait.js +1 -43
  49. package/lib/commonjs/network/conditions/xhr.js +1 -135
  50. package/lib/commonjs/network/hooks/useLiveNetworkEvent.js +1 -62
  51. package/lib/commonjs/network/hooks/useNetworkBadgeCounts.js +1 -83
  52. package/lib/commonjs/network/hooks/useNetworkEventList.js +1 -108
  53. package/lib/commonjs/network/hooks/useNetworkEvents.js +1 -318
  54. package/lib/commonjs/network/hooks/useNetworkHasMatches.js +1 -56
  55. package/lib/commonjs/network/hooks/useNetworkSaved.js +1 -38
  56. package/lib/commonjs/network/hooks/useNetworkSelection.js +1 -53
  57. package/lib/commonjs/network/hooks/useOverrideRules.js +1 -36
  58. package/lib/commonjs/network/hooks/useTickEveryMinute.js +1 -21
  59. package/lib/commonjs/network/overrides/applyToFetch.js +1 -80
  60. package/lib/commonjs/network/overrides/applyToXhr.js +2 -510
  61. package/lib/commonjs/network/overrides/engine.js +1 -93
  62. package/lib/commonjs/network/overrides/matchRule.js +1 -87
  63. package/lib/commonjs/network/overrides/overriddenRows.js +1 -37
  64. package/lib/commonjs/network/overrides/overrideRulesStore.js +1 -550
  65. package/lib/commonjs/network/overrides/presets.js +1 -70
  66. package/lib/commonjs/network/overrides/resolveOverride.js +1 -158
  67. package/lib/commonjs/network/overrides/types.js +1 -90
  68. package/lib/commonjs/network/sync/networkBodyResolver.js +1 -39
  69. package/lib/commonjs/network/sync/networkSyncAdapter.js +1 -882
  70. package/lib/commonjs/network/sync/overrideHonesty.release.test.js +1 -36
  71. package/lib/commonjs/network/types/index.js +1 -5
  72. package/lib/commonjs/network/utils/extractOperationName.js +1 -80
  73. package/lib/commonjs/network/utils/filterNetworkEvents.js +1 -96
  74. package/lib/commonjs/network/utils/formatGraphQLVariables.js +1 -219
  75. package/lib/commonjs/network/utils/formatting.js +1 -30
  76. package/lib/commonjs/network/utils/generateCurl.js +2 -71
  77. package/lib/commonjs/network/utils/generateNetworkCopyText.js +37 -166
  78. package/lib/commonjs/network/utils/httpCompletion.js +1 -37
  79. package/lib/commonjs/network/utils/networkEventStore.js +1 -411
  80. package/lib/commonjs/network/utils/networkListener.js +4 -1352
  81. package/lib/commonjs/network/utils/networkSavedStore.js +3 -577
  82. package/lib/commonjs/network/utils/networkSelectionStore.js +1 -193
  83. package/lib/commonjs/network/utils/realNow.js +1 -0
  84. package/lib/commonjs/network/utils/requestId.js +1 -16
  85. package/lib/commonjs/network/utils/resolveRequestUrl.js +1 -15
  86. package/lib/commonjs/network/utils/selectSavedEvents.js +1 -39
  87. package/lib/commonjs/network/utils/startNetworkCapture.js +1 -24
  88. package/lib/commonjs/network/utils/withPinnedFirst.js +1 -32
  89. package/lib/commonjs/preset.js +1 -93
  90. package/lib/module/index.js +1 -104
  91. package/lib/module/index.web.js +1 -82
  92. package/lib/module/network/components/DataViewer.web.js +1 -875
  93. package/lib/module/network/components/NetworkCopyScreen.web.js +1 -44
  94. package/lib/module/network/components/NetworkCopySettingsView.js +27 -750
  95. package/lib/module/network/components/NetworkCopySettingsView.web.js +14 -1237
  96. package/lib/module/network/components/NetworkDetailScreen.web.js +1 -97
  97. package/lib/module/network/components/NetworkDetailStepper.js +1 -104
  98. package/lib/module/network/components/NetworkDetailStepper.web.js +1 -296
  99. package/lib/module/network/components/NetworkEventDetailView.js +15 -1129
  100. package/lib/module/network/components/NetworkEventDetailView.web.js +15 -1482
  101. package/lib/module/network/components/NetworkEventItemCompact.js +2 -398
  102. package/lib/module/network/components/NetworkEventItemCompact.web.js +2 -818
  103. package/lib/module/network/components/NetworkFilterScreen.web.js +1 -51
  104. package/lib/module/network/components/NetworkFilterViewV3.js +1 -438
  105. package/lib/module/network/components/NetworkFilterViewV3.web.js +1 -1306
  106. package/lib/module/network/components/NetworkHeaderLive.js +1 -366
  107. package/lib/module/network/components/NetworkHeaderLive.web.js +1 -617
  108. package/lib/module/network/components/NetworkHeaderMenu.js +1 -184
  109. package/lib/module/network/components/NetworkListScreen.js +1 -399
  110. package/lib/module/network/components/NetworkListScreen.web.js +1 -622
  111. package/lib/module/network/components/NetworkModal.js +1 -781
  112. package/lib/module/network/components/NetworkNumberPrompt.js +1 -174
  113. package/lib/module/network/components/NetworkNumberPrompt.web.js +1 -230
  114. package/lib/module/network/components/NetworkOverrideEditor.js +1 -811
  115. package/lib/module/network/components/NetworkOverrideEditor.web.js +1 -939
  116. package/lib/module/network/components/NetworkOverrideHeaderButton.js +1 -104
  117. package/lib/module/network/components/NetworkOverrideHeaderButton.web.js +1 -131
  118. package/lib/module/network/components/NetworkOverridesButton.js +1 -87
  119. package/lib/module/network/components/NetworkOverridesButton.web.js +1 -141
  120. package/lib/module/network/components/NetworkOverridesScreen.js +1 -539
  121. package/lib/module/network/components/NetworkOverridesScreen.web.js +1 -826
  122. package/lib/module/network/components/NetworkSavedScreen.js +1 -222
  123. package/lib/module/network/components/NetworkSavedScreen.web.js +1 -461
  124. package/lib/module/network/components/NetworkUpgradeBanner.js +1 -72
  125. package/lib/module/network/components/response-editor/Explorer.js +1 -972
  126. package/lib/module/network/components/response-editor/Explorer.web.js +1 -1133
  127. package/lib/module/network/components/response-editor/deleteNestedDataByPath.js +1 -51
  128. package/lib/module/network/components/response-editor/editorContext.js +1 -29
  129. package/lib/module/network/components/response-editor/updateNestedDataByPath.js +1 -56
  130. package/lib/module/network/conditions/NetworkConditionsControl.js +1 -231
  131. package/lib/module/network/conditions/NetworkConditionsControl.test.js +1 -135
  132. package/lib/module/network/conditions/NetworkConditionsIcon.js +1 -29
  133. package/lib/module/network/conditions/NetworkFloatingTool.js +1 -304
  134. package/lib/module/network/conditions/NetworkFloatingTool.test.js +1 -218
  135. package/lib/module/network/conditions/store.js +1 -65
  136. package/lib/module/network/conditions/wait.js +1 -38
  137. package/lib/module/network/conditions/xhr.js +1 -131
  138. package/lib/module/network/hooks/useLiveNetworkEvent.js +1 -58
  139. package/lib/module/network/hooks/useNetworkBadgeCounts.js +1 -79
  140. package/lib/module/network/hooks/useNetworkEventList.js +1 -104
  141. package/lib/module/network/hooks/useNetworkEvents.js +1 -314
  142. package/lib/module/network/hooks/useNetworkHasMatches.js +1 -52
  143. package/lib/module/network/hooks/useNetworkSaved.js +1 -34
  144. package/lib/module/network/hooks/useNetworkSelection.js +1 -46
  145. package/lib/module/network/hooks/useOverrideRules.js +1 -32
  146. package/lib/module/network/hooks/useTickEveryMinute.js +1 -11
  147. package/lib/module/network/overrides/applyToFetch.js +1 -72
  148. package/lib/module/network/overrides/applyToXhr.js +2 -502
  149. package/lib/module/network/overrides/engine.js +1 -85
  150. package/lib/module/network/overrides/matchRule.js +1 -81
  151. package/lib/module/network/overrides/overriddenRows.js +1 -33
  152. package/lib/module/network/overrides/overrideRulesStore.js +1 -547
  153. package/lib/module/network/overrides/presets.js +1 -65
  154. package/lib/module/network/overrides/resolveOverride.js +1 -152
  155. package/lib/module/network/overrides/types.js +1 -86
  156. package/lib/module/network/sync/networkBodyResolver.js +1 -34
  157. package/lib/module/network/sync/networkSyncAdapter.js +1 -880
  158. package/lib/module/network/sync/overrideHonesty.release.test.js +1 -35
  159. package/lib/module/network/types/index.js +1 -3
  160. package/lib/module/network/utils/extractOperationName.js +1 -76
  161. package/lib/module/network/utils/filterNetworkEvents.js +1 -92
  162. package/lib/module/network/utils/formatGraphQLVariables.js +1 -213
  163. package/lib/module/network/utils/formatting.js +1 -9
  164. package/lib/module/network/utils/generateCurl.js +2 -67
  165. package/lib/module/network/utils/generateNetworkCopyText.js +37 -162
  166. package/lib/module/network/utils/httpCompletion.js +1 -32
  167. package/lib/module/network/utils/networkEventStore.js +1 -409
  168. package/lib/module/network/utils/networkListener.js +4 -1341
  169. package/lib/module/network/utils/networkSavedStore.js +3 -572
  170. package/lib/module/network/utils/networkSelectionStore.js +1 -188
  171. package/lib/module/network/utils/realNow.js +1 -0
  172. package/lib/module/network/utils/requestId.js +1 -12
  173. package/lib/module/network/utils/resolveRequestUrl.js +1 -11
  174. package/lib/module/network/utils/selectSavedEvents.js +1 -35
  175. package/lib/module/network/utils/startNetworkCapture.js +1 -21
  176. package/lib/module/network/utils/withPinnedFirst.js +1 -28
  177. package/lib/module/preset.js +1 -91
  178. package/lib/typescript/network/overrides/engine.d.ts +1 -1
  179. package/lib/typescript/network/overrides/matchRule.d.ts +1 -1
  180. package/lib/typescript/network/overrides/resolveOverride.d.ts +2 -2
  181. package/lib/typescript/network/overrides/types.d.ts +9 -0
  182. package/lib/typescript/network/utils/networkListener.d.ts +11 -0
  183. package/lib/typescript/network/utils/realNow.d.ts +18 -0
  184. package/lib/web/index.mjs +73 -74
  185. package/package.json +2 -2
  186. package/lib/typescript/index.d.ts.map +0 -1
  187. package/lib/typescript/index.web.d.ts.map +0 -1
  188. package/lib/typescript/network/components/DataViewer.web.d.ts.map +0 -1
  189. package/lib/typescript/network/components/NetworkCopyScreen.web.d.ts.map +0 -1
  190. package/lib/typescript/network/components/NetworkCopySettingsView.d.ts.map +0 -1
  191. package/lib/typescript/network/components/NetworkCopySettingsView.web.d.ts.map +0 -1
  192. package/lib/typescript/network/components/NetworkDetailScreen.web.d.ts.map +0 -1
  193. package/lib/typescript/network/components/NetworkDetailStepper.d.ts.map +0 -1
  194. package/lib/typescript/network/components/NetworkDetailStepper.web.d.ts.map +0 -1
  195. package/lib/typescript/network/components/NetworkEventDetailView.d.ts.map +0 -1
  196. package/lib/typescript/network/components/NetworkEventDetailView.web.d.ts.map +0 -1
  197. package/lib/typescript/network/components/NetworkEventItemCompact.d.ts.map +0 -1
  198. package/lib/typescript/network/components/NetworkEventItemCompact.web.d.ts.map +0 -1
  199. package/lib/typescript/network/components/NetworkFilterScreen.web.d.ts.map +0 -1
  200. package/lib/typescript/network/components/NetworkFilterViewV3.d.ts.map +0 -1
  201. package/lib/typescript/network/components/NetworkFilterViewV3.web.d.ts.map +0 -1
  202. package/lib/typescript/network/components/NetworkHeaderLive.d.ts.map +0 -1
  203. package/lib/typescript/network/components/NetworkHeaderLive.web.d.ts.map +0 -1
  204. package/lib/typescript/network/components/NetworkHeaderMenu.d.ts.map +0 -1
  205. package/lib/typescript/network/components/NetworkListScreen.d.ts.map +0 -1
  206. package/lib/typescript/network/components/NetworkListScreen.web.d.ts.map +0 -1
  207. package/lib/typescript/network/components/NetworkModal.d.ts.map +0 -1
  208. package/lib/typescript/network/components/NetworkNumberPrompt.d.ts.map +0 -1
  209. package/lib/typescript/network/components/NetworkNumberPrompt.web.d.ts.map +0 -1
  210. package/lib/typescript/network/components/NetworkOverrideEditor.d.ts.map +0 -1
  211. package/lib/typescript/network/components/NetworkOverrideEditor.web.d.ts.map +0 -1
  212. package/lib/typescript/network/components/NetworkOverrideHeaderButton.d.ts.map +0 -1
  213. package/lib/typescript/network/components/NetworkOverrideHeaderButton.web.d.ts.map +0 -1
  214. package/lib/typescript/network/components/NetworkOverridesButton.d.ts.map +0 -1
  215. package/lib/typescript/network/components/NetworkOverridesButton.web.d.ts.map +0 -1
  216. package/lib/typescript/network/components/NetworkOverridesScreen.d.ts.map +0 -1
  217. package/lib/typescript/network/components/NetworkOverridesScreen.web.d.ts.map +0 -1
  218. package/lib/typescript/network/components/NetworkSavedScreen.d.ts.map +0 -1
  219. package/lib/typescript/network/components/NetworkSavedScreen.web.d.ts.map +0 -1
  220. package/lib/typescript/network/components/NetworkUpgradeBanner.d.ts.map +0 -1
  221. package/lib/typescript/network/components/response-editor/Explorer.d.ts.map +0 -1
  222. package/lib/typescript/network/components/response-editor/Explorer.web.d.ts.map +0 -1
  223. package/lib/typescript/network/components/response-editor/deleteNestedDataByPath.d.ts.map +0 -1
  224. package/lib/typescript/network/components/response-editor/editorContext.d.ts.map +0 -1
  225. package/lib/typescript/network/components/response-editor/updateNestedDataByPath.d.ts.map +0 -1
  226. package/lib/typescript/network/conditions/NetworkConditionsControl.d.ts.map +0 -1
  227. package/lib/typescript/network/conditions/NetworkConditionsControl.test.d.ts.map +0 -1
  228. package/lib/typescript/network/conditions/NetworkConditionsIcon.d.ts.map +0 -1
  229. package/lib/typescript/network/conditions/NetworkFloatingTool.d.ts.map +0 -1
  230. package/lib/typescript/network/conditions/NetworkFloatingTool.test.d.ts.map +0 -1
  231. package/lib/typescript/network/conditions/store.d.ts.map +0 -1
  232. package/lib/typescript/network/conditions/wait.d.ts.map +0 -1
  233. package/lib/typescript/network/conditions/xhr.d.ts.map +0 -1
  234. package/lib/typescript/network/hooks/useLiveNetworkEvent.d.ts.map +0 -1
  235. package/lib/typescript/network/hooks/useNetworkBadgeCounts.d.ts.map +0 -1
  236. package/lib/typescript/network/hooks/useNetworkEventList.d.ts.map +0 -1
  237. package/lib/typescript/network/hooks/useNetworkEvents.d.ts.map +0 -1
  238. package/lib/typescript/network/hooks/useNetworkHasMatches.d.ts.map +0 -1
  239. package/lib/typescript/network/hooks/useNetworkSaved.d.ts.map +0 -1
  240. package/lib/typescript/network/hooks/useNetworkSelection.d.ts.map +0 -1
  241. package/lib/typescript/network/hooks/useOverrideRules.d.ts.map +0 -1
  242. package/lib/typescript/network/hooks/useTickEveryMinute.d.ts.map +0 -1
  243. package/lib/typescript/network/overrides/applyToFetch.d.ts.map +0 -1
  244. package/lib/typescript/network/overrides/applyToXhr.d.ts.map +0 -1
  245. package/lib/typescript/network/overrides/engine.d.ts.map +0 -1
  246. package/lib/typescript/network/overrides/matchRule.d.ts.map +0 -1
  247. package/lib/typescript/network/overrides/overriddenRows.d.ts.map +0 -1
  248. package/lib/typescript/network/overrides/overrideRulesStore.d.ts.map +0 -1
  249. package/lib/typescript/network/overrides/presets.d.ts.map +0 -1
  250. package/lib/typescript/network/overrides/resolveOverride.d.ts.map +0 -1
  251. package/lib/typescript/network/overrides/types.d.ts.map +0 -1
  252. package/lib/typescript/network/sync/networkBodyResolver.d.ts.map +0 -1
  253. package/lib/typescript/network/sync/networkSyncAdapter.d.ts.map +0 -1
  254. package/lib/typescript/network/sync/overrideHonesty.release.test.d.ts.map +0 -1
  255. package/lib/typescript/network/types/index.d.ts.map +0 -1
  256. package/lib/typescript/network/utils/extractOperationName.d.ts.map +0 -1
  257. package/lib/typescript/network/utils/filterNetworkEvents.d.ts.map +0 -1
  258. package/lib/typescript/network/utils/formatGraphQLVariables.d.ts.map +0 -1
  259. package/lib/typescript/network/utils/formatting.d.ts.map +0 -1
  260. package/lib/typescript/network/utils/generateCurl.d.ts.map +0 -1
  261. package/lib/typescript/network/utils/generateNetworkCopyText.d.ts.map +0 -1
  262. package/lib/typescript/network/utils/httpCompletion.d.ts.map +0 -1
  263. package/lib/typescript/network/utils/networkEventStore.d.ts.map +0 -1
  264. package/lib/typescript/network/utils/networkListener.d.ts.map +0 -1
  265. package/lib/typescript/network/utils/networkSavedStore.d.ts.map +0 -1
  266. package/lib/typescript/network/utils/networkSelectionStore.d.ts.map +0 -1
  267. package/lib/typescript/network/utils/requestId.d.ts.map +0 -1
  268. package/lib/typescript/network/utils/resolveRequestUrl.d.ts.map +0 -1
  269. package/lib/typescript/network/utils/selectSavedEvents.d.ts.map +0 -1
  270. package/lib/typescript/network/utils/startNetworkCapture.d.ts.map +0 -1
  271. package/lib/typescript/network/utils/withPinnedFirst.d.ts.map +0 -1
  272. package/lib/typescript/preset.d.ts.map +0 -1
@@ -1,87 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.compilePattern = compilePattern;
7
- exports.escapeRegex = escapeRegex;
8
- exports.ruleMatches = ruleMatches;
9
- /**
10
- * Glob matching for override rules — a faithful port of Chrome DevTools'.
11
- *
12
- * Ported from `NetworkPersistenceManager.ts:1051` + `StringUtilities.ts:9` in
13
- * the devtools-frontend source. Ported rather than reinvented on purpose: `*`
14
- * globs are the syntax developers already have in their fingers from Chrome's
15
- * "Override headers" `applyTo` field, and a pattern that behaves differently
16
- * here than it does in the browser would be a quiet trap.
17
- */
18
-
19
- /**
20
- * Chrome's escape set, character for character.
21
- *
22
- * `*` is deliberately ABSENT — it survives escaping so it can become `.*`
23
- * below. Everything else that means something to a regex is neutered.
24
- */
25
- const SPECIAL_CHARACTERS = "[]{}()\\.^$+|-,?";
26
-
27
- /**
28
- * Escape a glob into regex source: neutralize regex metacharacters, then
29
- * promote `*` to `.*`.
30
- *
31
- * `split`/`join` rather than `replaceAll` — same result, no reliance on how
32
- * complete a given Hermes build's ES2021 surface is.
33
- */
34
- function escapeRegex(pattern) {
35
- let result = "";
36
- for (let i = 0; i < pattern.length; i++) {
37
- const char = pattern.charAt(i);
38
- if (SPECIAL_CHARACTERS.indexOf(char) !== -1) {
39
- result += "\\";
40
- }
41
- result += char;
42
- }
43
- return result.split("*").join(".*");
44
- }
45
-
46
- /**
47
- * Compiled patterns, cached by source.
48
- *
49
- * `resolveOverride` runs on EVERY request the app makes, against every rule.
50
- * Recompiling a RegExp per request per rule is pure waste in the one place
51
- * this feature is allowed to cost nothing.
52
- */
53
- const compiled = new Map();
54
- function compilePattern(pattern) {
55
- const cached = compiled.get(pattern);
56
- if (cached) return cached;
57
- // Anchored, like Chrome's `^${...}$` — a pattern describes the whole URL, so
58
- // `pokeapi.co` matches nothing and `*pokeapi.co*` matches everything on that
59
- // host. Predictable beats clever; the rule editor writes full URLs for you.
60
- //
61
- // One exception: a pattern that starts with `/` is a PATH. Anchored to the
62
- // full URL it could never match anything (every URL starts with a scheme),
63
- // so it means "this path on any origin" — `/api/rewards` matches
64
- // `http://localhost:3002/api/rewards`, and `/api/rewards*` also its queries.
65
- const source = pattern.startsWith("/") ? `[a-zA-Z][a-zA-Z0-9+.-]*://[^/]*${escapeRegex(pattern)}` : escapeRegex(pattern);
66
- const regex = new RegExp(`^${source}$`);
67
- // Unbounded growth isn't possible in practice (patterns come from a capped
68
- // rule list), but a user editing a pattern character by character churns
69
- // entries, so keep the cache from becoming a leak.
70
- if (compiled.size > 200) compiled.clear();
71
- compiled.set(pattern, regex);
72
- return regex;
73
- }
74
-
75
- /** Does this rule apply to this request? Ignores `enabled` — callers check it. */
76
- function ruleMatches(rule, url, method) {
77
- if (rule.methods && rule.methods.length > 0) {
78
- if (!rule.methods.includes(method.toUpperCase())) return false;
79
- }
80
- try {
81
- return compilePattern(rule.urlPattern).test(url);
82
- } catch {
83
- // A pattern that can't compile matches nothing rather than throwing inside
84
- // the app's `send()`. The rule editor validates; this is the backstop.
85
- return false;
86
- }
87
- }
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.compilePattern=compilePattern;exports.escapeRegex=escapeRegex;exports.ruleMatches=ruleMatches;const SPECIAL_CHARACTERS="[]{}()\\.^$+|-,?";function escapeRegex(e){let r="";for(let s=0;s<e.length;s++){const t=e.charAt(s);if(SPECIAL_CHARACTERS.indexOf(t)!==-1){r+="\\"}r+=t}return r.split("*").join(".*")}const compiled=new Map;function compilePattern(e){const r=compiled.get(e);if(r)return r;const s=e.startsWith("/")?`[a-zA-Z][a-zA-Z0-9+.-]*://[^/]*${escapeRegex(e)}`:escapeRegex(e);const t=new RegExp(`^${s}$`);if(compiled.size>200)compiled.clear();compiled.set(e,t);return t}function hasHeader(e,r){if(!e)return false;const s=r.toLowerCase();for(const t of Object.keys(e)){if(t.toLowerCase()===s&&e[t]!==void 0&&e[t]!=="")return true}return false}function ruleMatches(e,r,s,t){if(e.methods&&e.methods.length>0){if(!e.methods.includes(s.toUpperCase()))return false}if(e.requireHeader&&!hasHeader(t,e.requireHeader))return false;try{return compilePattern(e.urlPattern).test(r)}catch{return false}}
@@ -1,37 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.overriddenEvents = overriddenEvents;
7
- var _matchRule = require("./matchRule");
8
- /**
9
- * Which captured requests belong in the list's OVERRIDDEN strip.
10
- *
11
- * A row belongs there when an active rule actually changed it (it carries the
12
- * rule's override mark) or matched it after the rule existed (while overrides
13
- * are paused those pass through, and the strip is how you find the rule again).
14
- * Before a rule existed nothing overrode anything, so older matching requests
15
- * are real server responses and stay in the list, with one exception: the
16
- * newest of them, which is the request the rule was built from. That one hoists
17
- * right away, so creating a rule shows where it points without waiting for the
18
- * endpoint to be called again.
19
- */
20
- function overriddenEvents(events, activeRules) {
21
- if (activeRules.length === 0) return [];
22
- const activeIds = new Set(activeRules.map(rule => rule.id));
23
- const picked = new Set();
24
- for (const rule of activeRules) {
25
- let source;
26
- for (const event of events) {
27
- if (event.override && activeIds.has(event.override.ruleId)) {
28
- picked.add(event.id);
29
- continue;
30
- }
31
- if (!(0, _matchRule.ruleMatches)(rule, event.url, String(event.method || "GET"))) continue;
32
- if (event.timestamp >= rule.createdAt) picked.add(event.id);else if (!source || event.timestamp > source.timestamp) source = event;
33
- }
34
- if (source) picked.add(source.id);
35
- }
36
- return events.filter(event => picked.has(event.id));
37
- }
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.overriddenEvents=overriddenEvents;var _matchRule=require("./matchRule");function overriddenEvents(n,d){if(d.length===0)return[];const o=new Set(d.map(t=>t.id));const i=new Set;for(const t of d){let r;for(const e of n){if(e.override&&o.has(e.override.ruleId)){i.add(e.id);continue}if(!(0,_matchRule.ruleMatches)(t,e.url,String(e.method||"GET"),e.requestHeaders))continue;if(e.timestamp>=t.createdAt)i.add(e.id);else if(!r||e.timestamp>r.timestamp)r=e}if(r)i.add(r.id)}return n.filter(t=>i.has(t.id))}
@@ -1,550 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.overrideRulesStore = void 0;
7
- var _sharedUi = require("@buoy-gg/shared-ui");
8
- var _networkListener = require("../utils/networkListener");
9
- var _engine = require("./engine");
10
- var _resolveOverride = require("./resolveOverride");
11
- var _types = require("./types");
12
- /**
13
- * The override rule list — persisted, and the source of truth for the engine.
14
- *
15
- * Shape and persistence follow `networkSavedStore` / `ignoredPatternsStore`:
16
- * lazy hydrate on first use, a `dirty` flag so a slow read can't clobber a
17
- * mutation the user just made, and commit = set + emit + persist.
18
- *
19
- * Two things here are specific to overrides and worth reading:
20
- *
21
- * - `getRules()` is on the HOT PATH. It is called inside the app's own
22
- * `XMLHttpRequest.send()`, for every request, so it does no work: the master
23
- * switch collapses to returning a frozen empty array.
24
- *
25
- * - `syncKeepAlive()` keeps the interceptor installed while any rule is
26
- * active. Without it a rule would stop firing the moment the Network tool
27
- * closed, because the swizzle is reference-counted off capture subscribers.
28
- */
29
-
30
- /**
31
- * A rule as authored. `id`/`createdAt` and the runtime counters (`hits`,
32
- * `seen`) are the store's business, never the caller's.
33
- */
34
-
35
- /**
36
- * Handlers the desktop dashboard installs to forward mutations to the device.
37
- *
38
- * Rules only DO anything on the device — a rule is applied inside the app's own
39
- * `fetch`/`XMLHttpRequest`, which the dashboard doesn't have. So in remote mode
40
- * this store becomes a MIRROR: it renders the device's rules and forwards every
41
- * edit, writing nothing to this machine's storage. Same seam
42
- * `networkSavedStore` uses for pins.
43
- */
44
-
45
- /**
46
- * How long a local optimistic write suppresses incoming mirrors.
47
- *
48
- * An edit is applied locally AND forwarded; the device echoes it back on its
49
- * next snapshot. Without this window the in-flight snapshot — the one already
50
- * on the wire when the user tapped — would land first and visibly revert the
51
- * edit for a frame.
52
- */
53
- const REMOTE_ECHO_GRACE_MS = 800;
54
-
55
- /**
56
- * Launches-with-rules-on before overrides pause themselves.
57
- *
58
- * Persisting rules is the point ("force a 500, restart, watch the boot path"),
59
- * but a body the app can't render turns that into a brick: the rule reinstates
60
- * itself on every launch and the controls to remove it live inside an app that
61
- * no longer draws. Verified in testing — the only exit was deleting the file
62
- * off the simulator.
63
- *
64
- * Three is chosen so the intended workflow survives (force, relaunch, look,
65
- * relaunch, look) while a wedge cannot outlive the second relaunch. The streak
66
- * resets whenever a rule is created or edited, so an actively-used rule set
67
- * never pauses.
68
- */
69
- const MAX_UNTOUCHED_LAUNCHES = 3;
70
- const EMPTY_RULES = Object.freeze([]);
71
-
72
- /** Hit counts change per request; the UI shouldn't re-render per request. */
73
- const HIT_EMIT_COALESCE_MS = 250;
74
- const VALID_KINDS = ["respond", "fail", "delay"];
75
-
76
- /**
77
- * Tolerate junk and older shapes rather than throwing the list away.
78
- *
79
- * Storage is forever: a shape that throws on parse would take the whole feature
80
- * down on every launch until the user cleared app data.
81
- */
82
- function parseRules(raw) {
83
- if (!Array.isArray(raw)) return [];
84
- const parsed = [];
85
- for (const entry of raw) {
86
- if (!entry || typeof entry !== "object") continue;
87
- const rule = entry;
88
- if (typeof rule.id !== "string" || typeof rule.urlPattern !== "string") {
89
- continue;
90
- }
91
- if (!rule.urlPattern) continue;
92
- const kind = VALID_KINDS.includes(rule.kind) ? rule.kind : "respond";
93
- parsed.push({
94
- id: rule.id,
95
- enabled: rule.enabled !== false,
96
- name: typeof rule.name === "string" ? rule.name : undefined,
97
- urlPattern: rule.urlPattern,
98
- methods: Array.isArray(rule.methods) ? rule.methods.filter(m => typeof m === "string") : undefined,
99
- kind,
100
- status: typeof rule.status === "number" ? Math.min(_types.STATUS_MAX, Math.max(_types.STATUS_MIN, rule.status)) : undefined,
101
- statusText: typeof rule.statusText === "string" ? rule.statusText : undefined,
102
- headers: rule.headers && typeof rule.headers === "object" ? rule.headers : undefined,
103
- body: typeof rule.body === "string" ? rule.body : undefined,
104
- failKind: rule.failKind === "timeout" ? "timeout" : undefined,
105
- delayMs: typeof rule.delayMs === "number" ? rule.delayMs : undefined,
106
- times: typeof rule.times === "number" ? rule.times : null,
107
- alternate: rule.alternate === true,
108
- // Runtime-only: a rule that fired 3 times last launch has fired 0 times
109
- // this one, and a persisted count would make `times` mean "ever" instead
110
- // of "this session".
111
- hits: 0,
112
- seen: 0,
113
- createdAt: typeof rule.createdAt === "number" ? rule.createdAt : 0
114
- });
115
- }
116
- return parsed.slice(0, _types.MAX_RULES);
117
- }
118
- class OverrideRulesStore {
119
- rules = [];
120
- enabled = true;
121
- listeners = new Set();
122
- loaded = false;
123
- loadPromise = null;
124
- /** Set once a mutation happens so a slow initial load can't clobber it. */
125
- dirty = false;
126
- idCounter = 0;
127
- state = {
128
- enabled: true,
129
- rules: [],
130
- autoPaused: false
131
- };
132
- /** Consecutive launches that began with rules armed and nobody touching them. */
133
- launchStreak = 0;
134
- autoPaused = false;
135
- /** Held while any rule is active — see `syncKeepAlive`. */
136
- keepAlive = null;
137
- hitEmitTimer = null;
138
- /** Set on the desktop dashboard — see `disableEngine`. */
139
- engineDisabled = false;
140
- /** Set on the desktop dashboard — see `OverrideRulesRemote`. */
141
- remote = null;
142
- remoteEchoUntil = 0;
143
-
144
- // ===========================================================================
145
- // REMOTE MIRROR (desktop dashboard)
146
- // ===========================================================================
147
-
148
- /**
149
- * Turn this store into a mirror of a connected device's rules. Edits are
150
- * applied locally for immediate feedback AND forwarded to the device, which
151
- * is the source of truth; nothing is persisted to this machine.
152
- */
153
- enableRemoteMode(remote) {
154
- this.remote = remote;
155
- // A dashboard must never run rules against its own traffic.
156
- this.disableEngine();
157
- }
158
- disableRemoteMode() {
159
- this.remote = null;
160
- }
161
-
162
- /**
163
- * Feed the device's rules in (mirror mode only). `force` bypasses the echo
164
- * guard — used when tearing the mirror down, where there is no later snapshot
165
- * to converge on.
166
- */
167
- replaceRules(state, force = false) {
168
- if (!this.remote) return;
169
- // A local edit is still in flight — the snapshot on the wire predates it
170
- // and would flicker the change away. Drop this one; the next carries the
171
- // device's real answer.
172
- if (!force && Date.now() < this.remoteEchoUntil) return;
173
- this.enabled = state.enabled;
174
- this.rules = state.rules;
175
- this.rebuild();
176
- this.emit();
177
- }
178
-
179
- /** Mark a local optimistic write so the next in-flight mirror is ignored. */
180
- markLocalEdit() {
181
- if (this.remote) this.remoteEchoUntil = Date.now() + REMOTE_ECHO_GRACE_MS;
182
- }
183
-
184
- /**
185
- * Never intercept traffic in this runtime.
186
- *
187
- * The desktop dashboard renders the real tool (`NetworkToolView`), so this
188
- * module is imported there too — but the dashboard is a VIEWER. Its job is to
189
- * drive rules on the connected device, never to swizzle its own `fetch` and
190
- * override its own requests. The same seam `networkEventStore.disableCapture()`
191
- * uses, for the same reason.
192
- */
193
- disableEngine() {
194
- this.engineDisabled = true;
195
- if (this.keepAlive) {
196
- this.keepAlive();
197
- this.keepAlive = null;
198
- if ((0, _networkListener.getNetworkListenerCount)() === 0) (0, _networkListener.stopNetworkListener)();
199
- }
200
- }
201
- getState() {
202
- return this.state;
203
- }
204
-
205
- /**
206
- * The hot path — called inside `send()` for every request the app makes.
207
- * Returns a frozen empty array when the master switch is off so the caller
208
- * needs no second check.
209
- */
210
- getRules() {
211
- if (this.engineDisabled || !this.enabled) return EMPTY_RULES;
212
- return this.rules;
213
- }
214
-
215
- /**
216
- * The rule's real body, fetching it from the device when this surface only
217
- * has the stripped copy (see `OverrideRule.bodyOmitted`).
218
- *
219
- * On the device itself every body is already here, so this resolves
220
- * immediately and the editor never notices the difference.
221
- */
222
- async fetchRuleBody(id) {
223
- const rule = this.rules.find(candidate => candidate.id === id);
224
- if (!rule) return null;
225
- if (!rule.bodyOmitted) return rule.body ?? null;
226
- if (!this.remote?.getRuleBody) return null;
227
- try {
228
- return await this.remote.getRuleBody(id);
229
- } catch {
230
- // The editor keeps the empty body and the developer can retype it —
231
- // better than an error state over a payload they can still replace.
232
- return null;
233
- }
234
- }
235
-
236
- /** Rules that would actually fire — drives the "overrides active" banner. */
237
- activeCount() {
238
- if (!this.enabled) return 0;
239
- return this.rules.filter(rule => rule.enabled && !(0, _resolveOverride.isSpent)(rule)).length;
240
- }
241
- subscribe(listener) {
242
- this.listeners.add(listener);
243
- void this.ensureLoaded();
244
- return () => {
245
- this.listeners.delete(listener);
246
- };
247
- }
248
-
249
- // ===========================================================================
250
- // MUTATIONS
251
- // ===========================================================================
252
-
253
- setEnabled(enabled) {
254
- if (this.enabled === enabled) return;
255
- this.remote?.setEnabled(enabled);
256
- this.markLocalEdit();
257
- this.markTouched();
258
- this.enabled = enabled;
259
- this.commit(this.rules);
260
- }
261
- addRule(draft) {
262
- if (this.rules.length >= _types.MAX_RULES) return null;
263
- const rule = {
264
- ...draft,
265
- id: `ovr_${Date.now().toString(36)}_${++this.idCounter}`,
266
- hits: 0,
267
- seen: 0,
268
- createdAt: Date.now()
269
- };
270
- // Newest first: a rule you just made should win over an older, broader one,
271
- // because first-match wins and you almost certainly meant the new one.
272
- this.commit([rule, ...this.rules]);
273
- return rule;
274
- }
275
-
276
- /**
277
- * Create or replace a rule in one call.
278
- *
279
- * THE ONLY WRITE PATH THE UI SHOULD USE. `addRule`/`updateRule` are the
280
- * primitives underneath and deliberately do NOT forward to the device — if
281
- * the UI called them directly, an edit made on the dashboard would apply to
282
- * the mirror and never reach the phone, which looks exactly like it worked.
283
- *
284
- * Returns the rule, or null when the list is full.
285
- */
286
- upsertRule(draft) {
287
- this.remote?.upsertRule(draft);
288
- this.markLocalEdit();
289
- this.markTouched();
290
- const {
291
- id,
292
- ...rest
293
- } = draft;
294
- if (id && this.rules.some(rule => rule.id === id)) {
295
- this.updateRule(id, rest);
296
- return this.rules.find(rule => rule.id === id) ?? null;
297
- }
298
- return this.addRule(rest);
299
- }
300
- updateRule(id, patch) {
301
- const index = this.rules.findIndex(rule => rule.id === id);
302
- if (index === -1) return;
303
- const next = [...this.rules];
304
- // Editing a rule resets its budget — otherwise a spent "fail once" rule
305
- // stays silently dead after you change it and looks broken.
306
- next[index] = {
307
- ...next[index],
308
- ...patch,
309
- hits: 0,
310
- seen: 0
311
- };
312
- this.commit(next);
313
- }
314
- setRuleEnabled(id, enabled) {
315
- const index = this.rules.findIndex(rule => rule.id === id);
316
- if (index === -1 || this.rules[index].enabled === enabled) return;
317
- this.remote?.setRuleEnabled(id, enabled);
318
- this.markLocalEdit();
319
- this.markTouched();
320
- const next = [...this.rules];
321
- // Re-enabling a spent rule has to clear its budget too, or the toggle
322
- // appears to do nothing.
323
- next[index] = {
324
- ...next[index],
325
- enabled,
326
- hits: enabled ? 0 : next[index].hits,
327
- seen: enabled ? 0 : next[index].seen
328
- };
329
- this.commit(next);
330
- }
331
- removeRule(id) {
332
- const next = this.rules.filter(rule => rule.id !== id);
333
- if (next.length === this.rules.length) return;
334
- this.remote?.removeRule(id);
335
- this.markLocalEdit();
336
- this.markTouched();
337
- this.commit(next);
338
- }
339
- clearRules() {
340
- if (this.rules.length === 0) return;
341
- this.remote?.clearRules();
342
- this.markLocalEdit();
343
- this.markTouched();
344
- this.commit([]);
345
- }
346
-
347
- /**
348
- * One rule matched one request.
349
- *
350
- * Replaces the rule object rather than mutating it so memoized rows actually
351
- * re-render, and coalesces the notification — this runs at request rate.
352
- */
353
- /**
354
- * One rule matched one request, applied or not.
355
- *
356
- * Deliberately silent — this fires on requests an alternating rule lets
357
- * through, where nothing visible changed. `recordHit` owns the notification.
358
- */
359
- recordMatch(ruleId) {
360
- const index = this.rules.findIndex(rule => rule.id === ruleId);
361
- if (index === -1) return;
362
- const next = [...this.rules];
363
- next[index] = {
364
- ...next[index],
365
- seen: next[index].seen + 1
366
- };
367
- this.rules = next;
368
- this.rebuild();
369
- }
370
- recordHit(ruleId) {
371
- const index = this.rules.findIndex(rule => rule.id === ruleId);
372
- if (index === -1) return;
373
- const rule = this.rules[index];
374
- const hits = rule.hits + 1;
375
- const spent = typeof rule.times === "number" && hits >= rule.times;
376
- const next = [...this.rules];
377
- next[index] = {
378
- ...rule,
379
- hits,
380
- enabled: spent ? false : rule.enabled
381
- };
382
- if (spent) {
383
- // Auto-expiry is a real state change (and releases the keep-alive), so it
384
- // commits immediately instead of waiting on the coalesce window.
385
- this.commit(next);
386
- return;
387
- }
388
- this.rules = next;
389
- this.rebuild();
390
- this.scheduleHitEmit();
391
- }
392
-
393
- // ===========================================================================
394
- // LIFECYCLE
395
- // ===========================================================================
396
-
397
- /**
398
- * Hydrate from storage. Safe to call repeatedly; only the first call reads.
399
- *
400
- * Called at package import (see `preset.tsx`) rather than on first subscribe,
401
- * because a rule has to fire from app boot — with the Network tool closed and
402
- * nothing capturing.
403
- */
404
- ensureLoaded() {
405
- // Mirror mode reads the device's rules, never this machine's storage.
406
- if (this.remote) return Promise.resolve();
407
- if (this.loaded) return Promise.resolve();
408
- if (this.loadPromise) return this.loadPromise;
409
- this.loadPromise = (async () => {
410
- try {
411
- const stored = await _sharedUi.persistentStorage.getItem(_sharedUi.devToolsStorageKeys.network.overrides());
412
- // A rule may have been created while this read was in flight — never
413
- // overwrite user intent with older disk state.
414
- if (stored && !this.dirty) {
415
- const parsed = JSON.parse(stored);
416
- this.enabled = parsed?.enabled !== false;
417
- this.rules = parseRules(parsed?.rules);
418
- this.launchStreak = typeof parsed?.launchStreak === "number" ? parsed.launchStreak : 0;
419
- this.applyLaunchGuard();
420
- this.rebuild();
421
- }
422
- } catch {
423
- // Corrupt or unreadable — start empty rather than taking the tool down.
424
- } finally {
425
- this.loaded = true;
426
- this.syncKeepAlive();
427
- this.emit();
428
- }
429
- })();
430
- return this.loadPromise;
431
- }
432
-
433
- /**
434
- * Count this launch, and pause overrides if they've been armed and untouched
435
- * for too many in a row. See MAX_UNTOUCHED_LAUNCHES for why.
436
- */
437
- applyLaunchGuard() {
438
- if (!this.enabled || this.activeCount() === 0) {
439
- this.launchStreak = 0;
440
- return;
441
- }
442
- this.launchStreak += 1;
443
- if (this.launchStreak >= MAX_UNTOUCHED_LAUNCHES) {
444
- this.enabled = false;
445
- this.autoPaused = true;
446
- this.launchStreak = 0;
447
- }
448
- this.persist();
449
- }
450
-
451
- /**
452
- * Keep the interceptor installed for as long as a rule could fire.
453
- *
454
- * The swizzle is reference-counted off `networkListener`'s listener count
455
- * (the event store adds one while capturing). Holding a no-op listener reuses
456
- * that existing lifecycle instead of inventing a second one.
457
- */
458
- syncKeepAlive() {
459
- const needed = !this.engineDisabled && this.activeCount() > 0;
460
- if (needed && !this.keepAlive) {
461
- (0, _networkListener.startNetworkListener)();
462
- this.keepAlive = (0, _networkListener.addNetworkListener)(() => {});
463
- return;
464
- }
465
- if (!needed && this.keepAlive) {
466
- this.keepAlive();
467
- this.keepAlive = null;
468
- // Only tear the swizzle down if nothing else wants it — the Network tool
469
- // may well still be open and capturing.
470
- if ((0, _networkListener.getNetworkListenerCount)() === 0) (0, _networkListener.stopNetworkListener)();
471
- }
472
- }
473
- scheduleHitEmit() {
474
- if (this.hitEmitTimer !== null) return;
475
- this.hitEmitTimer = setTimeout(() => {
476
- this.hitEmitTimer = null;
477
- this.emit();
478
- }, HIT_EMIT_COALESCE_MS);
479
- }
480
- commit(next) {
481
- this.dirty = true;
482
- this.rules = next.slice(0, _types.MAX_RULES);
483
- this.rebuild();
484
- this.syncKeepAlive();
485
- this.emit();
486
- this.persist();
487
- }
488
-
489
- /** Rebuild the derived view once per mutation so renders get stable refs. */
490
- rebuild() {
491
- this.state = {
492
- enabled: this.enabled,
493
- rules: this.rules,
494
- autoPaused: this.autoPaused
495
- };
496
- }
497
-
498
- /**
499
- * The developer is actively working with the rules, so the launch guard has
500
- * nothing to protect them from — reset it and clear any auto-pause notice.
501
- */
502
- markTouched() {
503
- this.launchStreak = 0;
504
- this.autoPaused = false;
505
- }
506
-
507
- /**
508
- * The developer reached the override UI, which is proof the app still runs.
509
- *
510
- * The launch guard exists to escape a WEDGE — a body the app can't render,
511
- * where the controls are unreachable because nothing draws. If this call
512
- * happens, that isn't the situation, so the streak has nothing to protect
513
- * against. Without it the guard nags anyone who legitimately keeps a rule
514
- * armed for days, which is a real workflow ("force /checkout to 500 every
515
- * morning") and not the failure mode it was built for.
516
- */
517
- noteHealthyLaunch() {
518
- if (this.launchStreak === 0 && !this.autoPaused) return;
519
- this.markTouched();
520
- this.persist();
521
- this.rebuild();
522
- this.emit();
523
- }
524
- persist() {
525
- // The dashboard must not write the device's rules into its own storage —
526
- // they'd outlive the connection and shadow the next device.
527
- if (this.remote) return;
528
- _sharedUi.persistentStorage.setItem(_sharedUi.devToolsStorageKeys.network.overrides(), JSON.stringify({
529
- enabled: this.enabled,
530
- rules: this.rules,
531
- launchStreak: this.launchStreak
532
- })).catch(() => {
533
- // Silently fail — rules remain in memory for this session.
534
- });
535
- }
536
- emit() {
537
- this.listeners.forEach(listener => listener());
538
- }
539
- }
540
-
541
- /** Singleton — one rule list per JS runtime. */
542
- const overrideRulesStore = exports.overrideRulesStore = new OverrideRulesStore();
543
-
544
- // Register with the engine so `networkListener` can reach the rules without
545
- // importing this module (which imports the listener — see engine.ts).
546
- (0, _engine.setOverrideHooks)({
547
- getRules: () => overrideRulesStore.getRules(),
548
- recordHit: ruleId => overrideRulesStore.recordHit(ruleId),
549
- recordMatch: ruleId => overrideRulesStore.recordMatch(ruleId)
550
- });
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.overrideRulesStore=void 0;var _sharedUi=require("@buoy-gg/shared-ui");var _networkListener=require("../utils/networkListener");var _engine=require("./engine");var _resolveOverride=require("./resolveOverride");var _types=require("./types");var _realNow=require("../utils/realNow");const REMOTE_ECHO_GRACE_MS=800;const MAX_UNTOUCHED_LAUNCHES=3;const EMPTY_RULES=Object.freeze([]);const HIT_EMIT_COALESCE_MS=250;const VALID_KINDS=["respond","fail","delay"];function parseRules(n){if(!Array.isArray(n))return[];const t=[];for(const i of n){if(!i||typeof i!=="object")continue;const e=i;if(typeof e.id!=="string"||typeof e.urlPattern!=="string"){continue}if(!e.urlPattern)continue;const s=VALID_KINDS.includes(e.kind)?e.kind:"respond";t.push({id:e.id,enabled:e.enabled!==false,name:typeof e.name==="string"?e.name:void 0,urlPattern:e.urlPattern,methods:Array.isArray(e.methods)?e.methods.filter(r=>typeof r==="string"):void 0,requireHeader:typeof e.requireHeader==="string"&&e.requireHeader?e.requireHeader:void 0,kind:s,status:typeof e.status==="number"?Math.min(_types.STATUS_MAX,Math.max(_types.STATUS_MIN,e.status)):void 0,statusText:typeof e.statusText==="string"?e.statusText:void 0,headers:e.headers&&typeof e.headers==="object"?e.headers:void 0,body:typeof e.body==="string"?e.body:void 0,failKind:e.failKind==="timeout"?"timeout":void 0,delayMs:typeof e.delayMs==="number"?e.delayMs:void 0,times:typeof e.times==="number"?e.times:null,alternate:e.alternate===true,hits:0,seen:0,createdAt:typeof e.createdAt==="number"?e.createdAt:0})}return t.slice(0,_types.MAX_RULES)}class OverrideRulesStore{rules=[];enabled=true;listeners=new Set;loaded=false;loadPromise=null;dirty=false;idCounter=0;state={enabled:true,rules:[],autoPaused:false};launchStreak=0;autoPaused=false;keepAlive=null;hitEmitTimer=null;engineDisabled=false;remote=null;remoteEchoUntil=0;enableRemoteMode(t){this.remote=t;this.disableEngine()}disableRemoteMode(){this.remote=null}replaceRules(t,i=false){if(!this.remote)return;if(!i&&(0,_realNow.realNow)()<this.remoteEchoUntil)return;this.enabled=t.enabled;this.rules=t.rules;this.rebuild();this.emit()}markLocalEdit(){if(this.remote)this.remoteEchoUntil=(0,_realNow.realNow)()+REMOTE_ECHO_GRACE_MS}disableEngine(){this.engineDisabled=true;if(this.keepAlive){this.keepAlive();this.keepAlive=null;if((0,_networkListener.getNetworkListenerCount)()===0)(0,_networkListener.stopNetworkListener)()}}getState(){return this.state}getRules(){if(this.engineDisabled||!this.enabled)return EMPTY_RULES;return this.rules}async fetchRuleBody(t){const i=this.rules.find(e=>e.id===t);if(!i)return null;if(!i.bodyOmitted)return i.body??null;if(!this.remote?.getRuleBody)return null;try{return await this.remote.getRuleBody(t)}catch{return null}}activeCount(){if(!this.enabled)return 0;return this.rules.filter(t=>t.enabled&&!(0,_resolveOverride.isSpent)(t)).length}subscribe(t){this.listeners.add(t);void this.ensureLoaded();return()=>{this.listeners.delete(t)}}setEnabled(t){if(this.enabled===t)return;this.remote?.setEnabled(t);this.markLocalEdit();this.markTouched();this.enabled=t;this.commit(this.rules)}addRule(t){if(this.rules.length>=_types.MAX_RULES)return null;const i={...t,id:`ovr_${Date.now().toString(36)}_${++this.idCounter}`,hits:0,seen:0,createdAt:Date.now()};this.commit([i,...this.rules]);return i}upsertRule(t){this.remote?.upsertRule(t);this.markLocalEdit();this.markTouched();const{id:i,...e}=t;if(i&&this.rules.some(s=>s.id===i)){this.updateRule(i,e);return this.rules.find(s=>s.id===i)??null}return this.addRule(e)}updateRule(t,i){const e=this.rules.findIndex(r=>r.id===t);if(e===-1)return;const s=[...this.rules];s[e]={...s[e],...i,hits:0,seen:0};this.commit(s)}setRuleEnabled(t,i){const e=this.rules.findIndex(r=>r.id===t);if(e===-1||this.rules[e].enabled===i)return;this.remote?.setRuleEnabled(t,i);this.markLocalEdit();this.markTouched();const s=[...this.rules];s[e]={...s[e],enabled:i,hits:i?0:s[e].hits,seen:i?0:s[e].seen};this.commit(s)}removeRule(t){const i=this.rules.filter(e=>e.id!==t);if(i.length===this.rules.length)return;this.remote?.removeRule(t);this.markLocalEdit();this.markTouched();this.commit(i)}clearRules(){if(this.rules.length===0)return;this.remote?.clearRules();this.markLocalEdit();this.markTouched();this.commit([])}recordMatch(t){const i=this.rules.findIndex(s=>s.id===t);if(i===-1)return;const e=[...this.rules];e[i]={...e[i],seen:e[i].seen+1};this.rules=e;this.rebuild()}recordHit(t){const i=this.rules.findIndex(u=>u.id===t);if(i===-1)return;const e=this.rules[i];const s=e.hits+1;const r=typeof e.times==="number"&&s>=e.times;const l=[...this.rules];l[i]={...e,hits:s,enabled:r?false:e.enabled};if(r){this.commit(l);return}this.rules=l;this.rebuild();this.scheduleHitEmit()}ensureLoaded(){if(this.remote)return Promise.resolve();if(this.loaded)return Promise.resolve();if(this.loadPromise)return this.loadPromise;this.loadPromise=(async()=>{try{const t=await _sharedUi.persistentStorage.getItem(_sharedUi.devToolsStorageKeys.network.overrides());if(t&&!this.dirty){const i=JSON.parse(t);this.enabled=i?.enabled!==false;this.rules=parseRules(i?.rules);this.launchStreak=typeof i?.launchStreak==="number"?i.launchStreak:0;this.applyLaunchGuard();this.rebuild()}}catch{}finally{this.loaded=true;this.syncKeepAlive();this.emit()}})();return this.loadPromise}applyLaunchGuard(){if(!this.enabled||this.activeCount()===0){this.launchStreak=0;return}this.launchStreak+=1;if(this.launchStreak>=MAX_UNTOUCHED_LAUNCHES){this.enabled=false;this.autoPaused=true;this.launchStreak=0}this.persist()}syncKeepAlive(){const t=!this.engineDisabled&&this.activeCount()>0;if(t&&!this.keepAlive){(0,_networkListener.startNetworkListener)();this.keepAlive=(0,_networkListener.addNetworkListener)(()=>{});return}if(!t&&this.keepAlive){this.keepAlive();this.keepAlive=null;if((0,_networkListener.getNetworkListenerCount)()===0)(0,_networkListener.stopNetworkListener)()}}scheduleHitEmit(){if(this.hitEmitTimer!==null)return;this.hitEmitTimer=setTimeout(()=>{this.hitEmitTimer=null;this.emit()},HIT_EMIT_COALESCE_MS)}commit(t){this.dirty=true;this.rules=t.slice(0,_types.MAX_RULES);this.rebuild();this.syncKeepAlive();this.emit();this.persist()}rebuild(){this.state={enabled:this.enabled,rules:this.rules,autoPaused:this.autoPaused}}markTouched(){this.launchStreak=0;this.autoPaused=false}noteHealthyLaunch(){if(this.launchStreak===0&&!this.autoPaused)return;this.markTouched();this.persist();this.rebuild();this.emit()}persist(){if(this.remote)return;_sharedUi.persistentStorage.setItem(_sharedUi.devToolsStorageKeys.network.overrides(),JSON.stringify({enabled:this.enabled,rules:this.rules,launchStreak:this.launchStreak})).catch(()=>{})}emit(){this.listeners.forEach(t=>t())}}const overrideRulesStore=exports.overrideRulesStore=new OverrideRulesStore;(0,_engine.setOverrideHooks)({getRules:()=>overrideRulesStore.getRules(),recordHit:n=>overrideRulesStore.recordHit(n),recordMatch:n=>overrideRulesStore.recordMatch(n)});