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.
Files changed (31) hide show
  1. package/API.md +7 -0
  2. package/README.md +11 -5
  3. package/index.js +22 -23
  4. package/index.test.js +47 -17
  5. package/package.json +1 -1
  6. package/systemlynx/App/App.js +11 -6
  7. package/systemlynx/App/components/initializeApp.js +2 -2
  8. package/systemlynx/App/components/loadServices.js +3 -3
  9. package/systemlynx/App/tests/App.test.js +95 -31
  10. package/systemlynx/Client/Client.js +6 -3
  11. package/systemlynx/Client/components/ClientModule.js +9 -3
  12. package/systemlynx/Client/components/ServiceRequestHandler.js +23 -19
  13. package/systemlynx/Client/components/SocketDispatcher.js +2 -2
  14. package/systemlynx/Client/components/loadConnectionData.js +11 -7
  15. package/systemlynx/Client/tests/Client.test.js +27 -16
  16. package/systemlynx/Client/tests/SocketDispatcher.test.js +17 -6
  17. package/systemlynx/Dispatcher/Dispatcher.js +16 -1
  18. package/systemlynx/Dispatcher/Dispatcher.test.js +4 -3
  19. package/systemlynx/HttpClient/HttpClient.js +1 -1
  20. package/systemlynx/LoadBalancer/tests/LoadBalancer.test.js +30 -7
  21. package/systemlynx/ServerManager/ServerManager.js +82 -35
  22. package/systemlynx/ServerManager/components/Router.js +30 -11
  23. package/systemlynx/ServerManager/components/Server.js +22 -18
  24. package/systemlynx/ServerManager/components/SocketEmitter.js +2 -2
  25. package/systemlynx/ServerManager/components/WebSocketServer.js +2 -2
  26. package/systemlynx/ServerManager/components/clearFolder.js +10 -0
  27. package/systemlynx/ServerManager/components/parseMethods.js +1 -1
  28. package/systemlynx/ServerManager/tests/ServerManager.test.js +124 -11
  29. package/systemlynx/Service/Service.js +31 -12
  30. package/systemlynx/Service/Service.test.js +81 -16
  31. package/temp/.gitignore +0 -4
@@ -1,17 +1,21 @@
1
1
  "use strict";
2
2
  const ServiceRequestHandler = require("./ServiceRequestHandler");
3
3
  const SocketDispatcher = require("./SocketDispatcher");
4
+ const getProtocol = (url) => url.match(/^(\w+):\/\//)[0];
5
+
4
6
  module.exports = function SystemLynxClientModule(
7
+ httpClient,
5
8
  { methods, namespace, route, connectionData, name },
6
- { port, host },
9
+ { port, host, serviceUrl },
7
10
  reconnectService,
8
11
  systemContext
9
12
  ) {
10
13
  const events = {};
11
- const ClientModule = this || {};
14
+ const ClientModule = {};
12
15
 
13
16
  ClientModule.__setConnection = (host, port, route, namespace) => {
14
17
  ClientModule.__connectionData = () => ({ route, host, port });
18
+
15
19
  SocketDispatcher.apply(ClientModule, [namespace, events, systemContext]);
16
20
  };
17
21
  ClientModule.__setConnection(host, port, route, namespace);
@@ -24,9 +28,11 @@ module.exports = function SystemLynxClientModule(
24
28
 
25
29
  if (typeof cb === "function") cb();
26
30
  };
27
-
31
+ const protocol = getProtocol(serviceUrl);
28
32
  methods.forEach(({ method, fn }) => {
29
33
  ClientModule[fn] = ServiceRequestHandler.apply(ClientModule, [
34
+ httpClient,
35
+ protocol,
30
36
  method,
31
37
  fn,
32
38
  reconnectService,
@@ -1,5 +1,4 @@
1
1
  "use strict";
2
- const HttpClient = require("../../HttpClient/HttpClient")();
3
2
  const isObject = (value) =>
4
3
  typeof value === "object" ? (!value ? false : !Array.isArray(value)) : false;
5
4
 
@@ -9,53 +8,58 @@ const makeQuery = (data) =>
9
8
  "?"
10
9
  );
11
10
  module.exports = function ServiceRequestHandler(
11
+ httpClient,
12
+ protocol,
12
13
  method,
13
14
  fn,
14
15
  reconnectService,
15
16
  reconnectModule
16
17
  ) {
17
18
  const ClientModule = this;
18
-
19
19
  return function sendRequest() {
20
20
  const __arguments = Array.from(arguments);
21
21
 
22
22
  const tryRequest = (cb, errCount = 0) => {
23
23
  const { route, port, host } = ClientModule.__connectionData();
24
- const singleFileURL = `http://${host}:${port}/sf${route}/${fn}`;
25
- const multiFileURL = `http://${host}:${port}/mf${route}/${fn}`;
26
- const defaultURL = `http://${host}:${port}${route}/${fn}`;
24
+ const singleFileURL = `${protocol}${host}:${port}/sf${route}/${fn}`;
25
+ const multiFileURL = `${protocol}${host}:${port}/mf${route}/${fn}`;
26
+ const defaultURL = `${protocol}${host}:${port}${route}/${fn}`;
27
27
  const { file, files } = __arguments[0] || {};
28
28
  const url = file ? singleFileURL : files ? multiFileURL : defaultURL;
29
29
 
30
30
  if (url === defaultURL)
31
- HttpClient.request({
32
- url: `${url}${
33
- method === "get" && isObject(__arguments[0]) ? makeQuery(__arguments[0]) : ""
34
- }`,
35
- method,
36
- body: { __arguments },
37
- })
31
+ httpClient
32
+ .request({
33
+ url: `${url}${
34
+ method === "get" && isObject(__arguments[0])
35
+ ? makeQuery(__arguments[0])
36
+ : ""
37
+ }`,
38
+ method,
39
+ body: { __arguments },
40
+ })
38
41
  .then((results) => cb(null, results))
39
42
  .catch((err) => ErrorHandler(err, errCount, cb));
40
43
  else
41
- HttpClient.upload({
42
- url,
43
- method,
44
- formData: { ...__arguments[0], __arguments },
45
- })
44
+ httpClient
45
+ .upload({
46
+ url,
47
+ method,
48
+ formData: { ...__arguments[0], __arguments },
49
+ })
46
50
  .then((results) => cb(null, results))
47
51
  .catch((err) => ErrorHandler(err, errCount, cb));
48
52
  };
49
53
 
50
54
  const ErrorHandler = (err, errCount, cb) => {
51
- if (err.SystemLynxServiceError) {
55
+ if (err.SystemLynxService) {
52
56
  cb(err);
53
57
  } else if (errCount <= 3) {
54
58
  console.log(err);
55
59
  errCount++;
56
60
  if (reconnectModule) reconnectModule(() => tryRequest(cb, errCount));
57
61
  else reconnectService(() => tryRequest(cb, errCount));
58
- } else throw Error(`[SystemLynx][Service][Error]: Invalid route:${err}`);
62
+ } else console.error(Error(`[SystemLynx][Service][Error]: Invalid route:${err}`));
59
63
  };
60
64
 
61
65
  return new Promise((resolve, reject) =>
@@ -1,12 +1,12 @@
1
1
  "use strict";
2
2
  const io = require("socket.io-client");
3
- const SystemLynxDispatcher = require("../../Dispatcher/Dispatcher");
3
+ const createDispatcher = require("../../Dispatcher/Dispatcher");
4
4
 
5
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, systemContext]);
9
+ : createDispatcher.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", () => {
@@ -1,19 +1,23 @@
1
- const HttpClient = require("../../HttpClient/HttpClient")();
2
-
3
- module.exports = function loadConnectionData(url, { limit = 10, wait = 150 } = {}) {
1
+ module.exports = function loadConnectionData(
2
+ httpClient,
3
+ url,
4
+ { limit = 3, wait = 1000 } = {}
5
+ ) {
4
6
  const errors = [];
5
7
 
6
- return new Promise(function getData(resolve) {
7
- HttpClient.request({ method: "GET", url }, (err, results) => {
8
+ return new Promise(function getData(resolve, reject) {
9
+ httpClient.request({ method: "GET", url }, (err, results) => {
8
10
  if (err) {
9
11
  errors.push(err);
10
12
 
11
13
  if (errors.length < limit)
12
- setTimeout(() => getData(resolve), errors.length * wait);
13
- else
14
+ setTimeout(() => getData(resolve, reject), errors.length * wait);
15
+ else {
14
16
  console.error(
15
17
  `[SystemLynx][Client][Error]: Failed to load Service @${url} after ${errors.length} attempts.`
16
18
  );
19
+ reject(err);
20
+ }
17
21
  } else resolve(results);
18
22
  });
19
23
  });
@@ -1,14 +1,14 @@
1
1
  const { expect } = require("chai");
2
- const SystemLynxClient = require("../Client");
3
- const SystemLynxService = require("../../Service/Service");
4
- const Service = SystemLynxService();
2
+ const createClient = require("../Client");
3
+ const createService = require("../../Service/Service");
4
+ const Service = createService();
5
5
  const port = 6757;
6
6
  const route = "service-test";
7
7
  const url = `http://localhost:${port}/${route}`;
8
8
 
9
- describe("SystemLynxClient()", () => {
9
+ describe("createClient()", () => {
10
10
  it("should return a SystemLynx Client", () => {
11
- const Client = SystemLynxClient();
11
+ const Client = createClient();
12
12
  expect(Client)
13
13
  .to.be.an("object")
14
14
  .that.has.property("loadService")
@@ -36,13 +36,21 @@ describe("Client", () => {
36
36
  );
37
37
 
38
38
  await Service.startService({ route, port });
39
- const Client = SystemLynxClient();
39
+ const Client = createClient();
40
40
  const buAPI = await Client.loadService(url);
41
41
 
42
42
  expect(buAPI)
43
43
  .to.be.an("object")
44
- .that.has.all.keys("emit", "on", "resetConnection", "disconnect", "orders")
44
+ .that.has.all.keys(
45
+ "emit",
46
+ "on",
47
+ "$clearEvent",
48
+ "resetConnection",
49
+ "disconnect",
50
+ "orders"
51
+ )
45
52
  .that.respondsTo("emit")
53
+ .that.respondsTo("$clearEvent")
46
54
  .that.respondsTo("on")
47
55
  .that.respondsTo("resetConnection")
48
56
  .that.respondsTo("disconnect");
@@ -52,6 +60,7 @@ describe("Client", () => {
52
60
  .that.has.all.keys(
53
61
  "emit",
54
62
  "on",
63
+ "$clearEvent",
55
64
  "disconnect",
56
65
  "__setConnection",
57
66
  "__connectionData",
@@ -61,8 +70,10 @@ describe("Client", () => {
61
70
  "noArgTest"
62
71
  )
63
72
  .that.respondsTo("emit")
73
+ .that.respondsTo("$clearEvent")
64
74
  .that.respondsTo("on")
65
75
  .that.respondsTo("emit")
76
+ .that.respondsTo("$clearEvent")
66
77
  .that.respondsTo("__setConnection")
67
78
  .that.respondsTo("__connectionData")
68
79
  .that.respondsTo("action1")
@@ -74,7 +85,7 @@ describe("Client", () => {
74
85
 
75
86
  describe("Service", () => {
76
87
  it("should be able to call methods from the frontend client to the backend Module", async () => {
77
- const Client = SystemLynxClient();
88
+ const Client = createClient();
78
89
  const buAPI = await Client.loadService(url);
79
90
 
80
91
  const results = await buAPI.orders.action1({ code: 3 });
@@ -89,7 +100,7 @@ describe("Service", () => {
89
100
  });
90
101
  });
91
102
  it("should be able to send multiple arguments to the backend Module", async () => {
92
- const Client = SystemLynxClient();
103
+ const Client = createClient();
93
104
  const buAPI = await Client.loadService(url);
94
105
  const arg1 = 4,
95
106
  arg2 = 5,
@@ -107,7 +118,7 @@ describe("Service", () => {
107
118
  });
108
119
 
109
120
  it("should be able to send no arguments and use a promise", async () => {
110
- const Client = SystemLynxClient();
121
+ const Client = createClient();
111
122
  const buAPI = await Client.loadService(url);
112
123
  const results = await buAPI.orders.noArgTest();
113
124
 
@@ -122,13 +133,13 @@ describe("Service", () => {
122
133
  const route = "test-service";
123
134
  const port = "8980";
124
135
  const url = `http://localhost:${port}/${route}`;
125
- const Service = SystemLynxService();
136
+ const Service = createService();
126
137
  const eventTester = Service.module("eventTester", function () {
127
138
  this.sendEvent = () => this.emit(eventName, { testPassed: true });
128
139
  });
129
140
  await Service.startService({ route, port });
130
141
 
131
- const Client = SystemLynxClient();
142
+ const Client = createClient();
132
143
 
133
144
  const buAPI = await Client.loadService(url);
134
145
  setTimeout(() => eventTester.emit(eventName, { testPassed: true }), 500);
@@ -148,8 +159,8 @@ describe("Service", () => {
148
159
  });
149
160
 
150
161
  it("should be able to send REST http requests", async () => {
151
- const Client = SystemLynxClient();
152
- const Service = SystemLynxService();
162
+ const Client = createClient();
163
+ const Service = createService();
153
164
  const route = "rest-tester";
154
165
  const port = "8492";
155
166
  const url = `http://localhost:${port}/${route}`;
@@ -183,7 +194,7 @@ describe("Service", () => {
183
194
  });
184
195
 
185
196
  it("should be able to use 'useReturnValue' configuration option to enable synchronous return values from Module methods", async () => {
186
- const service = SystemLynxService();
197
+ const service = createService();
187
198
  const route = "sync/test";
188
199
  const port = 4920;
189
200
  const host = "localhost";
@@ -199,7 +210,7 @@ describe("Service", () => {
199
210
  port,
200
211
  host,
201
212
  });
202
- const Client = SystemLynxClient();
213
+ const Client = createClient();
203
214
  const { AsyncMath } = await Client.loadService(url);
204
215
  const results = await AsyncMath.max(10, 2);
205
216
  expect(results).to.equal(10);
@@ -1,6 +1,7 @@
1
1
  const { expect } = require("chai");
2
2
  const SocketDispatcher = require("../components/SocketDispatcher");
3
- const { WebSocket, SocketServer } = require("../../ServerManager/components/WebSocketServer")();
3
+ const { WebSocket, SocketServer } =
4
+ require("../../ServerManager/components/WebSocketServer")();
4
5
 
5
6
  const namespace = "test-namespace";
6
7
  const port = 4592;
@@ -14,9 +15,10 @@ describe("SocketDispatcher", () => {
14
15
  it("should return an EventDispatcher object with methods on and emit", async () => {
15
16
  expect(dispatcher)
16
17
  .to.be.an("object")
17
- .that.has.all.keys("on", "emit", "disconnect")
18
+ .that.has.all.keys("on", "emit", "$clearEvent", "disconnect")
18
19
  .that.respondsTo("on")
19
20
  .that.respondsTo("emit")
21
+ .that.respondsTo("$clearEvent")
20
22
  .that.respondsTo("disconnect");
21
23
  });
22
24
  it("Should be able to emit and handle events", (done) => {
@@ -25,19 +27,25 @@ describe("SocketDispatcher", () => {
25
27
  done();
26
28
  });
27
29
  dispatcher.on("connect", () => console.log(`I'm all the way connected!`));
28
- setTimeout(() => socket.emit("dispatch", { name: eventName, data: { testPassed: true } }), 500);
30
+ setTimeout(
31
+ () => socket.emit("dispatch", { name: eventName, data: { testPassed: true } }),
32
+ 500
33
+ );
29
34
  });
30
35
  });
31
36
 
32
37
  describe("SocketDispatcher.apply()", () => {
33
38
  const eventName = "testing-event";
34
- const dispatcher = SocketDispatcher.apply({}, [`http://localhost:${port}/${namespace}`]);
39
+ const dispatcher = SocketDispatcher.apply({}, [
40
+ `http://localhost:${port}/${namespace}`,
41
+ ]);
35
42
  it("should return an EventDispatcher object with methods on and emit", async () => {
36
43
  expect(dispatcher)
37
44
  .to.be.an("object")
38
- .that.has.all.keys("on", "emit", "disconnect")
45
+ .that.has.all.keys("on", "emit", "$clearEvent", "disconnect")
39
46
  .that.respondsTo("on")
40
47
  .that.respondsTo("emit")
48
+ .that.respondsTo("$clearEvent")
41
49
  .that.respondsTo("disconnect");
42
50
  });
43
51
  it("Should be able to emit and handle events", (done) => {
@@ -49,6 +57,9 @@ describe("SocketDispatcher.apply()", () => {
49
57
  done();
50
58
  });
51
59
 
52
- setTimeout(() => socket.emit("dispatch", { name: eventName, data: { testPassed: true } }), 500);
60
+ setTimeout(
61
+ () => socket.emit("dispatch", { name: eventName, data: { testPassed: true } }),
62
+ 500
63
+ );
53
64
  });
54
65
  });
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- module.exports = function SystemLynxDispatcher(events = {}, systemContext) {
2
+ module.exports = function createDispatcher(events = {}, systemContext) {
3
3
  const Dispatcher = this || {};
4
4
 
5
5
  Dispatcher.emit = (eventName, data, event) => {
@@ -24,5 +24,20 @@ module.exports = function SystemLynxDispatcher(events = {}, systemContext) {
24
24
  return Dispatcher;
25
25
  };
26
26
 
27
+ Dispatcher.$clearEvent = (eventName, fn) => {
28
+ if (!events[eventName]) return Dispatcher;
29
+
30
+ if (!fn) {
31
+ // Clear all listeners for the given event
32
+ delete events[eventName];
33
+ } else {
34
+ // Remove the listener function with the specified name from the event's listener array
35
+ events[eventName] = events[eventName].filter((callback) => {
36
+ return callback.name !== fn;
37
+ });
38
+ }
39
+
40
+ return Dispatcher;
41
+ };
27
42
  return Dispatcher;
28
43
  };
@@ -1,14 +1,15 @@
1
1
  const { expect } = require("chai");
2
2
  const Dispatcher = require("./Dispatcher");
3
3
 
4
- describe("SystemLynxDispatcher", () => {
4
+ describe("createDispatcher", () => {
5
5
  const dispatcher = Dispatcher();
6
6
  it("should return an EventDispatcher object with methods on and emit", async () => {
7
7
  expect(dispatcher)
8
8
  .to.be.an("object")
9
- .that.has.all.keys("on", "emit")
9
+ .that.has.all.keys("on", "emit", "$clearEvent")
10
10
  .that.respondsTo("on")
11
- .that.respondsTo("emit");
11
+ .that.respondsTo("emit")
12
+ .that.respondsTo("$clearEvent");
12
13
  });
13
14
  it("Should be able to emit and handle events", (done) => {
14
15
  dispatcher.on("test", (data) => {
@@ -2,7 +2,7 @@
2
2
  const httpClient = require("request");
3
3
  const json = true;
4
4
 
5
- module.exports = function SystemLynxClient() {
5
+ module.exports = function createClient() {
6
6
  const Client = this || {};
7
7
  Client.request = ({ method, url, body }, cb) => {
8
8
  const tryRequest = (callback) => {
@@ -1,6 +1,6 @@
1
1
  const { expect } = require("chai");
2
2
  const LoadBalancer = require("../LoadBalancer")();
3
- const SystemLynxService = require("../../Service/Service");
3
+ const createService = require("../../Service/Service");
4
4
  const HttpClient = require("../../HttpClient/HttpClient")();
5
5
  const lbPort = 5030;
6
6
  const route = "loadbalancer";
@@ -9,14 +9,33 @@ describe("LoadBalancer()", () => {
9
9
  it("should return a SystemLynx LoadBalancer", () => {
10
10
  expect(LoadBalancer)
11
11
  .to.be.an("object")
12
- .that.has.all.keys("startService", "server", "WebSocket", "module", "clones")
12
+ .that.has.all.keys(
13
+ "startService",
14
+ "server",
15
+ "WebSocket",
16
+ "module",
17
+ "clones",
18
+ "before"
19
+ )
13
20
  .that.respondsTo("startService")
14
- .that.respondsTo("module");
21
+ .that.respondsTo("module")
22
+ .that.respondsTo("before");
15
23
  expect(LoadBalancer.clones)
16
24
  .to.be.an("object")
17
- .that.has.all.keys("on", "emit", "clones", "register", "dispatch", "assignDispatch")
25
+ .that.has.all.keys(
26
+ "on",
27
+ "emit",
28
+ "$clearEvent",
29
+ "before",
30
+ "clones",
31
+ "register",
32
+ "dispatch",
33
+ "assignDispatch"
34
+ )
18
35
  .that.respondsTo("emit")
36
+ .that.respondsTo("$clearEvent")
19
37
  .that.respondsTo("on")
38
+ .that.respondsTo("before")
20
39
  .that.respondsTo("register")
21
40
  .that.respondsTo("dispatch")
22
41
  .that.respondsTo("assignDispatch")
@@ -71,6 +90,8 @@ describe("LoadBalancer.clones (Module)", () => {
71
90
  "on",
72
91
  "emit",
73
92
  "$emit",
93
+ "$clearEvent",
94
+ "before",
74
95
  "register",
75
96
  "dispatch",
76
97
  "assignDispatch",
@@ -78,6 +99,8 @@ describe("LoadBalancer.clones (Module)", () => {
78
99
  )
79
100
  .that.respondsTo("on")
80
101
  .that.respondsTo("emit")
102
+ .that.respondsTo("$clearEvent")
103
+ .that.respondsTo("before")
81
104
  .that.respondsTo("$emit")
82
105
  .that.respondsTo("register")
83
106
  .that.respondsTo("dispatch")
@@ -87,7 +110,7 @@ describe("LoadBalancer.clones (Module)", () => {
87
110
  });
88
111
 
89
112
  it("should be able to use clones.register(connData, callback) method to host connection", async () => {
90
- const Service = SystemLynxService();
113
+ const Service = createService();
91
114
  const { route, port, host } = test_service1;
92
115
  await Service.startService({ route, port, host });
93
116
  LoadBalancer.clones.register({ route, port, host }, () => {});
@@ -113,8 +136,8 @@ describe("LoadBalancer.clones (Module)", () => {
113
136
 
114
137
  it("should be able to manager the routing to multiple clones of the same Service", async () => {
115
138
  const { route, port1, port2, host } = test_service2;
116
- const Clone1 = SystemLynxService();
117
- const Clone2 = SystemLynxService();
139
+ const Clone1 = createService();
140
+ const Clone2 = createService();
118
141
  await Clone1.startService({ route, port: port1, host });
119
142
  await Clone2.startService({ route, port: port2, host });
120
143
  LoadBalancer.clones.register({ route, port: port1, host }, () => {});