total5 0.0.1-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/503.html +65 -0
- package/CONTRIBUTING.md +55 -0
- package/LICENSE +211 -0
- package/README.md +32 -0
- package/api.js +289 -0
- package/bin/total5 +984 -0
- package/builders.js +1435 -0
- package/bundles.js +457 -0
- package/cache.js +58 -0
- package/changelog.txt +3 -0
- package/cluster.js +320 -0
- package/cms.js +625 -0
- package/controller.js +1419 -0
- package/cron.js +99 -0
- package/debug.js +539 -0
- package/edit.js +469 -0
- package/error.html +49 -0
- package/filestorage.js +1088 -0
- package/flow-flowstream.js +3152 -0
- package/flow.js +209 -0
- package/flowstream.js +1991 -0
- package/global.js +125 -0
- package/helpers/index.js +32 -0
- package/htmlparser.js +650 -0
- package/http.js +81 -0
- package/image.js +773 -0
- package/images.js +747 -0
- package/index.js +2658 -0
- package/jsonschema.js +691 -0
- package/ldap.js +792 -0
- package/mail.js +936 -0
- package/minificators.js +858 -0
- package/nosql-builder.js +440 -0
- package/nosql-querybuilder.js +316 -0
- package/nosql-reader.js +353 -0
- package/nosql-stream.js +617 -0
- package/nosql.js +763 -0
- package/openclient.js +219 -0
- package/package.json +32 -0
- package/pause.html +67 -0
- package/querybuilder.js +1361 -0
- package/release.js +167 -0
- package/routing.js +905 -0
- package/sourcemap.js +160 -0
- package/tangular.js +409 -0
- package/templates.js +145 -0
- package/templates.json +74 -0
- package/tms.js +384 -0
- package/tmsclient.js +125 -0
- package/todo.txt +7 -0
- package/tools/beta.sh +6 -0
- package/tools/release.sh +6 -0
- package/uibuilder.js +206 -0
- package/utils.js +6374 -0
- package/viewengine.js +880 -0
- package/websocket.js +1939 -0
- package/workers.js +129 -0
package/templates.json
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"empty": {
|
|
3
|
+
"id": "emptyproject",
|
|
4
|
+
"name": "Empty",
|
|
5
|
+
"total": 4,
|
|
6
|
+
"description": "Empty project without any special setup"
|
|
7
|
+
},
|
|
8
|
+
"typescript": {
|
|
9
|
+
"id": "emptyproject-typescript",
|
|
10
|
+
"name": "Typescript",
|
|
11
|
+
"total": 4,
|
|
12
|
+
"description": "Total.js with typescript"
|
|
13
|
+
},
|
|
14
|
+
"website": {
|
|
15
|
+
"id": "emptyproject-website",
|
|
16
|
+
"name": "Website",
|
|
17
|
+
"total": 4,
|
|
18
|
+
"description": "Website example"
|
|
19
|
+
},
|
|
20
|
+
"postgres": {
|
|
21
|
+
"id": "emptyproject-postgresql",
|
|
22
|
+
"name": "Postgres template",
|
|
23
|
+
"total": 4,
|
|
24
|
+
"description": "Empty project ready to be used with PostgreSQL"
|
|
25
|
+
},
|
|
26
|
+
"app-builder": {
|
|
27
|
+
"id": "emptyproject-builder",
|
|
28
|
+
"name": "App Builder",
|
|
29
|
+
"total": 4,
|
|
30
|
+
"description": "Tool for creating Total.js server-side applications"
|
|
31
|
+
},
|
|
32
|
+
"empty-spa": {
|
|
33
|
+
"id": "emptyproject-emptyspa",
|
|
34
|
+
"name": "Empty SPA",
|
|
35
|
+
"total": 4,
|
|
36
|
+
"description": "Empty single page application project"
|
|
37
|
+
},
|
|
38
|
+
"spa": {
|
|
39
|
+
"id": "emptyproject-spa",
|
|
40
|
+
"name": "SPA",
|
|
41
|
+
"total": 4,
|
|
42
|
+
"description": "Single page application template"
|
|
43
|
+
},
|
|
44
|
+
"pwa": {
|
|
45
|
+
"id": "emptyproject-emptyspa",
|
|
46
|
+
"name": "PWA",
|
|
47
|
+
"total": 4,
|
|
48
|
+
"description": "Progressive web application template"
|
|
49
|
+
},
|
|
50
|
+
"flow": {
|
|
51
|
+
"id": "emptyproject-flow",
|
|
52
|
+
"name": "Flow",
|
|
53
|
+
"total": 4,
|
|
54
|
+
"description": "Visual programming interface for IoT"
|
|
55
|
+
},
|
|
56
|
+
"flowstream": {
|
|
57
|
+
"id": "flowstream",
|
|
58
|
+
"name": "FlowStream",
|
|
59
|
+
"total": 4,
|
|
60
|
+
"description": "Total.js FlowStream"
|
|
61
|
+
},
|
|
62
|
+
"tms": {
|
|
63
|
+
"id": "tms",
|
|
64
|
+
"name": "TMS",
|
|
65
|
+
"total": 4,
|
|
66
|
+
"description": "Total.js Message Service integrator"
|
|
67
|
+
},
|
|
68
|
+
"cms": {
|
|
69
|
+
"id": "cmsbundle",
|
|
70
|
+
"name": "CMS",
|
|
71
|
+
"total": 4,
|
|
72
|
+
"description": "Total.js CMS"
|
|
73
|
+
}
|
|
74
|
+
}
|
package/tms.js
ADDED
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
// Total.js TMS
|
|
2
|
+
// The MIT License
|
|
3
|
+
// Copyright 2022-2023 (c) Peter Širka <petersirka@gmail.com>
|
|
4
|
+
|
|
5
|
+
const ErrorBuilder = F.TBuilders.ErrorBuilder;
|
|
6
|
+
|
|
7
|
+
var Cache = {
|
|
8
|
+
subscribers: {},
|
|
9
|
+
swatchers: {}, // watchers for subscribers
|
|
10
|
+
scache: {}, // cache for subscribers
|
|
11
|
+
publishers: {},
|
|
12
|
+
pcache: {}, // cache for publishers
|
|
13
|
+
calls: {},
|
|
14
|
+
socket: null,
|
|
15
|
+
timeout: null,
|
|
16
|
+
url: ''
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
exports.cache = Cache;
|
|
20
|
+
|
|
21
|
+
function tmscontroller($) {
|
|
22
|
+
|
|
23
|
+
var temporary = F.temporary;
|
|
24
|
+
|
|
25
|
+
Cache.socket = $;
|
|
26
|
+
|
|
27
|
+
$.autodestroy(() => Cache.socket = null);
|
|
28
|
+
|
|
29
|
+
$.on('open', function(client) {
|
|
30
|
+
|
|
31
|
+
if (temporary.tmsblocked[client.ip] > 5) {
|
|
32
|
+
client.close(4001);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (F.config.secret_tms) {
|
|
37
|
+
var token = client.headers['x-token']; // || client.query.token;
|
|
38
|
+
if (token != F.config.secret_tms) {
|
|
39
|
+
if (temporary.tmsblocked[client.ip])
|
|
40
|
+
temporary.tmsblocked[client.ip]++;
|
|
41
|
+
else
|
|
42
|
+
temporary.tmsblocked[client.ip] = 1;
|
|
43
|
+
client.close(4001);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
delete temporary.tmsblocked[client.ip];
|
|
49
|
+
Cache.publishers = {};
|
|
50
|
+
client.tmsready = true;
|
|
51
|
+
refresh(client);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
$.on('message', function(client, msg) {
|
|
55
|
+
|
|
56
|
+
// msg.type {String}
|
|
57
|
+
// msg.data {Object}
|
|
58
|
+
|
|
59
|
+
var response;
|
|
60
|
+
|
|
61
|
+
if (client.tmsready) {
|
|
62
|
+
if (msg.type === 'ping') {
|
|
63
|
+
msg.type = 'pong';
|
|
64
|
+
client.send(msg);
|
|
65
|
+
} else if (msg.type === 'subscribe' && msg.id) {
|
|
66
|
+
F.stats.performance.subscribe++;
|
|
67
|
+
var schema = Cache.scache[msg.id];
|
|
68
|
+
if (schema) {
|
|
69
|
+
response = schema.transform(msg.data);
|
|
70
|
+
if (!response.error)
|
|
71
|
+
F.TTMS.subscribe(msg.id, response, client);
|
|
72
|
+
}
|
|
73
|
+
} else if (msg.type === 'subscribers' && msg.subscribers instanceof Array) {
|
|
74
|
+
Cache.publishers = {};
|
|
75
|
+
for (var i = 0; i < msg.subscribers.length; i++)
|
|
76
|
+
Cache.publishers[msg.subscribers[i]] = 1;
|
|
77
|
+
} else if (msg.type === 'call' && msg.id) {
|
|
78
|
+
var tmp = Cache.calls[msg.id];
|
|
79
|
+
if (tmp) {
|
|
80
|
+
F.stats.performance.call++;
|
|
81
|
+
response = tmp.schema.transform(msg.data);
|
|
82
|
+
if (response.error) {
|
|
83
|
+
msg.data = response.error instanceof ErrorBuilder ? response.error.output() : response.response.toString();
|
|
84
|
+
msg.error = true;
|
|
85
|
+
client.send(msg);
|
|
86
|
+
} else {
|
|
87
|
+
tmp.callback(response.response, function(err, response) {
|
|
88
|
+
if (err) {
|
|
89
|
+
msg.error = true;
|
|
90
|
+
if (err instanceof ErrorBuilder)
|
|
91
|
+
msg.data = err.output();
|
|
92
|
+
else
|
|
93
|
+
msg.data = [{ error: err + '' }];
|
|
94
|
+
} else {
|
|
95
|
+
msg.success = true;
|
|
96
|
+
msg.data = response;
|
|
97
|
+
}
|
|
98
|
+
if (client && !client.isClosed)
|
|
99
|
+
client.send(msg);
|
|
100
|
+
}, client);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
} else {
|
|
104
|
+
msg.error = true;
|
|
105
|
+
msg.data = new ErrorBuilder.push(404).output();
|
|
106
|
+
client.send(msg);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
exports.client = function(url, token, callback) {
|
|
113
|
+
|
|
114
|
+
if (typeof(token) === 'function') {
|
|
115
|
+
callback = token;
|
|
116
|
+
token = undefined;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
var client = new F.TWebSocket.WebSocketClient();
|
|
120
|
+
var publishers = {};
|
|
121
|
+
var subscribers = {};
|
|
122
|
+
var callbacks = {};
|
|
123
|
+
var isopen = false;
|
|
124
|
+
var callbackid = 0;
|
|
125
|
+
var timeout;
|
|
126
|
+
|
|
127
|
+
if (token)
|
|
128
|
+
client.headers['x-token'] = token;
|
|
129
|
+
|
|
130
|
+
client.options.reconnectserver = true;
|
|
131
|
+
client.connect(url.replace(/^http/, 'ws'));
|
|
132
|
+
client.ready = false;
|
|
133
|
+
|
|
134
|
+
client.on('destroy', function() {
|
|
135
|
+
|
|
136
|
+
publishers = null;
|
|
137
|
+
subscribers = null;
|
|
138
|
+
|
|
139
|
+
for (let key in callbacks) {
|
|
140
|
+
let item = callbacks[key];
|
|
141
|
+
clearTimeout(item.timeout);
|
|
142
|
+
item.callback && item.callback('TMS has been destroyed');
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
callbacks = null;
|
|
146
|
+
|
|
147
|
+
timeout && clearTimeout(timeout);
|
|
148
|
+
timeout = null;
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
client.on('close', function() {
|
|
152
|
+
isopen = false;
|
|
153
|
+
client.ready = false;
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
client.on('message', function(msg) {
|
|
157
|
+
if (msg.type === 'call') {
|
|
158
|
+
if (callbacks[msg.callbackid]) {
|
|
159
|
+
let tmp = callbacks[msg.callbackid];
|
|
160
|
+
tmp.callback(msg.error ? ErrorBuilder.assign(msg.data) : null, msg.success ? msg.data : null);
|
|
161
|
+
tmp.timeout && clearTimeout(tmp.timeout);
|
|
162
|
+
delete callbacks[msg.callbackid];
|
|
163
|
+
}
|
|
164
|
+
} else if (msg.type === 'publish' && subscribers[msg.id] && publishers[msg.id]) {
|
|
165
|
+
var err = new ErrorBuilder();
|
|
166
|
+
var data = F.TJSONSchema.transform(publishers[msg.id], err, msg.data, true);
|
|
167
|
+
if (data) {
|
|
168
|
+
for (let fn of subscribers[msg.id])
|
|
169
|
+
fn(data);
|
|
170
|
+
}
|
|
171
|
+
} else if (msg.type === 'meta') {
|
|
172
|
+
publishers = {};
|
|
173
|
+
for (let item of msg.publish)
|
|
174
|
+
publishers[item.id] = item.schema;
|
|
175
|
+
sync_subscribers();
|
|
176
|
+
isopen = true;
|
|
177
|
+
client.ready = true;
|
|
178
|
+
client.meta = msg;
|
|
179
|
+
if (callback) {
|
|
180
|
+
setImmediate(callback, null, client, client.meta);
|
|
181
|
+
callback = null;
|
|
182
|
+
}
|
|
183
|
+
client.emit('meta', msg);
|
|
184
|
+
client.emit('ready');
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
var timeouthandler = function(id) {
|
|
189
|
+
let obj = callbacks[id];
|
|
190
|
+
obj.callback && obj.callback('408: Timeout');
|
|
191
|
+
delete callbacks[id];
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
client.call = function(name, data, callback, timeout) {
|
|
195
|
+
if (callback)
|
|
196
|
+
client.$call(name, data, callback, timeout);
|
|
197
|
+
else
|
|
198
|
+
return new Promise((resolve, reject) => client.$call(name, data, (err, res) => err ? reject(err) : resolve(res), timeout));
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
client.$call = function(name, data, callback, timeout) {
|
|
202
|
+
if (isopen) {
|
|
203
|
+
let key = (callbackid++) + '';
|
|
204
|
+
let obj = {};
|
|
205
|
+
obj.callback = callback;
|
|
206
|
+
obj.timeout = setTimeout(timeouthandler, timeout || 10000, key);
|
|
207
|
+
callbacks[key] = obj;
|
|
208
|
+
client.send({ type: 'call', id: name, data: data, callbackid: key });
|
|
209
|
+
} else
|
|
210
|
+
callback('TMS is offline');
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
client.subscribe = function(name, callback) {
|
|
214
|
+
timeout && clearTimeout(timeout);
|
|
215
|
+
timeout = setTimeout(sync_subscribers, 50, true);
|
|
216
|
+
if (subscribers[name])
|
|
217
|
+
subscribers[name].push(callback);
|
|
218
|
+
else
|
|
219
|
+
subscribers[name] = [callback];
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
client.publish = function(name, data) {
|
|
223
|
+
isopen && client.send({ type: 'subscribe', id: name, data: data });
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
var sync_subscribers = function(force) {
|
|
227
|
+
timeout && clearTimeout(timeout);
|
|
228
|
+
timeout = null;
|
|
229
|
+
let keys = Object.keys(subscribers);
|
|
230
|
+
if (force || keys.length)
|
|
231
|
+
client.send({ type: 'subscribers', subscribers: keys });
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
function refresh(client) {
|
|
237
|
+
|
|
238
|
+
if (Cache.socket) {
|
|
239
|
+
|
|
240
|
+
var subscribed = [];
|
|
241
|
+
var published = [];
|
|
242
|
+
|
|
243
|
+
for (let key in Cache.pcache) {
|
|
244
|
+
let schema = F.jsonschemas[Cache.pcache[key]];
|
|
245
|
+
published.push({ id: key, schema: schema });
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
for (let key in Cache.scache) {
|
|
249
|
+
let schema = F.jsonschemas[Cache.scache[key]];
|
|
250
|
+
subscribed.push({ id: key, schema: schema });
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
var calls = [];
|
|
254
|
+
for (let key in Cache.calls)
|
|
255
|
+
calls.push({ id: key, schema: F.jsonschemas[Cache.calls[key].schema] });
|
|
256
|
+
|
|
257
|
+
var msg = { type: 'meta', name: F.config.name, subscribe: subscribed, publish: published, subscribers: Object.keys(Cache.subscribers), call: calls };
|
|
258
|
+
if (client)
|
|
259
|
+
client.send(msg);
|
|
260
|
+
else
|
|
261
|
+
Cache.socket.send(msg);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
exports.refresh = function() {
|
|
266
|
+
Cache.timeout && clearTimeout(Cache.timeout);
|
|
267
|
+
Cache.timeout = setTimeout(refresh, 500);
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
exports.newpublish = function(name, schema) {
|
|
271
|
+
|
|
272
|
+
if (schema == null) {
|
|
273
|
+
delete Cache.pcache[name];
|
|
274
|
+
exports.refresh();
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
Cache.pcache[name] = F.TUtils.jsonschema(schema);
|
|
279
|
+
exports.refresh();
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
exports.newcall = function(name, schema, callback) {
|
|
283
|
+
|
|
284
|
+
if (schema == null) {
|
|
285
|
+
delete Cache.calls[name];
|
|
286
|
+
exports.refresh();
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
if (!callback)
|
|
291
|
+
callback = (data, callback, client) => F.action(schema, data, client).callback(callback);
|
|
292
|
+
|
|
293
|
+
let obj = {};
|
|
294
|
+
obj.schema = F.TUtils.jsonschema(schema);
|
|
295
|
+
obj.callback = callback;
|
|
296
|
+
Cache.calls[name] = obj;
|
|
297
|
+
exports.refresh();
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
exports.newsubscribe = function(name, schema, callback) {
|
|
301
|
+
|
|
302
|
+
if (typeof(schema) === 'function') {
|
|
303
|
+
callback = schema;
|
|
304
|
+
schema = null;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
if (schema)
|
|
308
|
+
Cache.scache[name] = F.TUtils.jsonschema(schema);
|
|
309
|
+
else
|
|
310
|
+
delete Cache.scache[name];
|
|
311
|
+
|
|
312
|
+
exports.subscribe(name, callback);
|
|
313
|
+
exports.refresh();
|
|
314
|
+
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
exports.publish = function(name, value) {
|
|
318
|
+
if (Cache.socket && Cache.pcache[name] && Cache.publishers[name]) {
|
|
319
|
+
F.stats.performance.publish++;
|
|
320
|
+
Cache.socket.send({ type: 'publish', id: name, data: value }, client => client.tmsready);
|
|
321
|
+
}
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
exports.subscribe = function(name, callback, client) {
|
|
325
|
+
if (client) {
|
|
326
|
+
var arr = Cache.swatchers[name];
|
|
327
|
+
if (arr) {
|
|
328
|
+
for (let fn of Cache.arr)
|
|
329
|
+
fn(callback, client);
|
|
330
|
+
}
|
|
331
|
+
} else {
|
|
332
|
+
if (Cache.swatchers[name])
|
|
333
|
+
Cache.swatchers[name].push(callback);
|
|
334
|
+
else
|
|
335
|
+
Cache.swatchers[name] = [callback];
|
|
336
|
+
Cache.subscribers[name] = 1;
|
|
337
|
+
exports.refresh();
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
exports.unsubscribe = function(name, callback) {
|
|
342
|
+
if (Cache.swatchers[name]) {
|
|
343
|
+
exports.refresh();
|
|
344
|
+
if (callback) {
|
|
345
|
+
let index = Cache.swatchers[name].indexOf(callback);
|
|
346
|
+
if (index !== -1)
|
|
347
|
+
Cache.swatchers[name].splice(index, 1);
|
|
348
|
+
if (!Cache.swatchers[name].length)
|
|
349
|
+
delete Cache.swatchers[name];
|
|
350
|
+
if (Cache.swatchers[name])
|
|
351
|
+
Cache.subscribers[name] = 1;
|
|
352
|
+
else
|
|
353
|
+
delete Cache.subscribers[name];
|
|
354
|
+
return index !== -1;
|
|
355
|
+
} else {
|
|
356
|
+
delete Cache.swatchers[name];
|
|
357
|
+
delete Cache.subscribers[name];
|
|
358
|
+
return true;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
return false;
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
F.on('@tms', function() {
|
|
365
|
+
|
|
366
|
+
var endpoint = F.config.$tmsurl;
|
|
367
|
+
var is = Cache.url !== endpoint;
|
|
368
|
+
|
|
369
|
+
if (is && Cache.route) {
|
|
370
|
+
Cache.route.remove();
|
|
371
|
+
Cache.route = null;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
if ((is && endpoint && F.config.$tms) || (endpoint && F.config.$tms && !Cache.route))
|
|
375
|
+
Cache.route = F.route('SOCKET ' + endpoint, tmscontroller, F.config.$tmsmaxsize);
|
|
376
|
+
|
|
377
|
+
Cache.url = endpoint;
|
|
378
|
+
|
|
379
|
+
if (endpoint && Cache.token !== F.config.secret_tms) {
|
|
380
|
+
Cache.token = F.config.secret_tms;
|
|
381
|
+
Cache.socket && Cache.socket.close(1000, 'Changed TMS secret');
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
});
|
package/tmsclient.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
exports.create = function(url, token, callback) {
|
|
2
|
+
|
|
3
|
+
if (typeof(token) === 'function') {
|
|
4
|
+
callback = token;
|
|
5
|
+
token = undefined;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
var client = F.TWebSocket.createclient();
|
|
9
|
+
|
|
10
|
+
var publishers = {};
|
|
11
|
+
var subscribers = {};
|
|
12
|
+
var callbacks = {};
|
|
13
|
+
var isopen = false;
|
|
14
|
+
var callbackid = 0;
|
|
15
|
+
var timeout;
|
|
16
|
+
|
|
17
|
+
if (token)
|
|
18
|
+
client.headers['x-token'] = token;
|
|
19
|
+
|
|
20
|
+
client.options.reconnectserver = true;
|
|
21
|
+
client.connect(url.replace(/^http/, 'ws'));
|
|
22
|
+
client.ready = false;
|
|
23
|
+
|
|
24
|
+
client.on('destroy', function() {
|
|
25
|
+
publishers = null;
|
|
26
|
+
subscribers = null;
|
|
27
|
+
|
|
28
|
+
for (var key in callbacks) {
|
|
29
|
+
var item = callbacks[key];
|
|
30
|
+
clearTimeout(item.timeout);
|
|
31
|
+
item.callback && item.callback('TMS has been destroyed');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
callbacks = null;
|
|
35
|
+
|
|
36
|
+
timeout && clearTimeout(timeout);
|
|
37
|
+
timeout = null;
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
client.on('close', function() {
|
|
41
|
+
isopen = false;
|
|
42
|
+
client.ready = false;
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
client.on('message', function(msg) {
|
|
46
|
+
|
|
47
|
+
if (msg.type === 'call') {
|
|
48
|
+
if (callbacks[msg.callbackid]) {
|
|
49
|
+
var tmp = callbacks[msg.callbackid];
|
|
50
|
+
tmp.callback(msg.error ? ErrorBuilder.assign(msg.data) : null, msg.success ? msg.data : null);
|
|
51
|
+
tmp.timeout && clearTimeout(tmp.timeout);
|
|
52
|
+
delete callbacks[msg.callbackid];
|
|
53
|
+
}
|
|
54
|
+
} else if (msg.type === 'publish' && subscribers[msg.id] && publishers[msg.id]) {
|
|
55
|
+
var err = new ErrorBuilder();
|
|
56
|
+
var data = framework_jsonschema.transform(publishers[msg.id], err, msg.data, true);
|
|
57
|
+
if (data) {
|
|
58
|
+
for (var fn of subscribers[msg.id])
|
|
59
|
+
fn(data);
|
|
60
|
+
}
|
|
61
|
+
} else if (msg.type === 'meta') {
|
|
62
|
+
publishers = {};
|
|
63
|
+
for (var item of msg.publish)
|
|
64
|
+
publishers[item.id] = item.schema;
|
|
65
|
+
sync_subscribers();
|
|
66
|
+
isopen = true;
|
|
67
|
+
client.ready = true;
|
|
68
|
+
client.meta = msg;
|
|
69
|
+
if (callback) {
|
|
70
|
+
setImmediate(callback, null, client, client.meta);
|
|
71
|
+
callback = null;
|
|
72
|
+
}
|
|
73
|
+
client.emit('meta', msg);
|
|
74
|
+
client.emit('ready');
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
var timeouthandler = function(id) {
|
|
79
|
+
var obj = callbacks[id];
|
|
80
|
+
obj.callback && obj.callback('408: Timeout');
|
|
81
|
+
delete callbacks[id];
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
client.call = function(name, data, callback, timeout) {
|
|
85
|
+
if (callback)
|
|
86
|
+
client._call(name, data, callback, timeout);
|
|
87
|
+
else
|
|
88
|
+
return new Promise((resolve, reject) => client._call(name, data, (err, res) => err ? reject(err) : resolve(res), timeout));
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
client._call = function(name, data, callback, timeout) {
|
|
92
|
+
if (isopen) {
|
|
93
|
+
var key = (callbackid++) + '';
|
|
94
|
+
var obj = {};
|
|
95
|
+
obj.callback = callback;
|
|
96
|
+
obj.timeout = setTimeout(timeouthandler, timeout || 10000, key);
|
|
97
|
+
callbacks[key] = obj;
|
|
98
|
+
client.send({ type: 'call', id: name, data: data, callbackid: key });
|
|
99
|
+
} else
|
|
100
|
+
callback('TMS is offline');
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
client.subscribe = function(name, callback) {
|
|
104
|
+
timeout && clearTimeout(timeout);
|
|
105
|
+
timeout = setTimeout(sync_subscribers, 50, true);
|
|
106
|
+
if (subscribers[name])
|
|
107
|
+
subscribers[name].push(callback);
|
|
108
|
+
else
|
|
109
|
+
subscribers[name] = [callback];
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
client.publish = function(name, data) {
|
|
113
|
+
isopen && client.send({ type: 'subscribe', id: name, data: data });
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
var sync_subscribers = function(force) {
|
|
117
|
+
timeout && clearTimeout(timeout);
|
|
118
|
+
timeout = null;
|
|
119
|
+
var keys = Object.keys(subscribers);
|
|
120
|
+
if (force || keys.length)
|
|
121
|
+
client.send({ type: 'subscribers', subscribers: keys });
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
return client;
|
|
125
|
+
};
|
package/todo.txt
ADDED
package/tools/beta.sh
ADDED