@digitalsamba/embedded-sdk 0.0.7 → 0.0.11

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
@@ -6,25 +6,25 @@ Digital Samba Embedded SDK - control easily with JS your iframe integration.
6
6
 
7
7
  Add it to dependency list using your preferred package manager:
8
8
 
9
- ```npm install @digitalsamba/embedded-sdk```
9
+ `npm install @digitalsamba/embedded-sdk`
10
10
 
11
11
  or
12
12
 
13
- ```yarn install @digitalsamba/embedded-sdk```
13
+ `yarn install @digitalsamba/embedded-sdk`
14
14
 
15
15
  After installation, use it in your application code using provided import:
16
16
 
17
17
  ```js
18
- const DigitalSambaEmbedded = require('@digitalsamba/embedded-sdk')
18
+ const DigitalSambaEmbedded = require('@digitalsamba/embedded-sdk');
19
19
 
20
20
  // or, using imports
21
- import DigitalSambaEmbedded from '@digitalsamba/embedded-sdk'
21
+ import DigitalSambaEmbedded from '@digitalsamba/embedded-sdk';
22
22
  ```
23
23
 
24
24
  This package is written in TypeScript, so type definitions are also available:
25
25
 
26
- ```ts
27
- import { SendMessageType, ReceiveMessageType, /* ...etc */} from '@digitalsamba/embedded-sdk'
26
+ ```ts
27
+ import { SendMessageType, ReceiveMessageType /* ...etc */ } from '@digitalsamba/embedded-sdk';
28
28
  ```
29
29
 
30
30
  ### Initialization
@@ -44,33 +44,33 @@ const api = DigitalSambaEmbedded.createControl(InitOptions);
44
44
 
45
45
  // ...
46
46
  // when necessary, load the frame:
47
- api.load(InstanceProperties /* optional */)
47
+ api.load(InstanceProperties /* optional */);
48
48
  ```
49
49
 
50
50
  ### InitOptions
51
51
 
52
52
  `InitOptions` has the following fields:
53
53
 
54
- * `root` - HTMLElement. If specified, target frame will be created within it.
55
- * `frame` - HTMLIFrameElement to be wrapped.
56
- * `url` - full URL to be applied as frame src. Must include protocol and `token` query param for private rooms;
57
- * `team` - team name string
58
- * `room` - room identifier string
59
- * `token` - optional string for authentication, mainly for private rooms
54
+ - `root` - HTMLElement. If specified, target frame will be created within it.
55
+ - `frame` - HTMLIFrameElement to be wrapped.
56
+ - `url` - full URL to be applied as frame src. Must include protocol and `token` query param for private rooms;
57
+ - `team` - team name string
58
+ - `room` - room identifier string
59
+ - `token` - optional string for authentication, mainly for private rooms
60
60
 
61
61
  To successfully initialize an instance of the wrapper one of following combinations needs to be used:
62
62
 
63
- * `root + team + room` - will create a controlled frame inside `root` element
64
- * `frame + team + room` - will attach to existing frame
65
- * `frame` - will attach to existing frame (assuming you've manually specified correct frame src)
66
- * `root + url` - will create a frame inside `root` element
63
+ - `root + team + room` - will create a controlled frame inside `root` element
64
+ - `frame + team + room` - will attach to existing frame
65
+ - `frame` - will attach to existing frame (assuming you've manually specified correct frame src)
66
+ - `root + url` - will create a frame inside `root` element
67
67
 
68
68
  Remember to always specify `allow="camera; microphone; display-capture; autoplay;"` and `allowFullscreen="true"` attributes on iframe if you want to wrap around an existing iframe.
69
69
 
70
70
  ### InstanceProperties
71
71
 
72
- * `frameAttributes` - list of attributes to be applied to target iframe
73
- * `reportErrors` - boolean, false by default. Whether to report misconfiguration or runtime errors to console
72
+ - `frameAttributes` - list of attributes to be applied to target iframe
73
+ - `reportErrors` - boolean, false by default. Whether to report misconfiguration or runtime errors to console
74
74
 
75
75
  ### Usage
76
76
 
@@ -84,13 +84,30 @@ api.on('userJoined', (data) => {
84
84
  api.on('userLeft', (data) => {
85
85
  // ...
86
86
  });
87
+ ```
87
88
 
88
- // you can also listen to all events simultaneously
89
- api.on('*', (data) => {
90
- console.log(data)
89
+ Error event can provide useful details:
90
+ ```js
91
+ api.on('appError', (error) => {
92
+ console.log(error);
93
+
94
+ /* outputs {
95
+ name: 'recording-not-allowed',
96
+ message:
97
+ 'Recording disabled. You’ll need to edit this room’s properties to record sessions in this room',
98
+ }
99
+ */
91
100
  });
101
+ ```
102
+
92
103
 
104
+ For debugging purposes, you can also listen to all events simultaneously
105
+ ```js
106
+ api.on('*', (data) => {
107
+ console.log(data);
108
+ });
93
109
  ```
110
+
94
111
  Also see `dist/index.html` for more examples.
95
112
 
96
113
  To send commands, api instance provides handy utilities:
@@ -104,24 +121,34 @@ api.disableAudio();
104
121
  ---
105
122
 
106
123
  ### Available events:
107
-
108
- * `connected`
109
- * `userJoined`
110
- * `userLeft`
111
- * `videoEnabled`
112
- * `videoDisabled`
113
- * `audioEnabled`
114
- * `audioDisabled`
115
- * `screenshareStarted`
116
- * `screenshareStopped`
124
+ - `appError`
125
+ - `userJoined`
126
+ - `userLeft`
127
+ - `videoEnabled`
128
+ - `videoDisabled`
129
+ - `audioEnabled`
130
+ - `audioDisabled`
131
+ - `screenshareStarted`
132
+ - `screenshareStopped`
133
+ - `recordingStarted`
134
+ - `recordingStopped`
135
+ - `recordingFailed`
136
+ - `layoutModeChanged`
137
+ - `activeSpeakerChanged`
117
138
 
118
139
  ### Available commands:
119
140
 
120
- * `enableVideo()`
121
- * `disableVideo()`
122
- * `toggleVideo(newState?: boolean)`
123
- * `enableAudio()`
124
- * `disableAudio()`
125
- * `toggleAudio(newState?: boolean)`
126
- * `startScreenshare()`
127
- * `stopScreenshare()`
141
+ - `enableVideo()`
142
+ - `disableVideo()`
143
+ - `toggleVideo(newState?: boolean)`
144
+ - `enableAudio()`
145
+ - `disableAudio()`
146
+ - `toggleAudio(newState?: boolean)`
147
+ - `startScreenshare()`
148
+ - `stopScreenshare()`
149
+ - `startRecording()`
150
+ - `stopRecording()`
151
+ - `showToolbar()`
152
+ - `hideToolbar()`
153
+ - `toggleToolbar(newState?: boolean)`
154
+ - `changeLayoutMode(mode: 'tiled' | 'auto')`
@@ -1,54 +1,17 @@
1
- export interface InitOptions {
2
- root: HTMLElement;
3
- frame: HTMLIFrameElement;
4
- url: string;
5
- team: string;
6
- room: string;
7
- token?: string;
8
- }
9
- export declare type FrameAttributes = {
10
- align: string;
11
- allow: string;
12
- allowFullscreen: boolean;
13
- frameBorder: string;
14
- height: string;
15
- longDesc: string;
16
- marginHeight: string;
17
- marginWidth: string;
18
- name: string;
19
- referrerPolicy: ReferrerPolicy;
20
- scrolling: string;
21
- src: string;
22
- srcdoc: string;
23
- width: string;
24
- } & HTMLElement;
25
- export interface InstanceProperties {
26
- frameAttributes?: Partial<FrameAttributes>;
27
- reportErrors?: boolean;
28
- }
29
- export declare type SendMessageType = "connect" | "enableVideo" | "enableAudio" | "disableVideo" | "disableAudio" | "toggleVideo" | "toggleAudio" | "startScreenshare" | "stopScreenshare";
30
- export declare type ReceiveMessageType = "connected" | "userJoined" | "userLeft" | "videoEnabled" | "videoDisabled" | "audioEnabled" | "audioDisabled" | "screenshareStarted" | "screenshareStopped";
31
- export interface SendMessage<P> {
32
- type: SendMessageType;
33
- payload?: P;
34
- }
35
- export interface ReceiveMessage {
36
- type: ReceiveMessageType;
37
- payload: unknown;
38
- }
39
- export declare class DigitalSambaEmbedded {
1
+ /// <reference types="node" />
2
+ import { InitOptions, InstanceProperties, LayoutMode } from './types';
3
+ import EventEmitter from 'events';
4
+ export declare class DigitalSambaEmbedded extends EventEmitter {
40
5
  initOptions: Partial<InitOptions>;
41
6
  savedIframeSrc: string;
42
7
  allowedOrigin: string;
43
8
  connected: boolean;
44
9
  frame: HTMLIFrameElement;
45
- eventHandlers: Partial<Record<ReceiveMessageType | "*", (payload: any) => void>>;
46
10
  reportErrors: boolean;
47
11
  constructor(options?: Partial<InitOptions>, instanceProperties?: Partial<InstanceProperties>, loadImmediately?: boolean);
48
12
  static createControl: (initOptions: InitOptions) => DigitalSambaEmbedded;
49
13
  private mountFrame;
50
14
  load: (instanceProperties?: InstanceProperties) => void;
51
- on: (type: ReceiveMessageType, handler: (payload: any) => void) => void;
52
15
  private onMessage;
53
16
  private setFrameSrc;
54
17
  private checkTarget;
@@ -63,4 +26,10 @@ export declare class DigitalSambaEmbedded {
63
26
  toggleAudio: (enable?: boolean) => void;
64
27
  startScreenshare: () => void;
65
28
  stopScreenshare: () => void;
29
+ startRecording: () => void;
30
+ stopRecording: () => void;
31
+ showToolbar: () => void;
32
+ hideToolbar: () => void;
33
+ changeLayoutMode: (mode: LayoutMode) => void;
34
+ toggleToolbar: (show?: boolean) => void;
66
35
  }
package/dist/cjs/index.js CHANGED
@@ -1,218 +1,214 @@
1
1
  "use strict";
2
- var __read = (this && this.__read) || function (o, n) {
3
- var m = typeof Symbol === "function" && o[Symbol.iterator];
4
- if (!m) return o;
5
- var i = m.call(o), r, ar = [], e;
6
- try {
7
- while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
8
- }
9
- catch (error) { e = { error: error }; }
10
- finally {
11
- try {
12
- if (r && !r.done && (m = i["return"])) m.call(i);
13
- }
14
- finally { if (e) throw e.error; }
15
- }
16
- return ar;
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
17
4
  };
5
+ var _a;
18
6
  Object.defineProperty(exports, "__esModule", { value: true });
19
7
  exports.DigitalSambaEmbedded = void 0;
20
- var errors_1 = require("./utils/errors");
21
- var CONNECT_TIMEOUT = 5000;
8
+ const errors_1 = require("./utils/errors");
9
+ const events_1 = __importDefault(require("events"));
10
+ const CONNECT_TIMEOUT = 10000;
22
11
  function isFunction(func) {
23
12
  return func instanceof Function;
24
13
  }
25
- var DigitalSambaEmbedded = /** @class */ (function () {
26
- function DigitalSambaEmbedded(options, instanceProperties, loadImmediately) {
27
- if (options === void 0) { options = {}; }
28
- if (instanceProperties === void 0) { instanceProperties = {}; }
29
- if (loadImmediately === void 0) { loadImmediately = true; }
30
- var _this = this;
31
- this.savedIframeSrc = "";
32
- this.allowedOrigin = "*";
14
+ class DigitalSambaEmbedded extends events_1.default {
15
+ constructor(options = {}, instanceProperties = {}, loadImmediately = true) {
16
+ super();
17
+ this.savedIframeSrc = '';
18
+ this.allowedOrigin = '*';
33
19
  this.connected = false;
34
- this.frame = document.createElement("iframe");
35
- this.eventHandlers = {};
20
+ this.frame = document.createElement('iframe');
36
21
  this.reportErrors = false;
37
- this.mountFrame = function (loadImmediately) {
38
- var _b = _this.initOptions, url = _b.url, frame = _b.frame, root = _b.root;
22
+ this.mountFrame = (loadImmediately) => {
23
+ const { url, frame, root } = this.initOptions;
39
24
  if (root) {
40
- root.appendChild(_this.frame);
25
+ root.appendChild(this.frame);
41
26
  }
42
27
  else if (frame) {
43
- _this.frame = frame;
28
+ this.frame = frame;
44
29
  if (!frame.allow) {
45
- _this.logError(errors_1.ALLOW_ATTRIBUTE_MISSING);
30
+ this.logError(errors_1.ALLOW_ATTRIBUTE_MISSING);
46
31
  }
47
32
  }
48
33
  else {
49
- document.body.appendChild(_this.frame);
34
+ document.body.appendChild(this.frame);
50
35
  }
51
- if (url || (_this.frame.src && _this.frame.src !== window.location.href)) {
36
+ if (url || (this.frame.src && this.frame.src !== window.location.href)) {
52
37
  try {
53
- var frameSrc = new URL(url || _this.frame.src).toString();
54
- _this.frame.src = frameSrc;
55
- _this.savedIframeSrc = frameSrc;
38
+ const frameSrc = new URL(url || this.frame.src).toString();
39
+ this.frame.src = frameSrc;
40
+ this.savedIframeSrc = frameSrc;
56
41
  }
57
- catch (_c) {
58
- _this.logError(errors_1.INVALID_URL);
42
+ catch (_b) {
43
+ this.logError(errors_1.INVALID_URL);
59
44
  }
60
45
  }
61
46
  if (!loadImmediately) {
62
- _this.savedIframeSrc = _this.frame.src;
63
- _this.frame.src = "";
64
- }
65
- };
66
- this.load = function (instanceProperties) {
67
- if (instanceProperties === void 0) { instanceProperties = {}; }
68
- _this.reportErrors = instanceProperties.reportErrors || false;
69
- _this.setFrameSrc();
70
- _this.applyFrameProperties(instanceProperties);
71
- _this.frame.style.display = "block";
72
- };
73
- this.on = function (type, handler) {
74
- _this.eventHandlers[type] = handler;
75
- };
76
- this.onMessage = function (event) {
77
- // if (event.origin !== this.allowedOrigin) {
78
- // // ignore messages from other sources;
79
- // return;
80
- // }
81
- if (typeof _this.eventHandlers["*"] === "function") {
82
- _this.eventHandlers["*"](event.data);
83
- }
84
- if (event.data.type) {
85
- var callback = _this.eventHandlers[event.data.type];
86
- if (isFunction(callback)) {
87
- callback(event.data);
88
- }
47
+ this.savedIframeSrc = this.frame.src;
48
+ this.frame.src = '';
89
49
  }
90
50
  };
91
- this.setFrameSrc = function () {
92
- var url = _this.savedIframeSrc;
93
- var _b = _this.initOptions, team = _b.team, room = _b.room, token = _b.token;
51
+ this.load = (instanceProperties = {}) => {
52
+ this.reportErrors = instanceProperties.reportErrors || false;
53
+ this.setFrameSrc();
54
+ this.applyFrameProperties(instanceProperties);
55
+ this.frame.style.display = 'block';
56
+ };
57
+ this.onMessage = (event) => {
58
+ if (event.origin !== this.allowedOrigin) {
59
+ // ignore messages from other sources;
60
+ return;
61
+ }
62
+ const message = event.data.DSPayload;
63
+ if (!message) {
64
+ return;
65
+ }
66
+ this.emit('*', message);
67
+ if (message.type) {
68
+ this.emit(message.type, message);
69
+ }
70
+ };
71
+ this.setFrameSrc = () => {
72
+ let url = this.savedIframeSrc;
73
+ const { team, room, token } = this.initOptions;
94
74
  if (team && room) {
95
- url = "https://".concat(team, ".digitalsamba.com/").concat(room);
75
+ url = `https://${team}.digitalsamba.com/${room}`;
96
76
  }
97
77
  if (url && token) {
98
- var urlObj = new URL(url);
99
- urlObj.searchParams.append("token", token);
100
- url = urlObj.toString(); //`${urlObj.origin}${urlObj.pathname}?${params}`;
78
+ const urlObj = new URL(url);
79
+ urlObj.searchParams.append('token', token);
80
+ url = urlObj.toString();
101
81
  }
102
82
  if (url) {
103
- _this.frame.src = url;
83
+ this.frame.src = url;
104
84
  }
105
85
  else {
106
- _this.logError(errors_1.INVALID_CONFIG);
86
+ this.logError(errors_1.INVALID_CONFIG);
107
87
  return;
108
88
  }
109
- var allowedURL = new URL(_this.frame.src);
110
- _this.allowedOrigin = allowedURL.origin;
111
- _this.frame.onload = function () { return _this.checkTarget(); };
89
+ const allowedURL = new URL(this.frame.src);
90
+ this.allowedOrigin = allowedURL.origin;
91
+ this.frame.onload = () => this.checkTarget();
112
92
  };
113
- this.logError = function (error) {
114
- if (_this.reportErrors) {
93
+ this.logError = (error) => {
94
+ if (this.reportErrors) {
115
95
  throw error;
116
96
  }
117
97
  };
118
- this.applyFrameProperties = function (instanceProperties) {
98
+ this.applyFrameProperties = (instanceProperties) => {
119
99
  if (instanceProperties.frameAttributes) {
120
100
  // TODO: only allow specific attrs here; This is a heck to support
121
- Object.entries(instanceProperties.frameAttributes).forEach(function (_b) {
122
- var _c = __read(_b, 2), attr = _c[0], value = _c[1];
123
- if (value !== null && typeof value !== "undefined") {
124
- _this.frame.setAttribute(attr, value.toString());
101
+ Object.entries(instanceProperties.frameAttributes).forEach(([attr, value]) => {
102
+ if (value !== null && typeof value !== 'undefined') {
103
+ this.frame.setAttribute(attr, value.toString());
125
104
  }
126
105
  else {
127
- _this.frame.removeAttribute(attr);
106
+ this.frame.removeAttribute(attr);
128
107
  }
129
108
  });
130
109
  }
131
110
  if (instanceProperties.reportErrors) {
132
- _this.reportErrors = true;
111
+ this.reportErrors = true;
133
112
  }
134
113
  };
135
114
  // commands
136
- this.enableVideo = function () {
137
- _this.sendMessage({ type: "enableVideo" });
115
+ this.enableVideo = () => {
116
+ this.sendMessage({ type: 'enableVideo' });
138
117
  };
139
- this.disableVideo = function () {
140
- _this.sendMessage({ type: "disableVideo" });
118
+ this.disableVideo = () => {
119
+ this.sendMessage({ type: 'disableVideo' });
141
120
  };
142
- this.toggleVideo = function (enable) {
143
- if (typeof enable === "undefined") {
144
- _this.sendMessage({ type: "toggleVideo" });
121
+ this.toggleVideo = (enable) => {
122
+ if (typeof enable === 'undefined') {
123
+ this.sendMessage({ type: 'toggleVideo' });
124
+ }
125
+ else if (enable) {
126
+ this.enableVideo();
145
127
  }
146
128
  else {
147
- if (enable) {
148
- _this.enableVideo();
149
- }
150
- else {
151
- _this.disableVideo();
152
- }
129
+ this.disableVideo();
153
130
  }
154
131
  };
155
- this.enableAudio = function () {
156
- _this.sendMessage({ type: "enableAudio" });
132
+ this.enableAudio = () => {
133
+ this.sendMessage({ type: 'enableAudio' });
157
134
  };
158
- this.disableAudio = function () {
159
- _this.sendMessage({ type: "disableAudio" });
135
+ this.disableAudio = () => {
136
+ this.sendMessage({ type: 'disableAudio' });
160
137
  };
161
- this.toggleAudio = function (enable) {
162
- if (typeof enable === "undefined") {
163
- _this.sendMessage({ type: "toggleAudio" });
138
+ this.toggleAudio = (enable) => {
139
+ if (typeof enable === 'undefined') {
140
+ this.sendMessage({ type: 'toggleAudio' });
141
+ }
142
+ else if (enable) {
143
+ this.enableAudio();
164
144
  }
165
145
  else {
166
- if (enable) {
167
- _this.enableAudio();
168
- }
169
- else {
170
- _this.disableAudio();
171
- }
146
+ this.disableAudio();
172
147
  }
173
148
  };
174
- this.startScreenshare = function () {
175
- _this.sendMessage({ type: "startScreenshare" });
149
+ this.startScreenshare = () => {
150
+ this.sendMessage({ type: 'startScreenshare' });
151
+ };
152
+ this.stopScreenshare = () => {
153
+ this.sendMessage({ type: 'stopScreenshare' });
154
+ };
155
+ this.startRecording = () => {
156
+ this.sendMessage({ type: 'startRecording' });
176
157
  };
177
- this.stopScreenshare = function () {
178
- _this.sendMessage({ type: "stopScreenshare" });
158
+ this.stopRecording = () => {
159
+ this.sendMessage({ type: 'stopRecording' });
160
+ };
161
+ this.showToolbar = () => {
162
+ this.sendMessage({ type: 'showToolbar' });
163
+ };
164
+ this.hideToolbar = () => {
165
+ this.sendMessage({ type: 'hideToolbar' });
166
+ };
167
+ this.changeLayoutMode = (mode) => {
168
+ this.sendMessage({ type: 'changeLayoutMode', data: mode });
169
+ };
170
+ this.toggleToolbar = (show) => {
171
+ if (typeof show === 'undefined') {
172
+ this.sendMessage({ type: 'toggleToolbar' });
173
+ }
174
+ else if (show) {
175
+ this.showToolbar();
176
+ }
177
+ else {
178
+ this.hideToolbar();
179
+ }
179
180
  };
180
181
  this.initOptions = options;
181
182
  this.reportErrors = instanceProperties.reportErrors || false;
182
- this.frame.allow = "camera; microphone; display-capture; autoplay;";
183
- this.frame.setAttribute("allowFullscreen", "true");
183
+ this.frame.allow = 'camera; microphone; display-capture; autoplay;';
184
+ this.frame.setAttribute('allowFullscreen', 'true');
184
185
  this.mountFrame(loadImmediately);
185
186
  if (loadImmediately) {
186
187
  this.load(instanceProperties);
187
188
  }
188
189
  else {
189
- this.frame.style.display = "none";
190
+ this.frame.style.display = 'none';
190
191
  }
191
- window.addEventListener("message", this.onMessage);
192
+ window.addEventListener('message', this.onMessage);
192
193
  }
193
- DigitalSambaEmbedded.prototype.checkTarget = function () {
194
- var _this = this;
195
- this.sendMessage({ type: "connect" });
196
- var confirmationTimeout = window.setTimeout(function () {
197
- _this.logError(errors_1.UNKNOWN_TARGET);
194
+ checkTarget() {
195
+ this.sendMessage({ type: 'connect' });
196
+ const confirmationTimeout = window.setTimeout(() => {
197
+ this.logError(errors_1.UNKNOWN_TARGET);
198
198
  }, CONNECT_TIMEOUT);
199
- this.on("connected", function () {
200
- _this.connected = true;
199
+ this.on('connected', () => {
200
+ this.connected = true;
201
201
  clearTimeout(confirmationTimeout);
202
202
  });
203
- };
204
- DigitalSambaEmbedded.prototype.sendMessage = function (message) {
203
+ }
204
+ sendMessage(message) {
205
205
  if (this.frame.contentWindow) {
206
206
  this.frame.contentWindow.postMessage(message, {
207
207
  targetOrigin: this.allowedOrigin,
208
208
  });
209
209
  }
210
- };
211
- var _a;
212
- _a = DigitalSambaEmbedded;
213
- DigitalSambaEmbedded.createControl = function (initOptions) {
214
- return new _a(initOptions, {}, false);
215
- };
216
- return DigitalSambaEmbedded;
217
- }());
210
+ }
211
+ }
218
212
  exports.DigitalSambaEmbedded = DigitalSambaEmbedded;
213
+ _a = DigitalSambaEmbedded;
214
+ DigitalSambaEmbedded.createControl = (initOptions) => new _a(initOptions, {}, false);