@naanlang/naan 1.6.0 → 1.7.1

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 (54) 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 -32
  5. package/dist/naan.min.js +10 -10
  6. package/frameworks/browser/sworker.js +23 -23
  7. package/frameworks/browser/terminals.nlg +161 -212
  8. package/frameworks/browser/worker.nlg +78 -30
  9. package/frameworks/browser/workers.nlg +1 -1
  10. package/frameworks/browser/ws_client.nlg +23 -87
  11. package/frameworks/client/apiclient.nlg +91 -58
  12. package/frameworks/client/client.nlg +22 -2
  13. package/frameworks/client/psm_client.nlg +10 -14
  14. package/frameworks/client/relaycon.nlg +1 -1
  15. package/frameworks/common/common.nlg +13 -9
  16. package/frameworks/node/apiserver.nlg +1 -2
  17. package/frameworks/node/node.nlg +1 -0
  18. package/frameworks/node/pty.nlg +21 -21
  19. package/frameworks/node/shell.nlg +26 -3
  20. package/frameworks/node/worker.nlg +166 -84
  21. package/frameworks/node/ws_client.nlg +25 -84
  22. package/frameworks/project/build.nlg +83 -32
  23. package/frameworks/project/projects.nlg +2 -2
  24. package/frameworks/running/debugcom.nlg +20 -3
  25. package/frameworks/running/debugnub.nlg +16 -7
  26. package/frameworks/running/executors.nlg +36 -26
  27. package/frameworks/running/instances.nlg +34 -22
  28. package/frameworks/running/remote_req.nlg +6 -9
  29. package/frameworks/running/remote_res.nlg +2 -2
  30. package/frameworks/running/sourcecode.nlg +3 -2
  31. package/frameworks/running/taskexec.nlg +14 -57
  32. package/frameworks/service/imp.nlg +37 -5
  33. package/frameworks/service/nubnode.nlg +39 -8
  34. package/frameworks/service/nubweb.nlg +28 -10
  35. package/frameworks/storage/file_manager.nlg +3 -2
  36. package/lib/browser/env_web.js +10 -39
  37. package/lib/browser/env_webworker.js +1 -30
  38. package/lib/core/naanlib.js +10 -10
  39. package/lib/env_node.js +5 -22
  40. package/lib/env_nodeworker.js +8 -43
  41. package/lib/node_server_init.nlg +149 -0
  42. package/lib/node_worker.js +36 -0
  43. package/lib/node_worker_init.nlg +43 -0
  44. package/package.json +1 -1
  45. package/plugins/openSearch/openSearch.nlg +3 -2
  46. package/plugins/openSearch/os_dynamo.nlg +3 -2
  47. package/plugins/serviceAws/aws_cloudwatchlogs.nlg +44 -2
  48. package/plugins/serviceAws/aws_dynamo.nlg +144 -63
  49. package/plugins/serviceAws/aws_utils.nlg +6 -11
  50. package/plugins/serviceAws/serviceAws.nlg +3 -2
  51. package/test/test_01_core.nlg +2 -2
  52. package/test/test_02_context.nlg +8 -8
  53. package/test/test_03_jsinterop.nlg +3 -3
  54. package/test/test_07_lingo.nlg +1 -1
@@ -634,18 +634,14 @@ closure psmcFsConnector(psm, api, local connClassID, connector, watch) {
634
634
  else {
635
635
  api = connector.apis[creds.urlName]
636
636
  if !api { // create API to remote server
637
- connector.apis[creds.urlName] = api = APIClient({
637
+ api = APIClient(App.imp, {
638
638
  url: creds.urlName
639
639
  guid: creds.authSecret
640
- instanceID: creds.instanceID
641
640
  })
642
- if creds.instanceID != api.instanceID { // update our client instanceID
643
- creds.instanceID = api.instanceID
644
- `(error) = connector.vault.updateResource(resID, creds)
645
- }
646
- }
647
- }
648
- }
641
+ `(error) = api.connect()
642
+ if !error
643
+ connector.apis[creds.urlName] = api
644
+ } } }
649
645
  if error
650
646
  list(error)
651
647
  else if service == "NideTerminal" {
@@ -653,11 +649,11 @@ closure psmcFsConnector(psm, api, local connClassID, connector, watch) {
653
649
  return (list(Error("NideTerminal not supported in this environment")))
654
650
  list(false, App.nide.track.spawn(App.nide.registerRemote(api),
655
651
  args.0, // terminal display name
656
- args.1)) // options:
657
- // {
658
- // workerID: "NideServer" -- for main thread; other strings for worker threads
659
- // type: "My Remotes" -- display name of terminal group; e.g. URL
660
- // }
652
+ merge(args.1, {
653
+ serverID: api.serverID // server we found
654
+ // workerID: "NideServer" -- for main thread; other strings for worker threads
655
+ // type: "My Remotes" -- display name of terminal group; e.g. URL
656
+ }))) // options:
661
657
  }
662
658
  else if service == "NideHostAPI"
663
659
  list(false, api) // connect to the Host API
@@ -52,7 +52,7 @@ closure RelayCon(imp, options, local relay, nlregex)
52
52
  serverID: "Workers"
53
53
  workerID: "NideServer"
54
54
  }, options.config)
55
- relay.instanceID = UUID()
55
+ relay.instanceID = imp.getUUID("RelayCon(${options.name}) instanceID")
56
56
  relay.exec = execsMod.ExecutorBase(false, "Host", options.name)
57
57
  nlregex = RegExp("\\n", "g")
58
58
 
@@ -247,17 +247,21 @@ macro LoadComponentOnDemand(functionKeys, componentPath, local modobj, key) {
247
247
  macro LiveExport() {
248
248
  global()
249
249
  closure (exporterMod, local importList) {
250
+ if !exporterMod
251
+ return (false) // no module (e.g. build time)
250
252
  importList = []
251
253
  //
252
254
  // LiveImport
253
- // Return a new LiveImport function to be exported by the module who called MakeLiveImport.
255
+ // Return a new LiveImport function to be exported by the module who called LiveExport.
254
256
  //
255
- macro LiveImport(fixproc, local importingMod, mdex, updater) {
257
+ macro LiveImport(fixproc, local importingMod, item, updater) {
256
258
  importingMod = car(nsrights().lookup("module"))
257
- mdex = importList.indexOf(importingMod)
258
- if mdex >= 0
259
- updater = importList[mdex] // already registered
260
- else {
259
+ for item in importList
260
+ if item.proc.1.namespace === importingMod.namespace {
261
+ updater = item
262
+ break
263
+ }
264
+ if !updater {
261
265
  updater = closure(importingMod, fixproc) { // create new updater
262
266
  putproc(compress(updateImports), function updateImports(local goback) {
263
267
  if importingMod !== exporterMod {
@@ -267,10 +271,10 @@ macro LiveExport() {
267
271
  try {
268
272
  call(fixproc, exporterMod) // let caller do any fixups
269
273
  } catch {
270
- if (true)
271
- debuglog("LiveImport fixup failed in", nsrights(), "exception:", exception)
274
+ debuglog("LiveImport fixup failed in", nsrights(), "exception:", exception)
275
+ } finally {
276
+ goback()
272
277
  }
273
- goback()
274
278
  })
275
279
  updateImports
276
280
  } (importingMod, eval(fixproc))
@@ -44,7 +44,7 @@ closure APIServer(options, local server, chroot) {
44
44
  server.guid = options.guid
45
45
  server.notifyq = []
46
46
  server.responseq = []
47
- server.instanceID = UUID()
47
+ server.instanceID = App.imp.getUUID("APIServer instanceID")
48
48
  options = merge({
49
49
  relpath: ""
50
50
  name: "NaanServer"
@@ -126,7 +126,6 @@ closure APIServer(options, local server, chroot) {
126
126
  return (list(error))
127
127
  }
128
128
  server.hostfs = hostfs
129
- server.workco = workerMod.WorkerController()
130
129
  server.Register(server.workco.serverID, server.workco)
131
130
 
132
131
  list(false, port)
@@ -124,6 +124,7 @@ function nodrInit(local manifest) {
124
124
  throw("module frameworks/node cannot be used from a browser")
125
125
  Naan.module.build(module.id, "node", function(modobj, compobj) {
126
126
  require("../common/").LiveImport()
127
+ require("../common/events.nlg")
127
128
  commonWatching = require("../common/watching.nlg")
128
129
  compobj.manifest = manifest
129
130
  function nodrReload() {
@@ -102,8 +102,9 @@ closure ptyManagerMain(local ptym, pty) {
102
102
  //
103
103
  // Close the pty manager, killing any open spawned processes.
104
104
  //
105
- ptym.close = closure close() {
106
- // ### kill any open spawned processes
105
+ ptym.close = closure close(local worker) {
106
+ for worker in ptym.workers
107
+ worker.kill()
107
108
  }
108
109
 
109
110
  // spawn
@@ -111,14 +112,16 @@ closure ptyManagerMain(local ptym, pty) {
111
112
  // Spawn a new pty process, returning a result tuple. If executable is omitted then a shell is
112
113
  // spawned.
113
114
  //
114
- // options:
115
+ // options: (all optional)
115
116
  // {
116
- // workerGUID: <string> // if specified, kills pty process when worker terminates
117
+ // cwd: <string> // current working directory
118
+ // env: <string> // environment
119
+ // raw: <boolean> // enable raw mode with ioctls
117
120
  // }
118
121
  //
119
122
  //
120
123
  ptym.spawn = closure spawn(executable, args, notify, options,
121
- local ptySpawned, ptypro) {
124
+ local error, ptySpawned, ptypro) {
122
125
 
123
126
  if !executable {
124
127
  if os.platform() == "win32"
@@ -136,6 +139,10 @@ closure ptyManagerMain(local ptym, pty) {
136
139
  env: js.g.process.env
137
140
  }, options)
138
141
 
142
+ `(error) = open() // ensure we're open
143
+ if error
144
+ return (list(error))
145
+
139
146
  ptySpawned = pty.spawn(executable, args, { // spawn the pty process
140
147
  name: options.name
141
148
  cols: options.cols
@@ -147,7 +154,6 @@ closure ptyManagerMain(local ptym, pty) {
147
154
  ptypro = ptyProcess(ptySpawned, notify)
148
155
  ptym.workers.push({ // track all pty processes
149
156
  pid: ptySpawned.pid
150
- workerGUID: options.workerGUID || undefined
151
157
  ptySpawned: ptySpawned
152
158
  })
153
159
 
@@ -160,19 +166,6 @@ closure ptyManagerMain(local ptym, pty) {
160
166
  ptypro.killed(event)
161
167
  })
162
168
 
163
- if options.workerGUID
164
- WorkerController().watcher.watch(
165
- function(action, worker, local ptydex) { // worker-owner of pty process died
166
- if action == "terminated" {
167
- ptydex = ptym.workers.findIndex(function(item) {
168
- options.workerGUID == item.workerGUID
169
- })
170
- if ptydex >= 0 {
171
- ptySpawned.kill()
172
- ptym.workers.splice(ptydex)
173
- }
174
- }
175
- })
176
169
  list(false, ptypro)
177
170
  }
178
171
 
@@ -238,7 +231,14 @@ closure ptyProcess(ptySpawned, notify, local ptyp) {
238
231
  // Kill the spawned process.
239
232
  //
240
233
  ptyp.kill = closure kill(signame) {
241
- ptySpawned.kill(signame)
234
+ if signame
235
+ ptySpawned.kill(signame) // use caller signal
236
+ else {
237
+ ptySpawned.kill("SIGTERM") // SIGTERM/SIGKILL sequence
238
+ sleep(1000)
239
+ if ptySpawned
240
+ ptySpawned.kill("SIGKILL")
241
+ }
242
242
  }
243
243
 
244
244
  // finis
@@ -268,7 +268,7 @@ closure ptyManagerWorker(local ptyw, mainContext, mainPty) {
268
268
  }
269
269
 
270
270
  if !mainContext {
271
- `(error, main) = require("naanlib:frameworks/running/mainthread.nlg").MainThread()
271
+ `(error, main) = require("naanlib:frameworks/running/remote_req.nlg").MainThread()
272
272
  if !error
273
273
  `(error, mainContext) = main.context()
274
274
  if error
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * column positioning: // // !
8
8
  *
9
- * Copyright (c) 2024-2025 by Richard C. Zulch
9
+ * Copyright (c) 2024-2026 by Richard C. Zulch
10
10
  *
11
11
  */
12
12
 
@@ -28,7 +28,7 @@
28
28
  */
29
29
 
30
30
  closure ShellConnect(options, local shob, error, fs, xparser, shelly) {
31
- global(js, compress)
31
+ global(js, compress, App)
32
32
  shob = new(object, this)
33
33
 
34
34
  // readline
@@ -78,6 +78,26 @@ closure ShellConnect(options, local shob, error, fs, xparser, shelly) {
78
78
  pending.wait()
79
79
  }
80
80
 
81
+ // pty
82
+ //
83
+ // Execute a shell command in a PTY terminal with optional current-working-directory.
84
+ //
85
+ shob.pty = closure pty(cmd, args, cwd, local exec, error, options, ptyp) {
86
+ exec = App.exec
87
+ if !exec
88
+ `(error, exec) = App.workerNub.execProxy()
89
+ if !error {
90
+ options = { input:"keyboard", output:"display", raw:true }
91
+ if cwd
92
+ options.spawn = { cwd: cwd }
93
+ `(error, ptyp) = exec.subprocess(cmd, args, options)
94
+ }
95
+ if ptyp
96
+ list(false, ptyp)
97
+ else
98
+ exec(cmd, args, cwd)
99
+ }
100
+
81
101
  // shellparser
82
102
  // intercept command-line parsing and look for a !shell escape
83
103
  function shellparser(source, grammar, operators, local token, text) {
@@ -89,7 +109,10 @@ closure ShellConnect(options, local shob, error, fs, xparser, shelly) {
89
109
  atom: `;;
90
110
  loc: tuple(0, text.length)
91
111
  })
92
- exec("bash", ["-c", text], js.d) // default directory: js.d
112
+ if text == "\n"
113
+ pty()
114
+ else
115
+ exec("bash", ["-c", text], js.d) // default directory: js.d
93
116
  }
94
117
  else {
95
118
  source.tokenpush(token)