@viibe/impulse-integration-js 2.2.3 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3 @@
1
+ {
2
+ "actions": []
3
+ }
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- (()=>{var t={579:t=>{function e(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var n=function(){function t(e){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.host=e.host,this.origin=/^localhost/.test(this.host)?"http://".concat(this.host):"https://".concat(this.host),this.source=e.source,this.handlers={},window.addEventListener("message",this.onMessage.bind(this))}var n,o;return n=t,o=[{key:"createCallIframe",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if(!this.host)throw new Error("fillHost");if(!this.source)throw new Error("fillSource");var e=this.createCallUrl(t),n=document.createElement("iframe");return n.style="border: 0;width: calc(100% - 1rem);margin: 0.5rem;",n.src=e,n.allow="geolocation;autoplay;microphone;camera;midi;encrypted-media;clipboard-write;",n}},{key:"createCallUrl",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=t.clipboard,n=void 0!==e&&e,o=t.components,i=t.links,a=t.o2m,r=void 0!==a&&a,s=t.ticket,c=t.token,l=t.locale,u="".concat(this.origin,"/integration/features/call"),d=new URLSearchParams({resize:"true",source:this.source});if(null!=s&&s.title&&d.set("title",s.title),null!=s&&s.integration&&d.set("thirdPartyId",s.integration.id),i){var h=i instanceof Array?i.map((function(t){return"".concat(t.category,":").concat(t.value)})).join(","):String(i);d.set("links",h)}if(c&&d.set("token",c),l&&d.set("locale",l),o){var f=o instanceof Array?o.join(","):String(o);d.set("components",f)}return d.set("clipboard",Boolean(n)),d.set("o2m",Boolean(r)),u+"?".concat(d)}},{key:"isViibeEvent",value:function(t){return Boolean(t.isTrusted&&0===t.origin.indexOf(this.origin))}},{key:"dispatch",value:function(t,e){var n=this.handlers[t];return n?n.map((function(t){return t(e)})):null}},{key:"onMessage",value:function(t){return this.isViibeEvent(t)?t.data&&t.data.event&&t.data.payload?this.dispatch(t.data.event,t.data.payload):t.data&&t.data.token?this.dispatch("authentication:token",t.data.token):t.data&&t.data.error?this.dispatch("authentication:error",t.data.error):null:null}},{key:"on",value:function(t,e){(this.handlers[t]=this.handlers[t]||[]).push(e)}},{key:"authenticate",value:function(t){var e=this,n="".concat(this.origin,"/api/auth/login/").concat(t),o=window.screen.width/2-240,i=window.screen.height/2-300,a=["toolbar=no","location=no","directories=no","status=no","menubar=no","scrollbars=no","resizable=no","copyhistory=no","width=".concat(480),"height=".concat(600),"top=".concat(i),"left=".concat(o)];return new Promise((function(t,o){var i=window.open(n,"Authorization",a.join(", ")),r=setInterval((function(){i.closed&&(c(),s())}),100),s=function(){o("User closed window")},c=function(){window.removeEventListener("message",l),clearInterval(r)},l=function(n){if(!e.isViibeEvent(n))return null;n.data.token&&(c(),t(n.data.token)),n.data.error&&(c(),o(n.data.error))};window.addEventListener("message",l)}))}}],o&&e(n.prototype,o),t}();"undefined"!=typeof window&&(window.Viibe=n),t.exports=n}},e={},n=function n(o){var i=e[o];if(void 0!==i)return i.exports;var a=e[o]={exports:{}};return t[o](a,a.exports,n),a.exports}(579);module.exports=n})();
1
+ (()=>{var t={579:t=>{function e(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var n=function(){function t(e){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.handlers=[],this.host=e.host,this.origin=/^localhost/.test(this.host)?"http://".concat(this.host):"https://".concat(this.host),this.source=e.source,window.addEventListener("message",this.onMessage.bind(this))}var n,o;return n=t,o=[{key:"createCallIframe",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if(!this.host)throw new Error("fillHost");if(!this.source)throw new Error("fillSource");var e=this.createCallUrl(t),n=document.createElement("iframe");return n.name="viibe-"+Math.floor(1e4*Math.random()),n.style="border: 0;width: calc(100% - 1rem);margin: 0.5rem;",n.src=e,n.allow="geolocation;autoplay;microphone;camera;midi;encrypted-media;clipboard-write;",n}},{key:"createCallUrl",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=t.clipboard,n=void 0!==e&&e,o=t.components,a=t.links,i=t.o2m,r=void 0!==i&&i,s=t.ticket,c=t.token,l=t.locale,u="".concat(this.origin,"/integration/features/call"),d=new URLSearchParams({resize:"true",source:this.source});if(null!=s&&s.title&&d.set("title",s.title),null!=s&&s.integration&&d.set("thirdPartyId",s.integration.id),a){var h=a instanceof Array?a.map((function(t){return"".concat(t.category,":").concat(t.value)})).join(","):String(a);d.set("links",h)}if(c&&d.set("token",c),l&&d.set("locale",l),o){var f=o instanceof Array?o.join(","):String(o);d.set("components",f)}return d.set("clipboard",Boolean(n)),d.set("o2m",Boolean(r)),u+"?".concat(d)}},{key:"isViibeEvent",value:function(t){return Boolean(t.isTrusted&&0===t.origin.indexOf(this.origin))}},{key:"dispatch",value:function(t,e,n){return this.handlers.filter((function(e){return e.eventName===t&&(!e.windowName||e.windowName===n)})).map((function(t){return t.func(e)}))}},{key:"onMessage",value:function(t){return this.isViibeEvent(t)?t.data&&t.data.event&&t.data.payload?this.dispatch(t.data.event,t.data.payload,t.data.windowName):t.data&&t.data.token?this.dispatch("authentication:token",t.data.token):t.data&&t.data.error?this.dispatch("authentication:error",t.data.error):null:null}},{key:"on",value:function(t,e,n){"string"==typeof t&&"function"==typeof e&&void 0===n&&(n=e,e=t,t=null);var o={eventName:e,windowName:t?t.name:null,func:n};this.handlers.push(o)}},{key:"authenticate",value:function(t){var e=this,n="".concat(this.origin,"/api/auth/login/").concat(t),o=window.screen.width/2-240,a=window.screen.height/2-300,i=["toolbar=no","location=no","directories=no","status=no","menubar=no","scrollbars=no","resizable=no","copyhistory=no","width=".concat(480),"height=".concat(600),"top=".concat(a),"left=".concat(o)];return new Promise((function(t,o){var a=window.open(n,"Authorization",i.join(", "));a||o("Failed to open window");var r=setInterval((function(){a.closed&&(c(),s())}),100),s=function(){o("User closed window")},c=function(){window.removeEventListener("message",l),clearInterval(r)},l=function(n){if(!e.isViibeEvent(n))return null;n.data.token&&(c(),t(n.data.token)),n.data.error&&(c(),o(n.data.error))};window.addEventListener("message",l)}))}}],o&&e(n.prototype,o),t}();"undefined"!=typeof window&&(window.Viibe=n),t.exports=n}},e={},n=function n(o){var a=e[o];if(void 0!==a)return a.exports;var i=e[o]={exports:{}};return t[o](i,i.exports,n),i.exports}(579);module.exports=n})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@viibe/impulse-integration-js",
3
- "version": "2.2.3",
3
+ "version": "2.3.1",
4
4
  "description": "ViiBE integration in js native",
5
5
  "main": "index.js",
6
6
  "publishConfig": {
package/src/index.js CHANGED
@@ -1,10 +1,21 @@
1
1
  class Viibe {
2
2
 
3
+ /**
4
+ * @typedef Handler
5
+ * @type {object}
6
+ * @property {string} eventName The name of the event to handle
7
+ * @property {string} windowName The name of the window / iframe to listen to
8
+ * @property {Function} func The function to trigger when an event is received
9
+ */
10
+
3
11
  constructor(options) {
12
+ /**
13
+ * @type {Handler[]}
14
+ */
15
+ this.handlers = []
4
16
  this.host = options.host
5
17
  this.origin = /^localhost/.test(this.host) ? `http://${this.host}` : `https://${this.host}`
6
18
  this.source = options.source
7
- this.handlers = {}
8
19
 
9
20
  window.addEventListener('message', this.onMessage.bind(this))
10
21
  }
@@ -16,6 +27,7 @@ class Viibe {
16
27
  const src = this.createCallUrl(options)
17
28
 
18
29
  const iframe = document.createElement('iframe')
30
+ iframe.name = 'viibe-' + Math.floor(Math.random() * 10000)
19
31
  iframe.style = 'border: 0;width: calc(100% - 1rem);margin: 0.5rem;'
20
32
  iframe.src = src
21
33
  iframe.allow = 'geolocation;autoplay;microphone;camera;midi;encrypted-media;clipboard-write;'
@@ -58,15 +70,15 @@ class Viibe {
58
70
 
59
71
  if (components) {
60
72
  let componentsParams = (components instanceof Array)
61
- ? components.join(',')
62
- : String(components)
73
+ ? components.join(',')
74
+ : String(components)
63
75
 
64
76
  params.set('components', componentsParams)
65
77
  }
66
78
 
67
79
  params.set('clipboard', Boolean(clipboard))
68
80
  params.set('o2m', Boolean(o2m))
69
-
81
+
70
82
  src += `?${params}`;
71
83
 
72
84
  return src
@@ -76,39 +88,80 @@ class Viibe {
76
88
  return Boolean(event.isTrusted && event.origin.indexOf(this.origin) === 0)
77
89
  }
78
90
 
79
- dispatch(eventName, payload) {
80
- const eventHandlers = this.handlers[eventName];
81
- if(!eventHandlers) {
82
- return null
83
- }
84
- return eventHandlers.map(handler => handler(payload))
91
+ /**
92
+ * Dispatches an event ie calls handlers corresponding to that event.
93
+ * Handlers with not windowName will be triggered regardless of the origin windowName
94
+ * Otherwise, the event will be triggered only if the handler windowName and the event windowName correspond
95
+ *
96
+ * @param {string} eventName
97
+ * @param {any} payload
98
+ * @param {string} windowName
99
+ * @returns
100
+ */
101
+ dispatch(eventName, payload, windowName) {
102
+ return this.handlers
103
+ .filter(handler =>
104
+ handler.eventName === eventName
105
+ && (!handler.windowName || (handler.windowName === windowName))
106
+ )
107
+ .map(handler => handler.func(payload))
85
108
  }
86
109
 
110
+ /**
111
+ * Handles postMessages / events received on the current window
112
+ * @param {any} event
113
+ * @returns
114
+ */
87
115
  onMessage(event) {
88
- if(!this.isViibeEvent(event)) {
116
+ if (!this.isViibeEvent(event)) {
89
117
  return null
90
118
  }
91
119
 
92
- if(event.data && event.data.event && event.data.payload) {
93
- return this.dispatch(event.data.event, event.data.payload)
120
+ if (event.data && event.data.event && event.data.payload) {
121
+ return this.dispatch(event.data.event, event.data.payload, event.data.windowName)
94
122
  }
95
123
 
96
124
  // FIXME: legacy authentication messages
97
- if(event.data && event.data.token) {
125
+ if (event.data && event.data.token) {
98
126
  return this.dispatch('authentication:token', event.data.token)
99
127
  }
100
- if(event.data && event.data.error) {
128
+ if (event.data && event.data.error) {
101
129
  return this.dispatch('authentication:error', event.data.error)
102
130
  }
103
131
 
104
132
  return null
105
133
  }
106
134
 
107
- on(eventName, handler) {
108
- const eventHandlers = this.handlers[eventName] = this.handlers[eventName] || []
109
- eventHandlers.push(handler);
135
+ /**
136
+ * Registers an event handler.
137
+ * Can be either called with 2 arguments (eventName and handler) to catch events from all iframes
138
+ * or with 3 arguments (iframe, eventName, handler) to catch events from only that iframe
139
+ * @param {HTMLIFrameElement} [iframe]
140
+ * @param {string} eventName
141
+ * @param {Function} handler
142
+ */
143
+ on(iframe, eventName, func) {
144
+ if (typeof iframe === 'string'
145
+ && typeof eventName === 'function'
146
+ && typeof func === 'undefined') {
147
+ func = eventName;
148
+ eventName = iframe;
149
+ iframe = null;
150
+ }
151
+
152
+ const handler = {
153
+ eventName,
154
+ windowName: iframe ? iframe.name : null,
155
+ func,
156
+ }
157
+ this.handlers.push(handler);
110
158
  }
111
-
159
+
160
+ /**
161
+ * Initiates an oauth login in a popup using the passed provider
162
+ * @param {string} provider A strategy name from the Viibe API (see /strategies API)
163
+ * @returns
164
+ */
112
165
  authenticate(provider) {
113
166
  const src = `${this.origin}/api/auth/login/${provider}`
114
167
  const width = 480
@@ -134,47 +187,57 @@ class Viibe {
134
187
 
135
188
  return new Promise((resolve, reject) => {
136
189
  const win = window.open(src, 'Authorization', windowParams.join(', '))
137
-
190
+
191
+ if (!win) {
192
+ reject('Failed to open window')
193
+ }
194
+
195
+ // pings the login window to check if it was closed
138
196
  const closeCheck = setInterval(() => {
139
- if(win.closed) {
197
+ if (win.closed) {
140
198
  destroy();
141
199
  onClose();
142
200
  }
201
+
143
202
  }, 100)
144
203
 
204
+ // triggered if the window was closed
145
205
  const onClose = () => {
146
206
  reject('User closed window')
147
207
  }
148
208
 
209
+ // completes the process, either because the user closes or because the authentication completed
210
+ // cleans intervals and event listeners
149
211
  const destroy = () => {
150
212
  window.removeEventListener('message', onMessage)
151
213
  clearInterval(closeCheck)
152
214
  }
153
215
 
216
+ // triggered when a message is received on the current window
154
217
  const onMessage = event => {
155
- if(!this.isViibeEvent(event)) {
218
+ if (!this.isViibeEvent(event)) {
156
219
  return null
157
220
  }
158
- if(event.data.token) {
221
+ if (event.data.token) {
159
222
  destroy();
160
223
  resolve(event.data.token)
161
224
  }
162
- if(event.data.error) {
225
+ if (event.data.error) {
163
226
  destroy();
164
227
  reject(event.data.error)
165
228
  }
166
229
  }
167
-
230
+
168
231
  window.addEventListener('message', onMessage)
169
232
  })
170
-
233
+
171
234
  }
172
235
 
173
236
  }
174
237
 
175
- if(typeof window !== 'undefined') {
238
+ if (typeof window !== 'undefined') {
176
239
  window.Viibe = Viibe
177
240
  }
178
- if(typeof module !== 'undefined') {
241
+ if (typeof module !== 'undefined') {
179
242
  module.exports = Viibe
180
243
  }