geonix 1.12.2 → 1.20.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/eslint.config.js +25 -0
- package/examples/ServeStatic/index.js +5 -5
- package/examples/ServeStatic/package.json +14 -14
- package/examples/SimpleService/index.js +8 -8
- package/examples/SimpleService/package.json +14 -14
- package/exports.js +14 -43
- package/index.d.ts +20 -20
- package/package.json +10 -6
- package/src/Connection.js +78 -55
- package/src/Gateway.js +214 -198
- package/src/Registry.js +38 -32
- package/src/Remote.js +3 -3
- package/src/Request.js +66 -52
- package/src/RequestOptions.js +4 -4
- package/src/Service.js +128 -121
- package/src/Stream.js +48 -139
- package/src/Util.js +85 -124
- package/src/WebServer.js +68 -65
- package/test/gateway.js +15 -0
- package/test/package.json +16 -0
- package/test/stream.js +38 -0
- package/tsconfig.json +10 -10
- package/src/status/deps/babel.development.js +0 -135978
- package/src/status/deps/babel.min.js +0 -17
- package/src/status/deps/react-dom.development.js +0 -29869
- package/src/status/deps/react-dom.production.min.js +0 -267
- package/src/status/deps/react.development.js +0 -3342
- package/src/status/deps/react.production.min.js +0 -31
- package/src/status/index.html +0 -13
- package/src/status/main.js +0 -30
package/src/Util.js
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
|
-
import { createHash, randomBytes } from
|
|
2
|
-
import { URL, fileURLToPath } from
|
|
3
|
-
import { readFile } from
|
|
4
|
-
import { join } from
|
|
5
|
-
import { Transform } from
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import net from 'net'
|
|
1
|
+
import { createHash, randomBytes } from "crypto";
|
|
2
|
+
import { URL, fileURLToPath } from "url";
|
|
3
|
+
import { readFile } from "fs/promises";
|
|
4
|
+
import { join } from "path";
|
|
5
|
+
import { Transform } from "node:stream";
|
|
6
|
+
import * as http from "http";
|
|
7
|
+
import * as https from "https";
|
|
8
|
+
import * as net from "net";
|
|
10
9
|
|
|
11
10
|
/**
|
|
12
11
|
* Wait for {delay} ms
|
|
13
12
|
* @param {number} delay
|
|
14
13
|
* @returns
|
|
15
14
|
*/
|
|
16
|
-
export const sleep = delay => new Promise(resolve => setTimeout(resolve, delay))
|
|
15
|
+
export const sleep = delay => new Promise(resolve => setTimeout(resolve, delay));
|
|
17
16
|
|
|
18
17
|
/**
|
|
19
18
|
* Parse nats:// URL
|
|
@@ -21,14 +20,19 @@ export const sleep = delay => new Promise(resolve => setTimeout(resolve, delay))
|
|
|
21
20
|
* @returns
|
|
22
21
|
*/
|
|
23
22
|
export function parseURL(url) {
|
|
24
|
-
const parsed = new URL(url)
|
|
23
|
+
const parsed = new URL(url);
|
|
25
24
|
|
|
26
|
-
|
|
25
|
+
const basic = {
|
|
27
26
|
servers: `${parsed.hostname}:${parsed.port || 4222}`,
|
|
28
|
-
user: parsed.password ? parsed.username :
|
|
27
|
+
user: parsed.password ? parsed.username : "",
|
|
29
28
|
pass: parsed.password,
|
|
30
29
|
token: parsed.username && !parsed.password ? parsed.username : undefined
|
|
31
|
-
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
...basic,
|
|
34
|
+
...Object.fromEntries(parsed.searchParams)
|
|
35
|
+
};
|
|
32
36
|
}
|
|
33
37
|
|
|
34
38
|
/**
|
|
@@ -36,14 +40,14 @@ export function parseURL(url) {
|
|
|
36
40
|
* @param {number} size
|
|
37
41
|
* @returns
|
|
38
42
|
*/
|
|
39
|
-
export const picoid = (size = 12) => randomBytes(size).toString(
|
|
43
|
+
export const picoid = (size = 12) => randomBytes(size).toString("base64");
|
|
40
44
|
|
|
41
45
|
/**
|
|
42
46
|
* Get SHA256 hash of a string or a buffer
|
|
43
47
|
* @param {string|Buffer} data
|
|
44
48
|
* @returns
|
|
45
49
|
*/
|
|
46
|
-
export const hash = (data) => createHash(
|
|
50
|
+
export const hash = (data) => createHash("sha256").update(data).digest("hex");
|
|
47
51
|
|
|
48
52
|
/**
|
|
49
53
|
* Create TCP or HTTP server at specified port
|
|
@@ -53,17 +57,17 @@ export const hash = (data) => createHash('sha256').update(data).digest('hex')
|
|
|
53
57
|
* @returns
|
|
54
58
|
*/
|
|
55
59
|
export const createServerAtPort = (port, pkg, handler) =>
|
|
56
|
-
new Promise((resolve
|
|
57
|
-
const server = pkg.createServer(handler)
|
|
58
|
-
server.on(
|
|
60
|
+
new Promise((resolve) => {
|
|
61
|
+
const server = pkg.createServer(handler);
|
|
62
|
+
server.on("error", (_error) => {
|
|
59
63
|
// console.log('error', error.message)
|
|
60
|
-
resolve(null)
|
|
61
|
-
})
|
|
64
|
+
resolve(null);
|
|
65
|
+
});
|
|
62
66
|
server.listen(port, () => {
|
|
63
|
-
const { port } = server.address()
|
|
64
|
-
resolve({ server, port })
|
|
65
|
-
})
|
|
66
|
-
})
|
|
67
|
+
const { port } = server.address();
|
|
68
|
+
resolve({ server, port });
|
|
69
|
+
});
|
|
70
|
+
});
|
|
67
71
|
|
|
68
72
|
/**
|
|
69
73
|
* Create TCP or HTTP server at first free port in rage
|
|
@@ -76,34 +80,36 @@ export const createServerAtPort = (port, pkg, handler) =>
|
|
|
76
80
|
export const createServerAtFreePort = async (pkg, handler, start = 30000, poolSize = 20000) => {
|
|
77
81
|
for (let port = start; port < start + poolSize; port++)
|
|
78
82
|
try {
|
|
79
|
-
const result = await createServerAtPort(port, pkg, handler)
|
|
83
|
+
const result = await createServerAtPort(port, pkg, handler);
|
|
80
84
|
// console.log(port, '=', result)
|
|
81
|
-
if (result) return result
|
|
82
|
-
} catch
|
|
83
|
-
|
|
85
|
+
if (result) return result;
|
|
86
|
+
} catch {
|
|
87
|
+
// silenty ignore errors
|
|
88
|
+
}
|
|
89
|
+
};
|
|
84
90
|
|
|
85
91
|
/**
|
|
86
92
|
* Create TCP server at random port
|
|
87
93
|
* @param {Function} handler
|
|
88
94
|
* @returns
|
|
89
95
|
*/
|
|
90
|
-
export const createTCPServer = (handler, start = 30000, poolSize = 20000) => createServerAtFreePort(net, handler, start, poolSize)
|
|
96
|
+
export const createTCPServer = (handler, start = 30000, poolSize = 20000) => createServerAtFreePort(net, handler, start, poolSize);
|
|
91
97
|
|
|
92
98
|
/**
|
|
93
99
|
* Create HTTP server at random port
|
|
94
100
|
* @param {Function} handler
|
|
95
101
|
* @returns
|
|
96
102
|
*/
|
|
97
|
-
export const createHTTPServer = (handler, start = 30000, poolSize = 20000) => createServerAtFreePort(net, handler, start, poolSize)
|
|
103
|
+
export const createHTTPServer = (handler, start = 30000, poolSize = 20000) => createServerAtFreePort(net, handler, start, poolSize);
|
|
98
104
|
|
|
99
105
|
/**
|
|
100
106
|
* Return number of seconds passed from the start of the day (0-86399)
|
|
101
107
|
* @returns Number
|
|
102
108
|
*/
|
|
103
109
|
export const getSecondsSinceMidnight = () => {
|
|
104
|
-
const date = new Date()
|
|
105
|
-
return Math.floor((date.getTime() - date.setHours(0, 0, 0, 0)) / 1000)
|
|
106
|
-
}
|
|
110
|
+
const date = new Date();
|
|
111
|
+
return Math.floor((date.getTime() - date.setHours(0, 0, 0, 0)) / 1000);
|
|
112
|
+
};
|
|
107
113
|
|
|
108
114
|
/**
|
|
109
115
|
* Parse function body and return array of param names
|
|
@@ -111,51 +117,51 @@ export const getSecondsSinceMidnight = () => {
|
|
|
111
117
|
* @returns string[]
|
|
112
118
|
*/
|
|
113
119
|
export const getFunctionParams = (fn) => {
|
|
114
|
-
const code = fn.toString()
|
|
115
|
-
const endParenthesisPosition = code.indexOf(
|
|
116
|
-
let params
|
|
120
|
+
const code = fn.toString();
|
|
121
|
+
const endParenthesisPosition = code.indexOf(")");
|
|
122
|
+
let params;
|
|
117
123
|
|
|
118
124
|
if (endParenthesisPosition != -1)
|
|
119
|
-
params = code.substring(code.indexOf(
|
|
125
|
+
params = code.substring(code.indexOf("(") + 1, endParenthesisPosition);
|
|
120
126
|
else
|
|
121
|
-
params = code.substring(0, code.indexOf(
|
|
127
|
+
params = code.substring(0, code.indexOf("=>"));
|
|
122
128
|
|
|
123
129
|
params = params
|
|
124
130
|
// cleanup spaces
|
|
125
|
-
.replaceAll(
|
|
131
|
+
.replaceAll(" ", "")
|
|
126
132
|
// split into array
|
|
127
|
-
.split(
|
|
133
|
+
.split(",");
|
|
128
134
|
|
|
129
135
|
// remove potential default values
|
|
130
136
|
for (let index = 0; index < params.length; index++) {
|
|
131
|
-
const defaultValueAssignmentPosition = params[index].indexOf(
|
|
137
|
+
const defaultValueAssignmentPosition = params[index].indexOf("=");
|
|
132
138
|
if (defaultValueAssignmentPosition != -1)
|
|
133
|
-
params[index] = params[index].substring(0, defaultValueAssignmentPosition - 1)
|
|
139
|
+
params[index] = params[index].substring(0, defaultValueAssignmentPosition - 1);
|
|
134
140
|
}
|
|
135
141
|
|
|
136
|
-
return params
|
|
137
|
-
}
|
|
142
|
+
return params;
|
|
143
|
+
};
|
|
138
144
|
|
|
139
145
|
export const proxyHttp = (target, req, res) =>
|
|
140
146
|
new Promise((resolve, reject) => {
|
|
141
|
-
const remoteTarget = `${target}${req.originalUrl}
|
|
147
|
+
const remoteTarget = `${target}${req.originalUrl}`;
|
|
142
148
|
const options = {
|
|
143
149
|
method: req.method,
|
|
144
150
|
headers: req.headers
|
|
145
|
-
}
|
|
151
|
+
};
|
|
146
152
|
|
|
147
|
-
const protocol = req.protocol ===
|
|
153
|
+
const protocol = req.protocol === "https" ? https : http;
|
|
148
154
|
const proxyReq = protocol.request(remoteTarget, options, (proxyRes) => {
|
|
149
|
-
res.status(proxyRes.statusCode)
|
|
155
|
+
res.status(proxyRes.statusCode);
|
|
150
156
|
for (const header in proxyRes.headers)
|
|
151
|
-
res.set(header, proxyRes.headers[header])
|
|
152
|
-
proxyRes.pipe(res)
|
|
153
|
-
})
|
|
154
|
-
proxyReq.on(
|
|
155
|
-
req.pipe(proxyReq)
|
|
156
|
-
req.on(
|
|
157
|
-
req.on(
|
|
158
|
-
})
|
|
157
|
+
res.set(header, proxyRes.headers[header]);
|
|
158
|
+
proxyRes.pipe(res);
|
|
159
|
+
});
|
|
160
|
+
proxyReq.on("error", (error) => reject(error));
|
|
161
|
+
req.pipe(proxyReq);
|
|
162
|
+
req.on("error", (error) => reject(error));
|
|
163
|
+
req.on("end", () => resolve());
|
|
164
|
+
});
|
|
159
165
|
|
|
160
166
|
/**
|
|
161
167
|
* Create a object proxy that overlays overlay object
|
|
@@ -163,87 +169,42 @@ export const proxyHttp = (target, req, res) =>
|
|
|
163
169
|
* @param {*} overlay
|
|
164
170
|
* @returns
|
|
165
171
|
*/
|
|
166
|
-
export const OverlayObject = (object, overlay) => new Proxy(object, { get: (t, p) => overlay[p] !== undefined ? overlay[p] : t[p] })
|
|
172
|
+
export const OverlayObject = (object, overlay) => new Proxy(object, { get: (t, p) => overlay[p] !== undefined ? overlay[p] : t[p] });
|
|
167
173
|
|
|
168
|
-
let _geonix_version =
|
|
174
|
+
let _geonix_version = "N/A";
|
|
169
175
|
try {
|
|
170
|
-
const __dirname = fileURLToPath(new URL(
|
|
171
|
-
const local = JSON.parse(await readFile(join(__dirname,
|
|
172
|
-
_geonix_version = local.version
|
|
173
|
-
} catch
|
|
176
|
+
const __dirname = fileURLToPath(new URL("..", import.meta.url));
|
|
177
|
+
const local = JSON.parse(await readFile(join(__dirname, "package.json")));
|
|
178
|
+
_geonix_version = local.version;
|
|
179
|
+
} catch {
|
|
180
|
+
// ignore errors
|
|
174
181
|
}
|
|
175
|
-
export const GeonixVersion = _geonix_version
|
|
176
182
|
|
|
177
|
-
export const
|
|
178
|
-
let buffer = Buffer.alloc(chunkSize)
|
|
183
|
+
export const GeonixVersion = _geonix_version;
|
|
179
184
|
|
|
185
|
+
export const StreamChunker = (chunkSize = 65536) => {
|
|
180
186
|
let chunker = new Transform();
|
|
181
187
|
|
|
182
188
|
chunker._transform = function (chunk, encoding, done) {
|
|
183
|
-
let offset = 0
|
|
189
|
+
let offset = 0;
|
|
184
190
|
while (offset < chunk.length) {
|
|
185
|
-
const sliceSize = Math.min(chunkSize, chunk.length - offset)
|
|
186
|
-
this.push(chunk.slice(offset, offset + sliceSize))
|
|
187
|
-
offset += sliceSize
|
|
191
|
+
const sliceSize = Math.min(chunkSize, chunk.length - offset);
|
|
192
|
+
this.push(chunk.slice(offset, offset + sliceSize));
|
|
193
|
+
offset += sliceSize;
|
|
188
194
|
}
|
|
189
195
|
|
|
190
|
-
done()
|
|
191
|
-
}
|
|
196
|
+
done();
|
|
197
|
+
};
|
|
192
198
|
|
|
193
199
|
chunker._flush = function (done) {
|
|
194
|
-
done()
|
|
195
|
-
}
|
|
200
|
+
done();
|
|
201
|
+
};
|
|
196
202
|
|
|
197
203
|
return chunker;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
export async function* timeoutAsyncGenerator(target, ms) {
|
|
201
|
-
const iterator = target[Symbol.asyncIterator]()
|
|
202
|
-
|
|
203
|
-
while (true) {
|
|
204
|
-
const { value, done } = await Promise.race([iterator.next(), sleep(ms)]) || {};
|
|
205
|
-
if (done || (value === undefined && done === undefined)) {
|
|
206
|
-
break;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
yield value;
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
export async function waitForAbort(abortSignal, result) {
|
|
214
|
-
return new Promise(resolve => {
|
|
215
|
-
if (abortSignal.aborted) {
|
|
216
|
-
resolve(result)
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
abortSignal.addEventListener('abort', () => {
|
|
220
|
-
console.log('aborted')
|
|
221
|
-
resolve(result)
|
|
222
|
-
})
|
|
223
|
-
})
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
export async function* abortableAsyncGenerator(target, abortSignal) {
|
|
227
|
-
const iterator = target[Symbol.asyncIterator]()
|
|
228
|
-
|
|
229
|
-
while (true) {
|
|
230
|
-
const { value, done } = await Promise.race([iterator.next(), waitForAbort(abortSignal)]) || {};
|
|
231
|
-
if (done || (value === undefined && done === undefined)) {
|
|
232
|
-
break;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
yield value;
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
export function getNetworkAddresses() {
|
|
240
|
-
const list = []
|
|
241
|
-
const interfaces = networkInterfaces()
|
|
242
|
-
|
|
243
|
-
for (let interfaceAddresses of Object.values(interfaces))
|
|
244
|
-
for (let addressObject of interfaceAddresses)
|
|
245
|
-
if (addressObject.family === 'IPv4')
|
|
246
|
-
list.push(addressObject.address)
|
|
204
|
+
};
|
|
247
205
|
|
|
248
|
-
|
|
206
|
+
export async function getFirstItemFromAsyncIterable(asyncIterable) {
|
|
207
|
+
const iterator = asyncIterable[Symbol.asyncIterator]();
|
|
208
|
+
const result = await iterator.next();
|
|
209
|
+
return result.value;
|
|
249
210
|
}
|
package/src/WebServer.js
CHANGED
|
@@ -1,81 +1,72 @@
|
|
|
1
|
-
import
|
|
2
|
-
import express, { Router } from
|
|
3
|
-
import expressWs from
|
|
4
|
-
import { networkInterfaces } from
|
|
5
|
-
import { createServerAtFreePort, createServerAtPort, sleep } from
|
|
6
|
-
import * as http from
|
|
7
|
-
import { Service } from
|
|
8
|
-
import * as path from
|
|
1
|
+
import "express-async-errors";
|
|
2
|
+
import express, { Router } from "express";
|
|
3
|
+
import expressWs from "express-ws";
|
|
4
|
+
import { networkInterfaces } from "os";
|
|
5
|
+
import { createServerAtFreePort, createServerAtPort, sleep } from "./Util.js";
|
|
6
|
+
import * as http from "http";
|
|
7
|
+
import { Service } from "./Service.js";
|
|
8
|
+
import * as path from "path";
|
|
9
9
|
|
|
10
|
-
export const HEALTH_CHECK_ENDPOINT =
|
|
11
|
-
|
|
12
|
-
const logger = (req, res, next) => {
|
|
13
|
-
console.log(`HTTP ${req.method} ${req.url}`)
|
|
14
|
-
|
|
15
|
-
next()
|
|
16
|
-
}
|
|
10
|
+
export const HEALTH_CHECK_ENDPOINT = "/pA4vY7fT9oG5aI8cA4yV3qW5fP9qR1vI";
|
|
17
11
|
|
|
18
12
|
export const ServeStatic = (root, options = {}) => {
|
|
19
|
-
const router = Router()
|
|
20
|
-
const absoluteRoot = path.resolve(root)
|
|
13
|
+
const router = Router();
|
|
14
|
+
const absoluteRoot = path.resolve(root);
|
|
21
15
|
|
|
22
16
|
router.use((req, res, next) => {
|
|
23
17
|
if (options.root) {
|
|
24
18
|
// remove trailing slash
|
|
25
|
-
if (options.root.endsWith(
|
|
26
|
-
options.root = options.root.slice(0, -1)
|
|
19
|
+
if (options.root.endsWith("/"))
|
|
20
|
+
options.root = options.root.slice(0, -1);
|
|
27
21
|
|
|
28
22
|
// replace root prefix
|
|
29
23
|
if (req.url.startsWith(options.root))
|
|
30
|
-
req.url = req.url.replace(options.root,
|
|
24
|
+
req.url = req.url.replace(options.root, "");
|
|
31
25
|
}
|
|
32
26
|
|
|
33
|
-
next()
|
|
34
|
-
})
|
|
27
|
+
next();
|
|
28
|
+
});
|
|
35
29
|
|
|
36
|
-
router.use(express.static(root, options))
|
|
30
|
+
router.use(express.static(root, options));
|
|
37
31
|
|
|
38
32
|
if (options.indexOn404)
|
|
39
|
-
router.get(
|
|
40
|
-
console.log(path.join(absoluteRoot,
|
|
41
|
-
res.sendFile(path.join(absoluteRoot,
|
|
42
|
-
})
|
|
33
|
+
router.get("*", (req, res) => {
|
|
34
|
+
console.log(path.join(absoluteRoot, "index.html"));
|
|
35
|
+
res.sendFile(path.join(absoluteRoot, "index.html"));
|
|
36
|
+
});
|
|
43
37
|
|
|
44
|
-
return router
|
|
45
|
-
}
|
|
38
|
+
return router;
|
|
39
|
+
};
|
|
46
40
|
|
|
47
41
|
class WebServer {
|
|
48
42
|
|
|
49
|
-
#app = express()
|
|
50
|
-
#server
|
|
51
|
-
#port
|
|
52
|
-
#ready = false
|
|
53
|
-
#started = false
|
|
54
|
-
|
|
55
|
-
constructor() {
|
|
56
|
-
}
|
|
43
|
+
#app = express();
|
|
44
|
+
#server;
|
|
45
|
+
#port;
|
|
46
|
+
#ready = false;
|
|
47
|
+
#started = false;
|
|
57
48
|
|
|
58
49
|
async start() {
|
|
59
50
|
if (this.#started)
|
|
60
|
-
return
|
|
51
|
+
return;
|
|
61
52
|
|
|
62
|
-
this.#started = true
|
|
53
|
+
this.#started = true;
|
|
63
54
|
|
|
64
|
-
let port, server
|
|
55
|
+
let port, server;
|
|
65
56
|
if (process.env.LOCAL_PORT) {
|
|
66
|
-
({ server, port } = await createServerAtPort(process.env.LOCAL_PORT, http, this.#app))
|
|
57
|
+
({ server, port } = await createServerAtPort(process.env.LOCAL_PORT, http, this.#app));
|
|
67
58
|
} else {
|
|
68
|
-
({ server, port } = await createServerAtFreePort(http, this.#app))
|
|
59
|
+
({ server, port } = await createServerAtFreePort(http, this.#app));
|
|
69
60
|
}
|
|
70
61
|
|
|
71
|
-
this.#server = server
|
|
72
|
-
this.#port = port
|
|
62
|
+
this.#server = server;
|
|
63
|
+
this.#port = port;
|
|
73
64
|
|
|
74
|
-
expressWs(this.#app, server)
|
|
65
|
+
expressWs(this.#app, server);
|
|
75
66
|
|
|
76
67
|
this.#app.get(HEALTH_CHECK_ENDPOINT, (req, res) => {
|
|
77
|
-
res.send({ status:
|
|
78
|
-
})
|
|
68
|
+
res.send({ status: "healthy", services: Service.serviceClasses });
|
|
69
|
+
});
|
|
79
70
|
|
|
80
71
|
// this.#app.use((req, res, next) => {
|
|
81
72
|
// next()
|
|
@@ -85,47 +76,59 @@ class WebServer {
|
|
|
85
76
|
// this should provide more than enough time to start all the services
|
|
86
77
|
setTimeout(() => {
|
|
87
78
|
// default answer
|
|
88
|
-
this.#app.all(
|
|
79
|
+
this.#app.all("*", (req, res) => {
|
|
89
80
|
res.status(404).send({
|
|
90
81
|
error: 404,
|
|
91
|
-
source:
|
|
92
|
-
})
|
|
93
|
-
})
|
|
94
|
-
}, 2000)
|
|
82
|
+
source: "ws"
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
}, 2000);
|
|
95
86
|
|
|
96
87
|
// config
|
|
97
|
-
this.#app.disable(
|
|
98
|
-
this.#app.disable(
|
|
88
|
+
this.#app.disable("x-powered-by");
|
|
89
|
+
this.#app.disable("etag");
|
|
90
|
+
|
|
91
|
+
console.log(`gx.webserver.start: listening on http://127.0.0.1:${this.#port}`);
|
|
92
|
+
|
|
93
|
+
this.#ready = true;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
getAddresses() {
|
|
97
|
+
const list = [];
|
|
98
|
+
const interfaces = networkInterfaces();
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
for (let interfaceAddresses of Object.values(interfaces))
|
|
101
|
+
for (let addressObject of interfaceAddresses)
|
|
102
|
+
if (addressObject.family === "IPv4")
|
|
103
|
+
list.push(addressObject.address);
|
|
101
104
|
|
|
102
|
-
|
|
105
|
+
return list;
|
|
103
106
|
}
|
|
104
107
|
|
|
105
108
|
getPort() {
|
|
106
|
-
return this.#port
|
|
109
|
+
return this.#port;
|
|
107
110
|
}
|
|
108
111
|
|
|
109
112
|
router() {
|
|
110
|
-
const router = Router()
|
|
111
|
-
this.#app.use(router)
|
|
112
|
-
return router
|
|
113
|
+
const router = Router();
|
|
114
|
+
this.#app.use(router);
|
|
115
|
+
return router;
|
|
113
116
|
}
|
|
114
117
|
|
|
115
118
|
async waitUntilReady() {
|
|
116
|
-
await this.start()
|
|
119
|
+
await this.start();
|
|
117
120
|
|
|
118
121
|
while (!this.#ready)
|
|
119
|
-
await sleep(100)
|
|
122
|
+
await sleep(100);
|
|
120
123
|
}
|
|
121
124
|
|
|
122
125
|
stop() {
|
|
123
126
|
if (this.#server) {
|
|
124
|
-
this.#server.close()
|
|
125
|
-
console.log(
|
|
127
|
+
this.#server.close();
|
|
128
|
+
console.log("gx.webserver.stop");
|
|
126
129
|
}
|
|
127
130
|
}
|
|
128
131
|
|
|
129
132
|
}
|
|
130
133
|
|
|
131
|
-
export const webserver = new WebServer()
|
|
134
|
+
export const webserver = new WebServer();
|
package/test/gateway.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Gateway, Service } from "../exports.js";
|
|
2
|
+
|
|
3
|
+
class TestService extends Service {
|
|
4
|
+
|
|
5
|
+
'GET /'(req, res) {
|
|
6
|
+
res.send('Hello World')
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
TestService.start()
|
|
11
|
+
Gateway.start({
|
|
12
|
+
beforeRequest: (req, res) => {
|
|
13
|
+
res.set('X-Test', 'Test')
|
|
14
|
+
}
|
|
15
|
+
})
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "test",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "stream.js",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [],
|
|
11
|
+
"author": "",
|
|
12
|
+
"license": "ISC",
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"geonix": "file:.."
|
|
15
|
+
}
|
|
16
|
+
}
|
package/test/stream.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { randomBytes } from 'node:crypto'
|
|
2
|
+
import { Stream, getReadable, connection } from 'geonix'
|
|
3
|
+
import { createWriteStream, readFileSync } from 'node:fs'
|
|
4
|
+
import { createHash } from 'node:crypto'
|
|
5
|
+
import { pipeline } from 'node:stream/promises'
|
|
6
|
+
|
|
7
|
+
await connection.waitUntilReady()
|
|
8
|
+
|
|
9
|
+
const hash = data => createHash('sha512').update(data).digest('base64')
|
|
10
|
+
|
|
11
|
+
const PAYLOAD_SIZE = 1024 * 1024 * 1024
|
|
12
|
+
const TEMP_FILE = '/tmp/geonix.stream_test'
|
|
13
|
+
|
|
14
|
+
console.time('test')
|
|
15
|
+
try {
|
|
16
|
+
const payload = randomBytes(PAYLOAD_SIZE)
|
|
17
|
+
const sourceHash = hash(payload)
|
|
18
|
+
|
|
19
|
+
const source = await getReadable(Stream(payload))
|
|
20
|
+
const dest = createWriteStream(TEMP_FILE)
|
|
21
|
+
|
|
22
|
+
await pipeline(source, dest)
|
|
23
|
+
|
|
24
|
+
const check = readFileSync(TEMP_FILE)
|
|
25
|
+
const destHash = hash(check)
|
|
26
|
+
|
|
27
|
+
if (sourceHash == destHash) {
|
|
28
|
+
console.log('MATCH')
|
|
29
|
+
} else {
|
|
30
|
+
console.error('Destination does not match the source!')
|
|
31
|
+
console.log(payload)
|
|
32
|
+
console.log(check)
|
|
33
|
+
}
|
|
34
|
+
} catch (e) {
|
|
35
|
+
console.error(e)
|
|
36
|
+
} finally {
|
|
37
|
+
console.timeEnd('test')
|
|
38
|
+
}
|
package/tsconfig.json
CHANGED
|
@@ -6,15 +6,15 @@
|
|
|
6
6
|
"src/status/**"
|
|
7
7
|
],
|
|
8
8
|
"compilerOptions": {
|
|
9
|
-
"target": "es2016",
|
|
10
|
-
"module": "commonjs",
|
|
11
|
-
"allowJs": true,
|
|
12
|
-
"declaration": true,
|
|
13
|
-
"emitDeclarationOnly": true,
|
|
14
|
-
"outDir": "./build",
|
|
15
|
-
"esModuleInterop": true,
|
|
16
|
-
"forceConsistentCasingInFileNames": true,
|
|
17
|
-
"strict": true,
|
|
18
|
-
"skipLibCheck": true
|
|
9
|
+
"target": "es2016",
|
|
10
|
+
"module": "commonjs",
|
|
11
|
+
"allowJs": true,
|
|
12
|
+
"declaration": true,
|
|
13
|
+
"emitDeclarationOnly": true,
|
|
14
|
+
"outDir": "./build",
|
|
15
|
+
"esModuleInterop": true,
|
|
16
|
+
"forceConsistentCasingInFileNames": true,
|
|
17
|
+
"strict": true,
|
|
18
|
+
"skipLibCheck": true
|
|
19
19
|
}
|
|
20
20
|
}
|