@fishjam-cloud/js-server-sdk 0.1.2 → 0.3.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.
package/README.md CHANGED
@@ -1,6 +1,8 @@
1
+ <img src="../../.github/images/fishjam-card.png" width="100%">
2
+
1
3
  # Fishjam Cloud Server SDK for JavaScript
2
4
 
3
- JavaScript server-side SDK for [Fishjam Cloud](https://cloud.fishjam.stream).
5
+ JavaScript server-side SDK for [Fishjam Cloud](https://fishjam.io).
4
6
 
5
7
  ## Installation
6
8
 
@@ -29,10 +31,12 @@ yarn docs
29
31
 
30
32
  See [examples](https://github.com/fishjam-cloud/js-server-sdk/tree/main/examples) directory.
31
33
 
32
- ## Copyright and License
34
+ ## License
35
+
36
+ Licensed under the [Apache License, Version 2.0](LICENSE)
33
37
 
34
- Copyright 2024, [Software Mansion](https://swmansion.com/?utm_source=git&utm_medium=readme&utm_campaign=fishjam-js-server-sdk)
38
+ ## Fishjam Cloud is created by Software Mansion
35
39
 
36
- [![Software Mansion](https://logo.swmansion.com/logo?color=white&variant=desktop&width=200&tag=fishjam-github)](https://swmansion.com/?utm_source=git&utm_medium=readme&utm_campaign=fishjam-js-server-sdk)
40
+ Since 2012 [Software Mansion](https://swmansion.com) is a software agency with experience in building web and mobile apps. We are Core React Native Contributors and experts in dealing with all kinds of React Native issues. We can help you build your next dream product – [Hire us](https://swmansion.com/contact/projects?utm_source=fishjam&utm_medium=js-server-readme).
37
41
 
38
- Licensed under the [Apache License, Version 2.0](LICENSE)
42
+ [![Software Mansion](https://logo.swmansion.com/logo?color=white&variant=desktop&width=200&tag=react-client)](https://swmansion.com/contact/projects?utm_source=fishjam&utm_medium=js-server-readme)
@@ -0,0 +1,8 @@
1
+ // src/proto.ts
2
+ import { ServerMessage, ServerMessage_AuthRequest, ServerMessage_EventType } from "@fishjam-cloud/fishjam-proto";
3
+
4
+ export {
5
+ ServerMessage,
6
+ ServerMessage_AuthRequest,
7
+ ServerMessage_EventType
8
+ };
package/dist/index.d.mts CHANGED
@@ -2,6 +2,7 @@ import { Peer, RoomConfig, PeerOptions } from '@fishjam-cloud/fishjam-openapi';
2
2
  export { Peer, PeerOptions, PeerStatus, RoomConfig } from '@fishjam-cloud/fishjam-openapi';
3
3
  import TypedEmitter from 'typed-emitter';
4
4
  import { ServerMessage } from '@fishjam-cloud/fishjam-proto';
5
+ import axios from 'axios';
5
6
 
6
7
  type Room = {
7
8
  id: string;
@@ -10,7 +11,7 @@ type Room = {
10
11
  };
11
12
  type FishjamConfig = {
12
13
  fishjamUrl: string;
13
- serverToken: string;
14
+ managementToken: string;
14
15
  };
15
16
 
16
17
  declare const allowedNotifications: readonly ["roomCreated", "roomDeleted", "roomCrashed", "peerAdded", "peerDeleted", "peerConnected", "peerDisconnected", "peerMetadataUpdated", "peerCrashed", "trackAdded", "trackRemoved", "trackMetadataUpdated"];
@@ -31,32 +32,35 @@ declare class FishjamClient {
31
32
  constructor(config: FishjamConfig);
32
33
  createPeer(roomId: string, options?: PeerOptions): Promise<{
33
34
  peer: Peer;
34
- token: string;
35
+ peerToken: string;
35
36
  }>;
36
37
  createRoom(config?: RoomConfig): Promise<Room>;
37
38
  getAllRooms(): Promise<Room[]>;
38
39
  getRoom(roomId: string): Promise<Room>;
39
40
  deletePeer(roomId: string, peerId: string): Promise<void>;
40
41
  deleteRoom(roomId: string): Promise<void>;
42
+ refreshPeerToken(roomId: string, peerId: string): Promise<string>;
41
43
  }
42
44
 
43
- declare class BaseException extends Error {
44
- constructor(message: string);
45
+ declare class FishjamBaseException extends Error {
46
+ statusCode: number;
47
+ constructor(error: axios.AxiosError<Record<string, string>>);
45
48
  }
46
- declare class BadRequestException extends BaseException {
47
- constructor();
49
+ declare class BadRequestException extends FishjamBaseException {
48
50
  }
49
- declare class UnauthorizedException extends BaseException {
50
- constructor();
51
+ declare class UnauthorizedException extends FishjamBaseException {
51
52
  }
52
- declare class RoomNotFoundException extends BaseException {
53
- constructor();
53
+ declare class ForbiddenException extends FishjamBaseException {
54
54
  }
55
- declare class PeerNotFoundException extends BaseException {
56
- constructor();
55
+ declare class RoomNotFoundException extends FishjamBaseException {
57
56
  }
58
- declare class ServiceUnavailableException extends BaseException {
59
- constructor();
57
+ declare class FishjamNotFoundException extends FishjamBaseException {
58
+ }
59
+ declare class PeerNotFoundException extends FishjamBaseException {
60
+ }
61
+ declare class ServiceUnavailableException extends FishjamBaseException {
62
+ }
63
+ declare class UnknownException extends FishjamBaseException {
60
64
  }
61
65
 
62
- export { BadRequestException, FishjamClient, type FishjamConfig, FishjamWSNotifier, PeerNotFoundException, type Room, RoomNotFoundException, ServiceUnavailableException, UnauthorizedException };
66
+ export { BadRequestException, FishjamBaseException, FishjamClient, type FishjamConfig, FishjamNotFoundException, FishjamWSNotifier, ForbiddenException, PeerNotFoundException, type Room, RoomNotFoundException, ServiceUnavailableException, UnauthorizedException, UnknownException };
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ import { Peer, RoomConfig, PeerOptions } from '@fishjam-cloud/fishjam-openapi';
2
2
  export { Peer, PeerOptions, PeerStatus, RoomConfig } from '@fishjam-cloud/fishjam-openapi';
3
3
  import TypedEmitter from 'typed-emitter';
4
4
  import { ServerMessage } from '@fishjam-cloud/fishjam-proto';
5
+ import axios from 'axios';
5
6
 
6
7
  type Room = {
7
8
  id: string;
@@ -10,7 +11,7 @@ type Room = {
10
11
  };
11
12
  type FishjamConfig = {
12
13
  fishjamUrl: string;
13
- serverToken: string;
14
+ managementToken: string;
14
15
  };
15
16
 
16
17
  declare const allowedNotifications: readonly ["roomCreated", "roomDeleted", "roomCrashed", "peerAdded", "peerDeleted", "peerConnected", "peerDisconnected", "peerMetadataUpdated", "peerCrashed", "trackAdded", "trackRemoved", "trackMetadataUpdated"];
@@ -31,32 +32,35 @@ declare class FishjamClient {
31
32
  constructor(config: FishjamConfig);
32
33
  createPeer(roomId: string, options?: PeerOptions): Promise<{
33
34
  peer: Peer;
34
- token: string;
35
+ peerToken: string;
35
36
  }>;
36
37
  createRoom(config?: RoomConfig): Promise<Room>;
37
38
  getAllRooms(): Promise<Room[]>;
38
39
  getRoom(roomId: string): Promise<Room>;
39
40
  deletePeer(roomId: string, peerId: string): Promise<void>;
40
41
  deleteRoom(roomId: string): Promise<void>;
42
+ refreshPeerToken(roomId: string, peerId: string): Promise<string>;
41
43
  }
42
44
 
43
- declare class BaseException extends Error {
44
- constructor(message: string);
45
+ declare class FishjamBaseException extends Error {
46
+ statusCode: number;
47
+ constructor(error: axios.AxiosError<Record<string, string>>);
45
48
  }
46
- declare class BadRequestException extends BaseException {
47
- constructor();
49
+ declare class BadRequestException extends FishjamBaseException {
48
50
  }
49
- declare class UnauthorizedException extends BaseException {
50
- constructor();
51
+ declare class UnauthorizedException extends FishjamBaseException {
51
52
  }
52
- declare class RoomNotFoundException extends BaseException {
53
- constructor();
53
+ declare class ForbiddenException extends FishjamBaseException {
54
54
  }
55
- declare class PeerNotFoundException extends BaseException {
56
- constructor();
55
+ declare class RoomNotFoundException extends FishjamBaseException {
57
56
  }
58
- declare class ServiceUnavailableException extends BaseException {
59
- constructor();
57
+ declare class FishjamNotFoundException extends FishjamBaseException {
58
+ }
59
+ declare class PeerNotFoundException extends FishjamBaseException {
60
+ }
61
+ declare class ServiceUnavailableException extends FishjamBaseException {
62
+ }
63
+ declare class UnknownException extends FishjamBaseException {
60
64
  }
61
65
 
62
- export { BadRequestException, FishjamClient, type FishjamConfig, FishjamWSNotifier, PeerNotFoundException, type Room, RoomNotFoundException, ServiceUnavailableException, UnauthorizedException };
66
+ export { BadRequestException, FishjamBaseException, FishjamClient, type FishjamConfig, FishjamNotFoundException, FishjamWSNotifier, ForbiddenException, PeerNotFoundException, type Room, RoomNotFoundException, ServiceUnavailableException, UnauthorizedException, UnknownException };
package/dist/index.js CHANGED
@@ -1 +1,249 @@
1
- "use strict";var S=Object.create;var v=Object.defineProperty;var N=Object.getOwnPropertyDescriptor;var T=Object.getOwnPropertyNames;var M=Object.getPrototypeOf,_=Object.prototype.hasOwnProperty;var j=(t,e)=>{for(var o in e)v(t,o,{get:e[o],enumerable:!0})},y=(t,e,o,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of T(e))!_.call(t,s)&&s!==o&&v(t,s,{get:()=>e[s],enumerable:!(r=N(e,s))||r.enumerable});return t};var E=(t,e,o)=>(o=t!=null?S(M(t)):{},y(e||!t||!t.__esModule?v(o,"default",{value:t,enumerable:!0}):o,t)),U=t=>y(v({},"__esModule",{value:!0}),t);var H={};j(H,{BadRequestException:()=>d,FishjamClient:()=>w,FishjamWSNotifier:()=>g,Peer:()=>i.Peer,PeerNotFoundException:()=>f,PeerOptions:()=>i.PeerOptions,PeerStatus:()=>i.PeerStatus,RoomConfig:()=>i.RoomConfig,RoomNotFoundException:()=>u,ServiceUnavailableException:()=>h,UnauthorizedException:()=>l});module.exports=U(H);var i=require("@fishjam-cloud/fishjam-openapi");var x=E(require("websocket")),P=require("events");var n=require("@fishjam-cloud/fishjam-proto");var b=t=>{let e=new URL(t);return e.protocol=e.protocol.replace("http","ws"),e.href};var F=["roomCreated","roomDeleted","roomCrashed","peerAdded","peerDeleted","peerConnected","peerDisconnected","peerMetadataUpdated","peerCrashed","trackAdded","trackRemoved","trackMetadataUpdated"],g=class extends P.EventEmitter{client;constructor(e,o,r,s){super(),this.client=new x.client;let R=`${b(e.fishjamUrl)}/socket/server/websocket`;this.client.on("connectFailed",p=>s(p)),this.client.on("connect",p=>this.setupConnection(p,e.serverToken,o,r)),this.client.connect(R)}dispatchNotification(e){if(e.type=="utf8"){console.warn("UTF-8 is an invalid notification type");return}try{let o=n.ServerMessage.toJSON(n.ServerMessage.decode(e.binaryData)),[r]=Object.keys(o);if(!this.isAllowedNotification(r))return;this.emit(r,o)}catch(o){console.error("Couldn't decode websocket server message."),console.error(o),console.error(e)}}setupConnection(e,o,r,s){let R=n.ServerMessage.encode({authRequest:{token:o}}).finish(),p=n.ServerMessage.encode({subscribeRequest:{eventType:n.ServerMessage_EventType.EVENT_TYPE_SERVER_NOTIFICATION}}).finish();e.send(R),e.send(p),e.on("message",m=>this.dispatchNotification(m)),e.on("error",m=>r(m)),e.on("close",(m,C)=>s(m,C))}isAllowedNotification(e){return F.includes(e)}};var k=E(require("axios")),A=require("@fishjam-cloud/fishjam-openapi");var a=class extends Error{constructor(e){super(e),this.name=this.constructor.name}},d=class extends a{constructor(){super("Invalid request body structure")}},l=class extends a{constructor(){super("Unauthorized")}},u=class extends a{constructor(){super("Room not found")}},f=class extends a{constructor(){super("Peer not found")}},h=class extends a{constructor(){super("Service unavailable")}};var c=(t,e)=>{switch(t){case 400:throw new d;case 401:throw new l;case 404:switch(e){case"peer":throw new f;case"room":throw new u;default:return}case 503:throw new h;default:return}};var w=class{roomApi;constructor(e){let o=k.default.create({validateStatus:r=>[200,201,400,401,404,503].includes(r),headers:{Authorization:`Bearer ${e.serverToken}`}});this.roomApi=new A.RoomApi(void 0,e.fishjamUrl,o)}async createPeer(e,o={}){let r=await this.roomApi.addPeer(e,{type:"webrtc",options:o});c(r.status);let{data:{data:s}}=r;return{peer:s.peer,token:s.token}}async createRoom(e={}){let o=await this.roomApi.createRoom(e);c(o.status);let{data:{data:{room:{components:r,...s}}}}=o;return s}async getAllRooms(){let e=await this.roomApi.getAllRooms();return c(e.status),e.data.data.map(({components:o,...r})=>r)??[]}async getRoom(e){let o=await this.roomApi.getRoom(e);c(o.status,"room");let{components:r,...s}=o.data.data;return s}async deletePeer(e,o){let r=await this.roomApi.deletePeer(e,o);c(r.status,"peer")}async deleteRoom(e){let o=await this.roomApi.deleteRoom(e);c(o.status,"room")}};0&&(module.exports={BadRequestException,FishjamClient,FishjamWSNotifier,Peer,PeerNotFoundException,PeerOptions,PeerStatus,RoomConfig,RoomNotFoundException,ServiceUnavailableException,UnauthorizedException});
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var src_exports = {};
32
+ __export(src_exports, {
33
+ BadRequestException: () => BadRequestException,
34
+ FishjamBaseException: () => FishjamBaseException,
35
+ FishjamClient: () => FishjamClient,
36
+ FishjamNotFoundException: () => FishjamNotFoundException,
37
+ FishjamWSNotifier: () => FishjamWSNotifier,
38
+ ForbiddenException: () => ForbiddenException,
39
+ Peer: () => import_fishjam_openapi2.Peer,
40
+ PeerNotFoundException: () => PeerNotFoundException,
41
+ PeerOptions: () => import_fishjam_openapi2.PeerOptions,
42
+ PeerStatus: () => import_fishjam_openapi2.PeerStatus,
43
+ RoomConfig: () => import_fishjam_openapi2.RoomConfig,
44
+ RoomNotFoundException: () => RoomNotFoundException,
45
+ ServiceUnavailableException: () => ServiceUnavailableException,
46
+ UnauthorizedException: () => UnauthorizedException,
47
+ UnknownException: () => UnknownException
48
+ });
49
+ module.exports = __toCommonJS(src_exports);
50
+ var import_fishjam_openapi2 = require("@fishjam-cloud/fishjam-openapi");
51
+
52
+ // src/ws_notifier.ts
53
+ var WebSocket = __toESM(require("websocket"));
54
+ var import_events = require("events");
55
+
56
+ // src/proto.ts
57
+ var import_fishjam_proto = require("@fishjam-cloud/fishjam-proto");
58
+
59
+ // src/utlis.ts
60
+ var httpToWebsocket = (httpUrl) => {
61
+ const url = new URL(httpUrl);
62
+ url.protocol = url.protocol.replace("http", "ws");
63
+ return url.href;
64
+ };
65
+
66
+ // src/ws_notifier.ts
67
+ var allowedNotifications = [
68
+ "roomCreated",
69
+ "roomDeleted",
70
+ "roomCrashed",
71
+ "peerAdded",
72
+ "peerDeleted",
73
+ "peerConnected",
74
+ "peerDisconnected",
75
+ "peerMetadataUpdated",
76
+ "peerCrashed",
77
+ "trackAdded",
78
+ "trackRemoved",
79
+ "trackMetadataUpdated"
80
+ ];
81
+ var FishjamWSNotifier = class extends import_events.EventEmitter {
82
+ client;
83
+ constructor(config, onError, onClose, onConnectionFailed) {
84
+ super();
85
+ this.client = new WebSocket.client();
86
+ const fishjamUrl = `${httpToWebsocket(config.fishjamUrl)}/socket/server/websocket`;
87
+ this.client.on("connectFailed", (message) => onConnectionFailed(message));
88
+ this.client.on(
89
+ "connect",
90
+ (connection) => this.setupConnection(connection, config.managementToken, onError, onClose)
91
+ );
92
+ this.client.connect(fishjamUrl);
93
+ }
94
+ dispatchNotification(message) {
95
+ if (message.type == "utf8") {
96
+ console.warn("UTF-8 is an invalid notification type");
97
+ return;
98
+ }
99
+ try {
100
+ const decodedMessage = import_fishjam_proto.ServerMessage.toJSON(import_fishjam_proto.ServerMessage.decode(message.binaryData));
101
+ const [notification] = Object.keys(decodedMessage);
102
+ if (!this.isAllowedNotification(notification)) return;
103
+ this.emit(notification, decodedMessage);
104
+ } catch (e) {
105
+ console.error("Couldn't decode websocket server message.");
106
+ console.error(e);
107
+ console.error(message);
108
+ }
109
+ }
110
+ setupConnection(connection, serverToken, onError, onClose) {
111
+ const auth = import_fishjam_proto.ServerMessage.encode({ authRequest: { token: serverToken } }).finish();
112
+ const subscription = import_fishjam_proto.ServerMessage.encode({
113
+ subscribeRequest: { eventType: import_fishjam_proto.ServerMessage_EventType.EVENT_TYPE_SERVER_NOTIFICATION }
114
+ }).finish();
115
+ connection.send(auth);
116
+ connection.send(subscription);
117
+ connection.on("message", (message) => this.dispatchNotification(message));
118
+ connection.on("error", (error) => onError(error));
119
+ connection.on("close", (code, reason) => onClose(code, reason));
120
+ }
121
+ isAllowedNotification(notification) {
122
+ return allowedNotifications.includes(notification);
123
+ }
124
+ };
125
+
126
+ // src/client.ts
127
+ var import_axios = __toESM(require("axios"));
128
+ var import_fishjam_openapi = require("@fishjam-cloud/fishjam-openapi");
129
+
130
+ // src/exceptions/index.ts
131
+ var FishjamBaseException = class extends Error {
132
+ statusCode;
133
+ constructor(error) {
134
+ super(error.response?.data["detail"] ?? error.response?.data["errors"] ?? "Unknown error");
135
+ this.statusCode = error.response?.status ?? 500;
136
+ }
137
+ };
138
+ var BadRequestException = class extends FishjamBaseException {
139
+ };
140
+ var UnauthorizedException = class extends FishjamBaseException {
141
+ };
142
+ var ForbiddenException = class extends FishjamBaseException {
143
+ };
144
+ var RoomNotFoundException = class extends FishjamBaseException {
145
+ };
146
+ var FishjamNotFoundException = class extends FishjamBaseException {
147
+ };
148
+ var PeerNotFoundException = class extends FishjamBaseException {
149
+ };
150
+ var ServiceUnavailableException = class extends FishjamBaseException {
151
+ };
152
+ var UnknownException = class extends FishjamBaseException {
153
+ };
154
+
155
+ // src/exceptions/mapper.ts
156
+ var raiseExceptions = (error, entity) => {
157
+ switch (error.response?.status) {
158
+ case 400:
159
+ throw new BadRequestException(error);
160
+ case 401:
161
+ throw new UnauthorizedException(error);
162
+ case 404:
163
+ switch (entity) {
164
+ case "peer":
165
+ throw new PeerNotFoundException(error);
166
+ case "room":
167
+ throw new RoomNotFoundException(error);
168
+ default:
169
+ throw new FishjamNotFoundException(error);
170
+ }
171
+ case 502:
172
+ throw new UnknownException(error);
173
+ case 503:
174
+ throw new ServiceUnavailableException(error);
175
+ default:
176
+ throw new UnknownException(error);
177
+ }
178
+ };
179
+
180
+ // src/client.ts
181
+ var FishjamClient = class {
182
+ roomApi;
183
+ constructor(config) {
184
+ const client2 = import_axios.default.create({
185
+ headers: {
186
+ Authorization: `Bearer ${config.managementToken}`
187
+ }
188
+ });
189
+ this.roomApi = new import_fishjam_openapi.RoomApi(void 0, config.fishjamUrl, client2);
190
+ }
191
+ async createPeer(roomId, options = {}) {
192
+ const response = await this.roomApi.addPeer(roomId, {
193
+ type: "webrtc",
194
+ options
195
+ }).catch(raiseExceptions);
196
+ const {
197
+ data: { data }
198
+ } = response;
199
+ return { peer: data.peer, peerToken: data.token };
200
+ }
201
+ async createRoom(config = {}) {
202
+ const response = await this.roomApi.createRoom(config).catch(raiseExceptions);
203
+ const {
204
+ data: {
205
+ data: {
206
+ room: { components: _, ...room }
207
+ }
208
+ }
209
+ } = response;
210
+ return room;
211
+ }
212
+ async getAllRooms() {
213
+ const getAllRoomsRepsonse = await this.roomApi.getAllRooms().catch(raiseExceptions);
214
+ return getAllRoomsRepsonse.data.data.map(({ components: _, ...room }) => room) ?? [];
215
+ }
216
+ async getRoom(roomId) {
217
+ const getRoomResponse = await this.roomApi.getRoom(roomId).catch((error) => raiseExceptions(error, "room"));
218
+ const { components: _, ...room } = getRoomResponse.data.data;
219
+ return room;
220
+ }
221
+ async deletePeer(roomId, peerId) {
222
+ await this.roomApi.deletePeer(roomId, peerId).catch((error) => raiseExceptions(error, "peer"));
223
+ }
224
+ async deleteRoom(roomId) {
225
+ await this.roomApi.deleteRoom(roomId).catch((error) => raiseExceptions(error, "room"));
226
+ }
227
+ async refreshPeerToken(roomId, peerId) {
228
+ const refreshTokenResponse = await this.roomApi.refreshToken(roomId, peerId).catch((error) => raiseExceptions(error, "peer"));
229
+ return refreshTokenResponse.data.data.token;
230
+ }
231
+ };
232
+ // Annotate the CommonJS export names for ESM import in node:
233
+ 0 && (module.exports = {
234
+ BadRequestException,
235
+ FishjamBaseException,
236
+ FishjamClient,
237
+ FishjamNotFoundException,
238
+ FishjamWSNotifier,
239
+ ForbiddenException,
240
+ Peer,
241
+ PeerNotFoundException,
242
+ PeerOptions,
243
+ PeerStatus,
244
+ RoomConfig,
245
+ RoomNotFoundException,
246
+ ServiceUnavailableException,
247
+ UnauthorizedException,
248
+ UnknownException
249
+ });
package/dist/index.mjs CHANGED
@@ -1 +1,202 @@
1
- import{a as p,c as g}from"./chunk-PVJVFZZS.mjs";import{Peer as V,PeerStatus as $,RoomConfig as J,PeerOptions as L}from"@fishjam-cloud/fishjam-openapi";import*as y from"websocket";import{EventEmitter as b}from"events";var R=r=>{let e=new URL(r);return e.protocol=e.protocol.replace("http","ws"),e.href};var x=["roomCreated","roomDeleted","roomCrashed","peerAdded","peerDeleted","peerConnected","peerDisconnected","peerMetadataUpdated","peerCrashed","trackAdded","trackRemoved","trackMetadataUpdated"],v=class extends b{client;constructor(e,o,t,s){super(),this.client=new y.client;let h=`${R(e.fishjamUrl)}/socket/server/websocket`;this.client.on("connectFailed",a=>s(a)),this.client.on("connect",a=>this.setupConnection(a,e.serverToken,o,t)),this.client.connect(h)}dispatchNotification(e){if(e.type=="utf8"){console.warn("UTF-8 is an invalid notification type");return}try{let o=p.toJSON(p.decode(e.binaryData)),[t]=Object.keys(o);if(!this.isAllowedNotification(t))return;this.emit(t,o)}catch(o){console.error("Couldn't decode websocket server message."),console.error(o),console.error(e)}}setupConnection(e,o,t,s){let h=p.encode({authRequest:{token:o}}).finish(),a=p.encode({subscribeRequest:{eventType:g.EVENT_TYPE_SERVER_NOTIFICATION}}).finish();e.send(h),e.send(a),e.on("message",c=>this.dispatchNotification(c)),e.on("error",c=>t(c)),e.on("close",(c,E)=>s(c,E))}isAllowedNotification(e){return x.includes(e)}};import P from"axios";import{RoomApi as k}from"@fishjam-cloud/fishjam-openapi";var n=class extends Error{constructor(e){super(e),this.name=this.constructor.name}},m=class extends n{constructor(){super("Invalid request body structure")}},d=class extends n{constructor(){super("Unauthorized")}},l=class extends n{constructor(){super("Room not found")}},u=class extends n{constructor(){super("Peer not found")}},f=class extends n{constructor(){super("Service unavailable")}};var i=(r,e)=>{switch(r){case 400:throw new m;case 401:throw new d;case 404:switch(e){case"peer":throw new u;case"room":throw new l;default:return}case 503:throw new f;default:return}};var w=class{roomApi;constructor(e){let o=P.create({validateStatus:t=>[200,201,400,401,404,503].includes(t),headers:{Authorization:`Bearer ${e.serverToken}`}});this.roomApi=new k(void 0,e.fishjamUrl,o)}async createPeer(e,o={}){let t=await this.roomApi.addPeer(e,{type:"webrtc",options:o});i(t.status);let{data:{data:s}}=t;return{peer:s.peer,token:s.token}}async createRoom(e={}){let o=await this.roomApi.createRoom(e);i(o.status);let{data:{data:{room:{components:t,...s}}}}=o;return s}async getAllRooms(){let e=await this.roomApi.getAllRooms();return i(e.status),e.data.data.map(({components:o,...t})=>t)??[]}async getRoom(e){let o=await this.roomApi.getRoom(e);i(o.status,"room");let{components:t,...s}=o.data.data;return s}async deletePeer(e,o){let t=await this.roomApi.deletePeer(e,o);i(t.status,"peer")}async deleteRoom(e){let o=await this.roomApi.deleteRoom(e);i(o.status,"room")}};export{m as BadRequestException,w as FishjamClient,v as FishjamWSNotifier,V as Peer,u as PeerNotFoundException,L as PeerOptions,$ as PeerStatus,J as RoomConfig,l as RoomNotFoundException,f as ServiceUnavailableException,d as UnauthorizedException};
1
+ import {
2
+ ServerMessage,
3
+ ServerMessage_EventType
4
+ } from "./chunk-LSLTFYHQ.mjs";
5
+
6
+ // src/index.ts
7
+ import { Peer as Peer2, PeerStatus, RoomConfig as RoomConfig2, PeerOptions as PeerOptions2 } from "@fishjam-cloud/fishjam-openapi";
8
+
9
+ // src/ws_notifier.ts
10
+ import * as WebSocket from "websocket";
11
+ import { EventEmitter } from "events";
12
+
13
+ // src/utlis.ts
14
+ var httpToWebsocket = (httpUrl) => {
15
+ const url = new URL(httpUrl);
16
+ url.protocol = url.protocol.replace("http", "ws");
17
+ return url.href;
18
+ };
19
+
20
+ // src/ws_notifier.ts
21
+ var allowedNotifications = [
22
+ "roomCreated",
23
+ "roomDeleted",
24
+ "roomCrashed",
25
+ "peerAdded",
26
+ "peerDeleted",
27
+ "peerConnected",
28
+ "peerDisconnected",
29
+ "peerMetadataUpdated",
30
+ "peerCrashed",
31
+ "trackAdded",
32
+ "trackRemoved",
33
+ "trackMetadataUpdated"
34
+ ];
35
+ var FishjamWSNotifier = class extends EventEmitter {
36
+ client;
37
+ constructor(config, onError, onClose, onConnectionFailed) {
38
+ super();
39
+ this.client = new WebSocket.client();
40
+ const fishjamUrl = `${httpToWebsocket(config.fishjamUrl)}/socket/server/websocket`;
41
+ this.client.on("connectFailed", (message) => onConnectionFailed(message));
42
+ this.client.on(
43
+ "connect",
44
+ (connection) => this.setupConnection(connection, config.managementToken, onError, onClose)
45
+ );
46
+ this.client.connect(fishjamUrl);
47
+ }
48
+ dispatchNotification(message) {
49
+ if (message.type == "utf8") {
50
+ console.warn("UTF-8 is an invalid notification type");
51
+ return;
52
+ }
53
+ try {
54
+ const decodedMessage = ServerMessage.toJSON(ServerMessage.decode(message.binaryData));
55
+ const [notification] = Object.keys(decodedMessage);
56
+ if (!this.isAllowedNotification(notification)) return;
57
+ this.emit(notification, decodedMessage);
58
+ } catch (e) {
59
+ console.error("Couldn't decode websocket server message.");
60
+ console.error(e);
61
+ console.error(message);
62
+ }
63
+ }
64
+ setupConnection(connection, serverToken, onError, onClose) {
65
+ const auth = ServerMessage.encode({ authRequest: { token: serverToken } }).finish();
66
+ const subscription = ServerMessage.encode({
67
+ subscribeRequest: { eventType: ServerMessage_EventType.EVENT_TYPE_SERVER_NOTIFICATION }
68
+ }).finish();
69
+ connection.send(auth);
70
+ connection.send(subscription);
71
+ connection.on("message", (message) => this.dispatchNotification(message));
72
+ connection.on("error", (error) => onError(error));
73
+ connection.on("close", (code, reason) => onClose(code, reason));
74
+ }
75
+ isAllowedNotification(notification) {
76
+ return allowedNotifications.includes(notification);
77
+ }
78
+ };
79
+
80
+ // src/client.ts
81
+ import axios from "axios";
82
+ import { RoomApi } from "@fishjam-cloud/fishjam-openapi";
83
+
84
+ // src/exceptions/index.ts
85
+ var FishjamBaseException = class extends Error {
86
+ statusCode;
87
+ constructor(error) {
88
+ super(error.response?.data["detail"] ?? error.response?.data["errors"] ?? "Unknown error");
89
+ this.statusCode = error.response?.status ?? 500;
90
+ }
91
+ };
92
+ var BadRequestException = class extends FishjamBaseException {
93
+ };
94
+ var UnauthorizedException = class extends FishjamBaseException {
95
+ };
96
+ var ForbiddenException = class extends FishjamBaseException {
97
+ };
98
+ var RoomNotFoundException = class extends FishjamBaseException {
99
+ };
100
+ var FishjamNotFoundException = class extends FishjamBaseException {
101
+ };
102
+ var PeerNotFoundException = class extends FishjamBaseException {
103
+ };
104
+ var ServiceUnavailableException = class extends FishjamBaseException {
105
+ };
106
+ var UnknownException = class extends FishjamBaseException {
107
+ };
108
+
109
+ // src/exceptions/mapper.ts
110
+ var raiseExceptions = (error, entity) => {
111
+ switch (error.response?.status) {
112
+ case 400:
113
+ throw new BadRequestException(error);
114
+ case 401:
115
+ throw new UnauthorizedException(error);
116
+ case 404:
117
+ switch (entity) {
118
+ case "peer":
119
+ throw new PeerNotFoundException(error);
120
+ case "room":
121
+ throw new RoomNotFoundException(error);
122
+ default:
123
+ throw new FishjamNotFoundException(error);
124
+ }
125
+ case 502:
126
+ throw new UnknownException(error);
127
+ case 503:
128
+ throw new ServiceUnavailableException(error);
129
+ default:
130
+ throw new UnknownException(error);
131
+ }
132
+ };
133
+
134
+ // src/client.ts
135
+ var FishjamClient = class {
136
+ roomApi;
137
+ constructor(config) {
138
+ const client2 = axios.create({
139
+ headers: {
140
+ Authorization: `Bearer ${config.managementToken}`
141
+ }
142
+ });
143
+ this.roomApi = new RoomApi(void 0, config.fishjamUrl, client2);
144
+ }
145
+ async createPeer(roomId, options = {}) {
146
+ const response = await this.roomApi.addPeer(roomId, {
147
+ type: "webrtc",
148
+ options
149
+ }).catch(raiseExceptions);
150
+ const {
151
+ data: { data }
152
+ } = response;
153
+ return { peer: data.peer, peerToken: data.token };
154
+ }
155
+ async createRoom(config = {}) {
156
+ const response = await this.roomApi.createRoom(config).catch(raiseExceptions);
157
+ const {
158
+ data: {
159
+ data: {
160
+ room: { components: _, ...room }
161
+ }
162
+ }
163
+ } = response;
164
+ return room;
165
+ }
166
+ async getAllRooms() {
167
+ const getAllRoomsRepsonse = await this.roomApi.getAllRooms().catch(raiseExceptions);
168
+ return getAllRoomsRepsonse.data.data.map(({ components: _, ...room }) => room) ?? [];
169
+ }
170
+ async getRoom(roomId) {
171
+ const getRoomResponse = await this.roomApi.getRoom(roomId).catch((error) => raiseExceptions(error, "room"));
172
+ const { components: _, ...room } = getRoomResponse.data.data;
173
+ return room;
174
+ }
175
+ async deletePeer(roomId, peerId) {
176
+ await this.roomApi.deletePeer(roomId, peerId).catch((error) => raiseExceptions(error, "peer"));
177
+ }
178
+ async deleteRoom(roomId) {
179
+ await this.roomApi.deleteRoom(roomId).catch((error) => raiseExceptions(error, "room"));
180
+ }
181
+ async refreshPeerToken(roomId, peerId) {
182
+ const refreshTokenResponse = await this.roomApi.refreshToken(roomId, peerId).catch((error) => raiseExceptions(error, "peer"));
183
+ return refreshTokenResponse.data.data.token;
184
+ }
185
+ };
186
+ export {
187
+ BadRequestException,
188
+ FishjamBaseException,
189
+ FishjamClient,
190
+ FishjamNotFoundException,
191
+ FishjamWSNotifier,
192
+ ForbiddenException,
193
+ Peer2 as Peer,
194
+ PeerNotFoundException,
195
+ PeerOptions2 as PeerOptions,
196
+ PeerStatus,
197
+ RoomConfig2 as RoomConfig,
198
+ RoomNotFoundException,
199
+ ServiceUnavailableException,
200
+ UnauthorizedException,
201
+ UnknownException
202
+ };
package/dist/proto.js CHANGED
@@ -1 +1,34 @@
1
- "use strict";var a=Object.defineProperty;var M=Object.getOwnPropertyDescriptor;var S=Object.getOwnPropertyNames;var o=Object.prototype.hasOwnProperty;var p=(r,e)=>{for(var v in e)a(r,v,{get:e[v],enumerable:!0})},u=(r,e,v,g)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of S(e))!o.call(r,t)&&t!==v&&a(r,t,{get:()=>e[t],enumerable:!(g=M(e,t))||g.enumerable});return r};var _=r=>u(a({},"__esModule",{value:!0}),r);var f={};p(f,{ServerMessage:()=>s.ServerMessage,ServerMessage_AuthRequest:()=>s.ServerMessage_AuthRequest,ServerMessage_EventType:()=>s.ServerMessage_EventType});module.exports=_(f);var s=require("@fishjam-cloud/fishjam-proto");0&&(module.exports={ServerMessage,ServerMessage_AuthRequest,ServerMessage_EventType});
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/proto.ts
21
+ var proto_exports = {};
22
+ __export(proto_exports, {
23
+ ServerMessage: () => import_fishjam_proto.ServerMessage,
24
+ ServerMessage_AuthRequest: () => import_fishjam_proto.ServerMessage_AuthRequest,
25
+ ServerMessage_EventType: () => import_fishjam_proto.ServerMessage_EventType
26
+ });
27
+ module.exports = __toCommonJS(proto_exports);
28
+ var import_fishjam_proto = require("@fishjam-cloud/fishjam-proto");
29
+ // Annotate the CommonJS export names for ESM import in node:
30
+ 0 && (module.exports = {
31
+ ServerMessage,
32
+ ServerMessage_AuthRequest,
33
+ ServerMessage_EventType
34
+ });
package/dist/proto.mjs CHANGED
@@ -1 +1,10 @@
1
- import{a,b,c}from"./chunk-PVJVFZZS.mjs";export{a as ServerMessage,b as ServerMessage_AuthRequest,c as ServerMessage_EventType};
1
+ import {
2
+ ServerMessage,
3
+ ServerMessage_AuthRequest,
4
+ ServerMessage_EventType
5
+ } from "./chunk-LSLTFYHQ.mjs";
6
+ export {
7
+ ServerMessage,
8
+ ServerMessage_AuthRequest,
9
+ ServerMessage_EventType
10
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fishjam-cloud/js-server-sdk",
3
- "version": "0.1.2",
3
+ "version": "0.3.0",
4
4
  "description": "Fishjam server SDK for JavaScript",
5
5
  "homepage": "https://github.com/fishjam-cloud/js-server-sdk",
6
6
  "author": "Fishjam Cloud Team",
@@ -31,7 +31,9 @@
31
31
  "build": "tsup",
32
32
  "format": "prettier --write .",
33
33
  "format:check": "prettier --check .",
34
- "typecheck": "tsc --noEmit"
34
+ "typecheck": "tsc --noEmit",
35
+ "lint": "eslint . --fix",
36
+ "lint:check": "eslint . "
35
37
  },
36
38
  "tsup": {
37
39
  "entry": [
@@ -39,7 +41,7 @@
39
41
  "src/proto.ts"
40
42
  ],
41
43
  "dts": true,
42
- "minify": true,
44
+ "minify": false,
43
45
  "format": [
44
46
  "cjs",
45
47
  "esm"
@@ -47,17 +49,16 @@
47
49
  "outDir": "dist"
48
50
  },
49
51
  "dependencies": {
50
- "@fishjam-cloud/fishjam-openapi": "0.1.2",
51
- "@fishjam-cloud/fishjam-proto": "0.1.2",
52
- "axios": "^1.7.4",
52
+ "@fishjam-cloud/fishjam-openapi": "0.3.0",
53
+ "@fishjam-cloud/fishjam-proto": "0.3.0",
54
+ "axios": "^1.7.7",
53
55
  "websocket": "^1.0.35"
54
56
  },
55
57
  "devDependencies": {
56
- "@openapitools/openapi-generator-cli": "^2.13.4",
57
- "@types/node": "^22.4.1",
58
+ "@openapitools/openapi-generator-cli": "^2.14.0",
59
+ "@types/node": "^22.7.5",
58
60
  "@types/websocket": "^1.0.10",
59
- "prettier": "3.3.3",
60
- "tsup": "^8.2.4",
61
+ "tsup": "^8.3.0",
61
62
  "typed-emitter": "^2.1.0"
62
63
  }
63
64
  }
@@ -1 +0,0 @@
1
- import{ServerMessage as s,ServerMessage_AuthRequest as t,ServerMessage_EventType as v}from"@fishjam-cloud/fishjam-proto";export{s as a,t as b,v as c};