@lsdsoftware/janus-client-node 1.0.4 → 1.0.5

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/client.js CHANGED
@@ -8,16 +8,31 @@ export function createClient(websocketUrl, websocketOpts) {
8
8
  const pendingTxs = new Map();
9
9
  return {
10
10
  requestSubject,
11
- send$: requestSubject.pipe(rxjs.concatMap(request => {
11
+ send$: requestSubject.pipe(rxjs.mergeMap(request => {
12
12
  const txId = String(Math.random());
13
13
  request.message.transaction = txId;
14
- conn.send(JSON.stringify(request.message), err => {
14
+ return new rxjs.Observable(subscriber => conn.send(JSON.stringify(request.message), err => {
15
+ subscriber.next(err);
16
+ subscriber.complete();
17
+ })).pipe(rxjs.exhaustMap(err => {
15
18
  if (err) {
16
19
  request.reject(err);
20
+ return rxjs.EMPTY;
17
21
  }
18
22
  else {
19
- pendingTxs.set(txId, response => {
20
- pendingTxs.delete(txId);
23
+ function waitResponse(timeout) {
24
+ return new rxjs.Observable(subscriber => {
25
+ pendingTxs.set(txId, response => {
26
+ subscriber.next(response);
27
+ subscriber.complete();
28
+ });
29
+ return () => pendingTxs.delete(txId);
30
+ }).pipe(timeout == Infinity ? rxjs.identity : rxjs.timeout({
31
+ first: timeout,
32
+ with: () => rxjs.of({ janus: 'error', error: { code: 408, reason: 'Request timeout' } })
33
+ }));
34
+ }
35
+ return waitResponse(30_000).pipe(rxjs.exhaustMap(response => rxjs.iif(() => response.janus == 'ack', waitResponse(request.timeout ?? 300_000), rxjs.of(response))), rxjs.exhaustMap(response => {
21
36
  if (response.janus == 'error') {
22
37
  const { code, reason } = response.error;
23
38
  request.reject(makeJanusError(request, code, reason));
@@ -25,16 +40,16 @@ export function createClient(websocketUrl, websocketOpts) {
25
40
  else {
26
41
  request.fulfill(response);
27
42
  }
28
- });
43
+ return rxjs.EMPTY;
44
+ }));
29
45
  }
30
- });
31
- return rxjs.EMPTY;
46
+ }));
32
47
  }), rxjs.share()),
33
48
  receive$: conn.message$.pipe(rxjs.concatMap(event => {
34
49
  try {
35
50
  assert(typeof event.data == 'string');
36
51
  const message = JSON.parse(event.data);
37
- if (message.janus == 'event' && typeof message.transaction == 'undefined') {
52
+ if (typeof message.transaction == 'undefined') {
38
53
  return rxjs.of(message);
39
54
  }
40
55
  else {
@@ -53,7 +68,10 @@ export function createClient(websocketUrl, websocketOpts) {
53
68
  return rxjs.EMPTY;
54
69
  }
55
70
  }), rxjs.share()),
56
- close$: conn.close$,
71
+ close$: conn.close$.pipe(rxjs.tap(() => {
72
+ for (const pending of pendingTxs.values())
73
+ pending({ janus: 'error', error: { code: 503, reason: 'Connection closed before response was received' } });
74
+ })),
57
75
  close: conn.close.bind(conn)
58
76
  };
59
77
  }));
@@ -35,7 +35,7 @@ export function createPluginHandle(session, plugin) {
35
35
  }), rxjs.share()),
36
36
  detach() {
37
37
  session.requestSubject.next({
38
- message: { janus: "detach" },
38
+ message: { janus: "detach", handle_id: handleId },
39
39
  stacktrace: new Error(),
40
40
  fulfill: rxjs.noop,
41
41
  reject: err => console.error('JanusPluginHandle detach fail', handleId, err)
package/dist/session.js CHANGED
@@ -11,7 +11,7 @@ export function createSession(client, { keepAliveInterval = 45_000 } = {}) {
11
11
  return rxjs.EMPTY;
12
12
  }), rxjs.share()),
13
13
  receive$: client.receive$.pipe(rxjs.filter(message => message.session_id == sessionId), rxjs.share()),
14
- keepAlive$: requestSubject.pipe(rxjs.switchMap(() => rxjs.interval(keepAliveInterval).pipe(rxjs.switchMap(() => new rxjs.Observable(subscriber => client.requestSubject.next({
14
+ keepAlive$: requestSubject.pipe(rxjs.startWith(null), rxjs.switchMap(() => rxjs.interval(keepAliveInterval).pipe(rxjs.switchMap(() => new rxjs.Observable(subscriber => client.requestSubject.next({
15
15
  message: { janus: "keepalive", session_id: sessionId },
16
16
  stacktrace: new Error(),
17
17
  fulfill() {
@@ -24,7 +24,7 @@ export function createSession(client, { keepAliveInterval = 45_000 } = {}) {
24
24
  }))))), rxjs.share()),
25
25
  destroy() {
26
26
  client.requestSubject.next({
27
- message: { janus: 'destroy' },
27
+ message: { janus: 'destroy', session_id: sessionId },
28
28
  stacktrace: new Error(),
29
29
  fulfill: rxjs.noop,
30
30
  reject: err => console.error('JanusSession destroy fail', sessionId, err)
package/dist/types.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export interface JanusRequest {
2
2
  readonly message: Record<string, unknown>;
3
+ readonly timeout?: number;
3
4
  readonly stacktrace: Error;
4
5
  fulfill(response: Record<string, unknown>): void;
5
6
  reject(err: Error): void;
package/dist/util.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import * as rxjs from "rxjs";
2
2
  import { JanusRequest } from "./types.js";
3
- export declare function request<T>(requestSubject: rxjs.Subject<JanusRequest>, message: Record<string, unknown>): rxjs.Observable<T>;
3
+ export declare function request<T>(requestSubject: rxjs.Subject<JanusRequest>, message: Record<string, unknown>, { timeout }?: {
4
+ timeout?: number;
5
+ }): rxjs.Observable<T>;
4
6
  export declare function makeJanusError({ stacktrace, message }: JanusRequest, code: number, reason: string): Error & {
5
7
  code: number;
6
8
  };
package/dist/util.js CHANGED
@@ -1,8 +1,9 @@
1
1
  import * as rxjs from "rxjs";
2
- export function request(requestSubject, message) {
2
+ export function request(requestSubject, message, { timeout } = {}) {
3
3
  const stacktrace = new Error();
4
4
  return new rxjs.Observable(subscriber => requestSubject.next({
5
5
  message,
6
+ timeout,
6
7
  stacktrace,
7
8
  fulfill(response) {
8
9
  subscriber.next(response);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lsdsoftware/janus-client-node",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "Janus WebSocket client for Node, built on RxJS observables",
5
5
  "keywords": [
6
6
  "janus",
package/src/client.ts CHANGED
@@ -14,25 +14,55 @@ export function createClient(websocketUrl: string, websocketOpts?: ClientOptions
14
14
  return {
15
15
  requestSubject,
16
16
  send$: requestSubject.pipe(
17
- rxjs.concatMap(request => {
17
+ rxjs.mergeMap(request => {
18
18
  const txId = String(Math.random())
19
19
  request.message.transaction = txId
20
- conn.send(JSON.stringify(request.message), err => {
21
- if (err) {
22
- request.reject(err)
23
- } else {
24
- pendingTxs.set(txId, response => {
25
- pendingTxs.delete(txId)
26
- if (response.janus == 'error') {
27
- const { code, reason } = response.error as { code: number, reason: string }
28
- request.reject(makeJanusError(request, code, reason))
29
- } else {
30
- request.fulfill(response)
20
+ return new rxjs.Observable<Error | undefined>(subscriber =>
21
+ conn.send(JSON.stringify(request.message), err => {
22
+ subscriber.next(err)
23
+ subscriber.complete()
24
+ })
25
+ ).pipe(
26
+ rxjs.exhaustMap(err => {
27
+ if (err) {
28
+ request.reject(err)
29
+ return rxjs.EMPTY
30
+ } else {
31
+ function waitResponse(timeout: number) {
32
+ return new rxjs.Observable<Record<string, unknown>>(subscriber => {
33
+ pendingTxs.set(txId, response => {
34
+ subscriber.next(response)
35
+ subscriber.complete()
36
+ })
37
+ return () => pendingTxs.delete(txId)
38
+ }).pipe(
39
+ timeout == Infinity ? rxjs.identity : rxjs.timeout({
40
+ first: timeout,
41
+ with: () => rxjs.of({ janus: 'error', error: { code: 408, reason: 'Request timeout' } })
42
+ })
43
+ )
31
44
  }
32
- })
33
- }
34
- })
35
- return rxjs.EMPTY
45
+ return waitResponse(30_000).pipe(
46
+ rxjs.exhaustMap(response =>
47
+ rxjs.iif(
48
+ () => response.janus == 'ack',
49
+ waitResponse(request.timeout ?? 300_000),
50
+ rxjs.of(response)
51
+ )
52
+ ),
53
+ rxjs.exhaustMap(response => {
54
+ if (response.janus == 'error') {
55
+ const { code, reason } = response.error as { code: number, reason: string }
56
+ request.reject(makeJanusError(request, code, reason))
57
+ } else {
58
+ request.fulfill(response)
59
+ }
60
+ return rxjs.EMPTY
61
+ })
62
+ )
63
+ }
64
+ })
65
+ )
36
66
  }),
37
67
  rxjs.share()
38
68
  ),
@@ -41,7 +71,7 @@ export function createClient(websocketUrl: string, websocketOpts?: ClientOptions
41
71
  try {
42
72
  assert(typeof event.data == 'string')
43
73
  const message = JSON.parse(event.data) as Record<string, unknown>
44
- if (message.janus == 'event' && typeof message.transaction == 'undefined') {
74
+ if (typeof message.transaction == 'undefined') {
45
75
  return rxjs.of(message)
46
76
  } else {
47
77
  const pending = pendingTxs.get(message.transaction)
@@ -59,7 +89,12 @@ export function createClient(websocketUrl: string, websocketOpts?: ClientOptions
59
89
  }),
60
90
  rxjs.share()
61
91
  ),
62
- close$: conn.close$,
92
+ close$: conn.close$.pipe(
93
+ rxjs.tap(() => {
94
+ for (const pending of pendingTxs.values())
95
+ pending({ janus: 'error', error: { code: 503, reason: 'Connection closed before response was received' }})
96
+ })
97
+ ),
63
98
  close: conn.close.bind(conn)
64
99
  }
65
100
  })
@@ -50,7 +50,7 @@ export function createPluginHandle(
50
50
  ),
51
51
  detach() {
52
52
  session.requestSubject.next({
53
- message: { janus: "detach" },
53
+ message: { janus: "detach", handle_id: handleId },
54
54
  stacktrace: new Error(),
55
55
  fulfill: rxjs.noop,
56
56
  reject: err => console.error('JanusPluginHandle detach fail', handleId, err)
package/src/session.ts CHANGED
@@ -29,6 +29,7 @@ export function createSession(
29
29
  rxjs.share()
30
30
  ),
31
31
  keepAlive$: requestSubject.pipe(
32
+ rxjs.startWith(null),
32
33
  rxjs.switchMap(() =>
33
34
  rxjs.interval(keepAliveInterval).pipe(
34
35
  rxjs.switchMap(() =>
@@ -52,7 +53,7 @@ export function createSession(
52
53
  ),
53
54
  destroy() {
54
55
  client.requestSubject.next({
55
- message: { janus: 'destroy' },
56
+ message: { janus: 'destroy', session_id: sessionId },
56
57
  stacktrace: new Error(),
57
58
  fulfill: rxjs.noop,
58
59
  reject: err => console.error('JanusSession destroy fail', sessionId, err)
package/src/types.ts CHANGED
@@ -1,6 +1,7 @@
1
1
 
2
2
  export interface JanusRequest {
3
3
  readonly message: Record<string, unknown>
4
+ readonly timeout?: number
4
5
  readonly stacktrace: Error
5
6
  fulfill(response: Record<string, unknown>): void
6
7
  reject(err: Error): void
package/src/util.ts CHANGED
@@ -3,12 +3,14 @@ import { JanusRequest } from "./types.js"
3
3
 
4
4
  export function request<T>(
5
5
  requestSubject: rxjs.Subject<JanusRequest>,
6
- message: Record<string, unknown>
6
+ message: Record<string, unknown>,
7
+ { timeout }: { timeout?: number } = {}
7
8
  ) {
8
9
  const stacktrace = new Error()
9
10
  return new rxjs.Observable<T>(subscriber =>
10
11
  requestSubject.next({
11
12
  message,
13
+ timeout,
12
14
  stacktrace,
13
15
  fulfill(response) {
14
16
  subscriber.next(response as T)