systemlynx 1.4.0 → 1.6.0
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 +10 -11
- package/README.md +14 -14
- package/index.test.js +2 -19
- package/package.json +1 -1
- package/systemlynx/App/App.js +12 -28
- package/systemlynx/App/components/initializeApp.js +4 -4
- package/systemlynx/App/components/loadModules.js +5 -11
- package/systemlynx/App/components/loadServices.js +9 -6
- package/systemlynx/App/tests/App.test.js +87 -21
- package/systemlynx/Client/Client.js +10 -4
- package/systemlynx/Client/components/ClientModule.js +3 -2
- package/systemlynx/Client/components/SocketDispatcher.js +2 -2
- package/systemlynx/Client/tests/Client.test.js +27 -24
- package/systemlynx/Dispatcher/Dispatcher.js +5 -2
- package/systemlynx/LoadBalancer/LoadBalancer.js +1 -1
- package/systemlynx/LoadBalancer/tests/LoadBalancer.test.js +3 -10
- package/systemlynx/ServerManager/ServerManager.js +8 -8
- package/systemlynx/ServerManager/components/Router.js +11 -11
- package/systemlynx/ServerManager/tests/ServerManager.test.js +2 -2
- package/systemlynx/Service/Service.js +21 -17
- package/systemlynx/Service/Service.test.js +10 -14
- package/systemlynx/utils/System.js +7 -0
- package/systemlynx/utils/SystemContext.js +10 -0
- package/systemlynx/App/components/SystemObject.js +0 -9
package/API.md
CHANGED
|
@@ -10,8 +10,7 @@ Welcome to the docs! Following is a list of the objects used and created when de
|
|
|
10
10
|
- [**startService(options)**](https://github.com/Odion100/SystemLynx/blob/tasksjs2.0/API.md#appstartserviceoptions)
|
|
11
11
|
- [**loadService(name, url)**](https://github.com/Odion100/SystemLynx/blob/tasksjs2.0/API.md#apploadserviceurl)
|
|
12
12
|
- [**onLoad(callback)**](https://github.com/Odion100/SystemLynx/tasksjs2.0/API.md#apponloadcallback)
|
|
13
|
-
- [**
|
|
14
|
-
- [**Module(name, constructor)**](https://github.com/Odion100/SystemLynx/tasksjs2.0/API.md#appmodulename-constructor)
|
|
13
|
+
- [**module(name, constructor [,reserved_methods])**]()
|
|
15
14
|
- [**config(constructor)**](https://github.com/Odion100/SystemLynx/tasksjs2.0/API.md#appconfigconstructor)
|
|
16
15
|
- [**on(event, callback)**]()
|
|
17
16
|
- [**emit(event, payload)**]()
|
|
@@ -29,7 +28,7 @@ Welcome to the docs! Following is a list of the objects used and created when de
|
|
|
29
28
|
<summary><b><a href="https://github.com/Odion100/SystemLynx/tasksjs2.0/API.md#service">Service</a></b></summary>
|
|
30
29
|
|
|
31
30
|
- [**startService(options)**]()
|
|
32
|
-
- [**
|
|
31
|
+
- [**module(name, constructor [,options])**]()
|
|
33
32
|
- [**Server()**]()
|
|
34
33
|
- [**WebSocket()**]()
|
|
35
34
|
|
|
@@ -39,7 +38,7 @@ Welcome to the docs! Following is a list of the objects used and created when de
|
|
|
39
38
|
<summary><b><a href="https://github.com/Odion100/SystemLynx/tasksjs2.0/API.md#service">LoadBalancer</a></b></summary>
|
|
40
39
|
|
|
41
40
|
- [**startService(options)**]()
|
|
42
|
-
- [**
|
|
41
|
+
- [**module(name, constructor [,options])**]()
|
|
43
42
|
- [**Server()**]()
|
|
44
43
|
- [**WebSocket()**]()
|
|
45
44
|
- [**clones**]()
|
|
@@ -61,7 +60,7 @@ Welcome to the docs! Following is a list of the objects used and created when de
|
|
|
61
60
|
</details>
|
|
62
61
|
|
|
63
62
|
<details>
|
|
64
|
-
<summary><b><a href="https://github.com/Odion100/SystemLynx/tasksjs2.0/API.md">
|
|
63
|
+
<summary><b><a href="https://github.com/Odion100/SystemLynx/tasksjs2.0/API.md">module</a></b></summary>
|
|
65
64
|
|
|
66
65
|
- [**[created_method]([args...] [,callback])**]()
|
|
67
66
|
- [**on(name, constructor [,options])**]()
|
|
@@ -79,9 +78,9 @@ Welcome to the docs! Following is a list of the objects used and created when de
|
|
|
79
78
|
const { App } = require("systemlynx");
|
|
80
79
|
```
|
|
81
80
|
|
|
82
|
-
## App.
|
|
81
|
+
## App.module(name, constructor [,reserved_methods])
|
|
83
82
|
|
|
84
|
-
Use **App.
|
|
83
|
+
Use **App.module(name, constructor)** function to create or pass an object that can be loaded by a SystemLynx Client.
|
|
85
84
|
|
|
86
85
|
- **_name_** (string) - name assigned to the module or object
|
|
87
86
|
- **_constructor_** (object/function) -
|
|
@@ -92,7 +91,7 @@ Use **App.ServerModule(name, constructor)** function to create or pass an object
|
|
|
92
91
|
|
|
93
92
|
## App.onLoad(callback)
|
|
94
93
|
|
|
95
|
-
## App.
|
|
94
|
+
## App.module(name, constructor)
|
|
96
95
|
|
|
97
96
|
## App.config(constructor)
|
|
98
97
|
|
|
@@ -116,15 +115,15 @@ const { Service } = require("systemlynx");
|
|
|
116
115
|
|
|
117
116
|
The Service object has the following methods:
|
|
118
117
|
|
|
119
|
-
- **_Service.
|
|
118
|
+
- **_Service.module(name, constructor [,reserved_methods])_** - Used to create or pass an object that is hosted by the Service.
|
|
120
119
|
- **_Service.startService(options)_** - Used
|
|
121
120
|
- **_Service.Server()_** - Returns the expressJS app instance used to handle routing to the _Services_.
|
|
122
121
|
- **_Service.WebSocket()_** - Returns socket.io WebSocket instance used to emit events from the _Services_.
|
|
123
122
|
|
|
124
|
-
## Service.
|
|
123
|
+
## Service.module(name, constructor [,reserved_methods])
|
|
125
124
|
|
|
126
125
|
- **Name** - String -
|
|
127
|
-
Use the `Service.
|
|
126
|
+
Use the `Service.module(name, constructor, [,options])` method to register an object to be hosted by a _SystemLynx Service_. This will allows you to load an instance of that object onto a client application, and call any methods on that object remotely.
|
|
128
127
|
|
|
129
128
|
```javascript
|
|
130
129
|
const { Service } = require("systemlynx");
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# SystemLynx JS   
|
|
2
2
|
|
|
3
|
-
SystemLynx is a framework for developing modular web APIs in NodeJS. It's a wrapper on top of ExpressJS and Socket.io. With SystemLynx, instead of developing a server with endpoints, you can simply
|
|
3
|
+
SystemLynx is a framework for developing modular web APIs in NodeJS. It's a wrapper on top of ExpressJS and Socket.io. With SystemLynx, instead of developing a server with endpoints, you can simply import objects from a server into a client application. Basically any objects hosted by a SystemLynx Service can be loaded and used by a SystemLynx Client.
|
|
4
4
|
|
|
5
5
|
SystemLynx comes with the following objects that are used for web app development:
|
|
6
6
|
|
|
@@ -20,9 +20,9 @@ Find the full [API Documentation](https://github.com/Odion100/SystemLynx/blob/ta
|
|
|
20
20
|
|
|
21
21
|
# Quick Start
|
|
22
22
|
|
|
23
|
-
## Service.
|
|
23
|
+
## Service.module(name, constructor [,options])
|
|
24
24
|
|
|
25
|
-
Use the `Service.
|
|
25
|
+
Use the `Service.module(name, constructor/object)` method to add an object to be hosted by a **SystemLynx Service**. This will allows you to load an instance of that object into a client application, and call any methods on that object remotely.
|
|
26
26
|
|
|
27
27
|
```javascript
|
|
28
28
|
const { Service } = require("systemlynx");
|
|
@@ -34,12 +34,12 @@ Users.add = function (data) {
|
|
|
34
34
|
return { message: "You have successfully called the Users.add method" };
|
|
35
35
|
};
|
|
36
36
|
|
|
37
|
-
Service.
|
|
37
|
+
Service.module("Users", Users);
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
-
In the code above we assigned an object to the variable `Users` and gave it an add method. The `Service.
|
|
40
|
+
In the code above we assigned an object to the variable `Users` and gave it an add method. The `Service.module(name, constructor/object)` function takes the name assigned to the object as the first argument and the object itself as the second argument.
|
|
41
41
|
|
|
42
|
-
Alternatively, you can use a constructor function instead of an object as the second argument. In the example below we create another **
|
|
42
|
+
Alternatively, you can use a constructor function instead of an object as the second argument. In the example below we create another **Module** called "Orders". This time we use a constructor function as the second argument of the to **Service.module** function. The `this` value is the initial instance of the **Module** object. Every method added to the `this` value will be accessible when the object is loaded by a **SystemLynx Client**. Note: **Module** methods can be synchronous or asynchronous functions.
|
|
43
43
|
|
|
44
44
|
```javascript
|
|
45
45
|
const { Service } = require("systemlynx");
|
|
@@ -51,9 +51,9 @@ Users.add = function (data) {
|
|
|
51
51
|
return { message: "You have successfully called the Users.add method" };
|
|
52
52
|
};
|
|
53
53
|
|
|
54
|
-
Service.
|
|
54
|
+
Service.module("Users", Users);
|
|
55
55
|
|
|
56
|
-
Service.
|
|
56
|
+
Service.module("Orders", function () {
|
|
57
57
|
const Orders = this;
|
|
58
58
|
|
|
59
59
|
Orders.find = async function (arg1, arg2) {
|
|
@@ -77,9 +77,9 @@ Users.add = function (data) {
|
|
|
77
77
|
return { message: "You have successfully called the Users.add method" };
|
|
78
78
|
};
|
|
79
79
|
|
|
80
|
-
Service.
|
|
80
|
+
Service.module("Users", Users);
|
|
81
81
|
|
|
82
|
-
Service.
|
|
82
|
+
Service.module("Orders", function () {
|
|
83
83
|
const Orders = this;
|
|
84
84
|
|
|
85
85
|
Orders.find = function (arg1, arg2) {
|
|
@@ -125,7 +125,7 @@ console.log(response);
|
|
|
125
125
|
|
|
126
126
|
## Sending and Receiving Websocket Events
|
|
127
127
|
|
|
128
|
-
We can also receive WebSocket events emitted from the remote objects we've loaded using the `Client.loadService(url)` function. In the example below we're using the `Users.on(event_name, callback)` method to listen for events coming from the "Users" **
|
|
128
|
+
We can also receive WebSocket events emitted from the remote objects we've loaded using the `Client.loadService(url)` function. In the example below we're using the `Users.on(event_name, callback)` method to listen for events coming from the "Users" **Module**.
|
|
129
129
|
|
|
130
130
|
```javascript
|
|
131
131
|
const { Client } = require("systemlynx");
|
|
@@ -147,7 +147,7 @@ const response = await Orders.find("hello", "world");
|
|
|
147
147
|
console.log(response);
|
|
148
148
|
```
|
|
149
149
|
|
|
150
|
-
Now let's go to our server application and call the `Users.emit(event_name, data)` method to emit a websocket event that can be received by its corresponding Clients. Below, notice that we've added `this.emit("new_user", { message:"new_user event test" })` at the end of the `Users.add` method, so the `new_user` event will be emitted every time this method is called. The `this` value of a **
|
|
150
|
+
Now let's go to our server application and call the `Users.emit(event_name, data)` method to emit a websocket event that can be received by its corresponding Clients. Below, notice that we've added `this.emit("new_user", { message:"new_user event test" })` at the end of the `Users.add` method, so the `new_user` event will be emitted every time this method is called. The `this` value of a **Module** method will always be scoped to the **Module** itself.
|
|
151
151
|
|
|
152
152
|
```javascript
|
|
153
153
|
const { Service } = require("systemlynx");
|
|
@@ -160,9 +160,9 @@ Users.add = function (data) {
|
|
|
160
160
|
this.emit("new_user", { message: "new_user event test" });
|
|
161
161
|
};
|
|
162
162
|
|
|
163
|
-
Service.
|
|
163
|
+
Service.module("Users", Users);
|
|
164
164
|
|
|
165
|
-
Service.
|
|
165
|
+
Service.module("Orders", function () {
|
|
166
166
|
const Orders = this;
|
|
167
167
|
|
|
168
168
|
Orders.find = function (arg1, arg2) {
|
package/index.test.js
CHANGED
|
@@ -33,7 +33,6 @@ describe("SystemLynx Objects", () => {
|
|
|
33
33
|
.to.be.an("object")
|
|
34
34
|
.that.has.all.keys(
|
|
35
35
|
"module",
|
|
36
|
-
"ServerModule",
|
|
37
36
|
"on",
|
|
38
37
|
"emit",
|
|
39
38
|
"startService",
|
|
@@ -42,7 +41,6 @@ describe("SystemLynx Objects", () => {
|
|
|
42
41
|
"config"
|
|
43
42
|
)
|
|
44
43
|
.that.respondsTo("module")
|
|
45
|
-
.that.respondsTo("ServerModule")
|
|
46
44
|
.that.respondsTo("on")
|
|
47
45
|
.that.respondsTo("emit")
|
|
48
46
|
.that.respondsTo("startService")
|
|
@@ -69,18 +67,11 @@ describe("SystemLynx Objects", () => {
|
|
|
69
67
|
it("should return a SystemLynx LoadBalancer", () => {
|
|
70
68
|
expect(LoadBalancer)
|
|
71
69
|
.to.be.an("object")
|
|
72
|
-
.that.has.all.keys(
|
|
73
|
-
"startService",
|
|
74
|
-
"Server",
|
|
75
|
-
"WebSocket",
|
|
76
|
-
"defaultModule",
|
|
77
|
-
"ServerModule",
|
|
78
|
-
"clones"
|
|
79
|
-
)
|
|
70
|
+
.that.has.all.keys("startService", "Server", "WebSocket", "clones", "module")
|
|
80
71
|
.that.respondsTo("startService")
|
|
81
72
|
.that.respondsTo("Server")
|
|
82
73
|
.that.respondsTo("WebSocket")
|
|
83
|
-
.that.respondsTo("
|
|
74
|
+
.that.respondsTo("module");
|
|
84
75
|
expect(LoadBalancer.clones)
|
|
85
76
|
.to.be.an("object")
|
|
86
77
|
.that.has.all.keys("on", "emit", "clones", "register", "dispatch", "assignDispatch")
|
|
@@ -106,15 +97,7 @@ describe("SystemLynx Objects", () => {
|
|
|
106
97
|
it("should return a new instance of a Service", () => {
|
|
107
98
|
expect(Service)
|
|
108
99
|
.to.be.an("object")
|
|
109
|
-
.that.has.all.keys(
|
|
110
|
-
"startService",
|
|
111
|
-
"ServerModule",
|
|
112
|
-
"Server",
|
|
113
|
-
"WebSocket",
|
|
114
|
-
"defaultModule"
|
|
115
|
-
)
|
|
116
100
|
.that.respondsTo("startService")
|
|
117
|
-
.that.respondsTo("ServerModule")
|
|
118
101
|
.that.respondsTo("Server")
|
|
119
102
|
.that.respondsTo("WebSocket");
|
|
120
103
|
});
|
package/package.json
CHANGED
package/systemlynx/App/App.js
CHANGED
|
@@ -1,34 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const { isNode } = require("../../utils/ProcessChecker");
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const Dispatcher = require("../Dispatcher/Dispatcher");
|
|
3
|
+
const SystemLynxService = require("../Service/Service");
|
|
4
|
+
const SystemLynxDispatcher = require("../Dispatcher/Dispatcher");
|
|
6
5
|
const initializeApp = require("./components/initializeApp");
|
|
6
|
+
const SystemContext = require("../utils/SystemContext");
|
|
7
|
+
const System = require("../utils/System");
|
|
7
8
|
|
|
8
9
|
module.exports = function SystemLynxApp() {
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
ServerModules: [],
|
|
14
|
-
configurations: {},
|
|
15
|
-
App,
|
|
16
|
-
routing: null,
|
|
17
|
-
};
|
|
18
|
-
SystemObject.apply(system, [system]);
|
|
19
|
-
setTimeout(() => initializeApp(system), 0);
|
|
10
|
+
const system = new System();
|
|
11
|
+
const systemContext = SystemContext(system);
|
|
12
|
+
const App = SystemLynxDispatcher(undefined, systemContext);
|
|
13
|
+
setTimeout(() => initializeApp(system, App, systemContext), 0);
|
|
20
14
|
|
|
21
15
|
if (isNode) {
|
|
22
|
-
system.Service =
|
|
23
|
-
system.Service.defaultModule = SystemObject(system);
|
|
16
|
+
system.Service = SystemLynxService(systemContext);
|
|
24
17
|
|
|
25
18
|
App.startService = (options) => {
|
|
26
19
|
system.routing = options;
|
|
27
20
|
return App;
|
|
28
21
|
};
|
|
29
22
|
|
|
30
|
-
App.
|
|
31
|
-
system.
|
|
23
|
+
App.module = (name, __constructor) => {
|
|
24
|
+
system.Modules.push({
|
|
32
25
|
name,
|
|
33
26
|
__constructor,
|
|
34
27
|
});
|
|
@@ -52,18 +45,9 @@ module.exports = function SystemLynxApp() {
|
|
|
52
45
|
return App;
|
|
53
46
|
};
|
|
54
47
|
|
|
55
|
-
App.module = (name, __constructor) => {
|
|
56
|
-
system.Modules.push({
|
|
57
|
-
name,
|
|
58
|
-
__constructor,
|
|
59
|
-
module: SystemObject(system),
|
|
60
|
-
});
|
|
61
|
-
return App;
|
|
62
|
-
};
|
|
63
|
-
|
|
64
48
|
App.config = (__constructor) => {
|
|
65
49
|
if (typeof __constructor === "function")
|
|
66
|
-
system.configurations = { __constructor, module:
|
|
50
|
+
system.configurations = { __constructor, module: SystemContext(system) };
|
|
67
51
|
else
|
|
68
52
|
throw Error(
|
|
69
53
|
"[SystemLynx][App][Error]: App.config(...) methods requires a constructor function as its first parameter."
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const loadModules = require("./loadModules");
|
|
2
2
|
const loadServices = require("./loadServices");
|
|
3
3
|
|
|
4
|
-
module.exports = async function initApp(system) {
|
|
4
|
+
module.exports = async function initApp(system, App, systemContext) {
|
|
5
5
|
let configComplete = false;
|
|
6
6
|
const continuationERROR = () => {
|
|
7
7
|
if (!configComplete)
|
|
@@ -16,7 +16,7 @@ module.exports = async function initApp(system) {
|
|
|
16
16
|
};
|
|
17
17
|
|
|
18
18
|
try {
|
|
19
|
-
await loadServices(system);
|
|
19
|
+
await loadServices(system, App, systemContext);
|
|
20
20
|
} catch (err) {
|
|
21
21
|
throw `[SystemLynx][App][Error]: Initialization Error - failed to load all services`;
|
|
22
22
|
}
|
|
@@ -26,8 +26,8 @@ module.exports = async function initApp(system) {
|
|
|
26
26
|
system.configurations.__constructor.apply(system.configurations.module, [
|
|
27
27
|
() => {
|
|
28
28
|
configComplete = true;
|
|
29
|
-
loadModules(system);
|
|
29
|
+
loadModules(system, App);
|
|
30
30
|
},
|
|
31
31
|
]);
|
|
32
|
-
} else loadModules(system);
|
|
32
|
+
} else loadModules(system, App);
|
|
33
33
|
};
|
|
@@ -1,14 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
module
|
|
4
|
-
system.Modules.forEach((mod) => {
|
|
5
|
-
Dispatcher.apply(mod.module);
|
|
6
|
-
mod.__constructor.apply(mod.module);
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
system.ServerModules.forEach(({ name, __constructor }) =>
|
|
10
|
-
system.Service.ServerModule(name, __constructor)
|
|
1
|
+
module.exports = async function loadModules(system, App) {
|
|
2
|
+
system.Modules.forEach(
|
|
3
|
+
(mod) => (mod.module = system.Service.module(mod.name, mod.__constructor))
|
|
11
4
|
);
|
|
5
|
+
|
|
12
6
|
if (system.routing) await system.Service.startService(system.routing);
|
|
13
|
-
|
|
7
|
+
App.emit("ready", system);
|
|
14
8
|
};
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
const
|
|
2
|
-
|
|
1
|
+
const SystemLynxClient = require("../../Client/Client");
|
|
2
|
+
|
|
3
|
+
module.exports = ({ Services }, App, systemContext) => {
|
|
4
|
+
const Client = SystemLynxClient(systemContext);
|
|
5
|
+
|
|
3
6
|
return Promise.all(
|
|
4
|
-
Services.map(serviceData => {
|
|
7
|
+
Services.map((serviceData) => {
|
|
5
8
|
const { url, limit, wait, name, onLoad } = serviceData;
|
|
6
|
-
return new Promise(resolve => {
|
|
9
|
+
return new Promise((resolve) => {
|
|
7
10
|
Client.loadService(url, { limit, wait })
|
|
8
|
-
.then(service => {
|
|
11
|
+
.then((service) => {
|
|
9
12
|
serviceData.client = service;
|
|
10
13
|
if (typeof onLoad === "function") {
|
|
11
14
|
onLoad(serviceData.client);
|
|
@@ -17,7 +20,7 @@ module.exports = ({ Services, App }) => {
|
|
|
17
20
|
);
|
|
18
21
|
resolve();
|
|
19
22
|
})
|
|
20
|
-
.catch(err => {
|
|
23
|
+
.catch((err) => {
|
|
21
24
|
console.warn(err);
|
|
22
25
|
App.emit("failed_connection", { err, ...serviceData });
|
|
23
26
|
resolve();
|
|
@@ -11,7 +11,6 @@ describe("App Factory", () => {
|
|
|
11
11
|
.to.be.an("object")
|
|
12
12
|
.that.has.all.keys(
|
|
13
13
|
"module",
|
|
14
|
-
"ServerModule",
|
|
15
14
|
"on",
|
|
16
15
|
"emit",
|
|
17
16
|
"startService",
|
|
@@ -20,7 +19,6 @@ describe("App Factory", () => {
|
|
|
20
19
|
"config"
|
|
21
20
|
)
|
|
22
21
|
.that.respondsTo("module")
|
|
23
|
-
.that.respondsTo("ServerModule")
|
|
24
22
|
.that.respondsTo("on")
|
|
25
23
|
.that.respondsTo("emit")
|
|
26
24
|
.that.respondsTo("startService")
|
|
@@ -35,7 +33,7 @@ describe("App: Loading Services", () => {
|
|
|
35
33
|
const route = "test-service";
|
|
36
34
|
const port = "8503";
|
|
37
35
|
|
|
38
|
-
Service.
|
|
36
|
+
Service.module("mod", function () {
|
|
39
37
|
this.test = () => {};
|
|
40
38
|
this.test2 = () => {};
|
|
41
39
|
});
|
|
@@ -68,7 +66,7 @@ describe("App: Loading Services", () => {
|
|
|
68
66
|
const port = "8422";
|
|
69
67
|
const url = `http://localhost:${port}/${route}`;
|
|
70
68
|
|
|
71
|
-
Service.
|
|
69
|
+
Service.module("mod", function () {
|
|
72
70
|
this.test = () => {};
|
|
73
71
|
this.test2 = () => {};
|
|
74
72
|
});
|
|
@@ -95,7 +93,7 @@ describe("App: Loading Services", () => {
|
|
|
95
93
|
const route = "test-service";
|
|
96
94
|
const port = "8423";
|
|
97
95
|
const url = `http://localhost:${port}/${route}`;
|
|
98
|
-
Service.
|
|
96
|
+
Service.module("mod", function () {
|
|
99
97
|
this.test = () => {};
|
|
100
98
|
this.test2 = () => {};
|
|
101
99
|
});
|
|
@@ -131,7 +129,7 @@ describe("App: Loading Services", () => {
|
|
|
131
129
|
const port = "8442";
|
|
132
130
|
const url = `http://localhost:${port}/${route}`;
|
|
133
131
|
|
|
134
|
-
Service.
|
|
132
|
+
Service.module("mod", function () {
|
|
135
133
|
this.test = () => {};
|
|
136
134
|
this.test2 = () => {};
|
|
137
135
|
});
|
|
@@ -156,7 +154,7 @@ describe("App: Loading Services", () => {
|
|
|
156
154
|
});
|
|
157
155
|
});
|
|
158
156
|
|
|
159
|
-
describe("App SystemObjects: Initializing Modules,
|
|
157
|
+
describe("App SystemObjects: Initializing Modules, Modules and configurations", () => {
|
|
160
158
|
it("should be able to use App.module to initialize a module", async () => {
|
|
161
159
|
const App = AppFactory();
|
|
162
160
|
return new Promise((resolve) =>
|
|
@@ -208,18 +206,18 @@ describe("App SystemObjects: Initializing Modules, ServerModules and configurat
|
|
|
208
206
|
.that.is.an("array").that.is.empty;
|
|
209
207
|
expect(connData.serviceUrl).to.equal(url);
|
|
210
208
|
});
|
|
211
|
-
it("should be able to use App.
|
|
209
|
+
it("should be able to use App.module to add a hosted Module to the Service", async () => {
|
|
212
210
|
const App = AppFactory();
|
|
213
211
|
const route = "test-service";
|
|
214
212
|
const port = "8494";
|
|
215
213
|
const url = `http://localhost:${port}/${route}`;
|
|
216
214
|
await new Promise((resolve) =>
|
|
217
215
|
App.startService({ route, port })
|
|
218
|
-
.
|
|
216
|
+
.module("mod", function () {
|
|
219
217
|
this.test = () => {};
|
|
220
218
|
this.test2 = () => {};
|
|
221
219
|
})
|
|
222
|
-
.
|
|
220
|
+
.module("mod2", function () {
|
|
223
221
|
this.test = () => {};
|
|
224
222
|
this.test2 = () => {};
|
|
225
223
|
})
|
|
@@ -256,7 +254,7 @@ describe("App SystemObjects: Initializing Modules, ServerModules and configurat
|
|
|
256
254
|
it('should be able to use App.on("ready", callback) fire a callback when App initialization is complete', async () => {
|
|
257
255
|
const App = AppFactory();
|
|
258
256
|
|
|
259
|
-
App.
|
|
257
|
+
App.module("mod", function () {
|
|
260
258
|
this.test = () => {};
|
|
261
259
|
this.test2 = () => {};
|
|
262
260
|
}).module("mod", function () {
|
|
@@ -272,23 +270,18 @@ describe("App SystemObjects: Initializing Modules, ServerModules and configurat
|
|
|
272
270
|
"Services",
|
|
273
271
|
"Service",
|
|
274
272
|
"Modules",
|
|
275
|
-
"ServerModules",
|
|
276
273
|
"configurations",
|
|
277
|
-
"
|
|
278
|
-
"routing",
|
|
279
|
-
"useService",
|
|
280
|
-
"useModule",
|
|
281
|
-
"useConfig"
|
|
274
|
+
"routing"
|
|
282
275
|
);
|
|
283
276
|
resolve();
|
|
284
277
|
})
|
|
285
278
|
);
|
|
286
279
|
});
|
|
287
280
|
|
|
288
|
-
it("should be able to use App.config(constructor) to construct a
|
|
281
|
+
it("should be able to use App.config(constructor) to construct a configuration module", async () => {
|
|
289
282
|
const App = AppFactory();
|
|
290
283
|
|
|
291
|
-
App.
|
|
284
|
+
App.module("mod", function () {
|
|
292
285
|
this.test = () => {};
|
|
293
286
|
this.test2 = () => {};
|
|
294
287
|
})
|
|
@@ -317,8 +310,8 @@ describe("App SystemObjects: Initializing Modules, ServerModules and configurat
|
|
|
317
310
|
});
|
|
318
311
|
});
|
|
319
312
|
|
|
320
|
-
describe("
|
|
321
|
-
it("should be able to use this.useModule and this.useService within modules and
|
|
313
|
+
describe("SystemContext", () => {
|
|
314
|
+
it("should be able to use this.useModule and this.useService within modules and Module", () => {
|
|
322
315
|
const App = AppFactory();
|
|
323
316
|
App.module("mod1", function () {
|
|
324
317
|
expect(this)
|
|
@@ -339,6 +332,7 @@ describe("SystemObjects", () => {
|
|
|
339
332
|
const config = this.useConfig();
|
|
340
333
|
expect(mod1.testPassed).to.equal(true);
|
|
341
334
|
expect(config.configPassed).to.equal(true);
|
|
335
|
+
this.testPassed = true;
|
|
342
336
|
})
|
|
343
337
|
.config(function (next) {
|
|
344
338
|
expect(this)
|
|
@@ -348,7 +342,79 @@ describe("SystemObjects", () => {
|
|
|
348
342
|
.that.respondsTo("useConfig");
|
|
349
343
|
this.configPassed = true;
|
|
350
344
|
next();
|
|
345
|
+
})
|
|
346
|
+
.on("ready", function () {
|
|
347
|
+
expect(this)
|
|
348
|
+
.to.be.an("object")
|
|
349
|
+
.that.respondsTo("useService")
|
|
350
|
+
.that.respondsTo("useModule")
|
|
351
|
+
.that.respondsTo("useConfig");
|
|
352
|
+
const mod1 = this.useModule("mod1");
|
|
353
|
+
const config = this.useConfig();
|
|
354
|
+
expect(mod1.testPassed).to.equal(true);
|
|
355
|
+
expect(config.configPassed).to.equal(true);
|
|
356
|
+
})
|
|
357
|
+
.on("ready", function () {
|
|
358
|
+
expect(this)
|
|
359
|
+
.to.be.an("object")
|
|
360
|
+
.that.respondsTo("useService")
|
|
361
|
+
.that.respondsTo("useModule")
|
|
362
|
+
.that.respondsTo("useConfig");
|
|
363
|
+
const mod2 = this.useModule("mod2");
|
|
364
|
+
const config = this.useConfig();
|
|
365
|
+
expect(mod2.testPassed).to.equal(true);
|
|
366
|
+
expect(config.configPassed).to.equal(true);
|
|
351
367
|
});
|
|
352
368
|
return new Promise((resolve) => App.on("ready", () => resolve()));
|
|
353
369
|
});
|
|
370
|
+
it("[SystemLynx][App][Client][on] should have access to systemContext during event callbacks.", async () => {
|
|
371
|
+
const AppBackend = AppFactory();
|
|
372
|
+
const eventName = "testing-this";
|
|
373
|
+
const _route = "test-service";
|
|
374
|
+
const _port = "8900";
|
|
375
|
+
const _url = `http://localhost:${_port}/${_route}`;
|
|
376
|
+
AppBackend.module("EventTesterModule", function () {
|
|
377
|
+
this.sendEvent = () => this.emit(eventName, { testPassed: true });
|
|
378
|
+
|
|
379
|
+
//testing local event callback context
|
|
380
|
+
this.on(eventName, function () {
|
|
381
|
+
console.log("Aww man... here we go again!", this);
|
|
382
|
+
expect(this)
|
|
383
|
+
.to.be.an("object")
|
|
384
|
+
.that.respondsTo("useService")
|
|
385
|
+
.that.respondsTo("useModule")
|
|
386
|
+
.that.respondsTo("useConfig");
|
|
387
|
+
});
|
|
388
|
+
});
|
|
389
|
+
await AppBackend.startService({ route: _route, port: _port });
|
|
390
|
+
|
|
391
|
+
const AppClient = AppFactory();
|
|
392
|
+
const route = "test-service";
|
|
393
|
+
const port = "8901";
|
|
394
|
+
|
|
395
|
+
AppClient.startService({ route, port }).loadService("buAPI", _url);
|
|
396
|
+
await new Promise((resolve) =>
|
|
397
|
+
AppClient.on("ready", function () {
|
|
398
|
+
const { EventTesterModule } = this.useService("buAPI");
|
|
399
|
+
EventTesterModule.on(eventName, function (data, event) {
|
|
400
|
+
console.log("Ladies and gentleman... another one!");
|
|
401
|
+
expect(this)
|
|
402
|
+
.to.be.an("object")
|
|
403
|
+
.that.respondsTo("useService")
|
|
404
|
+
.that.respondsTo("useModule")
|
|
405
|
+
.that.respondsTo("useConfig");
|
|
406
|
+
expect(data).to.deep.equal({ testPassed: true });
|
|
407
|
+
expect(event)
|
|
408
|
+
.to.be.an("object")
|
|
409
|
+
.that.has.all.keys("id", "name", "data", "type");
|
|
410
|
+
expect(event.name).to.equal(eventName);
|
|
411
|
+
expect(event.data).to.deep.equal({ testPassed: true });
|
|
412
|
+
expect(event.id).to.be.a("string");
|
|
413
|
+
expect(event.type).to.equal("WebSocket");
|
|
414
|
+
resolve();
|
|
415
|
+
});
|
|
416
|
+
EventTesterModule.sendEvent(eventName);
|
|
417
|
+
})
|
|
418
|
+
);
|
|
419
|
+
});
|
|
354
420
|
});
|
|
@@ -3,7 +3,7 @@ const loadConnectionData = require("./components/loadConnectionData");
|
|
|
3
3
|
const SocketDispatcher = require("./components/SocketDispatcher");
|
|
4
4
|
const ClientModule = require("./components/ClientModule");
|
|
5
5
|
|
|
6
|
-
module.exports = function SystemLynxClient() {
|
|
6
|
+
module.exports = function SystemLynxClient(systemContext) {
|
|
7
7
|
const Client = {};
|
|
8
8
|
Client.loadedServices = {};
|
|
9
9
|
|
|
@@ -12,14 +12,14 @@ module.exports = function SystemLynxClient() {
|
|
|
12
12
|
return Client.loadedServices[url];
|
|
13
13
|
|
|
14
14
|
const connData = await loadConnectionData(url, options);
|
|
15
|
-
const Service = SocketDispatcher(connData.namespace);
|
|
15
|
+
const Service = SocketDispatcher(connData.namespace, undefined, systemContext);
|
|
16
16
|
Client.loadedServices[url] = Service;
|
|
17
17
|
if (options.name) Client[options.name] = Service;
|
|
18
18
|
|
|
19
19
|
Service.resetConnection = async (cb) => {
|
|
20
20
|
const { modules, host, port, namespace } = await loadConnectionData(url, options);
|
|
21
21
|
|
|
22
|
-
SocketDispatcher.apply(Service, [namespace]);
|
|
22
|
+
SocketDispatcher.apply(Service, [namespace, undefined, systemContext]);
|
|
23
23
|
|
|
24
24
|
modules.forEach(({ namespace, route, name }) =>
|
|
25
25
|
Service[name].__setConnection(host, port, route, namespace)
|
|
@@ -29,7 +29,13 @@ module.exports = function SystemLynxClient() {
|
|
|
29
29
|
};
|
|
30
30
|
|
|
31
31
|
connData.modules.forEach(
|
|
32
|
-
(mod) =>
|
|
32
|
+
(mod) =>
|
|
33
|
+
(Service[mod.name] = ClientModule(
|
|
34
|
+
mod,
|
|
35
|
+
connData,
|
|
36
|
+
Service.resetConnection,
|
|
37
|
+
systemContext
|
|
38
|
+
))
|
|
33
39
|
);
|
|
34
40
|
|
|
35
41
|
Service.on("disconnect", Service.resetConnection);
|
|
@@ -4,14 +4,15 @@ const SocketDispatcher = require("./SocketDispatcher");
|
|
|
4
4
|
module.exports = function SystemLynxClientModule(
|
|
5
5
|
{ methods, namespace, route },
|
|
6
6
|
{ port, host },
|
|
7
|
-
resetConnection
|
|
7
|
+
resetConnection,
|
|
8
|
+
systemContext
|
|
8
9
|
) {
|
|
9
10
|
const events = {};
|
|
10
11
|
const ClientModule = this || {};
|
|
11
12
|
|
|
12
13
|
ClientModule.__setConnection = (host, port, route, namespace) => {
|
|
13
14
|
ClientModule.__connectionData = () => ({ route, host, port });
|
|
14
|
-
SocketDispatcher.apply(ClientModule, [namespace, events]);
|
|
15
|
+
SocketDispatcher.apply(ClientModule, [namespace, events, systemContext]);
|
|
15
16
|
};
|
|
16
17
|
|
|
17
18
|
ClientModule.__setConnection(host, port, route, namespace);
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
const io = require("socket.io-client");
|
|
3
3
|
const SystemLynxDispatcher = require("../../Dispatcher/Dispatcher");
|
|
4
4
|
|
|
5
|
-
module.exports = function SocketDispatcher(namespace, events = {}) {
|
|
5
|
+
module.exports = function SocketDispatcher(namespace, events = {}, systemContext) {
|
|
6
6
|
const dispatcher =
|
|
7
7
|
(this || {}).on && (this || {}).emit
|
|
8
8
|
? this
|
|
9
|
-
: SystemLynxDispatcher.apply(this, [events]);
|
|
9
|
+
: SystemLynxDispatcher.apply(this, [events, systemContext]);
|
|
10
10
|
const socket = io.connect(namespace);
|
|
11
11
|
socket.on("dispatch", (event) => dispatcher.emit(event.name, event.data, event));
|
|
12
12
|
socket.on("disconnect", () => {
|
|
@@ -17,7 +17,7 @@ describe("Client Factory", () => {
|
|
|
17
17
|
});
|
|
18
18
|
describe("Client", () => {
|
|
19
19
|
it("should be able to use Client.loadService(url, options) to return a promise that resolve into a backend service", async () => {
|
|
20
|
-
Service.
|
|
20
|
+
Service.module(
|
|
21
21
|
"orders",
|
|
22
22
|
function () {
|
|
23
23
|
this.action1 = (data) => ({ SERVICE_TEST_PASSED: true, ...data, action1: true });
|
|
@@ -73,7 +73,7 @@ describe("Client", () => {
|
|
|
73
73
|
});
|
|
74
74
|
|
|
75
75
|
describe("Service", () => {
|
|
76
|
-
it("should be able to call methods from the frontend client to the backend
|
|
76
|
+
it("should be able to call methods from the frontend client to the backend Module", async () => {
|
|
77
77
|
const Client = ClientFactory();
|
|
78
78
|
const buAPI = await Client.loadService(url);
|
|
79
79
|
|
|
@@ -88,7 +88,7 @@ describe("Service", () => {
|
|
|
88
88
|
action2: true,
|
|
89
89
|
});
|
|
90
90
|
});
|
|
91
|
-
it("should be able to send multiple arguments to the backend
|
|
91
|
+
it("should be able to send multiple arguments to the backend Module", async () => {
|
|
92
92
|
const Client = ClientFactory();
|
|
93
93
|
const buAPI = await Client.loadService(url);
|
|
94
94
|
const arg1 = 4,
|
|
@@ -119,27 +119,32 @@ describe("Service", () => {
|
|
|
119
119
|
|
|
120
120
|
it("should be able to receive events emitted from the backend Client", async () => {
|
|
121
121
|
const eventName = "testing";
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
|
|
122
|
+
const route = "test-service";
|
|
123
|
+
const port = "8980";
|
|
124
|
+
const url = `http://localhost:${port}/${route}`;
|
|
125
|
+
const Service = ServiceFactory();
|
|
126
|
+
const eventTester = Service.module("eventTester", function () {
|
|
127
|
+
this.sendEvent = () => this.emit(eventName, { testPassed: true });
|
|
125
128
|
});
|
|
129
|
+
await Service.startService({ route, port });
|
|
126
130
|
|
|
127
131
|
const Client = ClientFactory();
|
|
128
|
-
const buAPI = await Client.loadService(url);
|
|
129
132
|
|
|
130
|
-
buAPI.
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
133
|
+
const buAPI = await Client.loadService(url);
|
|
134
|
+
setTimeout(() => eventTester.emit(eventName, { testPassed: true }), 500);
|
|
135
|
+
|
|
136
|
+
await new Promise((resolve) => {
|
|
137
|
+
buAPI.eventTester.on(eventName, (data, event) => {
|
|
138
|
+
console.log("Ladies and gentleman... mission accomplish!");
|
|
139
|
+
expect(data).to.deep.equal({ testPassed: true });
|
|
140
|
+
expect(event).to.be.an("object").that.has.all.keys("id", "name", "data", "type");
|
|
141
|
+
expect(event.name).to.equal(eventName);
|
|
142
|
+
expect(event.data).to.deep.equal({ testPassed: true });
|
|
143
|
+
expect(event.id).to.be.a("string");
|
|
144
|
+
expect(event.type).to.equal("WebSocket");
|
|
145
|
+
resolve();
|
|
146
|
+
});
|
|
140
147
|
});
|
|
141
|
-
|
|
142
|
-
eventTester.emit(eventName, { testPassed: true });
|
|
143
148
|
});
|
|
144
149
|
|
|
145
150
|
it("should be able to send REST http requests", async () => {
|
|
@@ -149,7 +154,7 @@ describe("Service", () => {
|
|
|
149
154
|
const port = "8492";
|
|
150
155
|
const url = `http://localhost:${port}/${route}`;
|
|
151
156
|
const useREST = true;
|
|
152
|
-
Service.
|
|
157
|
+
Service.module("restTester", function () {
|
|
153
158
|
this.get = (data) => ({ REST_TEST_PASSED: true, getResponse: true, ...data });
|
|
154
159
|
this.put = () => ({ REST_TEST_PASSED: true, putResponse: true });
|
|
155
160
|
this.post = () => ({ REST_TEST_PASSED: true, postResponse: true });
|
|
@@ -177,13 +182,13 @@ describe("Service", () => {
|
|
|
177
182
|
});
|
|
178
183
|
});
|
|
179
184
|
|
|
180
|
-
it("should be able to use 'useReturnValue' configuration option to enable synchronous return values from
|
|
185
|
+
it("should be able to use 'useReturnValue' configuration option to enable synchronous return values from Module methods", async () => {
|
|
181
186
|
const service = ServiceFactory();
|
|
182
187
|
const route = "sync/test";
|
|
183
188
|
const port = 4920;
|
|
184
189
|
const host = "localhost";
|
|
185
190
|
const url = `http://localhost:${port}/${route}`;
|
|
186
|
-
service.
|
|
191
|
+
service.module("AsyncMath", function () {
|
|
187
192
|
this.max = Math.max;
|
|
188
193
|
this.min = Math.min;
|
|
189
194
|
this.round = Math.round;
|
|
@@ -193,8 +198,6 @@ describe("Service", () => {
|
|
|
193
198
|
route,
|
|
194
199
|
port,
|
|
195
200
|
host,
|
|
196
|
-
useReturnValues: true,
|
|
197
|
-
useCallbacks: false,
|
|
198
201
|
});
|
|
199
202
|
const Client = ClientFactory();
|
|
200
203
|
const { AsyncMath } = await Client.loadService(url);
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
module.exports = function SystemLynxDispatcher(events = {}) {
|
|
2
|
+
module.exports = function SystemLynxDispatcher(events = {}, systemContext) {
|
|
3
3
|
const Dispatcher = this || {};
|
|
4
4
|
|
|
5
5
|
Dispatcher.emit = (eventName, data, event) => {
|
|
6
|
-
if (events[eventName])
|
|
6
|
+
if (events[eventName])
|
|
7
|
+
events[eventName].forEach((callback) =>
|
|
8
|
+
callback.apply(systemContext, [data, event])
|
|
9
|
+
);
|
|
7
10
|
return Dispatcher;
|
|
8
11
|
};
|
|
9
12
|
|
|
@@ -2,6 +2,6 @@ const Service = require("../Service/Service");
|
|
|
2
2
|
const CloneManager = require("./components/CloneManager");
|
|
3
3
|
module.exports = function LoadBalancer() {
|
|
4
4
|
const LoadBalancer = Service();
|
|
5
|
-
const clones = LoadBalancer.
|
|
5
|
+
const clones = LoadBalancer.module("clones", CloneManager);
|
|
6
6
|
return { ...LoadBalancer, clones };
|
|
7
7
|
};
|
|
@@ -9,18 +9,11 @@ describe("LoadBalancerFactory", () => {
|
|
|
9
9
|
it("should return a SystemLynx LoadBalancer", () => {
|
|
10
10
|
expect(LoadBalancer)
|
|
11
11
|
.to.be.an("object")
|
|
12
|
-
.that.has.all.keys(
|
|
13
|
-
"startService",
|
|
14
|
-
"Server",
|
|
15
|
-
"WebSocket",
|
|
16
|
-
"defaultModule",
|
|
17
|
-
"ServerModule",
|
|
18
|
-
"clones"
|
|
19
|
-
)
|
|
12
|
+
.that.has.all.keys("startService", "Server", "WebSocket", "module", "clones")
|
|
20
13
|
.that.respondsTo("startService")
|
|
21
14
|
.that.respondsTo("Server")
|
|
22
15
|
.that.respondsTo("WebSocket")
|
|
23
|
-
.that.respondsTo("
|
|
16
|
+
.that.respondsTo("module");
|
|
24
17
|
expect(LoadBalancer.clones)
|
|
25
18
|
.to.be.an("object")
|
|
26
19
|
.that.has.all.keys("on", "emit", "clones", "register", "dispatch", "assignDispatch")
|
|
@@ -60,7 +53,7 @@ describe("LoadBalancer", () => {
|
|
|
60
53
|
.to.has.a.lengthOf(1);
|
|
61
54
|
});
|
|
62
55
|
});
|
|
63
|
-
describe("LoadBalancer.clones (
|
|
56
|
+
describe("LoadBalancer.clones (Module)", () => {
|
|
64
57
|
const test_service1 = {
|
|
65
58
|
route: "test-service1",
|
|
66
59
|
port: 5393,
|
|
@@ -64,8 +64,8 @@ module.exports = function SystemLynxServerManager() {
|
|
|
64
64
|
return new Promise((resolve) =>
|
|
65
65
|
server.listen(port, () => {
|
|
66
66
|
console.log(`[SystemLynx][Service]: Listening on ${serviceUrl}`);
|
|
67
|
-
moduleQueue.forEach(({ name,
|
|
68
|
-
ServerManager.addModule(name,
|
|
67
|
+
moduleQueue.forEach(({ name, Module, reserved_methods }) =>
|
|
68
|
+
ServerManager.addModule(name, Module, reserved_methods)
|
|
69
69
|
);
|
|
70
70
|
moduleQueue.length = 0;
|
|
71
71
|
resolve(ServerManager);
|
|
@@ -73,15 +73,15 @@ module.exports = function SystemLynxServerManager() {
|
|
|
73
73
|
);
|
|
74
74
|
};
|
|
75
75
|
|
|
76
|
-
ServerManager.addModule = (name,
|
|
76
|
+
ServerManager.addModule = (name, Module, reserved_methods = []) => {
|
|
77
77
|
const { host, route, serviceUrl, staticRouting, useService, useREST, socketPort } =
|
|
78
78
|
serverConfigurations;
|
|
79
79
|
|
|
80
|
-
if (!serviceUrl) return moduleQueue.push({ name,
|
|
81
|
-
const methods = parseMethods(
|
|
80
|
+
if (!serviceUrl) return moduleQueue.push({ name, Module, reserved_methods });
|
|
81
|
+
const methods = parseMethods(Module, ["on", "emit", ...reserved_methods], useREST);
|
|
82
82
|
const namespace = staticRouting ? name : shortId();
|
|
83
83
|
|
|
84
|
-
SocketEmitter.apply(
|
|
84
|
+
SocketEmitter.apply(Module, [namespace, WebSocket]);
|
|
85
85
|
|
|
86
86
|
if (useService) {
|
|
87
87
|
const path = staticRouting ? `${route}/${name}` : `${shortId()}/${shortId()}`;
|
|
@@ -92,7 +92,7 @@ module.exports = function SystemLynxServerManager() {
|
|
|
92
92
|
name,
|
|
93
93
|
methods,
|
|
94
94
|
});
|
|
95
|
-
methods.forEach((method) => router.addService(
|
|
95
|
+
methods.forEach((method) => router.addService(Module, path, method, name));
|
|
96
96
|
}
|
|
97
97
|
if (useREST)
|
|
98
98
|
methods.forEach((method) => {
|
|
@@ -101,7 +101,7 @@ module.exports = function SystemLynxServerManager() {
|
|
|
101
101
|
case "put":
|
|
102
102
|
case "post":
|
|
103
103
|
case "delete":
|
|
104
|
-
router.addREST(
|
|
104
|
+
router.addREST(Module, `${route}/${name}`, method, name);
|
|
105
105
|
}
|
|
106
106
|
});
|
|
107
107
|
};
|
|
@@ -4,26 +4,26 @@ const isEmpty = (obj) => Object.getOwnPropertyNames(obj).length === 0;
|
|
|
4
4
|
const isPromise = (p) => typeof p === "object" && typeof p.then === "function";
|
|
5
5
|
|
|
6
6
|
module.exports = function SystemLynxRouter(server, config) {
|
|
7
|
-
const addService = (
|
|
7
|
+
const addService = (Module, route, { fn, method }, module_name) => {
|
|
8
8
|
server[method](
|
|
9
9
|
[`/${route}/${fn}`, `/sf/${route}/${fn}`, `/mf/${route}/${fn}`],
|
|
10
10
|
(req, res, next) => {
|
|
11
11
|
req.module_name = module_name;
|
|
12
12
|
req.fn = fn;
|
|
13
|
-
req.
|
|
13
|
+
req.Module = Module;
|
|
14
14
|
next();
|
|
15
15
|
},
|
|
16
16
|
routeHandler
|
|
17
17
|
);
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
-
const addREST = (
|
|
20
|
+
const addREST = (Module, route, { method }, module_name) => {
|
|
21
21
|
server[method](
|
|
22
22
|
[`/${route}`],
|
|
23
23
|
(req, res, next) => {
|
|
24
24
|
req.module_name = module_name;
|
|
25
25
|
req.fn = method;
|
|
26
|
-
req.
|
|
26
|
+
req.Module = Module;
|
|
27
27
|
next();
|
|
28
28
|
},
|
|
29
29
|
routeHandler
|
|
@@ -31,13 +31,13 @@ module.exports = function SystemLynxRouter(server, config) {
|
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
const routeHandler = (req, res) => {
|
|
34
|
-
const { query, file, files, body, fn,
|
|
34
|
+
const { query, file, files, body, fn, Module, module_name, method } = req;
|
|
35
35
|
const { serviceUrl } = config();
|
|
36
36
|
const presets = { serviceUrl, module_name, fn };
|
|
37
37
|
|
|
38
38
|
const sendError = (error) => {
|
|
39
|
-
const status = error.status || 500;
|
|
40
|
-
const message = error.message || "Unexpected error";
|
|
39
|
+
const status = (error || {}).status || 500;
|
|
40
|
+
const message = (error || {}).message || "Unexpected error";
|
|
41
41
|
const unhandledMessage = status === 500 ? "Unhandled error" : "Error";
|
|
42
42
|
res.status(status).json({
|
|
43
43
|
...presets,
|
|
@@ -49,20 +49,20 @@ module.exports = function SystemLynxRouter(server, config) {
|
|
|
49
49
|
};
|
|
50
50
|
|
|
51
51
|
const sendResponse = (returnValue) => {
|
|
52
|
-
const status = returnValue.status || 200;
|
|
52
|
+
const status = (returnValue || {}).status || 200;
|
|
53
53
|
if (status < 400) {
|
|
54
54
|
res.status(status).json({
|
|
55
55
|
...presets,
|
|
56
56
|
status,
|
|
57
57
|
message:
|
|
58
|
-
returnValue.message ||
|
|
58
|
+
(returnValue || {}).message ||
|
|
59
59
|
`[SystemLynx][response]: ${module_name}.${fn}(...) returned successfully`,
|
|
60
60
|
returnValue,
|
|
61
61
|
});
|
|
62
62
|
} else sendError(returnValue);
|
|
63
63
|
};
|
|
64
64
|
|
|
65
|
-
if (typeof
|
|
65
|
+
if (typeof Module[fn] !== "function")
|
|
66
66
|
return sendResponse({
|
|
67
67
|
message: `[SystemLynx][error]:${module_name}.${fn} method not found`,
|
|
68
68
|
status: 404,
|
|
@@ -73,7 +73,7 @@ module.exports = function SystemLynxRouter(server, config) {
|
|
|
73
73
|
if (!isEmpty(query) && !args.length) args.push(query);
|
|
74
74
|
if (isObject(args[0]) && method === "PUT") args[0] = { ...args[0], file, files };
|
|
75
75
|
|
|
76
|
-
const results =
|
|
76
|
+
const results = Module[fn].apply(Module, args);
|
|
77
77
|
|
|
78
78
|
if (isPromise(results)) {
|
|
79
79
|
results.then(sendResponse).catch(sendError);
|
|
@@ -16,7 +16,7 @@ describe("SystemLynxServerManager function", () => {
|
|
|
16
16
|
});
|
|
17
17
|
});
|
|
18
18
|
describe("ServerManager", () => {
|
|
19
|
-
it("should be able use ServerManager.startService to start a server that will accept requests for
|
|
19
|
+
it("should be able use ServerManager.startService to start a server that will accept requests for Module Connection Data on the given route", async () => {
|
|
20
20
|
const ServerManager = SystemLynxServerManager();
|
|
21
21
|
const route = "/testService";
|
|
22
22
|
const port = 4400;
|
|
@@ -157,7 +157,7 @@ describe("ServerManager.startService(ServerConfiguration)", () => {
|
|
|
157
157
|
});
|
|
158
158
|
});
|
|
159
159
|
|
|
160
|
-
it("should be able to use the staticRouting=true property to create static routes to the
|
|
160
|
+
it("should be able to use the staticRouting=true property to create static routes to the Modules", async () => {
|
|
161
161
|
const ServerManager = SystemLynxServerManager();
|
|
162
162
|
const route = "/testAPI";
|
|
163
163
|
const port = 2233;
|
|
@@ -1,33 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const ServerManagerFactory = require("../ServerManager/ServerManager");
|
|
3
|
-
const
|
|
3
|
+
const SystemLynxDispatcher = require("../Dispatcher/Dispatcher");
|
|
4
4
|
|
|
5
|
-
module.exports = function ServiceFactory(
|
|
5
|
+
module.exports = function ServiceFactory(systemContext = {}) {
|
|
6
6
|
const ServerManager = ServerManagerFactory();
|
|
7
7
|
const { startService, Server, WebSocket } = ServerManager;
|
|
8
|
-
const Service = { startService, Server, WebSocket
|
|
8
|
+
const Service = { startService, Server, WebSocket };
|
|
9
|
+
|
|
10
|
+
Service.module = function (name, constructor, reserved_methods = []) {
|
|
11
|
+
const exclude_methods = reserved_methods.concat(
|
|
12
|
+
Object.getOwnPropertyNames(systemContext)
|
|
13
|
+
);
|
|
9
14
|
|
|
10
|
-
Service.ServerModule = function (name, constructor, reserved_methods = []) {
|
|
11
15
|
if (typeof constructor === "object" && constructor instanceof Object) {
|
|
12
|
-
|
|
13
|
-
|
|
16
|
+
const Module = SystemLynxDispatcher.apply({ ...constructor, ...systemContext }, [
|
|
17
|
+
undefined,
|
|
18
|
+
systemContext,
|
|
19
|
+
]);
|
|
20
|
+
ServerManager.addModule(name, Module, exclude_methods);
|
|
21
|
+
return Module;
|
|
14
22
|
}
|
|
15
23
|
|
|
16
24
|
if (typeof constructor === "function") {
|
|
17
25
|
if (constructor.constructor.name === "AsyncFunction")
|
|
18
|
-
throw `[SystemLynx][
|
|
26
|
+
throw `[SystemLynx][Module][Error]: Module(name, constructor) function cannot receive an async function as the constructor`;
|
|
19
27
|
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
...Object.getOwnPropertyNames(ServerModule),
|
|
24
|
-
];
|
|
25
|
-
constructor.apply(ServerModule, [
|
|
26
|
-
ServerManager.Server(),
|
|
27
|
-
ServerManager.WebSocket(),
|
|
28
|
+
const Module = SystemLynxDispatcher.apply(systemContext, [
|
|
29
|
+
undefined,
|
|
30
|
+
systemContext,
|
|
28
31
|
]);
|
|
29
|
-
|
|
30
|
-
|
|
32
|
+
constructor.apply(Module, [ServerManager.Server(), ServerManager.WebSocket()]);
|
|
33
|
+
ServerManager.addModule(name, Module, exclude_methods);
|
|
34
|
+
return Module;
|
|
31
35
|
}
|
|
32
36
|
};
|
|
33
37
|
return Service;
|
|
@@ -7,15 +7,9 @@ describe("SystemLynxService", () => {
|
|
|
7
7
|
const Service = ServiceFactory();
|
|
8
8
|
expect(Service)
|
|
9
9
|
.to.be.an("object")
|
|
10
|
-
.that.has.all.keys(
|
|
11
|
-
"startService",
|
|
12
|
-
"ServerModule",
|
|
13
|
-
"Server",
|
|
14
|
-
"WebSocket",
|
|
15
|
-
"defaultModule"
|
|
16
|
-
)
|
|
10
|
+
.that.has.all.keys("startService", "module", "Server", "WebSocket")
|
|
17
11
|
.that.respondsTo("startService")
|
|
18
|
-
.that.respondsTo("
|
|
12
|
+
.that.respondsTo("module")
|
|
19
13
|
.that.respondsTo("Server")
|
|
20
14
|
.that.respondsTo("WebSocket");
|
|
21
15
|
});
|
|
@@ -54,14 +48,14 @@ describe("Service factory", () => {
|
|
|
54
48
|
it("should throw an Error if Service.startService(options) is called twice", () => {});
|
|
55
49
|
});
|
|
56
50
|
|
|
57
|
-
describe("Service.
|
|
51
|
+
describe("Service.module(constructor)", () => {
|
|
58
52
|
const Service = ServiceFactory();
|
|
59
53
|
const port = 6542;
|
|
60
54
|
const route = "test/service";
|
|
61
55
|
const url = `http://localhost:${port}/${route}`;
|
|
62
56
|
|
|
63
57
|
it("should be able to return a Service instance constructed using the 'this' value in the constructor function", () => {
|
|
64
|
-
const mod = Service.
|
|
58
|
+
const mod = Service.module("mod", function () {
|
|
65
59
|
this.test = () => {};
|
|
66
60
|
this.test2 = () => {};
|
|
67
61
|
});
|
|
@@ -116,22 +110,24 @@ describe("Service.ServerModule(constructor)", () => {
|
|
|
116
110
|
});
|
|
117
111
|
});
|
|
118
112
|
|
|
119
|
-
describe("Service.
|
|
113
|
+
describe("Service.module(object)", () => {
|
|
120
114
|
const Service = ServiceFactory();
|
|
121
115
|
const port = 6543;
|
|
122
116
|
const route = "test/service2";
|
|
123
117
|
const url = `http://localhost:${port}/${route}`;
|
|
124
118
|
it("should be able to return a Service instance created using an object as the constructor", () => {
|
|
125
|
-
const mod = Service.
|
|
119
|
+
const mod = Service.module("mod", {
|
|
126
120
|
action1: () => {},
|
|
127
121
|
action2: () => {},
|
|
128
122
|
});
|
|
129
123
|
|
|
130
124
|
expect(mod)
|
|
131
125
|
.to.be.an("Object")
|
|
132
|
-
.that.has.all.keys("action1", "action2")
|
|
126
|
+
.that.has.all.keys("action1", "action2", "on", "emit")
|
|
133
127
|
.that.respondsTo("action1")
|
|
134
|
-
.that.respondsTo("action2")
|
|
128
|
+
.that.respondsTo("action2")
|
|
129
|
+
.that.respondsTo("on")
|
|
130
|
+
.that.respondsTo("emit");
|
|
135
131
|
});
|
|
136
132
|
it("should 'Serve' Service connection data created using an object as the constructor", async () => {
|
|
137
133
|
await Service.startService({ route, port });
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
module.exports = function SystemObject(system) {
|
|
3
|
+
const context = this || {};
|
|
4
|
+
context.useModule = (modName) =>
|
|
5
|
+
(system.Modules.find((mod) => mod.name === modName) || {}).module || {};
|
|
6
|
+
context.useService = (serviceName) =>
|
|
7
|
+
(system.Services.find((mod) => mod.name === serviceName) || {}).client || {};
|
|
8
|
+
context.useConfig = () => system.configurations.module || {};
|
|
9
|
+
return context;
|
|
10
|
+
};
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
module.exports = function SystemObject(system) {
|
|
3
|
-
const App = this || {};
|
|
4
|
-
App.useModule = modName => (system.Modules.find(mod => mod.name === modName) || {}).module || {};
|
|
5
|
-
App.useService = serviceName =>
|
|
6
|
-
(system.Services.find(mod => mod.name === serviceName) || {}).client || {};
|
|
7
|
-
App.useConfig = () => system.configurations.module || {};
|
|
8
|
-
return App;
|
|
9
|
-
};
|