@camera.ui/transport 0.0.18 → 0.0.20

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.
@@ -3,6 +3,7 @@ export type Detach = () => void;
3
3
  export interface BackoffOptions {
4
4
  readonly kernel: Kernel;
5
5
  readonly schedule?: readonly number[];
6
+ readonly firstAttemptDelayMs?: () => number | null | undefined;
6
7
  readonly now?: () => number;
7
8
  readonly setTimer?: (cb: () => void, ms: number) => unknown;
8
9
  readonly clearTimer?: (handle: unknown) => void;
package/dist/index.js CHANGED
@@ -291,7 +291,9 @@ function attachBackoff(options) {
291
291
  }
292
292
  function scheduleFromPhase(phase, isReschedule) {
293
293
  cancelTimer(isReschedule ? "rescheduled" : void 0);
294
- const scheduleDelay = schedule[Math.min(attempt, schedule.length - 1)];
294
+ const baseDelay = schedule[Math.min(attempt, schedule.length - 1)];
295
+ const quick = attempt === 0 ? options.firstAttemptDelayMs?.() : void 0;
296
+ const scheduleDelay = typeof quick === "number" && quick >= 0 ? Math.min(quick, baseDelay) : baseDelay;
295
297
  const phaseDelay = Math.max(0, phase.nextRetryAt - now());
296
298
  const delay = Math.max(scheduleDelay, phaseDelay);
297
299
  options.onScheduled?.(attempt + 1, delay);
@@ -49,10 +49,11 @@ function createNatsTransport(options = {}) {
49
49
  const url = new URL(target.endpoint.url);
50
50
  const wsProtocol = url.protocol === "https:" ? "wss:" : "ws:";
51
51
  const port = url.port || (url.protocol === "https:" ? "443" : "80");
52
+ const prefix = url.pathname.replace(/\/$/, "");
52
53
  const params = new URLSearchParams({ token: target.tokens.access });
53
54
  if (target.tokens.proxySession) params.set("session", target.tokens.proxySession);
54
55
  if (connId) params.set("connId", connId);
55
- return [`${wsProtocol}//${url.hostname}:${port}${proxyPath}?${params.toString()}`];
56
+ return [`${wsProtocol}//${url.hostname}:${port}${prefix}${proxyPath}?${params.toString()}`];
56
57
  }
57
58
  function notifyClient() {
58
59
  const next = status.up ? proxy : null;
@@ -92,9 +92,15 @@ function createSocketioTransport(options = {}) {
92
92
  });
93
93
  bindCommonAuthEvents(socket);
94
94
  }
95
+ function socketOrigin(target) {
96
+ return new URL(target.endpoint.url).origin;
97
+ }
98
+ function socketPath(target) {
99
+ return `${new URL(target.endpoint.url).pathname.replace(/\/$/, "")}${path}`;
100
+ }
95
101
  function openSocket(namespace, target) {
96
- const sock = io(`${target.endpoint.url}${namespace}`, {
97
- path,
102
+ const sock = io(`${socketOrigin(target)}${namespace}`, {
103
+ path: socketPath(target),
98
104
  auth: buildAuth(target),
99
105
  query: buildQuery(target),
100
106
  reconnection,
@@ -109,8 +115,8 @@ function createSocketioTransport(options = {}) {
109
115
  }
110
116
  function rebuildManager(target) {
111
117
  closeAllSockets();
112
- manager = new Manager(target.endpoint.url, {
113
- path,
118
+ manager = new Manager(socketOrigin(target), {
119
+ path: socketPath(target),
114
120
  autoConnect: false,
115
121
  reconnection,
116
122
  reconnectionDelay,
@@ -31,11 +31,12 @@ function createWsTransport(options = {}) {
31
31
  const base = new URL(target.endpoint.url);
32
32
  const wsProtocol = base.protocol === "https:" ? "wss:" : "ws:";
33
33
  const port = base.port || (base.protocol === "https:" ? "443" : "80");
34
+ const prefix = base.pathname.replace(/\/$/, "");
34
35
  const params = new URLSearchParams();
35
36
  for (const [k, v] of Object.entries(handleSpec.query ?? {})) if (v !== void 0 && v !== null && v !== "") params.set(k, v);
36
37
  params.set(tokenParam, target.tokens.access);
37
38
  if (target.tokens.proxySession) params.set(sessionParam, target.tokens.proxySession);
38
- return `${wsProtocol}//${base.hostname}:${port}${handleSpec.path}?${params.toString()}`;
39
+ return `${wsProtocol}//${base.hostname}:${port}${prefix}${handleSpec.path}?${params.toString()}`;
39
40
  }
40
41
  function isAuthCloseEvent(event) {
41
42
  if (event.code === 1008 || event.code === 4401) return true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camera.ui/transport",
3
- "version": "0.0.18",
3
+ "version": "0.0.20",
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",
@@ -63,19 +63,19 @@
63
63
  "devDependencies": {
64
64
  "@eslint/js": "9.39.4",
65
65
  "@stylistic/eslint-plugin": "^5.10.0",
66
- "@typescript-eslint/parser": "^8.62.1",
67
- "@vue/language-core": "^3.3.6",
66
+ "@typescript-eslint/parser": "^8.64.0",
67
+ "@vue/language-core": "^3.3.7",
68
68
  "eslint": "9.39.2",
69
69
  "globals": "^17.7.0",
70
70
  "jiti": "^2.7.0",
71
- "prettier": "^3.9.4",
71
+ "prettier": "^3.9.5",
72
72
  "rimraf": "^6.1.3",
73
73
  "typescript": "5.9.3",
74
- "typescript-eslint": "^8.62.1",
74
+ "typescript-eslint": "^8.64.0",
75
75
  "unplugin-dts": "^1.0.3",
76
- "updates": "^17.18.2",
77
- "vite": "^8.1.3",
78
- "vitest": "^4.1.9"
76
+ "updates": "^17.19.1",
77
+ "vite": "^8.1.5",
78
+ "vitest": "^4.1.10"
79
79
  },
80
80
  "overrides": {
81
81
  "@vue/language-core": "$@vue/language-core"