@buoy-gg/network 7.0.78 → 7.0.79
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.
- package/README.md +68 -2
- package/lib/commonjs/expo-network.js +1 -0
- package/lib/commonjs/index.js +1 -1
- package/lib/commonjs/index.web.js +1 -1
- package/lib/commonjs/netinfo.js +1 -0
- package/lib/commonjs/network/components/NetworkEventDetailView.js +2 -2
- package/lib/commonjs/network/components/NetworkEventDetailView.web.js +1 -1
- package/lib/commonjs/network/components/NetworkEventItemCompact.js +2 -2
- package/lib/commonjs/network/components/NetworkEventItemCompact.web.js +1 -1
- package/lib/commonjs/network/components/NetworkModal.js +1 -1
- package/lib/commonjs/network/conditions/NetworkConditionsControl.js +1 -1
- package/lib/commonjs/network/conditions/NetworkConditionsControl.test.js +1 -1
- package/lib/commonjs/network/conditions/NetworkConditionsIcon.js +1 -1
- package/lib/commonjs/network/conditions/NetworkFloatingTool.js +1 -1
- package/lib/commonjs/network/conditions/NetworkFloatingTool.test.js +1 -1
- package/lib/commonjs/network/conditions/connectivity/netInfoFacade.js +1 -0
- package/lib/commonjs/network/conditions/connectivity/patchNetwork.js +1 -0
- package/lib/commonjs/network/conditions/pacer.js +1 -0
- package/lib/commonjs/network/conditions/profiles.js +1 -0
- package/lib/commonjs/network/conditions/remoteState.js +1 -0
- package/lib/commonjs/network/conditions/store.js +1 -1
- package/lib/commonjs/network/conditions/wait.js +1 -1
- package/lib/commonjs/network/conditions/xhr.js +1 -1
- package/lib/commonjs/network/overrides/engine.js +1 -1
- package/lib/commonjs/network/overrides/matchRule.js +1 -1
- package/lib/commonjs/network/overrides/overrideRulesStore.js +1 -1
- package/lib/commonjs/network/sync/networkSyncAdapter.js +1 -1
- package/lib/commonjs/network/utils/generateNetworkCopyText.js +1 -0
- package/lib/commonjs/network/utils/networkListener.js +4 -4
- package/lib/module/expo-network.js +1 -0
- package/lib/module/index.js +1 -1
- package/lib/module/index.web.js +1 -1
- package/lib/module/netinfo.js +1 -0
- package/lib/module/network/components/NetworkEventDetailView.js +2 -2
- package/lib/module/network/components/NetworkEventDetailView.web.js +2 -2
- package/lib/module/network/components/NetworkEventItemCompact.js +2 -2
- package/lib/module/network/components/NetworkEventItemCompact.web.js +1 -1
- package/lib/module/network/components/NetworkModal.js +1 -1
- package/lib/module/network/conditions/NetworkConditionsControl.js +1 -1
- package/lib/module/network/conditions/NetworkConditionsControl.test.js +1 -1
- package/lib/module/network/conditions/NetworkConditionsIcon.js +1 -1
- package/lib/module/network/conditions/NetworkFloatingTool.js +1 -1
- package/lib/module/network/conditions/NetworkFloatingTool.test.js +1 -1
- package/lib/module/network/conditions/connectivity/netInfoFacade.js +1 -0
- package/lib/module/network/conditions/connectivity/patchNetwork.js +1 -0
- package/lib/module/network/conditions/pacer.js +1 -0
- package/lib/module/network/conditions/profiles.js +1 -0
- package/lib/module/network/conditions/remoteState.js +1 -0
- package/lib/module/network/conditions/store.js +1 -1
- package/lib/module/network/conditions/wait.js +1 -1
- package/lib/module/network/conditions/xhr.js +1 -1
- package/lib/module/network/overrides/engine.js +1 -1
- package/lib/module/network/overrides/matchRule.js +1 -1
- package/lib/module/network/overrides/overrideRulesStore.js +1 -1
- package/lib/module/network/sync/networkSyncAdapter.js +1 -1
- package/lib/module/network/utils/generateNetworkCopyText.js +23 -22
- package/lib/module/network/utils/networkListener.js +4 -4
- package/lib/typescript/expo-network.d.ts +2 -0
- package/lib/typescript/index.d.ts +3 -2
- package/lib/typescript/index.web.d.ts +3 -2
- package/lib/typescript/netinfo.d.ts +3 -0
- package/lib/typescript/network/conditions/NetworkConditionsControl.d.ts +5 -2
- package/lib/typescript/network/conditions/NetworkFloatingTool.d.ts +4 -3
- package/lib/typescript/network/conditions/connectivity/netInfoFacade.d.ts +3 -0
- package/lib/typescript/network/conditions/connectivity/patchNetwork.d.ts +24 -0
- package/lib/typescript/network/conditions/pacer.d.ts +16 -0
- package/lib/typescript/network/conditions/profiles.d.ts +57 -0
- package/lib/typescript/network/conditions/remoteState.d.ts +4 -0
- package/lib/typescript/network/conditions/store.d.ts +45 -19
- package/lib/typescript/network/conditions/xhr.d.ts +1 -1
- package/lib/typescript/network/overrides/engine.d.ts +14 -0
- package/lib/typescript/network/overrides/matchRule.d.ts +3 -0
- package/lib/typescript/network/overrides/overrideRulesStore.d.ts +3 -0
- package/lib/typescript/network/overrides/types.d.ts +19 -0
- package/lib/typescript/network/sync/networkSyncAdapter.d.ts +27 -12
- package/lib/typescript/network/utils/networkListener.d.ts +4 -0
- package/lib/web/index.mjs +58 -57
- package/package.json +26 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";export function maskConnection(t,n,i=false){if(n==="auto"||n==="real")return{...t};const r=n==="offline"?"none":n==="cellular"?"cellular":"wifi";return{type:i?r.toUpperCase():r,...!i?{details:n==="offline"?null:{isConnectionExpensive:n==="cellular",...n==="cellular"?{cellularGeneration:null,carrier:null}:{}}}:{},isConnected:n!=="offline",isInternetReachable:n!=="offline"&&n!=="noInternet"}}export function patchConnectionState(t,n,i,r={}){const o=r.eventName??"netInfo.networkStatusDidChange";if((t.eventEmitter.listenerCount?.(o)??0)>0)throw new Error("Link hook loaded too late. Load it before app code, then reload.");const y=t.getCurrentState;const s=t.eventEmitter.addListener;const l=new Set;let a={type:r.expo?"UNKNOWN":"unknown",isConnected:null,isInternetReachable:null};let u=0;let f=false;let C=n();const d=e=>maskConnection(e,n(),r.expo);const p=()=>{if(!f)l.forEach(e=>e(d(a)))};const x=s.call(t.eventEmitter,o,e=>{u++;a=e;p()});const h=async(...e)=>{const c=u;const b=await y.apply(r.receiver??t,e);if(e[0])return d(b);if(c===u)a=b;return d(a)};const E=(e,c)=>{if(e!==o)return s.call(t.eventEmitter,e,c);l.add(c);return{remove:()=>{l.delete(c)}}};let w;const S=()=>{f=true;try{w?.()}finally{try{x.remove()}finally{l.clear();if(t.getCurrentState===h)t.getCurrentState=y;if(t.eventEmitter.addListener===E)t.eventEmitter.addListener=s}}};try{t.getCurrentState=h;t.eventEmitter.addListener=E;w=i(()=>{const e=n();if(e!==C){C=e;p()}})}catch(e){S();throw e}void h(...r.expo?[]:[void 0]).then(p).catch(()=>{});return()=>{if(f)return;try{l.forEach(e=>e({...a}))}finally{S()}}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";import{realNow as w}from"../utils/realNow";import{waitBeforeDispatch as B,throwIfAborted as m}from"./wait";export const chunkSize=e=>Math.max(1,Math.min(16384,Math.floor(e*.02)));export const utf8Length=e=>new TextEncoder().encode(e).byteLength;export function bodyByteLength(e){if(e==null)return 0;if(typeof e==="string")return utf8Length(e);if(e instanceof ArrayBuffer)return e.byteLength;if(ArrayBuffer.isView(e))return e.byteLength;if(typeof Blob!=="undefined"&&e instanceof Blob)return e.size;if(typeof URLSearchParams!=="undefined"&&e instanceof URLSearchParams)return utf8Length(e.toString());return null}export async function paceByteCount(e,f,o,d){const y=chunkSize(f);const a=w();for(let i=0;i<e;){const b=Math.min(y,e-i);await B(Math.max(0,a+(i+b)/f*1e3-w()),o);m(o);i+=b;d?.(i,e)}}export function uploadBodySize(e,f){try{const o=typeof e==="object"&&"method"in e?e:void 0;const d=f?.body!==void 0?f.body:o&&"_bodyInit"in o?o._bodyInit:o?.body;return uploadSize(d)}catch{return L(0)}}function L(e){return{knownBytes:e,status:e>0?"partial":"not-applied",note:e>0?"upload cap partial: size unknown":"upload cap not applied: size unknown"}}export function uploadSize(e){let f=0;try{const o=bodyByteLength(e);if(o!==null)return{knownBytes:o,status:"applied"};if(e&&typeof e==="object"){const d=e;const y=Array.isArray(d._parts)?d._parts:typeof FormData!=="undefined"&&e instanceof FormData&&d.entries?d.entries():void 0;if(y){for(const[,a]of y){try{const i=bodyByteLength(a);if(i!==null)f+=i;else if(a&&typeof a==="object"&&"uri"in a&&"size"in a&&typeof a.size==="number"&&Number.isSafeInteger(a.size)&&a.size>=0)f+=a.size}catch{}}}}}catch{}return L(f)}export function createBytePacer(e){let f=0;return async(o,d)=>{const y=o/e*1e3;const a=w();const i=Math.max(0,y-f);if(i>0)await B(i,d);m(d);f=Math.min(chunkSize(e)/e*1e3,Math.max(0,f+w()-a-y))}}export function pacedStream(e,f,o,d){const y=createBytePacer(f);let a;const i=()=>{a?.releaseLock();a=void 0};const b=t=>{void(a?a.cancel(t):e.cancel(t)).catch(()=>{});i()};const l=new AbortController;let r;let n=0;let s=false;let u;const c=(t,p=false)=>{if(s)return;s=true;o?.removeEventListener("abort",h);l.abort();r=void 0;if(p)u.error(t);else{i();u.close()}d?.(null,t)};const h=()=>{const t=o?.reason!==void 0?o.reason:Object.assign(new Error("The request was aborted."),{name:"AbortError"});c(t,true);b(t)};return new ReadableStream({start(t){u=t;o?.addEventListener("abort",h,{once:true});if(o?.aborted)h()},async pull(){try{if(!r||n===r.byteLength){const x=await(a??=e.getReader()).read();if(s)return;if(x.done){c();return}r=x.value;n=0}const t=Math.min(chunkSize(f),r.byteLength-n);const p=r.subarray(n,n+t);await y(t,l.signal);if(s)return;n+=t;d?.(p);u.enqueue(p)}catch(t){if(!s){c(t,true);b(t)}}},cancel(t){if(!s){s=true;o?.removeEventListener("abort",h);l.abort();r=void 0;d?.(null,t??new Error("Body read stopped."))}b(t)}},{highWaterMark:0})}export function paceResponse(e,f,o,d,y=false){if(y||[204,205,304].includes(e.status)||e.body===null){d?.(null);return e}let a;let i=false;const b=()=>{if(!a){let r;let n=false;const s=new ReadableStream({async pull(u){i=true;try{if(e.body?.getReader){r??=e.body.getReader();const c=await r.read();if(n)return;if(c.done){n=true;r.releaseLock();r=void 0;u.close()}else u.enqueue(c.value)}else{const c=new Uint8Array(await e.arrayBuffer());if(n)return;u.enqueue(c);n=true;u.close()}}catch(c){if(!n){n=true;r?.releaseLock();r=void 0;u.error(c)}}},cancel(u){i=true;n=true;const c=r?r.cancel(u):e.body?.cancel?.(u);r?.releaseLock();r=void 0;return c}},{highWaterMark:0});a=pacedStream(s,f,o,d)}return a};const l=async(r=true)=>{if(i||a?.locked||e.bodyUsed)throw new TypeError("Body has already been read.");i=true;const n=b().getReader();const s=[];let u=0;try{for(;;){const t=await n.read();if(t.done)break;if(r){s.push(t.value);u+=t.value.byteLength}}}finally{n.releaseLock()}const c=new Uint8Array(u);let h=0;for(const t of s){c.set(t,h);h+=t.byteLength}return c};return new Proxy(e,{get(r,n){if(n==="body")return b();if(n==="bodyUsed")return i||e.bodyUsed;if(n==="arrayBuffer")return async()=>(await l()).buffer;if(n==="bytes")return l;if(n==="text")return async()=>new TextDecoder().decode(await l());if(n==="json")return async()=>JSON.parse(new TextDecoder().decode(await l()));if(n==="blob")return async()=>{if(i||a?.locked||e.bodyUsed)throw new TypeError("Body has already been read.");m(o);let u=false;try{new Blob([new Uint8Array(0)]);u=true}catch{}if(u)return new Blob([await l()],{type:r.headers.get("content-type")??""});const c=r.clone();let h;Object.defineProperty(c,"arrayBuffer",{configurable:true,value:async()=>{if(c.body&&!c.body.locked)void c.body.cancel().catch(()=>{});h??=l();return(await h).buffer}});try{const t=c.blob();void t.catch(()=>{});await(h??l(false));m(o);return await t}finally{if(c.body&&!c.body.locked)void c.body.cancel().catch(()=>{})}};if(n==="formData")return async()=>{const u=await l();return new Response(u,{headers:r.headers}).formData()};if(n==="clone")return()=>{if(i||a?.locked||e.bodyUsed)throw new TypeError("Body has already been read.");return paceResponse(r.clone(),f,o)};const s=Reflect.get(r,n,r);return typeof s==="function"?s.bind(r):s}})}
|
|
@@ -0,0 +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."};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";export function chooseConditionsSnapshot(i,r){if(!i)return null;if(!r||r.runtimeId!==i.runtimeId||r.revision<i.revision)return i;return r}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{hasAccountAccess as
|
|
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 +1 @@
|
|
|
1
|
-
"use strict";export function throwIfAborted(e){if(!e?.aborted)return;if(e.reason!==void 0)throw e.reason;const r=new Error("The request was aborted.");r.name="AbortError";throw r}export function waitBeforeDispatch(e,r){return new Promise((
|
|
1
|
+
"use strict";import{realSetTimeout as i,realClearTimeout as s}from"../utils/realNow";export function throwIfAborted(e){if(!e?.aborted)return;if(e.reason!==void 0)throw e.reason;const r=new Error("The request was aborted.");r.name="AbortError";throw r}export function waitBeforeDispatch(e,r){return new Promise((c,o)=>{try{throwIfAborted(r)}catch(t){o(t);return}const n=()=>r?.removeEventListener("abort",a);const a=()=>{s(u);n();try{throwIfAborted(r)}catch(t){o(t)}};const u=i(()=>{n();c()},e);r?.addEventListener("abort",a,{once:true})})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{canSynthesize as
|
|
1
|
+
"use strict";import{bodyByteLength as A,chunkSize as $,createBytePacer as ee,paceByteCount as B,uploadSize as te}from"./pacer";import{canSynthesize as re,completeNativeOverride as ne,runOverride as se}from"../overrides/applyToXhr";import{realClearTimeout as x,realNow as C,realSetTimeout as U}from"../utils/realNow";export function runConditionXhr(O,v,i,a,T,W){if(!re(O)){if(i.downloadBytesPerSecond)throw new Error("Byte caps need RN XHR. This XHR only supports waits and Offline.");const t={id:"condition",enabled:true,urlPattern:v,kind:"delay",hits:0,seen:0,createdAt:Date.now()};const n=i.profile==="offline"?{kind:"fail",rule:t,failKind:"network",delayMs:0}:a?{...a,delayMs:i.delayMs+a.delayMs}:{kind:"delay",rule:t,delayMs:i.delayMs};if(!se(O,v,n,T))throw new Error("Network conditions are unavailable for this XMLHttpRequest implementation.");return}const e=O;if(e.readyState!==1||e._sent)throw new Error("Request is not open or has already been sent.");const q=C();let u=e.timeout;let s=false;const g=new AbortController;const L=[];let D=false;let k;let N;const z=e.abort;const K=e.open;const F=Object.getOwnPropertyDescriptor(e,"abort");const G=Object.getOwnPropertyDescriptor(e,"open");const J=Object.getOwnPropertyDescriptor(e,"timeout");const R=(t,n)=>{if(n)Object.defineProperty(e,t,n);else delete e[t]};const b=()=>{if(s)return;s=true;x(N);g.abort();L.forEach(t=>t());x(k);e.removeEventListener("loadend",b);R("abort",F);R("open",G);R("timeout",J);e.timeout=u};const _=(t,n)=>{if(s)return;Object.assign(e,{readyState:4});z.call(e);e._aborted=false;e._hasError=true;e._timedOut=t;e._response=n??(t?"Request timed out (Buoy conditions)":"Network request failed (Buoy Offline)");e.setReadyState(4);b()};const Q=()=>u>0&&C()-q>=u;const X=()=>{x(k);if(u>0)k=U(()=>_(true),Math.max(0,u-(C()-q)))};Object.defineProperty(e,"timeout",{configurable:true,get:()=>D?0:u,set:t=>{u=Math.max(0,Number(t)||0);X()}});Object.defineProperty(e,"abort",{configurable:true,value:()=>{if(!s){z.call(e);b()}}});Object.defineProperty(e,"open",{configurable:true,value:(...t)=>{const n=Reflect.apply(K,e,t);b();return n}});e._sent=true;e._requestId=null;e.addEventListener("loadend",b);X();const l=e;const w=(t,n)=>{const d=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(e,t,{configurable:true,writable:true,value:n});L.push(()=>R(t,d))};const V=(t,n,d)=>{const m=new Event("progress");Object.defineProperties(m,{loaded:{value:n},total:{value:d},lengthComputable:{value:true}});t.dispatchEvent(m)};const y=i.downloadBytesPerSecond;if(y&&typeof l.__didReceiveData==="function"&&typeof l.__didCompleteResponse==="function"){const t=l.__didReceiveData.bind(e);const n=l.__didReceiveIncrementalData?.bind(e);const d=l.__didCompleteResponse.bind(e);const m=l.__didReceiveDataProgress?.bind(e);let H=Promise.resolve();let h=0;const Y=ee(y);const S=o=>{H=H.then(async()=>{if(!s)await o()}).catch(r=>{if(!s)_(false,r instanceof Error?r.message:String(r))})};const I=async(o,r,c=-1)=>{const j=!e.responseType||e.responseType==="text"||e.responseType==="json";if(j&&typeof r==="string"&&n){const f=new TextEncoder().encode(r);const M=new TextDecoder;for(let p=0;p<f.byteLength;){const P=Math.min($(y),f.byteLength-p);await Y(P,g.signal);if(s)return;const Z=M.decode(f.subarray(p,p+P),{stream:p+P<f.byteLength});p+=P;h+=P;n(o,Z,h,c);m?.(o,h,c)}}else{const f=typeof r==="object"&&r?r.size:e.responseType==="arraybuffer"&&typeof r==="string"?Math.max(0,r.length*3/4-(r.endsWith("==")?2:r.endsWith("=")?1:0)):A(r);if(typeof f!=="number")throw new Error("Cannot read this response size.");const M=h;await B(f,y,g.signal,p=>{h=M+p;m?.(o,h,c<0?f:c)});if(!s)t(o,r)}};w("__didReceiveData",(o,r)=>S(()=>I(o,r)));w("__didReceiveIncrementalData",(o,r,c,j)=>S(()=>I(o,r,j)));w("__didReceiveDataProgress",()=>{});w("__didCompleteResponse",(o,r,c)=>{if(r){d(o,r,c);return}S(async()=>{if(!s)d(o,r,c)})})}else if(y){b();throw new Error("This XHR lacks the RN byte hooks.")}const E=typeof l.__didUploadProgress==="function"?l.__didUploadProgress.bind(e):void 0;if(i.uploadBytesPerSecond&&E)w("__didUploadProgress",()=>{});N=U(()=>{void(async()=>{if(s)return;if(Q()){_(true);return}if(i.profile==="offline"){_(false);return}if(i.uploadBytesPerSecond){const t=(i.uploadCap??te(W)).knownBytes;await B(t,i.uploadBytesPerSecond,g.signal,(n,d)=>{if(E)E(e._requestId,n,d);else if(e.upload)V(e.upload,n,d)})}if(s)return;if(a&&a.kind!=="delay"){if(y&&a.kind==="respond")await B(A(a.body)??0,y,g.signal);if(!s)ne(e,v,a);return}e._sent=false;D=true;try{T()}finally{D=false}})().catch(t=>{if(!s)_(false,t instanceof Error?t.message:String(t))})},i.delayMs+(a?.delayMs??0))}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{getAccountAccess as
|
|
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 +1 @@
|
|
|
1
|
-
"use strict";const
|
|
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 +1 @@
|
|
|
1
|
-
"use strict";import{devToolsStorageKeys as
|
|
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 +1 @@
|
|
|
1
|
-
"use strict";import{getNetworkCondition as E,setNetworkCondition as T,subscribeNetworkConditions as j,conditionsCanApply as m,networkConditionsRuntimeId as k}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 C,OVERRIDES_INACTIVE_REASON as L}from"../overrides/engine";import{getNetworkListenerCount as R,isNetworkInterceptionLive as M,isNetworkListening as P}from"../utils/networkListener";import{MAX_RULES as w}from"../overrides/types";import{approxJsonSize as S,isOverWireBudget as _}from"@buoy-gg/shared-ui";import{expandKeyedArrays as $,patchFromPath as J,refusalText as W,shapeKind as I,suggestedPatch as U,typedEditViolations as K}from"@buoy-gg/shared-ui";export const SNAPSHOT_BODY_INLINE_LIMIT=16*1024;export const SNAPSHOT_EVENTS_BUDGET=1.25*1024*1024;function v(e,t){if(e===void 0)return false;if((t??0)>SNAPSHOT_BODY_INLINE_LIMIT)return true;return _(e,SNAPSHOT_BODY_INLINE_LIMIT)}const A=new WeakMap;const N=new WeakMap;function q(e){const t=A.get(e);if(t)return t;let n;try{n=F(e)}catch{n=z(e)}A.set(e,n);return n}function z(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=S(t,SNAPSHOT_EVENTS_BUDGET).bytes}catch{}return{event:t,bytes:n}}function F(e){const t=v(e.requestData,e.requestSize);const n=v(e.responseData,e.responseSize);const r=D(e.graphqlVariables);const o=H(e.requestHeaders);const s=H(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:S(u,SNAPSHOT_EVENTS_BUDGET).bytes}}function G(e){const t=N.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=D(r.graphqlVariables,true)}const o={event:r,bytes:S(r,SNAPSHOT_EVENTS_BUDGET).bytes};N.set(e,o);return o}function Y(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=G(e[r]);t[r]=s.event;n+=s.bytes}}return t}function D(e,t=false){if(!e)return e;if(!t&&!v(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 H(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 X=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 p=e=>c.getEventById(e)??a.getEventById(e);const b=e=>e&&typeof e==="object"?e.id:void 0;const g=(e,t)=>!!(e&&typeof e==="object"&&e[t]);const h=()=>C()?{}:{active:false,inactiveReason:L};const Q=["respond","fail","delay"];function Z(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=Q.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,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:te(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 y=e=>!!e&&typeof e==="object"&&!Array.isArray(e);function V(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(!y(e)||!y(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=I(e[s]);const f=I(d);if((l==="array"||l==="object")&&l!==f){r.breaks.push({path:u,from:l,to:f})}o[s]=V(e[s],d,u,r)}else{o[s]=d}}return o}function ee(e,t){if(e.body!=null||!y(e.bodyPatch)||typeof t!=="string")return[];try{return K(JSON.parse(t),e.bodyPatch,{noun:"response body"})}catch{return[]}}function te(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(V(JSON.parse(n),e.bodyPatch),null,2)}catch{return n}}return n}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.id;if(typeof n!=="string")return null;const r=i.getState().rules.find(o=>o.id===n);return r?{...r}:null}function ne(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 oe(e){if(!e||typeof e!=="object")return null;const t=e.fromRequestId;if(typeof t!=="string"||!t)return null;const n=p(t);return n?x(n):null}export const networkSyncAdapter={dispose:()=>{i.setEnabled(false)},version:6,getSnapshot:()=>{c.ensureInterception();return{conditions:{version:1,runtimeId:k,profile:E(),available:m()},events:Y(c.getEvents()),overrides:X(i.getState()),saved:a.getRecords().map(e=>({...e,event:q(e.event).event}))}},subscribe:e=>{const t=c.subscribeToEvents(e);const n=j(e);const r=a.subscribe(e);const o=i.subscribe(e);return()=>{n();t();r();o()}},actions:{getNetworkConditions:()=>({runtimeId:k,profile:E(),available:m()}),setNetworkConditions:e=>{const t=e&&typeof e==="object"?e.profile:void 0;return{runtimeId:k,profile:T(t),available:m()}},clearEvents:()=>{c.clearEvents()},getEventBody:e=>{const t=b(e);if(!t)return null;const n=p(t);if(!n)return null;return{url:n.url??null,method:n.method??null,status:n.status??null,override:n.override??null,requestData:n.requestData??null,responseData:n.responseData??null,requestHeaders:n.requestHeaders??null,responseHeaders:n.responseHeaders??null}},setPinned:e=>{const t=b(e);if(!t)return null;const n=p(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=b(e);if(!t)return null;const n=p(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=oe(e)??ne(e)??(n?re(e):null);if(t&&typeof t.bodyPath==="string"&&t.body==null){const d=r?.body??(typeof t.id==="string"?i.getState().rules.find(f=>f.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=J(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(u=>u.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."}}if(t.force!==true){let u;try{const f=$(JSON.parse(d),t.bodyPatch);u=f.error;if(f.notes.length)t.bodyPatch=f.patch}catch{}if(u){return{ok:false,error:`Refused: ${u}`}}const l=ee(t,d);if(l.length>0){return{ok:false,error:W(l,"response body",U(t.bodyPatch,l)),violations:l}}}}const o=Z(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=b(e);if(!t)return{ok:false,error:"Missing rule id."};i.setRuleEnabled(t,g(e,"enabled"));return{ok:true,...h()}},deleteOverrideRule:e=>{const t=b(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>w){return{ok:false,error:`Too many rules: ${t.rules.length}. The most is ${w}.`}}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=b(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=R()}catch{}let r=null;try{r=M()}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:R(),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 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,37 +1,38 @@
|
|
|
1
|
-
"use strict";function d(n){if(n===void 0||n===null)return"N/A";if(n===0)return"0 B";const
|
|
1
|
+
"use strict";function d(n){if(n===void 0||n===null)return"N/A";if(n===0)return"0 B";const e=1024;const u=["B","KB","MB","GB","TB"];const a=Math.floor(Math.log(n)/Math.log(e));return`${(n/Math.pow(e,a)).toFixed(1)} ${u[a]}`}function t(n,e){if(e===-1)return true;if(!n)return true;try{const u=JSON.stringify(n).length;return u<e*1024}catch{return false}}export function generateNetworkCopyText(n,e){let u=n;if(e.filterMode==="failed"){u=u.filter(s=>s.error||s.status&&s.status>=400)}else if(e.filterMode==="success"){u=u.filter(s=>s.status&&s.status>=200&&s.status<300)}if(u.length===0){return"No requests to copy"}if(e.format==="plaintext"){return u.map(s=>`${s.method} ${s.url}`).join("\n")}if(e.format==="json"){const s=u.map(i=>{const r={};if(e.includeMethod){r.method=i.method;r.url=i.url}if(e.includeStatus){r.status=i.status;r.statusText=i.statusText}if(e.includeDuration)r.duration=i.duration;if(i.condition)r.condition=i.condition;if(e.includeTimestamp)r.timestamp=i.timestamp;if(e.includeClient)r.requestClient=i.requestClient;if(e.includeSizes){r.requestSize=i.requestSize;r.responseSize=i.responseSize}if(e.includeErrors&&i.error)r.error=i.error;if(e.includeRequestHeaders){r.requestHeaders=i.requestHeaders}if(e.includeResponseHeaders){r.responseHeaders=i.responseHeaders}if(e.includeRequestBody&&t(i.requestData,e.bodySizeThreshold)){r.requestData=i.requestData}if(e.includeResponseBody&&t(i.responseData,e.bodySizeThreshold)){r.responseData=i.responseData}return r});return JSON.stringify(s,null,2)}const a=u.map((s,i)=>{let r=`# Request ${i+1}
|
|
2
2
|
|
|
3
|
-
`;if(
|
|
4
|
-
`;r+=`**URL:** ${
|
|
5
|
-
`}if(
|
|
6
|
-
`}if(
|
|
7
|
-
`}if(
|
|
8
|
-
`;if(s.
|
|
9
|
-
|
|
10
|
-
`}if(
|
|
3
|
+
`;if(e.includeMethod){r+=`**Method:** ${s.method}
|
|
4
|
+
`;r+=`**URL:** ${s.url}
|
|
5
|
+
`}if(e.includeStatus){const o=s.status||"Pending";r+=`**Status:** ${o}${s.statusText?` (${s.statusText})`:""}
|
|
6
|
+
`}if(e.includeClient&&s.requestClient){r+=`**Client:** ${s.requestClient}
|
|
7
|
+
`}if(s.condition)r+=`Conditions: ${s.condition.profile} (+${s.condition.delayMs} ms)
|
|
8
|
+
`;if(s.condition?.uploadCap?.note)r+=`${s.condition.uploadCap.note}
|
|
9
|
+
`;if(e.includeDuration&&s.duration){r+=`**Duration:** ${s.duration}ms
|
|
10
|
+
`}if(e.includeTimestamp){r+=`**Timestamp:** ${new Date(s.timestamp).toISOString()}
|
|
11
|
+
`}if(e.includeSizes){const o=s.requestSize?d(s.requestSize):"N/A";const f=s.responseSize?d(s.responseSize):"N/A";r+=`**Request Size:** ${o}
|
|
11
12
|
`;r+=`**Response Size:** ${f}
|
|
12
|
-
`}if(
|
|
13
|
-
`}if(
|
|
13
|
+
`}if(e.includeErrors&&s.error){r+=`**Error:** ${s.error}
|
|
14
|
+
`}if(e.includeRequestHeaders&&Object.keys(s.requestHeaders).length>0){r+=`
|
|
14
15
|
## Request Headers
|
|
15
16
|
\`\`\`json
|
|
16
|
-
${JSON.stringify(
|
|
17
|
+
${JSON.stringify(s.requestHeaders,null,2)}
|
|
17
18
|
\`\`\`
|
|
18
|
-
`}if(
|
|
19
|
+
`}if(e.includeRequestBody){r+=`
|
|
19
20
|
## Request Data
|
|
20
|
-
`;if(t(
|
|
21
|
-
${JSON.stringify(
|
|
21
|
+
`;if(t(s.requestData,e.bodySizeThreshold)){r+=`\`\`\`json
|
|
22
|
+
${JSON.stringify(s.requestData,null,2)}
|
|
22
23
|
\`\`\`
|
|
23
|
-
`}else{const o=
|
|
24
|
-
`}}if(
|
|
24
|
+
`}else{const o=s.requestSize?d(s.requestSize):"Unknown size";r+=`_Payload omitted (${o}). Exceeds ${e.bodySizeThreshold}KB threshold._
|
|
25
|
+
`}}if(e.includeResponseHeaders&&Object.keys(s.responseHeaders).length>0){r+=`
|
|
25
26
|
## Response Headers
|
|
26
27
|
\`\`\`json
|
|
27
|
-
${JSON.stringify(
|
|
28
|
+
${JSON.stringify(s.responseHeaders,null,2)}
|
|
28
29
|
\`\`\`
|
|
29
|
-
`}if(
|
|
30
|
+
`}if(e.includeResponseBody){r+=`
|
|
30
31
|
## Response Data
|
|
31
|
-
`;if(t(
|
|
32
|
-
${JSON.stringify(
|
|
32
|
+
`;if(t(s.responseData,e.bodySizeThreshold)){r+=`\`\`\`json
|
|
33
|
+
${JSON.stringify(s.responseData,null,2)}
|
|
33
34
|
\`\`\`
|
|
34
|
-
`}else{const o=
|
|
35
|
+
`}else{const o=s.responseSize?d(s.responseSize):"Unknown size";r+=`_Payload omitted (${o}). Exceeds ${e.bodySizeThreshold}KB threshold._
|
|
35
36
|
`}}r+=`
|
|
36
37
|
---
|
|
37
38
|
`;return r}).join("\n");const l=`# Network Requests (${u.length} total)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
"use strict";import{isBuoyRequest as
|
|
1
|
+
"use strict";import{paceByteCount as ue,paceResponse as le,uploadBodySize as he,uploadSize as pe,utf8Length as fe}from"../conditions/pacer";import{isBuoyRequest as ye}from"@buoy-gg/shared-ui";import{resolveRequestUrl as W}from"./resolveRequestUrl";import{nextRequestId as Y}from"./requestId";import{runConditionXhr as me}from"../conditions/xhr";import{snapshotNetworkCondition as re}from"../conditions/store";import{throwIfAborted as V,waitBeforeDispatch as be}from"../conditions/wait";import{accountCheckFor as ge,overrideForRequest as oe,overrideRulesLoaded as Re,overrideRulesNeedBody as we,overrideRulesReady as ie}from"../overrides/engine";import{runOverride as Le,hasPendingStandardRequest as He}from"../overrides/applyToXhr";import{canSynthesizeResponse as Q,synthesizeFetchError as qe,synthesizeResponse as Se}from"../overrides/applyToFetch";import{markForOutcome as ae}from"../overrides/types";import{httpStatusText as _e,xhrCompletionKind as Te}from"./httpCompletion";import{realNow as v}from"./realNow";let A;function ce(b){const e=globalThis.__buoyHeaderInjectors;if(!e||e.length===0)return void 0;let t;for(const s of e){try{const l=s(b);if(l)t={...t,...l}}catch{}}return t}function Ee(){if(A!==void 0)return A;A=null;try{if(typeof __DEV__!=="undefined"&&!__DEV__)return A;const b=require("react-native");const e=b?.NativeModules?.SourceCode;const t=e?.getConstants?.().scriptURL??e?.scriptURL;if(typeof t==="string"&&/^https?:\/\//.test(t)){const s=new URL(t);A=`${s.protocol}//${s.host}`}}catch{A=null}return A}let M=false;const ve=Symbol.for("buoy.earlyNetwork");function Oe(b){const e={};if(!b)return e;if(typeof Headers!=="undefined"&&b instanceof Headers)b.forEach((t,s)=>{e[s]=t});else if(Array.isArray(b))for(const[t,s]of b)e[t]=s;else Object.assign(e,b);return e}export const BUOY_FETCH_INTERCEPTOR_FLAG="__buoyNetworkFetchIntercepted";export const BUOY_XHR_INTERCEPTOR_FLAG="__buoyNetworkXhrIntercepted";const Xe=["text/event-stream","application/x-ndjson","application/stream+json"];const Z="[streaming\u2026]";let ee=false;function ke(){if(ee)return true;const b=globalThis.document;ee=!!b?.querySelector?.("[ng-version]");return ee}function de(b){if(!b)return false;const e=b.toLowerCase();return Xe.some(t=>e.includes(t))}const xe="__BUOY_INTERNAL_HOSTS__";function Ne(b){const e=globalThis[xe];if(!(e instanceof Set)||e.size===0)return false;let t;try{t=new URL(b).host.toLowerCase()}catch{return false}for(const s of e){if(typeof s==="string"&&s&&t===s.toLowerCase())return true}return false}class Be{listeners=[];isListening=false;patchedFetch=null;patchedXHROpen=null;patchedXHRSend=null;patchedXHRSetRequestHeader=null;fetchGeneration=0;xhrGeneration=0;constructor(){this.originalFetch=globalThis.fetch;this.originalXHROpen=XMLHttpRequest.prototype.open;this.originalXHRSend=XMLHttpRequest.prototype.send;this.originalXHRSetRequestHeader=XMLHttpRequest.prototype.setRequestHeader}shouldIgnoreUrl(e){if(ye(e))return true;try{const t=new URL(e);if(t.hostname==="keygen.sh"||t.hostname.endsWith(".keygen.sh"))return true;if((t.hostname==="buoy.gg"||t.hostname==="www.buoy.gg")&&(t.pathname.startsWith("/api/license")||t.pathname.startsWith("/api/settings/")))return true;const s=t.hostname==="localhost"||t.hostname==="127.0.0.1"||t.hostname==="10.0.2.2";if(s&&["8081","8802"].includes(t.port))return true;const l=Ee();if(l&&`${t.protocol}//${t.host}`===l)return true}catch{return false}return Ne(e)}emit(e){this.listeners.forEach(t=>{try{t(e)}catch(s){}})}parseUrl(e){let t=null;const s=e.indexOf("?");if(s>-1){t={};e.substring(s+1).split("&").forEach(l=>{const[u,i]=l.split("=");if(u&&i!==void 0){t[u]=decodeURIComponent(i.replace(/\+/g," "))}})}return{url:s>-1?e.substring(0,s):e,params:t}}async readStreamedBody(e,t=256*1024){const s=e.body;if(!s||typeof s.getReader!=="function"){const f=await e.text();return f.length>t?{body:`${f.slice(0,t)}
|
|
2
2
|
|
|
3
|
-
... [truncated]`,size:f.length}:{body:f,size:f.length}}const
|
|
3
|
+
... [truncated]`,size:f.length}:{body:f,size:f.length}}const l=s.getReader();const u=new TextDecoder;let i="";let p=0;let g=false;try{for(;;){const{done:f,value:a}=await l.read();if(f)break;p+=a?.byteLength??0;if(!g){i+=u.decode(a,{stream:true});if(p>=t){i=`${i.slice(0,t)}
|
|
4
4
|
|
|
5
|
-
... [truncated]`;
|
|
5
|
+
... [truncated]`;g=true;break}}}if(!g)i+=u.decode()}finally{try{void Promise.resolve(l.cancel()).catch(()=>{})}catch{}try{l.releaseLock()}catch{}}return{body:i,size:p}}async processResponseBody(e,t=1024*1024){try{const s=e.headers.get("content-length");if(s){const i=parseInt(s,10);if(!isNaN(i)&&i>t){return{body:`[Response too large: ${this.formatBytes(i)}]`,size:i,truncated:true}}}const l=await e.text();const u=l.length;if(u>t){const i=l.substring(0,t);const p=u-t;return{body:`${i}
|
|
6
6
|
|
|
7
|
-
... [truncated, ${this.formatBytes(h)} omitted]`,size:a,truncated:true}}try{return{body:JSON.parse(c),size:a,truncated:false}}catch{return{body:c,size:a,truncated:false}}}catch(n){return{body:"~~~ unable to read body ~~~",size:0,truncated:false}}}formatBytes(e){if(e===0)return"0 B";const t=1024;const n=["B","KB","MB","GB"];const c=Math.floor(Math.log(e)/Math.log(t));return`${Math.round(e/Math.pow(t,c)*100)/100} ${n[c]}`}handleXHRResponse(e,t,n,c,a,r,h,R,f=false,i="xhr",d,H){const y=R?S()-R:0;const l=e._buoyTtfb;const _=l===void 0?void 0:{ttfb:l,download:Math.max(0,y-l)};if(f||e.status===0){this.emit({type:"error",timestamp:new Date,duration:y,request:{id:t||"unknown",url:n,method:c,headers:a,data:r,params:h||void 0,client:i},error:{message:f?"Request failed":"Network error or request aborted"},override:d,condition:H});return}let s;let p=0;try{const o=e.response;if(e.responseType==="json"&&o){s=o;p=JSON.stringify(o).length}else if(e.responseType===""||e.responseType==="text"){if(e.responseText){p=e.responseText.length;try{s=JSON.parse(e.responseText)}catch{s=e.responseText}}}else if(e.responseType==="arraybuffer"){if(o){try{const q=new TextDecoder("utf-8").decode(o);p=q.length;try{s=JSON.parse(q)}catch{s=q}}catch(q){s=`[arraybuffer response - ${o.byteLength||0} bytes]`;p=o.byteLength||0}}else{s=`[arraybuffer response - no data]`;p=0}}else if(e.responseType==="blob"){if(o instanceof Blob){s=`[blob response - ${o.size} bytes, type: ${o.type||"unknown"}]`;p=o.size}else if(o){try{s=typeof o==="string"?JSON.parse(o):o;p=JSON.stringify(s).length}catch{s=`[blob response - unable to parse]`;p=0}}else{s=`[blob response - no data]`;p=0}}else if(o){if(typeof o==="string"){s=o;p=o.length;try{s=JSON.parse(o)}catch{}}else if(typeof o==="object"){s=o;p=JSON.stringify(o).length}else{s=String(o);p=String(o).length}}}catch(o){s="~~~ unable to read body ~~~"}const b={};try{const o=e.getAllResponseHeaders();if(o){o.split("\r\n").forEach(q=>{if(q){const m=q.indexOf(": ");if(m>0){const T=q.substring(0,m).toLowerCase();const u=q.substring(m+2);b[T]=u}}})}}catch{}if(ae(e.status)==="response"){this.emit({type:"response",timestamp:new Date,duration:y,timings:_,request:{id:t||"unknown",url:n,method:c,headers:a,data:r,params:h||void 0,client:i},response:{status:e.status,statusText:ie(e.status,e.statusText),headers:b,body:s,size:p},override:d,condition:H})}else{this.emit({type:"error",timestamp:new Date,duration:y,request:{id:t||"unknown",url:n,method:c,headers:a,data:r,params:h||void 0,client:i},response:{status:e.status,statusText:e.statusText,headers:b,body:s,size:p},error:{message:"Network Error"},override:d,condition:H})}}isFetchInterceptionLive(){return globalThis.fetch[BUOY_FETCH_INTERCEPTOR_FLAG]===true}isXhrInterceptionLive(){return XMLHttpRequest.prototype.send[BUOY_XHR_INTERCEPTOR_FLAG]===true}isInterceptionLive(){return this.isFetchInterceptionLive()&&this.isXhrInterceptionLive()}startListening(){const e=this.isListening&&this.isFetchInterceptionLive();const t=this.isListening&&this.isXhrInterceptionLive();if(e&&t){return}if(!e){this.installFetchInterceptor()}if(!t){this.installXhrInterceptor()}this.isListening=true;if(__DEV__){}}installFetchInterceptor(){const e=this;const t=globalThis.fetch.bind(globalThis);this.originalFetch=globalThis.fetch;const n=++this.fetchGeneration;const c=async(a,r)=>{const h=B(typeof a==="string"?a:a instanceof URL?a.href:a.url);if(n!==e.fetchGeneration){return t(a,r)}if(r?.__buoyInternal||e.shouldIgnoreUrl(h)){const u=x;x=true;try{return t(a,r)}finally{x=u}}const R=S();const f=D("fetch");const i=typeof a==="object"&&"method"in a?a:void 0;const d=r?.method??i?.method??"GET";const H=r?.signal!==void 0?r.signal:i?.signal;J(H);const y=j(h);const{url:l,params:_}=e.parseUrl(h);let s={};const p=r?.headers??i?.headers;if(p){if(p instanceof Headers){p.forEach((u,L)=>{s[L]=u})}else if(Array.isArray(p)){p.forEach(([u,L])=>{s[u]=L})}else{s={...p}}}Object.assign(s,W(h));let b;if(r?.body){if(typeof r.body==="string"){try{b=JSON.parse(r.body)}catch{b=r.body}}else{b=r.body}}const o=s["X-Request-Client"]||s["x-request-client"]||"fetch";const q=y?.profile!=="offline"&&P()?te(h,d,s,typeof r?.body==="string"?r.body:void 0):null;if(q)await q;const m=y?.profile!=="offline"&&P()?$(h,d,s,typeof r?.body==="string"?r.body:void 0):null;const T=m?Y(m):void 0;e.emit({type:"request",timestamp:new Date,request:{id:f||"unknown",url:l,method:d,headers:s,data:b,params:_||void 0,client:o},override:T,condition:y});if(r?.body===void 0&&i?.body&&!i.bodyUsed){try{const u=i.clone();void e.readStreamedBody(u).then(({body:L})=>{try{b=JSON.parse(L)}catch{b=L}e.emit({type:"request-body",timestamp:new Date,request:{id:f||"unknown",url:l,method:d,data:b,client:o}})}).catch(()=>{})}catch{}}try{if(y||m)await ee((y?.delayMs??0)+(m?.delayMs??0),H);J(H);if(y?.profile==="offline")throw new TypeError("Network request failed (Buoy Offline)");if(m?.kind==="fail")throw re(m);let u;if(m?.kind==="respond"){u=oe(h,m)}else{const X=x;x=true;let w;try{w=t(a,r)}finally{x=X}u=await w}const L=S()-R;const E=typeof u.body?.getReader==="function"||V(u.headers?.get?.("content-type"));const I=u.clone();const{body:C,size:O}=E?{body:K,size:0}:await e.processResponseBody(I);const M=S()-R;const F=Math.max(0,M-L);const U=F>0?{ttfb:L,download:F}:void 0;const N={};u.headers.forEach((X,w)=>{N[w.toLowerCase()]=X});e.emit({type:"response",timestamp:new Date,duration:M,timings:U,request:{id:f||"unknown",url:l,method:d,headers:s,data:b,params:_||void 0,client:o},response:{status:u.status,statusText:u.statusText,headers:N,body:C,size:O},override:T,condition:y});if(E){const X=u.headers?.get?.("content-type");void e.readStreamedBody(I,V(X)?void 0:1024*1024).then(w=>{let G=w.body;if(X?.includes("json")){try{G=JSON.parse(w.body)}catch{}}e.emit({type:"response",timestamp:new Date,duration:S()-R,timings:U,request:{id:f||"unknown",url:l,method:d,headers:s,data:b,params:_||void 0,client:o},response:{status:u.status,statusText:u.statusText,headers:N,body:G,size:w.size},override:T,condition:y})}).catch(()=>{})}return u}catch(u){const L=S()-R;e.emit({type:"error",timestamp:new Date,duration:L,request:{id:f||"unknown",url:l,method:d,headers:s,data:b,params:_||void 0,client:o},error:{message:u instanceof Error?u.message:"Network error",stack:u instanceof Error?u.stack:void 0},override:T,condition:y});throw u}};c[BUOY_FETCH_INTERCEPTOR_FLAG]=true;this.patchedFetch=c;globalThis.fetch=this.patchedFetch}installXhrInterceptor(){const e=this;const t=XMLHttpRequest.prototype.open;const n=XMLHttpRequest.prototype.send;const c=XMLHttpRequest.prototype.setRequestHeader;this.originalXHROpen=t;this.originalXHRSend=n;this.originalXHRSetRequestHeader=c;const a=++this.xhrGeneration;const r=new WeakMap;const h=function(i,d,H,y,l){const _=t.call(this,i,d,H??true,y,l);if(a===e.xhrGeneration){r.get(this)?.();const s=this;s._buoyRequestId=D("xhr");s._method=i;s._url=B(d);s._buoyStartTime=S();s._requestHeaders={}}return _};const R=function(i,d){const H=this;if(a===e.xhrGeneration&&H._requestHeaders){H._requestHeaders[i]=d}return c.call(this,i,d)};const f=function(i){if(a!==e.xhrGeneration||x){return n.call(this,i)}if(ne(this))throw new DOMException("The request has already been sent.","InvalidStateError");if(this.readyState!==1||this._sent){return n.call(this,i)}const d=this;const H=d._buoyRequestId;const y=d._method||"GET";const l=d._url||"";const _=S();d._buoyStartTime=_;d._buoyTtfb=void 0;const s=d._requestHeaders||{};Object.assign(s,W(l));if(e.shouldIgnoreUrl(l)){return n.call(this,i)}const{url:p,params:b}=e.parseUrl(l);let o;if(i){if(typeof i==="string"){try{o=JSON.parse(i)}catch{o=i}}else{o=i}}const q=s["X-Request-Client"]||s["x-request-client"];const m=s["Accept"]||s["accept"]||"";const T=m.includes("application/json")&&m.includes("text/plain")&&m.includes("*/*")&&!he();const u=q||(T?"axios":"xhr");const L=j(l);const E=L?.profile==="offline"?null:$(l,y,s,typeof i==="string"?i:void 0);const I=E?Y(E):void 0;e.emit({type:"request",timestamp:new Date,request:{id:H||"unknown",url:p,method:y,headers:s,data:o,params:b||void 0,client:u},override:I,condition:L});let C=false;const O=(w=false)=>{if(C)return;C=true;e.handleXHRResponse(this,H||"unknown",p,y,s,o,b,_||0,w,u,I,L);M()};const M=()=>{r.delete(this);this.removeEventListener("load",F);this.removeEventListener("error",U);this.removeEventListener("abort",N);this.removeEventListener("readystatechange",X)};r.set(this,M);const F=()=>{O(false)};const U=()=>{O(true)};const N=()=>{O(true)};const X=()=>{if(this.readyState===2){const w=this;if(w._buoyTtfb===void 0&&w._buoyStartTime){w._buoyTtfb=S()-w._buoyStartTime}}if(this.readyState===4&&!C){O(false)}};this.addEventListener("load",F);this.addEventListener("error",U);this.addEventListener("abort",N);this.addEventListener("readystatechange",X);if(L){Z(this,l,L,E,()=>n.call(this,i));return}if(E){const w=se(this,l,E,()=>n.call(this,i));if(w)return}return n.call(this,i)};f[BUOY_XHR_INTERCEPTOR_FLAG]=true;this.patchedXHROpen=h;this.patchedXHRSend=f;this.patchedXHRSetRequestHeader=R;XMLHttpRequest.prototype.open=this.patchedXHROpen;XMLHttpRequest.prototype.send=this.patchedXHRSend;XMLHttpRequest.prototype.setRequestHeader=this.patchedXHRSetRequestHeader}stopListening(){if(!this.isListening){return}this.fetchGeneration++;this.xhrGeneration++;if(this.patchedFetch&&globalThis.fetch===this.patchedFetch){globalThis.fetch=this.originalFetch}if(this.patchedXHROpen&&XMLHttpRequest.prototype.open===this.patchedXHROpen){XMLHttpRequest.prototype.open=this.originalXHROpen}if(this.patchedXHRSend&&XMLHttpRequest.prototype.send===this.patchedXHRSend){XMLHttpRequest.prototype.send=this.originalXHRSend}if(this.patchedXHRSetRequestHeader&&XMLHttpRequest.prototype.setRequestHeader===this.patchedXHRSetRequestHeader){XMLHttpRequest.prototype.setRequestHeader=this.originalXHRSetRequestHeader}this.patchedFetch=null;this.patchedXHROpen=null;this.patchedXHRSend=null;this.patchedXHRSetRequestHeader=null;this.isListening=false;if(__DEV__){}}adoptEarlyRequests(){const e=globalThis.__BUOY_EARLY_NETWORK__;if(e?.version!==1)return;for(const t of e.adopt()){try{if(t.kind==="fetch")this.adoptEarlyFetch(t);else this.adoptEarlyXhr(t)}catch{}}}adoptEarlyFetch(e){const{input:t,init:n}=e;const c=typeof t==="object"&&"method"in t?t:void 0;const a=B(typeof t==="string"?t:t instanceof URL?t.href:t.url);if(this.shouldIgnoreUrl(a))return;const r=D("fetch");const h=n?.method??c?.method??"GET";const{url:R,params:f}=this.parseUrl(a);const i=de(n?.headers??c?.headers);let d=n?.body;if(typeof d==="string"){try{d=JSON.parse(d)}catch{}}const H=i["X-Request-Client"]||i["x-request-client"]||"fetch";const y=()=>({id:r,url:R,method:h,headers:i,data:d,params:f||void 0,client:H});this.emit({type:"request",timestamp:new Date(e.start),request:y()});if(e.requestCopy){void this.readStreamedBody(e.requestCopy).then(({body:l})=>{try{d=JSON.parse(l)}catch{d=l}this.emit({type:"request-body",timestamp:new Date,request:{id:r,url:R,method:h,data:d,client:H}})}).catch(()=>{})}void e.settled.then(async({response:l,clone:_,error:s,headersAt:p})=>{if(!l){this.emit({type:"error",timestamp:new Date,duration:p-e.start,request:y(),error:{message:s instanceof Error?s.message:"Network error",stack:s instanceof Error?s.stack:void 0}});return}const{body:b,size:o}=_?await this.processResponseBody(_):{body:K,size:0};const q=Math.max(0,S()-e.start);const m=p-e.start;const T={};l.headers.forEach((u,L)=>{T[L.toLowerCase()]=u});this.emit({type:"response",timestamp:new Date,duration:q,timings:q>m?{ttfb:m,download:q-m}:void 0,request:y(),response:{status:l.status,statusText:l.statusText,headers:T,body:b,size:o}})})}adoptEarlyXhr(e){const t=B(e.url);if(this.shouldIgnoreUrl(t))return;const n=D("xhr");const c=e.method.toUpperCase();const{url:a,params:r}=this.parseUrl(t);let h=e.body;if(typeof h==="string"){try{h=JSON.parse(h)}catch{}}const R=e.headers["X-Request-Client"]||e.headers["x-request-client"]||"xhr";this.emit({type:"request",timestamp:new Date(e.start),request:{id:n,url:a,method:c,headers:e.headers,data:h,params:r||void 0,client:R}});const f=e.xhr;const i=()=>{const d=(f._buoyEarlyEnd??S())-e.start;this.handleXHRResponse(f,n,a,c,e.headers,h,r,S()-d,false,R)};if(f.readyState===4)i();else f.addEventListener("loadend",i,{once:true})}addListener(e){this.listeners.push(e);return()=>{const t=this.listeners.indexOf(e);if(t>-1){this.listeners.splice(t,1)}}}removeAllListeners(){this.listeners=[]}get isActive(){return this.isListening}get listenerCount(){return this.listeners.length}}let v=null;const z=()=>{if(!v){v=new fe}return v};export const networkListener=z;export const startNetworkListener=()=>z().startListening();export const stopNetworkListener=()=>v?.stopListening();export const addNetworkListener=g=>z().addListener(g);export const removeAllNetworkListeners=()=>v?.removeAllListeners();export const isNetworkListening=()=>v?.isActive??false;export const getNetworkListenerCount=()=>v?.listenerCount??0;export const isNetworkInterceptionLive=()=>v?.isInterceptionLive()??false;
|
|
7
|
+
... [truncated, ${this.formatBytes(p)} omitted]`,size:u,truncated:true}}try{return{body:JSON.parse(l),size:u,truncated:false}}catch{return{body:l,size:u,truncated:false}}}catch(s){return{body:"~~~ unable to read body ~~~",size:0,truncated:false}}}formatBytes(e){if(e===0)return"0 B";const t=1024;const s=["B","KB","MB","GB"];const l=Math.floor(Math.log(e)/Math.log(t));return`${Math.round(e/Math.pow(t,l)*100)/100} ${s[l]}`}handleXHRResponse(e,t,s,l,u,i,p,g,f=false,a="xhr",n,y){const R=g?v()-g:0;const c=e._buoyTtfb;const L=c===void 0?void 0:{ttfb:c,download:Math.max(0,R-c)};if(f||e.status===0){this.emit({type:"error",timestamp:new Date,duration:R,request:{id:t||"unknown",url:s,method:l,headers:u,data:i,params:p||void 0,client:a},error:{message:f?"Request failed":"Network error or request aborted"},override:n,condition:y});return}let o;let h=0;try{const r=e.response;if(e.responseType==="json"&&r){o=r;h=JSON.stringify(r).length}else if(e.responseType===""||e.responseType==="text"){if(e.responseText){h=e.responseText.length;try{o=JSON.parse(e.responseText)}catch{o=e.responseText}}}else if(e.responseType==="arraybuffer"){if(r){try{const m=new TextDecoder("utf-8").decode(r);h=m.length;try{o=JSON.parse(m)}catch{o=m}}catch(m){o=`[arraybuffer response - ${r.byteLength||0} bytes]`;h=r.byteLength||0}}else{o=`[arraybuffer response - no data]`;h=0}}else if(e.responseType==="blob"){if(r instanceof Blob){o=`[blob response - ${r.size} bytes, type: ${r.type||"unknown"}]`;h=r.size}else if(r){try{o=typeof r==="string"?JSON.parse(r):r;h=JSON.stringify(o).length}catch{o=`[blob response - unable to parse]`;h=0}}else{o=`[blob response - no data]`;h=0}}else if(r){if(typeof r==="string"){o=r;h=r.length;try{o=JSON.parse(r)}catch{}}else if(typeof r==="object"){o=r;h=JSON.stringify(r).length}else{o=String(r);h=String(r).length}}}catch(r){o="~~~ unable to read body ~~~"}if(y?.downloadBytesPerSecond&&(!e.responseType||e.responseType==="text"||e.responseType==="json")){const r=e._response;if(typeof r==="string")h=fe(r)}const H={};try{const r=e.getAllResponseHeaders();if(r){r.split("\r\n").forEach(m=>{if(m){const w=m.indexOf(": ");if(w>0){const k=m.substring(0,w).toLowerCase();const q=m.substring(w+2);H[k]=q}}})}}catch{}if(Te(e.status)==="response"){this.emit({type:"response",timestamp:new Date,duration:R,timings:L,request:{id:t||"unknown",url:s,method:l,headers:u,data:i,params:p||void 0,client:a},response:{status:e.status,statusText:_e(e.status,e.statusText),headers:H,body:o,size:h},override:n,condition:y})}else{this.emit({type:"error",timestamp:new Date,duration:R,request:{id:t||"unknown",url:s,method:l,headers:u,data:i,params:p||void 0,client:a},response:{status:e.status,statusText:e.statusText,headers:H,body:o,size:h},error:{message:"Network Error"},override:n,condition:y})}}isFetchInterceptionLive(){return globalThis.fetch[BUOY_FETCH_INTERCEPTOR_FLAG]===true}isXhrInterceptionLive(){return XMLHttpRequest.prototype.send[BUOY_XHR_INTERCEPTOR_FLAG]===true}isInterceptionLive(){return this.isFetchInterceptionLive()&&this.isXhrInterceptionLive()}startListening(){const e=this.isListening&&this.isFetchInterceptionLive();const t=this.isListening&&this.isXhrInterceptionLive();if(e&&t){return}if(!e){this.installFetchInterceptor()}if(!t){this.installXhrInterceptor()}this.isListening=true;if(__DEV__){}}installFetchInterceptor(){const e=this;const t=globalThis.fetch.bind(globalThis);this.originalFetch=globalThis.fetch;const s=++this.fetchGeneration;const l=async(u,i)=>{const p=W(typeof u==="string"?u:u instanceof URL?u.href:u.url);if(s!==e.fetchGeneration){return t(u,i)}if(i?.__buoyInternal||e.shouldIgnoreUrl(p)){const d=M;M=true;try{return t(u,i)}finally{M=d}}const g=v();const f=Y("fetch");const a=typeof u==="object"&&"method"in u?u:void 0;const n=i?.method??a?.method??"GET";const y=i?.signal!==void 0?i.signal:a?.signal;V(y);const R=re(p);const c=R?.uploadBytesPerSecond?{...R,uploadCap:he(u,i)}:R;const{url:L,params:o}=e.parseUrl(p);let h={};const H=i?.headers??a?.headers;if(H){if(H instanceof Headers){H.forEach((d,_)=>{h[_]=d})}else if(Array.isArray(H)){H.forEach(([d,_])=>{h[d]=_})}else{h={...H}}}Object.assign(h,ce(p));let r;if(i?.body){if(typeof i.body==="string"){try{r=JSON.parse(i.body)}catch{r=i.body}}else{r=i.body}}const m=h["X-Request-Client"]||h["x-request-client"]||"fetch";if(c?.profile!=="offline"&&Q())await ie();let w=typeof i?.body==="string"?i.body:void 0;if(w===void 0&&i?.body===void 0&&a&&!a.bodyUsed&&n!=="GET"&&n!=="HEAD"&&we()){try{w=(await e.readStreamedBody(a.clone())).body}catch{}}const k=c?.profile!=="offline"&&Q()?ge(p,n,h,w):null;if(k)await k;const q=c?.profile!=="offline"&&Q()?oe(p,n,h,w):null;const O=q?ae(q):void 0;e.emit({type:"request",timestamp:new Date,request:{id:f||"unknown",url:L,method:n,headers:h,data:r,params:o||void 0,client:m},override:O,condition:c});const B=d=>{try{r=JSON.parse(d)}catch{r=d}e.emit({type:"request-body",timestamp:new Date,request:{id:f||"unknown",url:L,method:n,data:r,client:m}})};if(i?.body===void 0&&a&&typeof w==="string"){B(w)}else if(!c?.uploadBytesPerSecond&&i?.body===void 0&&a&&!a.bodyUsed&&n!=="GET"&&n!=="HEAD"){try{const d=a.clone();void e.readStreamedBody(d).then(({body:_})=>{if(_)B(_)}).catch(()=>{})}catch{}}try{if(c||q)await be((c?.delayMs??0)+(q?.delayMs??0),y);V(y);if(c?.profile==="offline")throw new TypeError("Network request failed (Buoy Offline)");if(q?.kind==="fail")throw qe(q);if(c?.uploadBytesPerSecond){await ue(c.uploadCap?.knownBytes??0,c.uploadBytesPerSecond,y);V(y)}let d;if(q?.kind==="respond"){d=Se(p,q)}else{const E=M;M=true;let S;try{S=t(u,i)}finally{M=E}d=await S}if(c?.downloadBytesPerSecond){const E={};d.headers.forEach((x,N)=>{E[N.toLowerCase()]=x});let S=0;let X=0;const $=[];const G=(x,N)=>{const D=new Uint8Array(X);let se=0;for(const ne of $){D.set(ne,se);se+=ne.byteLength}let K=x?new TextDecoder().decode(D):Z;if(x&&E["content-type"]?.includes("json")){try{K=JSON.parse(K)}catch{}}e.emit({type:N!==void 0?"error":"response",timestamp:new Date,duration:v()-g,request:{id:f,url:L,method:n,headers:h,data:r,params:o||void 0,client:m},response:{status:d.status,statusText:d.statusText,headers:E,body:K,size:S},...N!==void 0?{error:{message:N instanceof Error?N.message:String(N)}}:{},override:O,condition:c})};G(false);return le(d,c.downloadBytesPerSecond,y,(x,N)=>{if(x){S+=x.byteLength;const D=Math.min(x.byteLength,65536-X);if(D>0){$.push(x.slice(0,D));X+=D}}else G(true,N)},n.toUpperCase()==="HEAD")}const _=v()-g;const F=typeof d.body?.getReader==="function"||de(d.headers?.get?.("content-type"));const I=d.clone();const{body:P,size:J}=F?{body:Z,size:0}:await e.processResponseBody(I);const U=v()-g;const z=Math.max(0,U-_);const j=z>0?{ttfb:_,download:z}:void 0;const T={};d.headers.forEach((E,S)=>{T[S.toLowerCase()]=E});e.emit({type:"response",timestamp:new Date,duration:U,timings:j,request:{id:f||"unknown",url:L,method:n,headers:h,data:r,params:o||void 0,client:m},response:{status:d.status,statusText:d.statusText,headers:T,body:P,size:J},override:O,condition:c});if(F){const E=d.headers?.get?.("content-type");void e.readStreamedBody(I,de(E)?void 0:1024*1024).then(S=>{let X=S.body;if(E?.includes("json")){try{X=JSON.parse(S.body)}catch{}}e.emit({type:"response",timestamp:new Date,duration:v()-g,timings:j,request:{id:f||"unknown",url:L,method:n,headers:h,data:r,params:o||void 0,client:m},response:{status:d.status,statusText:d.statusText,headers:T,body:X,size:S.size},override:O,condition:c})}).catch(()=>{})}return d}catch(d){const _=v()-g;e.emit({type:"error",timestamp:new Date,duration:_,request:{id:f||"unknown",url:L,method:n,headers:h,data:r,params:o||void 0,client:m},error:{message:d instanceof Error?d.message:"Network error",stack:d instanceof Error?d.stack:void 0},override:O,condition:c});throw d}};l[BUOY_FETCH_INTERCEPTOR_FLAG]=true;this.patchedFetch=l;globalThis.fetch=this.patchedFetch}installXhrInterceptor(){const e=this;const t=XMLHttpRequest.prototype.open;const s=XMLHttpRequest.prototype.send;const l=XMLHttpRequest.prototype.setRequestHeader;this.originalXHROpen=t;this.originalXHRSend=s;this.originalXHRSetRequestHeader=l;const u=++this.xhrGeneration;const i=new WeakMap;const p=function(a,n,y,R,c){const L=t.call(this,a,n,y??true,R,c);if(u===e.xhrGeneration){i.get(this)?.();const o=this;o._buoyRequestId=Y("xhr");o._method=a;o._url=W(n);o._buoyStartTime=v();o._requestHeaders={};o._buoyAsync=y!==false;o._buoyRestoreAbort?.();o._buoyWaitedForRules=false;o._buoyHeldSend=false;o._buoyOpenSeq=(o._buoyOpenSeq??0)+1}return L};const g=function(a,n){const y=this;if(u===e.xhrGeneration&&y._requestHeaders){y._requestHeaders[a]=n}return l.call(this,a,n)};const f=function(a){if(u!==e.xhrGeneration||M){return s.call(this,a)}if(He(this))throw new DOMException("The request has already been sent.","InvalidStateError");if(this.readyState!==1||this._sent){return s.call(this,a)}const n=this;if(n._buoyHeldSend)throw new DOMException("The request has already been sent.","InvalidStateError");if(!Re()&&n._buoyAsync!==false&&!n._buoyWaitedForRules){n._buoyWaitedForRules=true;n._buoyHeldSend=true;const T=n._buoyOpenSeq;let E=false;const S=Object.prototype.hasOwnProperty.call(this,"abort")?this.abort:void 0;const X=()=>{if(n._buoyRestoreAbort!==X)return;n._buoyRestoreAbort=void 0;if(S)this.abort=S;else delete this.abort};n._buoyRestoreAbort=X;const $=S??Object.getPrototypeOf(this).abort;this.abort=function(){E=true;n._buoyHeldSend=false;X();return $.call(this)};const G=()=>{X();if(E||n._buoyOpenSeq!==T)return;n._buoyHeldSend=false;if(this.readyState===1&&!this._sent)f.call(this,a)};void ie().then(G,G);return}const y=n._buoyRequestId;const R=n._method||"GET";const c=n._url||"";const L=v();n._buoyStartTime=L;n._buoyTtfb=void 0;const o=n._requestHeaders||{};Object.assign(o,ce(c));if(e.shouldIgnoreUrl(c)){return s.call(this,a)}const{url:h,params:H}=e.parseUrl(c);let r;if(a){if(typeof a==="string"){try{r=JSON.parse(a)}catch{r=a}}else{r=a}}const m=o["X-Request-Client"]||o["x-request-client"];const w=o["Accept"]||o["accept"]||"";const k=w.includes("application/json")&&w.includes("text/plain")&&w.includes("*/*")&&!ke();const q=m||(k?"axios":"xhr");const O=re(c);const B=O?.uploadBytesPerSecond?{...O,uploadCap:pe(a)}:O;const d=B?.profile==="offline"?null:oe(c,R,o,typeof a==="string"?a:void 0);const _=d?ae(d):void 0;e.emit({type:"request",timestamp:new Date,request:{id:y||"unknown",url:h,method:R,headers:o,data:r,params:H||void 0,client:q},override:_,condition:B});let F=false;const I=(T=false)=>{if(F)return;F=true;e.handleXHRResponse(this,y||"unknown",h,R,o,r,H,L||0,T,q,_,B);P()};const P=()=>{i.delete(this);this.removeEventListener("load",J);this.removeEventListener("error",U);this.removeEventListener("abort",z);this.removeEventListener("readystatechange",j)};i.set(this,P);const J=()=>{I(false)};const U=()=>{I(true)};const z=()=>{I(true)};const j=()=>{if(this.readyState===2){const T=this;if(T._buoyTtfb===void 0&&T._buoyStartTime){T._buoyTtfb=v()-T._buoyStartTime}}if(this.readyState===4&&!F){I(false)}};this.addEventListener("load",J);this.addEventListener("error",U);this.addEventListener("abort",z);this.addEventListener("readystatechange",j);if(B){me(this,c,B,d,()=>s.call(this,a),a);return}if(d){const T=Le(this,c,d,()=>s.call(this,a));if(T)return}return s.call(this,a)};f[BUOY_XHR_INTERCEPTOR_FLAG]=true;this.patchedXHROpen=p;this.patchedXHRSend=f;this.patchedXHRSetRequestHeader=g;XMLHttpRequest.prototype.open=this.patchedXHROpen;XMLHttpRequest.prototype.send=this.patchedXHRSend;XMLHttpRequest.prototype.setRequestHeader=this.patchedXHRSetRequestHeader}stopListening(){if(!this.isListening){return}this.fetchGeneration++;this.xhrGeneration++;if(this.patchedFetch&&globalThis.fetch===this.patchedFetch){globalThis.fetch=this.originalFetch}if(this.patchedXHROpen&&XMLHttpRequest.prototype.open===this.patchedXHROpen){XMLHttpRequest.prototype.open=this.originalXHROpen}if(this.patchedXHRSend&&XMLHttpRequest.prototype.send===this.patchedXHRSend){XMLHttpRequest.prototype.send=this.originalXHRSend}if(this.patchedXHRSetRequestHeader&&XMLHttpRequest.prototype.setRequestHeader===this.patchedXHRSetRequestHeader){XMLHttpRequest.prototype.setRequestHeader=this.originalXHRSetRequestHeader}this.patchedFetch=null;this.patchedXHROpen=null;this.patchedXHRSend=null;this.patchedXHRSetRequestHeader=null;this.isListening=false;if(__DEV__){}}adoptEarlyRequests(){const e=globalThis;const t=e[ve]??e.__BUOY_EARLY_NETWORK__;if(t?.version!==1)return;for(const s of t.adopt()){try{if(s.kind==="fetch")this.adoptEarlyFetch(s);else this.adoptEarlyXhr(s)}catch{}}}adoptEarlyFetch(e){const{input:t,init:s}=e;const l=typeof t==="object"&&"method"in t?t:void 0;const u=W(typeof t==="string"?t:t instanceof URL?t.href:t.url);if(this.shouldIgnoreUrl(u))return;const i=Y("fetch");const p=s?.method??l?.method??"GET";const{url:g,params:f}=this.parseUrl(u);const a=Oe(s?.headers??l?.headers);let n=s?.body;if(typeof n==="string"){try{n=JSON.parse(n)}catch{}}const y=a["X-Request-Client"]||a["x-request-client"]||"fetch";const R=()=>({id:i,url:g,method:p,headers:a,data:n,params:f||void 0,client:y});this.emit({type:"request",timestamp:new Date(e.start),request:R()});if(e.requestCopy){void this.readStreamedBody(e.requestCopy).then(({body:c})=>{try{n=JSON.parse(c)}catch{n=c}this.emit({type:"request-body",timestamp:new Date,request:{id:i,url:g,method:p,data:n,client:y}})}).catch(()=>{})}void e.settled.then(async({response:c,clone:L,error:o,headersAt:h})=>{if(!c){this.emit({type:"error",timestamp:new Date,duration:h-e.start,request:R(),error:{message:o instanceof Error?o.message:"Network error",stack:o instanceof Error?o.stack:void 0}});return}const{body:H,size:r}=L?await this.processResponseBody(L):{body:Z,size:0};const m=Math.max(0,v()-e.start);const w=h-e.start;const k={};c.headers.forEach((q,O)=>{k[O.toLowerCase()]=q});this.emit({type:"response",timestamp:new Date,duration:m,timings:m>w?{ttfb:w,download:m-w}:void 0,request:R(),response:{status:c.status,statusText:c.statusText,headers:k,body:H,size:r}})})}adoptEarlyXhr(e){const t=W(e.url);if(this.shouldIgnoreUrl(t))return;const s=Y("xhr");const l=e.method.toUpperCase();const{url:u,params:i}=this.parseUrl(t);let p=e.body;if(typeof p==="string"){try{p=JSON.parse(p)}catch{}}const g=e.headers["X-Request-Client"]||e.headers["x-request-client"]||"xhr";this.emit({type:"request",timestamp:new Date(e.start),request:{id:s,url:u,method:l,headers:e.headers,data:p,params:i||void 0,client:g}});const f=e.xhr;const a=()=>{const n=(f._buoyEarlyEnd??v())-e.start;this.handleXHRResponse(f,s,u,l,e.headers,p,i,v()-n,false,g)};if(f.readyState===4)a();else f.addEventListener("loadend",a,{once:true})}addListener(e){this.listeners.push(e);return()=>{const t=this.listeners.indexOf(e);if(t>-1){this.listeners.splice(t,1)}}}removeAllListeners(){this.listeners=[]}get isActive(){return this.isListening}get listenerCount(){return this.listeners.length}}let C=null;const te=()=>{if(!C){C=new Be}return C};export const networkListener=te;export const startNetworkListener=()=>te().startListening();export const stopNetworkListener=()=>C?.stopListening();export const addNetworkListener=b=>te().addListener(b);export const removeAllNetworkListeners=()=>C?.removeAllListeners();export const isNetworkListening=()=>C?.isActive??false;export const getNetworkListenerCount=()=>C?.listenerCount??0;export const isNetworkInterceptionLive=()=>C?.isInterceptionLive()??false;
|
|
@@ -46,6 +46,7 @@ export { networkSavedStore, flagsForEventId, FREE_TIER_SAVED_LIMIT, MAX_PINNED,
|
|
|
46
46
|
export { generateCurl } from "./network/utils/generateCurl";
|
|
47
47
|
/** @internal */
|
|
48
48
|
export { networkListener, addNetworkListener, removeAllNetworkListeners, } from "./network/utils/networkListener";
|
|
49
|
-
export { NETWORK_CONDITIONS, getNetworkCondition, setNetworkCondition, subscribeNetworkConditions } from "./network/conditions/store";
|
|
50
|
-
export type { NetworkConditionProfile, NetworkConditionStamp } from "./network/conditions/store";
|
|
49
|
+
export { NETWORK_CONDITIONS, getNetworkCondition, setNetworkCondition, subscribeNetworkConditions, getNetworkConditions, setNetworkConditions, getNetworkConnection, getConditionsRevision, networkConditionsActive } from "./network/conditions/store";
|
|
50
|
+
export type { NetworkConditionProfile, NetworkConditionStamp, NetworkConditionsState, NetworkConditionsChange, NetworkConnection } from "./network/conditions/store";
|
|
51
|
+
export { chooseConditionsSnapshot } from "./network/conditions/remoteState";
|
|
51
52
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -53,6 +53,7 @@ export { filterNetworkEvents, applyIgnoredPatterns, } from "./network/utils/filt
|
|
|
53
53
|
export { splitPinned, type PinnedSplit } from "./network/utils/withPinnedFirst";
|
|
54
54
|
export { extractOperationName } from "./network/utils/extractOperationName";
|
|
55
55
|
export { generateCurl } from "./network/utils/generateCurl";
|
|
56
|
-
export { NETWORK_CONDITIONS, getNetworkCondition, setNetworkCondition, subscribeNetworkConditions } from "./network/conditions/store";
|
|
57
|
-
export type { NetworkConditionProfile, NetworkConditionStamp } from "./network/conditions/store";
|
|
56
|
+
export { NETWORK_CONDITIONS, getNetworkCondition, setNetworkCondition, subscribeNetworkConditions, getNetworkConditions, setNetworkConditions, getNetworkConnection, getConditionsRevision, networkConditionsActive } from "./network/conditions/store";
|
|
57
|
+
export type { NetworkConditionProfile, NetworkConditionStamp, NetworkConditionsState, NetworkConditionsChange, NetworkConnection } from "./network/conditions/store";
|
|
58
|
+
export { chooseConditionsSnapshot } from "./network/conditions/remoteState";
|
|
58
59
|
//# sourceMappingURL=index.web.d.ts.map
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import { type NetworkConditionProfile } from "./store";
|
|
1
|
+
import { type NetworkConditionProfile, type NetworkConditionsState, type NetworkConnection } from "./store";
|
|
2
2
|
export interface RemoteNetworkConditions {
|
|
3
3
|
/** Identity of the connected device session, used to ignore stale UI completions. */
|
|
4
4
|
targetId?: string;
|
|
5
5
|
profile: NetworkConditionProfile | null;
|
|
6
|
+
state?: NetworkConditionsState;
|
|
7
|
+
onConnectionChange?(connection: NetworkConnection): Promise<unknown>;
|
|
6
8
|
available: boolean;
|
|
7
9
|
onChange(profile: NetworkConditionProfile): Promise<unknown>;
|
|
8
10
|
}
|
|
9
|
-
export declare function NetworkConditionsControl({ remote }: {
|
|
11
|
+
export declare function NetworkConditionsControl({ remote, compact }: {
|
|
10
12
|
remote?: RemoteNetworkConditions;
|
|
13
|
+
compact?: boolean;
|
|
11
14
|
}): import("react").JSX.Element;
|
|
12
15
|
//# sourceMappingURL=NetworkConditionsControl.d.ts.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type FloatingToolRenderContext } from "@buoy-gg/shared-ui";
|
|
2
|
-
import type
|
|
2
|
+
import { type RemoteNetworkConditions } from "./NetworkConditionsControl";
|
|
3
3
|
/** A live source keeps the desktop strip current after its launching panel closes. */
|
|
4
4
|
export declare function createRemoteConditionsSource(): {
|
|
5
5
|
getSnapshot: () => RemoteNetworkConditions | undefined;
|
|
@@ -8,9 +8,10 @@ export declare function createRemoteConditionsSource(): {
|
|
|
8
8
|
};
|
|
9
9
|
type RemoteSource = ReturnType<typeof createRemoteConditionsSource>;
|
|
10
10
|
export declare function registerLocalNetworkFloatingTool(): () => void;
|
|
11
|
-
export declare function openNetworkFloatingTool(source?: RemoteSource): void;
|
|
12
|
-
export declare function NetworkFloatingTool({ id, revealToken, dismiss, source }: FloatingToolRenderContext & {
|
|
11
|
+
export declare function openNetworkFloatingTool(source?: RemoteSource, showControls?: boolean): void;
|
|
12
|
+
export declare function NetworkFloatingTool({ id, revealToken, dismiss, source, showControls }: FloatingToolRenderContext & {
|
|
13
13
|
source?: RemoteSource;
|
|
14
|
+
showControls?: boolean;
|
|
14
15
|
}): import("react").JSX.Element;
|
|
15
16
|
export {};
|
|
16
17
|
//# sourceMappingURL=NetworkFloatingTool.d.ts.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { NetworkConnection } from "../profiles";
|
|
2
|
+
export interface ConnectionState {
|
|
3
|
+
type?: string;
|
|
4
|
+
details?: unknown;
|
|
5
|
+
isConnected?: boolean | null;
|
|
6
|
+
isInternetReachable?: boolean | null;
|
|
7
|
+
}
|
|
8
|
+
export interface ConnectivityModule {
|
|
9
|
+
getCurrentState(requestedInterface?: string): Promise<ConnectionState>;
|
|
10
|
+
eventEmitter: {
|
|
11
|
+
addListener(event: string, listener: (state: ConnectionState) => void): {
|
|
12
|
+
remove(): void;
|
|
13
|
+
};
|
|
14
|
+
listenerCount?(event: string): number;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export declare function maskConnection(state: ConnectionState, mode: NetworkConnection, expo?: boolean): ConnectionState;
|
|
18
|
+
/** Install before the library creates any state managers or app listeners. */
|
|
19
|
+
export declare function patchConnectionState(native: ConnectivityModule, mode: () => NetworkConnection, subscribe: (listener: () => void) => () => void, options?: {
|
|
20
|
+
eventName?: string;
|
|
21
|
+
expo?: boolean;
|
|
22
|
+
receiver?: object;
|
|
23
|
+
}): () => void;
|
|
24
|
+
//# sourceMappingURL=patchNetwork.d.ts.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { UploadCap } from "./profiles";
|
|
2
|
+
export declare const chunkSize: (rate: number) => number;
|
|
3
|
+
export declare const utf8Length: (text: string) => number;
|
|
4
|
+
/** Returns null when the native encoder owns a body whose byte size is unknown. */
|
|
5
|
+
export declare function bodyByteLength(body: unknown): number | null;
|
|
6
|
+
/** The upload is a pre-send simulation. No bytes are sent during these ticks. */
|
|
7
|
+
export declare function paceByteCount(bytes: number, rate: number, signal?: AbortSignal | null, progress?: (loaded: number, total: number) => void): Promise<void>;
|
|
8
|
+
export declare function uploadBodySize(input: RequestInfo | URL, init?: RequestInit): UploadCap;
|
|
9
|
+
/** Inspect sizes only. Never read a stream, open a URI, or alter the body. */
|
|
10
|
+
export declare function uploadSize(body: unknown): UploadCap;
|
|
11
|
+
/** Carry timer overshoot forward, but never bank idle time between reads. */
|
|
12
|
+
export declare function createBytePacer(rate: number): (bytes: number, signal?: AbortSignal | null) => Promise<void>;
|
|
13
|
+
export declare function pacedStream(source: ReadableStream<Uint8Array>, rate: number, signal?: AbortSignal | null, observe?: (chunk: Uint8Array | null, error?: unknown) => void): ReadableStream<Uint8Array<ArrayBufferLike>>;
|
|
14
|
+
/** Wrap body delivery without assuming RN's Response constructor accepts streams. */
|
|
15
|
+
export declare function paceResponse(response: Response, rate: number, signal?: AbortSignal | null, observe?: (chunk: Uint8Array | null, error?: unknown) => void, noBody?: boolean): Response;
|
|
16
|
+
//# sourceMappingURL=pacer.d.ts.map
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export declare const NETWORK_CONDITIONS: {
|
|
2
|
+
readonly normal: {
|
|
3
|
+
readonly label: "Normal";
|
|
4
|
+
readonly delayMs: 0;
|
|
5
|
+
};
|
|
6
|
+
readonly offline: {
|
|
7
|
+
readonly label: "Offline (requests)";
|
|
8
|
+
readonly delayMs: 0;
|
|
9
|
+
};
|
|
10
|
+
readonly slow: {
|
|
11
|
+
readonly label: "Slow (+500 ms)";
|
|
12
|
+
readonly delayMs: 500;
|
|
13
|
+
};
|
|
14
|
+
readonly verySlow: {
|
|
15
|
+
readonly label: "Very slow (+2000 ms)";
|
|
16
|
+
readonly delayMs: 2000;
|
|
17
|
+
};
|
|
18
|
+
readonly slow3g: {
|
|
19
|
+
readonly label: "Slow 3G";
|
|
20
|
+
readonly delayMs: 2000;
|
|
21
|
+
readonly downloadBytesPerSecond: 50000;
|
|
22
|
+
readonly uploadBytesPerSecond: 50000;
|
|
23
|
+
};
|
|
24
|
+
readonly slow4g: {
|
|
25
|
+
readonly label: "Slow 4G";
|
|
26
|
+
readonly delayMs: 562.5;
|
|
27
|
+
readonly downloadBytesPerSecond: 180000;
|
|
28
|
+
readonly uploadBytesPerSecond: 84375;
|
|
29
|
+
};
|
|
30
|
+
readonly fast4g: {
|
|
31
|
+
readonly label: "Fast 4G";
|
|
32
|
+
readonly delayMs: 165;
|
|
33
|
+
readonly downloadBytesPerSecond: 1012500;
|
|
34
|
+
readonly uploadBytesPerSecond: 168750;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
export type NetworkConditionProfile = keyof typeof NETWORK_CONDITIONS;
|
|
38
|
+
export type NetworkConnection = "auto" | "real" | "offline" | "wifi" | "cellular" | "noInternet";
|
|
39
|
+
export declare const CONNECTIONS: NetworkConnection[];
|
|
40
|
+
export interface NetworkConditionStamp {
|
|
41
|
+
readonly profile: NetworkConditionProfile;
|
|
42
|
+
readonly delayMs: number;
|
|
43
|
+
readonly downloadBytesPerSecond?: number;
|
|
44
|
+
readonly uploadBytesPerSecond?: number;
|
|
45
|
+
readonly uploadCap?: UploadCap;
|
|
46
|
+
}
|
|
47
|
+
export interface UploadCap {
|
|
48
|
+
readonly knownBytes: number;
|
|
49
|
+
readonly status: "applied" | "partial" | "not-applied";
|
|
50
|
+
readonly note?: string;
|
|
51
|
+
}
|
|
52
|
+
export declare const CONDITIONS_SCOPE: {
|
|
53
|
+
download: string;
|
|
54
|
+
upload: string;
|
|
55
|
+
transports: string;
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=profiles.d.ts.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { NetworkConditionsState } from "./store";
|
|
2
|
+
/** A new runtime needs a fresh read; old snapshots cannot rearm its controls. */
|
|
3
|
+
export declare function chooseConditionsSnapshot(confirmed: NetworkConditionsState | null, snapshot?: NetworkConditionsState): NetworkConditionsState | null;
|
|
4
|
+
//# sourceMappingURL=remoteState.d.ts.map
|