geonix 1.8.11 → 1.9.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "geonix",
3
- "version": "1.8.11",
3
+ "version": "1.9.0",
4
4
  "type": "module",
5
5
  "description": "",
6
6
  "bin": {
package/src/Connection.js CHANGED
@@ -55,6 +55,9 @@ class Connection {
55
55
  console.log('gx.connection.status', JSON.stringify(event))
56
56
  }
57
57
 
58
+ /**
59
+ * Wait for the connection to be safely closed
60
+ */
58
61
  async waitUntilClosed() {
59
62
  await this.#nc.closed()
60
63
  this.#closed = true
@@ -68,11 +71,21 @@ class Connection {
68
71
  process.exit(1)
69
72
  }
70
73
 
74
+ /**
75
+ * Wait for the connection to be fully established
76
+ */
71
77
  async waitUntilReady() {
72
78
  while (!this.#ready)
73
79
  await sleep(100)
74
80
  }
75
81
 
82
+ /**
83
+ * Publish JSON
84
+ *
85
+ * @param {string} subject
86
+ * @param {object} json
87
+ * @returns void
88
+ */
76
89
  async publish(subject, json) {
77
90
  if (this.#draining || this.#closed)
78
91
  return
@@ -86,6 +99,13 @@ class Connection {
86
99
  await this.#nc.publish(subject, payload)
87
100
  }
88
101
 
102
+ /**
103
+ * Publish RAW
104
+ *
105
+ * @param {string} subject
106
+ * @param {string | Buffer} data
107
+ * @returns void
108
+ */
89
109
  async publishRaw(subject, data) {
90
110
  if (this.#draining || this.#closed)
91
111
  return
@@ -93,8 +113,16 @@ class Connection {
93
113
  await this.#nc.publish(subject, data)
94
114
  }
95
115
 
116
+ /**
117
+ * Request/Reply pattern on top of pub/sub
118
+ *
119
+ * @param {string} subject
120
+ * @param {object} json
121
+ * @param {object} options
122
+ * @returns any
123
+ */
96
124
  async request(subject, json, options = { timeout: 300000 }) {
97
- const respondTo = `_INBOX.${picoid(32)}`
125
+ const respondTo = `gx2.r.${picoid(16)}`
98
126
 
99
127
  let payload = codec.encode({ $r: respondTo, p: json })
100
128
 
package/src/Request.js CHANGED
@@ -4,6 +4,7 @@ import { Service } from './Service.js'
4
4
  import { hash, sleep } from './Util.js'
5
5
  import { RequestOptionsClass } from './RequestOptions.js'
6
6
  import { isStream, streamToString } from './Stream.js'
7
+ import { inspect } from 'node:util'
7
8
 
8
9
  const REGISTRY_TIMEOUT = 300000
9
10
 
@@ -91,7 +92,7 @@ export async function Request(service, method, args = [], context = [], options)
91
92
  },
92
93
  options)
93
94
  } catch (e) {
94
- console.debug('GxError: Request', JSON.stringify({
95
+ console.debug('GxError: Request', inspect({
95
96
  originator, service, method, args, context, options,
96
97
  error: e, duration: Date.now() - requestBegin
97
98
  }))
package/src/Service.js CHANGED
@@ -32,11 +32,14 @@ export class Service {
32
32
 
33
33
  }
34
34
 
35
- // ---------------------------------------------------------------------------------------------
35
+ // ---------------------------------------------------------------------------------------------
36
36
 
37
37
  #me = {}
38
+ #options = {}
38
39
 
39
40
  async #start(options = {}) {
41
+ this.#options = options
42
+
40
43
  await webserver.waitUntilReady()
41
44
  await connection.waitUntilReady()
42
45
 
@@ -145,6 +148,11 @@ export class Service {
145
148
 
146
149
  let handlers = (Array.isArray(this[endpoint]) ? this[endpoint] : [this[endpoint]])
147
150
 
151
+ if (Array.isArray(this.#options?.handlers?.before))
152
+ handlers = [...this.#options?.handlers?.before, ...handlers]
153
+ if (Array.isArray(this.#options?.handlers?.after))
154
+ handlers = [...handlers, ...this.#options?.handlers?.after]
155
+
148
156
  for (let n = 0; n < handlers.length; n++)
149
157
  handlers[n] = handlers[n].bind(this)
150
158
 
File without changes
@@ -0,0 +1,60 @@
1
+ import { Service, Remote } from 'geonix'
2
+
3
+ const calc = Remote('Calculator')
4
+ const tp = Remote('TimeProvider')
5
+
6
+ class Logger {
7
+
8
+ constructor(prefix) {
9
+ this.prefix = prefix
10
+ }
11
+
12
+ log(...args) {
13
+ console.log(`${new Date().toISOString()}|${this.prefix}|`, ...args)
14
+ }
15
+ }
16
+
17
+ class BaseService extends Service {
18
+
19
+ logger = new Logger(this.constructor.name)
20
+
21
+ }
22
+
23
+
24
+ class CalculatorRepository {
25
+
26
+ constructor(service) {
27
+ this.logger = service.logger
28
+ }
29
+
30
+ async getCurrentTime() {
31
+ this.logger.log('getCurrentTime')
32
+ return await Remote('TimeProvider').now()
33
+ }
34
+
35
+ }
36
+
37
+ class Calculator extends BaseService {
38
+
39
+ repo = new CalculatorRepository(this)
40
+
41
+ async onStart() {
42
+ this.logger.log('current time =', await this.repo.getCurrentTime())
43
+ }
44
+
45
+ thisHere() {
46
+
47
+ }
48
+
49
+ }
50
+
51
+ class TimeProvider extends BaseService {
52
+
53
+ now() {
54
+ return new Date().toISOString()
55
+ }
56
+
57
+ }
58
+
59
+ Calculator.start()
60
+ TimeProvider.start()
@@ -0,0 +1,31 @@
1
+ export const OverlayObject = (object, overlay) => {
2
+ return new Proxy(object, {
3
+ get: (t, p) => overlay[p] !== undefined ? overlay[p] : t[p]
4
+ }
5
+ )
6
+ }
7
+
8
+ class Test {
9
+
10
+ #me = { works: true }
11
+
12
+ get me() { return this.#me }
13
+
14
+ external() {
15
+ return this.me
16
+ }
17
+
18
+ call(method) {
19
+ try {
20
+ const methodContext = { context: 'this is context value' }
21
+ const $context = OverlayObject(this, methodContext)
22
+ return instance[method].apply($context)
23
+ } catch (e) {
24
+ }
25
+ }
26
+
27
+ }
28
+
29
+ const instance = new Test()
30
+
31
+ console.log(instance.call('external'))
@@ -0,0 +1,36 @@
1
+ import { Service, Remote, registry } from '../exports.js'
2
+ import { sleep } from '../src/Util.js'
3
+
4
+ class BaseService extends Service {
5
+
6
+ static start(options = {}) {
7
+ super.start({
8
+ ...options,
9
+ handlers: {
10
+ before: [
11
+ (req, res, next) => {
12
+ console.log('before')
13
+ next()
14
+ }
15
+ ],
16
+ after: [(error, req, res, next) => {
17
+ if (error) {
18
+ res.send({ status: 'rawr', error: error.message })
19
+ }
20
+ }]
21
+ }
22
+ })
23
+ }
24
+
25
+ }
26
+
27
+ class First extends BaseService {
28
+
29
+ 'GET /wow'(req, res) {
30
+ throw Error('wow')
31
+ }
32
+
33
+ }
34
+
35
+
36
+ First.start()
@@ -0,0 +1,43 @@
1
+ import { readFile } from 'fs/promises';
2
+ import { Service, Stream, getReadable } from '../exports.js';
3
+
4
+ process.env.LOCAL_PORT = 1234
5
+
6
+ class DownloadServiceDebuggingSession extends Service {
7
+
8
+ #transferCounter = 1
9
+
10
+ onStart() {
11
+ console.log("Starting service...");
12
+ }
13
+
14
+ 'GET /api/download/local' = [
15
+ async (_, res) => {
16
+ const id = this.#transferCounter++
17
+
18
+ console.log(`transfer=${id} begin`)
19
+ const result = await this.getLocalFile()
20
+ console.log(`transfer=${id} stream=${JSON.stringify(result)}`)
21
+ const stream = await getReadable(result)
22
+ console.log(`transfer=${id}`)
23
+ stream.pipe(res)
24
+
25
+ let counter = 0;
26
+ stream.on('data', (chunk) => {
27
+ counter += chunk.length
28
+ // console.log(`transfer=${id} sent=${(counter / 1024 / 1024).toFixed(2).padStart()}`)
29
+ })
30
+
31
+ stream.on('end', () => {
32
+ console.log(`transfer=${id} end`)
33
+ })
34
+ }
35
+ ]
36
+
37
+ getLocalFile = async () => {
38
+ const buffer = await readFile("./test150.txt")
39
+ return Stream(buffer)
40
+ }
41
+ }
42
+
43
+ DownloadServiceDebuggingSession.start()
package/test/stream2.js CHANGED
@@ -33,7 +33,6 @@ class StreamTest extends Service {
33
33
  const bytes = randomBytes(size)
34
34
  const checksum = hash(bytes)
35
35
 
36
- console.log(size)
37
36
  return { checksum, stream: Stream(bytes) }
38
37
  }
39
38
 
@@ -1,33 +0,0 @@
1
- export function serialize(input) {
2
- const process = (value) => {
3
- if (value instanceof Buffer) {
4
- console.log('this is buffer')
5
- }
6
-
7
- if (typeof value === 'object')
8
- for (let prop in value)
9
- serialize()
10
-
11
- return value
12
- }
13
-
14
- let state = input
15
-
16
- process(state)
17
-
18
- return JSON.stringify(state)
19
- }
20
-
21
- export function deserialize(input) {
22
-
23
- }
24
-
25
- const input = {
26
-
27
- }
28
-
29
- const s = serialize(input)
30
- const ds = deserialize(s)
31
-
32
- console.log(' serialized =', s)
33
- console.log('deserialized =', ds)