@buoy-gg/external-sync 7.0.39 → 7.0.41

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.
@@ -48,11 +48,15 @@ function socketURLForHost(host) {
48
48
  */
49
49
  function getMetroHost() {
50
50
  try {
51
- // Requires stay lexically inside try{} so Metro treats them as optional;
52
- // react-native-web has neither path and falls through to null.
53
- const NativeSourceCode =
51
+ // The public route to the SourceCode TurboModule that
52
+ // react-native/Libraries/NativeModules/specs/NativeSourceCode wraps. Deep
53
+ // imports warn on RN 0.80+; react-native-web has no registry and falls
54
+ // through to null.
54
55
  // eslint-disable-next-line @typescript-eslint/no-var-requires
55
- require("react-native/Libraries/NativeModules/specs/NativeSourceCode").default;
56
+ const {
57
+ TurboModuleRegistry
58
+ } = require("react-native");
59
+ const NativeSourceCode = TurboModuleRegistry?.get?.("SourceCode");
56
60
  const host = hostFromScriptURL(NativeSourceCode?.getConstants?.().scriptURL);
57
61
  if (host) return host;
58
62
  } catch {
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.DEFAULT_BROKER_PORT = void 0;
7
+ exports.getDefaultSocketURL = getDefaultSocketURL;
8
+ exports.getMetroHost = getMetroHost;
9
+ exports.hostFromScriptURL = hostFromScriptURL;
10
+ exports.socketURLForHost = socketURLForHost;
11
+ const DEFAULT_BROKER_PORT = exports.DEFAULT_BROKER_PORT = 42831;
12
+ function hostFromScriptURL(url) {
13
+ try {
14
+ return url && /^https?:/.test(url) ? new URL(url).hostname : null;
15
+ } catch {
16
+ return null;
17
+ }
18
+ }
19
+ function socketURLForHost(host) {
20
+ return `http://${host ?? "localhost"}:${DEFAULT_BROKER_PORT}`;
21
+ }
22
+ function getMetroHost() {
23
+ return null;
24
+ }
25
+ function getDefaultSocketURL() {
26
+ return socketURLForHost(typeof location === "undefined" ? null : location.hostname);
27
+ }
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getPlatformSpecificURL = getPlatformSpecificURL;
7
+ function getPlatformSpecificURL(baseUrl, _platform) {
8
+ return baseUrl;
9
+ }
@@ -40,11 +40,15 @@ export function socketURLForHost(host) {
40
40
  */
41
41
  export function getMetroHost() {
42
42
  try {
43
- // Requires stay lexically inside try{} so Metro treats them as optional;
44
- // react-native-web has neither path and falls through to null.
45
- const NativeSourceCode =
43
+ // The public route to the SourceCode TurboModule that
44
+ // react-native/Libraries/NativeModules/specs/NativeSourceCode wraps. Deep
45
+ // imports warn on RN 0.80+; react-native-web has no registry and falls
46
+ // through to null.
46
47
  // eslint-disable-next-line @typescript-eslint/no-var-requires
47
- require("react-native/Libraries/NativeModules/specs/NativeSourceCode").default;
48
+ const {
49
+ TurboModuleRegistry
50
+ } = require("react-native");
51
+ const NativeSourceCode = TurboModuleRegistry?.get?.("SourceCode");
48
52
  const host = hostFromScriptURL(NativeSourceCode?.getConstants?.().scriptURL);
49
53
  if (host) return host;
50
54
  } catch {
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+
3
+ export const DEFAULT_BROKER_PORT = 42831;
4
+ export function hostFromScriptURL(url) {
5
+ try {
6
+ return url && /^https?:/.test(url) ? new URL(url).hostname : null;
7
+ } catch {
8
+ return null;
9
+ }
10
+ }
11
+ export function socketURLForHost(host) {
12
+ return `http://${host ?? "localhost"}:${DEFAULT_BROKER_PORT}`;
13
+ }
14
+ export function getMetroHost() {
15
+ return null;
16
+ }
17
+ export function getDefaultSocketURL() {
18
+ return socketURLForHost(typeof location === "undefined" ? null : location.hostname);
19
+ }
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ export function getPlatformSpecificURL(baseUrl, _platform) {
4
+ return baseUrl;
5
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"getDefaultSocketURL.d.ts","sourceRoot":"","sources":["../../../src/utils/getDefaultSocketURL.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,6CAA6C;AAC7C,eAAO,MAAM,mBAAmB,QAAQ,CAAC;AAIzC;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACnC,MAAM,GAAG,IAAI,CAEf;AAED,2EAA2E;AAC3E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAE5D;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,IAAI,MAAM,GAAG,IAAI,CAyB5C;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C"}
1
+ {"version":3,"file":"getDefaultSocketURL.d.ts","sourceRoot":"","sources":["../../../src/utils/getDefaultSocketURL.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,6CAA6C;AAC7C,eAAO,MAAM,mBAAmB,QAAQ,CAAC;AAIzC;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACnC,MAAM,GAAG,IAAI,CAEf;AAED,2EAA2E;AAC3E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAE5D;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,IAAI,MAAM,GAAG,IAAI,CA2B5C;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C"}
@@ -0,0 +1,6 @@
1
+ export declare const DEFAULT_BROKER_PORT = 42831;
2
+ export declare function hostFromScriptURL(url: string | null | undefined): string | null;
3
+ export declare function socketURLForHost(host: string | null): string;
4
+ export declare function getMetroHost(): null;
5
+ export declare function getDefaultSocketURL(): string;
6
+ //# sourceMappingURL=getDefaultSocketURL.web.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getDefaultSocketURL.web.d.ts","sourceRoot":"","sources":["../../../src/utils/getDefaultSocketURL.web.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,QAAQ,CAAC;AAEzC,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAG/E;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAE5D;AAED,wBAAgB,YAAY,IAAI,IAAI,CAAiB;AAErD,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C"}
@@ -0,0 +1,3 @@
1
+ import type { PlatformOS } from '../types';
2
+ export declare function getPlatformSpecificURL(baseUrl: string, _platform: PlatformOS): string;
3
+ //# sourceMappingURL=platformUtils.web.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platformUtils.web.d.ts","sourceRoot":"","sources":["../../../src/utils/platformUtils.web.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,GAAG,MAAM,CAAoB"}
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ var S=process.env.NODE_ENV!=="production";typeof window<"u"&&typeof globalThis.global>"u"&&(globalThis.global=globalThis);import{useAccountAccess as me}from"@buoy-gg/license/web";import{useEffect as ve,useRef as ae}from"react";import{LicenseManager as I}from"@buoy-gg/license/web";function l(t,c,n="log"){if(!(!c&&n==="log"))switch(n){case"warn":console.warn(t);break;case"error":console.error(t);break;default:console.log(t)}}var q="__buoyFlushToolSync";function K(){let t=globalThis;return t[q]||(t[q]=new Set),t[q]}function V(t){K().add(t)}function W(t){K().delete(t)}function he(t){try{for(let c of K())try{c(t)}catch{}}catch{}}function j(t,c){let n=0,i=[t],h=new Set;for(;i.length>0;){if(n>c)return{over:!0,approxBytes:n};let o=i.pop();if(o==null)n+=4;else if(typeof o=="string")n+=o.length+2;else if(typeof o=="number")n+=8;else if(typeof o=="boolean")n+=5;else if(typeof o=="object"){if(h.has(o))continue;if(h.add(o),Array.isArray(o)){n+=2+o.length;for(let s=0;s<o.length;s++)i.push(o[s])}else{n+=2;for(let s in o)n+=s.length+4,i.push(o[s])}}else n+=4}return{over:n>c,approxBytes:n}}var re=1;var P="[ExternalSync]";function ie({socket:t,deviceId:c,getTools:n,watched:i,throttleMs:h=200,enableLogs:o=!1}){let s=!1,a=!1,p=0,g=()=>!s&&a&&t.connected&&I.hasAccountAccess(),m=new Map,k={},v={},w=e=>e==="All"||e===c,u=(e,r)=>{if(g())try{t.emit(e,r)}catch(y){l(`${P} Failed to emit "${e}": ${y}. Payload must be JSON-serializable.`,o,"error")}},M=new Set,x=e=>{if(!g())return;let r=n()[e];if(!r)return;k[e]=Date.now();let y;try{y=r.getSnapshot()}catch{return}let{over:T,approxBytes:$}=j(y,2097152);if(T){M.has(e)||(M.add(e),console.warn(`${P} "${e}" snapshot \u2248${($/1e6).toFixed(1)}MB exceeds the ${2097152/1e6}MB sync budget \u2014 dropped (dashboard will be stale for this tool). The adapter should ship a wire-form snapshot (summaries + on-demand detail).`));return}let Y={toolId:e,persistentDeviceId:c,timestamp:k[e],version:r.version,kind:"snapshot",payload:y};u("devtool-sync",Y)},A=e=>{if(v[e])return;let r=Date.now()-(k[e]??0);if(r>=h){x(e);return}v[e]=setTimeout(()=>{delete v[e],x(e)},h-r)},O=e=>{t.connected&&m.has(e)&&(v[e]&&(clearTimeout(v[e]),delete v[e]),x(e))};V(O);let D=new Map,C=(e,r)=>{if(!g())return;let y=n()[e];if(y){if(m.has(e)){if(D.get(e)===r)return;let T=m.get(e);m.set(e,y.subscribe(r==="stream"?()=>A(e):()=>{})),D.set(e,r),T?.(),l(`${P} "${e}" watch mode \u2192 ${r}`,o);return}m.set(e,y.subscribe(r==="stream"?()=>A(e):()=>{})),D.set(e,r),l(`${P} Watching "${e}" (${r})`,o)}},E=e=>{m.get(e)?.(),m.delete(e),D.delete(e),v[e]&&(clearTimeout(v[e]),delete v[e]),l(`${P} Stopped watching "${e}"`,o)},N=()=>{let e={persistentDeviceId:c,protocolVersion:1,tools:Object.entries(n()).map(([r,y])=>({toolId:r,version:y.version,actions:Object.keys(y.actions??{})}))};u("devtool-capabilities",e)},f=e=>{if(!(!g()||!w(e.targetDeviceId)))if(e.watching){let r=e.consolidated===!0&&e.stream===!1?"capture":"stream";i.set(e.toolId,r),C(e.toolId,r),r==="stream"&&x(e.toolId)}else i.delete(e.toolId),E(e.toolId)},d=e=>{!g()||!w(e.targetDeviceId)||x(e.toolId)},Q=async e=>{if(!g()||!w(e.targetDeviceId))return;let r=p,{requestId:y,toolId:T,action:$,params:Y}=e,b={requestId:y,toolId:T,action:$,persistentDeviceId:c,timestamp:Date.now(),ok:!1},ne=n()[T],oe=ne?.actions?.[$];if(!oe){b.error=ne?`Unknown action "${$}" on tool "${T}"`:`Unknown tool "${T}"`,u("devtool-action-result",b);return}try{b.result=await oe(Y),b.ok=!0}catch(U){b.error=U instanceof Error?U.message:String(U)}if(!(r!==p||!g())){if(b.ok){let{over:U,approxBytes:Se}=j(b.result,8388608);U&&(b.ok=!1,b.result=void 0,b.error=`Result \u2248${(Se/1e6).toFixed(1)}MB exceeds the ${8388608/1e6}MB sync budget. Narrow the request (e.g. includeValues:false, a limit, or a more specific action).`)}b.timestamp=Date.now(),u("devtool-action-result",b)}},B=()=>{p+=1;for(let r of[...m.keys()])E(r);i.clear();for(let r of Object.values(v))clearTimeout(r);let e=t;e.sendBuffer&&(e.sendBuffer=e.sendBuffer.filter(r=>!["devtool-sync","devtool-capabilities","devtool-action-result","device-license"].includes(String(r.data?.[0]))))},Z=()=>{let e=I.getState();t.emit("device-license",{tier:e.tier,isPro:e.isPro?"1":"0"}),N()},ee=e=>{a=e?.protocol===1&&e.ready===!0,g()?Z():B()},ye=I.subscribe(()=>{I.hasAccountAccess()?g()&&Z():(t.connected&&t.emit("device-license",{tier:"locked",isPro:"0"}),B())}),L=()=>{a=!1,t.emit("buoy:access:request")},te=()=>{a=!1,B()};t.on("buoy:access",ee);for(let[e,r]of i)n()[e]&&C(e,r);return t.on("connect",L),t.on("disconnect",te),t.on("devtool-watch",f),t.on("request-devtool-state",d),t.on("devtool-action",Q),t.connected&&L(),()=>{s=!0,ye(),t.off("buoy:access",ee),B(),W(O),t.off("connect",L),t.off("disconnect",te),t.off("devtool-watch",f),t.off("request-devtool-state",d),t.off("devtool-action",Q);for(let e of[...m.keys()])E(e)}}function be({tools:t,socket:c,deviceId:n,enabled:i=!0,throttleMs:h=200,enableLogs:o=!1}){let a=me().status==="admitted",p=ae(t);p.current=t;let g=ae(new Map),m=Object.keys(t).sort().join(",");ve(()=>{if(!c||!n||!i||!a){g.current.clear();return}return ie({socket:c,deviceId:n,getTools:()=>p.current,watched:g.current,throttleMs:h,enableLogs:o})},[c,n,i,a,h,o,m])}function le(t,c){let n=()=>c(!1),i=()=>{n(),t.emit("buoy:access:request")},h=o=>{let s=o;c(s?.protocol===1&&s?.ready===!0)};return t.on("connect",i),t.on("disconnect",n),t.on("buoy:access",h),n(),t.connected&&i(),()=>{t.off("connect",i),t.off("disconnect",n),t.off("buoy:access",h)}}import{useEffect as G,useRef as fe,useState as J}from"react";import{io as De}from"socket.io-client";function ue(t,c){return t}var xe=42831;function Te(t){return`http://${t??"localhost"}:42831`}function ke(){return null}function H(){return Te(typeof location>"u"?null:location.hostname)}var z={targetURL:null,state:"idle",lastError:null,since:0},X=new Set;function R(t){z={...z,...t,since:Date.now()},X.forEach(c=>c())}function we(){return z}function Re(t){return X.add(t),()=>{X.delete(t)}}var Ee=typeof S<"u"?S:!1,_=null,F="",de="",pe="",ge=()=>`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`;function _e(){let t=globalThis;return t.__buoyInstanceId||(t.__buoyInstanceId=ge()),t.__buoyInstanceId}function Me(t){let c=n=>n&&Object.fromEntries(Object.entries(n).filter(([i])=>!["BUOY_LICENSE_KEY","BUOY_KEY","EXPO_PUBLIC_BUOY_KEY","VITE_BUOY_KEY","REACT_APP_BUOY_KEY","licenseKey"].includes(i)));return{deviceName:t.deviceName,deviceId:t.persistentDeviceId,platform:t.platform,extraDeviceInfo:JSON.stringify(c(t.extraDeviceInfo)),envVariables:JSON.stringify(c(t.envVariables)),connectionNonce:ge(),instanceId:_e()}}function Ae({deviceName:t,socketURL:c,persistentDeviceId:n,extraDeviceInfo:i,envVariables:h,platform:o,enableLogs:s=!1}){let a=fe(null),[p,g]=J(null),[m,k]=J(!1),v=c??H(),w=fe(!1),u=`[${t}]`,M=()=>{l(`${u} Socket connected successfully`,s),w.current=!1,k(!0),R({state:"connected",lastError:null})},x=f=>{l(`${u} Socket disconnected. Reason: ${f}`,s),k(!1),R({state:"retrying"})},A=f=>{if(R({state:"retrying",lastError:f.message}),!Ee||w.current)return;w.current=!0;let d=o==="android"&&/localhost|127\.0\.0\.1/.test(F)?"If this device is connected over USB, run: adb reverse tcp:42831 tcp:42831. ":"If it's running on another machine or port, pass socketURL via the externalSync prop. ";l(`[buoy] desktop sync: can't reach ${F} (is Buoy Desktop running?). Retrying in the background. ${d}(${f.message})`,s,"warn")},O=()=>{l(`${u} Socket connection timeout`,s,"error")};G(()=>{if(!n)return;let f=ue(v,o);R({targetURL:f,state:"connecting",lastError:null}),l(`${u} Platform: ${o}, using URL: ${f}`,s);try{_&&(F!==f||de!==n||pe!==o)&&(_.disconnect(),_=null),_?l(`${u} Reusing existing socket instance to ${f}`,s):(l(`${u} Creating new socket instance to ${f}`,s),_=De(f,{autoConnect:!0,query:Me({deviceName:t,persistentDeviceId:n,platform:o,extraDeviceInfo:i,envVariables:h}),reconnection:!0,reconnectionAttempts:1/0,reconnectionDelay:1e3,reconnectionDelayMax:5e3,transports:["websocket"]}),F=f,de=n,pe=o),a.current=_;let d=a.current;return g(d),d.on("connect_error",A),d.on("connect_timeout",O),k(d.connected),d.connected&&l(`${u} Socket already connected on init`,s),d.on("connect",M),d.on("disconnect",x),()=>{l(`${u} Cleaning up socket event listeners`,s),d.off("connect",M),d.off("disconnect",x),d.off("connect_error",A),d.off("connect_timeout",O)}}catch(d){l(`${u} Failed to initialize socket: ${d}`,s,"error")}},[n,v,o]),G(()=>{a.current&&a.current.io.opts.query&&n&&(l(`${u} Updating device name in socket connection`,s),a.current.io.opts.query={...a.current.io.opts.query,deviceName:t,deviceId:n,platform:o})},[t,u,n,o,s]);function D(){a.current&&!a.current.connected&&(l(`${u} Manually connecting to socket server`,s),a.current.connect())}function C(){a.current&&a.current.connected&&(l(`${u} Manually disconnecting from socket server`,s),a.current.disconnect())}let[E,N]=J(null);return G(()=>{if(p)return le(p,f=>{N(f?p:null),R(f?{state:"connected",lastError:null}:{state:"retrying",lastError:"Update Buoy Desktop and sign in to enable desktop sync."})})},[p]),{socket:E===p?p:null,connect:D,disconnect:C,isConnected:m&&E===p&&p!==null}}export{xe as DEFAULT_BROKER_PORT,re as SYNC_PROTOCOL_VERSION,he as flushToolSyncNow,H as getDefaultSocketURL,ke as getMetroHost,we as getSyncStatus,V as registerToolFlusher,R as setSyncStatus,Re as subscribeSyncStatus,W as unregisterToolFlusher,be as useExternalSync,Ae as useExternalSyncSocket};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buoy-gg/external-sync",
3
- "version": "7.0.39",
3
+ "version": "7.0.41",
4
4
  "description": "Generic device-to-desktop sync for Buoy dev tools",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
@@ -10,16 +10,24 @@
10
10
  "exports": {
11
11
  ".": {
12
12
  "react-native": "./lib/module/index.js",
13
+ "browser": {
14
+ "types": "./lib/typescript/index.d.ts",
15
+ "default": "./lib/web/index.mjs"
16
+ },
13
17
  "import": {
14
- "default": "./lib/module/index.js",
15
- "types": "./lib/typescript/index.d.ts"
18
+ "types": "./lib/typescript/index.d.ts",
19
+ "default": "./lib/module/index.js"
16
20
  },
17
21
  "require": {
18
- "default": "./lib/commonjs/index.js",
19
- "types": "./lib/typescript/index.d.ts"
22
+ "types": "./lib/typescript/index.d.ts",
23
+ "default": "./lib/commonjs/index.js"
20
24
  }
21
25
  },
22
- "./package.json": "./package.json"
26
+ "./package.json": "./package.json",
27
+ "./web": {
28
+ "types": "./lib/typescript/index.d.ts",
29
+ "default": "./lib/web/index.mjs"
30
+ }
23
31
  },
24
32
  "files": [
25
33
  "lib"
@@ -27,11 +35,13 @@
27
35
  "sideEffects": false,
28
36
  "dependencies": {
29
37
  "socket.io-client": "^4.8.1",
30
- "@buoy-gg/license": "^7.0.39"
38
+ "@buoy-gg/license": "^7.0.41"
31
39
  },
32
40
  "peerDependencies": {
33
41
  "react": "*",
34
- "react-native": "*"
42
+ "react-native": "*",
43
+ "react-native-web": "^0.21.0",
44
+ "react-dom": ">=18"
35
45
  },
36
46
  "devDependencies": {
37
47
  "@types/react": "^19.1.0",
@@ -74,10 +84,22 @@
74
84
  "access": "public",
75
85
  "tag": "latest"
76
86
  },
87
+ "peerDependenciesMeta": {
88
+ "react-native": {
89
+ "optional": true
90
+ },
91
+ "react-native-web": {
92
+ "optional": true
93
+ },
94
+ "react-dom": {
95
+ "optional": true
96
+ }
97
+ },
77
98
  "scripts": {
78
- "build": "bob build",
99
+ "build": "bob build && pnpm run build:web",
79
100
  "typecheck": "tsc --noEmit",
80
101
  "clean": "rimraf lib",
81
- "test": "pnpm run typecheck"
102
+ "test": "pnpm run typecheck",
103
+ "build:web": "node ../../scripts/build-web.mjs external-sync"
82
104
  }
83
105
  }