@furystack/websocket-api 12.0.0 → 12.0.1

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,19 +7,23 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
7
7
  import { Injector, Injectable } from '@furystack/inject';
8
8
  import { usingAsync } from '@furystack/utils';
9
9
  import { WebSocketApi } from './websocket-api.js';
10
- import WebSocket from 'ws';
10
+ import { WebSocket } from 'ws';
11
11
  import { useWebsockets } from './helpers.js';
12
12
  import { describe, it, expect } from 'vitest';
13
13
  import { getPort } from '@furystack/core/port-generator';
14
+ import { InMemoryStore, User, addStore } from '@furystack/core';
15
+ import { DefaultSession } from '@furystack/rest-service';
14
16
  describe('WebSocketApi', () => {
15
17
  it('Should be built', async () => {
16
18
  await usingAsync(new Injector(), async (i) => {
19
+ addStore(i, new InMemoryStore({ model: User, primaryKey: 'username' })).addStore(new InMemoryStore({ model: DefaultSession, primaryKey: 'sessionId' }));
17
20
  useWebsockets(i, { port: getPort() });
18
21
  expect(i.getInstance(WebSocketApi)).toBeInstanceOf(WebSocketApi);
19
22
  });
20
23
  });
21
24
  it('Should be built with settings', async () => {
22
25
  await usingAsync(new Injector(), async (i) => {
26
+ addStore(i, new InMemoryStore({ model: User, primaryKey: 'username' })).addStore(new InMemoryStore({ model: DefaultSession, primaryKey: 'sessionId' }));
23
27
  useWebsockets(i, { path: '/web-socket', port: getPort() });
24
28
  expect(i.getInstance(WebSocketApi)).toBeInstanceOf(WebSocketApi);
25
29
  });
@@ -27,6 +31,7 @@ describe('WebSocketApi', () => {
27
31
  it('Should broadcast messages', async () => {
28
32
  const port = getPort();
29
33
  await usingAsync(new Injector(), async (i) => {
34
+ addStore(i, new InMemoryStore({ model: User, primaryKey: 'username' })).addStore(new InMemoryStore({ model: DefaultSession, primaryKey: 'sessionId' }));
30
35
  expect.assertions(5); // All 5 clients should receive the message
31
36
  useWebsockets(i, { path: '/web-socket', port });
32
37
  const api = i.getInstance(WebSocketApi);
@@ -49,6 +54,7 @@ describe('WebSocketApi', () => {
49
54
  it('Should receive client messages', async () => {
50
55
  const port = getPort();
51
56
  await usingAsync(new Injector(), async (i) => {
57
+ addStore(i, new InMemoryStore({ model: User, primaryKey: 'username' })).addStore(new InMemoryStore({ model: DefaultSession, primaryKey: 'sessionId' }));
52
58
  expect.assertions(1);
53
59
  const data = { value: 'alma' };
54
60
  let ExampleWsAction = class ExampleWsAction {
@@ -1 +1 @@
1
- {"version":3,"file":"websocket-api.spec.js","sourceRoot":"","sources":["../src/websocket-api.spec.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"websocket-api.spec.js","sourceRoot":"","sources":["../src/websocket-api.spec.ts"],"names":[],"mappings":"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"}
@@ -1,20 +1,21 @@
1
1
  import { Injector } from '@furystack/inject';
2
2
  import { WhoAmI } from './actions/whoami.js';
3
- import ws from 'ws';
4
- import { addStore, InMemoryStore, User } from '@furystack/core';
5
- import { DefaultSession, ServerManager, useHttpAuthentication } from '@furystack/rest-service';
3
+ import { WebSocket } from 'ws';
4
+ import { addStore, InMemoryStore, StoreManager, User } from '@furystack/core';
5
+ import { DefaultSession, HttpUserContext, ServerManager, useHttpAuthentication } from '@furystack/rest-service';
6
6
  import { useRestService } from '@furystack/rest-service';
7
7
  import { useWebsockets } from './helpers.js';
8
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
8
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
9
9
  import { getPort } from '@furystack/core/port-generator';
10
10
  describe('WebSocket Integration tests', () => {
11
11
  const host = 'localhost';
12
12
  const path = '/ws';
13
13
  let i;
14
14
  let client;
15
+ let port;
15
16
  beforeEach(async () => {
16
17
  i = new Injector();
17
- const port = getPort();
18
+ port = getPort();
18
19
  useRestService({
19
20
  injector: i,
20
21
  api: {},
@@ -29,7 +30,7 @@ describe('WebSocket Integration tests', () => {
29
30
  i.getInstance(ServerManager)
30
31
  .getOrCreate({ port })
31
32
  .then(() => {
32
- client = new ws(`ws://${host}:${port}/ws`);
33
+ client = new WebSocket(`ws://${host}:${port}/ws`);
33
34
  client
34
35
  .on('open', () => {
35
36
  done();
@@ -41,15 +42,54 @@ describe('WebSocket Integration tests', () => {
41
42
  afterEach(async () => {
42
43
  await i.dispose();
43
44
  });
44
- it('Should be connected', async () => {
45
- await new Promise((done) => {
46
- client.on('message', (data) => {
47
- expect(data.toString()).toBe('{"currentUser":null}');
48
- client.close();
49
- done();
45
+ const getWhoAmIResult = async (subjectClient) => {
46
+ return new Promise((resolve, reject) => {
47
+ subjectClient.once('message', (data) => {
48
+ resolve(JSON.parse(data.toString()));
50
49
  });
51
- client.send('whoami');
50
+ subjectClient.once('error', reject);
51
+ subjectClient.send('whoami');
52
52
  });
53
+ };
54
+ describe('Authentication', () => {
55
+ it('Should be unauthenticated by default', async () => {
56
+ expect((await getWhoAmIResult(client)).currentUser).toBe(null);
57
+ });
58
+ });
59
+ it('Should be authenticated, roles should be updated and should be logged out', async () => {
60
+ const testUser = { username: 'test', password: 'test', roles: [] };
61
+ const userStore = i.getInstance(StoreManager).getStoreFor(User, 'username');
62
+ userStore.add(testUser);
63
+ const userCtx = i.getInstance(HttpUserContext);
64
+ let cookie = '';
65
+ await userCtx.cookieLogin(testUser, {
66
+ setHeader: (_setCookie, cookieValue) => {
67
+ cookie = cookieValue;
68
+ return {};
69
+ },
70
+ });
71
+ const authenticatedClient = await new Promise((done, reject) => {
72
+ const cl = new WebSocket(`ws://${host}:${port}/ws`, {
73
+ headers: { cookie },
74
+ });
75
+ cl.once('open', () => {
76
+ done(cl);
77
+ }).once('error', reject);
78
+ });
79
+ const whoAmIResult = await getWhoAmIResult(authenticatedClient);
80
+ expect(whoAmIResult.currentUser).toEqual(testUser);
81
+ userStore.update(testUser.username, { ...testUser, roles: ['newFancyRole'] });
82
+ const updatedWhoAmIResult = await getWhoAmIResult(authenticatedClient);
83
+ expect(updatedWhoAmIResult.currentUser.roles).toEqual(['newFancyRole']);
84
+ await userCtx.cookieLogout({
85
+ headers: {
86
+ cookie,
87
+ },
88
+ }, {
89
+ setHeader: vi.fn(),
90
+ });
91
+ const loggedOutWhoAmIResult = await getWhoAmIResult(authenticatedClient);
92
+ expect(loggedOutWhoAmIResult.currentUser).toBe(null);
53
93
  });
54
94
  });
55
95
  //# sourceMappingURL=websocket-integration.spec.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"websocket-integration.spec.js","sourceRoot":"","sources":["../src/websocket-integration.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAC5C,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAC/D,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAA;AAC9F,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAA;AAExD,QAAQ,CAAC,6BAA6B,EAAE,GAAG,EAAE;IAC3C,MAAM,IAAI,GAAG,WAAW,CAAA;IACxB,MAAM,IAAI,GAAG,KAAK,CAAA;IAClB,IAAI,CAAY,CAAA;IAChB,IAAI,MAAU,CAAA;IAEd,UAAU,CAAC,KAAK,IAAI,EAAE;QACpB,CAAC,GAAG,IAAI,QAAQ,EAAE,CAAA;QAClB,MAAM,IAAI,GAAG,OAAO,EAAE,CAAA;QACtB,cAAc,CAAC;YACb,QAAQ,EAAE,CAAC;YACX,GAAG,EAAE,EAAE;YACP,IAAI,EAAE,EAAE;YACR,IAAI;YACJ,QAAQ,EAAE,IAAI;SACf,CAAC,CAAA;QACF,QAAQ,CAAC,CAAC,EAAE,IAAI,aAAa,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,QAAQ,CAC9E,IAAI,aAAa,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,CACtE,CAAA;QACD,qBAAqB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;QAC5B,aAAa,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;QAEzD,MAAM,IAAI,OAAO,CAAO,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;YACvC,CAAC,CAAC,WAAW,CAAC,aAAa,CAAC;iBACzB,WAAW,CAAC,EAAE,IAAI,EAAE,CAAC;iBACrB,IAAI,CAAC,GAAG,EAAE;gBACT,MAAM,GAAG,IAAI,EAAE,CAAC,QAAQ,IAAI,IAAI,IAAI,KAAK,CAAC,CAAA;gBAC1C,MAAM;qBACH,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;oBACf,IAAI,EAAE,CAAA;gBACR,CAAC,CAAC;qBACD,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;YACxB,CAAC,CAAC,CAAA;QACN,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,MAAM,CAAC,CAAC,OAAO,EAAE,CAAA;IACnB,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qBAAqB,EAAE,KAAK,IAAI,EAAE;QACnC,MAAM,IAAI,OAAO,CAAO,CAAC,IAAI,EAAE,EAAE;YAC/B,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE;gBAC5B,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAA;gBACpD,MAAM,CAAC,KAAK,EAAE,CAAA;gBACd,IAAI,EAAE,CAAA;YACR,CAAC,CAAC,CAAA;YACF,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QACvB,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
1
+ {"version":3,"file":"websocket-integration.spec.js","sourceRoot":"","sources":["../src/websocket-integration.spec.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@furystack/websocket-api",
3
- "version": "12.0.0",
3
+ "version": "12.0.1",
4
4
  "description": "HTTP Api FuryStack package",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -34,16 +34,16 @@
34
34
  },
35
35
  "homepage": "https://github.com/furystack/furystack",
36
36
  "dependencies": {
37
- "@furystack/core": "^14.0.1",
38
- "@furystack/inject": "^11.0.0",
39
- "@furystack/rest-service": "^9.0.1",
40
- "@furystack/utils": "^6.0.1",
37
+ "@furystack/core": "^14.0.2",
38
+ "@furystack/inject": "^11.0.1",
39
+ "@furystack/rest-service": "^9.0.2",
40
+ "@furystack/utils": "^7.0.0",
41
41
  "ws": "^8.16.0"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@types/ws": "^8.5.10",
45
- "typescript": "^5.4.3",
46
- "vitest": "^1.4.0"
45
+ "typescript": "^5.4.5",
46
+ "vitest": "^1.5.0"
47
47
  },
48
48
  "gitHead": "1045d854bfd8c475b7035471d130d401417a2321"
49
49
  }
@@ -1,21 +1,30 @@
1
1
  import { Injector, Injectable } from '@furystack/inject'
2
2
  import { usingAsync } from '@furystack/utils'
3
3
  import { WebSocketApi } from './websocket-api.js'
4
- import WebSocket from 'ws'
4
+ import { WebSocket } from 'ws'
5
5
  import type { WebSocketAction } from './models/websocket-action.js'
6
6
  import { useWebsockets } from './helpers.js'
7
7
  import { describe, it, expect } from 'vitest'
8
8
  import { getPort } from '@furystack/core/port-generator'
9
+ import { InMemoryStore, User, addStore } from '@furystack/core'
10
+ import { DefaultSession } from '@furystack/rest-service'
9
11
 
10
12
  describe('WebSocketApi', () => {
11
13
  it('Should be built', async () => {
12
14
  await usingAsync(new Injector(), async (i) => {
15
+ addStore(i, new InMemoryStore({ model: User, primaryKey: 'username' })).addStore(
16
+ new InMemoryStore({ model: DefaultSession, primaryKey: 'sessionId' }),
17
+ )
13
18
  useWebsockets(i, { port: getPort() })
14
19
  expect(i.getInstance(WebSocketApi)).toBeInstanceOf(WebSocketApi)
15
20
  })
16
21
  })
17
22
  it('Should be built with settings', async () => {
18
23
  await usingAsync(new Injector(), async (i) => {
24
+ addStore(i, new InMemoryStore({ model: User, primaryKey: 'username' })).addStore(
25
+ new InMemoryStore({ model: DefaultSession, primaryKey: 'sessionId' }),
26
+ )
27
+
19
28
  useWebsockets(i, { path: '/web-socket', port: getPort() })
20
29
  expect(i.getInstance(WebSocketApi)).toBeInstanceOf(WebSocketApi)
21
30
  })
@@ -24,6 +33,10 @@ describe('WebSocketApi', () => {
24
33
  it('Should broadcast messages', async () => {
25
34
  const port = getPort()
26
35
  await usingAsync(new Injector(), async (i) => {
36
+ addStore(i, new InMemoryStore({ model: User, primaryKey: 'username' })).addStore(
37
+ new InMemoryStore({ model: DefaultSession, primaryKey: 'sessionId' }),
38
+ )
39
+
27
40
  expect.assertions(5) // All 5 clients should receive the message
28
41
  useWebsockets(i, { path: '/web-socket', port })
29
42
  const api = i.getInstance(WebSocketApi)
@@ -51,6 +64,10 @@ describe('WebSocketApi', () => {
51
64
  it('Should receive client messages', async () => {
52
65
  const port = getPort()
53
66
  await usingAsync(new Injector(), async (i) => {
67
+ addStore(i, new InMemoryStore({ model: User, primaryKey: 'username' })).addStore(
68
+ new InMemoryStore({ model: DefaultSession, primaryKey: 'sessionId' }),
69
+ )
70
+
54
71
  expect.assertions(1)
55
72
  const data = { value: 'alma' }
56
73
  @Injectable()
@@ -1,22 +1,23 @@
1
1
  import { Injector } from '@furystack/inject'
2
2
  import { WhoAmI } from './actions/whoami.js'
3
- import ws from 'ws'
4
- import { addStore, InMemoryStore, User } from '@furystack/core'
5
- import { DefaultSession, ServerManager, useHttpAuthentication } from '@furystack/rest-service'
3
+ import { WebSocket } from 'ws'
4
+ import { addStore, InMemoryStore, StoreManager, User } from '@furystack/core'
5
+ import { DefaultSession, HttpUserContext, ServerManager, useHttpAuthentication } from '@furystack/rest-service'
6
6
  import { useRestService } from '@furystack/rest-service'
7
7
  import { useWebsockets } from './helpers.js'
8
- import { describe, it, expect, beforeEach, afterEach } from 'vitest'
8
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
9
9
  import { getPort } from '@furystack/core/port-generator'
10
10
 
11
11
  describe('WebSocket Integration tests', () => {
12
12
  const host = 'localhost'
13
13
  const path = '/ws'
14
14
  let i!: Injector
15
- let client: ws
15
+ let client: WebSocket
16
+ let port: number
16
17
 
17
18
  beforeEach(async () => {
18
19
  i = new Injector()
19
- const port = getPort()
20
+ port = getPort()
20
21
  useRestService({
21
22
  injector: i,
22
23
  api: {},
@@ -34,7 +35,7 @@ describe('WebSocket Integration tests', () => {
34
35
  i.getInstance(ServerManager)
35
36
  .getOrCreate({ port })
36
37
  .then(() => {
37
- client = new ws(`ws://${host}:${port}/ws`)
38
+ client = new WebSocket(`ws://${host}:${port}/ws`)
38
39
  client
39
40
  .on('open', () => {
40
41
  done()
@@ -47,15 +48,66 @@ describe('WebSocket Integration tests', () => {
47
48
  afterEach(async () => {
48
49
  await i.dispose()
49
50
  })
51
+ const getWhoAmIResult = async (subjectClient: WebSocket) => {
52
+ return new Promise<{ currentUser: User }>((resolve, reject) => {
53
+ subjectClient.once('message', (data: any) => {
54
+ resolve(JSON.parse(data.toString()))
55
+ })
56
+ subjectClient.once('error', reject)
57
+ subjectClient.send('whoami')
58
+ })
59
+ }
60
+
61
+ describe('Authentication', () => {
62
+ it('Should be unauthenticated by default', async () => {
63
+ expect((await getWhoAmIResult(client)).currentUser).toBe(null)
64
+ })
65
+ })
66
+
67
+ it('Should be authenticated, roles should be updated and should be logged out', async () => {
68
+ const testUser = { username: 'test', password: 'test', roles: [] } as User
69
+
70
+ const userStore = i.getInstance(StoreManager).getStoreFor(User, 'username')
71
+ userStore.add(testUser)
72
+
73
+ const userCtx = i.getInstance(HttpUserContext)
50
74
 
51
- it('Should be connected', async () => {
52
- await new Promise<void>((done) => {
53
- client.on('message', (data) => {
54
- expect(data.toString()).toBe('{"currentUser":null}')
55
- client.close()
56
- done()
75
+ let cookie = ''
76
+ await userCtx.cookieLogin(testUser, {
77
+ setHeader: (_setCookie, cookieValue) => {
78
+ cookie = cookieValue as string
79
+ return {} as any
80
+ },
81
+ })
82
+
83
+ const authenticatedClient = await new Promise<WebSocket>((done, reject) => {
84
+ const cl = new WebSocket(`ws://${host}:${port}/ws`, {
85
+ headers: { cookie },
57
86
  })
58
- client.send('whoami')
87
+ cl.once('open', () => {
88
+ done(cl)
89
+ }).once('error', reject)
59
90
  })
91
+ const whoAmIResult = await getWhoAmIResult(authenticatedClient)
92
+ expect(whoAmIResult.currentUser).toEqual(testUser)
93
+
94
+ userStore.update(testUser.username, { ...testUser, roles: ['newFancyRole'] })
95
+
96
+ const updatedWhoAmIResult = await getWhoAmIResult(authenticatedClient)
97
+ expect(updatedWhoAmIResult.currentUser.roles).toEqual(['newFancyRole'])
98
+
99
+ await userCtx.cookieLogout(
100
+ {
101
+ headers: {
102
+ cookie,
103
+ },
104
+ },
105
+ {
106
+ setHeader: vi.fn(),
107
+ },
108
+ )
109
+
110
+ const loggedOutWhoAmIResult = await getWhoAmIResult(authenticatedClient)
111
+ expect(loggedOutWhoAmIResult.currentUser).toBe(null)
60
112
  })
61
113
  })