evmux-app-framework 0.0.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.
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # evmuxAppFramework
package/package.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "evmux-app-framework",
3
+ "version": "0.0.1",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "build": "webpack",
8
+ "build:prod": "webpack --mode production",
9
+ "dev": "webpack serve --mode development",
10
+ "test": "echo \"Error: no test specified\" && exit 1"
11
+ },
12
+ "keywords": [],
13
+ "author": "",
14
+ "license": "ISC",
15
+ "devDependencies": {
16
+ "html-webpack-plugin": "^5.5.0",
17
+ "webpack": "^5.75.0",
18
+ "webpack-cli": "^5.0.0",
19
+ "webpack-dev-server": "^4.11.1"
20
+ }
21
+ }
@@ -0,0 +1,52 @@
1
+
2
+
3
+ import { createPromise, generateGuid, pubSub } from '../EvmuxAppsApi/HelpersFromCore'
4
+
5
+
6
+ export class AppsDataManager {
7
+ /*
8
+ _requests: {} */
9
+
10
+ constructor(){
11
+ this._userApps = {}
12
+ this._userAppInstances = {}
13
+ }
14
+
15
+
16
+ updateUserAppData(appId, appData, merge = false) {
17
+ if (!merge || !this._userApps[appId]) {
18
+ this._userApps[appId] = appData;
19
+ }
20
+ else {
21
+ this._userApps[appId] = { ...this._userApps[appId], ...appData };
22
+ }
23
+ }
24
+
25
+ updateUserAppInstance(instanceId, instanceData, merge = false) {
26
+ if (!merge || !this._userAppInstances[instanceId]) {
27
+ this._userAppInstances[instanceId] = instanceData;
28
+ }
29
+ else {
30
+ this._userAppInstances[instanceId] = { ...this._userAppInstances[instanceId], ...instanceData };
31
+ }
32
+ }
33
+
34
+ async getUserAppDataByAppId(userAppId) {
35
+ return this._userApps[userAppId];
36
+ }
37
+
38
+ async getUserAppInstanceById(userInstanceId, includeAppData = false) {
39
+
40
+ let appInstance = this._userAppInstances[userInstanceId];
41
+
42
+ if (appInstance && includeAppData)
43
+ {
44
+ appInstance.appData = await this.getUserAppDataByAppId(appInstance.userAppId)
45
+ }
46
+
47
+ return appInstance;
48
+ }
49
+ }
50
+
51
+ let appsDataManager = new AppsDataManager();
52
+ export default appsDataManager;
@@ -0,0 +1,131 @@
1
+
2
+
3
+ import { createPromise, generateGuid, pubSub } from '../EvmuxAppsApi/HelpersFromCore'
4
+
5
+ import PostMessageManager from '../PostMessageManager/PostMessageManager';
6
+ import appsDataManager from '../AppsDataManager/AppsDataManager';
7
+
8
+ let createEventResultObject = (eventName, result) => {
9
+
10
+ let eventObj = {
11
+ requestName: "EvEvent",
12
+ eventName,
13
+ data: {...result}
14
+ }
15
+ return eventObj;
16
+ }
17
+
18
+
19
+ class AppsObserver {
20
+ /*
21
+ _requests: {} */
22
+
23
+ constructor(){
24
+ this._userAppInstances = {}
25
+ this._messagesEventHandlers = new pubSub()
26
+ this._eventHandler = new pubSub()
27
+ window.onmessage = this.onPostMessage.bind(this);
28
+ }
29
+
30
+ raiseEvent(eventName, data) {
31
+
32
+ }
33
+
34
+ getAppSettingsForAppInstanceId(appInstanceId)
35
+ {
36
+ return {}
37
+ }
38
+
39
+ _makeSureAppInstanceExist(userAppInstanceId)
40
+ {
41
+ this._userAppInstances[userAppInstanceId] = this._userAppInstances[userAppInstanceId] || { }
42
+ this._userAppInstances[userAppInstanceId].instances = this._userAppInstances[userAppInstanceId].instances || {};
43
+ this._userAppInstances[userAppInstanceId].events = this._userAppInstances[userAppInstanceId].events || {};
44
+ }
45
+
46
+ async onPostMessage(evt) {
47
+
48
+ let requestObj = {};
49
+ try {
50
+ requestObj = JSON.parse(evt.data);
51
+ } catch (error) {
52
+ console.log("xxxx", error)
53
+ }
54
+
55
+ let result = null
56
+
57
+ if (requestObj.request == "updateSettings")
58
+ {
59
+
60
+ if (this._userAppInstances[requestObj.userAppInstanceId]) {
61
+
62
+
63
+ this._eventHandler.publish("updateSettings", requestObj)
64
+
65
+ if (this._userAppInstances[requestObj.userAppInstanceId].events['settingsUpdated'])
66
+ {
67
+ let eventObj = createEventResultObject("settingsUpdated", requestObj.data)
68
+ let stringObjToSend = JSON.stringify(eventObj)
69
+ for (const [key, instanceWindow] of Object.entries(this._userAppInstances[requestObj.userAppInstanceId].instances)) {
70
+ instanceWindow.window.postMessage(stringObjToSend, "*")
71
+ }
72
+ }
73
+
74
+ }
75
+ }
76
+ else if (requestObj.request == "getSettings")
77
+ {
78
+
79
+ if (this._userAppInstances[requestObj.userAppInstanceId]) {
80
+
81
+ let eventObj = createEventResultObject("settings", requestObj.data)
82
+ let stringObjToSend = JSON.stringify(eventObj)
83
+ result = (await appsDataManager.getUserAppInstanceById(requestObj.userAppInstanceId, false)).settings
84
+ //this._userAppInstances[requestObj.userAppInstanceId].window.postMessage(stringObjToSend, "*")
85
+
86
+ }
87
+ }
88
+ else if (requestObj.request == "startLoad")
89
+ {
90
+ this._makeSureAppInstanceExist(requestObj.userAppInstanceId);
91
+ this._userAppInstances[requestObj.userAppInstanceId].instances[requestObj.componentId] = { window: evt.source }
92
+ return;
93
+ }
94
+ else if (requestObj.request == "loaded")
95
+ {
96
+ this._makeSureAppInstanceExist(requestObj.userAppInstanceId);
97
+
98
+ this._userAppInstances[requestObj.userAppInstanceId].instances[requestObj.componentId] = { window: evt.source }
99
+
100
+ result = this.getAppSettingsForAppInstanceId(requestObj.userAppInstanceId)
101
+ }
102
+ else if (requestObj.request == "registerEvent")
103
+ {
104
+ // verify that the app can register to this event
105
+ this._makeSureAppInstanceExist(requestObj.userAppInstanceId);
106
+ this._userAppInstances[requestObj.userAppInstanceId].events[requestObj.data.eventName] = true
107
+ }
108
+ else if (requestObj.request == "unregisterEvent")
109
+ {
110
+ this._makeSureAppInstanceExist(requestObj.userAppInstanceId);
111
+ delete this._userAppInstances[requestObj.userAppInstanceId].events[requestObj.data.eventName]
112
+ }
113
+
114
+ PostMessageManager.respondForPromiseBasedRequest(requestObj, evt.source, evt.origin, result);
115
+
116
+ }
117
+
118
+ onUserAppComponentUnload(userAppInstanceId, componentId)
119
+ {
120
+ if (this._userAppInstances[userAppInstanceId].instances[componentId]) {
121
+ delete this._userAppInstances[userAppInstanceId].instances[componentId]
122
+ if (Object.keys(this._userAppInstances[userAppInstanceId].instances).length == 0)
123
+ {
124
+ delete this._userAppInstances[userAppInstanceId]
125
+ }
126
+ }
127
+ }
128
+ }
129
+
130
+
131
+ export default new AppsObserver();
@@ -0,0 +1,75 @@
1
+ import PostMessageManager from '../PostMessageManager/PostMessageManager.js'
2
+
3
+ const availableEvents = ["settingsUpdated", "viewerCountChanged", ""]
4
+
5
+ export default class EvmuxAppsApi {
6
+
7
+ constructor(userAppInstanceId, componentId) {
8
+ if (userAppInstanceId == null)
9
+ {
10
+ let appIdFromUrl = new URLSearchParams(window.location.search).get("appInstanceId");
11
+
12
+ if (appIdFromUrl !== null)
13
+ userAppInstanceId = appIdFromUrl;
14
+ }
15
+
16
+ if (componentId == undefined)
17
+ {
18
+ let componentIdFromUrl = new URLSearchParams(window.location.search).get("compId");
19
+
20
+ if (componentIdFromUrl !== null)
21
+ componentId = componentIdFromUrl;
22
+ }
23
+
24
+ this._postMessageManager = new PostMessageManager();
25
+ this._userAppInstanceId = userAppInstanceId;
26
+ this._componentId = componentId;
27
+
28
+ let reqObj = {request: "startLoad", userAppInstanceId: this._userAppInstanceId, componentId: this._componentId}
29
+ this._postMessageManager.sendRequest(reqObj);
30
+
31
+ }
32
+
33
+ async registerEvent(eventName, callback)
34
+ {
35
+ this._postMessageManager._messagesEventHandlers.subscribe(eventName, callback)
36
+
37
+ let reqObj = { request: "registerEvent", userAppInstanceId: this._userAppInstanceId, componentId: this._componentId }
38
+ reqObj.data = {
39
+ eventName
40
+ }
41
+ return this._postMessageManager.sendRequestAsync(reqObj);
42
+ }
43
+
44
+ async unregisterEvent(eventName, callback)
45
+ {
46
+ this._postMessageManager._messagesEventHandlers.unsubscribe(eventName, callback)
47
+ let reqObj = { request: "unregisterEvent", userAppInstanceId: this._userAppInstanceId, componentId: this._componentId }
48
+ reqObj.data = {
49
+ eventName
50
+ }
51
+ return this._postMessageManager.sendRequestAsync(reqObj);
52
+ }
53
+
54
+ async reportLoaded() {
55
+ let reqObj = {request: "loaded", userAppInstanceId: this._userAppInstanceId, componentId: this._componentId}
56
+ return this._postMessageManager.sendRequestAsync(reqObj);
57
+ }
58
+
59
+ async getSettings() {
60
+
61
+ let reqObj = {request: "getSettings", userAppInstanceId: this._userAppInstanceId, componentId: this._componentId}
62
+ return this._postMessageManager.sendRequestAsync(reqObj);
63
+ }
64
+
65
+ async updateSettings(settingsObj) {
66
+
67
+ let requestObj = {
68
+ request: "updateSettings",
69
+ userAppInstanceId: this._userAppInstanceId,
70
+ componentId: this._componentId,
71
+ data: { ...settingsObj }
72
+ }
73
+ return this._postMessageManager.sendRequestAsync(requestObj);
74
+ }
75
+ }
@@ -0,0 +1,85 @@
1
+ export function createPromise(){
2
+ let resolve = null
3
+ let reject = null
4
+
5
+ let prom = new Promise((resolveF, rejectF) => {
6
+ resolve = resolveF
7
+ reject = rejectF
8
+ } )
9
+
10
+ return [prom, resolve, reject]
11
+ }
12
+
13
+ export function generateGuid() {
14
+ var result, i, j;
15
+ result = '';
16
+ for(j=0; j<32; j++) {
17
+ if( j == 8 || j == 12 || j == 16 || j == 20)
18
+ result = result + '-';
19
+ i = Math.floor(Math.random()*16).toString(16).toUpperCase();
20
+ result = result + i;
21
+ }
22
+ return result.toLowerCase();
23
+ }
24
+
25
+
26
+
27
+ export class pubSub
28
+ {
29
+ // this.subscribers = {};
30
+
31
+ constructor() {
32
+ this.subscribers = {};
33
+ }
34
+ init() {
35
+ }
36
+
37
+ publish(eventName, data /* EventArgs */) {
38
+ if (!Array.isArray(this.subscribers[eventName]))
39
+ return;
40
+
41
+ this.subscribers[eventName].forEach(
42
+ (subscriberCallback) => {
43
+ try{
44
+ subscriberCallback(eventName, data)
45
+ }catch (e) {
46
+ console.error(e)
47
+ }
48
+ });
49
+ }
50
+
51
+
52
+ subscribe(eventName, callback) {
53
+ if (!Array.isArray(this.subscribers[eventName])) {
54
+ this.subscribers[eventName] = [];
55
+ }
56
+ if (this.subscribers[eventName].indexOf(callback) >= 0)
57
+ return () => this.unsubscribe(eventName, callback);
58
+ this.subscribers[eventName].push(callback);
59
+
60
+ return () => this.unsubscribe(eventName, callback);
61
+
62
+ }
63
+
64
+ unsubscribe(eventName, callback) {
65
+
66
+ if (!Array.isArray(this.subscribers[eventName])) {
67
+ return false;
68
+ }
69
+
70
+ if (this.subscribers[eventName].indexOf(callback) < 0)
71
+ return false;
72
+
73
+ this.subscribers[eventName] = this.subscribers[eventName].filter((cb) => {
74
+ // Does not include the callback in the new array
75
+ if (cb === callback) {
76
+ return false
77
+ }
78
+ return true
79
+ });
80
+
81
+ }
82
+
83
+
84
+ }
85
+
@@ -0,0 +1,80 @@
1
+
2
+
3
+ import {createPromise, generateGuid, pubSub} from '../EvmuxAppsApi/HelpersFromCore'
4
+
5
+
6
+ export default class PostMessageManager {
7
+ /*
8
+ _requests: {} */
9
+
10
+ constructor(){
11
+ this._requests = {};
12
+ this._messagesEventHandlers = new pubSub()
13
+ window.onmessage = this.onPostMessage.bind(this);
14
+ }
15
+
16
+ static respondForPromiseBasedRequest(requestObj, targetWindow, targetAdress = '*', result)
17
+ {
18
+ if (targetAdress == 'null')
19
+ targetAdress = '*'
20
+ if (requestObj.promisedBased)
21
+ {
22
+ let objectToAttach = {requestGuid: requestObj.requestGuid, response: result}
23
+ targetWindow.postMessage(JSON.stringify(objectToAttach), '*');
24
+ }
25
+ }
26
+
27
+ async sendRequestAsync(requestObj, targetWindow = null) {
28
+
29
+ let reqId = generateGuid();
30
+ let [prom, resolve, reject] = createPromise();
31
+
32
+ this._requests[reqId] = {
33
+ prom,
34
+ resolve,
35
+ reject,
36
+ }
37
+
38
+ requestObj.requestGuid = reqId;
39
+ requestObj.promisedBased = true;
40
+
41
+ targetWindow = targetWindow ? targetWindow : window.parent;
42
+ targetWindow.postMessage(JSON.stringify(requestObj), "*");
43
+
44
+ return prom;
45
+ }
46
+
47
+ sendRequest(requestObj, targetWindow = null) {
48
+
49
+ let reqId = generateGuid();
50
+
51
+ requestObj.requestGuid = reqId;
52
+
53
+ targetWindow = targetWindow ? targetWindow : window.parent;
54
+ targetWindow.postMessage(JSON.stringify(requestObj), "*");
55
+ }
56
+
57
+
58
+ onPostMessage(evt) {
59
+ try {
60
+ let reqObj = evt && JSON.parse(evt.data)
61
+ if (reqObj.requestGuid && this._requests[reqObj.requestGuid])
62
+ {
63
+ let res = this._requests[reqObj.requestGuid];
64
+ delete this._requests[reqObj.requestGuid]
65
+ return res.resolve(reqObj)
66
+ }
67
+ else if (reqObj.requestName == "EvEvent")
68
+ {
69
+ this._messagesEventHandlers.publish(reqObj.eventName, reqObj.data)
70
+ }
71
+ } catch (error) {
72
+
73
+ }
74
+
75
+ }
76
+
77
+ unregisterFromEvents(){
78
+
79
+ }
80
+ }