socket-function 0.9.3 → 0.9.4

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 (45) hide show
  1. package/.eslintrc.js +50 -50
  2. package/SocketFunction.ts +280 -280
  3. package/SocketFunctionTypes.ts +90 -90
  4. package/hot/HotReloadController.ts +105 -105
  5. package/mobx/UrlParam.ts +39 -39
  6. package/mobx/observer.tsx +49 -49
  7. package/mobx/promiseToObservable.tsx +41 -41
  8. package/package.json +1 -1
  9. package/require/CSSShim.ts +19 -19
  10. package/require/RequireController.ts +252 -252
  11. package/require/buffer.js +2368 -2368
  12. package/require/compileFlags.ts +44 -44
  13. package/require/require.html +13 -13
  14. package/require/require.js +462 -462
  15. package/spec.txt +115 -115
  16. package/src/CallFactory.ts +389 -389
  17. package/src/JSONLACKS/JSONLACKS.generated.js +17 -17
  18. package/src/JSONLACKS/JSONLACKS.pegjs +247 -247
  19. package/src/JSONLACKS/JSONLACKS.ts +429 -429
  20. package/src/args.ts +21 -21
  21. package/src/batching.ts +170 -170
  22. package/src/caching.ts +324 -318
  23. package/src/callHTTPHandler.ts +203 -203
  24. package/src/callManager.ts +134 -134
  25. package/src/certStore.ts +29 -29
  26. package/src/fixLargeNetworkCalls.ts +8 -8
  27. package/src/formatting/colors.ts +78 -78
  28. package/src/formatting/format.ts +160 -160
  29. package/src/formatting/logColors.ts +17 -17
  30. package/src/misc.ts +303 -302
  31. package/src/nodeCache.ts +92 -92
  32. package/src/nodeProxy.ts +54 -54
  33. package/src/profiling/getOwnTime.ts +142 -142
  34. package/src/profiling/measure.ts +273 -273
  35. package/src/profiling/stats.ts +212 -212
  36. package/src/profiling/tcpLagProxy.ts +63 -63
  37. package/src/storagePath.ts +10 -10
  38. package/src/tlsParsing.ts +96 -96
  39. package/src/types.ts +8 -8
  40. package/src/webSocketServer.ts +250 -250
  41. package/test/client.css +2 -2
  42. package/test/client.ts +46 -46
  43. package/test/server.ts +43 -43
  44. package/test/shared.ts +52 -52
  45. package/tsconfig.json +26 -26
@@ -1,251 +1,251 @@
1
- import https from "https";
2
- import http from "http";
3
- import net from "net";
4
- import tls from "tls";
5
- import * as ws from "ws";
6
- import { getNodeIdsFromRequest, httpCallHandler } from "./callHTTPHandler";
7
- import { SocketFunction } from "../SocketFunction";
8
- import { getTrustedCertificates, watchTrustedCertificates } from "./certStore";
9
- import { createCallFactory } from "./CallFactory";
10
- import { parseSNIExtension, parseTLSHello, SNIType } from "./tlsParsing";
11
- import debugbreak from "debugbreak";
12
- import { getNodeId } from "./nodeCache";
13
- import crypto from "crypto";
14
- import { Watchable } from "./misc";
15
- import { delay, runInfinitePoll } from "./batching";
16
- import { magenta } from "./formatting/logColors";
17
- import { yellow } from "./formatting/logColors";
18
- import { green } from "./formatting/logColors";
19
-
20
- export type SocketServerConfig = (
21
- https.ServerOptions & {
22
- key: string | Buffer;
23
- cert: string | Buffer;
24
-
25
- port: number;
26
- /** You can also set `port: 0` if you don't care what port you want at all. */
27
- useAvailablePortIfPortInUse?: boolean;
28
-
29
- // public sets ip to "0.0.0.0", otherwise it defaults to "127.0.0.1", which
30
- // causes the server to only accept local connections.
31
- public?: boolean;
32
- ip?: string;
33
-
34
- // NOTE: Any same origin accesses are allowed (header.origin === header.host)
35
- // For example, to allow "letx.ca" to access the server (when the hosted domain
36
- // may be, "querysub.com", for example), use ["letx.ca"]
37
- allowHostnames?: string[];
38
-
39
- /** If the SNI matches this domain, we use a different key/cert. */
40
- SNICerts?: {
41
- [domain: string]: Watchable<https.ServerOptions>;
42
- };
43
- }
44
- );
45
-
46
- export async function startSocketServer(
47
- config: SocketServerConfig
48
- ): Promise<string> {
49
-
50
- const webSocketServer = new ws.Server({
51
- noServer: true,
52
- });
53
-
54
- async function setupHTTPSServer(watchOptions: Watchable<https.ServerOptions>) {
55
- let httpsServerLast: https.Server | undefined;
56
- let onHttpServer: (server: https.Server) => void;
57
- let httpServerPromise = new Promise<https.Server>(r => onHttpServer = r);
58
- let lastOptions!: https.ServerOptions;
59
- await watchOptions(value => {
60
- lastOptions = { ...value, ca: getTrustedCertificates() };
61
- if (!httpsServerLast) {
62
- httpsServerLast = https.createServer(lastOptions);
63
- } else {
64
- httpsServerLast.setSecureContext(lastOptions);
65
- }
66
- onHttpServer(httpsServerLast);
67
- });
68
- let httpsServer = await httpServerPromise;
69
-
70
- let allowedHostnames = new Set<string>();
71
- for (let hostname of config.allowHostnames || []) {
72
- allowedHostnames.add(hostname);
73
- }
74
-
75
- watchTrustedCertificates(() => {
76
- lastOptions.ca = getTrustedCertificates();
77
- httpsServer.setSecureContext(lastOptions);
78
- });
79
-
80
- httpsServer.on("connection", socket => {
81
- if (!SocketFunction.silent) {
82
- console.log("Client connection established");
83
- }
84
- socket.on("error", e => {
85
- if (!SocketFunction.silent) {
86
- console.log(`Client socket error ${e.message}`);
87
- }
88
- });
89
- socket.on("close", () => {
90
- if (!SocketFunction.silent) {
91
- console.log("Client socket closed");
92
- }
93
- });
94
- });
95
- httpsServer.on("error", e => {
96
- console.error(`Connection attempt error ${e.message}`);
97
- });
98
- httpsServer.on("tlsClientError", e => {
99
- console.error(`TLS client error ${e.message}`);
100
- });
101
-
102
- httpsServer.on("request", httpCallHandler);
103
-
104
- httpsServer.on("upgrade", (request, socket, upgradeHead) => {
105
- socket.on("error", e => {
106
- if (!SocketFunction.silent) {
107
- console.log(`Client socket error ${e.message}`);
108
- }
109
- });
110
-
111
- let originHeader = request.headers["origin"];
112
- if (originHeader) {
113
- try {
114
- let host = new URL("ws://" + request.headers["host"]).hostname;
115
- let origin = new URL(originHeader).hostname;
116
- if (host !== origin && !allowedHostnames.has(origin)) {
117
- throw new Error(`Invalid cross domain request, ${JSON.stringify(host)} !== ${JSON.stringify(origin)} (also not config.allowedHostnames ${JSON.stringify(config.allowHostnames)})`);
118
- }
119
- } catch (e) {
120
- console.error(e);
121
- return;
122
- }
123
- }
124
- webSocketServer.handleUpgrade(request, socket, upgradeHead, (ws) => {
125
- const { nodeId, localNodeId } = getNodeIdsFromRequest(request);
126
- createCallFactory(ws, nodeId, localNodeId).catch(e => {
127
- console.error(`Error in creating call factory, ${e.stack}`);
128
- });
129
- });
130
- });
131
- return httpsServer;
132
- }
133
-
134
- // TODO: Only allow unauthorized for ip certificates, and then for domains use the domain as the nodeId,
135
- // so it is easy to read, and consistent.
136
- let options: https.ServerOptions = {
137
- ...config,
138
- };
139
- if (!config.cert) {
140
- throw new Error("No cert specified");
141
- }
142
- if (!config.key) {
143
- throw new Error("No key specified");
144
- }
145
-
146
- const mainHTTPSServer = await setupHTTPSServer(callback => callback(options));
147
- let sniServers = new Map<string, https.Server>();
148
- for (let [domain, obj] of Object.entries(config.SNICerts || {})) {
149
- sniServers.set(domain, await setupHTTPSServer(obj));
150
- }
151
-
152
- let httpServer = http.createServer({}, async function (req, res) {
153
- let url = new URL("http://" + req.headers.host + req.url);
154
- url.protocol = "https:";
155
- //url.hostname = opts.hostname;
156
- url.hostname = req.headers.host || "";
157
- res.writeHead(301, { Location: url + "" });
158
- res.end();
159
- });
160
- httpServer.on("error", e => {
161
- console.error(`HTTP error ${e.stack}`);
162
- });
163
-
164
- let realServer = net.createServer(socket => {
165
- // NOTE: ONCE is used, so we only look at the first buffer, and then after that
166
- // we pipe. This should be very efficient, as pipe has insane throughput
167
- // (100s of MB/s, easily, even on a terrible machine).
168
- socket.once("data", buffer => {
169
- // All HTTPS requests start with 22, and no HTTP requests start with 22,
170
- // so we just need to read the first byte.
171
-
172
- let server: https.Server | http.Server;
173
- if (buffer[0] !== 22) {
174
- server = httpServer;
175
- } else {
176
- let data = parseTLSHello(buffer);
177
- let sni = data.extensions.filter(x => x.type === SNIType).flatMap(x => parseSNIExtension(x.data))[0];
178
- if (!SocketFunction.silent) {
179
- console.log(`Received TCP connection with SNI ${JSON.stringify(sni)}`);
180
- }
181
- server = sniServers.get(sni) || mainHTTPSServer;
182
- }
183
-
184
- // NOTE: Messages aren't dequeued until the current handler finishes, so we don't need to pause the socket or anything.
185
- server.emit("connection", socket);
186
- socket.unshift(buffer);
187
- });
188
- socket.on("error", (e) => {
189
- console.error(`Exposed socket error, ${e.stack}`);
190
- });
191
- });
192
-
193
-
194
- let listenPromise = new Promise<void>((resolve, error) => {
195
- realServer.on("listening", () => {
196
- resolve();
197
- });
198
- realServer.on("error", e => {
199
- error(e);
200
- });
201
- });
202
-
203
- let host = config.public ? "0.0.0.0" : "127.0.0.1";
204
- if (config.ip) {
205
- host = config.ip;
206
- }
207
-
208
- let port = config.port;
209
- if (config.useAvailablePortIfPortInUse && port) {
210
- async function isPortInUse(port: number): Promise<boolean> {
211
- return new Promise<boolean>((resolve, reject) => {
212
- let server = net.createServer();
213
- server.listen(port, host)
214
- .on("listening", function () {
215
- server.close();
216
- resolve(false);
217
- }).on("close", function () {
218
- resolve(true);
219
- }).on("error", function (e) {
220
- resolve(true);
221
- });
222
- });
223
- }
224
- if (await isPortInUse(port)) {
225
- port = 0;
226
- }
227
- }
228
-
229
- if (!SocketFunction.silent) {
230
- console.log(yellow(`Trying to listening on ${host}:${port}`));
231
- }
232
- realServer.listen(port, host);
233
-
234
- await listenPromise;
235
-
236
- port = (realServer.address() as net.AddressInfo).port;
237
- let nodeId = getNodeId(getCommonName(config.cert), port);
238
- if (!SocketFunction.silent) {
239
- console.log(green(`Started Listening on ${nodeId}`));
240
- }
241
-
242
- return nodeId;
243
- }
244
-
245
- function getCommonName(cert: Buffer | string) {
246
- let subject = new crypto.X509Certificate(cert).subject;
247
- let subjectKVPs = new Map(subject.split(",").map(x => x.trim().split("=")).map(x => [x[0], x.slice(1).join("=")]));
248
- let commonName = subjectKVPs.get("CN");
249
- if (!commonName) throw new Error(`No common name in subject: ${subject}`);
250
- return commonName;
1
+ import https from "https";
2
+ import http from "http";
3
+ import net from "net";
4
+ import tls from "tls";
5
+ import * as ws from "ws";
6
+ import { getNodeIdsFromRequest, httpCallHandler } from "./callHTTPHandler";
7
+ import { SocketFunction } from "../SocketFunction";
8
+ import { getTrustedCertificates, watchTrustedCertificates } from "./certStore";
9
+ import { createCallFactory } from "./CallFactory";
10
+ import { parseSNIExtension, parseTLSHello, SNIType } from "./tlsParsing";
11
+ import debugbreak from "debugbreak";
12
+ import { getNodeId } from "./nodeCache";
13
+ import crypto from "crypto";
14
+ import { Watchable } from "./misc";
15
+ import { delay, runInfinitePoll } from "./batching";
16
+ import { magenta } from "./formatting/logColors";
17
+ import { yellow } from "./formatting/logColors";
18
+ import { green } from "./formatting/logColors";
19
+
20
+ export type SocketServerConfig = (
21
+ https.ServerOptions & {
22
+ key: string | Buffer;
23
+ cert: string | Buffer;
24
+
25
+ port: number;
26
+ /** You can also set `port: 0` if you don't care what port you want at all. */
27
+ useAvailablePortIfPortInUse?: boolean;
28
+
29
+ // public sets ip to "0.0.0.0", otherwise it defaults to "127.0.0.1", which
30
+ // causes the server to only accept local connections.
31
+ public?: boolean;
32
+ ip?: string;
33
+
34
+ // NOTE: Any same origin accesses are allowed (header.origin === header.host)
35
+ // For example, to allow "letx.ca" to access the server (when the hosted domain
36
+ // may be, "querysub.com", for example), use ["letx.ca"]
37
+ allowHostnames?: string[];
38
+
39
+ /** If the SNI matches this domain, we use a different key/cert. */
40
+ SNICerts?: {
41
+ [domain: string]: Watchable<https.ServerOptions>;
42
+ };
43
+ }
44
+ );
45
+
46
+ export async function startSocketServer(
47
+ config: SocketServerConfig
48
+ ): Promise<string> {
49
+
50
+ const webSocketServer = new ws.Server({
51
+ noServer: true,
52
+ });
53
+
54
+ async function setupHTTPSServer(watchOptions: Watchable<https.ServerOptions>) {
55
+ let httpsServerLast: https.Server | undefined;
56
+ let onHttpServer: (server: https.Server) => void;
57
+ let httpServerPromise = new Promise<https.Server>(r => onHttpServer = r);
58
+ let lastOptions!: https.ServerOptions;
59
+ await watchOptions(value => {
60
+ lastOptions = { ...value, ca: getTrustedCertificates() };
61
+ if (!httpsServerLast) {
62
+ httpsServerLast = https.createServer(lastOptions);
63
+ } else {
64
+ httpsServerLast.setSecureContext(lastOptions);
65
+ }
66
+ onHttpServer(httpsServerLast);
67
+ });
68
+ let httpsServer = await httpServerPromise;
69
+
70
+ let allowedHostnames = new Set<string>();
71
+ for (let hostname of config.allowHostnames || []) {
72
+ allowedHostnames.add(hostname);
73
+ }
74
+
75
+ watchTrustedCertificates(() => {
76
+ lastOptions.ca = getTrustedCertificates();
77
+ httpsServer.setSecureContext(lastOptions);
78
+ });
79
+
80
+ httpsServer.on("connection", socket => {
81
+ if (!SocketFunction.silent) {
82
+ console.log("Client connection established");
83
+ }
84
+ socket.on("error", e => {
85
+ if (!SocketFunction.silent) {
86
+ console.log(`Client socket error ${e.message}`);
87
+ }
88
+ });
89
+ socket.on("close", () => {
90
+ if (!SocketFunction.silent) {
91
+ console.log("Client socket closed");
92
+ }
93
+ });
94
+ });
95
+ httpsServer.on("error", e => {
96
+ console.error(`Connection attempt error ${e.message}`);
97
+ });
98
+ httpsServer.on("tlsClientError", e => {
99
+ console.error(`TLS client error ${e.message}`);
100
+ });
101
+
102
+ httpsServer.on("request", httpCallHandler);
103
+
104
+ httpsServer.on("upgrade", (request, socket, upgradeHead) => {
105
+ socket.on("error", e => {
106
+ if (!SocketFunction.silent) {
107
+ console.log(`Client socket error ${e.message}`);
108
+ }
109
+ });
110
+
111
+ let originHeader = request.headers["origin"];
112
+ if (originHeader) {
113
+ try {
114
+ let host = new URL("ws://" + request.headers["host"]).hostname;
115
+ let origin = new URL(originHeader).hostname;
116
+ if (host !== origin && !allowedHostnames.has(origin)) {
117
+ throw new Error(`Invalid cross domain request, ${JSON.stringify(host)} !== ${JSON.stringify(origin)} (also not config.allowedHostnames ${JSON.stringify(config.allowHostnames)})`);
118
+ }
119
+ } catch (e) {
120
+ console.error(e);
121
+ return;
122
+ }
123
+ }
124
+ webSocketServer.handleUpgrade(request, socket, upgradeHead, (ws) => {
125
+ const { nodeId, localNodeId } = getNodeIdsFromRequest(request);
126
+ createCallFactory(ws, nodeId, localNodeId).catch(e => {
127
+ console.error(`Error in creating call factory, ${e.stack}`);
128
+ });
129
+ });
130
+ });
131
+ return httpsServer;
132
+ }
133
+
134
+ // TODO: Only allow unauthorized for ip certificates, and then for domains use the domain as the nodeId,
135
+ // so it is easy to read, and consistent.
136
+ let options: https.ServerOptions = {
137
+ ...config,
138
+ };
139
+ if (!config.cert) {
140
+ throw new Error("No cert specified");
141
+ }
142
+ if (!config.key) {
143
+ throw new Error("No key specified");
144
+ }
145
+
146
+ const mainHTTPSServer = await setupHTTPSServer(callback => callback(options));
147
+ let sniServers = new Map<string, https.Server>();
148
+ for (let [domain, obj] of Object.entries(config.SNICerts || {})) {
149
+ sniServers.set(domain, await setupHTTPSServer(obj));
150
+ }
151
+
152
+ let httpServer = http.createServer({}, async function (req, res) {
153
+ let url = new URL("http://" + req.headers.host + req.url);
154
+ url.protocol = "https:";
155
+ //url.hostname = opts.hostname;
156
+ url.hostname = req.headers.host || "";
157
+ res.writeHead(301, { Location: url + "" });
158
+ res.end();
159
+ });
160
+ httpServer.on("error", e => {
161
+ console.error(`HTTP error ${e.stack}`);
162
+ });
163
+
164
+ let realServer = net.createServer(socket => {
165
+ // NOTE: ONCE is used, so we only look at the first buffer, and then after that
166
+ // we pipe. This should be very efficient, as pipe has insane throughput
167
+ // (100s of MB/s, easily, even on a terrible machine).
168
+ socket.once("data", buffer => {
169
+ // All HTTPS requests start with 22, and no HTTP requests start with 22,
170
+ // so we just need to read the first byte.
171
+
172
+ let server: https.Server | http.Server;
173
+ if (buffer[0] !== 22) {
174
+ server = httpServer;
175
+ } else {
176
+ let data = parseTLSHello(buffer);
177
+ let sni = data.extensions.filter(x => x.type === SNIType).flatMap(x => parseSNIExtension(x.data))[0];
178
+ if (!SocketFunction.silent) {
179
+ console.log(`Received TCP connection with SNI ${JSON.stringify(sni)}`);
180
+ }
181
+ server = sniServers.get(sni) || mainHTTPSServer;
182
+ }
183
+
184
+ // NOTE: Messages aren't dequeued until the current handler finishes, so we don't need to pause the socket or anything.
185
+ server.emit("connection", socket);
186
+ socket.unshift(buffer);
187
+ });
188
+ socket.on("error", (e) => {
189
+ console.error(`Exposed socket error, ${e.stack}`);
190
+ });
191
+ });
192
+
193
+
194
+ let listenPromise = new Promise<void>((resolve, error) => {
195
+ realServer.on("listening", () => {
196
+ resolve();
197
+ });
198
+ realServer.on("error", e => {
199
+ error(e);
200
+ });
201
+ });
202
+
203
+ let host = config.public ? "0.0.0.0" : "127.0.0.1";
204
+ if (config.ip) {
205
+ host = config.ip;
206
+ }
207
+
208
+ let port = config.port;
209
+ if (config.useAvailablePortIfPortInUse && port) {
210
+ async function isPortInUse(port: number): Promise<boolean> {
211
+ return new Promise<boolean>((resolve, reject) => {
212
+ let server = net.createServer();
213
+ server.listen(port, host)
214
+ .on("listening", function () {
215
+ server.close();
216
+ resolve(false);
217
+ }).on("close", function () {
218
+ resolve(true);
219
+ }).on("error", function (e) {
220
+ resolve(true);
221
+ });
222
+ });
223
+ }
224
+ if (await isPortInUse(port)) {
225
+ port = 0;
226
+ }
227
+ }
228
+
229
+ if (!SocketFunction.silent) {
230
+ console.log(yellow(`Trying to listening on ${host}:${port}`));
231
+ }
232
+ realServer.listen(port, host);
233
+
234
+ await listenPromise;
235
+
236
+ port = (realServer.address() as net.AddressInfo).port;
237
+ let nodeId = getNodeId(getCommonName(config.cert), port);
238
+ if (!SocketFunction.silent) {
239
+ console.log(green(`Started Listening on ${nodeId}`));
240
+ }
241
+
242
+ return nodeId;
243
+ }
244
+
245
+ function getCommonName(cert: Buffer | string) {
246
+ let subject = new crypto.X509Certificate(cert).subject;
247
+ let subjectKVPs = new Map(subject.split(",").map(x => x.trim().split("=")).map(x => [x[0], x.slice(1).join("=")]));
248
+ let commonName = subjectKVPs.get("CN");
249
+ if (!commonName) throw new Error(`No common name in subject: ${subject}`);
250
+ return commonName;
251
251
  }
package/test/client.css CHANGED
@@ -1,3 +1,3 @@
1
- body {
2
- background: orange;
1
+ body {
2
+ background: orange;
3
3
  }
package/test/client.ts CHANGED
@@ -1,46 +1,46 @@
1
- /// <reference path="../require/RequireController.ts" />
2
-
3
- // https://letx.ca:2542/?classGuid=RequireController-e2f811f3-14b8-4759-b0d6-73f14516cf1d&functionName=requireHTML&args=[%22./test/test%22]
4
-
5
- //import typescript from "typescript";
6
-
7
- import debugbreak from "debugbreak";
8
- import { setFlag } from "../require/compileFlags";
9
- import { SocketFunction } from "../SocketFunction";
10
- import { Test } from "./shared";
11
-
12
- import "../require/CSSShim";
13
- import "./client.css";
14
- import { isNode } from "../src/misc";
15
- import { getCallObj } from "../src/nodeProxy";
16
-
17
- module.allowclient = true;
18
-
19
- //console.log(typeof typescript);
20
-
21
- //setFlag(require, "typescript", "allowclient", true);
22
-
23
-
24
- void main();
25
-
26
- async function main() {
27
- if (isNode()) return;
28
-
29
- SocketFunction.expose(Test);
30
-
31
- console.log("cool");
32
-
33
- const port = 2542;
34
-
35
- let serverId = await SocketFunction.connect({ port, address: "localhost" });
36
- let test = await Test.nodes[serverId].add(1, 2);
37
- console.log(`${test}=${1 + 2}`);
38
-
39
- // while (true) {
40
- // let test = await TestClass.nodes[serverId].add(1, 2);
41
- // console.log(`${test}=${1 + 2}`);
42
- // await new Promise(resolve => setTimeout(resolve, 1000));
43
- // }
44
-
45
- await Test.nodes[serverId].callMe();
46
- }
1
+ /// <reference path="../require/RequireController.ts" />
2
+
3
+ // https://letx.ca:2542/?classGuid=RequireController-e2f811f3-14b8-4759-b0d6-73f14516cf1d&functionName=requireHTML&args=[%22./test/test%22]
4
+
5
+ //import typescript from "typescript";
6
+
7
+ import debugbreak from "debugbreak";
8
+ import { setFlag } from "../require/compileFlags";
9
+ import { SocketFunction } from "../SocketFunction";
10
+ import { Test } from "./shared";
11
+
12
+ import "../require/CSSShim";
13
+ import "./client.css";
14
+ import { isNode } from "../src/misc";
15
+ import { getCallObj } from "../src/nodeProxy";
16
+
17
+ module.allowclient = true;
18
+
19
+ //console.log(typeof typescript);
20
+
21
+ //setFlag(require, "typescript", "allowclient", true);
22
+
23
+
24
+ void main();
25
+
26
+ async function main() {
27
+ if (isNode()) return;
28
+
29
+ SocketFunction.expose(Test);
30
+
31
+ console.log("cool");
32
+
33
+ const port = 2542;
34
+
35
+ let serverId = await SocketFunction.connect({ port, address: "localhost" });
36
+ let test = await Test.nodes[serverId].add(1, 2);
37
+ console.log(`${test}=${1 + 2}`);
38
+
39
+ // while (true) {
40
+ // let test = await TestClass.nodes[serverId].add(1, 2);
41
+ // console.log(`${test}=${1 + 2}`);
42
+ // await new Promise(resolve => setTimeout(resolve, 1000));
43
+ // }
44
+
45
+ await Test.nodes[serverId].callMe();
46
+ }