geonix 1.20.0 → 1.20.2

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 CHANGED
@@ -14,7 +14,8 @@ export default [
14
14
  }
15
15
  },
16
16
  rules: {
17
- // "no-console": "error",
17
+ "curly": "error",
18
+ "no-console": "error",
18
19
  semi: "error",
19
20
  "no-unused-vars": ["error", { argsIgnorePattern: "^_.*" }],
20
21
  "no-constant-condition": ["error", { checkLoops: false }],
package/index.d.ts CHANGED
@@ -65,6 +65,14 @@ export class Gateway {
65
65
  constructor(opts: any);
66
66
  #private;
67
67
  }
68
+ export class Logger {
69
+ constructor(options: any);
70
+ info(...args: any[]): void;
71
+ error(...args: any[]): void;
72
+ debug(...args: any[]): void;
73
+ #private;
74
+ }
75
+ export const logger: Logger;
68
76
  export const registry: Registry;
69
77
  /**
70
78
  * Registry maintains a local list of available services and their versions.
@@ -77,21 +85,27 @@ declare class Registry {
77
85
  export {};
78
86
  export function Remote(service: string, ...context: (string | Stream | Object)[]): string | Stream | Object;
79
87
  /**
88
+ * Send a request to a service
80
89
  *
81
- * @param {*} service
82
- * @param {*} method
83
- * @param {*} args
90
+ * @param {string} service
91
+ * @param {string} method
92
+ * @param {any[]} args
93
+ * @param {any[]} context
94
+ * @param {object} options
84
95
  * @returns
85
96
  */
86
- export function Request(service: any, method: any, args: any, context: any[] | undefined, options: any): Promise<any>;
97
+ export function Request(service: string, method: string, args: any[], context: any[], options: object): Promise<any>;
87
98
  /**
99
+ * Send a request to a service
88
100
  *
89
- * @param {*} service
90
- * @param {*} method
91
- * @param {*} args
101
+ * @param {string} identifier
102
+ * @param {string} method
103
+ * @param {any[]} args
104
+ * @param {any[]} context
105
+ * @param {object} options
92
106
  * @returns
93
107
  */
94
- export function directRequest(identifier: any, method: any, args: any, context: any[] | undefined, options: any, service: any): Promise<any>;
108
+ export function directRequest(identifier: string, method: string, args: any[], context: any[], options: object, service: any): Promise<any>;
95
109
  /**
96
110
  * Publish payload to a subject
97
111
  *
@@ -115,7 +129,6 @@ export function RequestOptions(options: any): RequestOptionsClass;
115
129
  export class Service {
116
130
  static serviceClasses: any[];
117
131
  static start(options?: {}): void;
118
- static static(): void;
119
132
  connections: Map<any, any>;
120
133
  $createConnection(streamId: any): Promise<boolean>;
121
134
  $getEnv(): {
@@ -133,6 +146,17 @@ export class Service {
133
146
  $getServiceInfo(): {};
134
147
  #private;
135
148
  }
149
+ export type ServiceOptions = {
150
+ middleware: {
151
+ json: boolean;
152
+ raw: boolean;
153
+ cookies: boolean;
154
+ };
155
+ /**
156
+ * Enable full beacon
157
+ */
158
+ fullBeacon: boolean;
159
+ };
136
160
  /**
137
161
  * Converts data to stream
138
162
  *
@@ -146,12 +170,15 @@ export function getReadable(object: any): Promise<any>;
146
170
  export function streamToBuffer(object: any): Promise<any>;
147
171
  export function streamToString(object: any): Promise<any>;
148
172
  export const stats: {};
173
+ export const activeStreams: {};
149
174
  /**
150
175
  * Parse nats:// URL
151
176
  * @param {string} url
152
177
  * @returns
153
178
  */
154
179
  export function parseURL(url: string): any;
180
+ export function getFirstItemFromAsyncIterable(asyncIterable: any): Promise<any>;
181
+ export function getNetworkAddresses(): any[];
155
182
  export function sleep(delay: number): Promise<any>;
156
183
  export function picoid(size?: number): any;
157
184
  export function hash(data: string | Buffer): any;
@@ -170,7 +197,6 @@ export function ServeStatic(root: any, options?: {}): any;
170
197
  export const webserver: WebServer;
171
198
  declare class WebServer {
172
199
  start(): Promise<void>;
173
- getAddresses(): any[];
174
200
  getPort(): any;
175
201
  router(): any;
176
202
  waitUntilReady(): Promise<void>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "geonix",
3
- "version": "1.20.0",
3
+ "version": "1.20.2",
4
4
  "type": "module",
5
5
  "description": "",
6
6
  "bin": {
@@ -10,6 +10,7 @@
10
10
  "scripts": {
11
11
  "test": "echo \"Error: no test specified\" && exit 1",
12
12
  "build": "npx tsc && cat build/* > index.d.ts && rm -rf build",
13
+ "lint": "npx eslint src",
13
14
  "deploy": "npm run build && npm publish"
14
15
  },
15
16
  "author": "Davor Tarandek <dtarandek@tria.hr>",
package/src/Connection.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import { connect, JSONCodec } from "nats";
2
- import { parseURL, picoid, sleep } from "./Util.js";
2
+ import { getFirstItemFromAsyncIterable, parseURL, picoid, sleep } from "./Util.js";
3
3
  import { Stream } from "./Stream.js";
4
4
  import { webserver } from "./WebServer.js";
5
+ import { logger } from "./Logger.js";
5
6
 
6
7
  // -------------------------------------------------------------------------------------------------
7
8
  const CONNECTION_TIMEOUT = 10000;
@@ -9,6 +10,16 @@ const CONNECTION_TIMEOUT = 10000;
9
10
  const defaultRequestOptions = {
10
11
  timeout: 300000
11
12
  };
13
+
14
+ const defaultConnectionOptions = {
15
+ timeout: CONNECTION_TIMEOUT,
16
+ reconnect: true,
17
+ debug: process.env.TRANSPORT_DEBUG === "true",
18
+ maxReconnectAttempts: 30,
19
+ pingInterval: 30000,
20
+ waitOnFirstConnect: true,
21
+ connections: 1
22
+ };
12
23
  // -------------------------------------------------------------------------------------------------
13
24
 
14
25
  /**
@@ -36,17 +47,8 @@ class Connection {
36
47
  * @param {string} transport
37
48
  */
38
49
  async start(transport = process.env.TRANSPORT || "nats://localhost") {
39
- const defaults = {
40
- timeout: CONNECTION_TIMEOUT,
41
- reconnect: true,
42
- debug: process.env.TRANSPORT_DEBUG === "true",
43
- maxReconnectAttempts: 30,
44
- pingInterval: 30000,
45
- waitOnFirstConnect: true,
46
- connections: 1
47
- };
48
50
  const options = {
49
- ...defaults,
51
+ ...defaultConnectionOptions,
50
52
  ...parseURL(transport)
51
53
  };
52
54
 
@@ -54,7 +56,7 @@ class Connection {
54
56
  this.#connections.push(await connect(options));
55
57
  }
56
58
 
57
- console.log("gx.connection.connected");
59
+ logger.info("gx.connection.connected");
58
60
 
59
61
  this.#ready = true;
60
62
 
@@ -64,7 +66,7 @@ class Connection {
64
66
 
65
67
  async monitorStatus() {
66
68
  for await (const event of this.#getConnection().status()) {
67
- console.log("gx.connection.status", JSON.stringify(event));
69
+ logger.info("gx.connection.status", JSON.stringify(event));
68
70
  }
69
71
  }
70
72
 
@@ -72,15 +74,17 @@ class Connection {
72
74
  * Wait for the connection to be safely closed
73
75
  */
74
76
  async waitUntilClosed() {
75
- await this.#getConnection().closed();
77
+ // wait for all connections to be closed
78
+ await Promise.all(this.#connections.map(connection => connection.closed()));
79
+
76
80
  this.#closed = true;
77
- console.log("gx.connection.closed");
81
+ logger.info("gx.connection.closed");
78
82
 
79
83
  webserver.stop();
80
84
 
81
85
  await sleep(5000);
82
86
 
83
- console.log("gx.terminate");
87
+ logger.info("gx.terminate");
84
88
  process.exit(1);
85
89
  }
86
90
 
@@ -88,8 +92,9 @@ class Connection {
88
92
  * Wait for the connection to be fully established
89
93
  */
90
94
  async waitUntilReady() {
91
- while (!this.#ready)
95
+ while (!this.#ready) {
92
96
  await sleep(100);
97
+ }
93
98
  }
94
99
 
95
100
  /**
@@ -100,14 +105,16 @@ class Connection {
100
105
  * @returns void
101
106
  */
102
107
  async publish(subject, json) {
103
- if (this.#draining || this.#closed)
108
+ if (this.#draining || this.#closed) {
104
109
  return;
110
+ }
105
111
 
106
112
  let payload = codec.encode(json);
107
113
 
108
114
  // if payload is too big, convert it to Stream
109
- if (payload.length > this.getMaxPayloadSize())
115
+ if (payload.length > this.getMaxPayloadSize()) {
110
116
  payload = codec.encode(Stream(JSON.stringify(json)));
117
+ }
111
118
 
112
119
  await this.#getConnection().publish(subject, payload);
113
120
  }
@@ -120,8 +127,9 @@ class Connection {
120
127
  * @returns void
121
128
  */
122
129
  async publishRaw(subject, data) {
123
- if (this.#draining || this.#closed)
130
+ if (this.#draining || this.#closed) {
124
131
  return;
132
+ }
125
133
 
126
134
  await this.#getConnection().publish(subject, data);
127
135
  }
@@ -145,16 +153,17 @@ class Connection {
145
153
  let payload = codec.encode({ $r: respondTo, p: json });
146
154
 
147
155
  // if payload is too big, convert it to Stream
148
- if (payload.length > this.getMaxPayloadSize())
156
+ if (payload.length > this.getMaxPayloadSize()) {
149
157
  payload = codec.encode(Stream(JSON.stringify({ $r: respondTo, p: json })));
158
+ }
150
159
 
151
160
  const nc = this.#getConnection();
152
161
  let response = await nc.subscribe(respondTo, { max: 1, ...options });
153
162
 
154
163
  await nc.publish(subject, payload);
155
164
 
156
- for await (let event of response)
157
- return codec.decode(event.data);
165
+ const event = await getFirstItemFromAsyncIterable(response);
166
+ return codec.decode(event.data);
158
167
  }
159
168
 
160
169
  async subscribe(subject, options) {
@@ -181,9 +190,7 @@ class Connection {
181
190
  async drain() {
182
191
  this.#draining = true;
183
192
 
184
- for (let connection of this.#connections) {
185
- await connection.drain();
186
- }
193
+ await Promise.all(this.#connections.map(connection => connection.drain()));
187
194
  }
188
195
 
189
196
  }
@@ -194,8 +201,9 @@ export const connection = new Connection();
194
201
  connection.start();
195
202
 
196
203
  export const stopConnection = () => {
197
- if (!connection)
204
+ if (!connection) {
198
205
  return;
206
+ }
199
207
 
200
208
  connection.drain();
201
209
  };
package/src/Gateway.js CHANGED
@@ -8,14 +8,15 @@ import expressWs from "express-ws";
8
8
  import querystring from "querystring";
9
9
  import semver from "semver";
10
10
  import { WebSocket } from "ws";
11
+ import { logger } from "./Logger.js";
11
12
 
12
13
  const raw = express.raw({ limit: "100mb" });
13
14
 
14
15
  const DEBUG_ENDPOINT = "/lZ6jD2eC3iP0zB3jJ1yJ9pM8gG3yI3vS";
15
16
  const endpointMatcher = /^((?<options>.+)\|)?(?<verb>WS|GET|POST|PATCH|PUT|DELETE|HEAD|OPTIONS|ALL)\s(?<url>.*)/;
16
17
 
17
- const logger = (req, res, next) => {
18
- console.info(`HTTP ${req.method} ${req.url}`);
18
+ const requestLogger = (req, res, next) => {
19
+ logger.info(`HTTP ${req.method} ${req.url}`);
19
20
 
20
21
  next();
21
22
  };
@@ -63,10 +64,10 @@ export class Gateway {
63
64
  this.#port = process.env.PORT || port;
64
65
  this.#api.listen(this.#port);
65
66
 
66
- console.debug(`geonix.gateway: listening on http://0.0.0.0:${this.#port}`);
67
+ logger.debug(`geonix.gateway: listening on http://0.0.0.0:${this.#port}`);
67
68
 
68
69
  // logging
69
- this.#api.use(logger);
70
+ this.#api.use(requestLogger);
70
71
 
71
72
  // cors
72
73
  this.#api.use((req, res, next) => {
@@ -86,8 +87,9 @@ export class Gateway {
86
87
  });
87
88
 
88
89
  // debug router (only available in non-production environments)
89
- if (process.env.NODE_ENV !== "production")
90
+ if (process.env.NODE_ENV !== "production") {
90
91
  this.#api.use(DEBUG_ENDPOINT, this.#debugRouter());
92
+ }
91
93
 
92
94
  this.#api.use((req, res, next) => {
93
95
  if (this.#opts.beforeRequest) {
@@ -100,10 +102,8 @@ export class Gateway {
100
102
  this.#api.use(raw, (req, res, next) => {
101
103
  stats.requests++;
102
104
 
103
- if (this.#router)
104
- this.#router(req, res, next);
105
- else
106
- next();
105
+ if (this.#router) { this.#router(req, res, next); }
106
+ else { next(); }
107
107
  });
108
108
 
109
109
  this.#api.use((req, res, next) => {
@@ -126,8 +126,9 @@ export class Gateway {
126
126
  });
127
127
 
128
128
  setInterval(() => {
129
- if (this.#rebuildRouter)
129
+ if (this.#rebuildRouter) {
130
130
  this.#buildRouter();
131
+ }
131
132
  }, 1000);
132
133
 
133
134
  while (true) {
@@ -143,12 +144,12 @@ export class Gateway {
143
144
  break;
144
145
  }
145
146
  } catch (e) {
146
- console.error(e);
147
+ logger.error(e);
147
148
  }
148
149
  }
149
150
 
150
151
  // terminate process
151
- console.debug("geonix.gateway: stopped");
152
+ logger.debug("geonix.gateway: stopped");
152
153
  process.exit(0);
153
154
  }
154
155
 
@@ -156,27 +157,29 @@ export class Gateway {
156
157
  let entries = Object.values(registry.getEntries());
157
158
 
158
159
  const processEntry = async (entry) => {
159
- if (this.#registry[entry.i] !== undefined)
160
- return false;
160
+ if (this.#registry[entry.i] !== undefined) { return false; }
161
161
 
162
- console.log(`gateway.onServiceAdded: ${entry.n}@${entry.v} (#${entry.i})`);
162
+ logger.info(`gateway.onServiceAdded: ${entry.n}@${entry.v} (#${entry.i})`);
163
163
 
164
164
  // figure out if endpoints is reachable via direct http call
165
165
  let backend;
166
- for (let address of entry.a)
167
- try {
168
- const ac = new AbortController();
169
- const timeout = setTimeout(() => ac.abort(), 500);
170
- const result = await (await fetch(`http://${address}${HEALTH_CHECK_ENDPOINT}`, { signal: ac.signal })).json();
171
- clearTimeout(timeout);
172
- if (result.status === "healthy" && result.services?.includes(entry.n)) {
173
- backend = address;
174
- console.log(`${entry.n}@${entry.v} (#${entry.i}) directly reachable @ ${address}`);
175
- break;
166
+ if (entry.a) {
167
+ for (let address of entry.a) {
168
+ try {
169
+ const ac = new AbortController();
170
+ const timeout = setTimeout(() => ac.abort(), 500);
171
+ const result = await (await fetch(`http://${address}${HEALTH_CHECK_ENDPOINT}`, { signal: ac.signal })).json();
172
+ clearTimeout(timeout);
173
+ if (result.status === "healthy" && result.services?.includes(entry.n)) {
174
+ backend = address;
175
+ logger.info(`${entry.n}@${entry.v} (#${entry.i}) directly reachable @ ${address}`);
176
+ break;
177
+ }
178
+ } catch {
179
+ // silently ignore errors
176
180
  }
177
- } catch {
178
- // silently ignore errors
179
181
  }
182
+ }
180
183
 
181
184
  let proxy;
182
185
  if (!backend) {
@@ -188,7 +191,7 @@ export class Gateway {
188
191
  try {
189
192
  await this.#proxyHttpOverNats(streamId, entry, client);
190
193
  } catch (e) {
191
- console.error("nats.proxy.error", e);
194
+ logger.error("nats.proxy.error", e);
192
195
  client.destroy();
193
196
  }
194
197
  }, 50000, 10000);
@@ -202,8 +205,9 @@ export class Gateway {
202
205
 
203
206
  entries = (await Promise.all(entries.map(processEntry))).filter(result => result === true);
204
207
 
205
- if (entries.length > 0)
208
+ if (entries.length > 0) {
206
209
  this.#rebuildRouter = true;
210
+ }
207
211
  }
208
212
 
209
213
  async #handleRemovedServices() {
@@ -213,7 +217,7 @@ export class Gateway {
213
217
  for (let { entry, proxy } of localEntries) {
214
218
  if (registryEntries[entry.i] === undefined) {
215
219
  proxy?.server?.close();
216
- console.log(`gateway.onServiceRemoved: ${entry.n}@${entry.v}`);
220
+ logger.info(`gateway.onServiceRemoved: ${entry.n}@${entry.v}`);
217
221
  delete this.#registry[entry.i];
218
222
 
219
223
  this.#rebuildRouter = true;
@@ -288,8 +292,7 @@ export class Gateway {
288
292
  });
289
293
 
290
294
  const dataLoop = async () => {
291
- for await (const event of ingress)
292
- client.write(event.data);
295
+ for await (const event of ingress) { client.write(event.data); }
293
296
  };
294
297
 
295
298
  dataLoop();
@@ -319,15 +322,16 @@ export class Gateway {
319
322
  inbound.on("close", () => backend.close());
320
323
  });
321
324
  } catch (e) {
322
- console.error(e);
325
+ logger.error(e);
323
326
  }
324
327
  }
325
328
 
326
329
  async #buildRouter() {
327
- if (this.#buildRouterRunning)
330
+ if (this.#buildRouterRunning) {
328
331
  return;
332
+ }
329
333
 
330
- console.debug("gateway.buildRouter");
334
+ logger.debug("gateway.buildRouter");
331
335
 
332
336
  this.#rebuildRouter = false;
333
337
  this.#buildRouterRunning = true;
@@ -357,8 +361,8 @@ export class Gateway {
357
361
  backend: [backend]
358
362
  });
359
363
  } catch (e) {
360
- console.error("gateway.buildRouter.error:", entry);
361
- console.error("gateway.buildRouter.error:", e);
364
+ logger.error("gateway.buildRouter.error:", entry);
365
+ logger.error("gateway.buildRouter.error:", e);
362
366
  }
363
367
  }
364
368
  }
@@ -370,12 +374,13 @@ export class Gateway {
370
374
  const version = endpoints[index].version;
371
375
  const url = `${endpoints[index].endpoint.verb} ${endpoints[index].endpoint.url}`;
372
376
 
373
- for (let n = 0; n < index; n++)
377
+ for (let n = 0; n < index; n++) {
374
378
  if (`${endpoints[n].endpoint.verb} ${endpoints[n].endpoint.url}` === url && endpoints[n].version === version) {
375
379
  endpoints[n].backend = endpoints[n].backend.concat(endpoints[index].backend);
376
380
  endpoints.splice(index, 1);
377
381
  break;
378
382
  }
383
+ }
379
384
  }
380
385
 
381
386
  // sort endpoints by order, if there is one
@@ -395,21 +400,22 @@ export class Gateway {
395
400
  router.ws(uri, (ws, req) => {
396
401
  const url = req.originalUrl.replace(/\/\.websocket$/, "");
397
402
 
398
- console.debug("proxy.web.ws.to:", backend + req.originalUrl);
403
+ logger.debug("proxy.web.ws.to:", backend + req.originalUrl);
399
404
  this.#proxyWebsocketOverNats(`ws://${backend}${url}`, ws, req);
400
405
  });
401
- } else
406
+ } else {
402
407
  router[verb](uri, async (req, res, _next) => {
403
408
  stats.proxied++;
404
409
  backend = endpoint.backend[endpoint.requests++ % endpoint.backend.length];
405
410
 
406
411
  try {
407
- console.debug("proxy.web.to:", backend + req.originalUrl);
412
+ logger.debug("proxy.web.to:", backend + req.originalUrl);
408
413
  await proxyHttp(`http://${backend}`, req, res);
409
414
  } catch (e) {
410
- console.error("proxy.web.error:", e);
415
+ logger.error("proxy.web.error:", e);
411
416
  }
412
417
  });
418
+ }
413
419
  }
414
420
 
415
421
  this.#router = router;
package/src/Logger.js ADDED
@@ -0,0 +1,34 @@
1
+ const defaultLoggerOptions = {
2
+ timestamp: true
3
+ };
4
+
5
+ export class Logger {
6
+
7
+ #options = defaultLoggerOptions;
8
+
9
+ constructor(options) {
10
+ this.#options = { ...this.#options, ...options };
11
+ }
12
+
13
+ #log(...args) {
14
+ const ts = this.#options.timestamp ? new Date().toISOString() : undefined;
15
+
16
+ // eslint-disable-next-line no-console
17
+ console.log(...[ts, ...args].filter($ => $));
18
+ }
19
+
20
+ info(...args) {
21
+ this.#log("INF", ...args);
22
+ }
23
+
24
+ error(...args) {
25
+ this.#log("ERR", ...args);
26
+ }
27
+
28
+ debug(...args) {
29
+ this.#log("DBG", ...args);
30
+ }
31
+
32
+ }
33
+
34
+ export const logger = new Logger();
package/src/Registry.js CHANGED
@@ -44,8 +44,9 @@ class Registry extends EventEmitter {
44
44
  timeout: Date.now() + REGISTRY_ENTRY_TIMEOUT
45
45
  };
46
46
 
47
- if (!exists)
47
+ if (!exists) {
48
48
  this.emit("added", this.#registry[data.i]);
49
+ }
49
50
  }
50
51
  }
51
52
 
@@ -83,14 +84,16 @@ class Registry extends EventEmitter {
83
84
  let matchVersion = version ? semver.satisfies(entry.v, version) : true;
84
85
  let matchId = id ? entry.id === id : true;
85
86
 
86
- if (matchName && matchVersion && matchId)
87
+ if (matchName && matchVersion && matchId) {
87
88
  matches.push(entry);
89
+ }
88
90
  }
89
91
 
90
92
  if (matches.length > 0) {
91
93
  // return instance id in case of id matching
92
- if (id)
94
+ if (id) {
93
95
  return matches[0].i;
96
+ }
94
97
 
95
98
  // sort matched services in the registry by version
96
99
  matches.sort((a, b) => semver.rcompare(a.v, b.v));
package/src/Request.js CHANGED
@@ -5,6 +5,7 @@ import { hash, sleep } from "./Util.js";
5
5
  import { RequestOptionsClass } from "./RequestOptions.js";
6
6
  import { isStream, streamToString } from "./Stream.js";
7
7
  import { inspect } from "node:util";
8
+ import { logger } from "./Logger.js";
8
9
 
9
10
  const REGISTRY_TIMEOUT = 300000;
10
11
 
@@ -44,8 +45,9 @@ function getOriginator() {
44
45
  for (const item of stack) {
45
46
  const typeName = item.getTypeName();
46
47
 
47
- if (Service.serviceClasses.includes(typeName))
48
+ if (Service.serviceClasses.includes(typeName)) {
48
49
  return `${typeName}.${item.getMethodName()}`;
50
+ }
49
51
  }
50
52
  }
51
53
 
@@ -64,8 +66,9 @@ export async function Request(service, method, args, context, options) {
64
66
  const { name, version, id } = match.groups;
65
67
 
66
68
  // allow passing RequestOptions as first arg
67
- if (args?.length > 0 && args[0] instanceof RequestOptionsClass)
69
+ if (args?.length > 0 && args[0] instanceof RequestOptionsClass) {
68
70
  options = (args.shift())?.options;
71
+ }
69
72
 
70
73
  let identifier = null;
71
74
 
@@ -75,8 +78,9 @@ export async function Request(service, method, args, context, options) {
75
78
  let retries = Math.floor(registryTimeout / delay);
76
79
  while (identifier == null && retries-- > 0) {
77
80
  identifier = registry.getIdentifier(name, version, id);
78
- if (!identifier)
81
+ if (!identifier) {
79
82
  await sleep(delay);
83
+ }
80
84
  }
81
85
 
82
86
  return directRequest(identifier, method, args, context, options, service);
@@ -108,10 +112,11 @@ export async function directRequest(identifier, method, args, context, options,
108
112
  options);
109
113
 
110
114
  // automatically process streamed response
111
- if (isStream(response))
115
+ if (isStream(response)) {
112
116
  response = JSON.parse(await streamToString(response));
117
+ }
113
118
  } catch (e) {
114
- console.debug("GxError: directRequest", inspect({
119
+ logger.debug("GxError: directRequest", inspect({
115
120
  originator, service: service ?? identifier, method, args, context, options,
116
121
  error: e, duration: Date.now() - requestBegin
117
122
  }));
@@ -119,12 +124,14 @@ export async function directRequest(identifier, method, args, context, options,
119
124
  throw e;
120
125
  }
121
126
 
122
- if (!response)
127
+ if (!response) {
123
128
  throw Error("Request: invalid response");
129
+ }
124
130
 
125
131
  // got error?
126
- if (response.e)
132
+ if (response.e) {
127
133
  throw Error(`Request: remote error: ${response.e}`);
134
+ }
128
135
 
129
136
  return response.r;
130
137
  }
@@ -147,10 +154,12 @@ export async function Publish(subject, payload) {
147
154
  * @returns
148
155
  */
149
156
  export async function Subscribe(subject, callback) {
150
- if (typeof callback !== "function")
157
+ if (typeof callback !== "function") {
151
158
  return;
159
+ }
152
160
 
153
161
  const subscription = await connection.subscribe(`gx.sub.${subject}`);
154
- for await (const event of subscription)
162
+ for await (const event of subscription) {
155
163
  callback(event.data);
164
+ }
156
165
  }
@@ -1,5 +1,6 @@
1
1
  export class RequestOptionsClass {
2
2
  options;
3
+
3
4
  constructor(options) {
4
5
  this.options = options;
5
6
  }