Skip to content

Commit a5dbf54

Browse files
authored
Merge pull request #34 from EkoLabs/eko-embed-v3
Introducing a new embedapi version '3.0' to load and play eko blueprint instances.
2 parents 64311ab + a681c9b commit a5dbf54

File tree

9 files changed

+761
-116
lines changed

9 files changed

+761
-116
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@ekolabs/eko-js-sdk",
3-
"version": "0.0.18",
3+
"version": "0.1.0",
44
"description": "A lightweight SDK that allows for easy integration of eko videos into webpages.",
55
"main": "dist/EkoPlayer.min.js",
66
"license": "Apache-2.0",

src/EkoPlayer.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ class EkoPlayer {
104104
/**
105105
* Will load and display an eko project.
106106
*
107-
* @param {string} id - id of the project to load
107+
* @param {string} id - id of the eko content, a studio project or a blueprint instance, to load
108108
* @param {object} [options] - loading options
109109
* @param {object} [options.params] - A list of embed params that will affect the delivery. Default includes {autoplay: true}.
110110
* @param {string[]} [options.events] - A list of events that should be forwarded to the app.
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import EventEmitter from 'eventemitter3';
2+
import ekoPlatform from '../ekoPlatform';
3+
import { stringifyQueryParams } from '../queryParamsUtils';
4+
import deepmerge from 'deepmerge';
5+
6+
class EkoEmbedDeliveryBase {
7+
constructor(embedapi, embedpath, iframe) {
8+
this.embedapi = embedapi || '2.0';
9+
this.embedpath = embedpath || '/';
10+
this.iframe = iframe;
11+
this.eventEmitter = new EventEmitter();
12+
this.onEkoEventFired = this.onEkoEventFired.bind(this);
13+
this.addIframeListeners();
14+
15+
return {
16+
load: this.load.bind(this),
17+
invoke: this.invoke.bind(this),
18+
on: this.on.bind(this),
19+
off: this.off.bind(this),
20+
once: this.once.bind(this),
21+
dispose: this.dispose.bind(this)
22+
};
23+
}
24+
25+
26+
load(id, options) {
27+
let embedParams = {
28+
id,
29+
embedapi: this.embedapi,
30+
embedid: this.iframe.id,
31+
events: options.events.join(',')
32+
};
33+
embedParams = deepmerge.all([embedParams, options.params]);
34+
35+
let clientSideParams = options.clientSideParams;
36+
if (clientSideParams && (typeof clientSideParams === 'object' || typeof clientSideParams === 'function')) {
37+
// Normalize clientSideParams - if it's an object, convert it into a function that returns that object
38+
if (typeof clientSideParams === 'object') {
39+
const cspObj = clientSideParams;
40+
clientSideParams = () => cspObj;
41+
}
42+
43+
embedParams.csp = true;
44+
this.once('loader.csp.ready', () => {
45+
Promise.resolve()
46+
.then(clientSideParams)
47+
.then((csp) => {
48+
this.iframe.contentWindow.postMessage({ target: 'loader', csp }, '*');
49+
});
50+
});
51+
}
52+
53+
// Finally, let's set the iframe's src to begin loading the project
54+
this.iframe.setAttribute(
55+
'src',
56+
`https://${options.env || ''}embed.eko.com${this.embedpath}?${stringifyQueryParams(embedParams)}`
57+
);
58+
}
59+
60+
invoke(method, args) {
61+
if (typeof method !== 'string') {
62+
throw new Error('Expected required argument method to have type string');
63+
}
64+
65+
const action = {
66+
target: 'embedapi',
67+
playerProperty: `${method}`,
68+
args: args
69+
};
70+
71+
this.iframe.contentWindow.postMessage(action, '*');
72+
}
73+
on(eventName, callback) {
74+
this.eventEmitter.on(eventName, callback);
75+
}
76+
77+
off(eventName, callback) {
78+
this.eventEmitter.off(eventName, callback);
79+
}
80+
81+
once(eventName, callback) {
82+
this.eventEmitter.once(eventName, callback);
83+
}
84+
85+
dispose() {
86+
this.removeIframeListeners();
87+
}
88+
89+
///////////////////////////
90+
// PRIVATE FUNCTIONS
91+
//////////////////////////
92+
addIframeListeners() {
93+
window.addEventListener('message', this.onEkoEventFired);
94+
}
95+
96+
removeIframeListeners() {
97+
window.removeEventListener('message', this.onEkoEventFired);
98+
}
99+
100+
onEkoEventFired(event) {
101+
if (!ekoPlatform.isEkoDomain(event.origin)) {
102+
return;
103+
}
104+
105+
const msg = event.data;
106+
107+
// Do nothing if this message was not intended for us
108+
if (!msg.event || msg.embedid !== this.iframe.id || msg.embedapi !== this.embedapi) {
109+
return;
110+
}
111+
112+
this.eventEmitter.emit(msg.event, ...msg.args);
113+
}
114+
}
115+
116+
export default EkoEmbedDeliveryBase;

src/lib/ekoEmbed/factory.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import v1 from './v1';
22
import v2 from './v2';
3+
import v3 from './v3';
34

45
const imples = {
56
'1.0': v1,
6-
'2.0': v2
7+
'2.0': v2,
8+
'3.0': v3
79
};
810

911
function create(iframe, embedapiVersion) {

src/lib/ekoEmbed/v2.js

Lines changed: 5 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1,113 +1,10 @@
1-
import EventEmitter from 'eventemitter3';
2-
import ekoPlatform from '../ekoPlatform';
3-
import { stringifyQueryParams } from '../queryParamsUtils';
4-
import deepmerge from 'deepmerge';
1+
import EkoEmbedDeliveryBase from './EkoEmbedDeliveryBase';
52

6-
class EkoEmbedV2 {
7-
constructor(iframe) {
8-
this.iframe = iframe;
9-
this.eventEmitter = new EventEmitter();
10-
this.onEkoEventFired = this.onEkoEventFired.bind(this);
11-
this.addIframeListeners();
12-
13-
return {
14-
load: this.load.bind(this),
15-
invoke: this.invoke.bind(this),
16-
on: this.on.bind(this),
17-
off: this.off.bind(this),
18-
once: this.once.bind(this),
19-
dispose: this.dispose.bind(this)
20-
};
21-
}
22-
23-
24-
load(id, options) {
25-
let embedParams = {
26-
id,
27-
embedapi: '2.0',
28-
embedid: this.iframe.id,
29-
events: options.events.join(',')
30-
};
31-
embedParams = deepmerge.all([embedParams, options.params]);
32-
33-
let clientSideParams = options.clientSideParams;
34-
if (clientSideParams && (typeof clientSideParams === 'object' || typeof clientSideParams === 'function')) {
35-
// Normalize clientSideParams - if it's an object, convert it into a function that returns that object
36-
if (typeof clientSideParams === 'object') {
37-
const cspObj = clientSideParams;
38-
clientSideParams = () => cspObj;
39-
}
40-
41-
embedParams.csp = true;
42-
this.once('loader.csp.ready', () => {
43-
Promise.resolve()
44-
.then(clientSideParams)
45-
.then((csp) => {
46-
this.iframe.contentWindow.postMessage({ target: 'loader', csp }, '*');
47-
});
48-
});
49-
}
50-
51-
// Finally, let's set the iframe's src to begin loading the project
52-
this.iframe.setAttribute(
53-
'src',
54-
`https://${options.env || ''}embed.eko.com/?${stringifyQueryParams(embedParams)}`
55-
);
56-
}
57-
58-
invoke(method, args) {
59-
if (typeof method !== 'string') {
60-
throw new Error('Expected required argument method to have type string');
61-
}
62-
63-
const action = {
64-
target: 'embedapi',
65-
playerProperty: `${method}`,
66-
args: args
67-
};
68-
69-
this.iframe.contentWindow.postMessage(action, '*');
70-
}
71-
on(eventName, callback) {
72-
this.eventEmitter.on(eventName, callback);
73-
}
3+
const INSTANCE_EMBED_API = '2.0';
744

75-
off(eventName, callback) {
76-
this.eventEmitter.off(eventName, callback);
77-
}
78-
79-
once(eventName, callback) {
80-
this.eventEmitter.once(eventName, callback);
81-
}
82-
83-
dispose() {
84-
this.removeIframeListeners();
85-
}
86-
87-
///////////////////////////
88-
// PRIVATE FUNCTIONS
89-
//////////////////////////
90-
addIframeListeners() {
91-
window.addEventListener('message', this.onEkoEventFired);
92-
}
93-
94-
removeIframeListeners() {
95-
window.removeEventListener('message', this.onEkoEventFired);
96-
}
97-
98-
onEkoEventFired(event) {
99-
if (!ekoPlatform.isEkoDomain(event.origin)) {
100-
return;
101-
}
102-
103-
const msg = event.data;
104-
105-
// Do nothing if this message was not intended for us
106-
if (!msg.event || msg.embedid !== this.iframe.id || msg.embedapi !== '2.0') {
107-
return;
108-
}
109-
110-
this.eventEmitter.emit(msg.event, ...msg.args);
5+
class EkoEmbedV2 extends EkoEmbedDeliveryBase {
6+
constructor(iframe) {
7+
super(INSTANCE_EMBED_API, '/', iframe);
1118
}
1129
}
11310

src/lib/ekoEmbed/v3.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import EkoEmbedDeliveryBase from './EkoEmbedDeliveryBase';
2+
3+
const INSTANCE_EMBED_API = '3.0';
4+
const DELIVERY_SRV_INSTANCE_PATH = '/instance';
5+
6+
class EkoEmbedV3 extends EkoEmbedDeliveryBase {
7+
constructor(iframe) {
8+
super(INSTANCE_EMBED_API, DELIVERY_SRV_INSTANCE_PATH, iframe);
9+
}
10+
}
11+
12+
export default EkoEmbedV3;

test/integration/ekoDelivery/v2.test.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -176,14 +176,12 @@ describe('ekoPlayer.load()', () => {
176176
});
177177

178178
// Get autoplay query string value
179-
const getQueryParamValue = async(key) => {
180-
const retVal = await page.evaluate((param) => {
179+
const getQueryParamValue = (key) => {
180+
return page.evaluate((param) => {
181181
const iframeSrc = document.querySelector('iframe').getAttribute('src');
182182
const iframeURL = new URL(iframeSrc);
183183
return iframeURL.searchParams.get(param);
184184
}, key);
185-
186-
return retVal;
187185
};
188186

189187
expect(await getQueryParamValue('autoplay')).toEqual('true');
@@ -393,7 +391,7 @@ describe('ekoPlayer.load()', () => {
393391
await page.goto(`file://${__dirname}/../app.html?autoplay=false`);
394392

395393
const overrideId = 'abcde';
396-
const overrideEmbedapi = '3.0';
394+
const overrideEmbedapi = '2.1';
397395

398396
// Init EkoPlayer
399397
await page.evaluate((id, api) => {

0 commit comments

Comments
 (0)