@naanlang/naan 1.4.4 → 1.6.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.
Files changed (61) hide show
  1. package/LICENSE.md +2 -2
  2. package/README.md +4 -4
  3. package/bin/index.js +25 -3
  4. package/dist/env_web.js +164 -22
  5. package/dist/naan.min.js +5 -5
  6. package/frameworks/browser/browser.nlg +2 -2
  7. package/frameworks/browser/https_request.nlg +2 -2
  8. package/frameworks/browser/sworker.js +28 -26
  9. package/frameworks/browser/terminals.nlg +342 -700
  10. package/frameworks/browser/worker.nlg +255 -0
  11. package/frameworks/browser/workers.nlg +5 -5
  12. package/frameworks/browser/ws_client.nlg +15 -10
  13. package/frameworks/client/apiclient.nlg +204 -19
  14. package/frameworks/client/client.nlg +22 -2
  15. package/frameworks/client/psm_client.nlg +12 -3
  16. package/frameworks/client/relaycon.nlg +87 -161
  17. package/frameworks/common/events.nlg +101 -0
  18. package/frameworks/common/repltools.nlg +80 -1
  19. package/frameworks/node/apiserver.nlg +39 -246
  20. package/frameworks/node/filesystem.nlg +39 -12
  21. package/frameworks/node/gitter.nlg +9 -7
  22. package/frameworks/node/http_request.nlg +34 -13
  23. package/frameworks/node/https_request.nlg +8 -3
  24. package/frameworks/node/node.nlg +2 -0
  25. package/frameworks/node/pty.nlg +346 -0
  26. package/frameworks/node/shell.nlg +4 -4
  27. package/frameworks/node/worker.nlg +409 -539
  28. package/frameworks/node/ws_client.nlg +2 -2
  29. package/frameworks/project/build.nlg +1 -1
  30. package/frameworks/project/projects.nlg +2 -1
  31. package/frameworks/running/debugnub.nlg +17 -4
  32. package/frameworks/running/executors.nlg +27 -274
  33. package/frameworks/running/instances.nlg +393 -0
  34. package/frameworks/running/remote_req.nlg +143 -0
  35. package/frameworks/running/remote_res.nlg +89 -0
  36. package/frameworks/running/taskexec.nlg +2 -2
  37. package/frameworks/service/imp.nlg +736 -0
  38. package/frameworks/service/model.nlg +71 -0
  39. package/frameworks/service/nubnode.nlg +105 -0
  40. package/frameworks/service/nubweb.nlg +106 -0
  41. package/frameworks/service/service.nlg +28 -0
  42. package/frameworks/storage/dbt_pouch.nlg +26 -13
  43. package/frameworks/storage/psm.nlg +39 -5
  44. package/frameworks/storage/psm_dbtables.nlg +10 -2
  45. package/lib/browser/env_web.js +171 -29
  46. package/lib/browser/env_webworker.js +91 -5
  47. package/lib/core/naanlib.js +5 -5
  48. package/lib/env_node.js +184 -8
  49. package/lib/env_nodeworker.js +74 -1
  50. package/package.json +1 -1
  51. package/plugins/serviceAws/aws_cloudwatchlogs.nlg +2 -1
  52. package/plugins/serviceAws/aws_dynamo.nlg +1 -0
  53. package/plugins/serviceAws/aws_s3.nlg +3 -3
  54. package/plugins/serviceAws/aws_sqs.nlg +3 -1
  55. package/plugins/serviceAws/aws_utils.nlg +3 -1
  56. package/plugins/serviceAws/dbt_aws.nlg +22 -20
  57. package/plugins/serviceAws/psm_aws.nlg +2 -1
  58. package/plugins/serviceNexara/speechrec.nlg +10 -6
  59. package/test/test_02_context.nlg +24 -1
  60. package/test/test_03_jsinterop.nlg +32 -3
  61. package/plugins/serviceGC/russian_trusted_root_ca_pem.crt +0 -33
@@ -0,0 +1,255 @@
1
+ /*
2
+ * worker.nlg
3
+ * Naanlib/frameworks/browser
4
+ *
5
+ * Manage NaaN instances.
6
+ *
7
+ * NaaN instances are managed by a top/bottom pair of of objects. InBot (INstance BOTtom) objects
8
+ * reside in the same JavaScript environment (node/browser) as their worker and communicate with the
9
+ * appropriate env_xxx.js adapter for NaaN in that environment.
10
+ *
11
+ * Zero or more InTop objects connect to each InBot object via the IMP network, providing remote
12
+ * evaluation and terminal access services. Each InTop supports only one terminal simultaneously, but
13
+ * they can be attached and detached at any time.
14
+ *
15
+ * column positioning: // // !
16
+ *
17
+ * Copyright (c) 2026 by Richard C. Zulch
18
+ *
19
+ */
20
+
21
+
22
+ /*
23
+ * InBot
24
+ *
25
+ * Create a remote interface for a single execution instance, returning the object. This provides
26
+ * instance access to zero or more InTops via IMP connections. The tops subscribe to receive
27
+ * notifications/responses.
28
+ *
29
+ * Options:
30
+ * {
31
+ * name: <string> // target name, e.g. "Play"
32
+ * type: <string> // target category, e.g. "Local"
33
+ * startup: <dictionary> // startup options
34
+ * workerID: <string> // initialize worker with this
35
+ * workerGUID: <string> // initialize worker with this
36
+ * topOriginID: <string> // so top can route to us through IMP
37
+ * }
38
+ *
39
+ */
40
+
41
+ closure InBot(worker, options, local inbot)
42
+ {
43
+ global(App)
44
+ inbot = new(object, this)
45
+ inbot.topsubs = []
46
+ options = merge({
47
+ type: "Local"
48
+ }, options)
49
+ inbot.workerID = options.workerID
50
+ inbot.worker = worker
51
+
52
+ inbot.instanceID = UUID()
53
+ inbot.sender = App.imp.register(inbot, {
54
+ name: options.name
55
+ type: options.type
56
+ instanceID: inbot.instanceID
57
+ services: ["naan-worker"]
58
+ })
59
+
60
+ // If this InBot is created remotely then we need to send a message from our new instanceID
61
+ // to the InTop origin so that it can send messages to us. The intermediate gateways save the
62
+ // route to allow replies.
63
+ if options.topOriginID && options.topOriginID != App.imp.us.instanceID
64
+ inbot.sender(options.topOriginID) // create route top->bottom
65
+
66
+ // subscribe
67
+ //
68
+ // Add an InTop to our subscribers if not already known.
69
+ //
70
+ function subscribe(destID) {
71
+ if !inbot.topsubs.find(function(item) { item == destID }) {
72
+ inbot.topsubs.push(destID)
73
+ if inbot.workerDestID
74
+ inbot.sender(destID, {
75
+ id: "workerDestID"
76
+ workerDestID: inbot.workerDestID
77
+ })
78
+ }
79
+ }
80
+
81
+ // unsubscribe
82
+ //
83
+ // Remove an InTop from our subscribers if present.
84
+ //
85
+ function unsubscribe(destID) {
86
+ inbot.topsubs = inbot.topsubs.filter(function(item) { item != destID })
87
+ }
88
+
89
+ // notifyAll
90
+ //
91
+ // Send the message to all our subscribers.
92
+ //
93
+ inbot.notifyAll = function notifyAll(message, exceptID, local topDestID) {
94
+ for topDestID in inbot.topsubs
95
+ if topDestID != exceptID
96
+ inbot.sender(topDestID, message)
97
+ }
98
+
99
+ // impUnknown
100
+ //
101
+ // Received an unknown destination notice from the other side.
102
+ //
103
+ inbot.impUnknown = function impUnknown(unknownID, sourceID, gateway) {
104
+ if inbot.topsubs[unknownID] { // did not have courtesy to unsubscribe!
105
+ unsubscribe(unknownID)
106
+ return
107
+ }
108
+ if !gateway
109
+ debuglog("InBot.impUnknownID:", unknownID, "sourceID:", sourceID)
110
+ }
111
+
112
+ // impReceive
113
+ //
114
+ // Received a message from InTop.
115
+ //
116
+ inbot.impReceive = function impReceive(message, sourceID) {
117
+ if message.id == "destroy"
118
+ destroy() // told to destroy worker
119
+ else if message.id == "subscribe"
120
+ subscribe(sourceID)
121
+ else if message.id == "unsubscribe"
122
+ unsubscribe(sourceID)
123
+ else if message.id == "typed"
124
+ notifyAll(message, sourceID)
125
+ else { // relay to worker
126
+ message.scope = "naan-env-web"
127
+ inbot.worker.postMessage(message)
128
+ }
129
+ }
130
+
131
+ // onmessage
132
+ //
133
+ // A message was received from the worker.
134
+ //
135
+ inbot.worker.addEventListener("message", function(e, local msg) {
136
+ msg = new(e.data)
137
+ if msg.scope == "naan-imp-web" {
138
+ inbot.impconn.dispatch(msg.data)
139
+ return
140
+ }
141
+ if msg.scope != "naan-env-web"
142
+ return
143
+ if msg.id == "loaded" {
144
+ if !inbot.started
145
+ inbot.worker.postMessage({
146
+ scope: "naan-env-web"
147
+ id: "start",
148
+ state: false // resume state, if we have any
149
+ altcmd: options.startup.initcmds
150
+ workerID: options.workerID
151
+ workerGUID: options.workerGUID
152
+ metadata: {
153
+ mainInstanceID: App.imp.us.instanceID
154
+ name: options.name
155
+ }
156
+ })
157
+ inbot.started = true
158
+ }
159
+ notifyAll(msg)
160
+ })
161
+
162
+ // onerror
163
+ //
164
+ // The worker had an error.
165
+ //
166
+ inbot.worker.addEventListener("error", function(e) {
167
+ debuglog("worker error:", e.message)
168
+ notifyAll({
169
+ id: "error"
170
+ data: e.message
171
+ })
172
+ inbot.worker = false
173
+ destroy()
174
+ })
175
+
176
+ // destroy
177
+ //
178
+ // Ensure the worker is destroyed and notify everyone.
179
+ //
180
+ inbot.destroy = function destroy() {
181
+ if inbot.worker {
182
+ inbot.worker.terminate() // kill without saving
183
+ inbot.worker = false
184
+ }
185
+ notifyAll({
186
+ id: "terminated"
187
+ })
188
+ inbot.impconn.close()
189
+ inbot.impconn = false
190
+ App.imp.unregister(inbot.instanceID)
191
+ }
192
+
193
+ // register our connects *after* the receivers are configured above
194
+
195
+ // finis
196
+
197
+ inbot
198
+ };
199
+
200
+
201
+ /*
202
+ * NubBot
203
+ *
204
+ * Create a remote interface like InBot, but also provide messaging support for WebWorkerNub inside
205
+ * the worker.
206
+ *
207
+ */
208
+
209
+ closure NubBot(worker, options, local nubbot)
210
+ {
211
+ global(App)
212
+ nubbot = InBot(worker, options)
213
+
214
+ App.imp.addEventListener("active", function(event, info) {
215
+ if info.ourID == nubbot.instanceID {
216
+ nubbot.workerDestID = info.destID // handshake completed
217
+ nubbot.notifyAll({ // send to tops
218
+ id: "workerDestID"
219
+ workerDestID: nubbot.workerDestID
220
+ })
221
+ }
222
+ })
223
+
224
+ nubbot.impconn = App.imp.responder(function(data) {
225
+ nubbot.worker.postMessage({ // send to worker
226
+ scope: "naan-imp-web" // scoped for WorkerNub
227
+ data: data
228
+ })
229
+ list(false, { sent: true })
230
+ }, {
231
+ ourID: nubbot.instanceID
232
+ })
233
+
234
+ // finis
235
+
236
+ nubbot
237
+ };
238
+
239
+
240
+ /*
241
+ * workInit
242
+ *
243
+ * Initialize the component.
244
+ *
245
+ */
246
+
247
+ function workInit(local manifest) {
248
+ manifest = `(InBot, NubBot, workInit)
249
+
250
+ Naan.module.build(module.id, "worker", function(modobj, compobj) {
251
+ require("./browser.nlg")
252
+ compobj.manifest = manifest
253
+ modobj.exports.InBot = InBot
254
+ })
255
+ } ();
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * column positioning: // // !
8
8
  *
9
- * Copyright (c) 2020-2023 by Richard C. Zulch
9
+ * Copyright (c) 2020-2026 by Richard C. Zulch
10
10
  *
11
11
  */
12
12
 
@@ -427,22 +427,22 @@ closure TrackServiceWorkers(track, pubID, pubVersion, callback, local error) {
427
427
  `(error, serviceWorker) = ScopedServiceWorker(pubID, pubVersion, callback)
428
428
  if error
429
429
  ErrorDebugLog("TrackServiceWorkers: cannot load service worker", error)
430
- track.register(TrackedScope, "V-Site")
430
+ track.register("V-Site", TrackedScope)
431
431
  serviceWorker
432
432
  };
433
433
 
434
434
 
435
435
  /*
436
- * workInit
436
+ * worksInit
437
437
  *
438
438
  * Initialize the debugger page.
439
439
  *
440
440
  */
441
441
 
442
- function workInit(local manifest) {
442
+ function worksInit(local manifest) {
443
443
 
444
444
  manifest = `(ServiceWorker, ScopedServiceWorker, findTrackedScope, TrackedScope,
445
- TrackServiceWorkers, workInit)
445
+ TrackServiceWorkers, worksInit)
446
446
 
447
447
  Naan.module.build(module.id, "workers", function(modobj, compobj) {
448
448
  require("./browser.nlg")
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * column positioning: // // !
7
7
  *
8
- * Copyright (c) 2023-2024 by Richard C. Zulch
8
+ * Copyright (c) 2023-2026 by Richard C. Zulch
9
9
  *
10
10
  */
11
11
 
@@ -13,11 +13,14 @@
13
13
  /*
14
14
  * WebSocket
15
15
  *
16
- * Create a WebSocket client connection object using the existing HTTPS connection.
16
+ * Create a WebSocket client connection object.
17
+ *
18
+ * Optional, default Host:
19
+ * host: <string> // host:port
17
20
  *
18
21
  * Options:
19
22
  * {
20
- * host: <string> // host:port
23
+ * wss: <boolean> // true to use secure connection
21
24
  * onopen: <proc>(e) // connection has opened
22
25
  * onmessage: <proc>(e, message) // message received
23
26
  * onerror: <proc>(e) // error occurred
@@ -28,12 +31,14 @@
28
31
  *
29
32
  */
30
33
 
31
- closure WebSocket(options, local wsock) {
34
+ closure WebSocket(host, options, local wsock) {
32
35
  global(window)
33
36
  wsock = new(object, this)
34
37
  options = new(options) || { }
35
- if !options.host
36
- options.host = window.location.host
38
+ if !host {
39
+ host = window.location.host
40
+ options.wss = window.location.protocol == "https:"
41
+ }
37
42
 
38
43
  // connect
39
44
  //
@@ -42,10 +47,10 @@ closure WebSocket(options, local wsock) {
42
47
  wsock.connect = closure connect(local url, pending) {
43
48
  if wsock.ws
44
49
  return (list(false, { open: true }))
45
- if window.location.protocol == "https:"
46
- url = "wss://${options.host}${options.querys||''}"
50
+ if options.wss
51
+ url = "wss://${host}${options.querys||''}"
47
52
  else
48
- url = "ws://${options.host}${options.query||''}"
53
+ url = "ws://${host}${options.query||''}"
49
54
  wsock.ws = xnew(window.WebSocket, url)
50
55
  pending = new(nonce)
51
56
 
@@ -58,7 +63,7 @@ closure WebSocket(options, local wsock) {
58
63
 
59
64
  // onmessage
60
65
  // A message was received from the worker via WebSockets.
61
- wsock.ws.onmessage = closure onmessage(e, message) {
66
+ wsock.ws.onmessage = closure onmessage(e, local message) {
62
67
  try {
63
68
  message = new(JSONparse(e.data))
64
69
  } catch {
@@ -2,41 +2,70 @@
2
2
  * apiclient.nlg
3
3
  * Naanlib/frameworks/client
4
4
  *
5
- * Access to Nide API with browser HTTP client.
5
+ * Access to Nide API with specified HTTP client.
6
6
  *
7
7
  * column positioning: // // !
8
8
  *
9
- * Copyright (c) 2017-2024 by Richard C. Zulch
9
+ * Copyright (c) 2017-2026 by Richard C. Zulch
10
10
  *
11
11
  */
12
12
 
13
13
 
14
+ // Globals
15
+
16
+ serviceMod;;
17
+
18
+
14
19
  /*
15
- * NideAPIclient
20
+ * APIClient
21
+ *
22
+ * Make an API client object.
16
23
  *
17
- * Make an API client object for browsers.
24
+ * Options:
25
+ * {
26
+ * url: <string> // hostname or URL of the remote server
27
+ * guid: <string> // shared secret for access to remote server
28
+ * }
18
29
  *
19
30
  */
20
31
 
21
- closure NideAPIclient(url, guid, apiRequester, local client) {
22
- global()
32
+ closure APIClient(imp, options, local client, url, guid) {
33
+ global(App, serviceMod)
23
34
  client = new(object, this)
35
+ options = merge({
36
+ }, options)
37
+ url = options.url
24
38
  if !url.match(RegExp("^https?:\/\/", "i"))
25
39
  url = "http://${url}" // a protocol is required
26
40
  if url.slice(-1) != "/"
27
41
  url = url.concat("/") // must end in "/"
28
42
  client.url = url
29
- client.guid = guid
43
+ options.url = url
44
+ client.guid = options.guid
30
45
  client.notifyAfter = 0
31
- client.instanceID = UUID() // our client's unique ID
46
+ client.requester = clirRequester()
47
+
48
+ //
49
+ // wsopen
50
+ //
51
+
52
+ client.wsopen = function wsopen(error) {
53
+ if !client.wesc {
54
+ client.wesc = WebSocketClient(options, imp)
55
+ `(error) = client.wesc.connect()
56
+ if error
57
+ ErrorDebuglog("APIClient: cannot connect to", url)
58
+ }
59
+ }
60
+ wsopen()
32
61
 
33
62
  // clientRequest() - append our guid to the headers
34
63
 
35
- closure clientRequest(url, options) {
36
- options = merge(options)
37
- if guid
38
- options.headers = [list("x-naanlang-api-guid", guid)]
39
- apiRequester(url, options)
64
+ closure clientRequest(url, reqops) {
65
+ reqops = merge(reqops)
66
+ if options.guid
67
+ reqops.headers = [list("x-naanlang-api-guid", options.guid)]
68
+ client.requester(url, reqops)
40
69
  }
41
70
 
42
71
  //
@@ -57,7 +86,7 @@ closure NideAPIclient(url, guid, apiRequester, local client) {
57
86
  timeout: timeoutms
58
87
  after: client.notifyAfter
59
88
  })
60
- `(error, content, extra) = clientRequest(url.concat(query))
89
+ `(error, content, extra) = clientRequest(url.concat(query), { retrier: false }) // don't retry inside
61
90
  if (error || extra.status != 200)
62
91
  cbStatus()
63
92
  else if (length(content) == 0)
@@ -76,8 +105,12 @@ closure NideAPIclient(url, guid, apiRequester, local client) {
76
105
  // get
77
106
  //
78
107
 
79
- client.get = closure get(path, options, local error, content, extra) {
80
- `(error, content, extra) = clientRequest(url.concat(path))
108
+ client.get = closure get(path, options, local requrl, error, content, extra) {
109
+ if App.cache
110
+ requrl = url.concat(EncodeQuery(path.concat("?"), { naanver: App.cache }))
111
+ else
112
+ requrl = url.concat(path)
113
+ `(error, content, extra) = clientRequest(requrl)
81
114
  if !error && extra.status != 200
82
115
  error = Error("readFile failed: ".concat(extra.status), {
83
116
  status: extra.status
@@ -139,26 +172,178 @@ closure NideAPIclient(url, guid, apiRequester, local client) {
139
172
  else
140
173
  callback(error, content)
141
174
  }
175
+
176
+ // destroy
177
+ //
178
+ // Close down the client and release all resources.
179
+ //
180
+ client.destroy = closure destroy() {
181
+ debuglog("client destroy websocket")
182
+ client.wesc.destroy()
183
+ client.wesc = false
184
+ }
142
185
 
143
186
  client
144
187
  };
145
188
 
146
189
 
190
+ /*
191
+ * WebSocketClient
192
+ *
193
+ * WebSocket client for websocket communications with a server. The Instance Messaage Processor (IMP)
194
+ * handles routing between instances using intermediaries.
195
+ *
196
+ * Options:
197
+ * {
198
+ * url: <string> // hostname or URL of the remote server
199
+ * guid: <string> // shared secret for access to remote server
200
+ * instanceID: <string> // UUID for our client; can be persisted by caller
201
+ * }
202
+ *
203
+ */
204
+
205
+ closure WebSocketClient(options, imp, local wesc, ws) {
206
+ global(js)
207
+ wesc = new(object, this)
208
+
209
+ // connect
210
+ //
211
+ // Establish a websocket connection with the host.
212
+ //
213
+ wesc.connect = closure connect(local url, pending) {
214
+ if ws && !wesc.fatal
215
+ return(list(false, { connected: true }))
216
+ if wesc.fatal
217
+ debuglog("WebSocketClient reopen")
218
+ wesc.fatal = false
219
+ try {
220
+ url = xnew(js.w.URL, options.url)
221
+ } catch {
222
+ return(list(Error("invalid URL ${options.url}", exception)))
223
+ }
224
+ if url.protocol == "https:"
225
+ url.protocol = "wss:"
226
+ else
227
+ url.protocol = "ws:"
228
+ ws = xnew(js.w.WebSocket, url.href)
229
+ pending = new(nonce)
230
+
231
+ // onopen
232
+ // The WebSocket connection is now open.
233
+ ws.onopen = function onopen(e, local error) {
234
+ wesc.impconn = imp.requester(function(data) {
235
+ if wesc.fatal // raw send function
236
+ return (list(wesc.fatal))
237
+ ws.send(js.w.JSON.stringify(data))
238
+ list(false, { sent: true })
239
+ }, {
240
+ secret: options.guid
241
+ label: "api-server"
242
+ wesc: wesc
243
+ })
244
+ if error
245
+ pending.signal(list(error))
246
+ else
247
+ pending.signal(list(false, { ok: true }))
248
+ }
249
+
250
+ // onmessage
251
+ // A message was received via WebSockets.
252
+ ws.onmessage = function onmessage(e, local error, message) {
253
+ `(error, message) = JsonParse(e.data)
254
+ if !error {
255
+ message = new(message)
256
+ if wesc.impconn.dispatch(message)
257
+ return
258
+ }
259
+ debuglog("socket message:", e.data)
260
+ }
261
+
262
+ // onerror
263
+ // An error occurred on the WebSocket connection.
264
+ // This can happen in normal operation when the connection times out.
265
+ ws.onerror = function onerror(e) {
266
+ if !wesc.fatal
267
+ wesc.fatal = Error("websocket failed", e)
268
+ pending.signal(list(wesc.fatal))
269
+ }
270
+
271
+ // onclose
272
+ // The WebSocket connection was closed.
273
+ ws.onclose = function onclose(e) {
274
+ // if e.code != 1000 && e.code != 1001 && e.code != 1005 && e.code != 1006
275
+ debuglog("WebSocketClient: closed:", e.code, e.reason)
276
+ ws = false
277
+ if !wesc.fatal
278
+ wesc.fatal = Error("websocket closed", e.code, e.reason)
279
+ pending.signal(list(wesc.fatal))
280
+ wesc.impconn.close({
281
+ code: e.code
282
+ reason: e.reason
283
+ })
284
+ wesc.impconn = false
285
+ }
286
+
287
+ pending.wait()
288
+ }
289
+
290
+ // close
291
+ //
292
+ // Close the connection, but can be opened again with connect().
293
+ //
294
+ wesc.close = function close() {
295
+ if !ws
296
+ return
297
+ ws.close(1000) // 1000: normal close
298
+ }
299
+
300
+ // destroy
301
+ //
302
+ // Destroy the connection permanently.
303
+ //
304
+ wesc.destroy = function destroy() {
305
+ close()
306
+ }
307
+
308
+ // send
309
+ //
310
+ // Send a message.
311
+ //
312
+ wesc.send = closure send(data) {
313
+ if wesc.fatal
314
+ return (wesc.fatal)
315
+ wesc.impconn.send(data)
316
+ }
317
+
318
+ // sendRaw
319
+ //
320
+ // Send a message with reconnect but no routing.
321
+ //
322
+ wesc.sendRaw = closure sendRaw(data) {
323
+ ws.send(data)
324
+ }
325
+
326
+ // finis
327
+ wesc
328
+ };
329
+
330
+
147
331
  /*
148
332
  * apicInit
149
333
  *
150
- * Initialize the apic component.
334
+ * Initialize the apiclient component.
151
335
  *
152
336
  */
153
337
 
154
338
  function apicInit(local manifest) {
155
339
 
156
- manifest = `(NideAPIclient, apicInit)
340
+ manifest = `(APIClient, WebSocketClient, apicInit)
157
341
 
158
342
  Naan.module.build(module.id, "apiclient", function(modobj, compobj) {
159
343
  Naan.module.require("./client.nlg")
344
+ serviceMod = Naan.module.require("naanlib:frameworks/service/imp.nlg")
160
345
  compobj.manifest = manifest
161
- modobj.exports.NideAPIclient = NideAPIclient
346
+ modobj.exports.APIClient = APIClient
162
347
  })
163
348
 
164
349
  } ();
@@ -6,11 +6,31 @@
6
6
  *
7
7
  * column positioning: // // !
8
8
  *
9
- * Copyright (c) 2020-2021 by Richard C. Zulch
9
+ * Copyright (c) 2020-2025 by Richard C. Zulch
10
10
  *
11
11
  */
12
12
 
13
13
 
14
+ /*
15
+ * clirRequester
16
+ *
17
+ * Return an appropriate HttpsRequestApi client based on our environment.
18
+ *
19
+ */
20
+
21
+ clirRequestApi = false;
22
+
23
+ function clirRequester() {
24
+ if !clirRequestApi {
25
+ if js.w
26
+ clirRequestApi = require("naanlib:frameworks/browser/https_request.nlg").HttpsApiRequest
27
+ else
28
+ clirRequestApi = require("naanlib:frameworks/node/https_request.nlg").HttpsApiRequest
29
+ }
30
+ clirRequestApi
31
+ };
32
+
33
+
14
34
  /*
15
35
  * clirInit
16
36
  *
@@ -20,7 +40,7 @@
20
40
  */
21
41
 
22
42
  function clirInit(local manifest) {
23
- manifest = `(clirInit)
43
+ manifest = `(clirRequester, clirInit)
24
44
 
25
45
  Naan.module.build(module.id, "client", function(modobj, compobj) {
26
46
  require("../common/").LiveImport()