@naanlang/naan 1.6.0 → 1.7.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 (50) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +1 -1
  3. package/bin/index.js +2 -2
  4. package/dist/env_web.js +3 -31
  5. package/dist/naan.min.js +10 -10
  6. package/frameworks/browser/sworker.js +23 -23
  7. package/frameworks/browser/terminals.nlg +44 -122
  8. package/frameworks/browser/worker.nlg +64 -24
  9. package/frameworks/browser/workers.nlg +1 -1
  10. package/frameworks/client/apiclient.nlg +73 -43
  11. package/frameworks/client/psm_client.nlg +10 -14
  12. package/frameworks/common/common.nlg +2 -0
  13. package/frameworks/node/apiserver.nlg +0 -1
  14. package/frameworks/node/node.nlg +1 -0
  15. package/frameworks/node/pty.nlg +21 -21
  16. package/frameworks/node/shell.nlg +26 -3
  17. package/frameworks/node/worker.nlg +153 -79
  18. package/frameworks/project/build.nlg +55 -13
  19. package/frameworks/project/projects.nlg +1 -1
  20. package/frameworks/running/debugcom.nlg +20 -3
  21. package/frameworks/running/debugnub.nlg +16 -7
  22. package/frameworks/running/executors.nlg +14 -12
  23. package/frameworks/running/instances.nlg +1 -0
  24. package/frameworks/running/remote_req.nlg +4 -8
  25. package/frameworks/running/remote_res.nlg +1 -1
  26. package/frameworks/running/sourcecode.nlg +3 -2
  27. package/frameworks/running/taskexec.nlg +14 -57
  28. package/frameworks/service/imp.nlg +15 -0
  29. package/frameworks/service/nubnode.nlg +35 -4
  30. package/frameworks/service/nubweb.nlg +22 -4
  31. package/frameworks/storage/file_manager.nlg +3 -2
  32. package/lib/browser/env_web.js +10 -38
  33. package/lib/browser/env_webworker.js +1 -30
  34. package/lib/core/naanlib.js +10 -10
  35. package/lib/env_node.js +5 -22
  36. package/lib/env_nodeworker.js +8 -43
  37. package/lib/node_server_init.nlg +149 -0
  38. package/lib/node_worker.js +36 -0
  39. package/lib/node_worker_init.nlg +43 -0
  40. package/package.json +1 -1
  41. package/plugins/openSearch/openSearch.nlg +3 -2
  42. package/plugins/openSearch/os_dynamo.nlg +3 -2
  43. package/plugins/serviceAws/aws_cloudwatchlogs.nlg +44 -2
  44. package/plugins/serviceAws/aws_dynamo.nlg +144 -63
  45. package/plugins/serviceAws/aws_utils.nlg +6 -11
  46. package/plugins/serviceAws/serviceAws.nlg +3 -2
  47. package/test/test_01_core.nlg +2 -2
  48. package/test/test_02_context.nlg +8 -8
  49. package/test/test_03_jsinterop.nlg +3 -3
  50. package/test/test_07_lingo.nlg +1 -1
package/lib/env_node.js CHANGED
@@ -304,27 +304,6 @@ exports.NaanNodeREPL = function NaanNodeREPL(options) {
304
304
  // messages are originating from the interpreter itself, so that it does not call itself back
305
305
  // recursively. That would be Very Bad™.
306
306
  //
307
-
308
- var replyHook;
309
- this.OnReplyHook = function OnReplyHook(proc) {
310
- replyHook = proc;
311
- return (proc);
312
- };
313
-
314
- this.ReplyMessage = function ReplyMessage(data) {
315
- if (replyHook)
316
- setTimeout(function() {
317
- replyHook(data);
318
- }, 1);
319
- if (termops)
320
- {
321
- setTimeout(function () {
322
- if (termops)
323
- termops.messageout(data);
324
- }, 1);
325
- }
326
- return (data);
327
- };
328
307
 
329
308
  var nodeListener;
330
309
  this.OnMessage = function OnMessage(proc) {
@@ -390,8 +369,12 @@ exports.NaanNodeREPL = function NaanNodeREPL(options) {
390
369
  debugListener(msg.data); // received a debugger message
391
370
  }, 1);
392
371
  }
372
+ else if (msg.id == "attached")
373
+ servSelf.ioctl_event("term-attach", msg.guid);
374
+ else if (msg.id == "detached")
375
+ servSelf.ioctl_event("term-detach", msg.guid);
393
376
  else if (msg.id == "ioctl-event")
394
- this.ioctl_event(msg.msg, msg.arg);
377
+ servSelf.ioctl_event(msg.msg, msg.arg);
395
378
  };
396
379
 
397
380
  // textToRemoteTerm
@@ -157,7 +157,7 @@ exports.NaanWorkerActivate = function NaanWorkerActivate(cbReady) {
157
157
  //==========================================================================
158
158
  // NodeJS Worker Terminal Interface
159
159
  //--------------------------------------------------------------------------
160
-
160
+
161
161
  naanlib.onText(function(text, level) {
162
162
  if (level)
163
163
  msgPort.postMessage({
@@ -171,7 +171,7 @@ exports.NaanWorkerActivate = function NaanWorkerActivate(cbReady) {
171
171
  text: text
172
172
  });
173
173
  });
174
-
174
+
175
175
  setInterval(function() {
176
176
  var samples = naanlib.status(1);
177
177
  if (samples.length > 0)
@@ -182,34 +182,6 @@ exports.NaanWorkerActivate = function NaanWorkerActivate(cbReady) {
182
182
  }
183
183
  });
184
184
  }, 1000);
185
-
186
- workSelf.ReplyMessage = function ReplyMessage(data) {
187
- msgPort.postMessage({ // worker is sending a message
188
- id: "targetout",
189
- data: data
190
- });
191
- return (data);
192
- };
193
-
194
- var workerListener;
195
- workSelf.OnMessage = function OnMessage(proc) {
196
- workerListener = proc;
197
- return (proc);
198
- };
199
-
200
- workSelf.DispatchMessage = function DispatchMessage(data) {
201
- msgPort.postMessage({ // target is sending a message
202
- id: "targetsend",
203
- data: data
204
- });
205
- return (data);
206
- };
207
-
208
- var targetReceiver;
209
- workSelf.OnReceive = function OnReceive(proc) {
210
- targetReceiver = proc;
211
- return (proc);
212
- };
213
185
 
214
186
  workSelf.ReplyDebugger = function ReplyDebugger(data) {
215
187
  msgPort.postMessage({ // target is sending debug data
@@ -218,13 +190,13 @@ exports.NaanWorkerActivate = function NaanWorkerActivate(cbReady) {
218
190
  });
219
191
  return (data);
220
192
  };
221
-
193
+
222
194
  var debugListener;
223
195
  workSelf.OnDebugger = function OnDebugger(proc) {
224
196
  debugListener = proc;
225
197
  return (proc);
226
198
  };
227
-
199
+
228
200
  msgPort.on("message", function(msg) {
229
201
  if (msg.id == "interrupt")
230
202
  naanlib.escape(); // interrupt request from terminal
@@ -235,7 +207,6 @@ exports.NaanWorkerActivate = function NaanWorkerActivate(cbReady) {
235
207
  else if (msg.id == "start")
236
208
  { // start execution with optional state
237
209
  workSelf.workerID = msg.workerID;
238
- workSelf.workerGUID = msg.workerGUID;
239
210
  workerMetadata = msg.metadata || { };
240
211
  if (typeof(__dirname) !== "undefined")
241
212
  naanlib.js.h = naanlib.js.d; // set host directory path
@@ -253,21 +224,15 @@ exports.NaanWorkerActivate = function NaanWorkerActivate(cbReady) {
253
224
  }
254
225
  else if (msg.id == "import")
255
226
  importScripts(msg.script); // load a JavaScript
256
- else if (msg.id == "targetin")
257
- {
258
- if (workerListener)
259
- workerListener(msg.data); // worker received a message
260
- }
261
227
  else if (msg.id == "debugin")
262
228
  {
263
229
  if (debugListener)
264
230
  debugListener(msg.data); // target received a message
265
231
  }
266
- else if (msg.id == "targetreceive")
267
- {
268
- if (targetReceiver)
269
- targetReceiver(msg.data);
270
- }
232
+ else if (msg.id == "attached")
233
+ workSelf.ioctl_event("term-attach", msg.guid);
234
+ else if (msg.id == "detached")
235
+ workSelf.ioctl_event("term-detach", msg.guid);
271
236
  else if (msg.id == "ioctl-event")
272
237
  workSelf.ioctl_event(msg.msg, msg.arg);
273
238
  });
@@ -0,0 +1,149 @@
1
+ /*
2
+ * node_server_init.nlg
3
+ * Naanide
4
+ *
5
+ * Loaded automatically for Node.js before REPL turned over to the user.
6
+ *
7
+ * column positioning: // // !
8
+ *
9
+ * Copyright (c) 2020-2026 by Richard C. Zulch
10
+ *
11
+ */
12
+
13
+ loglevel(3);
14
+
15
+
16
+ /*
17
+ * Debugging & Tools
18
+ *
19
+ */
20
+
21
+ if !module.owner.list.running.components.debugnub {
22
+ require("naanlib:frameworks/common/repltools.nlg").ImportReplTools()
23
+ require("naanlib:frameworks/running/debugnub.nlg").DebugNub()
24
+ };
25
+
26
+ App.shell = require("naanlib:frameworks/node/shell.nlg").ShellConnect({
27
+ cwd: js.d
28
+ })
29
+
30
+
31
+ /*
32
+ * versionCheck
33
+ *
34
+ * Ensure that Node is at least as new as the specified version.
35
+ *
36
+ */
37
+
38
+ function versionCheck(minver, local rxver, curver) {
39
+ rxver = RegExp("([0-9]+)[.]([0-9]+)[.]([0-9]+)")
40
+ minver = minver.match(rxver).map(function(x){Number.parseInt(x)})
41
+ curver = js.g.process.version.match(rxver).map(function(x){Number.parseInt(x)})
42
+ minver[1] < curver[1] || minver[1] == curver[1] && (minver[2] < curver[2] || minver[2] == curver[2] && minver[3] <= curver[3])
43
+ };
44
+
45
+
46
+ /*
47
+ * saveState
48
+ *
49
+ * Save our state soon. This saves in a future to avoid stack problems. Returns a nonce.
50
+ *
51
+ */
52
+
53
+ function saveState() {
54
+ future(function() {
55
+ js.t.Working()
56
+ js.save()
57
+ }, 0)
58
+ };
59
+
60
+
61
+ /*
62
+ * startup
63
+ *
64
+ * This is the normal NaanIDE startup code. The scenarios are as follows:
65
+ * 1. Start new server at available port and launch browser tab // default behavior
66
+ * 2. Start new server with intialization file that launches browser
67
+ * 3. Start new server at fixed port and launch browser tab
68
+ * 4. Start new server at fixed port with initialization file
69
+ * 5. Connect to existing server at fixed port and evaluate remote expression, then quit
70
+ *
71
+ * This uses the Naan symbol NaanStartParams as:
72
+ * {
73
+ * naanpath: <string> // path to the naan library
74
+ * serverPort: <integer> // defined if the command line specified a port
75
+ * guid: <string> // server secret
76
+ * cmd_mod: <string> // name of a command to execute
77
+ * cmd_path: <string> // path to command's module
78
+ * cmd_args: [<string>] // arguments to the command
79
+ * }
80
+ *
81
+ */
82
+
83
+ closure startup(local error, api, exists, oururl) {
84
+ if !versionCheck("16.20.2") {
85
+ debuglog("NaanIDE: NodeJS too old; version 16.20.2 required.")
86
+ js.g.process.exit(2)
87
+ }
88
+ if !dictionary(NaanStartParams) {
89
+ debuglog("NaanIDE: startup parameters missing.")
90
+ js.g.process.exit(3)
91
+ }
92
+
93
+ App.imp = require("naanlib:frameworks/service/imp.nlg").Imp({
94
+ name: "NaanIDE Server"
95
+ type: "Server IMP"
96
+ })
97
+ require("naanlib:frameworks/running/remote_res.nlg")
98
+ .RemoteResponder(App.imp.us.instanceID, { // make our server remotable
99
+ name: "NaanIDE Server"
100
+ type: "Node Remote"
101
+ })
102
+ App.exec = require("naanlib:frameworks/node/worker.nlg").CurBot({
103
+ name: "NaanIDE Server"
104
+ type: "NaaN Server"
105
+ })
106
+
107
+ App.api = undefined
108
+ App.naanpath = NaanStartParams.naanpath
109
+ App.nidecon = require("lib/nidecon").NideCon({
110
+ fixedPort: NaanStartParams.serverPort
111
+ guid: NaanStartParams.guid
112
+ statics: [
113
+ list("", NaanStartParams.naanpath)
114
+ ]
115
+ })
116
+ if NaanStartParams.cmd_mod {
117
+ `(error) = App.nidecon.runCommand(NaanStartParams.cmd_mod, NaanStartParams.cmd_path, NaanStartParams.cmd_args)
118
+ saveState().wait() // wait so we don't exit too soon
119
+ if error {
120
+ if error.memo != ""
121
+ ErrorDebuglog("NaanIDE: command failed", error)
122
+ if error.exit
123
+ js.g.process.exit(error.exit) // fatal error
124
+ }
125
+ }
126
+ else if js.expr
127
+ saveState().wait()
128
+ else {
129
+ `(error, api, exists) = App.nidecon.startServer()
130
+ if exists {
131
+ `(error, oururl) = App.nidecon.connectServer()
132
+ if error {
133
+ ErrorDebuglog("NaanIDE: server at port ${NaanStartParams.serverPort} not responding", error)
134
+ js.g.process.exit(1)
135
+ }
136
+ debuglog("existing server access:", oururl)
137
+ return
138
+ } else if error {
139
+ ErrorDebuglog("NaanIDE: can't start server:", error)
140
+ js.g.process.exit(1)
141
+ }
142
+ debuglog("server access:", api.oururl)
143
+ Naan.runtimelib.curdriver().setOptions({prompt:true})
144
+ saveState()
145
+ `(error) = App.nidecon.launchBrowser()
146
+ if error
147
+ ErrorDebuglog("NaanIDE: can't launch browser:", error)
148
+ }
149
+ }();
@@ -0,0 +1,36 @@
1
+ /*
2
+ * node_worker.js
3
+ * naanide
4
+ *
5
+ * Start a Naanide worker.
6
+ *
7
+ * column positioning: // // !
8
+ *
9
+ * Copyright (c) 2017-2026 by Richard C. Zulch
10
+ *
11
+ */
12
+
13
+ "use strict";
14
+
15
+
16
+ /*
17
+ * Begin
18
+ *
19
+ */
20
+
21
+ var workerData = require('node:worker_threads').workerData || { }; // passed from creator
22
+ var jspath = require("path");
23
+ var naanpath = jspath.resolve(require.resolve('@naanlang/naan'), '../../../');
24
+ var envpath = jspath.resolve(naanpath, 'lib/env_nodeworker.js');
25
+ var naanenv = require(envpath);
26
+
27
+ naanenv.NaanWorkerActivate(function(naanworker) {
28
+ naanworker.setRequire(require); // require relative to this file
29
+ naanworker.setImport(function(m) { return (import(m)); }); // import relative to this file
30
+
31
+ naanworker.textCommand(""
32
+ + `App.naanpath = '${ naanpath.replace(/\\/g, "\\\\") }';;` // path/to/our naan library
33
+ + "App.rootpath = js.d;;" // path/to/our package.json
34
+ + "Naan.module.defineLoc('naanlib', App.naanpath);;" // defines "naanlib:" prefix for require
35
+ + "Naan.module.nodeparse('lib/node_worker_init.nlg');;\n"); // Naan initialization
36
+ });
@@ -0,0 +1,43 @@
1
+ /*
2
+ * nide_worker_init.nlg
3
+ * NaanIDE
4
+ *
5
+ * Loaded automatically for Node.js before REPL turned over to the user.
6
+ *
7
+ * column positioning: // // !
8
+ *
9
+ * Copyright (c) 2020-2026 by Richard C. Zulch
10
+ *
11
+ */
12
+
13
+
14
+ loglevel(3);
15
+ chns("Start");
16
+
17
+
18
+ /*
19
+ * Debugging & Tools
20
+ *
21
+ */
22
+
23
+ function init(local metadata) {
24
+ sprint() // no interruptions
25
+ if !module.owner.list.running.components.debugnub {
26
+ require("naanlib:frameworks/common/repltools.nlg").ImportReplTools()
27
+ require("naanlib:frameworks/running/debugnub.nlg").DebugNub()
28
+ }
29
+ App.shell = require("naanlib:frameworks/node/shell.nlg").ShellConnect({
30
+ cwd: js.d
31
+ })
32
+ metadata = new(js.t.metadata())
33
+ App.mainInstanceID = metadata.mainInstanceID
34
+ App.imp = require("naanlib:frameworks/service/imp.nlg").Imp({
35
+ name: metadata.name
36
+ type: "node-worker"
37
+ })
38
+ require("naanlib:frameworks/service/nubnode.nlg").NodeWorkerNub(App.imp, {
39
+ name: App.imp.us.name
40
+ })
41
+ if metadata.maintext
42
+ textparse(metadata.maintext)
43
+ }();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naanlang/naan",
3
- "version": "1.6.0",
3
+ "version": "1.7.0",
4
4
  "author": "Richard C. Zulch",
5
5
  "description": "Naan™ software platform",
6
6
  "main": "./lib/core/naanlib.js",
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * column positioning: // // !
8
8
  *
9
- * Copyright (c) 2023 by Richard C. Zulch
9
+ * Copyright (c) 2023-2026 by Richard C. Zulch
10
10
  *
11
11
  */
12
12
 
@@ -53,6 +53,7 @@ closure openSearchIndex(prosc, indexName, ioptions, local osin) {
53
53
  osin = new(object, this)
54
54
  if symbol(indexName)
55
55
  indexName = indexName.tostring()
56
+ osin.name = indexName
56
57
  osin.analyzers = { // map names, language to analyzer
57
58
  english: "english"
58
59
  hashtag: "hashtag"
@@ -335,7 +336,7 @@ closure openSearchIndex(prosc, indexName, ioptions, local osin) {
335
336
  `(error, data) = prosc.request(indexName.concat("/_bulk"), {
336
337
  method: "POST"
337
338
  putdata: docs
338
- contentType: "application/json"
339
+ contentType: "application/x-ndjson"
339
340
  })
340
341
  if data
341
342
  data = data.items.map(function(item) {
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * column positioning: // // !
8
8
  *
9
- * Copyright (c) 2023-2025 by Richard C. Zulch
9
+ * Copyright (c) 2023-2026 by Richard C. Zulch
10
10
  *
11
11
  */
12
12
 
@@ -41,6 +41,7 @@
41
41
 
42
42
  closure OSDynIndexer(index, table, options,
43
43
  local dbOptions, scanPending, indexPending, updatePending, output, error, records, data, ids) {
44
+ global()
44
45
  if !options.converter
45
46
  return (Error("OSDynIndexer: options.converter is required"))
46
47
  dbOptions = {
@@ -78,7 +79,7 @@ closure OSDynIndexer(index, table, options,
78
79
  //
79
80
  // Batch index documents into OpenSearch, returning a nonce signaled with ids array.
80
81
  //
81
- closure batchIndex(records, local pending) {
82
+ closure batchIndex(records, local pending, docs) {
82
83
  pending = new(nonce)
83
84
  docs = asyncArray(records, 10, closure(record) {
84
85
  options.converter(record)
@@ -18,7 +18,7 @@
18
18
  *
19
19
  */
20
20
 
21
- closure CloudWatchLogs(local cwlogs) {
21
+ closure CloudWatchLogs(local cwlogs, delayf, backoffMS) {
22
22
  global(awsSDK)
23
23
  cwlogs = new(object, this)
24
24
 
@@ -35,7 +35,42 @@ closure CloudWatchLogs(local cwlogs) {
35
35
  })
36
36
  list(false, { ok: true })
37
37
  }
38
+
39
+ // retrier
40
+ //
41
+ // Perform exponential backoff when throttled, returning true for retry or false otherwise.
42
+ //
43
+ function retrier(error, local waitms, newbo) {
44
+ if !error
45
+ delayf = false
46
+ else if error.name == "ThrottlingException" { // retriable errors
47
+ if backoffMS > milliseconds() {
48
+ debuglog("DynaTable.retrier: existing backoff", backoffMS - milliseconds(), "msec")
49
+ return (true) // use existing backoff
50
+ }
51
+ if !delayf
52
+ delayf = ExbackFactory(6,60) // 6s max backoff, 60s deadline
53
+ waitms = delayf()
54
+ debuglog("DynaTable.retrier: new backoff:", waitms, "msec")
55
+ if waitms { // returns false for no retry
56
+ newbo = milliseconds() + waitms // tick when proceeding is allowed
57
+ if !(backoffMS > newbo)
58
+ backoffMS = newbo
59
+ true
60
+ }
61
+ }
62
+ }
38
63
 
64
+ // delayer
65
+ //
66
+ // Delay until the current backoff is complete.
67
+ //
68
+ function delayer(local waitms) {
69
+ waitms = backoffMS - milliseconds()
70
+ if waitms > 0
71
+ sleep(waitms + waitms * Math.random()/2)
72
+ }
73
+
39
74
  //
40
75
  // cwlQueryPager
41
76
  //
@@ -46,7 +81,14 @@ closure CloudWatchLogs(local cwlogs) {
46
81
  if !remaining
47
82
  remaining = 10 // default retrieve limit
48
83
  params.limit = remaining
49
- QueryPager(cwlogs.aws, procname, params, function(data, local processed) {
84
+ delayer()
85
+ QueryPager(cwlogs.aws, procname, params, function(error, data, local processed) {
86
+ if error {
87
+ if !retrier(error)
88
+ return (false)
89
+ delayer()
90
+ return (true)
91
+ }
50
92
  processed = doneCB(data)
51
93
  if processed
52
94
  remaining -= processed