systemlynx 1.8.2 → 1.9.3
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/API.md +7 -0
- package/README.md +11 -5
- package/index.js +22 -23
- package/index.test.js +47 -17
- package/package.json +1 -1
- package/systemlynx/App/App.js +11 -6
- package/systemlynx/App/components/initializeApp.js +2 -2
- package/systemlynx/App/components/loadServices.js +3 -3
- package/systemlynx/App/tests/App.test.js +95 -31
- package/systemlynx/Client/Client.js +6 -3
- package/systemlynx/Client/components/ClientModule.js +9 -3
- package/systemlynx/Client/components/ServiceRequestHandler.js +23 -19
- package/systemlynx/Client/components/SocketDispatcher.js +2 -2
- package/systemlynx/Client/components/loadConnectionData.js +11 -7
- package/systemlynx/Client/tests/Client.test.js +27 -16
- package/systemlynx/Client/tests/SocketDispatcher.test.js +17 -6
- package/systemlynx/Dispatcher/Dispatcher.js +16 -1
- package/systemlynx/Dispatcher/Dispatcher.test.js +4 -3
- package/systemlynx/HttpClient/HttpClient.js +1 -1
- package/systemlynx/LoadBalancer/tests/LoadBalancer.test.js +30 -7
- package/systemlynx/ServerManager/ServerManager.js +82 -35
- package/systemlynx/ServerManager/components/Router.js +30 -11
- package/systemlynx/ServerManager/components/Server.js +22 -18
- package/systemlynx/ServerManager/components/SocketEmitter.js +2 -2
- package/systemlynx/ServerManager/components/WebSocketServer.js +2 -2
- package/systemlynx/ServerManager/components/clearFolder.js +10 -0
- package/systemlynx/ServerManager/components/parseMethods.js +1 -1
- package/systemlynx/ServerManager/tests/ServerManager.test.js +124 -11
- package/systemlynx/Service/Service.js +31 -12
- package/systemlynx/Service/Service.test.js +81 -16
- package/temp/.gitignore +0 -4
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const
|
|
3
|
-
const
|
|
2
|
+
const createServer = require("./components/Server");
|
|
3
|
+
const createRouter = require("./components/Router");
|
|
4
4
|
const SocketEmitter = require("./components/SocketEmitter");
|
|
5
|
-
const
|
|
5
|
+
const createWebSocket = require("./components/WebSocketServer");
|
|
6
6
|
const parseMethods = require("./components/parseMethods");
|
|
7
7
|
const shortId = require("shortid");
|
|
8
|
+
const randomPort = () => parseInt(Math.random() * parseInt(Math.random() * 10000)) + 1023;
|
|
9
|
+
const createSSLServer = (app, options) => {
|
|
10
|
+
const https = require("https");
|
|
11
|
+
return https.createServer(options, app);
|
|
12
|
+
};
|
|
8
13
|
|
|
9
|
-
module.exports = function
|
|
14
|
+
module.exports = function createServerManager(customServer, customWebSocketServer) {
|
|
10
15
|
let serverConfigurations = {
|
|
11
16
|
route: null,
|
|
12
17
|
port: null,
|
|
@@ -16,21 +21,27 @@ module.exports = function SystemLynxServerManager() {
|
|
|
16
21
|
useREST: false,
|
|
17
22
|
useService: true,
|
|
18
23
|
staticRouting: false,
|
|
19
|
-
|
|
24
|
+
ssl: { key: "", cert: "" },
|
|
25
|
+
validators: { $all: [] },
|
|
20
26
|
};
|
|
21
|
-
const server =
|
|
22
|
-
const router =
|
|
23
|
-
const { SocketServer, WebSocket } =
|
|
27
|
+
const server = createServer(customServer);
|
|
28
|
+
const router = createRouter(server, () => serverConfigurations);
|
|
29
|
+
const { SocketServer, WebSocket } = createWebSocket(customWebSocketServer);
|
|
24
30
|
const moduleQueue = [];
|
|
25
31
|
const modules = [];
|
|
26
32
|
|
|
27
33
|
const ServerManager = { server, WebSocket };
|
|
28
34
|
|
|
29
35
|
ServerManager.startService = (options) => {
|
|
30
|
-
let {
|
|
36
|
+
let {
|
|
37
|
+
route,
|
|
38
|
+
host = "localhost",
|
|
39
|
+
port,
|
|
40
|
+
socketPort = randomPort(),
|
|
41
|
+
staticRouting,
|
|
42
|
+
ssl,
|
|
43
|
+
} = options;
|
|
31
44
|
|
|
32
|
-
socketPort =
|
|
33
|
-
socketPort || parseInt(Math.random() * parseInt(Math.random() * 10000)) + 1023;
|
|
34
45
|
const namespace = staticRouting ? route : shortId();
|
|
35
46
|
SocketServer.listen(socketPort);
|
|
36
47
|
SocketEmitter.apply(ServerManager, [namespace, WebSocket]);
|
|
@@ -38,7 +49,8 @@ module.exports = function SystemLynxServerManager() {
|
|
|
38
49
|
route = route.charAt(0) === "/" ? route.substr(1) : route;
|
|
39
50
|
route =
|
|
40
51
|
route.charAt(route.length - 1) === "/" ? route.substr(route.length - 1) : route;
|
|
41
|
-
const
|
|
52
|
+
const protocol = ssl ? "https" : "http";
|
|
53
|
+
const serviceUrl = `${protocol}://${host}:${port}/${route}`;
|
|
42
54
|
|
|
43
55
|
serverConfigurations = {
|
|
44
56
|
...serverConfigurations,
|
|
@@ -57,46 +69,44 @@ module.exports = function SystemLynxServerManager() {
|
|
|
57
69
|
SystemLynxService: true,
|
|
58
70
|
};
|
|
59
71
|
|
|
60
|
-
const selectModules = (moduleList) =>
|
|
61
|
-
moduleList.reduce(
|
|
62
|
-
(sum, moduleName) =>
|
|
63
|
-
sum.concat(modules.find(({ name }) => name === moduleName) || []),
|
|
64
|
-
[]
|
|
65
|
-
);
|
|
66
|
-
|
|
67
72
|
server.get(`/${route}`, (req, res) => {
|
|
68
73
|
//The route will return connection data for the service including an array of
|
|
69
74
|
//modules (objects) which contain instructions on how to make request to each object
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
res.json({
|
|
73
|
-
...connectionData,
|
|
74
|
-
modules: query.modules ? selectModules(query.modules.split(",")) : modules,
|
|
75
|
-
});
|
|
75
|
+
res.json({ ...connectionData, modules });
|
|
76
76
|
});
|
|
77
77
|
|
|
78
|
-
return new Promise((resolve) =>
|
|
79
|
-
server
|
|
78
|
+
return new Promise((resolve) => {
|
|
79
|
+
const _server = ssl ? createSSLServer(server, ssl) : server;
|
|
80
|
+
_server.listen(port, () => {
|
|
80
81
|
console.log(`[SystemLynx][Service]: Listening on ${serviceUrl}`);
|
|
81
82
|
moduleQueue.forEach(({ name, Module, reserved_methods }) =>
|
|
82
83
|
ServerManager.addModule(name, Module, reserved_methods)
|
|
83
84
|
);
|
|
84
85
|
moduleQueue.length = 0;
|
|
85
86
|
resolve(connectionData);
|
|
86
|
-
})
|
|
87
|
-
);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
88
89
|
};
|
|
89
90
|
|
|
90
91
|
ServerManager.addModule = (name, Module, reserved_methods = []) => {
|
|
91
|
-
const {
|
|
92
|
-
|
|
92
|
+
const {
|
|
93
|
+
host,
|
|
94
|
+
route,
|
|
95
|
+
serviceUrl,
|
|
96
|
+
staticRouting,
|
|
97
|
+
useService,
|
|
98
|
+
useREST,
|
|
99
|
+
socketPort,
|
|
100
|
+
validators,
|
|
101
|
+
} = serverConfigurations;
|
|
93
102
|
|
|
94
103
|
if (!serviceUrl) return moduleQueue.push({ name, Module, reserved_methods });
|
|
95
|
-
const
|
|
104
|
+
const exclude_methods = ["on", "emit", "before", "$clearEvent", ...reserved_methods];
|
|
105
|
+
const methods = parseMethods(Module, exclude_methods, useREST);
|
|
96
106
|
const namespace = staticRouting ? name : shortId();
|
|
97
107
|
|
|
98
108
|
SocketEmitter.apply(Module, [namespace, WebSocket]);
|
|
99
|
-
|
|
109
|
+
const _validators = [...validators.$all, ...(validators[name] || [])];
|
|
100
110
|
if (useService) {
|
|
101
111
|
const path = staticRouting ? `${route}/${name}` : `${shortId()}/${shortId()}`;
|
|
102
112
|
|
|
@@ -106,19 +116,56 @@ module.exports = function SystemLynxServerManager() {
|
|
|
106
116
|
name,
|
|
107
117
|
methods,
|
|
108
118
|
});
|
|
109
|
-
methods.forEach((method) =>
|
|
119
|
+
methods.forEach((method) => {
|
|
120
|
+
const nsp = `${name}.${method.fn}`;
|
|
121
|
+
const customValidators = [..._validators, ...(validators[nsp] || [])];
|
|
122
|
+
router.addService(Module, path, method, name, customValidators);
|
|
123
|
+
});
|
|
110
124
|
}
|
|
111
125
|
if (useREST)
|
|
112
126
|
methods.forEach((method) => {
|
|
127
|
+
const nsp = `${name}.${method.fn}`;
|
|
128
|
+
const customValidators = [..._validators, ...(validators[nsp] || [])];
|
|
113
129
|
switch (method.fn) {
|
|
114
130
|
case "get":
|
|
115
131
|
case "put":
|
|
116
132
|
case "post":
|
|
117
133
|
case "delete":
|
|
118
|
-
router.addREST(Module, `${route}/${name}`, method, name);
|
|
134
|
+
router.addREST(Module, `${route}/${name}`, method, name, customValidators);
|
|
119
135
|
}
|
|
120
136
|
});
|
|
121
137
|
};
|
|
138
|
+
ServerManager.addRouteHandler = (...args) => {
|
|
139
|
+
const name = typeof args[0] === "string" ? args.shift() : "$all";
|
|
140
|
+
args.forEach(async (middleware) => {
|
|
141
|
+
if (Array.isArray(middleware)) {
|
|
142
|
+
middleware.map(addMiddleware);
|
|
143
|
+
} else {
|
|
144
|
+
addMiddleware(middleware);
|
|
145
|
+
}
|
|
146
|
+
});
|
|
122
147
|
|
|
148
|
+
function addMiddleware(middleware) {
|
|
149
|
+
if (!serverConfigurations.validators[name])
|
|
150
|
+
serverConfigurations.validators[name] = [];
|
|
151
|
+
serverConfigurations.validators[name].push(async function (req, res, next) {
|
|
152
|
+
try {
|
|
153
|
+
await middleware(req, res, next);
|
|
154
|
+
} catch (error) {
|
|
155
|
+
res.sendError(error);
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
};
|
|
123
160
|
return ServerManager;
|
|
124
161
|
};
|
|
162
|
+
|
|
163
|
+
//creating an ssl setup with openssl cli
|
|
164
|
+
//1. `openssl genrsa -out key.pem` to generate a private key
|
|
165
|
+
//2. create a certificate signing request using the key we just generated
|
|
166
|
+
// `openssl req -new -key key.pem -out csr.pem`
|
|
167
|
+
//3. Answer the prompts in the terminal
|
|
168
|
+
//4. use the newly generate csr to generate a ssl certificate
|
|
169
|
+
// openssl x509 -req -days 365 -in csr.pem -signkey key.pem -out cert.pem
|
|
170
|
+
//(x509 is the standard to use for the certificate, days are the number of day the cert is valid)
|
|
171
|
+
//5. csr.pem is no longer needed
|
|
@@ -3,8 +3,8 @@ const isObject = (value) =>
|
|
|
3
3
|
const isEmpty = (obj) => Object.getOwnPropertyNames(obj).length === 0;
|
|
4
4
|
const isPromise = (p) => typeof p === "object" && typeof (p || {}).then === "function";
|
|
5
5
|
|
|
6
|
-
module.exports = function
|
|
7
|
-
const addService = (Module, route, { fn, method }, module_name) => {
|
|
6
|
+
module.exports = function createRouter(server, config) {
|
|
7
|
+
const addService = (Module, route, { fn, method }, module_name, validators) => {
|
|
8
8
|
server[method](
|
|
9
9
|
[`/${route}/${fn}`, `/sf/${route}/${fn}`, `/mf/${route}/${fn}`],
|
|
10
10
|
(req, res, next) => {
|
|
@@ -13,11 +13,13 @@ module.exports = function SystemLynxRouter(server, config) {
|
|
|
13
13
|
req.Module = Module;
|
|
14
14
|
next();
|
|
15
15
|
},
|
|
16
|
-
|
|
16
|
+
setHelpers,
|
|
17
|
+
validators,
|
|
18
|
+
requestHandler
|
|
17
19
|
);
|
|
18
20
|
};
|
|
19
21
|
|
|
20
|
-
const addREST = (Module, route, { method }, module_name) => {
|
|
22
|
+
const addREST = (Module, route, { method }, module_name, validators) => {
|
|
21
23
|
server[method](
|
|
22
24
|
[`/${route}`],
|
|
23
25
|
(req, res, next) => {
|
|
@@ -26,12 +28,15 @@ module.exports = function SystemLynxRouter(server, config) {
|
|
|
26
28
|
req.Module = Module;
|
|
27
29
|
next();
|
|
28
30
|
},
|
|
29
|
-
|
|
31
|
+
setHelpers,
|
|
32
|
+
validators,
|
|
33
|
+
requestHandler
|
|
30
34
|
);
|
|
31
35
|
};
|
|
32
36
|
|
|
33
|
-
const
|
|
34
|
-
const { query, file, files, body,
|
|
37
|
+
const setHelpers = (req, res, next) => {
|
|
38
|
+
const { fn, module_name, query, file, files, body, method, Module } = req;
|
|
39
|
+
|
|
35
40
|
const { serviceUrl } = config();
|
|
36
41
|
const presets = { serviceUrl, module_name, fn };
|
|
37
42
|
const unhandledMessage = `[SystemLynx]: handled error While calling ${module_name}.${fn}(...)`;
|
|
@@ -44,12 +49,12 @@ module.exports = function SystemLynxRouter(server, config) {
|
|
|
44
49
|
...error,
|
|
45
50
|
status,
|
|
46
51
|
message,
|
|
47
|
-
|
|
52
|
+
SystemLynxService: true,
|
|
48
53
|
});
|
|
49
54
|
};
|
|
50
55
|
|
|
51
56
|
const sendResponse = (returnValue) => {
|
|
52
|
-
const status = (returnValue || {}).status
|
|
57
|
+
const status = (returnValue || {}).status >= 100 ? returnValue.status : 200;
|
|
53
58
|
if (status < 400) {
|
|
54
59
|
res.status(status).json({
|
|
55
60
|
...presets,
|
|
@@ -68,11 +73,25 @@ module.exports = function SystemLynxRouter(server, config) {
|
|
|
68
73
|
status: 404,
|
|
69
74
|
});
|
|
70
75
|
|
|
71
|
-
|
|
76
|
+
const getArguments = () => {
|
|
72
77
|
const args = body.__arguments || [];
|
|
73
78
|
if (!isEmpty(query) && !args.length) args.push(query);
|
|
74
|
-
if (isObject(args[0]) && method === "PUT")
|
|
79
|
+
if (isObject(args[0]) && method === "PUT")
|
|
80
|
+
args[0] = { ...args[0], ...(file && { file }), ...(files && { files }) };
|
|
81
|
+
return args;
|
|
82
|
+
};
|
|
83
|
+
req.arguments = getArguments();
|
|
84
|
+
res.sendError = sendError;
|
|
85
|
+
res.sendResponse = sendResponse;
|
|
86
|
+
next();
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const requestHandler = (req, res) => {
|
|
90
|
+
const { fn, Module } = req;
|
|
91
|
+
const { sendError, sendResponse } = res;
|
|
75
92
|
|
|
93
|
+
try {
|
|
94
|
+
const args = req.arguments;
|
|
76
95
|
const results = Module[fn].apply({ ...Module, req, res }, args);
|
|
77
96
|
|
|
78
97
|
if (isPromise(results)) {
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
//express server, socket.io server and middleware needed for SystemLynx basic functionality
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
const clearFolder = require("./clearFolder");
|
|
3
|
+
const clearTempFolder = clearFolder.bind({}, "./temp");
|
|
4
|
+
module.exports = function createServer(customServer) {
|
|
4
5
|
const cwd = process.cwd();
|
|
5
6
|
//express server
|
|
6
7
|
const express = require("express");
|
|
7
|
-
const server = express();
|
|
8
|
+
const server = customServer || express();
|
|
8
9
|
//express middleware
|
|
9
10
|
const multer = require("multer");
|
|
10
11
|
//express file upload middleware setup
|
|
@@ -17,19 +18,21 @@ module.exports = function SystemLynxServer() {
|
|
|
17
18
|
cb(null, `${shortId()}.${mime.getExtension(file.mimetype)}`),
|
|
18
19
|
});
|
|
19
20
|
//multi-file and single-file upload middleware functions
|
|
20
|
-
const sf = multer({ storage
|
|
21
|
-
const mf = multer({ storage
|
|
21
|
+
const sf = multer({ storage }).single("file");
|
|
22
|
+
const mf = multer({ storage }).array("files");
|
|
22
23
|
//the sf and mf functions are used to a extract file from the req during a file upload
|
|
23
24
|
//a property named file and files will be added to the req object respectively
|
|
24
25
|
const singleFileUpload = (req, res, next) =>
|
|
25
26
|
sf(req, res, (err) => {
|
|
26
|
-
if (err) res.json(
|
|
27
|
-
|
|
27
|
+
if (err) return res.json(err);
|
|
28
|
+
res.on("finish", clearTempFolder);
|
|
29
|
+
next();
|
|
28
30
|
});
|
|
29
31
|
const multiFileUpload = (req, res, next) =>
|
|
30
32
|
mf(req, res, (err) => {
|
|
31
|
-
if (err) res.json(
|
|
32
|
-
|
|
33
|
+
if (err) return res.json(err);
|
|
34
|
+
res.on("finish", clearTempFolder);
|
|
35
|
+
next();
|
|
33
36
|
});
|
|
34
37
|
|
|
35
38
|
server.use("/sf", singleFileUpload);
|
|
@@ -37,15 +40,16 @@ module.exports = function SystemLynxServer() {
|
|
|
37
40
|
server.use(express.static(cwd + "/public"));
|
|
38
41
|
server.use(express.json({ limit: "5mb" }));
|
|
39
42
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
!customServer &&
|
|
44
|
+
server.use((req, res, next) => {
|
|
45
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
46
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT ,DELETE");
|
|
47
|
+
res.setHeader(
|
|
48
|
+
"Access-Control-Allow-Headers",
|
|
49
|
+
"X-Requested-With,content-type, Authorization"
|
|
50
|
+
);
|
|
51
|
+
next();
|
|
52
|
+
});
|
|
49
53
|
|
|
50
54
|
return server;
|
|
51
55
|
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const
|
|
2
|
+
const createDispatcher = require("../../Dispatcher/Dispatcher");
|
|
3
3
|
const shortid = require("shortid");
|
|
4
4
|
module.exports = function SocketEmitter(namespace, WebSocket) {
|
|
5
5
|
const Emitter =
|
|
6
|
-
(this || {}).on && (this || {}).emit ? this :
|
|
6
|
+
(this || {}).on && (this || {}).emit ? this : createDispatcher.apply(this);
|
|
7
7
|
|
|
8
8
|
const socket = WebSocket.of(`/${namespace}`);
|
|
9
9
|
//use $emit to emit events locally only
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
module.exports = function
|
|
1
|
+
module.exports = function createWebSocket(server) {
|
|
2
2
|
const express = require("express");
|
|
3
|
-
const SocketServer = require("http").Server(express());
|
|
3
|
+
const SocketServer = require("http").Server(server || express());
|
|
4
4
|
const WebSocket = require("socket.io")(SocketServer);
|
|
5
5
|
|
|
6
6
|
return { WebSocket, SocketServer };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
module.exports = function clearFolder(folder) {
|
|
4
|
+
fs.readdir(folder, (err, files) => {
|
|
5
|
+
if (err) return console.error(err);
|
|
6
|
+
files.forEach((file) => {
|
|
7
|
+
fs.unlink(path.join(folder, file), (err) => err && console.error(err));
|
|
8
|
+
});
|
|
9
|
+
});
|
|
10
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const parseMethods = (obj, reserved_methods = [], useREST) => {
|
|
2
2
|
const methods = [];
|
|
3
|
-
const REST_methods = ["get", "put", "post", "delete"];
|
|
3
|
+
const REST_methods = ["get", "put", "post", "delete", "options"];
|
|
4
4
|
const props = Object.getOwnPropertyNames(obj);
|
|
5
5
|
|
|
6
6
|
props.forEach((fn) => {
|
|
@@ -1,21 +1,28 @@
|
|
|
1
1
|
const { expect } = require("chai");
|
|
2
|
-
const
|
|
2
|
+
const createServerManager = require("../ServerManager");
|
|
3
3
|
const request = require("request");
|
|
4
4
|
|
|
5
|
-
describe("
|
|
5
|
+
describe("createServerManager function", () => {
|
|
6
6
|
it("should return an ServerManager instance", () => {
|
|
7
|
-
const ServerManager =
|
|
7
|
+
const ServerManager = createServerManager();
|
|
8
8
|
|
|
9
9
|
expect(ServerManager)
|
|
10
10
|
.to.be.an("Object")
|
|
11
|
-
.that.has.all.keys([
|
|
11
|
+
.that.has.all.keys([
|
|
12
|
+
"startService",
|
|
13
|
+
"addModule",
|
|
14
|
+
"addRouteHandler",
|
|
15
|
+
"server",
|
|
16
|
+
"WebSocket",
|
|
17
|
+
])
|
|
12
18
|
.that.respondsTo("startService")
|
|
13
|
-
.that.respondsTo("addModule")
|
|
19
|
+
.that.respondsTo("addModule")
|
|
20
|
+
.that.respondsTo("addRouteHandler");
|
|
14
21
|
});
|
|
15
22
|
});
|
|
16
23
|
describe("ServerManager", () => {
|
|
17
24
|
it("should be able use ServerManager.startService to start a server that will accept requests for Module Connection Data on the given route", async () => {
|
|
18
|
-
const ServerManager =
|
|
25
|
+
const ServerManager = createServerManager();
|
|
19
26
|
const route = "/testService";
|
|
20
27
|
const port = 4400;
|
|
21
28
|
const url = `http://localhost:${port}${route}`;
|
|
@@ -43,7 +50,7 @@ describe("ServerManager", () => {
|
|
|
43
50
|
});
|
|
44
51
|
|
|
45
52
|
it("should be able to use the ServerManager.addModule method to add data to the ServerManager instance that can be accessed via a GET request", async () => {
|
|
46
|
-
const ServerManager =
|
|
53
|
+
const ServerManager = createServerManager();
|
|
47
54
|
const route = "/testService";
|
|
48
55
|
const port = 4634;
|
|
49
56
|
const url = `http://localhost:${port}${route}`;
|
|
@@ -78,7 +85,7 @@ describe("ServerManager", () => {
|
|
|
78
85
|
});
|
|
79
86
|
|
|
80
87
|
it("should be able call ServerManager.addModule method before or after calling ServerManager.startService", async () => {
|
|
81
|
-
const ServerManager =
|
|
88
|
+
const ServerManager = createServerManager();
|
|
82
89
|
const route = "/testService";
|
|
83
90
|
const port = 4500;
|
|
84
91
|
const url = `http://localhost:${port}${route}`;
|
|
@@ -117,13 +124,13 @@ describe("ServerManager", () => {
|
|
|
117
124
|
|
|
118
125
|
describe("ServerManager.startService(ServerConfiguration)", () => {
|
|
119
126
|
it("should be able to use the useREST=true property to create a REST API route for any method with the name 'get', 'put', 'post' or 'delete'", async () => {
|
|
120
|
-
const ServerManager =
|
|
127
|
+
const ServerManager = createServerManager();
|
|
121
128
|
const route = "/testAPI";
|
|
122
129
|
const port = 8372;
|
|
123
130
|
const url = `http://localhost:${port}${route}`;
|
|
124
131
|
const name = "testObject";
|
|
125
132
|
const object = {
|
|
126
|
-
get: () => (
|
|
133
|
+
get: () => ({ REST_TEST_PASSED: true }),
|
|
127
134
|
put: () => {},
|
|
128
135
|
post: () => {},
|
|
129
136
|
delete: () => {},
|
|
@@ -156,7 +163,7 @@ describe("ServerManager.startService(ServerConfiguration)", () => {
|
|
|
156
163
|
});
|
|
157
164
|
|
|
158
165
|
it("should be able to use the staticRouting=true property to create static routes to the Modules", async () => {
|
|
159
|
-
const ServerManager =
|
|
166
|
+
const ServerManager = createServerManager();
|
|
160
167
|
const route = "/testAPI";
|
|
161
168
|
const port = 2233;
|
|
162
169
|
const url = `http://localhost:${port}${route}`;
|
|
@@ -192,4 +199,110 @@ describe("ServerManager.startService(ServerConfiguration)", () => {
|
|
|
192
199
|
status: 200,
|
|
193
200
|
});
|
|
194
201
|
});
|
|
202
|
+
|
|
203
|
+
it("should be able to use the ServerManager.addRouteHandler method to add additional route handling", async () => {
|
|
204
|
+
const ServerManager = createServerManager();
|
|
205
|
+
const route = "/testAPI";
|
|
206
|
+
const port = 5454;
|
|
207
|
+
const url = `http://localhost:${port}${route}`;
|
|
208
|
+
const name = "testObject";
|
|
209
|
+
const object = {
|
|
210
|
+
get: function () {
|
|
211
|
+
const { req } = this;
|
|
212
|
+
return {
|
|
213
|
+
SERVICE_TEST_PASSED: true,
|
|
214
|
+
$allHandlerAdded: req.$allHandlerAdded,
|
|
215
|
+
putHandlerAdded: req.putHandlerAdded,
|
|
216
|
+
};
|
|
217
|
+
},
|
|
218
|
+
put: function () {
|
|
219
|
+
const { req } = this;
|
|
220
|
+
return {
|
|
221
|
+
SERVICE_TEST_PASSED: true,
|
|
222
|
+
$allHandlerAdded: req.$allHandlerAdded,
|
|
223
|
+
putHandlerAdded: req.putHandlerAdded,
|
|
224
|
+
};
|
|
225
|
+
},
|
|
226
|
+
test: function () {
|
|
227
|
+
return { SERVICE_TEST_PASSED: false };
|
|
228
|
+
},
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
ServerManager.addRouteHandler((req, res, next) => {
|
|
232
|
+
req.$allHandlerAdded = true;
|
|
233
|
+
next();
|
|
234
|
+
});
|
|
235
|
+
ServerManager.addRouteHandler(`${name}.put`, (req, res, next) => {
|
|
236
|
+
req.putHandlerAdded = true;
|
|
237
|
+
next();
|
|
238
|
+
});
|
|
239
|
+
ServerManager.addRouteHandler(`${name}.test`, (req, res, next) => {
|
|
240
|
+
res.sendError({ status: 400, message: "tested passed" });
|
|
241
|
+
});
|
|
242
|
+
ServerManager.addModule(name, object);
|
|
243
|
+
await ServerManager.startService({
|
|
244
|
+
route,
|
|
245
|
+
port,
|
|
246
|
+
staticRouting: true,
|
|
247
|
+
useREST: true,
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
const results = await new Promise((resolve) => {
|
|
251
|
+
request({ url: `${url}/${name}/get`, json: true }, (err, res, body) => {
|
|
252
|
+
resolve(body);
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
expect(results).to.deep.equal({
|
|
257
|
+
returnValue: {
|
|
258
|
+
SERVICE_TEST_PASSED: true,
|
|
259
|
+
$allHandlerAdded: true,
|
|
260
|
+
},
|
|
261
|
+
fn: "get",
|
|
262
|
+
message: "[SystemLynx][response]: testObject.get(...) returned successfully",
|
|
263
|
+
module_name: "testObject",
|
|
264
|
+
serviceUrl: "http://localhost:5454/testAPI",
|
|
265
|
+
status: 200,
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
const result2 = await new Promise((resolve) => {
|
|
269
|
+
request(
|
|
270
|
+
{ url: `${url}/${name}/put`, json: true, method: "PUT" },
|
|
271
|
+
(err, res, body) => {
|
|
272
|
+
resolve(body);
|
|
273
|
+
}
|
|
274
|
+
);
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
expect(result2).to.deep.equal({
|
|
278
|
+
returnValue: {
|
|
279
|
+
SERVICE_TEST_PASSED: true,
|
|
280
|
+
$allHandlerAdded: true,
|
|
281
|
+
putHandlerAdded: true,
|
|
282
|
+
},
|
|
283
|
+
fn: "put",
|
|
284
|
+
message: "[SystemLynx][response]: testObject.put(...) returned successfully",
|
|
285
|
+
module_name: "testObject",
|
|
286
|
+
serviceUrl: "http://localhost:5454/testAPI",
|
|
287
|
+
status: 200,
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
const result3 = await new Promise((resolve) => {
|
|
291
|
+
request(
|
|
292
|
+
{ url: `${url}/${name}/test`, json: true, method: "PUT" },
|
|
293
|
+
(err, res, body) => {
|
|
294
|
+
resolve(body);
|
|
295
|
+
}
|
|
296
|
+
);
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
expect(result3).to.deep.equal({
|
|
300
|
+
message: "tested passed",
|
|
301
|
+
fn: "test",
|
|
302
|
+
module_name: "testObject",
|
|
303
|
+
serviceUrl: "http://localhost:5454/testAPI",
|
|
304
|
+
status: 400,
|
|
305
|
+
SystemLynxService: true,
|
|
306
|
+
});
|
|
307
|
+
});
|
|
195
308
|
});
|
|
@@ -1,22 +1,41 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const
|
|
3
|
-
const
|
|
2
|
+
const createServerManager = require("../ServerManager/ServerManager");
|
|
3
|
+
const createDispatcher = require("../Dispatcher/Dispatcher");
|
|
4
4
|
|
|
5
|
-
module.exports = function
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
module.exports = function createService(
|
|
6
|
+
customServer,
|
|
7
|
+
customWebSocketServer,
|
|
8
|
+
systemContext = {}
|
|
9
|
+
) {
|
|
10
|
+
const ServerManager = createServerManager(customServer, customWebSocketServer);
|
|
11
|
+
const { startService, addRouteHandler, server, WebSocket } = ServerManager;
|
|
12
|
+
const Service = { startService, server, WebSocket, before: addRouteHandler };
|
|
9
13
|
|
|
10
14
|
Service.module = function (name, constructor, reserved_methods = []) {
|
|
11
15
|
const exclude_methods = reserved_methods.concat(
|
|
12
16
|
Object.getOwnPropertyNames(systemContext)
|
|
13
17
|
);
|
|
14
|
-
|
|
18
|
+
const before = (...args) => {
|
|
19
|
+
if (typeof args[0] === "string") {
|
|
20
|
+
const arg1 = args.shift();
|
|
21
|
+
const fn = arg1 === "$all" ? "" : `.${arg1}`;
|
|
22
|
+
addRouteHandler(`${name}${fn}`, ...args);
|
|
23
|
+
} else {
|
|
24
|
+
addRouteHandler(`${name}`, ...args);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
15
27
|
if (typeof constructor === "object" && constructor instanceof Object) {
|
|
16
|
-
const Module =
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
28
|
+
const Module = createDispatcher.apply(
|
|
29
|
+
{
|
|
30
|
+
...Object.getOwnPropertyNames(constructor).reduce((obj, fn) => {
|
|
31
|
+
if (typeof constructor[fn] === "function") obj[fn] = constructor[fn];
|
|
32
|
+
return obj;
|
|
33
|
+
}, {}),
|
|
34
|
+
...systemContext,
|
|
35
|
+
before,
|
|
36
|
+
},
|
|
37
|
+
[undefined, systemContext]
|
|
38
|
+
);
|
|
20
39
|
ServerManager.addModule(name, Module, exclude_methods);
|
|
21
40
|
return Module;
|
|
22
41
|
}
|
|
@@ -25,7 +44,7 @@ module.exports = function SystemLynxService(systemContext = {}) {
|
|
|
25
44
|
if (constructor.constructor.name === "AsyncFunction")
|
|
26
45
|
throw `[SystemLynx][Module][Error]: Module(name, constructor) function cannot receive an async function as the constructor`;
|
|
27
46
|
|
|
28
|
-
const Module =
|
|
47
|
+
const Module = createDispatcher.apply({ ...systemContext, before }, [
|
|
29
48
|
undefined,
|
|
30
49
|
systemContext,
|
|
31
50
|
]);
|