@caboodle-tech/node-simple-server 4.1.0 → 4.2.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/README.md CHANGED
@@ -87,7 +87,7 @@ function watcherCallback(event, path, extension) {
87
87
  /**
88
88
  * NOTE: This is a heavy request to use if your site loads resources from
89
89
  * other sites such as images, databases, or API calls. Consider a better
90
- * approach in this cases such as throttling.
90
+ * approach in these cases such as throttling.
91
91
  */
92
92
  Server.reloadAllPages();
93
93
  return;
@@ -97,7 +97,13 @@ function watcherCallback(event, path, extension) {
97
97
  }
98
98
  }
99
99
 
100
- // A bare minimum callback to handle all websocket messages from the frontend.
100
+ /**
101
+ * A bare minimum callback to handle all websocket messages from the frontend. By
102
+ * default NSS registers and responds to WebSockets by the web pages pathname. In
103
+ * a web page:
104
+ *
105
+ * NSS_WS.send([string|int|bool|object]) // Pathname lookup will be used.
106
+ */
101
107
  function websocketCallback(messageObject, pageId) {
102
108
  // Interpret and do what you need to with the message:
103
109
  const datatype = messageObject.type
@@ -107,9 +113,26 @@ function websocketCallback(messageObject, pageId) {
107
113
  // Respond to the page that sent the message if you like:
108
114
  Server.message(pageId, 'Messaged received!');
109
115
  }
110
-
111
116
  Server.addWebsocketCallback('.*', websocketCallback);
112
117
 
118
+ /**
119
+ * A bare minimum callback to handle all websocket messages from the frontend.
120
+ * This is a special example that registers a specific route to listen for. In a
121
+ * web page:
122
+ *
123
+ * NSS_WS.send([string|int|bool|object], [route string]) // Route lookup will be used.
124
+ */
125
+ function websocketCallback(messageObject, pageId) {
126
+ // Interpret and do what you need to with the message:
127
+ const datatype = messageObject.type
128
+ const data = messageObject.data;
129
+ console.log(`Route received ${datatype} data from page ${pageId}: ${data}`)
130
+
131
+ // Respond to the page that sent the message if you like:
132
+ Server.message(pageId, 'Route specific messaged received!');
133
+ }
134
+ Server.addWebsocketCallback('api/search', websocketCallback);
135
+
113
136
  // A bare minimum watcher options object; use for development, omit for production.
114
137
  const watcherOptions = {
115
138
  events: {
package/bin/nss.js CHANGED
@@ -8,6 +8,7 @@ import { fileURLToPath } from 'url';
8
8
 
9
9
  import ContentTypes from '../handlers/js/content-types.js';
10
10
  import HTTPStatus from '../handlers/js/http-status.js';
11
+ import Print from './print.js';
11
12
 
12
13
  // eslint-disable-next-line no-underscore-dangle
13
14
  const __filename = fileURLToPath(import.meta.url);
@@ -43,7 +44,7 @@ class NodeSimpleServer {
43
44
  map: {}
44
45
  };
45
46
 
46
- #VERSION = '4.1.0';
47
+ #VERSION = '4.2.0';
47
48
 
48
49
  #watching = [];
49
50
 
@@ -730,7 +731,6 @@ class NodeSimpleServer {
730
731
  * @param {object} request The incoming initial connection.
731
732
  */
732
733
  #socketListener(socket, request) {
733
-
734
734
  // Strip the page ID and /ws tag off the url to get the actual url.
735
735
  let cleanURL = request.url.substr(1, request.url.indexOf('/ws?id=') - 1);
736
736
  if (!cleanURL) {
@@ -749,7 +749,20 @@ class NodeSimpleServer {
749
749
  }
750
750
 
751
751
  // Record the unique page ID directly on the socket object.
752
- const pageId = request.url.substr(request.url.indexOf('?id=')).replace('?id=', '');
752
+ let idStartIndex;
753
+ if (request.url.indexOf('?id=') !== -1) {
754
+ idStartIndex = request.url.indexOf('?id=');
755
+ } else {
756
+ idStartIndex = -1;
757
+ }
758
+
759
+ let pageId;
760
+ if (idStartIndex !== -1) {
761
+ pageId = request.url.substr(idStartIndex).replace('?id=', '');
762
+ } else {
763
+ pageId = 'unknown';
764
+ }
765
+
753
766
  // eslint-disable-next-line no-param-reassign
754
767
  socket.nssUid = pageId;
755
768
 
@@ -779,7 +792,17 @@ class NodeSimpleServer {
779
792
  // Handle future incoming WebSocket messages from this page.
780
793
  socket.on('message', (message) => {
781
794
  // NSS messages have a standard format.
782
- const msgObj = JSON.parse(message.toString());
795
+ let msgObj;
796
+ try {
797
+ msgObj = JSON.parse(message.toString());
798
+ if (!('message' in msgObj) || !('type' in msgObj)) {
799
+ throw new Error('Bad format!');
800
+ }
801
+ } catch (e) {
802
+ Print.warn('Invalid socket message received! Socket message must be in Node Simple Server\'s format.');
803
+ return;
804
+ }
805
+
783
806
  // If message is a ping send pong and stop.
784
807
  if (msgObj.type === 'string') {
785
808
  if (msgObj.message === 'ping') {
@@ -787,17 +810,32 @@ class NodeSimpleServer {
787
810
  return;
788
811
  }
789
812
  }
813
+
814
+ // Pull out specific route if there is one.
815
+ let route = null;
816
+ if ('route' in msgObj) {
817
+ route = msgObj.route;
818
+ }
819
+
790
820
  // See if the message belongs to a callback and send it there.
791
821
  for (let i = 0; i < this.#OPS.callbacks.length; i++) {
792
822
  const regex = this.#OPS.callbacks[i][0];
793
823
  const callback = this.#OPS.callbacks[i][1];
794
- if (regex.test(cleanURL)) {
824
+ // If the message has a route check that only.
825
+ if (route) {
826
+ if (regex.test(route)) {
827
+ callback(msgObj, pageId);
828
+ return;
829
+ }
830
+ } else if (regex.test(cleanURL)) {
831
+ // Default to the URL (pathname).
795
832
  callback(msgObj, pageId);
796
833
  return;
797
834
  }
798
835
  }
836
+
799
837
  // No one is listening for this message.
800
- console.log(`Unanswered WebSocket message from ${cleanURL}: ${message.toString()}`);
838
+ Print.warn(`Unanswered WebSocket message from ${cleanURL}: ${message.toString()}`);
801
839
  });
802
840
 
803
841
  // When a connection closes remove it from CONNECTIONS.
@@ -813,6 +851,7 @@ class NodeSimpleServer {
813
851
  }
814
852
  });
815
853
 
854
+ console.log(this.#OPS.callbacks);
816
855
  }
817
856
 
818
857
  /**
@@ -842,7 +881,7 @@ class NodeSimpleServer {
842
881
 
843
882
  // Don't start an already running server.
844
883
  if (this.#OPS.running) {
845
- console.log('Server is already running.');
884
+ Print.warn('Server is already running.');
846
885
  // Notify the callback.
847
886
  if (callback) {
848
887
  callback(true);
@@ -878,7 +917,8 @@ class NodeSimpleServer {
878
917
  if (port) {
879
918
  // Stop trying new ports after 100 attempts.
880
919
  if (this.#OPS.port - port > 100) {
881
- console.log(`FATAL ERROR: Could not find an available port number in the range of ${this.#OPS.port}–${this.#OPS.port + 100}.`);
920
+ // eslint-disable-next-line max-len
921
+ Print.error(`FATAL ERROR: Could not find an available port number in the range of ${this.#OPS.port}–${this.#OPS.port + 100}.`);
882
922
  // Notify the callback.
883
923
  if (callback) {
884
924
  callback(false);
@@ -891,7 +931,7 @@ class NodeSimpleServer {
891
931
  }
892
932
  return;
893
933
  }
894
- console.log('Server error', error);
934
+ Print.error(`Server Error:\n${error}`);
895
935
  });
896
936
 
897
937
  // Attempt to start the server now.
@@ -907,19 +947,19 @@ class NodeSimpleServer {
907
947
 
908
948
  // Warn the user if we had to change port numbers.
909
949
  if (port && (port !== this.#OPS.port)) {
910
- console.log(`Port ${this.#OPS.port} was in use, switched to using ${port}.\n`);
950
+ Print.warn(`Port ${this.#OPS.port} was in use, switched to using ${port}.\n`);
911
951
  }
912
952
 
913
953
  // Record port in use.
914
954
  this.#OPS.portInUse = port;
915
955
 
916
956
  // Log the ip addresses being watched.
917
- console.log('Node Simple Server live @:');
957
+ Print.notice('Node Simple Server live @:');
918
958
  const addresses = this.getAddresses(port);
919
959
  addresses.forEach((address) => {
920
- console.log(` ${address}`);
960
+ Print.notice(` ${address}`);
921
961
  });
922
- console.log('');
962
+ Print.log('');
923
963
 
924
964
  // Notify the callback.
925
965
  if (callback) {
@@ -953,7 +993,7 @@ class NodeSimpleServer {
953
993
  this.#server = null;
954
994
  this.#socket = null;
955
995
  this.#OPS.running = false;
956
- console.log('Server has been stopped.');
996
+ Print.notice('Server has been stopped.');
957
997
  }
958
998
  // Notify the callback.
959
999
  if (callback) {
@@ -1031,7 +1071,7 @@ class NodeSimpleServer {
1031
1071
  * all backslashes (\) into forward slashes (/).
1032
1072
  */
1033
1073
  if (alterCatachAlls.includes(key)) {
1034
- watcher.on(key, (evt, path, statsOrDetails) => {
1074
+ watcher.on(key, (evt, path, statsOrDetails = {}) => {
1035
1075
  // Capture the call and alter the path before passing it on.
1036
1076
  const altPath = path.replace(/\\/g, '/');
1037
1077
  // Since we're messing with the path already grab the extension for the user.
@@ -1040,7 +1080,7 @@ class NodeSimpleServer {
1040
1080
  options.events[key](evt, altPath, statsOrDetails);
1041
1081
  });
1042
1082
  } else if (alterAddUpdates.includes(key)) {
1043
- watcher.on(key, (path, statsOrDetails) => {
1083
+ watcher.on(key, (path, statsOrDetails = {}) => {
1044
1084
  // Capture the call and alter the path before passing it on.
1045
1085
  const altPath = path.replace(/\\/g, '/');
1046
1086
  // Since we're messing with the path already grab the extension for the user.
@@ -1061,7 +1101,7 @@ class NodeSimpleServer {
1061
1101
  }
1062
1102
  });
1063
1103
  } catch (error) {
1064
- console.log(error);
1104
+ Print.error(error);
1065
1105
  return false;
1066
1106
  }
1067
1107
  return true;
package/bin/print.js ADDED
@@ -0,0 +1,64 @@
1
+ /* eslint-disable no-console */
2
+
3
+ class Print {
4
+
5
+ #enabled = true;
6
+
7
+ disable() {
8
+ this.#enabled = false;
9
+ }
10
+
11
+ enable() {
12
+ this.#enabled = true;
13
+ }
14
+
15
+ error(message, override = false) {
16
+ if (!this.#enabled && !override) {
17
+ return;
18
+ }
19
+ // Red color
20
+ console.error(this.#formatMessage(message, '\x1b[31m'));
21
+ }
22
+
23
+ #formatMessage(message, colorCode) {
24
+ const resetCode = '\x1b[0m';
25
+ return `${colorCode}${message}${resetCode}`;
26
+ }
27
+
28
+ log(message, override = false) {
29
+ if (!this.#enabled && !override) {
30
+ return;
31
+ }
32
+ // White color
33
+ console.log(this.#formatMessage(message, '\x1b[37m'));
34
+ }
35
+
36
+ notice(message, override = false) {
37
+ if (!this.#enabled && !override) {
38
+ return;
39
+ }
40
+ // Blue color
41
+ console.log(this.#formatMessage(message, '\x1b[94m'));
42
+ }
43
+
44
+ success(message, override = false) {
45
+ if (!this.#enabled && !override) {
46
+ return;
47
+ }
48
+ // Green color
49
+ console.log(this.#formatMessage(message, '\x1b[32m'));
50
+ }
51
+
52
+ warn(message, override = false) {
53
+ if (!this.#enabled && !override) {
54
+ return;
55
+ }
56
+ // Yellow color
57
+ console.warn(this.#formatMessage(message, '\x1b[33m'));
58
+ }
59
+
60
+ }
61
+
62
+ const printer = new Print();
63
+
64
+ export default printer;
package/changelogs/v4.md CHANGED
@@ -1,3 +1,12 @@
1
+ ### NSS 4.2.0 (23 January 2024)
2
+
3
+ - feat: WebSocket connections can now specify a specific backend route instead of just sending messages to the the listener (if any) for the pages path.
4
+
5
+ ### NSS 4.1.1 (22 January 2024)
6
+
7
+ - fix: Correct a bug in the watcher where we attach a files extension to the stats object. This object is missing when moving directories causing a crash since there is no object to attach the extension, albeit non-existent, to.
8
+ - improve: Quality of life improvement by adding the Caboodle Tech Print class to replace console output; Now in color!
9
+
1
10
  ### NSS 4.0.0 (7 January 2024)
2
11
 
3
12
  - !feat: Correct bug caused by NSS non-standard implementation of Chokidar; see below.
@@ -91,10 +91,11 @@
91
91
  };
92
92
 
93
93
  /** Send a WebSocket message to the WebSocket server. */
94
- const send = (message) => {
94
+ const send = (message, route = null) => {
95
95
  if (ready && socket.readyState === WebSocket.OPEN) {
96
96
  socket.send(JSON.stringify({
97
97
  message,
98
+ route,
98
99
  type: whatIs(message)
99
100
  }));
100
101
  return;
@@ -147,7 +148,7 @@
147
148
 
148
149
  // Socket specific variables.
149
150
  const protocol = window.location.protocol === "http:" ? "ws://" : "wss://";
150
- const address = protocol + window.location.host + window.location.pathname + "/ws?id=" + pageId;
151
+ const address = protocol + window.location.host + pathname + "/ws?id=" + pageId;
151
152
  const socket = new WebSocket(address);
152
153
 
153
154
  // Respond to messages the socket receives.
@@ -42,15 +42,16 @@
42
42
  };
43
43
 
44
44
  /** Send a WebSocket message to the WebSocket server. */
45
- const send = (message) => {
45
+ const send = (message, route = null) => {
46
46
  if (ready && socket.readyState === WebSocket.OPEN) {
47
47
  socket.send(JSON.stringify({
48
48
  message,
49
+ route,
49
50
  type: whatIs(message)
50
51
  }));
51
52
  return;
52
53
  }
53
- console.warn("Node Simple Server: The WebSocket is not ready or the connection was closed.");
54
+ console.warn('Node Simple Server: The WebSocket is not ready or the connection was closed.');
54
55
  };
55
56
 
56
57
  /** Generate a random unique ID for this page; will be registered in the back-end. */
@@ -90,9 +91,15 @@
90
91
  let restartAttempts = 0;
91
92
  let restartInterval = null;
92
93
 
94
+ // Prep window path.
95
+ let pathname = window.location.pathname;
96
+ if (pathname === '/') {
97
+ pathname = '';
98
+ }
99
+
93
100
  // Socket specific variables.
94
101
  const protocol = window.location.protocol === "http:" ? "ws://" : "wss://";
95
- const address = protocol + window.location.host + window.location.pathname + "/ws?id=" + pageId;
102
+ const address = protocol + window.location.host + pathname + "/ws?id=" + pageId;
96
103
  const socket = new WebSocket(address);
97
104
 
98
105
  // Respond to messages the socket receives.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@caboodle-tech/node-simple-server",
3
- "version": "4.1.0",
3
+ "version": "4.2.0",
4
4
  "description": "Node Simple Server (NSS): A small but effective node based server for development sites, customizable live reloading, and websocket support built-in.",
5
5
  "main": "bin/nss.js",
6
6
  "scripts": {