@buoy-gg/network 7.0.79 → 7.0.80

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 (91) hide show
  1. package/README.md +8 -0
  2. package/lib/commonjs/index.js +1 -1
  3. package/lib/commonjs/index.web.js +1 -1
  4. package/lib/commonjs/network/components/NetworkEventDetailView.js +1 -1
  5. package/lib/commonjs/network/components/NetworkEventDetailView.web.js +1 -1
  6. package/lib/commonjs/network/components/NetworkModal.js +1 -1
  7. package/lib/commonjs/network/components/sockets/NetworkSocketsButton.js +1 -0
  8. package/lib/commonjs/network/components/sockets/NetworkSocketsScreen.js +1 -0
  9. package/lib/commonjs/network/components/sockets/SocketFrameView.js +1 -0
  10. package/lib/commonjs/network/components/sockets/SocketListView.js +1 -0
  11. package/lib/commonjs/network/components/sockets/SocketRows.js +1 -0
  12. package/lib/commonjs/network/components/sockets/SocketTricksView.js +1 -0
  13. package/lib/commonjs/network/conditions/NetworkConditionsControl.js +1 -1
  14. package/lib/commonjs/network/conditions/profiles.js +1 -1
  15. package/lib/commonjs/network/conditions/store.js +1 -1
  16. package/lib/commonjs/network/hooks/useSocketsState.js +1 -0
  17. package/lib/commonjs/network/overrides/engine.js +1 -1
  18. package/lib/commonjs/network/overrides/matchRule.js +1 -1
  19. package/lib/commonjs/network/overrides/overrideRulesStore.js +1 -1
  20. package/lib/commonjs/network/sockets/findProblems.js +1 -0
  21. package/lib/commonjs/network/sockets/foldFrames.js +1 -0
  22. package/lib/commonjs/network/sockets/format.js +1 -0
  23. package/lib/commonjs/network/sockets/readMessage.js +1 -0
  24. package/lib/commonjs/network/sockets/socketMoments.js +1 -0
  25. package/lib/commonjs/network/sockets/socketStore.js +1 -0
  26. package/lib/commonjs/network/sockets/socketsSyncAdapter.js +1 -0
  27. package/lib/commonjs/network/sockets/types.js +1 -0
  28. package/lib/commonjs/network/sockets/webSocketPatch.js +1 -0
  29. package/lib/commonjs/network/sync/networkSyncAdapter.js +1 -1
  30. package/lib/commonjs/network/utils/networkEventStore.js +1 -1
  31. package/lib/commonjs/network/utils/networkListener.js +4 -4
  32. package/lib/commonjs/network/utils/startNetworkCapture.js +1 -1
  33. package/lib/commonjs/preset.js +1 -1
  34. package/lib/module/index.js +1 -1
  35. package/lib/module/index.web.js +1 -1
  36. package/lib/module/network/components/NetworkEventDetailView.js +1 -1
  37. package/lib/module/network/components/NetworkEventDetailView.web.js +1 -1
  38. package/lib/module/network/components/NetworkModal.js +1 -1
  39. package/lib/module/network/components/sockets/NetworkSocketsButton.js +1 -0
  40. package/lib/module/network/components/sockets/NetworkSocketsScreen.js +1 -0
  41. package/lib/module/network/components/sockets/SocketFrameView.js +1 -0
  42. package/lib/module/network/components/sockets/SocketListView.js +1 -0
  43. package/lib/module/network/components/sockets/SocketRows.js +1 -0
  44. package/lib/module/network/components/sockets/SocketTricksView.js +1 -0
  45. package/lib/module/network/conditions/NetworkConditionsControl.js +1 -1
  46. package/lib/module/network/conditions/profiles.js +1 -1
  47. package/lib/module/network/conditions/store.js +1 -1
  48. package/lib/module/network/hooks/useSocketsState.js +1 -0
  49. package/lib/module/network/overrides/engine.js +1 -1
  50. package/lib/module/network/overrides/matchRule.js +1 -1
  51. package/lib/module/network/overrides/overrideRulesStore.js +1 -1
  52. package/lib/module/network/sockets/findProblems.js +1 -0
  53. package/lib/module/network/sockets/foldFrames.js +1 -0
  54. package/lib/module/network/sockets/format.js +1 -0
  55. package/lib/module/network/sockets/readMessage.js +1 -0
  56. package/lib/module/network/sockets/socketMoments.js +1 -0
  57. package/lib/module/network/sockets/socketStore.js +1 -0
  58. package/lib/module/network/sockets/socketsSyncAdapter.js +1 -0
  59. package/lib/module/network/sockets/types.js +1 -0
  60. package/lib/module/network/sockets/webSocketPatch.js +1 -0
  61. package/lib/module/network/sync/networkSyncAdapter.js +1 -1
  62. package/lib/module/network/utils/networkEventStore.js +1 -1
  63. package/lib/module/network/utils/networkListener.js +4 -4
  64. package/lib/module/network/utils/startNetworkCapture.js +1 -1
  65. package/lib/module/preset.js +1 -1
  66. package/lib/typescript/index.d.ts +11 -0
  67. package/lib/typescript/index.web.d.ts +4 -0
  68. package/lib/typescript/network/components/sockets/NetworkSocketsButton.d.ts +17 -0
  69. package/lib/typescript/network/components/sockets/NetworkSocketsScreen.d.ts +19 -0
  70. package/lib/typescript/network/components/sockets/SocketFrameView.d.ts +9 -0
  71. package/lib/typescript/network/components/sockets/SocketListView.d.ts +9 -0
  72. package/lib/typescript/network/components/sockets/SocketRows.d.ts +19 -0
  73. package/lib/typescript/network/components/sockets/SocketTricksView.d.ts +23 -0
  74. package/lib/typescript/network/conditions/store.d.ts +1 -1
  75. package/lib/typescript/network/hooks/useSocketsState.d.ts +3 -0
  76. package/lib/typescript/network/overrides/overrideRulesStore.d.ts +19 -0
  77. package/lib/typescript/network/overrides/types.d.ts +14 -0
  78. package/lib/typescript/network/sockets/findProblems.d.ts +31 -0
  79. package/lib/typescript/network/sockets/foldFrames.d.ts +50 -0
  80. package/lib/typescript/network/sockets/format.d.ts +19 -0
  81. package/lib/typescript/network/sockets/readMessage.d.ts +41 -0
  82. package/lib/typescript/network/sockets/socketMoments.d.ts +24 -0
  83. package/lib/typescript/network/sockets/socketStore.d.ts +94 -0
  84. package/lib/typescript/network/sockets/socketsSyncAdapter.d.ts +66 -0
  85. package/lib/typescript/network/sockets/types.d.ts +139 -0
  86. package/lib/typescript/network/sockets/webSocketPatch.d.ts +57 -0
  87. package/lib/typescript/network/sync/networkSyncAdapter.d.ts +3 -1
  88. package/lib/typescript/network/types/index.d.ts +6 -0
  89. package/lib/typescript/network/utils/networkListener.d.ts +6 -0
  90. package/lib/web/index.mjs +58 -58
  91. package/package.json +2 -2
@@ -1 +1 @@
1
- "use strict";import{createRemoteConditionsSource as qe,openNetworkFloatingTool as ue}from"../conditions/NetworkFloatingTool";import{useState as n,useRef as B,useEffect as b,useCallback as X}from"react";import{View as M,StyleSheet as He,TouchableOpacity as Le}from"react-native";import{Search as Ue,Wifi as pe,Filter as ze,Bookmark as je,JsModal as Ke,ModalHeader as o,devToolsStorageKeys as D,macOSColors as We,night as d,persistentStorage as fe,NightSegmented as Je,useFeatureGate as $e,UpgradeModal as Ge,PowerToggleButton as Xe,useIgnoredPatterns as Ye,windowDragProps as Qe}from"@buoy-gg/shared-ui";import{NetworkFilterViewV3 as Ze}from"./NetworkFilterViewV3";import{TickProvider as ge}from"../hooks/useTickEveryMinute";import{NetworkEventDetailView as et}from"./NetworkEventDetailView";import{NetworkCopySettingsView as tt,DEFAULT_COPY_SETTINGS as rt}from"./NetworkCopySettingsView";import{NetworkHeaderBadges as ot,NetworkClearButton as nt,NetworkDetailPinActions as st,NetworkHeaderCopyButton as at}from"./NetworkHeaderLive";import{NetworkListScreen as it}from"./NetworkListScreen";import{NetworkSavedScreen as lt}from"./NetworkSavedScreen";import{NetworkOverridesScreen as ct}from"./NetworkOverridesScreen";import{NetworkOverridesButton as dt}from"./NetworkOverridesButton";import{NetworkOverrideHeaderButton as ut}from"./NetworkOverrideHeaderButton";import{NetworkHeaderMenu as pt,NetworkHeaderMenuButton as ft,NetworkHeaderMenuItem as _}from"./NetworkHeaderMenu";import{NetworkDetailStepper as gt}from"./NetworkDetailStepper";import{useNetworkEventList as he}from"../hooks/useNetworkEventList";import{useLiveNetworkEvent as ht}from"../hooks/useLiveNetworkEvent";import{useHasNetworkSelection as mt,useNetworkBodyEventId as St,useSelectedNetworkEventId as vt}from"../hooks/useNetworkSelection";import{networkSelectionStore as V}from"../utils/networkSelectionStore";import{FREE_TIER_SAVED_LIMIT as wt,MAX_SAVED as yt}from"../utils/networkSavedStore";import{FREE_TIER_RULE_LIMIT as kt,MAX_RULES as Pt}from"../overrides/types";import{jsx as e,jsxs as c,Fragment as bt}from"react/jsx-runtime";function Ct({visible:r,paused:p,ignoredPatternValues:f,onTogglePattern:g,isPro:w,filter:l,ignoredPatterns:h,fromSaved:m,savedSearch:S,applySafeAreaInset:i}){const y=vt();const q=St();const R=y!=null&&y===q;const s=ht(y,{paused:p||!r});b(()=>{if(r&&s&&R){V.reportRendered(s.id)}},[r,s,R]);if(!r)return null;return c(M,{style:C.detailRoot,children:[s?e(et,{event:s,ignoredPatterns:f,onTogglePattern:g,showBodies:R}):e(M,{style:C.detailBodyFallback}),e(gt,{paused:p,filter:l,ignoredPatterns:h,isPro:w,fromSaved:m,savedSearch:S,applySafeAreaInset:i})]})}function Rt({visible:r,paused:p,isPro:f,filter:g,onFilterChange:w,ignoredPatterns:l,onRemovePattern:h,onAddPattern:m,onTogglePatternMode:S,isTeamPattern:i}){const{events:y}=he({filter:g,ignoredPatterns:l,paused:p,visible:r,isPro:f});if(!r)return null;return e(Ze,{events:y,filter:g,onFilterChange:w,ignoredPatterns:l,onRemovePattern:h,onAddPattern:m,onTogglePatternMode:S,isTeamPattern:i})}function It({visible:r,paused:p,isPro:f,filter:g,ignoredPatterns:w,settings:l,onSettingsChange:h}){const{events:m}=he({filter:g,ignoredPatterns:w,paused:p,visible:r,isPro:f});if(!r)return null;return e(tt,{settings:l,onSettingsChange:h,events:m})}function me({visible:r,onClose:p,onBack:f,onMinimize:g,enableSharedModalDimensions:w=false,inline:l=false,paused:h,onPausedChange:m,remoteConditions:S}){const{isPro:i}=$e();const[y,q]=n(false);const R=h!=null&&m!=null;const s=R?h:y;const Se=t=>{const a=typeof t==="function"?t(s):t;if(R)m(a);else q(a)};const[u,H]=n({});const v=mt();const[k,Y]=n(false);const[A,Q]=n(false);const[x,L]=n(false);const[Z,P]=n(false);const[ve,ee]=n(0);const[I]=n(qe);b(()=>{I.update(S)},[I,S]);b(()=>()=>I.update(void 0),[I]);const N=true;const[we,U]=n(null);const[z,te]=n("filters");const[re,ye]=n("");const[j,K]=n(false);const Tt=B(false);const[oe,ke]=n("");const Pe=B(null);const{patterns:T,values:be,add:Ce,remove:Re,toggle:Ie,toggleMode:Ne,isTeamOnly:Te}=Ye();const[F,ne]=n(rt);const W=B(false);const[J,$]=n(false);const[E,Ee]=n("export");const O=t=>{Ee(t);$(true)};b(()=>{if(J&&i){$(false)}},[J,i]);b(()=>{if(!r||W.current)return;const t=async()=>{try{const a=await fe.getItem(D.network.copyOptions());if(a){const Ve=JSON.parse(a);ne(Ve)}}catch(a){}finally{W.current=true}};t()},[r]);b(()=>{if(!W.current)return;const t=async()=>{try{await fe.setItem(D.network.copyOptions(),JSON.stringify(F))}catch(a){}};t()},[F]);const Me=()=>{V.clear()};const se=X(t=>{V.select(t.id)},[]);const Fe=X((t,a)=>{U(a?{...t,id:a}:t);L(true);V.clear()},[]);const Oe=X(()=>U(null),[]);const ae=B(null);const ie=t=>{ye(t);H(a=>({...a,searchText:t}))};const Ae=t=>{H(a=>({...a,status:a.status===t?void 0:t}))};const[le,xe]=n("bottomSheet");const Be=t=>{xe(t)};b(()=>{if(j){requestAnimationFrame(()=>{Pe.current?.focus()})}},[j]);const ce=()=>{if(k){return c(o,{children:[e(o.Navigation,{onBack:()=>Y(false)}),e(o.Content,{title:"",noMargin:true,children:e(Je,{size:"sm",tabs:[{key:"filters",label:"Filters"},{key:"copy",label:"Copy"}],activeKey:z,onChange:t=>te(t)})})]})}if(v){return c(o,{children:[e(o.Navigation,{onBack:Me}),e(o.Content,{title:"Request Details",centered:true}),c(o.Actions,{children:[N?e(ut,{onOpen:Fe}):null,e(st,{isPro:i,onUpgradePress:()=>O("saved")})]})]})}if(x&&N){return c(o,{children:[e(o.Navigation,{onBack:()=>{if(ae.current?.())return;L(false);U(null)}}),e(o.Content,{title:"Response Overrides",centered:true})]})}if(A){return c(o,{children:[e(o.Navigation,{onBack:()=>Q(false)}),e(o.Content,{title:"Saved Requests",centered:true})]})}return c(o,{children:[f&&e(o.Navigation,{onBack:f}),e(o.Content,{title:"",children:j?e(o.Search,{value:re,onChangeText:ie,onCancel:()=>{ie("");K(false)},onDismiss:()=>K(false),dismissOnBlur:true,clearOnlyWhenText:true,placeholder:"Search URL, method, operation, error...",accessibilityLabel:"Search network requests",iconSize:14,testID:"buoy-network-search-input",clearTestID:"buoy-network-search-clear",inputProps:{"sentry-label":"ignore network search header"}}):e(ot,{activeStatus:u.status,onToggleStatus:Ae,ignoredPatterns:T,paused:s})}),c(o.Actions,{children:[e(Le,{"sentry-label":"ignore open search",testID:"buoy-network-search-open",accessibilityLabel:"Open search",accessibilityRole:"button",onPress:()=>K(true),style:C.headerActionButton,children:e(Ue,{size:14,color:d.color.textSecondary})}),N?e(dt,{onPress:()=>L(true)}):null,e(Xe,{isEnabled:!s,onToggle:()=>Se(t=>!t),accessibilityLabel:s?"Resume network capture":"Pause network capture",testID:"buoy-network-power"}),e(nt,{paused:s}),e(ft,{onPress:()=>P(t=>!t),isOpen:Z,hasIndicator:G})]})]})};const G=!!(u.status||u.method||u.contentType);const De=w?D.modal.root():D.network.modal();if(!r)return null;const _e=v||!k;const de=c(bt,{children:[c(M,{style:C.container,children:[e(Ct,{visible:v,paused:s,ignoredPatternValues:be,onTogglePattern:Ie,isPro:i,filter:u,ignoredPatterns:T,fromSaved:A,savedSearch:oe,applySafeAreaInset:!l&&le==="bottomSheet"}),e(Rt,{visible:k&&z==="filters"&&!v,paused:s,isPro:i,filter:u,onFilterChange:H,ignoredPatterns:T,onRemovePattern:Re,onAddPattern:Ce,onTogglePatternMode:Ne,isTeamPattern:Te}),e(It,{visible:k&&z==="copy"&&!v,paused:s,isPro:i,filter:u,ignoredPatterns:T,settings:F,onSettingsChange:ne}),e(ct,{visible:N&&x&&!v&&!k,isPro:i,onUpgradePress:()=>O("overrides"),pendingDraft:we,onPendingConsumed:Oe,backHandlerRef:ae,applySafeAreaInset:!l&&le==="bottomSheet"}),e(lt,{visible:A&&!v&&!k&&!(x&&N),isPro:i,copySettings:F,search:oe,onSearchChange:ke,onEventPress:se,onUpgradePress:()=>O("saved")}),e(it,{visible:!v&&!k&&!A&&!(x&&N),paused:s,filter:u,ignoredPatterns:T,isPro:i,searchText:re,onEventPress:se,onUpgradePress:()=>O("export")})]}),Z?c(pt,{onClose:()=>P(false),children:[e(_,{icon:e(pe,{size:14,color:d.color.textSecondary}),label:"Network throttling",testID:"buoy-network-menu-throttling",onPress:()=>{P(false);ue(S?I:void 0);if(!l)ee(t=>t+1)}}),e(_,{icon:e(pe,{size:14,color:d.color.textSecondary}),label:"Speed and link state",testID:"buoy-network-menu-conditions",onPress:()=>{P(false);ue(S?I:void 0,true);if(!l)ee(t=>t+1)}}),e(_,{icon:e(ze,{size:14,color:G?d.color.accent:d.color.textSecondary}),label:"Filters",detail:G?"Active":void 0,onPress:()=>{P(false);te("filters");Y(true)}}),e(_,{icon:e(je,{size:14,color:d.color.textSecondary}),label:"Saved requests",onPress:()=>{P(false);Q(true)}}),e(M,{style:C.menuCopyRow,children:e(at,{isPro:i,filter:u,ignoredPatterns:T,copySettings:F,paused:s,onUpgradePress:()=>{P(false);O("export")},label:"Copy requests"})})]}):null,e(Ge,{visible:J,onClose:()=>$(false),featureName:E==="saved"?"Saved Requests":E==="overrides"?"Response Overrides":"Network Export",description:E==="saved"?"Keep the requests that matter. Saved requests survive Clear, app restarts, and the 500-request history cap.":E==="overrides"?"Force any endpoint to fail, stall or return something else \u2014 no backend changes, no code changes. Free keeps one active rule.":"Export network requests to share with your team, debug APIs, or feed into AI tools.",benefits:E==="overrides"?[`Run ${Pt} rules at once (free keeps ${kt})`,"Force a 500, a 401 or an empty list in one tap","Simulate offline, timeouts and slow connections","Rules survive an app reload, so you can test the boot path"]:E==="saved"?[`Save up to ${yt} requests (free keeps ${wt})`,"Failed requests stay put through a Clear","Snapshots survive an app restart","Export saved requests to teammates or AI assistants"]:["Export to JSON, Markdown, or plain text","Customizable copy presets (URLs only, LLM-ready, full data)","Share request details with teammates","Feed network data directly to AI assistants"]})]});if(l){return c(M,{style:C.inlineRoot,children:[e(M,{style:C.inlineHeader,...Qe,children:ce()}),de]})}return e(Ke,{visible:r,onClose:p,onMinimize:g,minimizeRequest:ve,persistenceKey:De,variant:"night",header:{showToggleButton:true,customContent:ce()},onModeChange:Be,enablePersistence:true,initialMode:"bottomSheet",enableGlitchEffects:true,disableScrollWrapper:_e,styles:{},children:de})}const C=He.create({container:{flex:1,backgroundColor:"transparent"},detailRoot:{flex:1,minHeight:0},detailBodyFallback:{flex:1},inlineRoot:{flex:1,minHeight:0,backgroundColor:"transparent"},inlineHeader:{paddingHorizontal:12,paddingVertical:8,borderBottomWidth:1,borderBottomColor:We.border.default,backgroundColor:"transparent"},menuCopyRow:{paddingHorizontal:6},headerActionButton:{width:32,height:32,borderRadius:8,backgroundColor:d.color.buttonSurface,borderWidth:1,borderColor:d.color.border,alignItems:"center",justifyContent:"center"},activeFilterButton:{backgroundColor:d.color.accentSoft,borderColor:d.color.accentBorderStrong}});export function NetworkModal(r){return e(ge,{children:e(me,{...r})})}export function NetworkToolView(r={}){return e(ge,{children:e(me,{...r,inline:true,visible:true,onClose:Nt})})}const Nt=()=>{};
1
+ "use strict";import{createRemoteConditionsSource as je,openNetworkFloatingTool as he}from"../conditions/NetworkFloatingTool";import{useState as n,useRef as A,useEffect as C,useCallback as Q}from"react";import{View as B,StyleSheet as Ke,TouchableOpacity as We}from"react-native";import{Search as Je,Wifi as ge,Filter as $e,Bookmark as Ge,Activity as Xe,JsModal as Ye,ModalHeader as o,devToolsStorageKeys as _,macOSColors as Qe,night as d,persistentStorage as me,NightSegmented as Ze,useFeatureGate as et,UpgradeModal as tt,PowerToggleButton as ot,useIgnoredPatterns as rt,windowDragProps as nt}from"@buoy-gg/shared-ui";import{NetworkFilterViewV3 as st}from"./NetworkFilterViewV3";import{TickProvider as Se}from"../hooks/useTickEveryMinute";import{NetworkEventDetailView as at}from"./NetworkEventDetailView";import{NetworkCopySettingsView as it,DEFAULT_COPY_SETTINGS as lt}from"./NetworkCopySettingsView";import{NetworkHeaderBadges as ct,NetworkClearButton as dt,NetworkDetailPinActions as ut,NetworkHeaderCopyButton as pt}from"./NetworkHeaderLive";import{NetworkListScreen as ft}from"./NetworkListScreen";import{NetworkSavedScreen as ht}from"./NetworkSavedScreen";import{NetworkOverridesScreen as gt}from"./NetworkOverridesScreen";import{NetworkOverridesButton as mt}from"./NetworkOverridesButton";import{NetworkOverrideHeaderButton as St}from"./NetworkOverrideHeaderButton";import{NetworkSocketsButton as kt}from"./sockets/NetworkSocketsButton";import{NetworkSocketsScreen as wt}from"./sockets/NetworkSocketsScreen";import{NetworkHeaderMenu as vt,NetworkHeaderMenuButton as yt,NetworkHeaderMenuItem as O}from"./NetworkHeaderMenu";import{NetworkDetailStepper as Pt}from"./NetworkDetailStepper";import{useNetworkEventList as ke}from"../hooks/useNetworkEventList";import{useLiveNetworkEvent as bt}from"../hooks/useLiveNetworkEvent";import{useHasNetworkSelection as Ct,useNetworkBodyEventId as Rt,useSelectedNetworkEventId as Nt}from"../hooks/useNetworkSelection";import{networkSelectionStore as H}from"../utils/networkSelectionStore";import{FREE_TIER_SAVED_LIMIT as It,MAX_SAVED as Tt}from"../utils/networkSavedStore";import{FREE_TIER_RULE_LIMIT as Et,MAX_RULES as Mt}from"../overrides/types";import{jsx as e,jsxs as l,Fragment as Bt}from"react/jsx-runtime";function Ft({visible:r,paused:h,ignoredPatternValues:g,onTogglePattern:m,isPro:P,filter:c,ignoredPatterns:S,fromSaved:k,savedSearch:w,applySafeAreaInset:a}){const b=Nt();const q=Rt();const N=b!=null&&b===q;const s=bt(b,{paused:h||!r});C(()=>{if(r&&s&&N){H.reportRendered(s.id)}},[r,s,N]);if(!r)return null;return l(B,{style:R.detailRoot,children:[s?e(at,{event:s,ignoredPatterns:g,onTogglePattern:m,showBodies:N}):e(B,{style:R.detailBodyFallback}),e(Pt,{paused:h,filter:c,ignoredPatterns:S,isPro:P,fromSaved:k,savedSearch:w,applySafeAreaInset:a})]})}function xt({visible:r,paused:h,isPro:g,filter:m,onFilterChange:P,ignoredPatterns:c,onRemovePattern:S,onAddPattern:k,onTogglePatternMode:w,isTeamPattern:a}){const{events:b}=ke({filter:m,ignoredPatterns:c,paused:h,visible:r,isPro:g});if(!r)return null;return e(st,{events:b,filter:m,onFilterChange:P,ignoredPatterns:c,onRemovePattern:S,onAddPattern:k,onTogglePatternMode:w,isTeamPattern:a})}function At({visible:r,paused:h,isPro:g,filter:m,ignoredPatterns:P,settings:c,onSettingsChange:S}){const{events:k}=ke({filter:m,ignoredPatterns:P,paused:h,visible:r,isPro:g});if(!r)return null;return e(it,{settings:c,onSettingsChange:S,events:k})}function we({visible:r,onClose:h,onBack:g,onMinimize:m,enableSharedModalDimensions:P=false,inline:c=false,paused:S,onPausedChange:k,remoteConditions:w}){const{isPro:a}=et();const[b,q]=n(false);const N=S!=null&&k!=null;const s=N?S:b;const ve=t=>{const i=typeof t==="function"?t(s):t;if(N)k(i);else q(i)};const[u,L]=n({});const p=Ct();const[v,Z]=n(false);const[D,ee]=n(false);const[V,z]=n(false);const[F,U]=n(false);const[ye,Pe]=n("Sockets");const[te,y]=n(false);const[be,oe]=n(0);const[I]=n(je);C(()=>{I.update(w)},[I,w]);C(()=>()=>I.update(void 0),[I]);const T=true;const[Ce,j]=n(null);const[K,re]=n("filters");const[ne,Re]=n("");const[W,J]=n(false);const Dt=A(false);const[se,Ne]=n("");const Ie=A(null);const{patterns:E,values:Te,add:Ee,remove:Me,toggle:Be,toggleMode:Fe,isTeamOnly:xe}=rt();const[x,ae]=n(lt);const $=A(false);const[G,X]=n(false);const[f,Ae]=n("export");const M=t=>{Ae(t);X(true)};C(()=>{if(G&&a){X(false)}},[G,a]);C(()=>{if(!r||$.current)return;const t=async()=>{try{const i=await me.getItem(_.network.copyOptions());if(i){const Ue=JSON.parse(i);ae(Ue)}}catch(i){}finally{$.current=true}};t()},[r]);C(()=>{if(!$.current)return;const t=async()=>{try{await me.setItem(_.network.copyOptions(),JSON.stringify(x))}catch(i){}};t()},[x]);const Oe=()=>{H.clear()};const ie=Q(t=>{H.select(t.id)},[]);const De=Q((t,i)=>{j(i?{...t,id:i}:t);z(true);H.clear()},[]);const Ve=Q(()=>j(null),[]);const le=A(null);const ce=A(null);const de=t=>{Re(t);L(i=>({...i,searchText:t}))};const _e=t=>{L(i=>({...i,status:i.status===t?void 0:t}))};const[ue,He]=n("bottomSheet");const qe=t=>{He(t)};C(()=>{if(W){requestAnimationFrame(()=>{Ie.current?.focus()})}},[W]);const pe=()=>{if(v){return l(o,{children:[e(o.Navigation,{onBack:()=>Z(false)}),e(o.Content,{title:"",noMargin:true,children:e(Ze,{size:"sm",tabs:[{key:"filters",label:"Filters"},{key:"copy",label:"Copy"}],activeKey:K,onChange:t=>re(t)})})]})}if(p){return l(o,{children:[e(o.Navigation,{onBack:Oe}),e(o.Content,{title:"Request Details",centered:true}),l(o.Actions,{children:[T?e(St,{onOpen:De}):null,e(ut,{isPro:a,onUpgradePress:()=>M("saved")})]})]})}if(F){return l(o,{children:[e(o.Navigation,{onBack:()=>{if(ce.current?.())return;U(false)}}),e(o.Content,{title:ye,centered:true})]})}if(V&&T){return l(o,{children:[e(o.Navigation,{onBack:()=>{if(le.current?.())return;z(false);j(null)}}),e(o.Content,{title:"Response Overrides",centered:true})]})}if(D){return l(o,{children:[e(o.Navigation,{onBack:()=>ee(false)}),e(o.Content,{title:"Saved Requests",centered:true})]})}return l(o,{children:[g&&e(o.Navigation,{onBack:g}),e(o.Content,{title:"",children:W?e(o.Search,{value:ne,onChangeText:de,onCancel:()=>{de("");J(false)},onDismiss:()=>J(false),dismissOnBlur:true,clearOnlyWhenText:true,placeholder:"Search URL, method, operation, error...",accessibilityLabel:"Search network requests",iconSize:14,testID:"buoy-network-search-input",clearTestID:"buoy-network-search-clear",inputProps:{"sentry-label":"ignore network search header"}}):e(ct,{activeStatus:u.status,onToggleStatus:_e,ignoredPatterns:E,paused:s})}),l(o.Actions,{children:[e(We,{"sentry-label":"ignore open search",testID:"buoy-network-search-open",accessibilityLabel:"Open search",accessibilityRole:"button",onPress:()=>J(true),style:R.headerActionButton,children:e(Je,{size:14,color:d.color.textSecondary})}),e(kt,{paused:s,onPress:()=>U(true)}),T?e(mt,{onPress:()=>z(true)}):null,e(ot,{isEnabled:!s,onToggle:()=>ve(t=>!t),accessibilityLabel:s?"Resume network capture":"Pause network capture",testID:"buoy-network-power"}),e(dt,{paused:s}),e(yt,{onPress:()=>y(t=>!t),isOpen:te,hasIndicator:Y})]})]})};const Y=!!(u.status||u.method||u.contentType);const Le=P?_.modal.root():_.network.modal();if(!r)return null;const ze=p||!v;const fe=l(Bt,{children:[l(B,{style:R.container,children:[e(Ft,{visible:p,paused:s,ignoredPatternValues:Te,onTogglePattern:Be,isPro:a,filter:u,ignoredPatterns:E,fromSaved:D,savedSearch:se,applySafeAreaInset:!c&&ue==="bottomSheet"}),e(xt,{visible:v&&K==="filters"&&!p,paused:s,isPro:a,filter:u,onFilterChange:L,ignoredPatterns:E,onRemovePattern:Me,onAddPattern:Ee,onTogglePatternMode:Fe,isTeamPattern:xe}),e(At,{visible:v&&K==="copy"&&!p,paused:s,isPro:a,filter:u,ignoredPatterns:E,settings:x,onSettingsChange:ae}),e(gt,{visible:T&&V&&!p&&!v&&!F,isPro:a,onUpgradePress:()=>M("overrides"),pendingDraft:Ce,onPendingConsumed:Ve,backHandlerRef:le,applySafeAreaInset:!c&&ue==="bottomSheet"}),e(wt,{visible:F&&!p&&!v,paused:s,isPro:a,onUpgradePress:()=>M("sockets"),backHandlerRef:ce,onTitleChange:Pe}),e(ht,{visible:D&&!p&&!v&&!F&&!(V&&T),isPro:a,copySettings:x,search:se,onSearchChange:Ne,onEventPress:ie,onUpgradePress:()=>M("saved")}),e(ft,{visible:!p&&!v&&!D&&!F&&!(V&&T),paused:s,filter:u,ignoredPatterns:E,isPro:a,searchText:ne,onEventPress:ie,onUpgradePress:()=>M("export")})]}),te?l(vt,{onClose:()=>y(false),children:[e(O,{icon:e(ge,{size:14,color:d.color.textSecondary}),label:"Network throttling",testID:"buoy-network-menu-throttling",onPress:()=>{y(false);he(w?I:void 0);if(!c)oe(t=>t+1)}}),e(O,{icon:e(ge,{size:14,color:d.color.textSecondary}),label:"Speed and link state",testID:"buoy-network-menu-conditions",onPress:()=>{y(false);he(w?I:void 0,true);if(!c)oe(t=>t+1)}}),e(O,{icon:e($e,{size:14,color:Y?d.color.accent:d.color.textSecondary}),label:"Filters",detail:Y?"Active":void 0,onPress:()=>{y(false);re("filters");Z(true)}}),e(O,{icon:e(Ge,{size:14,color:d.color.textSecondary}),label:"Saved requests",onPress:()=>{y(false);ee(true)}}),e(O,{icon:e(Xe,{size:14,color:d.color.textSecondary}),label:"Sockets",testID:"buoy-network-menu-sockets",onPress:()=>{y(false);U(true)}}),e(B,{style:R.menuCopyRow,children:e(pt,{isPro:a,filter:u,ignoredPatterns:E,copySettings:x,paused:s,onUpgradePress:()=>{y(false);M("export")},label:"Copy requests"})})]}):null,e(tt,{visible:G,onClose:()=>X(false),featureName:f==="saved"?"Saved Requests":f==="overrides"?"Response Overrides":f==="sockets"?"Socket Tricks":"Network Export",description:f==="saved"?"Keep the requests that matter. Saved requests survive Clear, app restarts, and the 500-request history cap.":f==="overrides"?"Force any endpoint to fail, stall or return something else \u2014 no backend changes, no code changes. Free keeps one active rule.":f==="sockets"?"Push fake server messages into your app, and drop, freeze or block its sockets. Your app's real code handles each one.":"Export network requests to share with your team, debug APIs, or feed into AI tools.",benefits:f==="sockets"?["Push a fake message, like auth.expired, in one tap","Drop a socket with 1006 or kick it out with 1008","Freeze a socket to test your ping check","Block every reconnect to test your backoff"]:f==="overrides"?[`Run ${Mt} rules at once (free keeps ${Et})`,"Force a 500, a 401 or an empty list in one tap","Simulate offline, timeouts and slow connections","Rules survive an app reload, so you can test the boot path"]:f==="saved"?[`Save up to ${Tt} requests (free keeps ${It})`,"Failed requests stay put through a Clear","Snapshots survive an app restart","Export saved requests to teammates or AI assistants"]:["Export to JSON, Markdown, or plain text","Customizable copy presets (URLs only, LLM-ready, full data)","Share request details with teammates","Feed network data directly to AI assistants"]})]});if(c){return l(B,{style:R.inlineRoot,children:[e(B,{style:R.inlineHeader,...nt,children:pe()}),fe]})}return e(Ye,{visible:r,onClose:h,onMinimize:m,minimizeRequest:be,persistenceKey:Le,variant:"night",header:{showToggleButton:true,customContent:pe()},onModeChange:qe,enablePersistence:true,initialMode:"bottomSheet",enableGlitchEffects:true,disableScrollWrapper:ze,styles:{},children:fe})}const R=Ke.create({container:{flex:1,backgroundColor:"transparent"},detailRoot:{flex:1,minHeight:0},detailBodyFallback:{flex:1},inlineRoot:{flex:1,minHeight:0,backgroundColor:"transparent"},inlineHeader:{paddingHorizontal:12,paddingVertical:8,borderBottomWidth:1,borderBottomColor:Qe.border.default,backgroundColor:"transparent"},menuCopyRow:{paddingHorizontal:6},headerActionButton:{width:32,height:32,borderRadius:8,backgroundColor:d.color.buttonSurface,borderWidth:1,borderColor:d.color.border,alignItems:"center",justifyContent:"center"},activeFilterButton:{backgroundColor:d.color.accentSoft,borderColor:d.color.accentBorderStrong}});export function NetworkModal(r){return e(Se,{children:e(we,{...r})})}export function NetworkToolView(r={}){return e(Se,{children:e(we,{...r,inline:true,visible:true,onClose:Ot})})}const Ot=()=>{};
@@ -0,0 +1 @@
1
+ "use strict";import{StyleSheet as d,Text as g,TouchableOpacity as u,View as p}from"react-native";import{Activity as h,night as o}from"@buoy-gg/shared-ui";import{useSocketsState as f}from"../../hooks/useSocketsState";import{jsx as c,jsxs as m}from"react/jsx-runtime";export function NetworkSocketsButton({onPress:i,paused:l}){const t=f(l);if(t.connections.length===0)return null;const r=t.connections.some(b=>b.state==="open");const s=t.tests.blocked||t.tests.offline||t.tests.frozen.length>0;const e=t.problems.length;const a=s?o.color.warning:r?o.color.accent:o.color.textSecondary;return m(u,{onPress:i,"sentry-label":"ignore open sockets",testID:"buoy-network-sockets",accessibilityRole:"button",accessibilityLabel:`Sockets${r?", one open":""}${e?`, ${e} ${e===1?"problem":"problems"}`:""}${s?", a trick is on":""}`,style:[n.button,s?n.testing:r?n.open:null],children:[c(h,{size:14,color:a}),e>0?c(p,{style:n.badge,children:c(g,{style:n.badgeText,children:e})}):null]})}const n=d.create({button:{width:32,height:32,borderRadius:8,alignItems:"center",justifyContent:"center",backgroundColor:o.color.buttonSurface,borderWidth:1,borderColor:o.color.border},open:{backgroundColor:o.color.accentSoft,borderColor:o.color.accentBorder},testing:{backgroundColor:o.color.warningSoft,borderColor:o.color.warning+"77"},badge:{position:"absolute",top:1,right:1,minWidth:12,height:12,borderRadius:6,paddingHorizontal:3,alignItems:"center",justifyContent:"center",backgroundColor:o.color.danger},badgeText:{fontSize:8,fontWeight:"800",color:"#FFFFFF"}});
@@ -0,0 +1 @@
1
+ "use strict";import{useEffect as l,useState as d}from"react";import{StyleSheet as x,View as w}from"react-native";import{SocketFrameView as I}from"./SocketFrameView";import{SocketListView as j}from"./SocketListView";import{SocketTricksView as F}from"./SocketTricksView";import{jsx as m,jsxs as T}from"react/jsx-runtime";export function NetworkSocketsScreen({visible:o,paused:k,isPro:i,onUpgradePress:c,backHandlerRef:s,onTitleChange:a}){const[e,u]=d(null);const[t,n]=d(null);const f=t?"Tricks":e?"Message":"Sockets";l(()=>{a?.(f)},[a,f]);l(()=>{if(!s)return;s.current=t||e?()=>{if(t)n(null);else u(null);return true}:null;return()=>{s.current=null}},[s,t,e]);l(()=>{if(o)return;u(null);n(null)},[o]);const p=r=>{if(!i)return c();n({socketId:r,data:""})};const S=r=>n({socketId:r.socketId,data:r.data??""});if(!o)return null;return T(w,{style:V.container,children:[m(j,{visible:!t&&!e,paused:k,search:"",onOpenFrame:r=>u(r.id),onOpenTricks:p}),m(I,{visible:!t&&!!e,frameId:e,isPro:i,onUpgradePress:c,onEdit:S}),m(F,{visible:!!t,draft:t,isPro:i,onUpgradePress:c})]})}const V=x.create({container:{flex:1}});
@@ -0,0 +1 @@
1
+ "use strict";import{useEffect as B,useState as z}from"react";import{ScrollView as W,StyleSheet as C,Text as r,View as f}from"react-native";import{InlineCopyButton as j,NightBadge as s,NightButton as F,monoFont as g,night as l}from"@buoy-gg/shared-ui";import{clockTime as H,prettyData as R,shortDuration as I}from"../../sockets/format";import{socketStore as S}from"../../sockets/socketStore";import{jsx as e,jsxs as p}from"react/jsx-runtime";function T({frame:n,label:i}){const c=R(n);return p(f,{style:o.box,children:[p(f,{style:o.boxHead,children:[e(r,{style:o.boxLabel,children:i}),e(r,{style:o.boxTime,children:H(n.timestamp)}),e(j,{value:c})]}),e(r,{selectable:true,style:o.code,testID:`buoy-socket-data-${n.id}`,children:c||"(empty)"}),n.truncated?e(r,{style:o.boxNote,children:"Cut at 64 KB. The rest was not kept."}):null]})}function N({visible:n}){if(!n)return null;return e(f,{style:o.missing,children:e(r,{style:o.note,children:"This message is gone. It was cleared or pushed out by newer ones."})})}function $({loaded:n,isPro:i,onUpgradePress:c,onEdit:k}){const[b,h]=z(null);const t=n?.frame;B(()=>h(null),[t?.id]);if(!t)return null;const y=t.direction==="out";const m=n?.partner??null;const a=t.replyTo?m:t;const d=t.replyTo?t:m;const u=S.getState().problems.find(x=>x.frameIds.includes(t.id));const w=async()=>{if(!i)return c();const x=t.data??"";const D=await S.act(y?{action:"send",socketId:t.socketId,data:x}:{action:"inject",socketId:t.socketId,data:x});h(D.message)};return p(W,{contentContainerStyle:o.content,testID:"buoy-socket-detail",children:[p(f,{style:o.titleRow,children:[e(r,{style:[o.dir,y?o.up:o.down],children:y?"\u2191":"\u2193"}),e(r,{style:o.title,numberOfLines:2,children:t.type??"message"})]}),p(f,{style:o.badges,children:[u?e(s,{label:u.kind==="no-reply"?"No reply":"Problem",tone:"danger"}):null,a?.replyMs!==void 0?e(s,{label:`Reply in ${I(a.replyMs)}`,tone:"accent"}):null,t.correlationId?e(s,{label:`id ${t.correlationId}`,tone:"info"}):null,e(s,{label:`Socket ${t.socketId}`}),t.size!==void 0?e(s,{label:`${t.size} B`}):null,t.fake==="inject"?e(s,{label:"Fake: pushed by Buoy",tone:"info"}):null,t.fake==="send"?e(s,{label:"Sent by Buoy",tone:"info"}):null,t.held?e(s,{label:"Held back",tone:"warning"}):null,t.sentWhileClosed?e(s,{label:"Sent while closed",tone:"danger"}):null]}),a?e(T,{frame:a,label:a.direction==="out"?"\u2191 Sent":"\u2193 Got"}):null,a&&d?e(r,{style:o.gap,children:I(d.timestamp-a.timestamp)}):null,d?e(T,{frame:d,label:"\u2193 Reply"}):null,p(f,{style:o.buttons,children:[e(F,{label:y?"Send again":"Push to app again",variant:"primary",onPress:w,testID:"buoy-socket-replay"}),e(F,{label:"Edit in Tricks",onPress:()=>i?k(t):c(),testID:"buoy-socket-edit"})]}),u?e(r,{style:o.problem,children:u.message}):null,b?e(r,{style:o.result,children:b}):null,t.data?.includes("[hidden]")?e(r,{style:o.note,children:"Buoy hid secrets in this message. Sending it again sends the word [hidden] in their place."}):null]})}export function SocketFrameView({visible:n,frameId:i,isPro:c,onUpgradePress:k,onEdit:b}){const[h,t]=z(null);const[y,m]=z(false);B(()=>{t(null);m(false);if(!n||!i)return;let u=true;void S.loadFrame(i).then(w=>{if(!u)return;t(w);m(true)});return()=>{u=false}},[n,i]);if(!n)return null;const a=i?S.getFrame(i):void 0;const d=h??(a?{frame:a,partner:null}:null);return p(f,{style:o.fill,children:[e(N,{visible:y&&!d}),e($,{loaded:d,isPro:c,onUpgradePress:k,onEdit:b})]})}const o=C.create({fill:{flex:1},content:{padding:12,gap:10,paddingBottom:32},missing:{padding:24},titleRow:{flexDirection:"row",alignItems:"center",gap:8},dir:{fontSize:16,fontWeight:"700",fontFamily:g},up:{color:"#6EA1FF"},down:{color:l.color.accent},title:{flexShrink:1,fontSize:15,fontWeight:"600",color:l.color.text,fontFamily:g},badges:{flexDirection:"row",flexWrap:"wrap",gap:6},box:{borderWidth:1,borderColor:l.color.border,borderRadius:8,backgroundColor:l.color.surface,overflow:"hidden"},boxHead:{flexDirection:"row",alignItems:"center",gap:8,paddingHorizontal:9,paddingVertical:6,borderBottomWidth:1,borderBottomColor:l.color.separator},boxLabel:{flex:1,fontSize:10,fontWeight:"700",color:l.color.textSecondary,letterSpacing:.4},boxTime:{fontSize:10,color:l.color.textTertiary,fontFamily:g},boxNote:{paddingHorizontal:9,paddingBottom:8,fontSize:11,color:l.color.textTertiary},code:{padding:9,fontSize:11,lineHeight:16,color:l.color.text,fontFamily:g},gap:{textAlign:"center",fontSize:11,color:l.color.textSecondary,fontFamily:g},buttons:{flexDirection:"row",flexWrap:"wrap",gap:8},result:{fontSize:12,color:l.color.textSecondary},problem:{fontSize:12,color:l.color.danger,fontWeight:"600"},note:{fontSize:11,color:l.color.textTertiary}});
@@ -0,0 +1 @@
1
+ "use strict";import{useEffect as H,useState as h}from"react";import{FlatList as _,ScrollView as A,StyleSheet as F,Text as d,TouchableOpacity as z,View as u}from"react-native";import{EVENT_LIST_PRESET as M,NightChip as m,ToolEmptyState as V,Zap as j,monoFont as U,night as i,resolveListEmptyState as J}from"@buoy-gg/shared-ui";import{useSocketsState as G}from"../../hooks/useSocketsState";import{foldFrames as X,topTypePrefixes as Z}from"../../sockets/foldFrames";import{clockTime as q,connectionStatus as D,shortUrl as K}from"../../sockets/format";import{SocketLifecycleRow as Q,SocketMessageRow as Y}from"./SocketRows";import{jsx as n,jsxs as c}from"react/jsx-runtime";const ee=2;const te=2*6e4;const oe=o=>o.frame.id;function le(o){const[p,r]=h(Date.now);H(()=>{if(!o)return;r(Date.now());const s=setInterval(()=>r(Date.now()),1e3);return()=>clearInterval(s)},[o]);return p}function ne({conn:o,selected:p,onPress:r,showPings:s,onTogglePings:f}){const l=o.state==="open";const a=le(l);const y=l?t.pillOk:o.state==="closed"?t.pillWarn:t.pillPlain;const g=l?t.pillOkText:o.state==="closed"?t.pillWarnText:t.pillPlainText;return c(z,{activeOpacity:.8,onPress:r,"sentry-label":"ignore pick socket",testID:`buoy-socket-card-${o.id}`,accessibilityRole:"button",accessibilityLabel:`Socket ${o.id}, ${D(o,a)}`,style:[t.card,p?t.cardSelected:null],children:[n(d,{style:t.cardUrl,numberOfLines:1,children:K(o.url)}),c(u,{style:t.pills,children:[n(u,{style:[t.pill,y],children:c(d,{style:[t.pillText,g],children:[l?"\u25CF ":"",D(o,a)]})}),o.frozen?n(u,{style:[t.pill,t.pillWarn],children:n(d,{style:[t.pillText,t.pillWarnText],children:"Frozen"})}):null,o.attempt>1?n(u,{style:[t.pill,t.pillPlain],children:c(d,{style:[t.pillText,t.pillPlainText],children:["Try #",o.attempt]})}):null,n(u,{style:[t.pill,t.pillPlain],children:c(d,{style:[t.pillText,t.pillPlainText],children:["\u2191",o.sent," \u2193",o.received]})}),o.pings>0?n(z,{onPress:f,"sentry-label":"ignore toggle socket pings",testID:`buoy-socket-pings-${o.id}`,style:[t.pill,t.pillPlain],children:c(d,{style:[t.pillText,t.pillPlainText],children:["\u2665 ",o.pings," ",o.pings===1?"heartbeat":"heartbeats"," ",s?"shown":"hidden"]})}):null]})]})}function se({problems:o}){const p=Date.now();const r=o.filter(s=>p-s.at<te&&(s.frameIds.length===0||s.kind==="reconnect-storm"||s.kind==="auth-loop"||s.kind==="cant-connect"));if(r.length===0)return null;return n(u,{style:t.banner,testID:"buoy-socket-problems",children:r.slice(0,3).map(s=>c(d,{style:t.bannerText,numberOfLines:2,children:["\u26A0 ",s.message," \xB7 ",q(s.at)]},`${s.kind}-${s.at}`))})}export function SocketListView({visible:o,paused:p,search:r,onOpenFrame:s,onOpenTricks:f}){const l=G(p||!o);const[a,y]=h(null);const[g,x]=h({kind:"all"});const[S,N]=h(false);const[T,O]=h(()=>new Set);if(!o)return null;const P=l.connections.filter(e=>e.state!=="closed");const w=l.connections.find(e=>e.id===a&&e.state==="closed");const I=P.length?P:l.connections.filter(e=>e.state==="closed").slice(0,1);const E=[...w&&!I.includes(w)?[w]:[],...I].slice(0,ee);const W=X(l,{socketId:a,filter:g,showPings:S,search:r,expanded:T});const L=e=>O(new Set(T).add(e));const $=new Map(l.connections.map(e=>[e.id,e.attempt]));const R=Z(l.frames);const C=new Set(l.problems.flatMap(e=>e.frameIds)).size;const b=e=>JSON.stringify(e)===JSON.stringify(g);const k=e=>x(b(e)?{kind:"all"}:e);const v=({item:e})=>e.frame.kind==="message"?n(Y,{row:e,onOpen:s,onExpand:L}):n(Q,{row:e,attempt:$.get(e.frame.socketId)});const B=c(u,{style:t.header,children:[E.map(e=>n(ne,{conn:e,selected:a===e.id,onPress:()=>y(a===e.id?null:e.id),showPings:S,onTogglePings:()=>N(!S)},e.id)),n(se,{problems:l.problems}),c(A,{horizontal:true,showsHorizontalScrollIndicator:false,contentContainerStyle:t.chips,children:[n(m,{label:"Tricks",icon:n(j,{size:11,color:i.color.warning}),onPress:()=>f(a??l.connections.find(e=>e.state==="open")?.id??null),testID:"buoy-socket-tricks"}),n(m,{label:`All ${l.frames.length}`,selected:g.kind==="all",onPress:()=>x({kind:"all"}),testID:"buoy-socket-chip-all"}),C>0?n(m,{label:`Problems ${C}`,selected:g.kind==="problems",onPress:()=>k({kind:"problems"}),testID:"buoy-socket-chip-problems"}):null,n(m,{label:"\u2191 Sent",selected:b({kind:"direction",direction:"out"}),onPress:()=>k({kind:"direction",direction:"out"}),testID:"buoy-socket-chip-sent"}),n(m,{label:"\u2193 Got",selected:b({kind:"direction",direction:"in"}),onPress:()=>k({kind:"direction",direction:"in"}),testID:"buoy-socket-chip-got"}),R.map(e=>n(m,{label:e.match(/[.:/]$/)?`${e}*`:e,selected:b({kind:"type",prefix:e}),onPress:()=>k({kind:"type",prefix:e}),testID:`buoy-socket-chip-type-${e}`},e))]}),l.tests.blocked||l.tests.offline||l.tests.frozen.length>0?n(d,{style:t.testNote,numberOfLines:1,children:l.tests.offline?"Offline mode is on":l.tests.blocked?"New sockets are blocked":"A socket is frozen"}):null]});return n(_,{...M,testID:"buoy-socket-list",accessibilityLabel:"Socket messages",data:W,renderItem:v,keyExtractor:oe,ListHeaderComponent:B,ListEmptyComponent:n(V,{testID:"buoy-socket-empty",...J({subject:"messages",search:r,total:l.frames.length,capturing:l.capturingSince!==null||l.connections.length>0,waiting:{otto:"fishing",title:"No socket messages",message:"Messages show here when your app opens a WebSocket."},paused:{title:"Not watching sockets",message:"Buoy watches sockets in dev builds once the Network tool loads."}})}),contentContainerStyle:t.listContent,keyboardShouldPersistTaps:"handled",showsVerticalScrollIndicator:true})}const t=F.create({listContent:{paddingBottom:24},header:{gap:6,paddingTop:8,paddingBottom:4},card:{marginHorizontal:10,padding:9,gap:6,borderRadius:10,borderWidth:1,borderColor:i.color.border,backgroundColor:i.color.surface},cardSelected:{borderColor:i.color.accentBorderStrong,backgroundColor:i.color.accentSoft},cardUrl:{fontSize:11,color:i.color.text,fontFamily:U},pills:{flexDirection:"row",flexWrap:"wrap",gap:5},pill:{paddingHorizontal:6,paddingVertical:2,borderRadius:5},pillText:{fontSize:10,fontWeight:"600"},pillOk:{backgroundColor:i.color.accentSoft},pillOkText:{color:i.color.accent},pillWarn:{backgroundColor:i.color.warningSoft},pillWarnText:{color:i.color.warning},pillPlain:{backgroundColor:i.color.fill},pillPlainText:{color:i.color.textSecondary},banner:{marginHorizontal:10,padding:8,gap:3,borderRadius:8,backgroundColor:i.color.dangerSoft,borderWidth:1,borderColor:"rgba(255,59,48,0.3)"},bannerText:{fontSize:11,color:i.color.danger,fontWeight:"600"},chips:{gap:6,paddingHorizontal:10},testNote:{paddingHorizontal:12,fontSize:11,color:i.color.warning,fontWeight:"600"}});
@@ -0,0 +1 @@
1
+ "use strict";import{StyleSheet as f,Text as a,TouchableOpacity as S,View as c}from"react-native";import{monoFont as p,night as t}from"@buoy-gg/shared-ui";import{clockTime as y,closeLabel as L,previewText as T,shortDuration as C}from"../../sockets/format";import{jsx as i,jsxs as s}from"react/jsx-runtime";const m="#6EA1FF";function h({label:o,tone:l}){return i(c,{style:[n.tag,k[l].box],children:i(a,{style:[n.tagText,k[l].text],numberOfLines:1,children:o})})}function w(o){const l=o.frame;const e=[];if(o.problem)e.push({label:x[o.problem.kind],tone:"bad"});if(l.replyMs!==void 0)e.push({label:`\u2713 ${C(l.replyMs)}`,tone:"ok"});if(l.fake==="inject")e.push({label:"Fake",tone:"info"});if(l.fake==="send")e.push({label:"Buoy sent",tone:"info"});if(l.held)e.push({label:"Held",tone:"warn"});if(l.sentWhileClosed)e.push({label:"Closed",tone:"bad"});return e}const x={"no-reply":"No reply","reconnect-storm":"Storm","auth-loop":"Sign-in loop","cant-connect":"Can't connect","two-sockets":"Two sockets","sent-while-closed":"Sent while closed"};export function SocketMessageRow({row:o,onOpen:l,onExpand:e}){const r=o.frame;const b=r.direction==="out";const d=r.type??(r.binary?"binary":"message");const g=o.count>1&&o.foldKey!==void 0;return s(S,{activeOpacity:.7,onPress:()=>g?e(o.foldKey):l(r),"sentry-label":"ignore open socket message",testID:`buoy-socket-row-${r.id}`,accessibilityRole:"button",accessibilityLabel:g?`${o.count} ${d} messages, tap to show each`:`${b?"Sent":"Got"} ${d}`,style:[n.row,o.problem?n.rowProblem:null],children:[i(a,{style:[n.dir,{color:b?m:t.color.accent}],children:b?"\u2191":"\u2193"}),s(c,{style:n.middle,children:[s(c,{style:n.titleLine,children:[i(a,{style:n.type,numberOfLines:1,children:d}),o.count>1?i(h,{label:`\xD7${o.count}`,tone:"plain"}):null]}),s(a,{style:n.preview,numberOfLines:1,children:[r.correlationId?`${r.correlationId} \xB7 `:"",T(r)]})]}),s(c,{style:n.right,children:[i(c,{style:n.tags,children:w(o).slice(0,2).map(u=>i(h,{label:u.label,tone:u.tone},u.label))}),i(a,{style:n.time,children:y(r.timestamp)})]})]})}export function SocketLifecycleRow({row:o,attempt:l}){const e=o.frame;const r=e.kind==="open"?`Open${l&&l>1?` #${l}`:""}`:e.kind==="error"?"Error":L(e.code,e.neverOpened);const b=e.byBuoy&&!/buoy/i.test(e.reason??"")?"by Buoy":null;const d=[o.problem?`\u26A0 ${x[o.problem.kind]}`:null,e.kind==="close"?e.reason:null,e.kind==="close"?b:null].filter(Boolean).join(" \xB7 ");const g=o.problem||e.kind==="error"?t.color.danger:e.kind==="open"?t.color.accent:t.color.warning;return s(c,{style:n.life,testID:`buoy-socket-life-${e.id}`,children:[i(c,{style:n.lifeLine}),s(a,{style:n.lifeText,numberOfLines:1,children:[i(a,{style:[n.lifeLabel,{color:g}],children:r}),d?` \xB7 ${d}`:""," \xB7 ",y(e.timestamp)]}),i(c,{style:n.lifeLine})]})}const k={ok:f.create({box:{backgroundColor:t.color.accentSoft},text:{color:t.color.accent}}),bad:f.create({box:{backgroundColor:t.color.dangerSoft},text:{color:t.color.danger}}),warn:f.create({box:{backgroundColor:t.color.warningSoft},text:{color:t.color.warning}}),info:f.create({box:{backgroundColor:t.color.infoSoft},text:{color:m}}),plain:f.create({box:{backgroundColor:t.color.fill},text:{color:t.color.textSecondary}})};const n=f.create({row:{flexDirection:"row",alignItems:"center",gap:8,paddingVertical:7,paddingHorizontal:10,marginHorizontal:8,backgroundColor:"rgba(12, 12, 12, 0.9)",borderBottomWidth:1,borderBottomColor:t.color.separator,borderLeftWidth:3,borderLeftColor:"transparent"},rowProblem:{borderLeftColor:t.color.danger,backgroundColor:"rgba(40, 12, 12, 0.9)"},dir:{width:14,fontSize:13,fontWeight:"700",fontFamily:p,textAlign:"center"},middle:{flex:1,minWidth:0,gap:1},titleLine:{flexDirection:"row",alignItems:"center",gap:6},type:{flexShrink:1,fontSize:12,fontWeight:"600",color:t.color.text,fontFamily:p},preview:{fontSize:10,color:t.color.textTertiary,fontFamily:p},right:{alignItems:"flex-end",gap:3},tags:{flexDirection:"row",gap:4},tag:{paddingHorizontal:5,paddingVertical:1,borderRadius:4},tagText:{fontSize:9.5,fontWeight:"700"},time:{fontSize:9,color:t.color.textTertiary,fontFamily:p},life:{flexDirection:"row",alignItems:"center",gap:8,paddingVertical:6,paddingHorizontal:12},lifeLine:{flex:1,height:1,backgroundColor:t.color.separator},lifeText:{fontSize:10.5,color:t.color.textSecondary,flexShrink:1},lifeLabel:{fontWeight:"700"}});
@@ -0,0 +1 @@
1
+ "use strict";import{useEffect as z,useState as f}from"react";import{ScrollView as C,StyleSheet as R,Text as s,TextInput as W,TouchableOpacity as v,View as i}from"react-native";import{NightButton as k,NightChip as B,NightSectionLabel as g,NightSwitch as x,monoFont as P,night as r}from"@buoy-gg/shared-ui";import{useSocketsState as j}from"../../hooks/useSocketsState";import{shortUrl as N}from"../../sockets/format";import{socketStore as O}from"../../sockets/socketStore";import{jsx as e,jsxs as n}from"react/jsx-runtime";const V=[{code:1006,title:"Drop it",detail:"1006 \xB7 like lost signal",testID:"buoy-socket-drop"},{code:1008,title:"Kick out",detail:"1008 \xB7 like a bad token",testID:"buoy-socket-kick"},{code:1001,title:"Server going away",detail:"1001 \xB7 like a deploy",testID:"buoy-socket-going-away"}];export function SocketTricksView({visible:u,draft:p,isPro:S,onUpgradePress:D}){const a=j(!u);const[I,b]=f(null);const[d,w]=f("");const[y,m]=f(null);z(()=>{if(!u||!p)return;b(p.socketId);w(p.data);m(null)},[u,p]);if(!u)return null;const h=a.connections.filter(o=>o.state==="open"||o.state==="connecting");const l=h.find(o=>o.id===I)??h[0]??null;const c=async o=>{if(!S)return D();m(await O.act(o))};const T=a.tests.blocked||a.tests.frozen.length>0;return n(C,{contentContainerStyle:t.content,keyboardShouldPersistTaps:"handled",testID:"buoy-socket-tricks-screen",children:[e(s,{style:t.lede,children:"Make the socket misbehave on purpose. Your app's real code handles each one."}),e(g,{children:"Socket"}),h.length===0?e(s,{style:t.note,children:"No socket is open. Open one in your app, or turn Block off."}):null,h.length>0?e(i,{style:t.chips,children:h.map(o=>e(B,{label:`${o.id} \xB7 ${N(o.url)}`,selected:l?.id===o.id,onPress:()=>b(o.id),testID:`buoy-socket-target-${o.id}`},o.id))}):null,e(g,{children:"Message"}),e(W,{value:d,onChangeText:w,multiline:true,autoCapitalize:"none",autoCorrect:false,placeholder:'{"type":"chat.message","payload":{"text":"hi"}}',placeholderTextColor:r.color.placeholder,style:t.input,testID:"buoy-socket-message-input",accessibilityLabel:"Message to push or send"}),n(i,{style:t.row,children:[e(k,{label:"Push to app",variant:"primary",disabled:!l||!d.trim(),onPress:()=>l&&c({action:"inject",socketId:l.id,data:d}),testID:"buoy-socket-inject"}),e(k,{label:"Send to server",disabled:!l||!d.trim(),onPress:()=>l&&c({action:"send",socketId:l.id,data:d}),testID:"buoy-socket-send"})]}),e(g,{children:"Break the socket"}),e(i,{style:t.grid,children:V.map(o=>n(v,{disabled:!l,onPress:()=>l&&c({action:"close",socketId:l.id,code:o.code}),"sentry-label":"ignore socket break",testID:o.testID,accessibilityRole:"button",style:[t.cell,!l?t.cellOff:null],children:[e(s,{style:t.cellTitle,children:o.title}),e(s,{style:t.cellDetail,children:o.detail})]},o.code))}),e(s,{style:t.note,children:'On iOS, a real lost link often closes as 1001 "Stream end encountered", not 1006. Check for both.'}),n(i,{style:t.switchRow,children:[n(i,{style:t.switchText,children:[e(s,{style:t.switchTitle,children:"Freeze"}),e(s,{style:t.cellDetail,children:"Looks open, but nothing gets through. Tests your app's ping check."})]}),e(x,{value:!!l?.frozen,disabled:!l,onValueChange:o=>l&&c({action:"freeze",socketId:l.id,frozen:o}),testID:"buoy-socket-freeze"})]}),n(i,{style:t.switchRow,children:[n(i,{style:t.switchText,children:[e(s,{style:t.switchTitle,children:"Block"}),e(s,{style:t.cellDetail,children:"Drops open sockets, and every new one fails. Tests your backoff."})]}),e(x,{value:a.tests.blocked,onValueChange:o=>c({action:"block",blocked:o}),testID:"buoy-socket-block"})]}),a.tests.offline?e(s,{style:t.warn,children:"Network's offline mode is on, so sockets act offline too."}):null,e(i,{style:t.row,children:e(k,{label:"Reset all",variant:"tertiary",disabled:!T,onPress:()=>c({action:"reset"}),testID:"buoy-socket-reset"})}),y?e(s,{style:[t.result,y.ok?null:t.warn],testID:"buoy-socket-result",children:y.message}):null]})}const t=R.create({content:{padding:12,gap:10,paddingBottom:40},lede:{fontSize:12,color:r.color.textSecondary},note:{fontSize:12,color:r.color.textTertiary},chips:{flexDirection:"row",flexWrap:"wrap",gap:6},input:{minHeight:96,padding:10,borderRadius:8,borderWidth:1,borderColor:r.color.border,backgroundColor:r.color.surface,color:r.color.text,fontFamily:P,fontSize:12,textAlignVertical:"top"},row:{flexDirection:"row",flexWrap:"wrap",gap:8},grid:{flexDirection:"row",flexWrap:"wrap",gap:8},cell:{flexGrow:1,flexBasis:"45%",padding:9,gap:2,borderRadius:8,borderWidth:1,borderColor:r.color.border,backgroundColor:r.color.surface},cellOff:{opacity:.4},cellTitle:{fontSize:12,fontWeight:"700",color:r.color.text},cellDetail:{fontSize:10.5,color:r.color.textTertiary},switchRow:{flexDirection:"row",alignItems:"center",gap:10},switchText:{flex:1,gap:2},switchTitle:{fontSize:13,fontWeight:"600",color:r.color.text},warn:{fontSize:12,color:r.color.warning,fontWeight:"600"},result:{fontSize:12,color:r.color.textSecondary}});
@@ -1 +1 @@
1
- "use strict";import{useEffect as O,useRef as N,useState as w,useSyncExternalStore as I}from"react";import{ActivityIndicator as V,StyleSheet as $,Text as i,TouchableOpacity as k,View as S}from"react-native";import{ChevronDown as _,Check as J,night as t}from"@buoy-gg/shared-ui";import{conditionsCanApply as W,getNetworkCondition as A,setNetworkCondition as X,subscribeNetworkConditions as R,getNetworkConditions as M,getConditionsRevision as K,setNetworkConditions as Q}from"./store";import{jsx as n,jsxs as h}from"react/jsx-runtime";const L=[{profile:"normal",label:"No throttling"},{profile:"slow",label:"Slow"},{profile:"verySlow",label:"Very slow"},{profile:"offline",label:"Offline"},{profile:"slow3g",label:"Slow 3G"},{profile:"slow4g",label:"Slow 4G"},{profile:"fast4g",label:"Fast 4G"}];const j={normal:"No added delay",slow:"+500 ms before each new request",verySlow:"+2 seconds before each new request",offline:"New requests fail before sending",slow3g:"50 KB/s down, 50 KB/s up; +2000 ms",slow4g:"180 KB/s down, 84.375 KB/s up; +562.5 ms",fast4g:"1012.5 KB/s down, 168.75 KB/s up; +165 ms"};export function NetworkConditionsControl({remote:r,compact:P=false}){I(R,K,K);const l=r?r.state:M();const[U,T]=w(false);const q=I(R,A,A);const F=I(R,W,W);const[C,m]=w(false);const[E,y]=w();const[c,g]=w(false);const u=N(false);const p=N(true);const d=N(0);O(()=>{d.current++;u.current=false;g(false);y(void 0)},[r?.targetId]);O(()=>{p.current=true;return()=>{p.current=false}},[]);const f=r?r.profile:q;const s=r?r.available:F;const z=l?.active??(f!==null&&f!=="normal");const v=f==="offline"?t.color.danger:z?t.color.warning:t.color.accent;async function G(o){if(!s||u.current)return;if(o===f&&(o!=="normal"||!l?.active)){m(false);return}const a=++d.current;u.current=true;g(true);y(void 0);try{if(r)await r.onChange(o);else X(o);if(p.current&&d.current===a)m(false)}catch(b){if(p.current&&d.current===a)y(b instanceof Error?b.message:String(b))}finally{if(d.current===a){u.current=false;if(p.current)g(false)}}}const D=[["auto","Follow speed"],["real","Real link"],["offline","Offline"],["wifi","Wi-Fi"],["cellular","Cellular"],["noInternet","No internet"]];const B=(!r||!!r.onConnectionChange)&&(l?.capabilities.netInfo.supported||l?.capabilities.expoNetwork.supported);const H=L.find(o=>o.profile===f)?.label??"Unavailable";return h(S,{style:e.container,testID:"buoy-network-throttling-screen",children:[n(i,{style:e.heading,children:"Connection profile"}),h(k,{testID:"buoy-network-conditions",accessibilityRole:"button",accessibilityLabel:`Network throttling: ${H}`,accessibilityState:{expanded:C,disabled:!s||c},disabled:!s||c,onPress:()=>m(o=>!o),style:[e.dropdown,C&&e.dropdownOpen,!s&&e.disabled],children:[n(i,{style:[e.value,z&&{color:v}],children:H}),c?n(V,{size:"small",color:t.color.textSecondary}):n(_,{size:16,color:t.color.textSecondary})]}),C&&n(S,{accessibilityRole:"radiogroup",accessibilityLabel:"Connection profile",style:e.options,children:L.map(o=>{const a=f===o.profile;return h(k,{testID:`buoy-network-condition-${o.profile}`,accessibilityRole:"radio",accessibilityLabel:o.label,accessibilityState:{checked:a,disabled:!s||c},disabled:!s||c,onPress:()=>void G(o.profile),style:[e.option,a&&e.selected],children:[h(S,{style:e.optionBody,children:[n(i,{style:[e.optionTitle,a&&{color:v}],children:o.label}),n(i,{style:e.caption,children:j[o.profile]})]}),a&&n(J,{size:16,color:v})]},o.profile)})}),n(i,{style:e.caption,accessibilityLiveRegion:"polite",children:c?"Applying to device\u2026":!s?r?"Conditions unavailable on this device":"Requires a signed-in account and a development build":f?j[f]:"Waiting for device status"}),!!E&&n(i,{accessibilityRole:"alert",style:e.error,children:E}),n(k,{testID:"buoy-network-link-state",accessibilityRole:"button",accessibilityLabel:"App link state",disabled:!s||c||!B,onPress:()=>T(o=>!o),style:e.dropdown,children:h(i,{style:e.value,children:["App link: ",D.find(([o])=>o===l?.connection)?.[1]??"Unavailable"]})}),U&&D.map(([o,a])=>n(k,{testID:`buoy-network-link-${o}`,accessibilityRole:"radio",accessibilityState:{checked:l?.connection===o,disabled:c||!s},disabled:c||!s,style:e.option,onPress:async()=>{if(u.current)return;const b=++d.current;u.current=true;g(true);y(void 0);try{if(r)await r.onConnectionChange?.(o);else Q({connection:o});if(p.current&&d.current===b)T(false)}catch(x){if(p.current&&d.current===b)y(x instanceof Error?x.message:String(x))}finally{if(d.current===b){u.current=false;if(p.current)g(false)}}},children:n(i,{style:e.optionTitle,children:a})},o)),!B&&n(i,{style:e.caption,children:l?.capabilities.netInfo.reason??"This device has no link hook."}),!P&&h(S,{style:e.help,children:[n(i,{style:e.heading,children:"How it works"}),l&&h(i,{style:e.caption,children:["NetInfo: ",l.capabilities.netInfo.supported?"Hook on":l.capabilities.netInfo.reason??"No hook",". Expo Network: ",l.capabilities.expoNetwork.supported?"Hook on":l.capabilities.expoNetwork.reason??"No hook","."]}),n(i,{style:e.caption,children:"Down caps pace bytes to the app in JS. The socket stays at its real speed."}),n(i,{style:e.caption,children:"Up caps wait before send for known bytes. Upload time is simulated. The socket is not paced. Unknown sizes pass through with latency only. Each call shows any cap gap."}),n(i,{style:e.caption,children:"Caps apply per call through global fetch and RN XHR. WebSocket, native images, native SDKs and file transfers are not affected."}),n(i,{style:e.caption,children:"Link state changes what NetInfo and Expo Network report. It does not change the radio or web calls."}),n(i,{style:e.caption,children:"Stays on when this tool closes or capture pauses. No throttling clears both controls. App reload clears them too."})]})]})}const e=$.create({container:{padding:t.gutter,gap:10},heading:{fontSize:t.font.caption,fontWeight:"600",color:t.color.textSecondary},dropdown:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:12,minHeight:44,paddingHorizontal:12,paddingVertical:10,borderRadius:t.radius.segment,borderWidth:1,borderColor:t.color.separator,backgroundColor:t.color.surfaceElevated},dropdownOpen:{borderColor:t.color.accentBorderStrong},value:{flex:1,fontSize:t.font.body,color:t.color.text},options:{padding:4,borderRadius:t.radius.row,borderWidth:1,borderColor:t.color.border,backgroundColor:t.color.surface},option:{flexDirection:"row",alignItems:"center",gap:12,minHeight:54,padding:10,borderRadius:t.radius.segment},optionBody:{flex:1,gap:4},optionTitle:{fontSize:t.font.caption,fontWeight:"600",color:t.color.text},selected:{backgroundColor:t.color.surfaceElevated},disabled:{opacity:.45},caption:{fontSize:t.font.caption,lineHeight:19,color:t.color.textSecondary},help:{marginTop:14,paddingTop:16,gap:10,borderTopWidth:1,borderTopColor:t.color.separator},error:{fontSize:t.font.caption,lineHeight:18,color:t.color.danger}});
1
+ "use strict";import{useEffect as O,useRef as N,useState as w,useSyncExternalStore as I}from"react";import{ActivityIndicator as V,StyleSheet as $,Text as i,TouchableOpacity as k,View as S}from"react-native";import{ChevronDown as _,Check as J,night as t}from"@buoy-gg/shared-ui";import{conditionsCanApply as W,getNetworkCondition as A,setNetworkCondition as X,subscribeNetworkConditions as R,getNetworkConditions as M,getConditionsRevision as K,setNetworkConditions as Q}from"./store";import{jsx as n,jsxs as h}from"react/jsx-runtime";const L=[{profile:"normal",label:"No throttling"},{profile:"slow",label:"Slow"},{profile:"verySlow",label:"Very slow"},{profile:"offline",label:"Offline"},{profile:"slow3g",label:"Slow 3G"},{profile:"slow4g",label:"Slow 4G"},{profile:"fast4g",label:"Fast 4G"}];const j={normal:"No added delay",slow:"+500 ms before each new request",verySlow:"+2 seconds before each new request",offline:"New requests fail before sending",slow3g:"50 KB/s down, 50 KB/s up; +2000 ms",slow4g:"180 KB/s down, 84.375 KB/s up; +562.5 ms",fast4g:"1012.5 KB/s down, 168.75 KB/s up; +165 ms"};export function NetworkConditionsControl({remote:r,compact:P=false}){I(R,K,K);const l=r?r.state:M();const[U,T]=w(false);const q=I(R,A,A);const F=I(R,W,W);const[C,m]=w(false);const[E,y]=w();const[c,g]=w(false);const u=N(false);const p=N(true);const d=N(0);O(()=>{d.current++;u.current=false;g(false);y(void 0)},[r?.targetId]);O(()=>{p.current=true;return()=>{p.current=false}},[]);const f=r?r.profile:q;const s=r?r.available:F;const z=l?.active??(f!==null&&f!=="normal");const v=f==="offline"?t.color.danger:z?t.color.warning:t.color.accent;async function G(o){if(!s||u.current)return;if(o===f&&(o!=="normal"||!l?.active)){m(false);return}const a=++d.current;u.current=true;g(true);y(void 0);try{if(r)await r.onChange(o);else X(o);if(p.current&&d.current===a)m(false)}catch(b){if(p.current&&d.current===a)y(b instanceof Error?b.message:String(b))}finally{if(d.current===a){u.current=false;if(p.current)g(false)}}}const D=[["auto","Follow speed"],["real","Real link"],["offline","Offline"],["wifi","Wi-Fi"],["cellular","Cellular"],["noInternet","No internet"]];const B=(!r||!!r.onConnectionChange)&&(l?.capabilities.netInfo.supported||l?.capabilities.expoNetwork.supported);const H=L.find(o=>o.profile===f)?.label??"Unavailable";return h(S,{style:e.container,testID:"buoy-network-throttling-screen",children:[n(i,{style:e.heading,children:"Connection profile"}),h(k,{testID:"buoy-network-conditions",accessibilityRole:"button",accessibilityLabel:`Network throttling: ${H}`,accessibilityState:{expanded:C,disabled:!s||c},disabled:!s||c,onPress:()=>m(o=>!o),style:[e.dropdown,C&&e.dropdownOpen,!s&&e.disabled],children:[n(i,{style:[e.value,z&&{color:v}],children:H}),c?n(V,{size:"small",color:t.color.textSecondary}):n(_,{size:16,color:t.color.textSecondary})]}),C&&n(S,{accessibilityRole:"radiogroup",accessibilityLabel:"Connection profile",style:e.options,children:L.map(o=>{const a=f===o.profile;return h(k,{testID:`buoy-network-condition-${o.profile}`,accessibilityRole:"radio",accessibilityLabel:o.label,accessibilityState:{checked:a,disabled:!s||c},disabled:!s||c,onPress:()=>void G(o.profile),style:[e.option,a&&e.selected],children:[h(S,{style:e.optionBody,children:[n(i,{style:[e.optionTitle,a&&{color:v}],children:o.label}),n(i,{style:e.caption,children:j[o.profile]})]}),a&&n(J,{size:16,color:v})]},o.profile)})}),n(i,{style:e.caption,accessibilityLiveRegion:"polite",children:c?"Applying to device\u2026":!s?r?"Conditions unavailable on this device":"Requires a signed-in account and a development build":f?j[f]:"Waiting for device status"}),!!E&&n(i,{accessibilityRole:"alert",style:e.error,children:E}),n(k,{testID:"buoy-network-link-state",accessibilityRole:"button",accessibilityLabel:"App link state",disabled:!s||c||!B,onPress:()=>T(o=>!o),style:e.dropdown,children:h(i,{style:e.value,children:["App link: ",D.find(([o])=>o===l?.connection)?.[1]??"Unavailable"]})}),U&&D.map(([o,a])=>n(k,{testID:`buoy-network-link-${o}`,accessibilityRole:"radio",accessibilityState:{checked:l?.connection===o,disabled:c||!s},disabled:c||!s,style:e.option,onPress:async()=>{if(u.current)return;const b=++d.current;u.current=true;g(true);y(void 0);try{if(r)await r.onConnectionChange?.(o);else Q({connection:o});if(p.current&&d.current===b)T(false)}catch(x){if(p.current&&d.current===b)y(x instanceof Error?x.message:String(x))}finally{if(d.current===b){u.current=false;if(p.current)g(false)}}},children:n(i,{style:e.optionTitle,children:a})},o)),!B&&n(i,{style:e.caption,children:l?.capabilities.netInfo.reason??"This device has no link hook."}),!P&&h(S,{style:e.help,children:[n(i,{style:e.heading,children:"How it works"}),l&&h(i,{style:e.caption,children:["NetInfo: ",l.capabilities.netInfo.supported?"Hook on":l.capabilities.netInfo.reason??"No hook",". Expo Network: ",l.capabilities.expoNetwork.supported?"Hook on":l.capabilities.expoNetwork.reason??"No hook","."]}),n(i,{style:e.caption,children:"Down caps pace bytes to the app in JS. The socket stays at its real speed."}),n(i,{style:e.caption,children:"Up caps wait before send for known bytes. Upload time is simulated. The socket is not paced. Unknown sizes pass through with latency only. Each call shows any cap gap."}),n(i,{style:e.caption,children:"Caps apply per call through global fetch and RN XHR. Offline also drops WebSockets; speeds don't slow them. Native images, native SDKs and file transfers are not affected."}),n(i,{style:e.caption,children:"Link state changes what NetInfo and Expo Network report. It does not change the radio or web calls."}),n(i,{style:e.caption,children:"Stays on when this tool closes or capture pauses. No throttling clears both controls. App reload clears them too."})]})]})}const e=$.create({container:{padding:t.gutter,gap:10},heading:{fontSize:t.font.caption,fontWeight:"600",color:t.color.textSecondary},dropdown:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:12,minHeight:44,paddingHorizontal:12,paddingVertical:10,borderRadius:t.radius.segment,borderWidth:1,borderColor:t.color.separator,backgroundColor:t.color.surfaceElevated},dropdownOpen:{borderColor:t.color.accentBorderStrong},value:{flex:1,fontSize:t.font.body,color:t.color.text},options:{padding:4,borderRadius:t.radius.row,borderWidth:1,borderColor:t.color.border,backgroundColor:t.color.surface},option:{flexDirection:"row",alignItems:"center",gap:12,minHeight:54,padding:10,borderRadius:t.radius.segment},optionBody:{flex:1,gap:4},optionTitle:{fontSize:t.font.caption,fontWeight:"600",color:t.color.text},selected:{backgroundColor:t.color.surfaceElevated},disabled:{opacity:.45},caption:{fontSize:t.font.caption,lineHeight:19,color:t.color.textSecondary},help:{marginTop:14,paddingTop:16,gap:10,borderTopWidth:1,borderTopColor:t.color.separator},error:{fontSize:t.font.caption,lineHeight:18,color:t.color.danger}});
@@ -1 +1 @@
1
- "use strict";export const NETWORK_CONDITIONS={normal:{label:"Normal",delayMs:0},offline:{label:"Offline (requests)",delayMs:0},slow:{label:"Slow (+500 ms)",delayMs:500},verySlow:{label:"Very slow (+2000 ms)",delayMs:2e3},slow3g:{label:"Slow 3G",delayMs:2e3,downloadBytesPerSecond:5e4,uploadBytesPerSecond:5e4},slow4g:{label:"Slow 4G",delayMs:562.5,downloadBytesPerSecond:18e4,uploadBytesPerSecond:84375},fast4g:{label:"Fast 4G",delayMs:165,downloadBytesPerSecond:1012500,uploadBytesPerSecond:168750}};export const CONNECTIONS=["auto","real","offline","wifi","cellular","noInternet"];export const CONDITIONS_SCOPE={download:"Paces bytes to the app in JS. The socket stays at its real speed.",upload:"Waits before send for known body bytes. Unknown sizes pass through with latency only. Multipart overhead is not counted. Each call marks a partial or skipped cap. Upload time is simulated; the socket is not paced.",transports:"Affects global fetch and RN XHR. WebSocket, native images, native SDKs and file transfers are not affected."};
1
+ "use strict";export const NETWORK_CONDITIONS={normal:{label:"Normal",delayMs:0},offline:{label:"Offline (requests)",delayMs:0},slow:{label:"Slow (+500 ms)",delayMs:500},verySlow:{label:"Very slow (+2000 ms)",delayMs:2e3},slow3g:{label:"Slow 3G",delayMs:2e3,downloadBytesPerSecond:5e4,uploadBytesPerSecond:5e4},slow4g:{label:"Slow 4G",delayMs:562.5,downloadBytesPerSecond:18e4,uploadBytesPerSecond:84375},fast4g:{label:"Fast 4G",delayMs:165,downloadBytesPerSecond:1012500,uploadBytesPerSecond:168750}};export const CONNECTIONS=["auto","real","offline","wifi","cellular","noInternet"];export const CONDITIONS_SCOPE={download:"Paces bytes to the app in JS. The socket stays at its real speed.",upload:"Waits before send for known body bytes. Unknown sizes pass through with latency only. Multipart overhead is not counted. Each call marks a partial or skipped cap. Upload time is simulated; the socket is not paced.",transports:"Affects global fetch and RN XHR. Offline also drops WebSockets; speeds don't slow them. Native images, native SDKs and file transfers are not affected."};
@@ -1 +1 @@
1
- "use strict";import{hasAccountAccess as u,subscribeAccountAccess as w}from"@buoy-gg/shared-ui";import{addNetworkListener as N,startNetworkListener as C,getNetworkListenerCount as k,stopNetworkListener as h}from"../utils/networkListener";import{NETWORK_CONDITIONS as d,CONNECTIONS as m,CONDITIONS_SCOPE as x}from"./profiles";export{NETWORK_CONDITIONS,CONDITIONS_SCOPE}from"./profiles";const c={netInfo:{supported:false,reason:"Load the NetInfo hook before app code."},expoNetwork:{supported:false,reason:"Load the Expo Network hook before app code."}};let r="auto";let p=0;export const getNetworkConnection=()=>r;export const getConditionsRevision=()=>p;export const getEffectiveNetworkConnection=()=>!conditionsCanApply()?"real":r==="auto"?n==="offline"?"offline":"real":r;export const networkConditionsActive=()=>n!=="normal"||!["auto","real"].includes(r);export function setConnectionSupport(o,e){c[o]=e;p++;s.forEach(t=>t())}export function getNetworkConditions(){const o=d[n];return{version:2,runtimeId:networkConditionsRuntimeId,revision:p,profile:n,connection:r,available:conditionsCanApply(),active:networkConditionsActive(),delayMs:o.delayMs,downloadBytesPerSecond:o.downloadBytesPerSecond??null,uploadBytesPerSecond:o.uploadBytesPerSecond??null,capabilities:{...c,fetch:"JS body delivery",xhr:"RN progress and body delivery",upload:"time-simulated",webSocket:false,nativeImages:false,nativeModules:false},scope:x}}export function setNetworkConditions(o){if(!o||typeof o!=="object"||Array.isArray(o))throw new Error("Choose a speed or link state.");const e=o;if(Object.keys(e).some(a=>a!=="profile"&&a!=="connection")||!("profile"in e)&&!("connection"in e))throw new Error("Choose a speed or link state.");const t="profile"in e?e.profile:n;const i="connection"in e?e.connection:t==="normal"&&"profile"in e?"auto":r;if(typeof t!=="string"||!Object.prototype.hasOwnProperty.call(d,t))throw new Error("Choose a valid speed profile.");if(!m.includes(i))throw new Error("Choose a valid link state.");if((t!=="normal"||!["auto","real"].includes(i))&&!conditionsCanApply())throw new Error("Use a signed-in account and a dev build.");if(!["auto","real"].includes(i)&&!c.netInfo.supported&&!c.expoNetwork.supported)throw new Error("Load a link hook before app code.");if(t===n&&i===r)return getNetworkConditions();const f=t!=="normal";if(f&&!l){C();l=N(()=>{})}if(!f){l?.();l=void 0;if(k()===0)h()}n=t;r=i;p++;s.forEach(a=>a());return getNetworkConditions()}export const networkConditionsRuntimeId=`${Date.now()}-${Math.random().toString(36).slice(2)}`;let n="normal";let l;const s=new Set;export const conditionsCanApply=()=>typeof __DEV__!=="undefined"&&__DEV__&&u();export const getNetworkCondition=()=>n;export const subscribeNetworkConditions=o=>{s.add(o);return()=>{s.delete(o)}};export function setNetworkCondition(o){return setNetworkConditions({profile:o}).profile}export function snapshotNetworkCondition(o){if(n==="normal"||!conditionsCanApply()||!/^https?:\/\//i.test(o))return;const{label:e,...t}=d[n];return Object.freeze({profile:n,...t})}w(()=>{if(!u())setNetworkCondition("normal");s.forEach(o=>o())});
1
+ "use strict";import{hasAccountAccess as u,subscribeAccountAccess as w}from"@buoy-gg/shared-ui";import{addNetworkListener as N,startNetworkListener as C,getNetworkListenerCount as k,stopNetworkListener as h}from"../utils/networkListener";import{NETWORK_CONDITIONS as d,CONNECTIONS as m,CONDITIONS_SCOPE as x}from"./profiles";export{NETWORK_CONDITIONS,CONDITIONS_SCOPE}from"./profiles";const c={netInfo:{supported:false,reason:"Load the NetInfo hook before app code."},expoNetwork:{supported:false,reason:"Load the Expo Network hook before app code."}};let r="auto";let l=0;export const getNetworkConnection=()=>r;export const getConditionsRevision=()=>l;export const getEffectiveNetworkConnection=()=>!conditionsCanApply()?"real":r==="auto"?n==="offline"?"offline":"real":r;export const networkConditionsActive=()=>n!=="normal"||!["auto","real"].includes(r);export function setConnectionSupport(o,e){c[o]=e;l++;s.forEach(t=>t())}export function getNetworkConditions(){const o=d[n];return{version:2,runtimeId:networkConditionsRuntimeId,revision:l,profile:n,connection:r,available:conditionsCanApply(),active:networkConditionsActive(),delayMs:o.delayMs,downloadBytesPerSecond:o.downloadBytesPerSecond??null,uploadBytesPerSecond:o.uploadBytesPerSecond??null,capabilities:{...c,fetch:"JS body delivery",xhr:"RN progress and body delivery",upload:"time-simulated",webSocket:"offline only",nativeImages:false,nativeModules:false},scope:x}}export function setNetworkConditions(o){if(!o||typeof o!=="object"||Array.isArray(o))throw new Error("Choose a speed or link state.");const e=o;if(Object.keys(e).some(a=>a!=="profile"&&a!=="connection")||!("profile"in e)&&!("connection"in e))throw new Error("Choose a speed or link state.");const t="profile"in e?e.profile:n;const i="connection"in e?e.connection:t==="normal"&&"profile"in e?"auto":r;if(typeof t!=="string"||!Object.prototype.hasOwnProperty.call(d,t))throw new Error("Choose a valid speed profile.");if(!m.includes(i))throw new Error("Choose a valid link state.");if((t!=="normal"||!["auto","real"].includes(i))&&!conditionsCanApply())throw new Error("Use a signed-in account and a dev build.");if(!["auto","real"].includes(i)&&!c.netInfo.supported&&!c.expoNetwork.supported)throw new Error("Load a link hook before app code.");if(t===n&&i===r)return getNetworkConditions();const f=t!=="normal";if(f&&!p){C();p=N(()=>{})}if(!f){p?.();p=void 0;if(k()===0)h()}n=t;r=i;l++;s.forEach(a=>a());return getNetworkConditions()}export const networkConditionsRuntimeId=`${Date.now()}-${Math.random().toString(36).slice(2)}`;let n="normal";let p;const s=new Set;export const conditionsCanApply=()=>typeof __DEV__!=="undefined"&&__DEV__&&u();export const getNetworkCondition=()=>n;export const subscribeNetworkConditions=o=>{s.add(o);return()=>{s.delete(o)}};export function setNetworkCondition(o){return setNetworkConditions({profile:o}).profile}export function snapshotNetworkCondition(o){if(n==="normal"||!conditionsCanApply()||!/^https?:\/\//i.test(o))return;const{label:e,...t}=d[n];return Object.freeze({profile:n,...t})}w(()=>{if(!u())setNetworkCondition("normal");s.forEach(o=>o())});
@@ -0,0 +1 @@
1
+ "use strict";import{useEffect as i,useState as S}from"react";import{socketStore as e}from"../sockets/socketStore";const f=100;export function useSocketsState(r=false){const[a,s]=S(()=>e.getState());i(()=>{if(r)return;s(e.getState());let t=null;let o=0;const n=()=>{t=null;o=Date.now();s(e.getState())};const u=e.subscribeState(()=>{if(t)return;const c=Math.max(0,f-(Date.now()-o));t=setTimeout(n,c)});return()=>{u();if(t)clearTimeout(t)}},[r]);return a}
@@ -1 +1 @@
1
- "use strict";import{getAccountAccess as f,hasAccountAccess as c,subscribeAccountAccess as _}from"@buoy-gg/shared-ui";import{findMatchingRule as d,shouldApply as a,toOutcome as p}from"./resolveOverride";import{realClearTimeout as R,realSetTimeout as g}from"../utils/realNow";let e=null;export function setOverrideHooks(t){e=t}export function overrideRulesReady(){return e?.ready?.()??Promise.resolve()}export function overrideRulesLoaded(){return e?.isReady?.()??true}export function overrideRulesNeedBody(){return!!e?.getRules().some(t=>t.enabled&&(t.bodyIncludes||t.graphqlOperation))}export function overridesCanApply(){return c()&&!(typeof __DEV__!=="undefined"&&!__DEV__)}export const OVERRIDES_INACTIVE_REASON="Response overrides never apply in a release build \u2014 the rule is saved but will not affect any request.";export function inspectEngine(t,u){return{hooksInstalled:e!==null,devFlag:typeof __DEV__==="undefined"?"undefined":__DEV__,ruleCount:e?e.getRules().length:0,matches:e?d(t,u,e.getRules())!==null:false}}const m=3e3;export function accountCheckFor(t,u,i,l){if(!e||c())return null;if(typeof __DEV__!=="undefined"&&!__DEV__)return null;if(f().status!=="initializing")return null;if(!d(t,u,e.getRules(),i,l))return null;return new Promise(r=>{let n=()=>{};const o=()=>{R(s);n();r()};const s=g(o,m);n=_(()=>{if(f().status!=="initializing")o()})})}export function overrideForRequest(t,u,i,l){if(!e)return null;if(typeof __DEV__!=="undefined"&&!__DEV__)return null;let r=e.getRules();if(r.length===0)return null;if(!c()){r=r.filter(s=>s.sandbox===true);if(r.length===0)return null}const n=d(t,u,r,i,l);if(!n)return null;const o=a(n);e.recordMatch(n.id);if(!o)return null;e.recordHit(n.id);return p(n)}
1
+ "use strict";import{getAccountAccess as f,hasAccountAccess as d,subscribeAccountAccess as _}from"@buoy-gg/shared-ui";import{findMatchingRule as c,shouldApply as a,toOutcome as p}from"./resolveOverride";import{realClearTimeout as R,realSetTimeout as g}from"../utils/realNow";let e=null;export function setOverrideHooks(t){e=t}export function overrideRulesReady(){return e?.ready?.()??Promise.resolve()}export function overrideRulesLoaded(){return e?.isReady?.()??true}export function overrideRulesNeedBody(){return!!e?.getRules().some(t=>t.enabled&&(t.bodyIncludes||t.graphqlOperation||t.bodyJson!==void 0))}export function overridesCanApply(){return d()&&!(typeof __DEV__!=="undefined"&&!__DEV__)}export const OVERRIDES_INACTIVE_REASON="Response overrides never apply in a release build \u2014 the rule is saved but will not affect any request.";export function inspectEngine(t,o){return{hooksInstalled:e!==null,devFlag:typeof __DEV__==="undefined"?"undefined":__DEV__,ruleCount:e?e.getRules().length:0,matches:e?c(t,o,e.getRules())!==null:false}}const m=3e3;export function accountCheckFor(t,o,i,l){if(!e||d())return null;if(typeof __DEV__!=="undefined"&&!__DEV__)return null;if(f().status!=="initializing")return null;if(!c(t,o,e.getRules(),i,l))return null;return new Promise(r=>{let n=()=>{};const u=()=>{R(s);n();r()};const s=g(u,m);n=_(()=>{if(f().status!=="initializing")u()})})}export function overrideForRequest(t,o,i,l){if(!e)return null;if(typeof __DEV__!=="undefined"&&!__DEV__)return null;let r=e.getRules();if(r.length===0)return null;if(!d()){r=r.filter(s=>s.sandbox===true);if(r.length===0)return null}const n=c(t,o,r,i,l);if(!n)return null;const u=a(n);e.recordMatch(n.id);if(!u)return null;e.recordHit(n.id);return p(n)}
@@ -1 +1 @@
1
- "use strict";const a="[]{}()\\.^$+|-,?";export function escapeRegex(e){let n="";for(let t=0;t<e.length;t++){const r=e.charAt(t);if(a.indexOf(r)!==-1){n+="\\"}n+=r}return n.split("*").join(".*")}const i=new Map;export function compilePattern(e){const n=i.get(e);if(n)return n;const t=e.startsWith("/")?`[a-zA-Z][a-zA-Z0-9+.-]*://[^/]*${escapeRegex(e)}`:escapeRegex(e);const r=new RegExp(`^${t}$`);if(i.size>200)i.clear();i.set(e,r);return r}function c(e,n){if(!e)return false;const t=n.toLowerCase();for(const r of Object.keys(e)){if(r.toLowerCase()===t&&e[r]!==void 0&&e[r]!=="")return true}return false}export function canonicalJson(e){const n=t=>Array.isArray(t)?t.map(n):t&&typeof t==="object"?Object.fromEntries(Object.keys(t).sort().map(r=>[r,n(t[r])])):t;return JSON.stringify(n(e))??"null"}function f(e,n,t){if(typeof e!=="string"||!e.includes(n))return false;try{const r=JSON.parse(e);const s=Array.isArray(r)?r:[r];return s.some(o=>{if(!o||typeof o!=="object"||o.operationName!==n)return false;return t===void 0||canonicalJson(o.variables??{})===t})}catch{return false}}export function ruleMatches(e,n,t,r,s){if(e.methods&&e.methods.length>0){if(!e.methods.includes(t.toUpperCase()))return false}if(e.requireHeader&&!c(r,e.requireHeader))return false;if(e.bodyIncludes&&(typeof s!=="string"||!s.includes(e.bodyIncludes)))return false;if(e.graphqlOperation&&!f(s,e.graphqlOperation,e.graphqlVariables))return false;try{return compilePattern(e.urlPattern).test(n)}catch{return false}}
1
+ "use strict";const f="[]{}()\\.^$+|-,?";export function escapeRegex(e){let r="";for(let t=0;t<e.length;t++){const n=e.charAt(t);if(f.indexOf(n)!==-1){r+="\\"}r+=n}return r.split("*").join(".*")}const a=new Map;export function compilePattern(e){const r=a.get(e);if(r)return r;const t=e.startsWith("/")?`[a-zA-Z][a-zA-Z0-9+.-]*://[^/]*${escapeRegex(e)}`:escapeRegex(e);const n=new RegExp(`^${t}$`);if(a.size>200)a.clear();a.set(e,n);return n}function c(e,r){if(!e)return false;const t=r.toLowerCase();for(const n of Object.keys(e)){if(n.toLowerCase()===t&&e[n]!==void 0&&e[n]!=="")return true}return false}export function canonicalJson(e){const r=t=>Array.isArray(t)?t.map(r):t&&typeof t==="object"?Object.fromEntries(Object.keys(t).sort().map(n=>[n,r(t[n])])):t;return JSON.stringify(r(e))??"null"}function u(e,r,t,n){if(typeof e!=="string"||!e.includes(r))return false;try{const s=JSON.parse(e);if(n&&Array.isArray(s))return false;const o=Array.isArray(s)?s:[s];return o.some(i=>{if(!i||typeof i!=="object"||i.operationName!==r)return false;return t===void 0||canonicalJson(i.variables??{})===t})}catch{return false}}function l(e,r){if(typeof e!=="string")return false;try{return canonicalJson(JSON.parse(e))===r}catch{return JSON.stringify(e)===r}}export function ruleMatches(e,r,t,n,s){if(e.methods&&e.methods.length>0){if(!e.methods.includes(t.toUpperCase()))return false}if(e.requireHeader&&!c(n,e.requireHeader))return false;if(e.bodyIncludes&&(typeof s!=="string"||!s.includes(e.bodyIncludes)))return false;if(e.graphqlOperation&&!u(s,e.graphqlOperation,e.graphqlVariables,e.graphqlSingle))return false;if(e.bodyJson!==void 0&&!l(s,e.bodyJson))return false;try{return compilePattern(e.urlPattern).test(r)}catch{return false}}
@@ -1 +1 @@
1
- "use strict";import{devToolsStorageKeys as l,persistentStorage as o}from"@buoy-gg/shared-ui";import{addNetworkListener as b,getNetworkListenerCount as d,startNetworkListener as y,stopNetworkListener as h}from"../utils/networkListener";import{setOverrideHooks as g}from"./engine";import{isSpent as k}from"./resolveOverride";import{MAX_RULES as u,STATUS_MAX as S,STATUS_MIN as E}from"./types";import{realNow as c}from"../utils/realNow";const v=800;const A=3;function R(){const r=`${l.network.overrides()}_launch`;try{const t=globalThis.sessionStorage;if(!t)return false;if(t.getItem(r))return true;t.setItem(r,"1")}catch{}return false}const m=Object.freeze([]);const T=250;const x=["respond","fail","delay"];function f(r){if(!Array.isArray(r))return[];const t=[];for(const i of r){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=x.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(n=>typeof n==="string"):void 0,requireHeader:typeof e.requireHeader==="string"&&e.requireHeader?e.requireHeader:void 0,bodyIncludes:typeof e.bodyIncludes==="string"&&e.bodyIncludes?e.bodyIncludes:void 0,graphqlOperation:typeof e.graphqlOperation==="string"&&e.graphqlOperation?e.graphqlOperation:void 0,graphqlVariables:typeof e.graphqlVariables==="string"?e.graphqlVariables:void 0,sandbox:e.sandbox===true?true:void 0,kind:s,status:typeof e.status==="number"?Math.min(S,Math.max(E,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,u)}class P{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&&c()<this.remoteEchoUntil)return;this.enabled=t.enabled;this.rules=t.rules;this.rebuild();this.emit()}markLocalEdit(){if(this.remote)this.remoteEchoUntil=c()+v}disableEngine(){this.engineDisabled=true;if(this.keepAlive){this.keepAlive();this.keepAlive=null;if(d()===0)h()}}getState(){return this.state}getRules(){if(this.engineDisabled)return m;if(!this.enabled)return this.sandboxOnly();return this.rules}sandboxCache=null;sandboxOnly(){if(this.sandboxCache?.from!==this.rules){const t=this.rules.filter(i=>i.sandbox===true);this.sandboxCache={from:this.rules,rules:t.length?t:m}}return this.sandboxCache.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(){return(this.enabled?this.rules:this.sandboxOnly()).filter(t=>t.enabled&&!k(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>=u)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)}replaceAllRules(t,i){if(this.remote)return null;this.markTouched();const e=t.map(s=>s&&typeof s==="object"&&typeof s.id==="string"?s:{...s,id:`ovr_${Date.now().toString(36)}_${++this.idCounter}`,createdAt:Date.now()});this.enabled=i;this.commit(f(e));return this.rules.slice()}updateRule(t,i){const e=this.rules.findIndex(n=>n.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(n=>n.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(p=>p.id===t);if(i===-1)return;const e=this.rules[i];const s=e.hits+1;const n=typeof e.times==="number"&&s>=e.times;const a=[...this.rules];a[i]={...e,hits:s,enabled:n?false:e.enabled};if(n){this.commit(a);return}this.rules=a;this.rebuild();this.scheduleHitEmit()}isLoaded(){return!!this.remote||this.loaded}ensureLoaded(){if(this.remote)return Promise.resolve();if(this.loaded)return Promise.resolve();if(this.loadPromise)return this.loadPromise;this.loadPromise=(async()=>{let t=null;try{t=await o.getItem(l.network.overrides())}catch{}this.hydrate(t)})();return this.loadPromise}loadNow(){if(this.remote||this.loaded||this.loadPromise)return;let t;try{t=globalThis.localStorage?.getItem(l.network.overrides())??null}catch{return}if(t===null)return;this.hydrate(t)}hydrate(t){try{if(t&&!this.dirty){const i=JSON.parse(t);this.enabled=i?.enabled!==false;this.rules=f(i?.rules);this.launchStreak=typeof i?.launchStreak==="number"?i.launchStreak:0;this.autoPaused=i?.autoPaused===true&&!this.enabled;this.applyLaunchGuard();this.rebuild()}}catch{}finally{this.loaded=true;this.syncKeepAlive();this.emit()}}applyLaunchGuard(){if(!this.enabled||this.activeCount()===0||this.rules.some(t=>t.enabled&&t.sandbox)){this.launchStreak=0;return}if(R())return;this.launchStreak+=1;if(this.launchStreak>=A){this.enabled=false;this.autoPaused=true;this.launchStreak=0}this.persist()}syncKeepAlive(){const t=!this.engineDisabled&&this.activeCount()>0;if(t&&!this.keepAlive){y();this.keepAlive=b(()=>{});return}if(!t&&this.keepAlive){this.keepAlive();this.keepAlive=null;if(d()===0)h()}}scheduleHitEmit(){if(this.hitEmitTimer!==null)return;this.hitEmitTimer=setTimeout(()=>{this.hitEmitTimer=null;this.emit()},T)}commit(t){this.dirty=true;this.rules=t.slice(0,u);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;o.setItem(l.network.overrides(),JSON.stringify({enabled:this.enabled,rules:this.rules,launchStreak:this.launchStreak,autoPaused:this.autoPaused})).catch(()=>{})}emit(){this.listeners.forEach(t=>t())}}export const overrideRulesStore=new P;g({getRules:()=>overrideRulesStore.getRules(),ready:()=>overrideRulesStore.ensureLoaded(),isReady:()=>overrideRulesStore.isLoaded(),recordHit:r=>overrideRulesStore.recordHit(r),recordMatch:r=>overrideRulesStore.recordMatch(r)});if(typeof window!=="undefined"&&typeof document!=="undefined"&&!(typeof navigator!=="undefined"&&navigator.product==="ReactNative")){overrideRulesStore.loadNow()}
1
+ "use strict";import{devToolsStorageKeys as a,persistentStorage as d,setItemChecked as k}from"@buoy-gg/shared-ui";import{addNetworkListener as S,getNetworkListenerCount as h,startNetworkListener as v,stopNetworkListener as c}from"../utils/networkListener";import{setOverrideHooks as E}from"./engine";import{isSpent as T}from"./resolveOverride";import{MAX_RULES as u,STATUS_MAX as R,STATUS_MIN as A}from"./types";import{realNow as f}from"../utils/realNow";const w=800;const x=3;function C(){const r=`${a.network.overrides()}_launch`;try{const t=globalThis.sessionStorage;if(!t)return false;if(t.getItem(r))return true;t.setItem(r,"1")}catch{}return false}const m=Object.freeze([]);const b=()=>`${a.base}_bug_links_loaded`;function p(){if(typeof navigator!=="undefined"&&navigator.product==="ReactNative")return null;try{return globalThis.localStorage??null}catch{return null}}let o={raw:null,blocks:false};function L(){let r;try{r=p()?.getItem(b())??null}catch{return false}if(r===o.raw)return o.blocks;o={raw:r,blocks:P(r)};return o.blocks}function P(r){try{if(!r)return false;const t=JSON.parse(r);if(t.block===void 0)return t.options?.replay!==false&&t.report?.replay?.active===true;return t.block===true}catch{return true}}const _=5e3;const O=Object.freeze([Object.freeze({id:"bug-case-other-tab",name:"Bug case (loaded in another tab)",enabled:true,sandbox:true,urlPattern:"*",kind:"fail",failKind:"network"})]);const I=250;const M=["respond","fail","delay"];function y(r){if(!Array.isArray(r))return[];const t=[];for(const s of r){if(!s||typeof s!=="object")continue;const e=s;if(typeof e.id!=="string"||typeof e.urlPattern!=="string"){continue}if(!e.urlPattern)continue;const i=M.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(n=>typeof n==="string"):void 0,requireHeader:typeof e.requireHeader==="string"&&e.requireHeader?e.requireHeader:void 0,bodyIncludes:typeof e.bodyIncludes==="string"&&e.bodyIncludes?e.bodyIncludes:void 0,graphqlOperation:typeof e.graphqlOperation==="string"&&e.graphqlOperation?e.graphqlOperation:void 0,graphqlVariables:typeof e.graphqlVariables==="string"?e.graphqlVariables:void 0,bodyJson:typeof e.bodyJson==="string"?e.bodyJson:void 0,graphqlSingle:e.graphqlSingle===true?true:void 0,sandbox:e.sandbox===true?true:void 0,kind:i,status:typeof e.status==="number"?Math.min(R,Math.max(A,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,u)}class H{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,s=false){if(!this.remote)return;if(!s&&f()<this.remoteEchoUntil)return;this.enabled=t.enabled;this.rules=t.rules;this.rebuild();this.emit()}markLocalEdit(){if(this.remote)this.remoteEchoUntil=f()+w}disableEngine(){this.engineDisabled=true;if(this.keepAlive){this.keepAlive();this.keepAlive=null;if(h()===0)c()}}getState(){return this.state}getRules(){if(this.engineDisabled)return m;if(this.otherTabCase())return O;if(!this.enabled)return this.sandboxOnly();return this.rules}otherTabCase(){if(this.remote||this.sandboxOnly().length)return false;if(!p())return false;return L()}caseLockChanged(){this.syncKeepAlive();this.emit()}sandboxCache=null;sandboxOnly(){if(this.sandboxCache?.from!==this.rules){const t=this.rules.filter(s=>s.sandbox===true);this.sandboxCache={from:this.rules,rules:t.length?t:m}}return this.sandboxCache.rules}async fetchRuleBody(t){const s=this.rules.find(e=>e.id===t);if(!s)return null;if(!s.bodyOmitted)return s.body??null;if(!this.remote?.getRuleBody)return null;try{return await this.remote.getRuleBody(t)}catch{return null}}activeCount(){return(this.enabled?this.rules:this.sandboxOnly()).filter(t=>t.enabled&&!T(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>=u)return null;const s={...t,id:`ovr_${Date.now().toString(36)}_${++this.idCounter}`,hits:0,seen:0,createdAt:Date.now()};this.commit([s,...this.rules]);return s}upsertRule(t){this.remote?.upsertRule(t);this.markLocalEdit();this.markTouched();const{id:s,...e}=t;if(s&&this.rules.some(i=>i.id===s)){this.updateRule(s,e);return this.rules.find(i=>i.id===s)??null}return this.addRule(e)}replaceAllRules(t,s){if(this.remote)return null;this.markTouched();const e=t.map(i=>i&&typeof i==="object"&&typeof i.id==="string"?i:{...i,id:`ovr_${Date.now().toString(36)}_${++this.idCounter}`,createdAt:Date.now()});this.enabled=s;this.commit(y(e));return this.rules.slice()}updateRule(t,s){const e=this.rules.findIndex(n=>n.id===t);if(e===-1)return;const i=[...this.rules];i[e]={...i[e],...s,hits:0,seen:0};this.commit(i)}setRuleEnabled(t,s){const e=this.rules.findIndex(n=>n.id===t);if(e===-1||this.rules[e].enabled===s)return;this.remote?.setRuleEnabled(t,s);this.markLocalEdit();this.markTouched();const i=[...this.rules];i[e]={...i[e],enabled:s,hits:s?0:i[e].hits,seen:s?0:i[e].seen};this.commit(i)}removeRule(t){const s=this.rules.filter(e=>e.id!==t);if(s.length===this.rules.length)return;this.remote?.removeRule(t);this.markLocalEdit();this.markTouched();this.commit(s)}clearRules(){if(this.rules.length===0)return;this.remote?.clearRules();this.markLocalEdit();this.markTouched();this.commit([])}recordMatch(t){const s=this.rules.findIndex(i=>i.id===t);if(s===-1)return;const e=[...this.rules];e[s]={...e[s],seen:e[s].seen+1};this.rules=e;this.rebuild()}recordHit(t){const s=this.rules.findIndex(g=>g.id===t);if(s===-1)return;const e=this.rules[s];const i=e.hits+1;const n=typeof e.times==="number"&&i>=e.times;const l=[...this.rules];l[s]={...e,hits:i,enabled:n?false:e.enabled};if(n){this.commit(l);return}this.rules=l;this.rebuild();this.scheduleHitEmit()}isLoaded(){return!!this.remote||this.loaded}ensureLoaded(){if(this.remote)return Promise.resolve();if(this.loaded)return Promise.resolve();if(this.loadPromise)return this.loadPromise;this.loadPromise=(async()=>{let t=null;try{t=await d.getItem(a.network.overrides())}catch{}this.hydrate(t)})();return this.loadPromise}loadNow(){if(this.remote||this.loaded||this.loadPromise)return;let t;try{t=globalThis.localStorage?.getItem(a.network.overrides())??null}catch{return}if(t===null)return;this.hydrate(t)}hydrate(t){try{if(t&&!this.dirty){const s=JSON.parse(t);this.enabled=s?.enabled!==false;this.rules=y(s?.rules);this.launchStreak=typeof s?.launchStreak==="number"?s.launchStreak:0;this.autoPaused=s?.autoPaused===true&&!this.enabled;this.applyLaunchGuard();this.rebuild()}}catch{}finally{this.loaded=true;this.syncKeepAlive();this.emit()}}applyLaunchGuard(){if(!this.enabled||this.activeCount()===0||this.rules.some(t=>t.enabled&&t.sandbox)){this.launchStreak=0;return}if(C())return;this.launchStreak+=1;if(this.launchStreak>=x){this.enabled=false;this.autoPaused=true;this.launchStreak=0}this.persist()}syncKeepAlive(){const t=!this.engineDisabled&&(this.activeCount()>0||this.otherTabCase());if(t&&!this.keepAlive){v();this.keepAlive=S(()=>{});return}if(!t&&this.keepAlive){this.keepAlive();this.keepAlive=null;if(h()===0)c()}}scheduleHitEmit(){if(this.hitEmitTimer!==null)return;this.hitEmitTimer=setTimeout(()=>{this.hitEmitTimer=null;this.emit()},I)}commit(t){this.dirty=true;this.rules=t.slice(0,u);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()}persisted(){return JSON.stringify({enabled:this.enabled,rules:this.rules,launchStreak:this.launchStreak,autoPaused:this.autoPaused})}writes=Promise.resolve();persist(){if(this.remote)return;const t=this.persisted();this.writes=this.writes.then(()=>d.setItem(a.network.overrides(),t)).catch(()=>{})}async saveChecked(){if(this.remote)return false;const t=this.persisted();const s=this.writes.then(()=>k(a.network.overrides(),t));this.writes=s.catch(()=>{});let e;const i=new Promise(n=>{e=setTimeout(()=>n(false),_)});return Promise.race([s.catch(()=>false),i]).finally(()=>clearTimeout(e))}emit(){this.listeners.forEach(t=>t())}}export const overrideRulesStore=new H;E({getRules:()=>overrideRulesStore.getRules(),ready:()=>overrideRulesStore.ensureLoaded(),isReady:()=>overrideRulesStore.isLoaded(),recordHit:r=>overrideRulesStore.recordHit(r),recordMatch:r=>overrideRulesStore.recordMatch(r)});if(typeof window!=="undefined"&&typeof document!=="undefined"&&!(typeof navigator!=="undefined"&&navigator.product==="ReactNative")){overrideRulesStore.loadNow();overrideRulesStore.caseLockChanged();window.addEventListener?.("storage",r=>{if(r.key===null||r.key===b())overrideRulesStore.caseLockChanged()})}
@@ -0,0 +1 @@
1
+ "use strict";import{socketKey as m}from"./readMessage";export const REPLY_TIMEOUT_MS=1e4;export const STORM_OPENS=3;export const STORM_WINDOW_MS=15e3;export const CANT_CONNECT_TRIES=3;export const AUTH_FAILURES=3;export const AUTH_WINDOW_MS=12e4;export const SIGNED_IN_MS=3e4;const T=1008;const $=/(^|[._:-])(auth[._:-]?(expired|fail(ed|ure)?|error|invalid|rejected)|unauthori[sz]ed|token[._:-]?expired)$/i;export function answeredTypes(i,f){const u=new Map(i.map(c=>[c.id,c]));const d=new Map;for(const c of i){if(!c.replyTo)continue;const r=u.get(c.replyTo);const a=f.get(c.socketId);if(!r?.type||!a)continue;const l=m(a.url);let p=d.get(l);if(!p)d.set(l,p=new Set);p.add(r.type)}return d}function S(i,f,u){const d=[...i].sort((a,l)=>a.at-l.at);let c=0;let r=null;for(let a=0;a<d.length;a++){while(d[a].at-d[c].at>u)c++;const l=a-c+1;if(l>f&&l>(r?.length??0))r=d.slice(c,a+1)}return r}const x=(i,f)=>`${i} ${f}${i===1?"":"s"}`;export function findProblems(i,f,u,d){const c=[];const r=new Map(f.map(t=>[t.id,t]));const a=answeredTypes(i,r);if(d){for(const[t,e]of d){const n=a.get(t)??new Set;e.forEach(s=>n.add(s));a.set(t,n)}}const l=new Map;for(const t of i){if(t.kind==="message"&&t.direction==="in"&&t.held){l.set(t.socketId,[...l.get(t.socketId)??[],t.timestamp])}}for(const t of i){if(t.kind!=="message"||t.direction!=="out"||t.held||t.ping)continue;if(t.sentWhileClosed)continue;if(!t.type||!t.correlationId||t.replyId)continue;const e=r.get(t.socketId);if(!e||!a.get(m(e.url))?.has(t.type))continue;if(e.frozen||l.get(t.socketId)?.some(s=>s>=t.timestamp))continue;const n=e.closedAt!==void 0&&e.closedAt>=t.timestamp?e.closedAt:u;if(n-t.timestamp<REPLY_TIMEOUT_MS)continue;c.push({kind:"no-reply",message:`${t.type} got no reply after ${REPLY_TIMEOUT_MS/1e3}s`,socketId:t.socketId,url:e.url,frameIds:[t.id],at:t.timestamp})}const p=new Map;for(const t of[...f].sort((e,n)=>e.createdAt-n.createdAt)){const e=m(t.url);p.set(e,[...p.get(e)??[],t])}const _=new Set;for(const t of p.values()){for(let e=1;e<t.length;e++){const n=t[e-1];if(n.closedByBuoy&&n.closedAt!==void 0&&t[e].createdAt>=n.closedAt)_.add(t[e].id)}}const k=new Map;const h=new Map;for(const t of i){const e=r.get(t.socketId);if(!e)continue;const n=m(e.url);if(t.kind==="open"&&!_.has(e.id)){k.set(n,[...k.get(n)??[],{at:t.timestamp,id:t.id}])}const s=t.kind==="close"&&t.code===T&&!t.byBuoy;const o=t.kind==="message"&&t.direction==="in"&&!t.fake&&!!t.type&&$.test(t.type);if(!s&&!o)continue;const g=h.get(t.socketId);if(!g||t.timestamp<g.at)h.set(t.socketId,{at:t.timestamp,id:t.id,url:n})}const I=new Map;for(const t of h.values())I.set(t.url,[...I.get(t.url)??[],{at:t.at,id:t.id}]);for(const[t,e]of k){const n=S(e,STORM_OPENS,STORM_WINDOW_MS);if(!n)continue;const s=Math.max(1,Math.round((n[n.length-1].at-n[0].at)/1e3));c.push({kind:"reconnect-storm",message:`Opened ${n.length} times in ${s}s`,url:t,frameIds:n.map(o=>o.id),at:n[n.length-1].at})}for(const[t,e]of I){let n=-Infinity;for(const o of p.get(t)??[]){if(o.openedAt===void 0)continue;const g=h.get(o.id)?.at??o.closedAt??u;if(g-o.openedAt>=SIGNED_IN_MS)n=Math.max(n,g)}const s=S(e.filter(o=>o.at>n),AUTH_FAILURES-1,AUTH_WINDOW_MS);if(!s)continue;c.push({kind:"auth-loop",message:`Sign-in failed ${x(s.length,"time")} in a row`,url:t,frameIds:s.map(o=>o.id),at:s[s.length-1].at})}const y=new Map;const M=new Map;for(const t of[...f].sort((e,n)=>e.createdAt-n.createdAt)){if(t.state!=="closed"&&t.openedAt===void 0)continue;const e=m(t.url);const n=t.state==="closed"&&t.openedAt===void 0&&!t.closedByBuoy;if(!n){y.set(e,[]);M.delete(e);continue}const s=[...y.get(e)??[],t];y.set(e,s);if(s.length>=CANT_CONNECT_TRIES)M.set(e,s)}for(const[t,e]of M){const n=new Set(e.map(o=>o.id));const s=i.filter(o=>o.kind==="close"&&n.has(o.socketId));c.push({kind:"cant-connect",message:`Couldn't connect: ${e.length} tries in a row failed`,url:t,frameIds:s.map(o=>o.id),at:Math.max(...e.map(o=>o.closedAt??o.createdAt))})}const A=new Map;for(const t of f){if(t.state!=="open")continue;const e=m(t.url);A.set(e,[...A.get(e)??[],t])}for(const[t,e]of A){if(e.length<2)continue;c.push({kind:"two-sockets",message:`${e.length} sockets open to the same URL`,url:t,frameIds:[],at:Math.max(...e.map(n=>n.openedAt??n.createdAt))})}const w=new Map;for(const t of i){if(!t.sentWhileClosed)continue;w.set(t.socketId,[...w.get(t.socketId)??[],t])}for(const[t,e]of w){const n=[...e].sort((s,o)=>s.timestamp-o.timestamp);c.push({kind:"sent-while-closed",message:`Sent ${x(n.length,"message")} while the socket was not open`,socketId:t,url:r.get(t)?.url,frameIds:n.map(s=>s.id),at:n[0].timestamp})}return c.sort((t,e)=>e.at-t.at)}
@@ -0,0 +1 @@
1
+ "use strict";export const BURST_GAP_MS=1500;export const FOLD_MIN=3;function d(s,n,o){if(n.socketId&&s.socketId!==n.socketId)return false;if(s.ping&&!n.showPings)return false;const t=n.filter??{kind:"all"};if(t.kind==="problems"&&!o.has(s.id))return false;if(t.kind==="direction"&&s.direction!==t.direction)return false;if(t.kind==="type"&&!matchesPrefix(s.type,t.prefix))return false;if(n.search){const i=n.search.toLowerCase();if(!`${s.type??""} ${s.data??""} ${s.reason??""}`.toLowerCase().includes(i))return false}return true}export function foldFrames(s,n={}){const o=new Map;for(const e of s.problems)for(const r of e.frameIds)if(!o.has(r))o.set(r,e);const t=[];for(const e of s.frames){if(!d(e,n,o))continue;const r=o.get(e.id);const c=t[t.length-1];const f=c?.frames[c.frames.length-1];const a=f&&!r&&!c.problem&&e.kind==="message"&&f.kind==="message"&&!e.fake&&!f.fake&&!e.replyId&&!f.replyId&&e.type!==void 0&&e.type===f.type&&e.direction===f.direction&&e.socketId===f.socketId&&f.timestamp-e.timestamp<=BURST_GAP_MS;if(a)c.frames.push(e);else t.push({frames:[e],...r?{problem:r}:{}})}const i=[];for(const e of t){const r=e.frames[e.frames.length-1].id;if(e.frames.length>=FOLD_MIN&&!n.expanded?.has(r)){i.push({frame:e.frames[0],count:e.frames.length,foldKey:r});continue}for(const c of e.frames)i.push({frame:c,count:1,...e.problem?{problem:e.problem}:{}})}return i}export function matchesPrefix(s,n){if(!s)return false;return s.startsWith(n)||/[.:/]$/.test(n)&&s===n.slice(0,-1)}export function topTypePrefixes(s,n=4){const o=new Map;for(const t of s){if(t.kind!=="message"||t.ping||!t.type)continue;const i=t.type.search(/[.:/]/);const e=i>0?`${t.type.slice(0,i+1)}`:t.type;o.set(e,(o.get(e)??0)+1)}for(const[t,i]of[...o]){const e=[".",":","/"].map(r=>t+r).find(r=>o.has(r));if(!e)continue;o.set(e,o.get(e)+i);o.delete(t)}return[...o.entries()].sort((t,i)=>i[1]-t[1]).slice(0,n).map(([t])=>t)}
@@ -0,0 +1 @@
1
+ "use strict";export function clockTime(t){const n=new Date(t);return[n.getHours(),n.getMinutes(),n.getSeconds()].map(e=>String(e).padStart(2,"0")).join(":")}export function shortDuration(t){if(t<1e3)return`${Math.max(0,Math.round(t))}ms`;if(t<1e4)return`${(t/1e3).toFixed(1)}s`;const n=Math.round(t/1e3);if(n<60)return`${n}s`;const e=Math.floor(n/60);if(e<60)return`${e}m ${n%60}s`;return`${Math.floor(e/60)}h ${e%60}m`}export function shortUrl(t){return t.replace(/^wss?:\/\//,"")}const u={1e3:"normal",1001:"going away",1006:"lost connection",1008:"rejected",1011:"server error",1012:"server restart",4999:"Buoy"};export function closeLabel(t,n=false){if(t===void 0)return"Closed";const e=t===1006&&n?"couldn't connect":u[t];return e?`Closed ${t} \xB7 ${e}`:`Closed ${t}`}export function connectionStatus(t,n){switch(t.state){case"connecting":return"Connecting";case"open":return`Open ${shortDuration(n-(t.openedAt??t.createdAt))}`;case"closing":return"Closing";case"closed":return`${closeLabel(t.closeCode,t.openedAt===void 0)}${t.closedByBuoy?" (Buoy)":""}`}}const d=["payload","data","body","d"];const f=["content","text","message","body"];function y(t){if(!t||typeof t!=="object"||Array.isArray(t))return void 0;for(const n of f){const e=t[n];if(typeof e==="string"&&e.trim())return e.trim().slice(0,80)}return void 0}export function previewText(t){if(t.binary)return t.data??"[binary]";const n=(t.data??"").replace(/\s+/g," ").trim();if(!t.json||!t.type)return n;try{const e=JSON.parse(t.data??"");if(e&&typeof e==="object"&&!Array.isArray(e)){const{type:l,event:p,op:g,action:$,method:h,...r}=e;for(const a of["requestId","request_id","correlationId","correlation_id","ref","id"]){if(String(r[a])===t.correlationId)delete r[a]}const o=Object.keys(r);const s=o.length===1&&d.includes(o[0])?r[o[0]]:void 0;const i=s&&typeof s==="object"?s:r;const c=y(i);return`${c?`"${c}" \xB7 `:""}${JSON.stringify(i)}`}}catch{}return n}export function prettyData(t){if(!t.json||!t.data)return t.data??"";try{return JSON.stringify(JSON.parse(t.data),null,2)}catch{return t.data}}
@@ -0,0 +1 @@
1
+ "use strict";import{classifyKey as g}from"@buoy-gg/shared-ui";export const MAX_FRAME_CHARS=64*1024;export const HIDDEN="[hidden]";const x=["type","event","op","action","method"];const I=["requestId","request_id","correlationId","correlation_id","ref","id"];const T=["success","ok","result","error","status"];const O=/^(ping|pong|heartbeat|hb|keep-?alive)$/i;const P=new Set(["2","3","ping","pong","heartbeat","primus::ping","primus::pong"]);const S=/^(auth|authenticate|authorize|login|sign-?in|connection_init)$/i;const d=/\beyJ[\w-]{6,}\.[\w-]{6,}\.[\w-]*/g;const N=/^4[0-6](?:\/[^,]*,)?(\d*)([[{].*)$/s;export const MAX_PARSE_CHARS=256*1024;const B=/("?)([\w.-]{2,64})\1(\s*[:=]\s*)("(?:[^"\\]|\\.)*(?:"|$)|(?:(?:Bearer|Basic|Token)\s+)?[^\s,;&}\]"]+)/gi;const Y=/\b(Bearer|Basic|Token)\s+[\w.~+/=-]{8,}/g;const j=/("payload"\s*:\s*)("(?:[^"\\]|\\.)*(?:"|$)|[^\s,}\]]+)/;const L=/"(?:type|event|op|action|method)"\s*:\s*"([^"\\]{1,80})"/;function k(e){if(typeof ArrayBuffer!=="undefined"){if(e instanceof ArrayBuffer)return e.byteLength;if(ArrayBuffer.isView(e))return e.byteLength}if(typeof Blob!=="undefined"&&e instanceof Blob)return e.size;return null}function R(e){try{const t=e instanceof ArrayBuffer?new Uint8Array(e):ArrayBuffer.isView(e)?new Uint8Array(e.buffer,e.byteOffset,e.byteLength):null;if(!t)return"";const i=Array.from(t.subarray(0,32),s=>s.toString(16).padStart(2,"0")).join(" ");return t.byteLength>32?`${i} \u2026`:i}catch{return""}}export function hideSecrets(e,t=0){if(t>20)return e!==null&&typeof e==="object"?HIDDEN:typeof e==="string"?e.replace(d,HIDDEN):e;if(typeof e==="string")return e.replace(d,HIDDEN);if(Array.isArray(e))return e.map(i=>hideSecrets(i,t+1));if(e&&typeof e==="object"){const i={};for(const[s,n]of Object.entries(e)){i[s]=g(s)==="secret"&&n!=null&&n!==""?HIDDEN:hideSecrets(n,t+1)}return i}return e}export function scrubText(e,t=0){return e.replace(B,(i,s,n,r,c)=>{if(g(n)==="secret")return`${s}${n}${s}${r}${c.startsWith('"')?`"${HIDDEN}"`:HIDDEN}`;if(c.startsWith('"')&&c.length>2&&t<3){const u=c.endsWith('"')&&c.length>1;const y=c.slice(1,u?-1:void 0);return`${s}${n}${s}${r}"${scrubText(y,t+1)}${u?'"':""}`}return i}).replace(Y,`$1 ${HIDDEN}`).replace(d,HIDDEN)}export function hideUrlSecrets(e){const t=e.replace(/^([a-z][\w+.-]*:\/\/[^/@:?#]*):[^/@?#]*@/i,`$1:${HIDDEN}@`);const i=t.indexOf("?");if(i===-1)return t.replace(d,HIDDEN);const s=t.slice(i+1).split("&").map(n=>{const r=n.indexOf("=");if(r===-1)return n;let c=n.slice(0,r);try{c=decodeURIComponent(c)}catch{}return g(c)==="secret"?`${n.slice(0,r)}=${HIDDEN}`:n}).join("&");return`${t.slice(0,i)}?${s}`.replace(d,HIDDEN)}export function socketKey(e){const t=e.search(/[?#]/);return t===-1?e:e.slice(0,t)}function m(e,t){for(const i of t){const s=e[i];if(typeof s==="string"&&s)return s;if(typeof s==="number"&&Number.isFinite(s))return String(s)}return void 0}const E="phx_reply";function H(e){const t=m(e,x);return{type:t,correlationId:m(e,I),replyShaped:t===E||T.some(i=>i in e)}}function J(e){if(e.length!==5||typeof e[2]!=="string"||typeof e[3]!=="string")return null;const t=e[1];return{type:e[3],correlationId:typeof t==="string"||typeof t==="number"?String(t):void 0,replyShaped:e[3]===E}}export function readMessage(e){const t=k(e);if(t!==null){const f=R(e);return{data:`[binary, ${t} bytes]${f?` ${f}`:""}`,size:t,binary:true}}const i=typeof e==="string"?e:String(e);const s=i.length;if(s>MAX_PARSE_CHARS){const f=i.slice(0,MAX_FRAME_CHARS);const p=f.trimStart()[0];const l=L.exec(f.slice(0,4096))?.[1];const A=l?scrubText(l):void 0;const _=l&&S.test(l)?f.replace(j,`$1"${HIDDEN}"`):f;return{data:scrubText(_).replace(/\beyJ[\w-]{6,}(?:\.[\w-]*)?$/,HIDDEN),size:s,truncated:true,...p==="{"||p==="["?{json:true}:{},...A?{type:A}:{}}}const n=i.trim();if(P.has(n.toLowerCase()))return{data:i,size:s,ping:true,type:n};let r;let c=false;let u;const y=N.exec(n);try{if(y){r=JSON.parse(y[2]);u=y[1]||void 0}else if(n.startsWith("{")||n.startsWith("[")){r=JSON.parse(n);c=true}}catch{r=void 0}let o={};let $=false;let a;if(y&&r&&typeof r==="object"){const f=n[1]==="3"||n[1]==="6";if(Array.isArray(r)){o=f?{correlationId:u,replyShaped:true}:{type:typeof r[0]==="string"?r[0]:void 0,correlationId:u}}a=`${n.slice(0,n.length-y[2].length)}${JSON.stringify(hideSecrets(r))}`}else if(r&&typeof r==="object"&&!Array.isArray(r)){const f=r;o=H(f);let p=hideSecrets(f);if(o.type&&S.test(o.type)&&"payload"in p&&p.payload!=null){p={...p,payload:HIDDEN}}a=JSON.stringify(p)}else if(c){if(Array.isArray(r)){o=J(r)??{};$=o.type!==void 0&&r[2]==="phoenix"}a=JSON.stringify(hideSecrets(r))}else{a=scrubText(i)}if(o.correlationId)o.correlationId=scrubText(o.correlationId);if(o.type)o.type=scrubText(o.type);const b=$||!!o.type&&O.test(o.type);const h=a.length>MAX_FRAME_CHARS;return{data:h?a.slice(0,MAX_FRAME_CHARS):a,size:s,...h?{truncated:h}:{},...c||y?{json:true}:{},...o,...b?{ping:b}:{}}}
@@ -0,0 +1 @@
1
+ "use strict";import{closeLabel as r,shortUrl as i}from"./format";import{socketStore as n}from"./socketStore";export function toSocketMoment(t,o){const e={id:`socket-${t.id}`,source:"socket",timestamp:t.timestamp,subtitle:i(o),originalEvent:t,correlationId:t.socketId};switch(t.kind){case"open":return{...e,title:"Socket opened",status:"success"};case"error":return{...e,title:"Socket error",status:"error"};case"close":return{...e,title:`Socket ${r(t.code,t.neverOpened).toLowerCase()}${t.byBuoy?" (Buoy)":""}`,status:t.code===1e3||t.code===1001?"neutral":"error"};case"message":if(t.fake!=="inject")return null;return{...e,title:`Buoy pushed ${t.type??"a message"}`,status:"neutral"}}}export function onSocketMoment(t){return n.onEvent(o=>{const e=n.getState().connections.find(c=>c.id===o.socketId);const s=toSocketMoment(o,e?.url??"");if(s)t(s)})}
@@ -0,0 +1 @@
1
+ "use strict";import{BaseEventStore as I,getAccountAccess as p,isBuoyRequest as S,subscribeAccountAccess as A}from"@buoy-gg/shared-ui";import{conditionsCanApply as C,getEffectiveNetworkConnection as z,getNetworkCondition as E,subscribeNetworkConditions as M}from"../conditions/store";import{findProblems as O,REPLY_TIMEOUT_MS as w}from"./findProblems";const m=2*6e4;import{hideUrlSecrets as R,readMessage as T,socketKey as y}from"./readMessage";import{installWebSocketPatch as _}from"./webSocketPatch";const x=1e3;const v=50;const $=50;const F=200;const L=3e4;const N=/\/(hot|message|inspector\/(device|debug)|debugger-proxy|__expo[^/?]*)(?:[/?]|$)/;const D=/^wss?:\/\/[^/]+:8097(?:\/|$)/;export function isToolingSocket(u){return S(u)||N.test(u)||D.test(u)}class B extends I{connections=new Map;controls=new Map;pending=new Map;answered=new Map;socketSeq=0;frameSeq=0;blocked=false;offline=false;installed=false;mirror=false;remote=null;capturingSince=null;mirrored=null;cache=null;version=0;recheck=null;retryOnAccess=null;constructor(){super({storeName:"sockets",maxEvents:x})}install(){if(this.installed||this.mirror)return this.installed;if(p().status==="locked"){this.retryOnAccess??=A(()=>{if(p().status!=="locked"&&this.install()){this.retryOnAccess?.();this.retryOnAccess=null}});return false}this.installed=_(this);if(this.installed){this.capturingSince=Date.now();M(()=>this.syncOffline());this.syncOffline()}return this.installed}startCapturing(){this.install()}stopCapturing(){}isCapturing(){return this.installed}disableCapture(){this.mirror=true;super.disableCapture()}bump(){this.notifyArrayListeners()}nextFrameId(){return`f${++this.frameSeq}`}setConnection(e,t){const n=this.connections.get(e);if(n)this.connections.set(e,{...n,...t})}push(e){this.addEvent(e)}register(e,t,n){if(this.mirror||isToolingSocket(e)||p().status==="locked")return null;const s=`s${++this.socketSeq}`;const i=R(e);const o=y(i);let r;for(const c of this.connections.values())if(y(c.url)===o)r=c;const a=r?.openedAt!==void 0&&(r.closedAt??Date.now())-r.openedAt>=L;const f=r?.state==="closed"&&r.closeCode!==1e3&&!a;const d=f?r.attempt+1:1;this.connections.set(s,{id:s,url:i,...t?.length?{protocols:t}:{},attempt:d,state:"connecting",createdAt:Date.now(),sent:0,received:0,bytesSent:0,bytesReceived:0,pings:0});this.controls.set(s,n);this.trimConnections();this.bump();return s}trimConnections(){if(this.connections.size<=v)return;for(const e of this.connections.values()){if(this.connections.size<=v)break;if(e.state!=="closed")continue;this.connections.delete(e.id);this.controls.delete(e.id);this.pending.delete(e.id)}}open(e){const t=Date.now();this.setConnection(e,{state:"open",openedAt:t});this.push({id:this.nextFrameId(),socketId:e,kind:"open",timestamp:t})}close(e,t,n,s){const i=this.connections.get(e);if(!i||i.state==="closed")return;const o=Date.now();this.setConnection(e,{state:"closed",closedAt:o,closeCode:t,closeReason:n||void 0,...s?{closedByBuoy:true}:{},frozen:false});this.controls.delete(e);this.pending.delete(e);this.trimConnections();this.push({id:this.nextFrameId(),socketId:e,kind:"close",timestamp:o,...t!==void 0?{code:t}:{},...n?{reason:n}:{},...s?{byBuoy:s}:{},...i.openedAt===void 0?{neverOpened:true}:{}})}error(e){this.push({id:this.nextFrameId(),socketId:e,kind:"error",timestamp:Date.now()})}message(e,t,n,s){const i=this.connections.get(e);if(!i||p().status==="locked")return void 0;const o=T(n);const r=Date.now();const a=this.nextFrameId();const f={id:a,socketId:e,kind:"message",direction:t,timestamp:r,data:o.data,size:o.size,...o.binary?{binary:true}:{},...o.truncated?{truncated:true}:{},...o.json?{json:true}:{},...o.type?{type:o.type}:{},...o.correlationId?{correlationId:o.correlationId}:{},...o.ping?{ping:true}:{},...s?.fake?{fake:s.fake}:{},...s?.held?{held:true}:{},...s?.sentWhileClosed?{sentWhileClosed:true}:{}};const d=t==="out";this.setConnection(e,{lastMessageAt:r,...o.ping?{pings:i.pings+1}:d?{sent:i.sent+1,bytesSent:i.bytesSent+o.size}:{received:i.received+1,bytesReceived:i.bytesReceived+o.size}});if(o.correlationId&&!s?.held&&!(d&&s?.sentWhileClosed)){let c=this.pending.get(e);if(d){if(!c)this.pending.set(e,c=new Map);c.set(o.correlationId,{frameId:a,at:r});this.scheduleRecheck()}else{const h=c?.get(o.correlationId);if(h&&r-h.at>m)c.delete(o.correlationId);const b=h&&r-h.at<=m?h.frameId:void 0;const l=b?this.events.find(k=>k.id===b):void 0;if(l&&(o.replyShaped||o.type&&o.type===l.type)){c.delete(o.correlationId);f.replyTo=l.id;const k=r-l.timestamp;this.events=this.events.map(g=>g.id===l.id?{...g,replyId:a,replyMs:k}:g);if(l.type)this.rememberAnswered(y(i.url),l.type)}}}this.push(f);return a}rememberAnswered(e,t){let n=this.answered.get(e);if(n)this.answered.delete(e);else n=new Set;this.answered.set(e,n);n.delete(t);n.add(t);while(n.size>F)n.delete(n.values().next().value);while(this.answered.size>$)this.answered.delete(this.answered.keys().next().value)}scheduleRecheck(){if(this.recheck)clearTimeout(this.recheck);this.recheck=null;const e=Date.now();let t=Infinity;for(const[n,s]of this.pending){for(const[i,o]of s){const r=e-o.at;if(r>m)s.delete(i);else t=Math.min(t,r<w?o.at+w:o.at+m+1)}if(s.size===0)this.pending.delete(n)}if(t===Infinity)return;this.recheck=setTimeout(()=>{this.recheck=null;this.bump();this.scheduleRecheck()},Math.max(0,t-e)+100)}cutOff(){if(this.offline)return"Offline (Buoy)";return this.blocked?"Blocked by Buoy":null}isFrozen(e){return this.connections.get(e)?.frozen===true}syncOffline(){const e=C()&&(E()==="offline"||["offline","noInternet"].includes(z()));if(e===this.offline)return;this.offline=e;if(e){for(const t of[...this.controls.values()])t.fakeClose(1006,"Offline (Buoy)")}this.bump()}getState(){if(this.mirrored)return this.mirrored;if(this.cache?.version===this.version&&this.cache.state.frames===this.events)return this.cache.state;const e=[...this.connections.values()].reverse();const t=this.getEvents();const n={connections:e,frames:t,problems:O(t,e,Date.now(),this.answered),tests:{blocked:this.blocked,offline:this.offline,frozen:e.filter(s=>s.frozen).map(s=>s.id)},capturingSince:this.capturingSince};this.cache={version:this.version,state:n};return n}getFrame(e){return this.getState().frames.find(t=>t.id===e)}subscribeState(e){return this.subscribeToEvents(()=>e())}setRemote(e){this.remote=e}async loadFrame(e){if(this.remote)return this.remote.getFrame(e);const t=this.getFrame(e);if(!t)return null;const n=t.replyId??t.replyTo;return{frame:t,partner:n?this.getFrame(n)??null:null}}applySnapshot(e){this.mirrored=e;this.notifyArrayListeners()}async act(e){if(this.remote)return this.remote.act(e);return this.actLocal(e)}actLocal(e){const t="socketId"in e?this.controls.get(e.socketId):void 0;const n=s=>({ok:false,message:this.connections.has(s)?`Socket ${s} is closed.`:`No socket ${s}. Read get_sockets for ids.`});switch(e.action){case"inject":{if(!t)return n(e.socketId);const s=t.inject(e.data);return{ok:true,frameId:s,message:`Pushed the message into the app on ${e.socketId}, as if the server sent it.`}}case"send":{if(!t)return n(e.socketId);const s=this.connections.get(e.socketId)?.state==="connecting";const i=t.send(e.data);const o=i?this.getFrame(i)?.held:false;return o?{ok:false,frameId:i,message:s?`Held back: ${e.socketId} is still connecting, so the server did not get it. Try again once it's open.`:`Held back: ${e.socketId} is frozen, blocked or offline, so the server did not get it.`}:{ok:true,frameId:i,message:`Sent to the server on ${e.socketId}.`}}case"close":{if(!t)return n(e.socketId);const s=e.code??1006;if(!Number.isInteger(s)||s<1e3||s>4999){return{ok:false,message:`Close code ${s} isn't a WebSocket close code. Use 1000-4999, like 1006, 1008 or 1001.`}}const i=e.reason??(s===1006?"Dropped by Buoy":"Closed by Buoy");t.fakeClose(s,i);return{ok:true,message:`Closed ${e.socketId} with code ${s}. The app got the close; watch for its reconnect.`}}case"freeze":{if(!t)return n(e.socketId);this.setConnection(e.socketId,{frozen:e.frozen});this.bump();return{ok:true,message:e.frozen?`Froze ${e.socketId}: it still looks open, but no messages get through either way.`:`Unfroze ${e.socketId}. Messages held while frozen are lost.`}}case"block":{this.blocked=e.blocked;if(e.blocked)for(const s of[...this.controls.values()])s.fakeClose(1006,"Blocked by Buoy");this.bump();return{ok:true,message:e.blocked?"Blocked: open sockets dropped, and every new one fails until you unblock.":"Unblocked: new sockets can connect again."}}case"reset":{this.blocked=false;for(const s of this.connections.values())if(s.frozen)this.setConnection(s.id,{frozen:false});this.bump();return{ok:true,message:"Reset: no socket is frozen or blocked. The app reconnects on its own schedule."}}case"clear":{this.clearEvents();return{ok:true,message:"Cleared the message list."}}}}clearEvents(){for(const[e,t]of this.connections)if(t.state==="closed")this.connections.delete(e);this.pending.clear();this.answered.clear();super.clearEvents()}notifyArrayListeners(){this.version++;super.notifyArrayListeners()}}export const socketStore=new B;
@@ -0,0 +1 @@
1
+ "use strict";import{matchesPrefix as p}from"./foldFrames";import{socketKey as s}from"./readMessage";import{socketStore as c}from"./socketStore";export const SNAPSHOT_FRAMES=300;export const SNAPSHOT_TEXT=1e3;const m=200;export const LIST_BODY_TEXT=4e3;function d(t,e){if(!t.data||t.data.length<=e)return t;return{...t,data:t.data.slice(0,e),dataCut:true}}export function matchesType(t,e){if(!t)return false;const r=e.toLowerCase();const o=t.toLowerCase();return r.endsWith("*")?p(o,r.slice(0,-1)):o.includes(r)}export function querySockets(t,e={}){const r=new Set(t.problems.flatMap(n=>n.frameIds));let o=t.frames;if(e.frameId)o=o.filter(n=>n.id===e.frameId||n.replyTo===e.frameId||n.replyId===e.frameId);if(e.socketId)o=o.filter(n=>n.socketId===e.socketId);if(!e.includePings&&!e.frameId)o=o.filter(n=>!n.ping);if(e.type)o=o.filter(n=>matchesType(n.type,e.type));if(e.direction==="lifecycle")o=o.filter(n=>n.kind!=="message");else if(e.direction)o=o.filter(n=>n.direction===e.direction);if(e.problems)o=o.filter(n=>r.has(n.id));if(e.since)o=o.filter(n=>n.timestamp>=e.since);const l=o.length;const a=typeof e.limit==="number"&&e.limit>=0?Math.min(e.limit,500):50;const f=o.slice(0,a).map(n=>e.frameId?n:d(n,e.includeBodies?LIST_BODY_TEXT:m));const i=e.socketId?t.connections.find(n=>n.id===e.socketId):void 0;const u=i?s(i.url):void 0;return{connections:e.socketId?t.connections.filter(n=>n.id===e.socketId):t.connections,problems:e.socketId?t.problems.filter(n=>n.socketId?n.socketId===e.socketId:!!n.url&&s(n.url)===u):t.problems,tests:t.tests,capturingSince:t.capturingSince,frames:f,total:l,flagged:[...r]}}function I(t){if(!t||typeof t!=="object")return null;const e=t;const r=typeof e.socketId==="string"?e.socketId:"";const o=typeof e.data==="string"?e.data:e.data!==void 0?JSON.stringify(e.data):void 0;switch(e.action){case"inject":case"send":return r&&o!==void 0?{action:e.action,socketId:r,data:o}:null;case"close":return r?{action:"close",socketId:r,...typeof e.code==="number"?{code:e.code}:{},...typeof e.reason==="string"?{reason:e.reason}:{}}:null;case"freeze":return r?{action:"freeze",socketId:r,frozen:e.frozen!==false}:null;case"block":return{action:"block",blocked:e.blocked!==false};case"reset":case"clear":return{action:e.action};default:return null}}export const socketsSyncAdapter={version:1,getSnapshot:()=>{const t=c.getState();return{...t,frames:t.frames.slice(0,SNAPSHOT_FRAMES).map(e=>d(e,SNAPSHOT_TEXT))}},subscribe:t=>c.subscribeState(t),actions:{getFrame:t=>{const e=t&&typeof t==="object"?t.id:void 0;if(typeof e!=="string")return null;const r=c.getFrame(e);if(!r)return null;const o=r.replyId??r.replyTo;return{frame:r,partner:o?c.getFrame(o)??null:null}},query:t=>querySockets(c.getState(),t??{}),act:t=>{const e=I(t);if(!e){return{ok:false,message:"Unknown or incomplete action. inject/send need socketId and data; close/freeze need socketId."}}return c.actLocal(e)}}};
@@ -0,0 +1 @@
1
+ "use strict";
@@ -0,0 +1 @@
1
+ "use strict";const A=["open","message","close","error"];const V=0;const P=1;const z=3;const w=Symbol.for("buoy.websocket.patched");const G=4999;function Y(n,c,y){try{if(typeof c==="function")c.call(n,y);else if(c&&typeof c.handleEvent==="function"){c.handleEvent(y)}}catch(m){const h=globalThis.reportError;if(typeof h==="function")h(m);else console.error(m)}}function l(n){try{return n()}catch(c){if(typeof __DEV__!=="undefined"&&__DEV__)console.warn("[Buoy] Couldn't record a socket event:",c);return void 0}}function D(n,c,y){return{type:n,target:c,currentTarget:c,isTrusted:false,timeStamp:Date.now(),defaultPrevented:false,preventDefault(){},stopPropagation(){},stopImmediatePropagation(){},...y}}export function isWebSocketPatched(){const n=globalThis.WebSocket;return typeof n==="function"&&n[w]===true}export function installWebSocketPatch(n){const c=globalThis;const y=c.WebSocket;if(typeof y!=="function"||y[w])return false;const m=y.prototype;const h=m.send;const L=m.close;const I=m.addEventListener;const R=m.removeEventListener;class j extends y{static[w]=true;constructor(a,u,...E){super(a,u,...E);const i=this;const _={open:[],message:[],close:[],error:[]};let p=false;let S=false;let o=null;const O=Object.getOwnPropertyDescriptor(i,"readyState");let x=O&&"value"in O?O.value:void 0;const k=()=>O&&"value"in O?x:Reflect.get(m,"readyState",i);Object.defineProperty(i,"readyState",{configurable:true,enumerable:true,get:()=>p?z:S?V:k(),set:e=>{x=e}});const v=()=>{const e=p;p=false;try{L.call(i,G,"Closed by Buoy")}catch{}finally{p=e}};const C=(e,t)=>{const s=_[e];let r=false;const f=t;const b=f?.stopImmediatePropagation;if(f&&typeof b==="function"){try{f.stopImmediatePropagation=()=>{r=true;b.call(f)}}catch{}}for(const d of[...s]){if(r)break;const g=s.indexOf(d);if(g===-1)continue;if(d.once)s.splice(g,1);Y(i,d.listener,t)}};for(const e of A){Object.defineProperty(i,`on${e}`,{configurable:true,enumerable:true,get:()=>_[e].find(t=>t.attr)?.listener??null,set:t=>{const s=_[e];const r=s.find(f=>f.attr);if(typeof t==="function"){if(r)r.listener=t;else s.push({listener:t,once:false,capture:false,attr:true})}else if(r){s.splice(s.indexOf(r),1)}}})}const N=e=>typeof e==="boolean"?e:!!e?.capture;i.__buoyAdd=(e,t,s)=>{const r=_[e];if(!r)return false;const f=N(s);if(!t||r.some(g=>!g.attr&&g.listener===t&&g.capture===f))return true;const b=typeof s==="object"?s:void 0;if(b?.signal?.aborted)return true;const d={listener:t,once:!!b?.once,capture:f};r.push(d);b?.signal?.addEventListener?.("abort",()=>{const g=r.indexOf(d);if(g!==-1)r.splice(g,1)},{once:true});return true};i.__buoyRemove=(e,t,s)=>{const r=_[e];if(!r)return false;const f=N(s);const b=r.findIndex(d=>!d.attr&&d.listener===t&&d.capture===f);if(b!==-1)r.splice(b,1);return true};i.__buoySend=e=>{if(!o)return h.call(i,e);if(p){l(()=>n.message(o,"out",e,{sentWhileClosed:true,held:true}));return}if(S){l(()=>n.message(o,"out",e,{sentWhileClosed:true,held:true}));const t=globalThis.DOMException;throw typeof t==="function"?new t("Failed to execute 'send' on 'WebSocket': Still in CONNECTING state.","InvalidStateError"):new Error("INVALID_STATE_ERR")}if(k()!==P){l(()=>n.message(o,"out",e,{sentWhileClosed:true}));return h.call(i,e)}if(l(()=>n.cutOff()!==null||n.isFrozen(o))===true){l(()=>n.message(o,"out",e,{held:true}));return}l(()=>n.message(o,"out",e));return h.call(i,e)};const T={inject(e){if(!o)return void 0;const t=l(()=>n.message(o,"in",e,{fake:"inject"}));C("message",D("message",i,{data:e,origin:"",lastEventId:"",ports:[]}));return t},send(e){if(!o)return void 0;const t=p||k()!==P||l(()=>n.cutOff()!==null||n.isFrozen(o))===true;const s=l(()=>n.message(o,"out",e,t?{fake:"send",held:t}:{fake:"send"}));if(!t)h.call(i,e);return s},fakeClose(e,t){if(p)return;p=true;if(o&&e===1006)l(()=>n.error(o));if(o)l(()=>n.close(o,e,t,true));if(e===1006)C("error",D("error",i,{message:t}));C("close",D("close",i,{code:e,reason:t,wasClean:e!==1006}));v()},isOpen:()=>!p&&k()===P};const B=typeof a==="string"?a:String(a);const F=u==null?void 0:Array.isArray(u)?u:[u];o=l(()=>n.register(B,F,T))??null;for(const e of A){I.call(i,e,t=>{if(p||S){if(e==="open")v();return}if(o){const s=o;const r=e==="open"?l(()=>n.cutOff()):null;if(r)return T.fakeClose(1006,r);if(e==="open")l(()=>n.open(s));else if(e==="close")l(()=>n.close(s,t?.code,t?.reason,false));else if(e==="error")l(()=>n.error(s));else{const f=l(()=>n.cutOff()!==null||n.isFrozen(s))===true;l(()=>n.message(s,"in",t?.data,f?{held:f}:void 0));if(f)return}}C(e,t)})}const W=o?l(()=>n.cutOff()):null;if(W){S=true;v();setTimeout(()=>T.fakeClose(1006,W),0)}}addEventListener(a,u,E){if(this.__buoyAdd?.(a,u,E))return;return I.call(this,a,u,E)}removeEventListener(a,u,E){if(this.__buoyRemove?.(a,u,E))return;return R.call(this,a,u,E)}send(a){const u=this;return u.__buoySend?u.__buoySend(a):h.call(u,a)}}c.WebSocket=j;return true}
@@ -1 +1 @@
1
- "use strict";import{getNetworkConditions as v,setNetworkConditions as H,subscribeNetworkConditions as T}from"../conditions/store";import{networkEventStore as f}from"../utils/networkEventStore";import{flagsForEventId as O,networkSavedStore as a}from"../utils/networkSavedStore";import{overrideRulesStore as i}from"../overrides/overrideRulesStore";import{draftFromEvent as x}from"../overrides/presets";import{inspectEngine as B,overridesCanApply as j,OVERRIDES_INACTIVE_REASON as C}from"../overrides/engine";import{getNetworkListenerCount as E,isNetworkInterceptionLive as L,isNetworkListening as P}from"../utils/networkListener";import{MAX_RULES as R}from"../overrides/types";import{approxJsonSize as m,isOverWireBudget as M}from"@buoy-gg/shared-ui";import{expandKeyedArrays as _,patchFromPath as $,refusalText as J,shapeKind as w,suggestedPatch as W,typedEditViolations as U}from"@buoy-gg/shared-ui";export const SNAPSHOT_BODY_INLINE_LIMIT=16*1024;export const SNAPSHOT_EVENTS_BUDGET=1.25*1024*1024;function S(e,t){if(e===void 0)return false;if((t??0)>SNAPSHOT_BODY_INLINE_LIMIT)return true;return M(e,SNAPSHOT_BODY_INLINE_LIMIT)}const I=new WeakMap;const A=new WeakMap;function k(e){const t=I.get(e);if(t)return t;let n;try{n=z(e)}catch{n=K(e)}I.set(e,n);return n}function K(e){const t={...e,requestData:void 0,responseData:void 0,graphqlVariables:void 0,requestBodyOmitted:e.requestData!==void 0?true:void 0,responseBodyOmitted:e.responseData!==void 0?true:void 0};let n=1024;try{n=m(t,SNAPSHOT_EVENTS_BUDGET).bytes}catch{}return{event:t,bytes:n}}function z(e){const t=S(e.requestData,e.requestSize);const n=S(e.responseData,e.responseSize);const r=V(e.graphqlVariables);const o=N(e.requestHeaders);const s=N(e.responseHeaders);const d=t||n||r!==e.graphqlVariables||o!==e.requestHeaders||s!==e.responseHeaders;let u=e;if(d){u={...e};if(t){u.requestData=void 0;u.requestBodyOmitted=true}if(n){u.responseData=void 0;u.responseBodyOmitted=true}if(r!==e.graphqlVariables){u.graphqlVariables=r}if(o!==e.requestHeaders){u.requestHeaders=o;u.headersOmitted=true}if(s!==e.responseHeaders){u.responseHeaders=s;u.headersOmitted=true}}return{event:u,bytes:m(u,SNAPSHOT_EVENTS_BUDGET).bytes}}function F(e){const t=A.get(e);if(t)return t;const{event:n}=k(e);const r={...n};if(r.requestData!==void 0){r.requestData=void 0;r.requestBodyOmitted=true}if(r.responseData!==void 0){r.responseData=void 0;r.responseBodyOmitted=true}if(r.graphqlVariables!==void 0){r.graphqlVariables=V(r.graphqlVariables,true)}const o={event:r,bytes:m(r,SNAPSHOT_EVENTS_BUDGET).bytes};A.set(e,o);return o}function G(e){const t=new Array(e.length);let n=0;for(let r=0;r<e.length;r++){const o=k(e[r]);if(n+o.bytes<=SNAPSHOT_EVENTS_BUDGET){t[r]=o.event;n+=o.bytes}else{const s=F(e[r]);t[r]=s.event;n+=s.bytes}}return t}function V(e,t=false){if(!e)return e;if(!t&&!S(e,void 0))return e;const n={};for(const[r,o]of Object.entries(e)){if(typeof o==="string"&&o.length<=64)n[r]=o;else if(typeof o==="number"||typeof o==="boolean"){n[r]=o}}return Object.keys(n).length>0?n:void 0}export const SNAPSHOT_HEADER_VALUE_LIMIT=64;function N(e){if(!e)return e;let t=false;const n={};for(const[r,o]of Object.entries(e)){if(typeof o!=="string")continue;if(o.length<=SNAPSHOT_HEADER_VALUE_LIMIT){n[r]=o}else{n[r]=`${o.slice(0,SNAPSHOT_HEADER_VALUE_LIMIT)}\u2026 [${o.length-SNAPSHOT_HEADER_VALUE_LIMIT} more]`;t=true}}return t?n:e}const Y=e=>{let t=false;const n=e.rules.map(r=>{if(!r.body||r.body.length<=SNAPSHOT_BODY_INLINE_LIMIT){return r}t=true;return{...r,body:void 0,bodyOmitted:true}});return t?{...e,rules:n}:e};const b=e=>f.getEventById(e)??a.getEventById(e);const c=e=>e&&typeof e==="object"?e.id:void 0;const g=(e,t)=>!!(e&&typeof e==="object"&&e[t]);const h=()=>j()?{}:{active:false,inactiveReason:C};const X=["respond","fail","delay"];function Q(e,t){if(!e||typeof e!=="object")return null;const n=e.rule??e;if(!n||typeof n!=="object")return null;const r=n;const o=typeof r.urlPattern==="string"&&r.urlPattern.trim()?r.urlPattern.trim():t?.urlPattern??"";if(!o)return null;const s=X.includes(r.kind)?r.kind:t?.kind??"respond";return{id:typeof r.id==="string"?r.id:void 0,enabled:r.enabled!==false,name:typeof r.name==="string"?r.name:t?.name,urlPattern:o,methods:Array.isArray(r.methods)?r.methods.filter(d=>typeof d==="string").map(d=>d.toUpperCase()):t?.methods,requireHeader:typeof r.requireHeader==="string"&&r.requireHeader.trim()?r.requireHeader.trim():void 0,bodyIncludes:typeof r.bodyIncludes==="string"&&r.bodyIncludes?r.bodyIncludes.slice(0,4096):t?.bodyIncludes,graphqlOperation:typeof r.graphqlOperation==="string"&&r.graphqlOperation?r.graphqlOperation.slice(0,200):t?.graphqlOperation,graphqlVariables:typeof r.graphqlVariables==="string"?r.graphqlVariables.slice(0,4096):t?.graphqlVariables,sandbox:r.sandbox===true?true:void 0,kind:s,status:typeof r.status==="number"?r.status:t?.status,statusText:typeof r.statusText==="string"?r.statusText:t?.statusText,headers:r.headers&&typeof r.headers==="object"?r.headers:t?.headers,body:ee(r,t),failKind:r.failKind==="timeout"?"timeout":void 0,delayMs:typeof r.delayMs==="number"?r.delayMs:void 0,times:typeof r.times==="number"?r.times:null,alternate:r.alternate===true}}const q=e=>!!e&&typeof e==="object"&&!Array.isArray(e);const y=e=>q(e)||Array.isArray(e);function D(e,t,n="",r={shrunk:[],breaks:[]}){if(Array.isArray(e)&&Array.isArray(t)){if(t.length>0&&t.length<e.length){r.shrunk.push({path:n||"(root)",have:e.length,sent:t.length})}return t}if(!q(e)||!q(t))return t;const o={...e};for(const[s,d]of Object.entries(t)){const u=n?`${n}.${s}`:s;if(s in e){const l=w(e[s]);const p=w(d);if((l==="array"||l==="object")&&l!==p){r.breaks.push({path:u,from:l,to:p})}o[s]=D(e[s],d,u,r)}else{o[s]=d}}return o}function Z(e,t){if(e.body!=null||!y(e.bodyPatch)||typeof t!=="string")return[];try{return U(JSON.parse(t),e.bodyPatch,{noun:"response body"})}catch{return[]}}function ee(e,t){if(typeof e.body==="string")return e.body;if(e.body!=null)return JSON.stringify(e.body,null,2);const n=t?.body??(y(e.bodyPatch)&&typeof e.id==="string"?i.getState().rules.find(r=>r.id===e.id)?.body:void 0);if(y(e.bodyPatch)&&typeof n==="string"){try{return JSON.stringify(D(JSON.parse(n),e.bodyPatch),null,2)}catch{return n}}return n}function te(e){if(!e||typeof e!=="object")return null;const t=e.rule??e;if(!t||typeof t!=="object")return null;const n=t.id;if(typeof n!=="string")return null;const r=i.getState().rules.find(o=>o.id===n);return r?{...r}:null}function re(e){if(!e||typeof e!=="object")return null;const t=e.rule??e;if(!t||typeof t!=="object")return null;const n=t;if(n.bodyOmitted!==true||typeof n.id!=="string")return null;const r=i.getState().rules.find(o=>o.id===n.id);return r?{body:r.body}:null}function ne(e){if(!e||typeof e!=="object")return null;const t=e.fromRequestId;if(typeof t!=="string"||!t)return null;const n=b(t);return n?x(n):null}export const networkSyncAdapter={dispose:()=>{i.setEnabled(false)},version:6,getSnapshot:()=>{f.ensureInterception();return{conditions:v(),events:G(f.getEvents()),overrides:Y(i.getState()),saved:a.getRecords().map(e=>({...e,event:k(e.event).event}))}},subscribe:e=>{const t=f.subscribeToEvents(e);const n=T(e);const r=a.subscribe(e);const o=i.subscribe(e);return()=>{n();t();r();o()}},actions:{getNetworkConditions:v,setNetworkConditions:H,clearEvents:()=>{f.clearEvents()},getEventBody:e=>{const t=c(e);if(!t)return null;const n=b(t);if(!n)return null;return{url:n.url??null,method:n.method??null,status:n.status??null,override:n.override??null,condition:n.condition??null,requestData:n.requestData??null,responseData:n.responseData??null,requestHeaders:n.requestHeaders??null,responseHeaders:n.responseHeaders??null}},setPinned:e=>{const t=c(e);if(!t)return null;const n=b(t);if(!n)return null;const r=g(e,"pinned");const o=O(a.getState(),t).pinned;if(o===r)return{ok:true};return a.togglePin(n)},setSaved:e=>{const t=c(e);if(!t)return null;const n=b(t);if(!n)return null;const r=g(e,"saved");const o=O(a.getState(),t).saved;if(o===r)return{ok:true};return a.toggleSave(n)},removeSavedRecord:e=>{const t=e&&typeof e==="object"?e.key:void 0;if(!t)return null;a.remove(t);return{ok:true}},clearSavedRequests:()=>{a.clearSaved();return{ok:true}},clearPinnedRequests:()=>{a.clearPinned();return{ok:true}},setOverridesEnabled:e=>{i.setEnabled(g(e,"enabled"));return{ok:true,enabled:i.getState().enabled,...h()}},upsertOverrideRule:e=>{const t=e?.rule??e;const n=!!t&&t.body==null&&(y(t.bodyPatch)||typeof t.bodyPath==="string");const r=ne(e)??re(e)??(n?te(e):null);if(t&&typeof t.bodyPath==="string"&&t.body==null){const d=r?.body??(typeof t.id==="string"?i.getState().rules.find(p=>p.id===t.id)?.body:void 0);if(typeof d!=="string"){return{ok:false,error:"bodyPath needs something to patch: send fromRequestId (the captured request whose real response it addresses) or the id of an existing rule."}}if(t.bodyValue===void 0){return{ok:false,error:`Refused: sent \`bodyPath\` without \`bodyValue\`. Say what to set "${t.bodyPath}" to.`}}let u;try{u=JSON.parse(d)}catch{return{ok:false,error:"The captured response body is not JSON, so it cannot be addressed by path. Send a whole `body` instead."}}const l=$(u,t.bodyPath,t.bodyValue);if(!l.ok)return{ok:false,error:`Refused: ${l.error}`};t.bodyPatch=l.patch;delete t.bodyPath;delete t.bodyValue}if(t&&y(t.bodyPatch)&&t.body==null){const d=r?.body??(typeof t.id==="string"?i.getState().rules.find(l=>l.id===t.id)?.body:void 0);if(typeof d!=="string"){return{ok:false,error:"bodyPatch needs something to patch: send fromRequestId (the captured request whose real response the patch is merged into) or the id of an existing rule."}}let u;try{const l=_(JSON.parse(d),t.bodyPatch);u=l.error;if(l.notes.length)t.bodyPatch=l.patch}catch{}if(u){return{ok:false,error:`Refused: ${u}`}}if(t.force!==true){const l=Z(t,d);if(l.length>0){return{ok:false,error:J(l,"response body",W(t.bodyPatch,l)),violations:l}}}}const o=Q(e,r);if(!o){const d=e?.fromRequestId;return{ok:false,error:d?`No captured request \`${d}\` \u2014 it may have been cleared. Send a urlPattern instead.`:"A rule needs a non-empty urlPattern."}}const s=i.upsertRule(o);if(!s)return{ok:false,error:"Override rule limit reached."};if(s.enabled)i.setEnabled(true);return{ok:true,rule:{id:s.id,urlPattern:s.urlPattern,enabled:s.enabled,kind:s.kind,status:s.status,times:s.times,bodySize:s.body?s.body.length:0},...s.times===void 0||s.times===null?{lingers:`This rule has no \`times\` budget, so it overrides EVERY matching request until it is disabled or deleted (id \`${s.id}\`). If you meant only the next one, set times:1.`}:{},...h()}},setOverrideRuleEnabled:e=>{const t=c(e);if(!t)return{ok:false,error:"Missing rule id."};i.setRuleEnabled(t,g(e,"enabled"));return{ok:true,...h()}},deleteOverrideRule:e=>{const t=c(e);if(!t)return{ok:false,error:"Missing rule id."};i.removeRule(t);return{ok:true}},clearOverrideRules:()=>{i.clearRules();return{ok:true}},replaceOverrideRules:async e=>{const t=e??{};if(!Array.isArray(t.rules)){return{ok:false,error:"replaceOverrideRules needs `rules`: an array of rules, first match first."}}if(t.rules.length>R){return{ok:false,error:`Too many rules: ${t.rules.length}. The most is ${R}.`}}await i.ensureLoaded();const n=i.replaceAllRules(t.rules,t.enabled!==false);if(!n)return{ok:false,error:"This copy of the Network tool only mirrors a device, so it can't replace rules."};return{ok:true,count:n.length,enabled:i.getState().enabled,...h()}},listOverrideRules:async()=>{await i.ensureLoaded();return i.getState()},getOverrideRuleBody:e=>{const t=c(e);if(!t)return null;const n=i.getState().rules.find(r=>r.id===t);if(!n)return null;return{body:n.body??null}},getCaptureStatus:()=>{const e=f.getSubscriberCounts().total;let t=null;let n=null;try{t=P();n=E()}catch{}let r=null;try{r=L()}catch{}return{capturing:e>0,subscribers:e,interceptorInstalled:t,interceptorLive:r,listenerCount:n,eventCount:f.getEvents().length}},debugOverrides:e=>{const{url:t,method:n}=e&&typeof e==="object"?e:{};const r=typeof t==="string"?t:"https://example.com/";const o=typeof n==="string"&&n.trim()?n.trim().toUpperCase():"GET";return{tested:{url:r,method:o},interceptorInstalled:P(),listenerCount:E(),engine:B(r,o),store:{enabled:i.getState().enabled,autoPaused:i.getState().autoPaused,ruleCount:i.getState().rules.length,rulesVisibleToEngine:i.getRules().length}}}}};
1
+ "use strict";import{getNetworkConditions as v,setNetworkConditions as H,subscribeNetworkConditions as T}from"../conditions/store";import{networkEventStore as c}from"../utils/networkEventStore";import{flagsForEventId as O,networkSavedStore as a}from"../utils/networkSavedStore";import{overrideRulesStore as i}from"../overrides/overrideRulesStore";import{draftFromEvent as x}from"../overrides/presets";import{inspectEngine as B,overridesCanApply as j,OVERRIDES_INACTIVE_REASON as C}from"../overrides/engine";import{getNetworkListenerCount as E,isNetworkInterceptionLive as J,isNetworkListening as P}from"../utils/networkListener";import{MAX_RULES as R}from"../overrides/types";import{approxJsonSize as m,isOverWireBudget as L}from"@buoy-gg/shared-ui";import{expandKeyedArrays as M,patchFromPath as _,refusalText as $,shapeKind as w,suggestedPatch as W,typedEditViolations as U}from"@buoy-gg/shared-ui";export const SNAPSHOT_BODY_INLINE_LIMIT=16*1024;export const SNAPSHOT_EVENTS_BUDGET=1.25*1024*1024;function S(e,t){if(e===void 0)return false;if((t??0)>SNAPSHOT_BODY_INLINE_LIMIT)return true;return L(e,SNAPSHOT_BODY_INLINE_LIMIT)}const I=new WeakMap;const A=new WeakMap;function q(e){const t=I.get(e);if(t)return t;let n;try{n=z(e)}catch{n=K(e)}I.set(e,n);return n}function K(e){const t={...e,requestData:void 0,responseData:void 0,graphqlVariables:void 0,requestBodyOmitted:e.requestData!==void 0?true:void 0,responseBodyOmitted:e.responseData!==void 0?true:void 0};let n=1024;try{n=m(t,SNAPSHOT_EVENTS_BUDGET).bytes}catch{}return{event:t,bytes:n}}function z(e){const t=S(e.requestData,e.requestSize);const n=S(e.responseData,e.responseSize);const r=V(e.graphqlVariables);const o=N(e.requestHeaders);const s=N(e.responseHeaders);const u=t||n||r!==e.graphqlVariables||o!==e.requestHeaders||s!==e.responseHeaders;let d=e;if(u){d={...e};if(t){d.requestData=void 0;d.requestBodyOmitted=true}if(n){d.responseData=void 0;d.responseBodyOmitted=true}if(r!==e.graphqlVariables){d.graphqlVariables=r}if(o!==e.requestHeaders){d.requestHeaders=o;d.headersOmitted=true}if(s!==e.responseHeaders){d.responseHeaders=s;d.headersOmitted=true}}return{event:d,bytes:m(d,SNAPSHOT_EVENTS_BUDGET).bytes}}function F(e){const t=A.get(e);if(t)return t;const{event:n}=q(e);const r={...n};if(r.requestData!==void 0){r.requestData=void 0;r.requestBodyOmitted=true}if(r.responseData!==void 0){r.responseData=void 0;r.responseBodyOmitted=true}if(r.graphqlVariables!==void 0){r.graphqlVariables=V(r.graphqlVariables,true)}const o={event:r,bytes:m(r,SNAPSHOT_EVENTS_BUDGET).bytes};A.set(e,o);return o}function G(e){const t=new Array(e.length);let n=0;for(let r=0;r<e.length;r++){const o=q(e[r]);if(n+o.bytes<=SNAPSHOT_EVENTS_BUDGET){t[r]=o.event;n+=o.bytes}else{const s=F(e[r]);t[r]=s.event;n+=s.bytes}}return t}function V(e,t=false){if(!e)return e;if(!t&&!S(e,void 0))return e;const n={};for(const[r,o]of Object.entries(e)){if(typeof o==="string"&&o.length<=64)n[r]=o;else if(typeof o==="number"||typeof o==="boolean"){n[r]=o}}return Object.keys(n).length>0?n:void 0}export const SNAPSHOT_HEADER_VALUE_LIMIT=64;function N(e){if(!e)return e;let t=false;const n={};for(const[r,o]of Object.entries(e)){if(typeof o!=="string")continue;if(o.length<=SNAPSHOT_HEADER_VALUE_LIMIT){n[r]=o}else{n[r]=`${o.slice(0,SNAPSHOT_HEADER_VALUE_LIMIT)}\u2026 [${o.length-SNAPSHOT_HEADER_VALUE_LIMIT} more]`;t=true}}return t?n:e}const Y=e=>{let t=false;const n=e.rules.map(r=>{if(!r.body||r.body.length<=SNAPSHOT_BODY_INLINE_LIMIT){return r}t=true;return{...r,body:void 0,bodyOmitted:true}});return t?{...e,rules:n}:e};const b=e=>c.getEventById(e)??a.getEventById(e);const f=e=>e&&typeof e==="object"?e.id:void 0;const g=(e,t)=>!!(e&&typeof e==="object"&&e[t]);const h=()=>j()?{}:{active:false,inactiveReason:C};const X=["respond","fail","delay"];function Q(e,t){if(!e||typeof e!=="object")return null;const n=e.rule??e;if(!n||typeof n!=="object")return null;const r=n;const o=typeof r.urlPattern==="string"&&r.urlPattern.trim()?r.urlPattern.trim():t?.urlPattern??"";if(!o)return null;const s=X.includes(r.kind)?r.kind:t?.kind??"respond";return{id:typeof r.id==="string"?r.id:void 0,enabled:r.enabled!==false,name:typeof r.name==="string"?r.name:t?.name,urlPattern:o,methods:Array.isArray(r.methods)?r.methods.filter(u=>typeof u==="string").map(u=>u.toUpperCase()):t?.methods,requireHeader:typeof r.requireHeader==="string"&&r.requireHeader.trim()?r.requireHeader.trim():void 0,bodyIncludes:typeof r.bodyIncludes==="string"&&r.bodyIncludes?r.bodyIncludes.slice(0,4096):t?.bodyIncludes,graphqlOperation:typeof r.graphqlOperation==="string"&&r.graphqlOperation?r.graphqlOperation.slice(0,200):t?.graphqlOperation,graphqlVariables:typeof r.graphqlVariables==="string"?r.graphqlVariables.slice(0,4096):t?.graphqlVariables,bodyJson:typeof r.bodyJson==="string"&&r.bodyJson.length<=4096?r.bodyJson:t?.bodyJson,graphqlSingle:r.graphqlSingle===true?true:t?.graphqlSingle,sandbox:r.sandbox===true?true:void 0,kind:s,status:typeof r.status==="number"?r.status:t?.status,statusText:typeof r.statusText==="string"?r.statusText:t?.statusText,headers:r.headers&&typeof r.headers==="object"?r.headers:t?.headers,body:ee(r,t),failKind:r.failKind==="timeout"?"timeout":void 0,delayMs:typeof r.delayMs==="number"?r.delayMs:void 0,times:typeof r.times==="number"?r.times:null,alternate:r.alternate===true}}const k=e=>!!e&&typeof e==="object"&&!Array.isArray(e);const y=e=>k(e)||Array.isArray(e);function D(e,t,n="",r={shrunk:[],breaks:[]}){if(Array.isArray(e)&&Array.isArray(t)){if(t.length>0&&t.length<e.length){r.shrunk.push({path:n||"(root)",have:e.length,sent:t.length})}return t}if(!k(e)||!k(t))return t;const o={...e};for(const[s,u]of Object.entries(t)){const d=n?`${n}.${s}`:s;if(s in e){const l=w(e[s]);const p=w(u);if((l==="array"||l==="object")&&l!==p){r.breaks.push({path:d,from:l,to:p})}o[s]=D(e[s],u,d,r)}else{o[s]=u}}return o}function Z(e,t){if(e.body!=null||!y(e.bodyPatch)||typeof t!=="string")return[];try{return U(JSON.parse(t),e.bodyPatch,{noun:"response body"})}catch{return[]}}function ee(e,t){if(typeof e.body==="string")return e.body;if(e.body!=null)return JSON.stringify(e.body,null,2);const n=t?.body??(y(e.bodyPatch)&&typeof e.id==="string"?i.getState().rules.find(r=>r.id===e.id)?.body:void 0);if(y(e.bodyPatch)&&typeof n==="string"){try{return JSON.stringify(D(JSON.parse(n),e.bodyPatch),null,2)}catch{return n}}return n}function te(e){if(!e||typeof e!=="object")return null;const t=e.rule??e;if(!t||typeof t!=="object")return null;const n=t.id;if(typeof n!=="string")return null;const r=i.getState().rules.find(o=>o.id===n);return r?{...r}:null}function re(e){if(!e||typeof e!=="object")return null;const t=e.rule??e;if(!t||typeof t!=="object")return null;const n=t;if(n.bodyOmitted!==true||typeof n.id!=="string")return null;const r=i.getState().rules.find(o=>o.id===n.id);return r?{body:r.body}:null}function ne(e){if(!e||typeof e!=="object")return null;const t=e.fromRequestId;if(typeof t!=="string"||!t)return null;const n=b(t);return n?x(n):null}export const networkSyncAdapter={dispose:()=>{i.setEnabled(false)},version:6,getSnapshot:()=>{c.ensureInterception();return{conditions:v(),events:G(c.getEvents()),overrides:Y(i.getState()),saved:a.getRecords().map(e=>({...e,event:q(e.event).event}))}},subscribe:e=>{const t=c.subscribeToEvents(e);const n=T(e);const r=a.subscribe(e);const o=i.subscribe(e);return()=>{n();t();r();o()}},actions:{getNetworkConditions:v,setNetworkConditions:H,clearEvents:()=>{c.clearEvents()},getEventBody:e=>{const t=f(e);if(!t)return null;const n=b(t);if(!n)return null;return{url:n.url??null,method:n.method??null,status:n.status??null,override:n.override??null,condition:n.condition??null,requestData:n.requestData??null,responseData:n.responseData??null,requestHeaders:n.requestHeaders??null,responseHeaders:n.responseHeaders??null}},setPinned:e=>{const t=f(e);if(!t)return null;const n=b(t);if(!n)return null;const r=g(e,"pinned");const o=O(a.getState(),t).pinned;if(o===r)return{ok:true};return a.togglePin(n)},setSaved:e=>{const t=f(e);if(!t)return null;const n=b(t);if(!n)return null;const r=g(e,"saved");const o=O(a.getState(),t).saved;if(o===r)return{ok:true};return a.toggleSave(n)},removeSavedRecord:e=>{const t=e&&typeof e==="object"?e.key:void 0;if(!t)return null;a.remove(t);return{ok:true}},clearSavedRequests:()=>{a.clearSaved();return{ok:true}},clearPinnedRequests:()=>{a.clearPinned();return{ok:true}},setOverridesEnabled:e=>{i.setEnabled(g(e,"enabled"));return{ok:true,enabled:i.getState().enabled,...h()}},upsertOverrideRule:e=>{const t=e?.rule??e;const n=!!t&&t.body==null&&(y(t.bodyPatch)||typeof t.bodyPath==="string");const r=ne(e)??re(e)??(n?te(e):null);if(t&&typeof t.bodyPath==="string"&&t.body==null){const u=r?.body??(typeof t.id==="string"?i.getState().rules.find(p=>p.id===t.id)?.body:void 0);if(typeof u!=="string"){return{ok:false,error:"bodyPath needs something to patch: send fromRequestId (the captured request whose real response it addresses) or the id of an existing rule."}}if(t.bodyValue===void 0){return{ok:false,error:`Refused: sent \`bodyPath\` without \`bodyValue\`. Say what to set "${t.bodyPath}" to.`}}let d;try{d=JSON.parse(u)}catch{return{ok:false,error:"The captured response body is not JSON, so it cannot be addressed by path. Send a whole `body` instead."}}const l=_(d,t.bodyPath,t.bodyValue);if(!l.ok)return{ok:false,error:`Refused: ${l.error}`};t.bodyPatch=l.patch;delete t.bodyPath;delete t.bodyValue}if(t&&y(t.bodyPatch)&&t.body==null){const u=r?.body??(typeof t.id==="string"?i.getState().rules.find(l=>l.id===t.id)?.body:void 0);if(typeof u!=="string"){return{ok:false,error:"bodyPatch needs something to patch: send fromRequestId (the captured request whose real response the patch is merged into) or the id of an existing rule."}}let d;try{const l=M(JSON.parse(u),t.bodyPatch);d=l.error;if(l.notes.length)t.bodyPatch=l.patch}catch{}if(d){return{ok:false,error:`Refused: ${d}`}}if(t.force!==true){const l=Z(t,u);if(l.length>0){return{ok:false,error:$(l,"response body",W(t.bodyPatch,l)),violations:l}}}}const o=Q(e,r);if(!o){const u=e?.fromRequestId;return{ok:false,error:u?`No captured request \`${u}\` \u2014 it may have been cleared. Send a urlPattern instead.`:"A rule needs a non-empty urlPattern."}}const s=i.upsertRule(o);if(!s)return{ok:false,error:"Override rule limit reached."};if(s.enabled)i.setEnabled(true);return{ok:true,rule:{id:s.id,urlPattern:s.urlPattern,enabled:s.enabled,kind:s.kind,status:s.status,times:s.times,bodySize:s.body?s.body.length:0},...s.times===void 0||s.times===null?{lingers:`This rule has no \`times\` budget, so it overrides EVERY matching request until it is disabled or deleted (id \`${s.id}\`). If you meant only the next one, set times:1.`}:{},...h()}},setOverrideRuleEnabled:e=>{const t=f(e);if(!t)return{ok:false,error:"Missing rule id."};i.setRuleEnabled(t,g(e,"enabled"));return{ok:true,...h()}},deleteOverrideRule:e=>{const t=f(e);if(!t)return{ok:false,error:"Missing rule id."};i.removeRule(t);return{ok:true}},clearOverrideRules:()=>{i.clearRules();return{ok:true}},replaceOverrideRules:async e=>{const t=e??{};if(!Array.isArray(t.rules)){return{ok:false,error:"replaceOverrideRules needs `rules`: an array of rules, first match first."}}if(t.rules.length>R){return{ok:false,error:`Too many rules: ${t.rules.length}. The most is ${R}.`}}await i.ensureLoaded();const n=i.replaceAllRules(t.rules,t.enabled!==false);if(!n)return{ok:false,error:"This copy of the Network tool only mirrors a device, so it can't replace rules."};const r=await i.saveChecked();return{ok:true,count:n.length,enabled:i.getState().enabled,saved:r,...h()}},listOverrideRules:async()=>{await i.ensureLoaded();return i.getState()},getOverrideRuleBody:e=>{const t=f(e);if(!t)return null;const n=i.getState().rules.find(r=>r.id===t);if(!n)return null;return{body:n.body??null}},getCaptureStatus:()=>{const e=c.getSubscriberCounts().total;let t=null;let n=null;try{t=P();n=E()}catch{}let r=null;try{r=J()}catch{}return{capturing:e>0,subscribers:e,interceptorInstalled:t,interceptorLive:r,listenerCount:n,eventCount:c.getEvents().length}},debugOverrides:e=>{const{url:t,method:n}=e&&typeof e==="object"?e:{};const r=typeof t==="string"?t:"https://example.com/";const o=typeof n==="string"&&n.trim()?n.trim().toUpperCase():"GET";return{tested:{url:r,method:o},interceptorInstalled:P(),listenerCount:E(),engine:B(r,o),store:{enabled:i.getState().enabled,autoPaused:i.getState().autoPaused,ruleCount:i.getState().rules.length,rulesVisibleToEngine:i.getRules().length}}}}};
@@ -1 +1 @@
1
- "use strict";import{isBuoyRequest as f,getAccountAccess as d}from"@buoy-gg/shared-ui";import{BaseEventStore as m}from"@buoy-gg/shared-ui";import{extractOperationName as l}from"./extractOperationName";import{networkListener as h,addNetworkListener as p,getNetworkListenerCount as b,stopNetworkListener as g}from"./networkListener";import{networkSavedStore as v}from"./networkSavedStore";const y=200;class w extends m{replaceEvents(e){super.replaceEvents(e.filter(t=>!f(t.url)))}pendingRequests=new Map;rawListenerUnsubscribe=null;bootBuffer=[];bootBufferUnsubscribe=null;mirrorMode=false;constructor(){super({storeName:"network",maxEvents:500})}startBootCapture(){if(d().status==="locked")return;if(this.mirrorMode||this.bootBufferUnsubscribe||this.isCapturing()){return}const e=h();if(!e.isActive){e.startListening()}this.bootBufferUnsubscribe=p(t=>{this.bootBuffer.push(t);if(this.bootBuffer.length>y)this.bootBuffer.shift()})}takeBootBuffer(){if(this.bootBufferUnsubscribe){this.bootBufferUnsubscribe();this.bootBufferUnsubscribe=null}const e=this.bootBuffer;this.bootBuffer=[];return e}startCapturing(){const e=h();if(!e.isActive){e.startListening()}for(const t of this.takeBootBuffer()){this.processNetworkEvent(t)}if(!this.rawListenerUnsubscribe){this.rawListenerUnsubscribe=p(t=>{this.processNetworkEvent(t)})}e.adoptEarlyRequests()}stopCapturing(){this.takeBootBuffer();if(this.rawListenerUnsubscribe){this.rawListenerUnsubscribe();this.rawListenerUnsubscribe=null}if(b()===0){g()}}disableCapture(){this.mirrorMode=true;this.takeBootBuffer();if(b()===0){g()}super.disableCapture()}isCapturing(){return this.rawListenerUnsubscribe!==null}ensureInterception(){if(!this.isCapturing())return;h().startListening()}subscribeToEvents(e){const t=super.subscribeToEvents(e);this.ensureInterception();return t}processNetworkEvent(e){if(d().status==="locked")return;const{request:t}=e;if(f(t.url))return;if(e.type==="request"){if(this.events.some(u=>u.id===t.id))return;const r=t.params?`?${new URLSearchParams(t.params).toString()}`:"";const s=`${t.url}${r}`;let n;let o;if(t.client==="graphql"){const u=l(t.data);n=u||void 0;if(t.data&&typeof t.data==="object"&&"variables"in t.data&&t.data.variables&&typeof t.data.variables==="object"){o=t.data.variables}}const a={id:t.id,method:t.method,url:s,host:this.extractHost(t.url),path:this.extractPath(t.url),query:r,timestamp:e.timestamp.getTime(),requestHeaders:t.headers||{},requestData:t.data,requestSize:this.getDataSize(t.data),responseHeaders:{},requestClient:t.client,operationName:n,graphqlVariables:o,override:e.override,condition:e.condition};this.pendingRequests.set(t.id,a);this.events=[a,...this.events].slice(0,this.maxEvents);this.notify(a);this.notifyArrayListeners()}else if(e.type==="request-body"){const r=this.events.find(n=>n.id===t.id);if(!r)return;const s={...r,requestData:t.data,requestSize:this.getDataSize(t.data)};if(t.client==="graphql"){s.operationName=l(t.data)||void 0;const n=t.data?.variables;if(n&&typeof n==="object")s.graphqlVariables=n}this.events=this.events.map(n=>n.id===t.id?s:n);if(this.pendingRequests.has(t.id))this.pendingRequests.set(t.id,s);v.syncFromLive(s);this.notify(s);this.notifyArrayListeners()}else if(e.type==="response"||e.type==="error"){const r=this.events.findIndex(s=>s.id===t.id);if(r!==-1){const s={...this.events[r],duration:e.duration,timings:e.timings};if(e.response){s.status=e.response.status;s.statusText=e.response.statusText;s.responseHeaders=e.response.headers||{};s.responseData=e.response.body;s.responseSize=e.response.size||0;s.responseType=e.response.headers?.["content-type"]}if(e.error){s.error=e.error.message;s.status=s.status||0}if(e.override)s.override=e.override;this.events=this.events.map((n,o)=>o===r?s:n);this.pendingRequests.delete(t.id);v.syncFromLive(s);this.notify(s);this.notifyArrayListeners()}}}extractHost(e){try{const t=new URL(e);return t.hostname}catch{return""}}extractPath(e){try{const t=new URL(e);return t.pathname}catch{return e}}getDataSize(e){if(!e)return 0;if(typeof e==="string")return e.length;try{return JSON.stringify(e).length}catch{return 0}}getEventById(e){return this.events.find(t=>t.id===e)}clearEvents(){super.clearEvents();this.pendingRequests.clear()}onEvent(e,t=true){const r=this.subscribe(e);if(t&&this.events.length>0){const s=[...this.events].reverse();for(const n of s){try{e(n)}catch{}}}return r}getStats(){const e=this.events.length;const t=this.events.filter(i=>i.status&&i.status>=200&&i.status<300).length;const r=this.events.filter(i=>i.error||i.status&&i.status>=400).length;const s=this.events.filter(i=>!i.status&&!i.error).length;const n=this.events.filter(i=>i.duration).map(i=>i.duration);const o=n.length>0?n.reduce((i,c)=>i+c,0)/n.length:0;const a=this.events.reduce((i,c)=>i+(c.requestSize||0),0);const u=this.events.reduce((i,c)=>i+(c.responseSize||0),0);return{totalRequests:e,successfulRequests:t,failedRequests:r,pendingRequests:s,totalDataSent:a,totalDataReceived:u,averageDuration:Math.round(o)}}filterEvents(e){let t=[...this.events];if(e.method){t=t.filter(r=>r.method===e.method)}if(e.status){switch(e.status){case"success":t=t.filter(r=>r.status&&r.status>=200&&r.status<300);break;case"error":t=t.filter(r=>r.error||r.status&&r.status>=400);break;case"pending":t=t.filter(r=>!r.status&&!r.error);break}}if(e.searchText){const r=e.searchText.toLowerCase();t=t.filter(s=>s.url.toLowerCase().includes(r)||s.method.toLowerCase().includes(r)||s.error&&s.error.toLowerCase().includes(r))}if(e.host){t=t.filter(r=>r.host===e.host)}return t}}export const networkEventStore=new w;
1
+ "use strict";import{isBuoyRequest as f,getAccountAccess as h}from"@buoy-gg/shared-ui";import{BaseEventStore as v}from"@buoy-gg/shared-ui";import{extractOperationName as p}from"./extractOperationName";import{networkListener as d,addNetworkListener as l,getNetworkListenerCount as b,stopNetworkListener as g}from"./networkListener";import{networkSavedStore as m}from"./networkSavedStore";const y=200;class w extends v{replaceEvents(t){super.replaceEvents(t.filter(e=>!f(e.url)))}pendingRequests=new Map;rawListenerUnsubscribe=null;bootBuffer=[];bootBufferUnsubscribe=null;mirrorMode=false;constructor(){super({storeName:"network",maxEvents:500})}startBootCapture(){if(h().status==="locked")return;if(this.mirrorMode||this.bootBufferUnsubscribe||this.isCapturing()){return}const t=d();if(!t.isActive){t.startListening()}this.bootBufferUnsubscribe=l(e=>{this.bootBuffer.push(e);if(this.bootBuffer.length>y)this.bootBuffer.shift()})}takeBootBuffer(){if(this.bootBufferUnsubscribe){this.bootBufferUnsubscribe();this.bootBufferUnsubscribe=null}const t=this.bootBuffer;this.bootBuffer=[];return t}startCapturing(){const t=d();if(!t.isActive){t.startListening()}for(const e of this.takeBootBuffer()){this.processNetworkEvent(e)}if(!this.rawListenerUnsubscribe){this.rawListenerUnsubscribe=l(e=>{this.processNetworkEvent(e)})}t.adoptEarlyRequests()}stopCapturing(){this.takeBootBuffer();if(this.rawListenerUnsubscribe){this.rawListenerUnsubscribe();this.rawListenerUnsubscribe=null}if(b()===0){g()}}disableCapture(){this.mirrorMode=true;this.takeBootBuffer();if(b()===0){g()}super.disableCapture()}isCapturing(){return this.rawListenerUnsubscribe!==null}ensureInterception(){if(!this.isCapturing())return;d().startListening()}subscribeToEvents(t){const e=super.subscribeToEvents(t);this.ensureInterception();return e}processNetworkEvent(t){if(h().status==="locked")return;const{request:e}=t;if(f(e.url))return;if(t.type==="request"){if(this.events.some(u=>u.id===e.id))return;const r=e.params?`?${new URLSearchParams(e.params).toString()}`:"";const s=`${e.url}${r}`;let n;let o;if(e.client==="graphql"){const u=p(e.data);n=u||void 0;if(e.data&&typeof e.data==="object"&&"variables"in e.data&&e.data.variables&&typeof e.data.variables==="object"){o=e.data.variables}}const a={id:e.id,method:e.method,url:s,host:this.extractHost(e.url),path:this.extractPath(e.url),query:r,timestamp:t.timestamp.getTime(),requestHeaders:e.headers||{},requestData:e.data,requestSize:this.getDataSize(e.data),responseHeaders:{},requestClient:e.client,operationName:n,graphqlVariables:o,override:t.override,condition:t.condition};this.pendingRequests.set(e.id,a);this.events=[a,...this.events].slice(0,this.maxEvents);this.notify(a);this.notifyArrayListeners()}else if(t.type==="request-body"){const r=this.events.find(n=>n.id===e.id);if(!r)return;const s={...r,requestData:e.data,requestSize:this.getDataSize(e.data)};if(e.client==="graphql"){s.operationName=p(e.data)||void 0;const n=e.data?.variables;if(n&&typeof n==="object")s.graphqlVariables=n}this.events=this.events.map(n=>n.id===e.id?s:n);if(this.pendingRequests.has(e.id))this.pendingRequests.set(e.id,s);m.syncFromLive(s);this.notify(s);this.notifyArrayListeners()}else if(t.type==="response"||t.type==="error"){const r=this.events.findIndex(s=>s.id===e.id);if(r!==-1){const s={...this.events[r],duration:t.duration,timings:t.timings};if(t.response){s.status=t.response.status;s.statusText=t.response.statusText;s.responseHeaders=t.response.headers||{};s.responseData=t.response.body;s.responseJson=typeof t.response.json==="boolean"?t.response.json:void 0;s.responseTruncated=t.response.truncated===true||void 0;s.responseUnread=t.response.unread===true||void 0;s.responseSize=t.response.size||0;s.responseType=t.response.headers?.["content-type"]}if(t.error){s.error=t.error.message;s.status=s.status||0}if(t.override)s.override=t.override;this.events=this.events.map((n,o)=>o===r?s:n);this.pendingRequests.delete(e.id);m.syncFromLive(s);this.notify(s);this.notifyArrayListeners()}}}extractHost(t){try{const e=new URL(t);return e.hostname}catch{return""}}extractPath(t){try{const e=new URL(t);return e.pathname}catch{return t}}getDataSize(t){if(!t)return 0;if(typeof t==="string")return t.length;try{return JSON.stringify(t).length}catch{return 0}}getEventById(t){return this.events.find(e=>e.id===t)}clearEvents(){super.clearEvents();this.pendingRequests.clear()}onEvent(t,e=true){const r=this.subscribe(t);if(e&&this.events.length>0){const s=[...this.events].reverse();for(const n of s){try{t(n)}catch{}}}return r}getStats(){const t=this.events.length;const e=this.events.filter(i=>i.status&&i.status>=200&&i.status<300).length;const r=this.events.filter(i=>i.error||i.status&&i.status>=400).length;const s=this.events.filter(i=>!i.status&&!i.error).length;const n=this.events.filter(i=>i.duration).map(i=>i.duration);const o=n.length>0?n.reduce((i,c)=>i+c,0)/n.length:0;const a=this.events.reduce((i,c)=>i+(c.requestSize||0),0);const u=this.events.reduce((i,c)=>i+(c.responseSize||0),0);return{totalRequests:t,successfulRequests:e,failedRequests:r,pendingRequests:s,totalDataSent:a,totalDataReceived:u,averageDuration:Math.round(o)}}filterEvents(t){let e=[...this.events];if(t.method){e=e.filter(r=>r.method===t.method)}if(t.status){switch(t.status){case"success":e=e.filter(r=>r.status&&r.status>=200&&r.status<300);break;case"error":e=e.filter(r=>r.error||r.status&&r.status>=400);break;case"pending":e=e.filter(r=>!r.status&&!r.error);break}}if(t.searchText){const r=t.searchText.toLowerCase();e=e.filter(s=>s.url.toLowerCase().includes(r)||s.method.toLowerCase().includes(r)||s.error&&s.error.toLowerCase().includes(r))}if(t.host){e=e.filter(r=>r.host===t.host)}return e}}export const networkEventStore=new w;