@furystack/websocket-api 10.0.0 → 12.0.0

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.
@@ -1,7 +1,7 @@
1
1
  /// <reference path="../../../rest-service/esm/incoming-message-extensions.d.ts" />
2
2
  /// <reference path="../../../rest-service/esm/server-response-extensions.d.ts" />
3
3
  /// <reference types="node/http.js" />
4
- import type { Data } from 'ws';
4
+ import type { Data, WebSocket } from 'ws';
5
5
  import type { WebSocketAction } from '../models/websocket-action.js';
6
6
  import type { IncomingMessage } from 'http';
7
7
  /**
@@ -16,8 +16,8 @@ export declare class WhoAmI implements WebSocketAction {
16
16
  execute(options: {
17
17
  data: Data;
18
18
  request: IncomingMessage;
19
+ socket: WebSocket;
19
20
  }): Promise<void>;
20
21
  private readonly httpUserContext;
21
- private readonly websocket;
22
22
  }
23
23
  //# sourceMappingURL=whoami.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"whoami.d.ts","sourceRoot":"","sources":["../../src/actions/whoami.ts"],"names":[],"mappings":";;;AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,IAAI,CAAA;AAE9B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,MAAM,CAAA;AAE3C;;GAEG;AACH,qBACa,MAAO,YAAW,eAAe;IACrC,OAAO;WAGA,UAAU,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,OAAO,EAAE,eAAe,CAAA;KAAE,GAAG,OAAO;IAIvE,OAAO,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,OAAO,EAAE,eAAe,CAAA;KAAE;IAUtE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAkB;IAGlD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAK;CAChC"}
1
+ {"version":3,"file":"whoami.d.ts","sourceRoot":"","sources":["../../src/actions/whoami.ts"],"names":[],"mappings":";;;AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,IAAI,CAAA;AACzC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,MAAM,CAAA;AAE3C;;GAEG;AACH,qBACa,MAAO,YAAW,eAAe;IACrC,OAAO;WAGA,UAAU,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,OAAO,EAAE,eAAe,CAAA;KAAE,GAAG,OAAO;IAIvE,OAAO,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,OAAO,EAAE,eAAe,CAAC;QAAC,MAAM,EAAE,SAAS,CAAA;KAAE;IASzF,iBACyB,eAAe,CAAiB;CAC1D"}
@@ -9,7 +9,6 @@ var __metadata = (this && this.__metadata) || function (k, v) {
9
9
  };
10
10
  import { HttpUserContext } from '@furystack/rest-service';
11
11
  import { Injectable, Injected } from '@furystack/inject';
12
- import ws from 'ws';
13
12
  /**
14
13
  * Example action that returns the current user instance
15
14
  */
@@ -23,23 +22,17 @@ let WhoAmI = class WhoAmI {
23
22
  async execute(options) {
24
23
  try {
25
24
  const currentUser = await this.httpUserContext.getCurrentUser(options.request);
26
- this.websocket.send(JSON.stringify({ currentUser }));
25
+ options.socket.send(JSON.stringify({ currentUser }));
27
26
  }
28
27
  catch (error) {
29
- this.websocket.send(JSON.stringify({ currentUser: null }));
28
+ options.socket.send(JSON.stringify({ currentUser: null }));
30
29
  }
31
30
  }
32
- httpUserContext;
33
- websocket;
34
31
  };
35
32
  __decorate([
36
33
  Injected(HttpUserContext),
37
34
  __metadata("design:type", HttpUserContext)
38
35
  ], WhoAmI.prototype, "httpUserContext", void 0);
39
- __decorate([
40
- Injected(ws),
41
- __metadata("design:type", ws)
42
- ], WhoAmI.prototype, "websocket", void 0);
43
36
  WhoAmI = __decorate([
44
37
  Injectable({ lifetime: 'transient' })
45
38
  ], WhoAmI);
@@ -1 +1 @@
1
- {"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../src/actions/whoami.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAExD,OAAO,EAAE,MAAM,IAAI,CAAA;AAInB;;GAEG;AAEI,IAAM,MAAM,GAAZ,MAAM,MAAM;IACV,OAAO;QACZ,MAAM;IACR,CAAC;IACM,MAAM,CAAC,UAAU,CAAC,OAAiD;QACxE,OAAO,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,gBAAgB,CAAA;IAC7F,CAAC;IAEM,KAAK,CAAC,OAAO,CAAC,OAAiD;QACpE,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;YAC9E,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAA;QACtD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;QAC5D,CAAC;IACH,CAAC;IAGgB,eAAe,CAAkB;IAGjC,SAAS,CAAK;CAChC,CAAA;AAJkB;IADhB,QAAQ,CAAC,eAAe,CAAC;8BACS,eAAe;+CAAA;AAGjC;IADhB,QAAQ,CAAC,EAAE,CAAC;8BACgB,EAAE;yCAAA;AArBpB,MAAM;IADlB,UAAU,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;GACzB,MAAM,CAsBlB"}
1
+ {"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../src/actions/whoami.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAKxD;;GAEG;AAEI,IAAM,MAAM,GAAZ,MAAM,MAAM;IACV,OAAO;QACZ,MAAM;IACR,CAAC;IACM,MAAM,CAAC,UAAU,CAAC,OAAiD;QACxE,OAAO,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,gBAAgB,CAAA;IAC7F,CAAC;IAEM,KAAK,CAAC,OAAO,CAAC,OAAoE;QACvF,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;YAC9E,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAA;QACtD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;QAC5D,CAAC;IACH,CAAC;CAIF,CAAA;AAD0B;IADxB,QAAQ,CAAC,eAAe,CAAC;8BACgB,eAAe;+CAAA;AAlB9C,MAAM;IADlB,UAAU,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;GACzB,MAAM,CAmBlB"}
@@ -25,7 +25,7 @@ describe('Whoami action', () => {
25
25
  injector.setExplicitInstance(contextMock, HttpUserContext);
26
26
  injector.setExplicitInstance(wsMock, ws);
27
27
  const instance = injector.getInstance(WhoAmI);
28
- await instance.execute({ request, data: '' });
28
+ await instance.execute({ request, data: '', socket: wsMock });
29
29
  expect(wsMock.send).toBeCalledWith(JSON.stringify({ currentUser }));
30
30
  });
31
31
  });
@@ -1 +1 @@
1
- {"version":3,"file":"whoami.spec.js","sourceRoot":"","sources":["../../src/actions/whoami.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAEjD,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,MAAM,WAAW,GAAG,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAA;IAC5C,MAAM,WAAW,GAAoB,EAAE,cAAc,EAAE,KAAK,IAAI,EAAE,CAAC,WAAW,EAAgC,CAAA;IAE9G,MAAM,OAAO,GAAG,EAAE,GAAG,EAAE,oBAAoB,EAAqB,CAAA;IAEhE,MAAM,MAAM,GAAO;QACjB,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC;KACZ,CAAA;IAElB,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,CAAA;IACjE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,CAAA;IACrE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,CAAA;IAC7E,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;QAC9C,MAAM,UAAU,CAAC,IAAI,QAAQ,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;YAClD,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,eAAe,CAAC,CAAA;YAC1D,QAAQ,CAAC,mBAAmB,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;YACxC,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;YAE7C,MAAM,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAA;YAC7C,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAA;QACrE,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
1
+ {"version":3,"file":"whoami.spec.js","sourceRoot":"","sources":["../../src/actions/whoami.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAEjD,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,MAAM,WAAW,GAAG,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAA;IAC5C,MAAM,WAAW,GAAoB,EAAE,cAAc,EAAE,KAAK,IAAI,EAAE,CAAC,WAAW,EAAgC,CAAA;IAE9G,MAAM,OAAO,GAAG,EAAE,GAAG,EAAE,oBAAoB,EAAqB,CAAA;IAEhE,MAAM,MAAM,GAAO;QACjB,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC;KACZ,CAAA;IAElB,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,CAAA;IACjE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,CAAA;IACrE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,CAAA;IAC7E,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;QAC9C,MAAM,UAAU,CAAC,IAAI,QAAQ,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;YAClD,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,eAAe,CAAC,CAAA;YAC1D,QAAQ,CAAC,mBAAmB,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;YACxC,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;YAC7C,MAAM,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;YAC7D,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAA;QACrE,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -1,11 +1,17 @@
1
+ /// <reference path="../../../rest-service/esm/incoming-message-extensions.d.ts" />
2
+ /// <reference path="../../../rest-service/esm/server-response-extensions.d.ts" />
3
+ /// <reference types="node/http.js" />
1
4
  import type { Disposable } from '@furystack/utils';
2
- import type { Data } from 'ws';
5
+ import type { Data, WebSocket } from 'ws';
6
+ import type { IncomingMessage } from 'http';
3
7
  /**
4
8
  * Static methods of a WebSocket Action
5
9
  */
6
10
  export interface WebSocketActionStatic {
7
11
  canExecute(options: {
8
12
  data: Data;
13
+ request: IncomingMessage;
14
+ socket: WebSocket;
9
15
  }): boolean;
10
16
  }
11
17
  /**
@@ -14,6 +20,8 @@ export interface WebSocketActionStatic {
14
20
  export interface WebSocketAction extends Disposable {
15
21
  execute(options: {
16
22
  data: Data;
23
+ request: IncomingMessage;
24
+ socket: WebSocket;
17
25
  }): void;
18
26
  }
19
27
  //# sourceMappingURL=websocket-action.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"websocket-action.d.ts","sourceRoot":"","sources":["../../src/models/websocket-action.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,IAAI,CAAA;AAE9B;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,UAAU,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,IAAI,CAAA;KAAE,GAAG,OAAO,CAAA;CAC7C;AAED;;GAEG;AACH,MAAM,WAAW,eAAgB,SAAQ,UAAU;IACjD,OAAO,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,IAAI,CAAA;KAAE,GAAG,IAAI,CAAA;CACvC"}
1
+ {"version":3,"file":"websocket-action.d.ts","sourceRoot":"","sources":["../../src/models/websocket-action.ts"],"names":[],"mappings":";;;AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,IAAI,CAAA;AACzC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,MAAM,CAAA;AAE3C;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,UAAU,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,OAAO,EAAE,eAAe,CAAC;QAAC,MAAM,EAAE,SAAS,CAAA;KAAE,GAAG,OAAO,CAAA;CAC1F;AAED;;GAEG;AACH,MAAM,WAAW,eAAgB,SAAQ,UAAU;IACjD,OAAO,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,OAAO,EAAE,eAAe,CAAC;QAAC,MAAM,EAAE,SAAS,CAAA;KAAE,GAAG,IAAI,CAAA;CACpF"}
@@ -3,15 +3,16 @@
3
3
  /// <reference types="node/http.js" />
4
4
  /// <reference types="node/http.js" />
5
5
  import { IncomingMessage } from 'http';
6
- import { Injector } from '@furystack/inject';
7
- import type { Disposable } from '@furystack/utils';
6
+ import type { Injector } from '@furystack/inject';
7
+ import { type Disposable } from '@furystack/utils';
8
8
  import type { Data } from 'ws';
9
+ import type WebSocket from 'ws';
9
10
  import ws from 'ws';
10
11
  /**
11
12
  * A WebSocket API implementation for FuryStack
12
13
  */
13
14
  export declare class WebSocketApi implements Disposable {
14
- readonly socket: ws.Server<typeof ws, typeof IncomingMessage>;
15
+ readonly socket: WebSocket.Server<typeof WebSocket, typeof IncomingMessage>;
15
16
  private clients;
16
17
  private readonly settings;
17
18
  private readonly serverManager;
@@ -24,6 +25,6 @@ export declare class WebSocketApi implements Disposable {
24
25
  ws: ws;
25
26
  message: IncomingMessage;
26
27
  }) => void | Promise<void>): Promise<void>;
27
- execute(data: Data, injector: Injector): void;
28
+ execute(data: Data, request: IncomingMessage, injector: Injector, socket: WebSocket): Promise<void>;
28
29
  }
29
30
  //# sourceMappingURL=websocket-api.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"websocket-api.d.ts","sourceRoot":"","sources":["../src/websocket-api.ts"],"names":[],"mappings":";;;;AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,MAAM,CAAA;AAEtC,OAAO,EAAwB,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,IAAI,CAAA;AAE9B,OAAO,EAAE,MAAM,IAAI,CAAA;AAMnB;;GAEG;AACH,qBACa,YAAa,YAAW,UAAU;IAC7C,SAAgB,MAAM,+CAA0C;IAEhE,OAAO,CAAC,OAAO,CAA0E;IAGzF,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuB;IAGhD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAG9C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;IAEpC,OAAO,CAAC,aAAa,CAAQ;IACtB,IAAI;IA+BE,OAAO;IAMP,SAAS,CACpB,QAAQ,EAAE,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,EAAE,EAAE,EAAE,CAAC;QAAC,OAAO,EAAE,eAAe,CAAA;KAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBhG,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ;CAO9C"}
1
+ {"version":3,"file":"websocket-api.d.ts","sourceRoot":"","sources":["../src/websocket-api.ts"],"names":[],"mappings":";;;;AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,MAAM,CAAA;AAEtC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAEjD,OAAO,EAAc,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC9D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,IAAI,CAAA;AAC9B,OAAO,KAAK,SAAS,MAAM,IAAI,CAAA;AAE/B,OAAO,EAAE,MAAM,IAAI,CAAA;AAKnB;;GAEG;AACH,qBACa,YAAa,YAAW,UAAU;IAC7C,SAAgB,MAAM,6DAA0C;IAEhE,OAAO,CAAC,OAAO,CAA0E;IAEzF,iBACyB,QAAQ,CAAsB;IAEvD,iBACyB,aAAa,CAAe;IAErD,iBAAyB,QAAQ,CAAU;IAE3C,OAAO,CAAC,aAAa,CAAQ;IACtB,IAAI;IA+BE,OAAO;IAMP,SAAS,CACpB,QAAQ,EAAE,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,EAAE,EAAE,EAAE,CAAC;QAAC,OAAO,EAAE,eAAe,CAAA;KAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB1F,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS;CAQjG"}
@@ -9,22 +9,19 @@ var __metadata = (this && this.__metadata) || function (k, v) {
9
9
  };
10
10
  import { URL } from 'url';
11
11
  import { IncomingMessage } from 'http';
12
- import { ServerManager } from '@furystack/rest-service';
13
- import { Injectable, Injected, Injector } from '@furystack/inject';
12
+ import { HttpUserContext, ServerManager } from '@furystack/rest-service';
13
+ import { Injectable, Injected } from '@furystack/inject';
14
+ import { usingAsync } from '@furystack/utils';
14
15
  import { WebSocketServer } from 'ws';
15
16
  import ws from 'ws';
16
17
  import { WebSocketApiSettings } from './websocket-api-settings.js';
17
18
  import { AggregatedError, IdentityContext } from '@furystack/core';
18
- import { WebsocketUserContext } from './websocket-user-context.js';
19
19
  /**
20
20
  * A WebSocket API implementation for FuryStack
21
21
  */
22
22
  let WebSocketApi = class WebSocketApi {
23
23
  socket = new WebSocketServer({ noServer: true });
24
24
  clients = new Map();
25
- settings;
26
- serverManager;
27
- injector;
28
25
  isInitialized = false;
29
26
  init() {
30
27
  if (!this.isInitialized) {
@@ -32,10 +29,10 @@ let WebSocketApi = class WebSocketApi {
32
29
  const connectionInjector = this.injector.createChild({ owner: msg });
33
30
  connectionInjector.setExplicitInstance(websocket, ws);
34
31
  connectionInjector.setExplicitInstance(msg, IncomingMessage);
35
- connectionInjector.setExplicitInstance(connectionInjector.getInstance(WebsocketUserContext), IdentityContext);
32
+ connectionInjector.setExplicitInstance(connectionInjector.getInstance(HttpUserContext), IdentityContext);
36
33
  this.clients.set(websocket, { injector: connectionInjector, message: msg, ws: websocket });
37
34
  websocket.on('message', (message) => {
38
- this.execute(message, connectionInjector);
35
+ this.execute(message, msg, connectionInjector, websocket);
39
36
  });
40
37
  websocket.on('close', () => {
41
38
  this.clients.delete(websocket);
@@ -77,11 +74,12 @@ let WebSocketApi = class WebSocketApi {
77
74
  throw new AggregatedError('The Broadcast operation encountered some errors', errors);
78
75
  }
79
76
  }
80
- execute(data, injector) {
81
- const action = this.settings.actions.find((a) => a.canExecute({ data }));
82
- if (action) {
83
- const actionInstance = injector.getInstance(action);
84
- actionInstance.execute({ data });
77
+ async execute(data, request, injector, socket) {
78
+ const Action = this.settings.actions.find((a) => a.canExecute({ data, request, socket }));
79
+ if (Action) {
80
+ await usingAsync(injector.getInstance(Action), async (action) => {
81
+ await action.execute({ data, request, socket });
82
+ });
85
83
  }
86
84
  }
87
85
  };
@@ -93,10 +91,6 @@ __decorate([
93
91
  Injected(ServerManager),
94
92
  __metadata("design:type", ServerManager)
95
93
  ], WebSocketApi.prototype, "serverManager", void 0);
96
- __decorate([
97
- Injected(Injector),
98
- __metadata("design:type", Injector)
99
- ], WebSocketApi.prototype, "injector", void 0);
100
94
  WebSocketApi = __decorate([
101
95
  Injectable({ lifetime: 'scoped' })
102
96
  ], WebSocketApi);
@@ -1 +1 @@
1
- {"version":3,"file":"websocket-api.js","sourceRoot":"","sources":["../src/websocket-api.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAEzB,OAAO,EAAE,eAAe,EAAE,MAAM,MAAM,CAAA;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACvD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAGlE,OAAO,EAAE,eAAe,EAAE,MAAM,IAAI,CAAA;AACpC,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAA;AAElE,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAA;AAElE;;GAEG;AAEI,IAAM,YAAY,GAAlB,MAAM,YAAY;IACP,MAAM,GAAG,IAAI,eAAe,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;IAExD,OAAO,GAAG,IAAI,GAAG,EAAgE,CAAA;IAGxE,QAAQ,CAAuB;IAG/B,aAAa,CAAgB;IAG7B,QAAQ,CAAW;IAE5B,aAAa,GAAG,KAAK,CAAA;IACtB,IAAI;QACT,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;YACxB,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,EAAE;gBAC9C,MAAM,kBAAkB,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAA;gBACpE,kBAAkB,CAAC,mBAAmB,CAAC,SAAS,EAAE,EAAE,CAAC,CAAA;gBACrD,kBAAkB,CAAC,mBAAmB,CAAC,GAAG,EAAE,eAAe,CAAC,CAAA;gBAC5D,kBAAkB,CAAC,mBAAmB,CAAC,kBAAkB,CAAC,WAAW,CAAC,oBAAoB,CAAC,EAAE,eAAe,CAAC,CAAA;gBAC7G,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,kBAAkB,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAAA;gBAC1F,SAAS,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE;oBAClC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAA;gBAC3C,CAAC,CAAC,CAAA;gBAEF,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;oBACzB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;gBAChC,CAAC,CAAC,CAAA;YACJ,CAAC,CAAC,CAAA;YAEF,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;gBACzG,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,OAAwB,EAAE,MAAc,EAAE,IAAY,EAAE,EAAE;oBACrF,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAa,EAAE,UAAU,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;oBACrF,IAAI,QAAQ,KAAK,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;wBACpC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,EAAE;4BAC7D,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,SAAS,EAAE,OAAO,CAAC,CAAA;wBACpD,CAAC,CAAC,CAAA;oBACJ,CAAC;gBACH,CAAC,CAAC,CAAA;YACJ,CAAC,CAAC,CAAA;QACJ,CAAC;aAAM,CAAC;YACN,MAAM,KAAK,CAAC,sCAAsC,CAAC,CAAA;QACrD,CAAC;IACH,CAAC;IACM,KAAK,CAAC,OAAO;QAClB,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAA;QACvD,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAA;QAC3D,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAA;IAC3G,CAAC;IAEM,KAAK,CAAC,SAAS,CACpB,QAAqG;QAErG,MAAM,MAAM,GAAc,EAAE,CAAA;QAC5B,MAAM,OAAO,CAAC,GAAG,CACf,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;aACvB,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,UAAU,KAAK,EAAE,CAAC,IAAI,CAAC;aACpD,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;YACpB,IAAI,CAAC;gBACH,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAA;YACxB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YACpB,CAAC;QACH,CAAC,CAAC,CACL,CAAA;QACD,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAClB,MAAM,IAAI,eAAe,CAAC,iDAAiD,EAAE,MAAM,CAAC,CAAA;QACtF,CAAC;IACH,CAAC;IAEM,OAAO,CAAC,IAAU,EAAE,QAAkB;QAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;QACxE,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,cAAc,GAAG,QAAQ,CAAC,WAAW,CAAkB,MAAM,CAAC,CAAA;YACpE,cAAc,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,CAAA;QAClC,CAAC;IACH,CAAC;CACF,CAAA;AAzEkB;IADhB,QAAQ,CAAC,oBAAoB,CAAC;8BACH,oBAAoB;8CAAA;AAG/B;IADhB,QAAQ,CAAC,aAAa,CAAC;8BACS,aAAa;mDAAA;AAG7B;IADhB,QAAQ,CAAC,QAAQ,CAAC;8BACS,QAAQ;8CAAA;AAZzB,YAAY;IADxB,UAAU,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;GACtB,YAAY,CA+ExB"}
1
+ {"version":3,"file":"websocket-api.js","sourceRoot":"","sources":["../src/websocket-api.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": "10.0.0",
3
+ "version": "12.0.0",
4
4
  "description": "HTTP Api FuryStack package",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -34,15 +34,15 @@
34
34
  },
35
35
  "homepage": "https://github.com/furystack/furystack",
36
36
  "dependencies": {
37
- "@furystack/core": "^13.0.0",
38
- "@furystack/inject": "^9.0.0",
39
- "@furystack/rest-service": "^8.0.0",
40
- "@furystack/utils": "^5.0.0",
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",
41
41
  "ws": "^8.16.0"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@types/ws": "^8.5.10",
45
- "typescript": "^5.4.2",
45
+ "typescript": "^5.4.3",
46
46
  "vitest": "^1.4.0"
47
47
  },
48
48
  "gitHead": "1045d854bfd8c475b7035471d130d401417a2321"
@@ -33,8 +33,7 @@ describe('Whoami action', () => {
33
33
  injector.setExplicitInstance(contextMock, HttpUserContext)
34
34
  injector.setExplicitInstance(wsMock, ws)
35
35
  const instance = injector.getInstance(WhoAmI)
36
-
37
- await instance.execute({ request, data: '' })
36
+ await instance.execute({ request, data: '', socket: wsMock })
38
37
  expect(wsMock.send).toBeCalledWith(JSON.stringify({ currentUser }))
39
38
  })
40
39
  })
@@ -1,7 +1,6 @@
1
1
  import { HttpUserContext } from '@furystack/rest-service'
2
2
  import { Injectable, Injected } from '@furystack/inject'
3
- import type { Data } from 'ws'
4
- import ws from 'ws'
3
+ import type { Data, WebSocket } from 'ws'
5
4
  import type { WebSocketAction } from '../models/websocket-action.js'
6
5
  import type { IncomingMessage } from 'http'
7
6
 
@@ -17,18 +16,15 @@ export class WhoAmI implements WebSocketAction {
17
16
  return options.data.toString() === 'whoami' || options.data.toString() === 'whoami /claims'
18
17
  }
19
18
 
20
- public async execute(options: { data: Data; request: IncomingMessage }) {
19
+ public async execute(options: { data: Data; request: IncomingMessage; socket: WebSocket }) {
21
20
  try {
22
21
  const currentUser = await this.httpUserContext.getCurrentUser(options.request)
23
- this.websocket.send(JSON.stringify({ currentUser }))
22
+ options.socket.send(JSON.stringify({ currentUser }))
24
23
  } catch (error) {
25
- this.websocket.send(JSON.stringify({ currentUser: null }))
24
+ options.socket.send(JSON.stringify({ currentUser: null }))
26
25
  }
27
26
  }
28
27
 
29
28
  @Injected(HttpUserContext)
30
- private readonly httpUserContext!: HttpUserContext
31
-
32
- @Injected(ws)
33
- private readonly websocket!: ws
29
+ private declare readonly httpUserContext: HttpUserContext
34
30
  }
@@ -1,16 +1,17 @@
1
1
  import type { Disposable } from '@furystack/utils'
2
- import type { Data } from 'ws'
2
+ import type { Data, WebSocket } from 'ws'
3
+ import type { IncomingMessage } from 'http'
3
4
 
4
5
  /**
5
6
  * Static methods of a WebSocket Action
6
7
  */
7
8
  export interface WebSocketActionStatic {
8
- canExecute(options: { data: Data }): boolean
9
+ canExecute(options: { data: Data; request: IncomingMessage; socket: WebSocket }): boolean
9
10
  }
10
11
 
11
12
  /**
12
13
  * A WebSocket action implementaion
13
14
  */
14
15
  export interface WebSocketAction extends Disposable {
15
- execute(options: { data: Data }): void
16
+ execute(options: { data: Data; request: IncomingMessage; socket: WebSocket }): void
16
17
  }
@@ -1,16 +1,17 @@
1
1
  import { URL } from 'url'
2
2
  import type { Socket } from 'net'
3
3
  import { IncomingMessage } from 'http'
4
- import { ServerManager } from '@furystack/rest-service'
5
- import { Injectable, Injected, Injector } from '@furystack/inject'
6
- import type { Disposable } from '@furystack/utils'
4
+ import { HttpUserContext, ServerManager } from '@furystack/rest-service'
5
+ import type { Injector } from '@furystack/inject'
6
+ import { Injectable, Injected } from '@furystack/inject'
7
+ import { usingAsync, type Disposable } from '@furystack/utils'
7
8
  import type { Data } from 'ws'
9
+ import type WebSocket from 'ws'
8
10
  import { WebSocketServer } from 'ws'
9
11
  import ws from 'ws'
10
12
  import { WebSocketApiSettings } from './websocket-api-settings.js'
11
13
  import type { WebSocketAction } from './models/websocket-action.js'
12
14
  import { AggregatedError, IdentityContext } from '@furystack/core'
13
- import { WebsocketUserContext } from './websocket-user-context.js'
14
15
 
15
16
  /**
16
17
  * A WebSocket API implementation for FuryStack
@@ -22,13 +23,12 @@ export class WebSocketApi implements Disposable {
22
23
  private clients = new Map<ws, { injector: Injector; ws: ws; message: IncomingMessage }>()
23
24
 
24
25
  @Injected(WebSocketApiSettings)
25
- private readonly settings!: WebSocketApiSettings
26
+ private declare readonly settings: WebSocketApiSettings
26
27
 
27
28
  @Injected(ServerManager)
28
- private readonly serverManager!: ServerManager
29
+ private declare readonly serverManager: ServerManager
29
30
 
30
- @Injected(Injector)
31
- private readonly injector!: Injector
31
+ private declare readonly injector: Injector
32
32
 
33
33
  private isInitialized = false
34
34
  public init() {
@@ -37,10 +37,10 @@ export class WebSocketApi implements Disposable {
37
37
  const connectionInjector = this.injector.createChild({ owner: msg })
38
38
  connectionInjector.setExplicitInstance(websocket, ws)
39
39
  connectionInjector.setExplicitInstance(msg, IncomingMessage)
40
- connectionInjector.setExplicitInstance(connectionInjector.getInstance(WebsocketUserContext), IdentityContext)
40
+ connectionInjector.setExplicitInstance(connectionInjector.getInstance(HttpUserContext), IdentityContext)
41
41
  this.clients.set(websocket, { injector: connectionInjector, message: msg, ws: websocket })
42
42
  websocket.on('message', (message) => {
43
- this.execute(message, connectionInjector)
43
+ this.execute(message, msg, connectionInjector, websocket)
44
44
  })
45
45
 
46
46
  websocket.on('close', () => {
@@ -88,11 +88,12 @@ export class WebSocketApi implements Disposable {
88
88
  }
89
89
  }
90
90
 
91
- public execute(data: Data, injector: Injector) {
92
- const action = this.settings.actions.find((a) => a.canExecute({ data }))
93
- if (action) {
94
- const actionInstance = injector.getInstance<WebSocketAction>(action)
95
- actionInstance.execute({ data })
91
+ public async execute(data: Data, request: IncomingMessage, injector: Injector, socket: WebSocket) {
92
+ const Action = this.settings.actions.find((a) => a.canExecute({ data, request, socket }))
93
+ if (Action) {
94
+ await usingAsync(injector.getInstance<WebSocketAction>(Action), async (action) => {
95
+ await action.execute({ data, request, socket })
96
+ })
96
97
  }
97
98
  }
98
99
  }
@@ -1,8 +0,0 @@
1
- import type { IdentityContext, User } from '@furystack/core';
2
- export declare class WebsocketUserContext implements IdentityContext {
3
- isAuthenticated(): Promise<boolean>;
4
- isAuthorized(...roles: string[]): Promise<boolean>;
5
- getCurrentUser<TUser extends User>(): Promise<TUser>;
6
- private readonly injector;
7
- }
8
- //# sourceMappingURL=websocket-user-context.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"websocket-user-context.d.ts","sourceRoot":"","sources":["../src/websocket-user-context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAI5D,qBACa,oBAAqB,YAAW,eAAe;IAC7C,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IAOnC,YAAY,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAalD,cAAc,CAAC,KAAK,SAAS,IAAI,KAAK,OAAO,CAAC,KAAK,CAAC;IAQjE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;CACrC"}
@@ -1,52 +0,0 @@
1
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
- return c > 3 && r && Object.defineProperty(target, key, r), r;
6
- };
7
- var __metadata = (this && this.__metadata) || function (k, v) {
8
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
- };
10
- import { IncomingMessage } from 'http';
11
- import { Injectable, Injected, Injector } from '@furystack/inject';
12
- import { HttpUserContext } from '@furystack/rest-service';
13
- let WebsocketUserContext = class WebsocketUserContext {
14
- async isAuthenticated() {
15
- try {
16
- return (await this.getCurrentUser()) ? true : false;
17
- }
18
- catch (error) {
19
- return false;
20
- }
21
- }
22
- async isAuthorized(...roles) {
23
- try {
24
- const currentUser = await this.getCurrentUser();
25
- for (const role of roles) {
26
- if (!currentUser || !currentUser.roles.some((c) => c === role)) {
27
- return false;
28
- }
29
- }
30
- return true;
31
- }
32
- catch (error) {
33
- return false;
34
- }
35
- }
36
- async getCurrentUser() {
37
- const user = await this.injector
38
- .getInstance(HttpUserContext)
39
- .authenticateRequest(this.injector.getInstance(IncomingMessage));
40
- return user;
41
- }
42
- injector;
43
- };
44
- __decorate([
45
- Injected(Injector),
46
- __metadata("design:type", Injector)
47
- ], WebsocketUserContext.prototype, "injector", void 0);
48
- WebsocketUserContext = __decorate([
49
- Injectable({ lifetime: 'scoped' })
50
- ], WebsocketUserContext);
51
- export { WebsocketUserContext };
52
- //# sourceMappingURL=websocket-user-context.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"websocket-user-context.js","sourceRoot":"","sources":["../src/websocket-user-context.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,MAAM,CAAA;AAEtC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAGlD,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;IACxB,KAAK,CAAC,eAAe;QAC1B,IAAI,CAAC;YACH,OAAO,CAAC,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAA;QACrD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IACM,KAAK,CAAC,YAAY,CAAC,GAAG,KAAe;QAC1C,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAA;YAC/C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,IAAI,CAAC,WAAW,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC;oBAC/D,OAAO,KAAK,CAAA;gBACd,CAAC;YACH,CAAC;YACD,OAAO,IAAI,CAAA;QACb,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IACM,KAAK,CAAC,cAAc;QACzB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ;aAC7B,WAAW,CAAC,eAAe,CAAC;aAC5B,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC,CAAA;QAClE,OAAO,IAAa,CAAA;IACtB,CAAC;IAGgB,QAAQ,CAAW;CACrC,CAAA;AADkB;IADhB,QAAQ,CAAC,QAAQ,CAAC;8BACS,QAAQ;sDAAA;AA7BzB,oBAAoB;IADhC,UAAU,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;GACtB,oBAAoB,CA8BhC"}
@@ -1,2 +0,0 @@
1
- import '.';
2
- //# sourceMappingURL=websocket-user-context.spec.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"websocket-user-context.spec.d.ts","sourceRoot":"","sources":["../src/websocket-user-context.spec.ts"],"names":[],"mappings":"AAEA,OAAO,GAAG,CAAA"}
@@ -1,68 +0,0 @@
1
- import { Injector } from '@furystack/inject';
2
- import { IncomingMessage } from 'http';
3
- import '.';
4
- import { HttpUserContext } from '@furystack/rest-service';
5
- import { usingAsync } from '@furystack/utils';
6
- import { WebsocketUserContext } from './websocket-user-context.js';
7
- import { describe, it, expect, vi } from 'vitest';
8
- describe('WebSocket User Context', () => {
9
- const mockUser = { username: 'mock@gmail.com', roles: [] };
10
- const mockAdmin = { username: 'mock@gmail.com', roles: ['admin'] };
11
- describe('isAuthenticated', () => {
12
- it('should authenticate with HttpUserContext and the IncomingMessage', async () => {
13
- await usingAsync(new Injector(), async (i) => {
14
- const authFn = vi.fn(async () => mockUser);
15
- const incomingMessage = {};
16
- i.setExplicitInstance(incomingMessage, IncomingMessage);
17
- i.setExplicitInstance({ authenticateRequest: authFn }, HttpUserContext);
18
- const authResult = await i.getInstance(WebsocketUserContext).isAuthenticated();
19
- expect(authResult).toBeTruthy();
20
- expect(authFn).toBeCalledWith(incomingMessage);
21
- });
22
- });
23
- it('should return false if HttpUserContext throws', async () => {
24
- await usingAsync(new Injector(), async (i) => {
25
- const authFn = vi.fn(() => Promise.reject('Hey! No user here!'));
26
- const incomingMessage = {};
27
- i.setExplicitInstance(incomingMessage, IncomingMessage);
28
- i.setExplicitInstance({ authenticateRequest: authFn }, HttpUserContext);
29
- const authResult = await i.getInstance(WebsocketUserContext).isAuthenticated();
30
- expect(authResult).toBeFalsy();
31
- expect(authFn).toBeCalledWith(incomingMessage);
32
- });
33
- });
34
- });
35
- describe('isAuthorized', () => {
36
- it('should return true if the user has the role', async () => {
37
- await usingAsync(new Injector(), async (i) => {
38
- const authFn = vi.fn(async () => mockAdmin);
39
- const incomingMessage = {};
40
- i.setExplicitInstance(incomingMessage, IncomingMessage);
41
- i.setExplicitInstance({ authenticateRequest: authFn }, HttpUserContext);
42
- const authResult = await i.getInstance(WebsocketUserContext).isAuthorized('admin');
43
- expect(authResult).toBe(true);
44
- });
45
- });
46
- it('should return false if the user does not have the role', async () => {
47
- await usingAsync(new Injector(), async (i) => {
48
- const authFn = vi.fn(async () => mockUser);
49
- const incomingMessage = {};
50
- i.setExplicitInstance(incomingMessage, IncomingMessage);
51
- i.setExplicitInstance({ authenticateRequest: authFn }, HttpUserContext);
52
- const authResult = await i.getInstance(WebsocketUserContext).isAuthorized('admin');
53
- expect(authResult).toBe(false);
54
- });
55
- });
56
- it('should return false if getting the current user throws', async () => {
57
- await usingAsync(new Injector(), async (i) => {
58
- const authFn = vi.fn(() => Promise.reject('Hey! No user here!'));
59
- const incomingMessage = {};
60
- i.setExplicitInstance(incomingMessage, IncomingMessage);
61
- i.setExplicitInstance({ authenticateRequest: authFn }, HttpUserContext);
62
- const authResult = await i.getInstance(WebsocketUserContext).isAuthorized('admin');
63
- expect(authResult).toBe(false);
64
- });
65
- });
66
- });
67
- });
68
- //# sourceMappingURL=websocket-user-context.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"websocket-user-context.spec.js","sourceRoot":"","sources":["../src/websocket-user-context.spec.ts"],"names":[],"mappings":"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"}
@@ -1,73 +0,0 @@
1
- import { Injector } from '@furystack/inject'
2
- import { IncomingMessage } from 'http'
3
- import '.'
4
- import { HttpUserContext } from '@furystack/rest-service'
5
- import { usingAsync } from '@furystack/utils'
6
- import { WebsocketUserContext } from './websocket-user-context.js'
7
- import { describe, it, expect, vi } from 'vitest'
8
-
9
- describe('WebSocket User Context', () => {
10
- const mockUser = { username: 'mock@gmail.com', roles: [] }
11
- const mockAdmin = { username: 'mock@gmail.com', roles: ['admin'] }
12
-
13
- describe('isAuthenticated', () => {
14
- it('should authenticate with HttpUserContext and the IncomingMessage', async () => {
15
- await usingAsync(new Injector(), async (i) => {
16
- const authFn = vi.fn(async () => mockUser)
17
- const incomingMessage = {}
18
- i.setExplicitInstance(incomingMessage, IncomingMessage)
19
- i.setExplicitInstance({ authenticateRequest: authFn }, HttpUserContext)
20
- const authResult = await i.getInstance(WebsocketUserContext).isAuthenticated()
21
- expect(authResult).toBeTruthy()
22
- expect(authFn).toBeCalledWith(incomingMessage)
23
- })
24
- })
25
-
26
- it('should return false if HttpUserContext throws', async () => {
27
- await usingAsync(new Injector(), async (i) => {
28
- const authFn = vi.fn(() => Promise.reject('Hey! No user here!'))
29
- const incomingMessage = {}
30
- i.setExplicitInstance(incomingMessage, IncomingMessage)
31
- i.setExplicitInstance({ authenticateRequest: authFn }, HttpUserContext)
32
- const authResult = await i.getInstance(WebsocketUserContext).isAuthenticated()
33
- expect(authResult).toBeFalsy()
34
- expect(authFn).toBeCalledWith(incomingMessage)
35
- })
36
- })
37
- })
38
-
39
- describe('isAuthorized', () => {
40
- it('should return true if the user has the role', async () => {
41
- await usingAsync(new Injector(), async (i) => {
42
- const authFn = vi.fn(async () => mockAdmin)
43
- const incomingMessage = {}
44
- i.setExplicitInstance(incomingMessage, IncomingMessage)
45
- i.setExplicitInstance({ authenticateRequest: authFn }, HttpUserContext)
46
- const authResult = await i.getInstance(WebsocketUserContext).isAuthorized('admin')
47
- expect(authResult).toBe(true)
48
- })
49
- })
50
-
51
- it('should return false if the user does not have the role', async () => {
52
- await usingAsync(new Injector(), async (i) => {
53
- const authFn = vi.fn(async () => mockUser)
54
- const incomingMessage = {}
55
- i.setExplicitInstance(incomingMessage, IncomingMessage)
56
- i.setExplicitInstance({ authenticateRequest: authFn }, HttpUserContext)
57
- const authResult = await i.getInstance(WebsocketUserContext).isAuthorized('admin')
58
- expect(authResult).toBe(false)
59
- })
60
- })
61
-
62
- it('should return false if getting the current user throws', async () => {
63
- await usingAsync(new Injector(), async (i) => {
64
- const authFn = vi.fn(() => Promise.reject('Hey! No user here!'))
65
- const incomingMessage = {}
66
- i.setExplicitInstance(incomingMessage, IncomingMessage)
67
- i.setExplicitInstance({ authenticateRequest: authFn }, HttpUserContext)
68
- const authResult = await i.getInstance(WebsocketUserContext).isAuthorized('admin')
69
- expect(authResult).toBe(false)
70
- })
71
- })
72
- })
73
- })
@@ -1,37 +0,0 @@
1
- import { IncomingMessage } from 'http'
2
- import type { IdentityContext, User } from '@furystack/core'
3
- import { Injectable, Injected, Injector } from '@furystack/inject'
4
- import { HttpUserContext } from '@furystack/rest-service'
5
-
6
- @Injectable({ lifetime: 'scoped' })
7
- export class WebsocketUserContext implements IdentityContext {
8
- public async isAuthenticated(): Promise<boolean> {
9
- try {
10
- return (await this.getCurrentUser()) ? true : false
11
- } catch (error) {
12
- return false
13
- }
14
- }
15
- public async isAuthorized(...roles: string[]): Promise<boolean> {
16
- try {
17
- const currentUser = await this.getCurrentUser()
18
- for (const role of roles) {
19
- if (!currentUser || !currentUser.roles.some((c) => c === role)) {
20
- return false
21
- }
22
- }
23
- return true
24
- } catch (error) {
25
- return false
26
- }
27
- }
28
- public async getCurrentUser<TUser extends User>(): Promise<TUser> {
29
- const user = await this.injector
30
- .getInstance(HttpUserContext)
31
- .authenticateRequest(this.injector.getInstance(IncomingMessage))
32
- return user as TUser
33
- }
34
-
35
- @Injected(Injector)
36
- private readonly injector!: Injector
37
- }