@connexis/transport-websocket 1.0.1 → 1.0.2

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.d.mts CHANGED
@@ -3,6 +3,7 @@ import { Transport, Serializer, ConnectionState, TransportCapabilities } from '@
3
3
  interface WebSocketTransportOptions {
4
4
  protocols?: string | string[];
5
5
  serializer?: Serializer;
6
+ authToken?: string | (() => string | Promise<string>);
6
7
  }
7
8
  declare class WebSocketTransport implements Transport {
8
9
  private url;
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ import { Transport, Serializer, ConnectionState, TransportCapabilities } from '@
3
3
  interface WebSocketTransportOptions {
4
4
  protocols?: string | string[];
5
5
  serializer?: Serializer;
6
+ authToken?: string | (() => string | Promise<string>);
6
7
  }
7
8
  declare class WebSocketTransport implements Transport {
8
9
  private url;
package/dist/index.js CHANGED
@@ -49,10 +49,16 @@ var WebSocketTransport = class _WebSocketTransport {
49
49
  return;
50
50
  }
51
51
  this.updateState("connecting");
52
+ let connectionUrl = this.url;
53
+ if (this.options.authToken) {
54
+ const token = typeof this.options.authToken === "function" ? await this.options.authToken() : this.options.authToken;
55
+ const separator = connectionUrl.includes("?") ? "&" : "?";
56
+ connectionUrl = `${connectionUrl}${separator}token=${encodeURIComponent(token)}`;
57
+ }
52
58
  return new Promise((resolve, reject) => {
53
59
  try {
54
60
  const protocols = this.options.protocols;
55
- this.ws = protocols ? new WebSocket(this.url, protocols) : new WebSocket(this.url);
61
+ this.ws = protocols ? new WebSocket(connectionUrl, protocols) : new WebSocket(connectionUrl);
56
62
  } catch (err) {
57
63
  this.updateState("error", err);
58
64
  reject(err);
package/dist/index.mjs CHANGED
@@ -25,10 +25,16 @@ var WebSocketTransport = class _WebSocketTransport {
25
25
  return;
26
26
  }
27
27
  this.updateState("connecting");
28
+ let connectionUrl = this.url;
29
+ if (this.options.authToken) {
30
+ const token = typeof this.options.authToken === "function" ? await this.options.authToken() : this.options.authToken;
31
+ const separator = connectionUrl.includes("?") ? "&" : "?";
32
+ connectionUrl = `${connectionUrl}${separator}token=${encodeURIComponent(token)}`;
33
+ }
28
34
  return new Promise((resolve, reject) => {
29
35
  try {
30
36
  const protocols = this.options.protocols;
31
- this.ws = protocols ? new WebSocket(this.url, protocols) : new WebSocket(this.url);
37
+ this.ws = protocols ? new WebSocket(connectionUrl, protocols) : new WebSocket(connectionUrl);
32
38
  } catch (err) {
33
39
  this.updateState("error", err);
34
40
  reject(err);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@connexis/transport-websocket",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "WebSocket transport for @connexis",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -13,7 +13,7 @@
13
13
  }
14
14
  },
15
15
  "dependencies": {
16
- "@connexis/core": "1.0.1"
16
+ "@connexis/core": "1.0.2"
17
17
  },
18
18
  "devDependencies": {
19
19
  "typescript": "^5.5.2"
@@ -0,0 +1,85 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
+ import { WebSocketTransport } from '../index.js';
3
+
4
+ // Setup Mock WebSocket class
5
+ class MockWebSocket {
6
+ public static lastInstance: MockWebSocket | null = null;
7
+ public onopen: (() => void) | null = null;
8
+ public onmessage: ((e: { data: any }) => void) | null = null;
9
+ public onerror: ((e: any) => void) | null = null;
10
+ public onclose: (() => void) | null = null;
11
+ public url: string;
12
+ public protocols: string | string[] | undefined;
13
+ public readyState = 1; // OPEN
14
+
15
+ constructor(url: string, protocols?: string | string[]) {
16
+ this.url = url;
17
+ this.protocols = protocols;
18
+ MockWebSocket.lastInstance = this;
19
+
20
+ // Simulate async connection success
21
+ setTimeout(() => {
22
+ this.onopen?.();
23
+ }, 10);
24
+ }
25
+
26
+ send(_data: any) {}
27
+ close() {
28
+ setTimeout(() => {
29
+ this.onclose?.();
30
+ }, 10);
31
+ }
32
+ }
33
+
34
+ describe('WebSocketTransport Auth', () => {
35
+ beforeEach(() => {
36
+ vi.stubGlobal('WebSocket', MockWebSocket);
37
+ MockWebSocket.lastInstance = null;
38
+ });
39
+
40
+ afterEach(() => {
41
+ vi.unstubAllGlobals();
42
+ vi.restoreAllMocks();
43
+ });
44
+
45
+ it('should append token as query parameter for static authToken', async () => {
46
+ const transport = new WebSocketTransport('ws://localhost/ws', {
47
+ authToken: 'static-socket-token'
48
+ });
49
+
50
+ await transport.connect();
51
+
52
+ expect(MockWebSocket.lastInstance).not.toBeNull();
53
+ expect(MockWebSocket.lastInstance!.url).toBe('ws://localhost/ws?token=static-socket-token');
54
+
55
+ await transport.disconnect();
56
+ });
57
+
58
+ it('should append token correctly using & if URL already contains query params', async () => {
59
+ const transport = new WebSocketTransport('ws://localhost/ws?foo=bar', {
60
+ authToken: 'static-socket-token'
61
+ });
62
+
63
+ await transport.connect();
64
+
65
+ expect(MockWebSocket.lastInstance).not.toBeNull();
66
+ expect(MockWebSocket.lastInstance!.url).toBe('ws://localhost/ws?foo=bar&token=static-socket-token');
67
+
68
+ await transport.disconnect();
69
+ });
70
+
71
+ it('should resolve and append token for dynamic async getAuthToken callback', async () => {
72
+ const mockGetToken = vi.fn().mockResolvedValue('dynamic-socket-token');
73
+ const transport = new WebSocketTransport('ws://localhost/ws', {
74
+ authToken: mockGetToken
75
+ });
76
+
77
+ await transport.connect();
78
+
79
+ expect(mockGetToken).toHaveBeenCalled();
80
+ expect(MockWebSocket.lastInstance).not.toBeNull();
81
+ expect(MockWebSocket.lastInstance!.url).toBe('ws://localhost/ws?token=dynamic-socket-token');
82
+
83
+ await transport.disconnect();
84
+ });
85
+ });
package/src/index.ts CHANGED
@@ -3,6 +3,7 @@ import { Transport, ConnectionState, TransportCapabilities, Serializer } from '@
3
3
  export interface WebSocketTransportOptions {
4
4
  protocols?: string | string[];
5
5
  serializer?: Serializer;
6
+ authToken?: string | (() => string | Promise<string>);
6
7
  }
7
8
 
8
9
  const defaultSerializer: Serializer = {
@@ -37,10 +38,19 @@ export class WebSocketTransport implements Transport {
37
38
 
38
39
  this.updateState('connecting');
39
40
 
41
+ let connectionUrl = this.url;
42
+ if (this.options.authToken) {
43
+ const token = typeof this.options.authToken === 'function'
44
+ ? await this.options.authToken()
45
+ : this.options.authToken;
46
+ const separator = connectionUrl.includes('?') ? '&' : '?';
47
+ connectionUrl = `${connectionUrl}${separator}token=${encodeURIComponent(token)}`;
48
+ }
49
+
40
50
  return new Promise<void>((resolve, reject) => {
41
51
  try {
42
52
  const protocols = this.options.protocols;
43
- this.ws = protocols ? new WebSocket(this.url, protocols) : new WebSocket(this.url);
53
+ this.ws = protocols ? new WebSocket(connectionUrl, protocols) : new WebSocket(connectionUrl);
44
54
  } catch (err) {
45
55
  this.updateState('error', err as Error);
46
56
  reject(err);