neo.mjs 4.0.5 → 4.0.8
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/examples/remotesApi/basic/remotes-api-response.json +3 -0
- package/examples/remotesApi/basic/remotes-api.json +13 -12
- package/examples/tab/container/neo-config.json +1 -1
- package/package.json +4 -4
- package/src/collection/Base.mjs +1 -1
- package/src/data/connection/Fetch.mjs +21 -15
- package/src/data/connection/WebSocket.mjs +227 -0
- package/src/manager/RpcApi.mjs +46 -0
- package/src/manager/RpcMessage.mjs +135 -0
- package/src/remotes/Api.mjs +14 -10
- package/src/util/Function.mjs +28 -11
- package/src/worker/Data.mjs +22 -6
- package/src/data/connection/Socket.mjs +0 -24
- package/src/manager/RemotesApi.mjs +0 -40
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"namespace": "MyApi",
|
|
3
|
-
"url" : "
|
|
3
|
+
"url" : "../../examples/remotesApi/basic/remotes-api-response.json",
|
|
4
4
|
|
|
5
|
-
"services":
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
5
|
+
"services": {
|
|
6
|
+
"FriendService": {
|
|
7
|
+
"methods": {
|
|
8
|
+
"getAll": {}
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
"UserService": {
|
|
12
|
+
"methods": {
|
|
13
|
+
"getAll": {}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
16
17
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "neo.mjs",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.8",
|
|
4
4
|
"description": "The webworkers driven UI framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -40,16 +40,16 @@
|
|
|
40
40
|
"autoprefixer": "^10.4.4",
|
|
41
41
|
"chalk": "^5.0.1",
|
|
42
42
|
"clean-webpack-plugin": "^4.0.0",
|
|
43
|
-
"commander": "^9.
|
|
43
|
+
"commander": "^9.2.0",
|
|
44
44
|
"cssnano": "^5.1.7",
|
|
45
45
|
"envinfo": "^7.8.1",
|
|
46
|
-
"fs-extra": "^10.0
|
|
46
|
+
"fs-extra": "^10.1.0",
|
|
47
47
|
"highlightjs-line-numbers.js": "^2.8.0",
|
|
48
48
|
"inquirer": "^8.2.2",
|
|
49
49
|
"neo-jsdoc": "^1.0.1",
|
|
50
50
|
"neo-jsdoc-x": "^1.0.4",
|
|
51
51
|
"postcss": "^8.4.12",
|
|
52
|
-
"sass": "^1.50.
|
|
52
|
+
"sass": "^1.50.1",
|
|
53
53
|
"webpack": "^5.72.0",
|
|
54
54
|
"webpack-cli": "^4.9.2",
|
|
55
55
|
"webpack-dev-server": "4.8.1",
|
package/src/collection/Base.mjs
CHANGED
|
@@ -705,7 +705,7 @@ class Base extends CoreBase {
|
|
|
705
705
|
/**
|
|
706
706
|
* Returns all items which match the property and value
|
|
707
707
|
* @param {Object|String} property
|
|
708
|
-
* @param {String|Number} value
|
|
708
|
+
* @param {String|Number} [value] Optional, in case the first param is an object
|
|
709
709
|
* @returns {Array} Returns an empty Array in case no items are found
|
|
710
710
|
*/
|
|
711
711
|
find(property, value) {
|
|
@@ -95,24 +95,30 @@ class Fetch extends Base {
|
|
|
95
95
|
if (!Neo.isString(url)) {
|
|
96
96
|
config = url;
|
|
97
97
|
url = config.url;
|
|
98
|
+
} else {
|
|
99
|
+
config.url = config;
|
|
98
100
|
}
|
|
99
101
|
|
|
100
|
-
return fetch(url
|
|
101
|
-
|
|
102
|
-
|
|
102
|
+
return fetch(url, {
|
|
103
|
+
body : data,
|
|
104
|
+
method: method || config.method
|
|
105
|
+
}).then(resp => {
|
|
106
|
+
let response = {
|
|
107
|
+
ok : resp.ok,
|
|
108
|
+
redirected: resp.redirected,
|
|
109
|
+
request : config,
|
|
110
|
+
status : resp.status,
|
|
111
|
+
statusText: resp.statusText,
|
|
112
|
+
type : resp.type,
|
|
113
|
+
url : resp.url
|
|
114
|
+
};
|
|
103
115
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
type : resp.type,
|
|
111
|
-
url : resp.url
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
return response
|
|
115
|
-
})
|
|
116
|
+
return resp[config.responseType || 'json']()
|
|
117
|
+
.then(data => {
|
|
118
|
+
response.data = data;
|
|
119
|
+
})
|
|
120
|
+
.then(() => (resp.ok ? response : Promise.reject(response)));
|
|
121
|
+
})
|
|
116
122
|
}
|
|
117
123
|
}
|
|
118
124
|
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import Base from '../../core/Base.mjs';
|
|
2
|
+
import NeoFunction from '../../util/Function.mjs';
|
|
3
|
+
import Observable from '../../core/Observable.mjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @class Neo.data.connection.WebSocket
|
|
7
|
+
* @extends Neo.core.Base
|
|
8
|
+
*/
|
|
9
|
+
class Socket extends Base {
|
|
10
|
+
/**
|
|
11
|
+
* @member {String|null} channel=null
|
|
12
|
+
*/
|
|
13
|
+
channel = null
|
|
14
|
+
/**
|
|
15
|
+
* @member {Number} maxReconnectAttempts=5
|
|
16
|
+
*/
|
|
17
|
+
maxReconnectAttempts = 5
|
|
18
|
+
/**
|
|
19
|
+
* @member {Number} reconnectAttempts=0
|
|
20
|
+
* @protected
|
|
21
|
+
*/
|
|
22
|
+
reconnectAttempts = 0
|
|
23
|
+
/**
|
|
24
|
+
* @member {String|null} serverAddress=null
|
|
25
|
+
*/
|
|
26
|
+
serverAddress = null
|
|
27
|
+
|
|
28
|
+
static getStaticConfig() {return {
|
|
29
|
+
/**
|
|
30
|
+
* True automatically applies the core.Observable mixin
|
|
31
|
+
* @member {Boolean} observable=true
|
|
32
|
+
* @static
|
|
33
|
+
*/
|
|
34
|
+
observable: true
|
|
35
|
+
}}
|
|
36
|
+
|
|
37
|
+
static getConfig() {return {
|
|
38
|
+
/**
|
|
39
|
+
* @member {String} className='Neo.data.connection.WebSocket'
|
|
40
|
+
* @protected
|
|
41
|
+
*/
|
|
42
|
+
className: 'Neo.data.connection.WebSocket',
|
|
43
|
+
/**
|
|
44
|
+
* @member {String} ntype='socket-connection'
|
|
45
|
+
* @protected
|
|
46
|
+
*/
|
|
47
|
+
ntype: 'socket-connection',
|
|
48
|
+
/**
|
|
49
|
+
* @member {WebSocket|null} socket_=null
|
|
50
|
+
* @protected
|
|
51
|
+
*/
|
|
52
|
+
socket_: null
|
|
53
|
+
}}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @param {Object} config
|
|
57
|
+
*/
|
|
58
|
+
construct(config) {
|
|
59
|
+
super.construct(config);
|
|
60
|
+
this.createSocket();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @param {Function} callback
|
|
65
|
+
* @param {Object} scope
|
|
66
|
+
*/
|
|
67
|
+
attemptReconnect(callback, scope) {
|
|
68
|
+
let me = this;
|
|
69
|
+
|
|
70
|
+
me.reconnectAttempts++;
|
|
71
|
+
|
|
72
|
+
if (me.reconnectAttempts < me.maxReconnectAttempts) {
|
|
73
|
+
me.createSocket();
|
|
74
|
+
|
|
75
|
+
callback && me.on('open', {
|
|
76
|
+
callback,
|
|
77
|
+
scope : scope || me,
|
|
78
|
+
single: true
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Intercepts the WebSocket send calls
|
|
85
|
+
* @param {Object} data
|
|
86
|
+
* @returns {String}
|
|
87
|
+
*/
|
|
88
|
+
beforeSend(data) {
|
|
89
|
+
let me = this,
|
|
90
|
+
channel = me.channel;
|
|
91
|
+
|
|
92
|
+
console.log('WS: Sending message', (channel ? '\nChannel: ' + channel : ''), '\nData:', data);
|
|
93
|
+
|
|
94
|
+
return JSON.stringify(channel ? {channel, data} : data);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Triggered before the socket config gets changed.
|
|
99
|
+
* @param {WebSocket|null} value
|
|
100
|
+
* @param {WebSocket|null} oldValue
|
|
101
|
+
* @returns {WebSocket|null}
|
|
102
|
+
* @protected
|
|
103
|
+
*/
|
|
104
|
+
beforeSetSocket(value, oldValue) {
|
|
105
|
+
if (value) {
|
|
106
|
+
let me = this;
|
|
107
|
+
|
|
108
|
+
Object.assign(value, {
|
|
109
|
+
onclose : me.onClose .bind(me),
|
|
110
|
+
onerror : me.onError .bind(me),
|
|
111
|
+
onmessage: me.onMessage.bind(me),
|
|
112
|
+
onopen : me.onOpen .bind(me)
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
NeoFunction.createInterceptor(value, 'send', me.beforeSend, me);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return value;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* @param {Number} [code] defaults to 1000
|
|
123
|
+
* @param {String} [reason]
|
|
124
|
+
*/
|
|
125
|
+
close(code, reason) {
|
|
126
|
+
this.socket.close(code, reason);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
*
|
|
131
|
+
*/
|
|
132
|
+
createSocket() {
|
|
133
|
+
this.socket = new WebSocket(this.serverAddress);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
*
|
|
138
|
+
*/
|
|
139
|
+
destroy(...args) {
|
|
140
|
+
this.close();
|
|
141
|
+
super.destroy(...args);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* @param {CloseEvent} event The Websocket generated CloseEvent
|
|
146
|
+
* @param {Number} event.code The WebSocket connection close code provided by the server
|
|
147
|
+
*
|
|
148
|
+
* Code Name Description
|
|
149
|
+
* 0-999 Reserved and not used.
|
|
150
|
+
* 1000 CLOSE_NORMAL Normal closure; the connection successfully completed whatever purpose for which it was created.
|
|
151
|
+
* 1001 CLOSE_GOING_AWAY The endpoint is going away, either because of a server failure or because the browser is navigating away from the page that opened the connection.
|
|
152
|
+
* 1002 CLOSE_PROTOCOL_ERROR The endpoint is terminating the connection due to a protocol error.
|
|
153
|
+
* 1003 CLOSE_UNSUPPORTED The connection is being terminated because the endpoint received data of a type it cannot accept (for example, a text-only endpoint received binary data).
|
|
154
|
+
* 1004 CLOSE_TOO_LARGE The endpoint is terminating the connection because a data frame was received that is too large.
|
|
155
|
+
* 1005 CLOSE_NO_STATUS Reserved. Indicates that no status code was provided even though one was expected.
|
|
156
|
+
* 1006 CLOSE_ABNORMAL Reserved. Used to indicate that a connection was closed abnormally (that is, with no close frame being sent) when a status code is expected.
|
|
157
|
+
* 1007-1999 Reserved for future use by the WebSocket standard.
|
|
158
|
+
* 2000-2999 Reserved for use by WebSocket extensions.
|
|
159
|
+
* 3000-3999 Available for use by libraries and frameworks. May not be used by applications.
|
|
160
|
+
* 4000-4999 Available for use by applications.
|
|
161
|
+
*
|
|
162
|
+
* @param {String} reason A string indicating the reason the server closed the connection. This is specific to the particular server and sub-protocol.
|
|
163
|
+
* @param {Boolean} wasClean Indicates whether or not the connection was cleanly closed.
|
|
164
|
+
*/
|
|
165
|
+
onClose(event, reason, wasClean) {
|
|
166
|
+
console.log('onClose', event, reason, wasClean);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
*
|
|
171
|
+
*/
|
|
172
|
+
onError() {
|
|
173
|
+
console.log('onError', arguments);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* @param {MessageEvent} event
|
|
178
|
+
*/
|
|
179
|
+
onMessage(event) {
|
|
180
|
+
let data = JSON.parse(event.data);
|
|
181
|
+
|
|
182
|
+
console.log('onMessage', data);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
*
|
|
187
|
+
*/
|
|
188
|
+
onOpen() {
|
|
189
|
+
this.fire('open', {scope: this});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* @param {Object} data
|
|
194
|
+
*/
|
|
195
|
+
sendMessage(data) {
|
|
196
|
+
let me = this,
|
|
197
|
+
socket = me.socket,
|
|
198
|
+
d = data;
|
|
199
|
+
|
|
200
|
+
// CONNECTING 0 The connection is not yet open.
|
|
201
|
+
// OPEN 1 The connection is open and ready to communicate.
|
|
202
|
+
// CLOSING 2 The connection is in the process of closing.
|
|
203
|
+
// CLOSED 3 The connection is closed or couldn't be opened.
|
|
204
|
+
|
|
205
|
+
// If socket is not yet ready let's defer to open then resend
|
|
206
|
+
switch (socket.readyState) {
|
|
207
|
+
case WebSocket.CLOSED:
|
|
208
|
+
case WebSocket.CLOSING:
|
|
209
|
+
me.attemptReconnect(function() {
|
|
210
|
+
me.send(d);
|
|
211
|
+
});
|
|
212
|
+
break;
|
|
213
|
+
case WebSocket.CONNECTING:
|
|
214
|
+
me.on('open', function() {
|
|
215
|
+
me.send(d);
|
|
216
|
+
}, me, {single: true});
|
|
217
|
+
break;
|
|
218
|
+
case WebSocket.OPEN:
|
|
219
|
+
socket.send(data);
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
Neo.applyClassConfig(Socket);
|
|
226
|
+
|
|
227
|
+
export default Socket;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import Base from './Base.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @class Neo.manager.RpcApi
|
|
5
|
+
* @extends Neo.manager.Base
|
|
6
|
+
* @singleton
|
|
7
|
+
*/
|
|
8
|
+
class RpcApi extends Base {
|
|
9
|
+
static getConfig() {return {
|
|
10
|
+
/**
|
|
11
|
+
* @member {String} className='Neo.manager.RpcApi'
|
|
12
|
+
* @protected
|
|
13
|
+
*/
|
|
14
|
+
className: 'Neo.manager.RpcApi',
|
|
15
|
+
/**
|
|
16
|
+
* @member {Boolean} singleton=true
|
|
17
|
+
* @protected
|
|
18
|
+
*/
|
|
19
|
+
singleton: true
|
|
20
|
+
}}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Registers each service & method combination into the collection
|
|
24
|
+
* @param api
|
|
25
|
+
*/
|
|
26
|
+
registerApi(api) {
|
|
27
|
+
Object.entries(api.services).forEach(([service, serviceValue]) => {
|
|
28
|
+
Object.entries(serviceValue.methods).forEach(([method, methodValue]) => {
|
|
29
|
+
this.register({
|
|
30
|
+
id : `${service}.${method}`,
|
|
31
|
+
method,
|
|
32
|
+
service,
|
|
33
|
+
url: methodValue.url || serviceValue.url || api.url
|
|
34
|
+
})
|
|
35
|
+
})
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
Neo.applyClassConfig(RpcApi);
|
|
41
|
+
|
|
42
|
+
let instance = Neo.create(RpcApi);
|
|
43
|
+
|
|
44
|
+
Neo.applyToGlobalNs(instance);
|
|
45
|
+
|
|
46
|
+
export default instance;
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import Base from './Base.mjs';
|
|
2
|
+
import NeoArray from '../util/Array.mjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @class Neo.manager.RpcMessage
|
|
6
|
+
* @extends Neo.manager.Base
|
|
7
|
+
* @singleton
|
|
8
|
+
*/
|
|
9
|
+
class RpcMessage extends Base {
|
|
10
|
+
/**
|
|
11
|
+
* Stores the urls of endpoints for which a setTimeout() call is in progress
|
|
12
|
+
* @member {String[]} endPointTimeouts=[]
|
|
13
|
+
*/
|
|
14
|
+
endPointTimeouts = []
|
|
15
|
+
/**
|
|
16
|
+
* internal incrementing flag
|
|
17
|
+
* @member {Number} messageId=1
|
|
18
|
+
* @protected
|
|
19
|
+
*/
|
|
20
|
+
messageId = 1
|
|
21
|
+
/**
|
|
22
|
+
* Time window in ms for buffering incoming message requests
|
|
23
|
+
* @member {Number} requestBuffer=20
|
|
24
|
+
*/
|
|
25
|
+
requestBuffer = 20
|
|
26
|
+
/**
|
|
27
|
+
* internal incrementing flag
|
|
28
|
+
* @member {Number} transactionId=1
|
|
29
|
+
* @protected
|
|
30
|
+
*/
|
|
31
|
+
transactionId = 1
|
|
32
|
+
|
|
33
|
+
static getConfig() {return {
|
|
34
|
+
/**
|
|
35
|
+
* @member {String} className='Neo.manager.RpcMessage'
|
|
36
|
+
* @protected
|
|
37
|
+
*/
|
|
38
|
+
className: 'Neo.manager.RpcMessage',
|
|
39
|
+
/**
|
|
40
|
+
* @member {Boolean} singleton=true
|
|
41
|
+
* @protected
|
|
42
|
+
*/
|
|
43
|
+
singleton: true,
|
|
44
|
+
/**
|
|
45
|
+
* @member {Object[]} sorters
|
|
46
|
+
*/
|
|
47
|
+
sorters: [{
|
|
48
|
+
direction: 'ASC',
|
|
49
|
+
property : 'id'
|
|
50
|
+
}]
|
|
51
|
+
}}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
*
|
|
55
|
+
* @param {Object} msg
|
|
56
|
+
* @returns {Promise<any>}
|
|
57
|
+
*/
|
|
58
|
+
onMessage(msg) {
|
|
59
|
+
return new Promise((resolve, reject) => {
|
|
60
|
+
let me = this,
|
|
61
|
+
method = Neo.manager.RpcApi.get(`${msg.service}.${msg.method}`),
|
|
62
|
+
url = method.url;
|
|
63
|
+
|
|
64
|
+
me.register({
|
|
65
|
+
id : me.messageId,
|
|
66
|
+
method : msg.method,
|
|
67
|
+
params : msg.params,
|
|
68
|
+
reject,
|
|
69
|
+
resolve,
|
|
70
|
+
service : msg.service,
|
|
71
|
+
transactionId: 0,
|
|
72
|
+
url
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
me.messageId++;
|
|
76
|
+
|
|
77
|
+
if (!me.endPointTimeouts.includes(url)) {
|
|
78
|
+
me.endPointTimeouts.push(url);
|
|
79
|
+
|
|
80
|
+
setTimeout(() => {
|
|
81
|
+
me.resolveBufferTimeout(url);
|
|
82
|
+
}, me.requestBuffer)
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* @param {String} url
|
|
89
|
+
*/
|
|
90
|
+
async resolveBufferTimeout(url) {
|
|
91
|
+
let me = this,
|
|
92
|
+
itemIds = [],
|
|
93
|
+
processItems = me.find({transactionId: 0, url}),
|
|
94
|
+
requests = [],
|
|
95
|
+
transactionId = me.transactionId,
|
|
96
|
+
response;
|
|
97
|
+
|
|
98
|
+
processItems.forEach(item => {
|
|
99
|
+
item.transactionId = transactionId;
|
|
100
|
+
|
|
101
|
+
itemIds.push(item.id);
|
|
102
|
+
|
|
103
|
+
requests.push({
|
|
104
|
+
id : item.id,
|
|
105
|
+
method : item.method,
|
|
106
|
+
params : item.params,
|
|
107
|
+
service: item.service
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
NeoArray.remove(me.endPointTimeouts, url);
|
|
112
|
+
|
|
113
|
+
me.transactionId++;
|
|
114
|
+
|
|
115
|
+
response = await Neo.Fetch.request(url, {}, 'post', JSON.stringify({tid: transactionId, requests}));
|
|
116
|
+
|
|
117
|
+
processItems.forEach(item => {
|
|
118
|
+
// todo: pass the item which is included inside the response object
|
|
119
|
+
// todo: reject the Promise in case the item is missing
|
|
120
|
+
|
|
121
|
+
item.resolve();
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// todo: remove only the items which are included inside the response
|
|
125
|
+
me.remove(itemIds);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
Neo.applyClassConfig(RpcMessage);
|
|
130
|
+
|
|
131
|
+
let instance = Neo.create(RpcMessage);
|
|
132
|
+
|
|
133
|
+
Neo.applyToGlobalNs(instance);
|
|
134
|
+
|
|
135
|
+
export default instance;
|
package/src/remotes/Api.mjs
CHANGED
|
@@ -51,21 +51,25 @@ class Api extends Base {
|
|
|
51
51
|
|
|
52
52
|
fetch(path)
|
|
53
53
|
.then(response => response.json())
|
|
54
|
-
.then(data => {
|
|
54
|
+
.then(data => {
|
|
55
|
+
Neo.currentWorker.sendMessage('data', {action: 'registerApi', data});
|
|
56
|
+
this.register(data)
|
|
57
|
+
})
|
|
55
58
|
}
|
|
56
59
|
|
|
57
60
|
/**
|
|
58
|
-
* @param {Object}
|
|
61
|
+
* @param {Object} api
|
|
59
62
|
*/
|
|
60
|
-
register(
|
|
61
|
-
let
|
|
63
|
+
register(api) {
|
|
64
|
+
let ns;
|
|
62
65
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
Object.entries(api.services).forEach(([service, serviceValue]) => {
|
|
67
|
+
ns = Neo.ns(`${api.namespace}.${service}`, true);
|
|
68
|
+
|
|
69
|
+
Object.entries(serviceValue.methods).forEach(([method, methodValue]) => {
|
|
70
|
+
ns[method] = this.generateRemote(service, method);
|
|
71
|
+
})
|
|
72
|
+
})
|
|
69
73
|
}
|
|
70
74
|
}
|
|
71
75
|
|
package/src/util/Function.mjs
CHANGED
|
@@ -27,6 +27,22 @@ class NeoFunction extends Base {
|
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Intended for functions with 1 param where the interceptor can change the value
|
|
32
|
+
* @param {Object} target
|
|
33
|
+
* @param {String} targetMethodName
|
|
34
|
+
* @param {Function} interceptFunction
|
|
35
|
+
* @param {Object} scope=target
|
|
36
|
+
* @returns {Function}
|
|
37
|
+
*/
|
|
38
|
+
static createInterceptor(target, targetMethodName, interceptFunction, scope) {
|
|
39
|
+
let targetMethod = target[targetMethodName];
|
|
40
|
+
|
|
41
|
+
return (target[targetMethodName] = function(value) {
|
|
42
|
+
return targetMethod.call(target, interceptFunction.call(scope || target, value));
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
30
46
|
/**
|
|
31
47
|
* @param {Neo.core.Base} target
|
|
32
48
|
* @param {String} methodName
|
|
@@ -44,20 +60,21 @@ class NeoFunction extends Base {
|
|
|
44
60
|
}
|
|
45
61
|
|
|
46
62
|
/**
|
|
47
|
-
*
|
|
48
|
-
* @param {
|
|
49
|
-
* @param {
|
|
50
|
-
* @param {
|
|
63
|
+
* The interceptor can prevent the targetMethod from getting executed in case it returns false.
|
|
64
|
+
* @param {Object} target
|
|
65
|
+
* @param {String} targetMethodName
|
|
66
|
+
* @param {Function} interceptFunction
|
|
67
|
+
* @param {Object} scope=target
|
|
68
|
+
* @param {*} preventedReturnValue=null The value to return in case the interceptFunction returns false
|
|
51
69
|
* @returns {Function}
|
|
52
70
|
*/
|
|
53
|
-
static intercept(target,
|
|
54
|
-
let
|
|
55
|
-
|
|
56
|
-
return (target[methodName] = function() {
|
|
57
|
-
let returnValue = fn.apply(scope || this, arguments);
|
|
58
|
-
method.apply(this, arguments);
|
|
71
|
+
static intercept(target, targetMethodName, interceptFunction, scope, preventedReturnValue=null) {
|
|
72
|
+
let targetMethod = target[targetMethodName];
|
|
59
73
|
|
|
60
|
-
|
|
74
|
+
return (target[targetMethodName] = function() {
|
|
75
|
+
return (interceptFunction.apply(scope || target, arguments) === false)
|
|
76
|
+
? preventedReturnValue
|
|
77
|
+
: targetMethod.apply(target, arguments);
|
|
61
78
|
});
|
|
62
79
|
}
|
|
63
80
|
}
|
package/src/worker/Data.mjs
CHANGED
|
@@ -15,10 +15,15 @@ import Xhr from '../Xhr.mjs';
|
|
|
15
15
|
*/
|
|
16
16
|
class Data extends Base {
|
|
17
17
|
/**
|
|
18
|
-
* @member {Boolean}
|
|
18
|
+
* @member {Boolean} rpcApiManagerLoaded=false
|
|
19
19
|
* @protected
|
|
20
20
|
*/
|
|
21
|
-
|
|
21
|
+
rpcApiManagerLoaded = false
|
|
22
|
+
/**
|
|
23
|
+
* @member {Boolean} rpcMessageManagerLoaded=false
|
|
24
|
+
* @protected
|
|
25
|
+
*/
|
|
26
|
+
rpcMessageManagerLoaded = false
|
|
22
27
|
|
|
23
28
|
static getConfig() {return {
|
|
24
29
|
/**
|
|
@@ -60,14 +65,25 @@ class Data extends Base {
|
|
|
60
65
|
console.log('worker.Data onLoad');
|
|
61
66
|
}
|
|
62
67
|
|
|
68
|
+
/**
|
|
69
|
+
* @param {Object} msg
|
|
70
|
+
* @param {Object} msg.data the API content
|
|
71
|
+
*/
|
|
72
|
+
onRegisterApi(msg) {
|
|
73
|
+
import('../manager/RpcApi.mjs').then(module => {
|
|
74
|
+
module.default.registerApi(msg.data);
|
|
75
|
+
this.rpcApiManagerLoaded = true
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
|
|
63
79
|
/**
|
|
64
80
|
* @param {Object} msg
|
|
65
81
|
*/
|
|
66
82
|
onRegisterNeoConfig(msg) {
|
|
67
83
|
super.onRegisterNeoConfig(msg);
|
|
68
84
|
|
|
69
|
-
Neo.config.remotesApiUrl && import('../manager/
|
|
70
|
-
this.
|
|
85
|
+
Neo.config.remotesApiUrl && import('../manager/RpcMessage.mjs').then(module => {
|
|
86
|
+
this.rpcMessageManagerLoaded = true
|
|
71
87
|
})
|
|
72
88
|
}
|
|
73
89
|
|
|
@@ -80,13 +96,13 @@ class Data extends Base {
|
|
|
80
96
|
let me = this,
|
|
81
97
|
response;
|
|
82
98
|
|
|
83
|
-
if (!me.
|
|
99
|
+
if (!me.rpcMessageManagerLoaded) {
|
|
84
100
|
// todo: we could store calls which arrive too early and pass them to the manager once it is ready
|
|
85
101
|
console.warn('manager.RemotesApi not loaded yet', msg);
|
|
86
102
|
|
|
87
103
|
me.reject(msg);
|
|
88
104
|
} else {
|
|
89
|
-
response = await Neo.manager.
|
|
105
|
+
response = await Neo.manager.RpcMessage.onMessage(msg);
|
|
90
106
|
|
|
91
107
|
me.resolve(msg, response);
|
|
92
108
|
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import Base from '../../core/Base.mjs';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @class Neo.data.connection.Socket
|
|
5
|
-
* @extends Neo.core.Base
|
|
6
|
-
*/
|
|
7
|
-
class Socket extends Base {
|
|
8
|
-
static getConfig() {return {
|
|
9
|
-
/**
|
|
10
|
-
* @member {String} className='Neo.data.connection.Socket'
|
|
11
|
-
* @protected
|
|
12
|
-
*/
|
|
13
|
-
className: 'Neo.data.connection.Socket',
|
|
14
|
-
/**
|
|
15
|
-
* @member {String} ntype='socket-connection'
|
|
16
|
-
* @protected
|
|
17
|
-
*/
|
|
18
|
-
ntype: 'socket-connection'
|
|
19
|
-
}}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
Neo.applyClassConfig(Socket);
|
|
23
|
-
|
|
24
|
-
export default Socket;
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import Base from './Base.mjs';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @class Neo.manager.RemotesApi
|
|
5
|
-
* @extends Neo.manager.Base
|
|
6
|
-
* @singleton
|
|
7
|
-
*/
|
|
8
|
-
class RemotesApi extends Base {
|
|
9
|
-
static getConfig() {return {
|
|
10
|
-
/**
|
|
11
|
-
* @member {String} className='Neo.manager.RemotesApi'
|
|
12
|
-
* @protected
|
|
13
|
-
*/
|
|
14
|
-
className: 'Neo.manager.RemotesApi',
|
|
15
|
-
/**
|
|
16
|
-
* @member {Boolean} singleton=true
|
|
17
|
-
* @protected
|
|
18
|
-
*/
|
|
19
|
-
singleton: true
|
|
20
|
-
}}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
*
|
|
24
|
-
* @param msg
|
|
25
|
-
* @returns {Promise<any>}
|
|
26
|
-
*/
|
|
27
|
-
async onMessage(msg) {
|
|
28
|
-
let response = await Neo.Fetch.get(msg);
|
|
29
|
-
|
|
30
|
-
return response;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
Neo.applyClassConfig(RemotesApi);
|
|
35
|
-
|
|
36
|
-
let instance = Neo.create(RemotesApi);
|
|
37
|
-
|
|
38
|
-
Neo.applyToGlobalNs(instance);
|
|
39
|
-
|
|
40
|
-
export default instance;
|