@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.
package/dist/index.mjs CHANGED
@@ -4394,7 +4394,7 @@ function createServerHandlers(registry, executor, config) {
4394
4394
  };
4395
4395
  if (config?.appInfo) {
4396
4396
  response.uiBridge = {
4397
- version: "0.6.13",
4397
+ version: "0.6.14",
4398
4398
  ...config.appInfo,
4399
4399
  capabilities: ["elements", "components", "actions", "design"],
4400
4400
  elementCount: stats.elements,
@@ -6317,7 +6317,26 @@ function describeErrorEvent(event) {
6317
6317
  }
6318
6318
 
6319
6319
  // src/transport/DeviceAnnouncer.ts
6320
+ function registeredServiceName(result, requested) {
6321
+ if (result !== null && typeof result === "object") {
6322
+ const name = result.name;
6323
+ if (typeof name === "string" && name.length > 0) return name;
6324
+ }
6325
+ return requested;
6326
+ }
6320
6327
  var DEFAULT_PORT = 8087;
6328
+ async function releaseZeroconf(zeroconf, name) {
6329
+ if (name !== null) {
6330
+ try {
6331
+ await zeroconf.unpublishService(name);
6332
+ } catch {
6333
+ }
6334
+ }
6335
+ try {
6336
+ zeroconf.removeDeviceListeners?.();
6337
+ } catch {
6338
+ }
6339
+ }
6321
6340
  var RECONNECT_INITIAL_DELAY_MS = 2e3;
6322
6341
  var RECONNECT_MAX_DELAY_MS = 6e4;
6323
6342
  var DeviceAnnouncer = class {
@@ -6330,8 +6349,16 @@ var DeviceAnnouncer = class {
6330
6349
  this.reconnectTimer = null;
6331
6350
  this.reconnectDelay = RECONNECT_INITIAL_DELAY_MS;
6332
6351
  this.stopped = false;
6333
- /** Zeroconf instance, set when mDNS is successfully started */
6352
+ /** Zeroconf instance, set when mDNS is started (cleared by `stop()`) */
6334
6353
  this.zeroconf = null;
6354
+ /** The name the library registered — the only name this announcer may unpublish */
6355
+ this.publishedName = null;
6356
+ /**
6357
+ * True while a publish is awaiting the library. A `stop()` that lands in that
6358
+ * window leaves the cleanup to the publish path, which is the only side that
6359
+ * will learn the registered name.
6360
+ */
6361
+ this.publishInFlight = false;
6335
6362
  this.config = config;
6336
6363
  this.pairingToken = generateHex(16);
6337
6364
  }
@@ -6356,19 +6383,38 @@ var DeviceAnnouncer = class {
6356
6383
  );
6357
6384
  return;
6358
6385
  }
6386
+ if (this.stopped) return;
6387
+ let zeroconf = null;
6359
6388
  try {
6360
- this.zeroconf = new ZeroconfCtor();
6389
+ zeroconf = new ZeroconfCtor();
6390
+ this.zeroconf = zeroconf;
6361
6391
  const port = this.config.port ?? DEFAULT_PORT;
6362
6392
  const serviceName = `UIBridge-${this.config.deviceId.slice(0, 8)}`;
6363
- this.zeroconf.publishService("_uibridge", "_tcp.", "local.", serviceName, port, {
6364
- device_id: this.config.deviceId,
6365
- app_id: this.config.appId,
6366
- version: this.config.version ?? "unknown",
6367
- pairing_token: this.pairingToken
6368
- });
6393
+ this.publishInFlight = true;
6394
+ let result;
6395
+ try {
6396
+ result = await zeroconf.publishService("_uibridge", "_tcp.", "local.", serviceName, port, {
6397
+ device_id: this.config.deviceId,
6398
+ app_id: this.config.appId,
6399
+ version: this.config.version ?? "unknown",
6400
+ pairing_token: this.pairingToken
6401
+ });
6402
+ } finally {
6403
+ this.publishInFlight = false;
6404
+ }
6405
+ const registered = registeredServiceName(result, serviceName);
6406
+ if (this.stopped) {
6407
+ await releaseZeroconf(zeroconf, registered);
6408
+ return;
6409
+ }
6410
+ this.publishedName = registered;
6369
6411
  this.state = { ...this.state, mdnsActive: true };
6370
- transportLogger.log(`[DeviceAnnouncer] mDNS: advertising "${serviceName}" on port ${port}`);
6412
+ transportLogger.log(`[DeviceAnnouncer] mDNS: advertising "${registered}" on port ${port}`);
6371
6413
  } catch (err) {
6414
+ if (this.stopped) {
6415
+ if (zeroconf) await releaseZeroconf(zeroconf, null);
6416
+ return;
6417
+ }
6372
6418
  transportLogger.warn("[DeviceAnnouncer] mDNS start failed:", err);
6373
6419
  }
6374
6420
  }
@@ -6441,15 +6487,15 @@ var DeviceAnnouncer = class {
6441
6487
  clearTimeout(this.reconnectTimer);
6442
6488
  this.reconnectTimer = null;
6443
6489
  }
6444
- if (this.zeroconf) {
6445
- try {
6446
- const serviceName = `UIBridge-${this.config.deviceId.slice(0, 8)}`;
6447
- this.zeroconf.unpublishService(serviceName);
6448
- } catch {
6449
- }
6450
- this.zeroconf = null;
6451
- }
6490
+ const zeroconf = this.zeroconf;
6491
+ const publishedName = this.publishedName;
6492
+ const inFlight = this.publishInFlight;
6493
+ this.zeroconf = null;
6494
+ this.publishedName = null;
6452
6495
  this.state = { ...this.state, mdnsActive: false };
6496
+ if (zeroconf && !inFlight) {
6497
+ await releaseZeroconf(zeroconf, publishedName);
6498
+ }
6453
6499
  if (this.cloudWs) {
6454
6500
  this.cloudWs.onclose = null;
6455
6501
  this.cloudWs.close();
@@ -6865,6 +6911,7 @@ function UIBridgeNativeProvider({
6865
6911
  routeProvider,
6866
6912
  cloudRelayConfig,
6867
6913
  enableMdnsAnnounce,
6914
+ zeroconf,
6868
6915
  deviceId
6869
6916
  }) {
6870
6917
  const features = useValueStable(featuresProp);
@@ -7038,7 +7085,7 @@ function UIBridgeNativeProvider({
7038
7085
  cloudToken: cloudRelayConfig?.authToken
7039
7086
  });
7040
7087
  announcerRef.current = announcer;
7041
- void announcer.startMdnsAdvertise().catch((err) => {
7088
+ void announcer.startMdnsAdvertise(zeroconf).catch((err) => {
7042
7089
  console.warn("[ui-bridge-native] mDNS advertise failed:", err);
7043
7090
  });
7044
7091
  } catch (err) {
@@ -7079,6 +7126,7 @@ function UIBridgeNativeProvider({
7079
7126
  cloudRelayConfig?.relayUrl,
7080
7127
  cloudRelayConfig?.authToken,
7081
7128
  enableMdnsAnnounce,
7129
+ zeroconf,
7082
7130
  deviceId
7083
7131
  ]);
7084
7132
  useEffect(() => {