@qontinui/ui-bridge-native 0.6.13 → 0.6.14

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.
@@ -9,6 +9,7 @@ import { NativeUIBridgeRegistry } from '../core/registry';
9
9
  import type { NativeActionExecutor } from '../control/types';
10
10
  import { type ServerAdapter } from '../server/http-server';
11
11
  import type { RouteProvider, KeepAwakeProvider } from '../server/types';
12
+ import { type ZeroconfConstructor } from '../transport/DeviceAnnouncer';
12
13
  import { type CloudRelayConfig } from '../transport/CloudRelayClient';
13
14
  import { ModalDetector } from '../modal/modal-detector';
14
15
  import { ToastCapture } from '../toast/toast-capture';
@@ -109,9 +110,24 @@ export interface UIBridgeNativeProviderProps {
109
110
  cloudRelayConfig?: Omit<CloudRelayConfig, 'uiBridgeServer'>;
110
111
  /**
111
112
  * Enable mDNS advertisement so that runners on the same LAN can discover this
112
- * device automatically (requires react-native-zeroconf).
113
+ * device automatically. Advertises `_uibridge._tcp` only when `zeroconf` is
114
+ * also passed; without it the announcer logs that advertisement was skipped.
113
115
  */
114
116
  enableMdnsAnnounce?: boolean;
117
+ /**
118
+ * The `Zeroconf` constructor from `react-native-zeroconf`
119
+ * (`import Zeroconf from 'react-native-zeroconf'` → `zeroconf={Zeroconf}`),
120
+ * forwarded to `DeviceAnnouncer.startMdnsAdvertise`. The SDK never
121
+ * `require()`s that package itself — Metro raises an uncatchable module-load
122
+ * error when it is absent — so the host app, which knows it is installed,
123
+ * hands the constructor in. Omitted, mDNS advertisement is skipped.
124
+ *
125
+ * Must be a STABLE reference — the module-level import, never an inline
126
+ * wrapper — because it is a dependency of the transport effect: a new
127
+ * identity per render tears down and re-publishes the advertisement (and the
128
+ * cloud relay) on every render.
129
+ */
130
+ zeroconf?: ZeroconfConstructor;
115
131
  /**
116
132
  * Stable device identifier used for mDNS TXT records and cloud relay
117
133
  * registration. Typically sourced from expo-device or a UUID stored in
@@ -119,7 +135,7 @@ export interface UIBridgeNativeProviderProps {
119
135
  */
120
136
  deviceId?: string;
121
137
  }
122
- export declare function UIBridgeNativeProvider({ children, features: featuresProp, config: configProp, onEvent, serverAdapter, navigationProvider, screenshotProvider, keepAwakeProvider, routeProvider, cloudRelayConfig, enableMdnsAnnounce, deviceId, }: UIBridgeNativeProviderProps): import("react/jsx-runtime").JSX.Element;
138
+ export declare function UIBridgeNativeProvider({ children, features: featuresProp, config: configProp, onEvent, serverAdapter, navigationProvider, screenshotProvider, keepAwakeProvider, routeProvider, cloudRelayConfig, enableMdnsAnnounce, zeroconf, deviceId, }: UIBridgeNativeProviderProps): import("react/jsx-runtime").JSX.Element;
123
139
  /**
124
140
  * useUIBridgeNative hook
125
141
  *
@@ -1 +1 @@
1
- {"version":3,"file":"UIBridgeNativeProvider.d.ts","sourceRoot":"","sources":["../../src/react/UIBridgeNativeProvider.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"UIBridgeNativeProvider.d.ts","sourceRoot":"","sources":["../../src/react/UIBridgeNativeProvider.tsx"],"names":[],"mappings":"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"}
@@ -4313,7 +4313,7 @@ function createServerHandlers(registry, executor, config) {
4313
4313
  };
4314
4314
  if (config?.appInfo) {
4315
4315
  response.uiBridge = {
4316
- version: "0.6.13",
4316
+ version: "0.6.14",
4317
4317
  ...config.appInfo,
4318
4318
  capabilities: ["elements", "components", "actions", "design"],
4319
4319
  elementCount: stats.elements,
@@ -6236,7 +6236,26 @@ function describeErrorEvent(event) {
6236
6236
  }
6237
6237
 
6238
6238
  // src/transport/DeviceAnnouncer.ts
6239
+ function registeredServiceName(result, requested) {
6240
+ if (result !== null && typeof result === "object") {
6241
+ const name = result.name;
6242
+ if (typeof name === "string" && name.length > 0) return name;
6243
+ }
6244
+ return requested;
6245
+ }
6239
6246
  var DEFAULT_PORT = 8087;
6247
+ async function releaseZeroconf(zeroconf, name) {
6248
+ if (name !== null) {
6249
+ try {
6250
+ await zeroconf.unpublishService(name);
6251
+ } catch {
6252
+ }
6253
+ }
6254
+ try {
6255
+ zeroconf.removeDeviceListeners?.();
6256
+ } catch {
6257
+ }
6258
+ }
6240
6259
  var RECONNECT_INITIAL_DELAY_MS = 2e3;
6241
6260
  var RECONNECT_MAX_DELAY_MS = 6e4;
6242
6261
  var DeviceAnnouncer = class {
@@ -6249,8 +6268,16 @@ var DeviceAnnouncer = class {
6249
6268
  this.reconnectTimer = null;
6250
6269
  this.reconnectDelay = RECONNECT_INITIAL_DELAY_MS;
6251
6270
  this.stopped = false;
6252
- /** Zeroconf instance, set when mDNS is successfully started */
6271
+ /** Zeroconf instance, set when mDNS is started (cleared by `stop()`) */
6253
6272
  this.zeroconf = null;
6273
+ /** The name the library registered — the only name this announcer may unpublish */
6274
+ this.publishedName = null;
6275
+ /**
6276
+ * True while a publish is awaiting the library. A `stop()` that lands in that
6277
+ * window leaves the cleanup to the publish path, which is the only side that
6278
+ * will learn the registered name.
6279
+ */
6280
+ this.publishInFlight = false;
6254
6281
  this.config = config;
6255
6282
  this.pairingToken = generateHex(16);
6256
6283
  }
@@ -6275,19 +6302,38 @@ var DeviceAnnouncer = class {
6275
6302
  );
6276
6303
  return;
6277
6304
  }
6305
+ if (this.stopped) return;
6306
+ let zeroconf = null;
6278
6307
  try {
6279
- this.zeroconf = new ZeroconfCtor();
6308
+ zeroconf = new ZeroconfCtor();
6309
+ this.zeroconf = zeroconf;
6280
6310
  const port = this.config.port ?? DEFAULT_PORT;
6281
6311
  const serviceName = `UIBridge-${this.config.deviceId.slice(0, 8)}`;
6282
- this.zeroconf.publishService("_uibridge", "_tcp.", "local.", serviceName, port, {
6283
- device_id: this.config.deviceId,
6284
- app_id: this.config.appId,
6285
- version: this.config.version ?? "unknown",
6286
- pairing_token: this.pairingToken
6287
- });
6312
+ this.publishInFlight = true;
6313
+ let result;
6314
+ try {
6315
+ result = await zeroconf.publishService("_uibridge", "_tcp.", "local.", serviceName, port, {
6316
+ device_id: this.config.deviceId,
6317
+ app_id: this.config.appId,
6318
+ version: this.config.version ?? "unknown",
6319
+ pairing_token: this.pairingToken
6320
+ });
6321
+ } finally {
6322
+ this.publishInFlight = false;
6323
+ }
6324
+ const registered = registeredServiceName(result, serviceName);
6325
+ if (this.stopped) {
6326
+ await releaseZeroconf(zeroconf, registered);
6327
+ return;
6328
+ }
6329
+ this.publishedName = registered;
6288
6330
  this.state = { ...this.state, mdnsActive: true };
6289
- transportLogger.log(`[DeviceAnnouncer] mDNS: advertising "${serviceName}" on port ${port}`);
6331
+ transportLogger.log(`[DeviceAnnouncer] mDNS: advertising "${registered}" on port ${port}`);
6290
6332
  } catch (err) {
6333
+ if (this.stopped) {
6334
+ if (zeroconf) await releaseZeroconf(zeroconf, null);
6335
+ return;
6336
+ }
6291
6337
  transportLogger.warn("[DeviceAnnouncer] mDNS start failed:", err);
6292
6338
  }
6293
6339
  }
@@ -6360,15 +6406,15 @@ var DeviceAnnouncer = class {
6360
6406
  clearTimeout(this.reconnectTimer);
6361
6407
  this.reconnectTimer = null;
6362
6408
  }
6363
- if (this.zeroconf) {
6364
- try {
6365
- const serviceName = `UIBridge-${this.config.deviceId.slice(0, 8)}`;
6366
- this.zeroconf.unpublishService(serviceName);
6367
- } catch {
6368
- }
6369
- this.zeroconf = null;
6370
- }
6409
+ const zeroconf = this.zeroconf;
6410
+ const publishedName = this.publishedName;
6411
+ const inFlight = this.publishInFlight;
6412
+ this.zeroconf = null;
6413
+ this.publishedName = null;
6371
6414
  this.state = { ...this.state, mdnsActive: false };
6415
+ if (zeroconf && !inFlight) {
6416
+ await releaseZeroconf(zeroconf, publishedName);
6417
+ }
6372
6418
  if (this.cloudWs) {
6373
6419
  this.cloudWs.onclose = null;
6374
6420
  this.cloudWs.close();
@@ -6784,6 +6830,7 @@ function UIBridgeNativeProvider({
6784
6830
  routeProvider,
6785
6831
  cloudRelayConfig,
6786
6832
  enableMdnsAnnounce,
6833
+ zeroconf,
6787
6834
  deviceId
6788
6835
  }) {
6789
6836
  const features = useValueStable(featuresProp);
@@ -6957,7 +7004,7 @@ function UIBridgeNativeProvider({
6957
7004
  cloudToken: cloudRelayConfig?.authToken
6958
7005
  });
6959
7006
  announcerRef.current = announcer;
6960
- void announcer.startMdnsAdvertise().catch((err) => {
7007
+ void announcer.startMdnsAdvertise(zeroconf).catch((err) => {
6961
7008
  console.warn("[ui-bridge-native] mDNS advertise failed:", err);
6962
7009
  });
6963
7010
  } catch (err) {
@@ -6998,6 +7045,7 @@ function UIBridgeNativeProvider({
6998
7045
  cloudRelayConfig?.relayUrl,
6999
7046
  cloudRelayConfig?.authToken,
7000
7047
  enableMdnsAnnounce,
7048
+ zeroconf,
7001
7049
  deviceId
7002
7050
  ]);
7003
7051
  react.useEffect(() => {