@camera.ui/transport 0.0.27 → 0.0.29

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.
@@ -7,6 +7,7 @@ var NATS_SPEC = {
7
7
  kind: "persistent",
8
8
  phaseGating: true
9
9
  };
10
+ var RESOLVE_RETRY_MIN_MS = 3e3;
10
11
  function newConnId() {
11
12
  const c = globalThis.crypto;
12
13
  if (c?.randomUUID) return c.randomUUID();
@@ -48,6 +49,8 @@ function createNatsTransport(options = {}) {
48
49
  let connId = null;
49
50
  let applyEpoch = 0;
50
51
  let pendingConnectAbort = null;
52
+ let poolRefreshAt = 0;
53
+ let poolRefreshing = false;
51
54
  function buildServers(target) {
52
55
  const url = new URL(target.endpoint.url);
53
56
  const wsProtocol = url.protocol === "https:" ? "wss:" : "ws:";
@@ -70,11 +73,16 @@ function createNatsTransport(options = {}) {
70
73
  async function refreshPool(p) {
71
74
  const target = currentTarget;
72
75
  if (!resolveServers || !target || disposed) return;
76
+ if (poolRefreshing || Date.now() - poolRefreshAt < RESOLVE_RETRY_MIN_MS) return;
77
+ poolRefreshing = true;
73
78
  try {
74
79
  const servers = await serversFor(target);
75
80
  if (proxy === p && !disposed) p.setServers(servers);
76
81
  } catch (err) {
77
82
  logger?.warn(`server refresh failed: ${stringifyError(err)}`);
83
+ } finally {
84
+ poolRefreshing = false;
85
+ poolRefreshAt = Date.now();
78
86
  }
79
87
  }
80
88
  function stopRefresh() {
@@ -86,7 +94,7 @@ function createNatsTransport(options = {}) {
86
94
  function startRefresh(p) {
87
95
  stopRefresh();
88
96
  if (!resolveServers || resolveRefreshMs <= 0) return;
89
- refreshTimer = setInterval(() => void refreshPool(p), resolveRefreshMs);
97
+ refreshTimer = setInterval(() => refreshPool(p), resolveRefreshMs);
90
98
  }
91
99
  async function resign(reason) {
92
100
  const target = currentTarget;
@@ -150,6 +158,9 @@ function createNatsTransport(options = {}) {
150
158
  notifyClient();
151
159
  if (resolveServers) refreshPool(p);
152
160
  break;
161
+ case "reconnecting":
162
+ if (resolveServers) refreshPool(p);
163
+ break;
153
164
  case "staleConnection":
154
165
  markDown("staleConnection");
155
166
  notifyClient();
@@ -2,6 +2,7 @@ import { n as isEndpointChange, r as isSameTarget, t as TransportEmitter } from
2
2
  import { t as classifyClose } from "../closeCodes-ClWJVOpq.js";
3
3
  import { Manager, io } from "socket.io-client";
4
4
  //#region src/transports/socketio.ts
5
+ var RESOLVE_RETRY_MIN_MS = 3e3;
5
6
  var SOCKETIO_SPEC = {
6
7
  id: "socketio",
7
8
  kind: "persistent",
@@ -27,8 +28,11 @@ function createSocketioTransport(options = {}) {
27
28
  let currentTarget = null;
28
29
  let currentQuery = {};
29
30
  let refreshTimer = null;
31
+ let queryRefreshAt = 0;
32
+ let queryRefreshing = false;
30
33
  let status = { up: false };
31
34
  let disposed = false;
35
+ let applyEpoch = 0;
32
36
  const staleAfterMs = options.staleAfterMs ?? 6e4;
33
37
  let lastActivityAt = 0;
34
38
  function touchActivity() {
@@ -59,6 +63,8 @@ function createSocketioTransport(options = {}) {
59
63
  async function refreshQuery() {
60
64
  const target = currentTarget;
61
65
  if (!resolveQuery || !target || disposed) return;
66
+ if (queryRefreshing || Date.now() - queryRefreshAt < RESOLVE_RETRY_MIN_MS) return;
67
+ queryRefreshing = true;
62
68
  try {
63
69
  const query = await queryFor(target);
64
70
  if (currentTarget !== target || disposed) return;
@@ -66,6 +72,9 @@ function createSocketioTransport(options = {}) {
66
72
  for (const sock of sockets.values()) sock.io.opts.query = query;
67
73
  } catch (err) {
68
74
  logger?.warn(`query refresh failed: ${err instanceof Error ? err.message : String(err)}`);
75
+ } finally {
76
+ queryRefreshing = false;
77
+ queryRefreshAt = Date.now();
69
78
  }
70
79
  }
71
80
  function stopRefresh() {
@@ -77,7 +86,7 @@ function createSocketioTransport(options = {}) {
77
86
  function startRefresh() {
78
87
  stopRefresh();
79
88
  if (!resolveQuery || resolveRefreshMs <= 0) return;
80
- refreshTimer = setInterval(() => void refreshQuery(), resolveRefreshMs);
89
+ refreshTimer = setInterval(() => refreshQuery(), resolveRefreshMs);
81
90
  }
82
91
  function markUp() {
83
92
  if (status.up) return;
@@ -106,6 +115,7 @@ function createSocketioTransport(options = {}) {
106
115
  socket.on("connect_error", (err) => {
107
116
  const msg = err?.message ?? "connect_error";
108
117
  logger?.debug(`connect_error (main): ${msg}`);
118
+ if (resolveQuery) refreshQuery();
109
119
  if (isAuthError(msg)) {
110
120
  emitter.emit("auth-error", { message: msg });
111
121
  return;
@@ -202,7 +212,13 @@ function createSocketioTransport(options = {}) {
202
212
  return;
203
213
  }
204
214
  if (endpointChanged || !manager) {
205
- await rebuildManager(target);
215
+ const epoch = ++applyEpoch;
216
+ try {
217
+ await rebuildManager(target);
218
+ } catch (err) {
219
+ if (epoch === applyEpoch && currentTarget === target) currentTarget = null;
220
+ throw err;
221
+ }
206
222
  return;
207
223
  }
208
224
  rebindAuth(target);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camera.ui/transport",
3
- "version": "0.0.27",
3
+ "version": "0.0.29",
4
4
  "description": "camera.ui transport layer — framework-agnostic connection kernel, reducer state, pluggable transports (HTTP/WS/Socket.IO/NATS), lifecycle effects and worker bridge",
5
5
  "author": "seydx (https://github.com/cameraui/clients)",
6
6
  "type": "module",
@@ -56,23 +56,23 @@
56
56
  },
57
57
  "dependencies": {
58
58
  "@camera.ui/logger": ">=0.0.3",
59
- "@camera.ui/rpc": ">=1.0.11",
59
+ "@camera.ui/rpc": ">=1.0.12",
60
60
  "axios": ">=1.20.0",
61
61
  "socket.io-client": ">=4.8.3"
62
62
  },
63
63
  "devDependencies": {
64
64
  "@eslint/js": "9.39.4",
65
65
  "@stylistic/eslint-plugin": "^5.10.0",
66
- "@typescript-eslint/parser": "^8.68.0",
66
+ "@typescript-eslint/parser": "^8.69.0",
67
67
  "@vue/language-core": "^3.3.11",
68
68
  "eslint": "9.39.2",
69
- "globals": "^17.11.0",
69
+ "globals": "^17.12.0",
70
70
  "jiti": "^2.7.0",
71
71
  "prettier": "^3.9.6",
72
72
  "rimraf": "^6.1.3",
73
73
  "typescript": "5.9.3",
74
- "typescript-eslint": "^8.68.0",
75
- "unplugin-dts": "^1.0.3",
74
+ "typescript-eslint": "^8.69.0",
75
+ "unplugin-dts": "^1.1.0",
76
76
  "updates": "^18.0.7",
77
77
  "vite": "^8.2.2",
78
78
  "vitest": "^4.1.11"