@naanlang/naan 1.0.7 → 1.0.8

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 (36) hide show
  1. package/LICENSE.md +3 -4
  2. package/README.md +20 -2
  3. package/bin/index.js +2 -2
  4. package/dist/env_web.js +86 -17
  5. package/dist/naan.min.js +7 -7
  6. package/frameworks/browser/browser.nlg +26 -2
  7. package/frameworks/browser/sworker.js +17 -17
  8. package/frameworks/browser/workers.nlg +7 -0
  9. package/frameworks/client/psm_client.nlg +1 -0
  10. package/frameworks/common/common.nlg +33 -5
  11. package/frameworks/node/filesystem.nlg +32 -26
  12. package/frameworks/node/gitter.nlg +9 -4
  13. package/frameworks/node/https_request.nlg +19 -14
  14. package/frameworks/project/build.nlg +177 -68
  15. package/frameworks/project/projects.nlg +1 -1
  16. package/frameworks/running/running.nlg +32 -10
  17. package/frameworks/storage/psm.nlg +20 -4
  18. package/lib/browser/env_web.js +90 -21
  19. package/lib/core/naanlib.js +7 -7
  20. package/package.json +1 -1
  21. package/plugins/serviceAws/aws/aws-sdk-node.min.js +1 -1
  22. package/plugins/serviceAws/aws/aws-sdk.min.js +1 -1
  23. package/plugins/serviceAws/aws/lambda_ws_init.nlg +2 -1
  24. package/plugins/serviceAws/aws_dynamo.nlg +27 -20
  25. package/plugins/serviceAws/aws_dynextra.nlg +110 -5
  26. package/plugins/serviceAws/aws_lambda.nlg +4 -8
  27. package/plugins/serviceAws/aws_sqs.nlg +113 -0
  28. package/plugins/serviceAws/serviceAws.nlg +1 -1
  29. package/plugins/serviceYC/generic_api.yaml +36 -0
  30. package/plugins/serviceYC/naanide-relay-index.js +148 -0
  31. package/plugins/serviceYC/serviceYC.nlg +59 -0
  32. package/plugins/serviceYC/yc_function.nlg +161 -0
  33. package/test/test_01_core.nlg +2 -2
  34. package/test/test_02_context.nlg +2 -2
  35. package/test/test_05_strings.nlg +11 -1
  36. package/test/test_06_lingoparse.nlg +43 -14
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * column positioning: // // !
8
8
  *
9
- * Copyright (c) 2020-2021 by Richard C. Zulch
9
+ * Copyright (c) 2020-2023 by Richard C. Zulch
10
10
  *
11
11
  */
12
12
 
@@ -69,6 +69,29 @@ closure FileDownload(file, progress, local error, blob, sizez, url, link) {
69
69
  };
70
70
 
71
71
 
72
+ /*
73
+ * Platform
74
+ *
75
+ * Return a string identifying the platform our browser is running on, or false if unknown.
76
+ *
77
+ */
78
+
79
+ function Platform(local agent, patterns, key, rx) {
80
+ agent = window.navigator.userAgent.toLowerCase()
81
+ patterns = {
82
+ macos: RegExp("macintosh|macintel|macppc|mac68k|macos")
83
+ windows: RegExp("win32|win64|windows|wince")
84
+ ios: RegExp("iphone|ipad|ipod")
85
+ android: RegExp("android")
86
+ linux: RegExp("linux")
87
+ }
88
+ for `(key, rx) in patterns
89
+ if rx.test(agent)
90
+ return (key)
91
+ false
92
+ };
93
+
94
+
72
95
  /*
73
96
  * brorInit
74
97
  *
@@ -78,13 +101,14 @@ closure FileDownload(file, progress, local error, blob, sizez, url, link) {
78
101
  */
79
102
 
80
103
  function brorInit(local manifest) {
81
- manifest = `(FileReader, FileDownload, brorInit)
104
+ manifest = `(FileReader, FileDownload, Platform, brorInit)
82
105
 
83
106
  Naan.module.build(module.id, "browser", function(modobj, compobj) {
84
107
  require("../common").LiveImport()
85
108
  compobj.manifest = manifest
86
109
  modobj.exports.FileReader = FileReader
87
110
  modobj.exports.FileDownload = FileDownload
111
+ modobj.exports.Platform = Platform
88
112
 
89
113
  function brorReload() {
90
114
  window = js.w
@@ -36,7 +36,7 @@
36
36
  *
37
37
  */
38
38
 
39
- var CurrentCacheName = "Naanlang-1.0.7+2";
39
+ var CurrentCacheName = "Naanlang-1.0.8+1";
40
40
 
41
41
 
42
42
  //
@@ -89,11 +89,11 @@ var waitingForInit = []; // initialization functions, or
89
89
  var pubVersion = event.data.hereIsMyVersion;
90
90
  var sourceId = event.source.id; // client id of sender of message
91
91
  msgPorts[sourceId] = msgport;
92
- console.log("[1.0.7+2] received new msgport for", sourceId, pubID, "-", pubVersion);
93
- if (pubVersion != "1.0.7+2")
92
+ console.log("[1.0.8+1] received new msgport for", sourceId, pubID, "-", pubVersion);
93
+ if (pubVersion != "1.0.8+1")
94
94
  msgport.postMessage({ // notify new version available
95
95
  id: "upgrade",
96
- version: "1.0.7+2"
96
+ version: "1.0.8+1"
97
97
  });
98
98
  Reaper(); // clean up obsolete info
99
99
 
@@ -107,7 +107,7 @@ var waitingForInit = []; // initialization functions, or
107
107
  if (msg.id == "response")
108
108
  processResponse(msg);
109
109
  else if (msg.id == "text")
110
- console.log("[1.0.7+2] msg received:", msg.text);
110
+ console.log("[1.0.8+1] msg received:", msg.text);
111
111
  };
112
112
 
113
113
  // send text to IDE log
@@ -118,7 +118,7 @@ var waitingForInit = []; // initialization functions, or
118
118
  // don't clutter the log
119
119
  msgport.postMessage({
120
120
  id: "text",
121
- text: "port received by 1.0.7+2",
121
+ text: "port received by 1.0.8+1",
122
122
  });
123
123
  */
124
124
  if (--pending === 0)
@@ -135,7 +135,7 @@ var waitingForInit = []; // initialization functions, or
135
135
  includeUncontrolled: true
136
136
  }).then(function(clientList) {
137
137
  clientList.every(function(client) {
138
- console.log("[1.0.7+2] requesting new msgport for", client.id);
138
+ console.log("[1.0.8+1] requesting new msgport for", client.id);
139
139
  ++pending;
140
140
  client.postMessage({ // tell client(s) we need this fetch source
141
141
  msg: "Naan_need_fetch_port",
@@ -181,12 +181,12 @@ function Reaper() {
181
181
  clients[clientList[clidex].id] = clientList[clidex];
182
182
  for (var sourceId in msgPorts)
183
183
  if (!clients[sourceId]) {
184
- console.log("[1.0.7+2] source gone:", sourceId);
184
+ console.log("[1.0.8+1] source gone:", sourceId);
185
185
  delete msgPorts[sourceId]; // no longer a source
186
186
  }
187
187
  for (var clientId in fetchPorts)
188
188
  if (!clients[clientId]) {
189
- console.log("[1.0.7+2] client gone:", clientId);
189
+ console.log("[1.0.8+1] client gone:", clientId);
190
190
  delete fetchPorts[clientId]; // no longer a client
191
191
  }
192
192
  for (var fqdex = 0; fqdex < fetchQueue.length; ++fqdex) {
@@ -220,13 +220,13 @@ function ClearCaches() {
220
220
  return (Promise.all(
221
221
  cacheNames.map(function(cacheName) {
222
222
  if (cacheName != CurrentCacheName) {
223
- console.log('[1.0.7+2] deleting old cache:', cacheName);
223
+ console.log('[1.0.8+1] deleting old cache:', cacheName);
224
224
  return (caches.delete(cacheName));
225
225
  }
226
226
  })
227
227
  ));
228
228
  }).then(function() { // claim all clients
229
- console.log('[1.0.7+2] claiming clients');
229
+ console.log('[1.0.8+1] claiming clients');
230
230
  return (self.clients.claim());
231
231
  });
232
232
  return (promise);
@@ -269,7 +269,7 @@ function GetClientResponse(event, urlpath) {
269
269
  msgport.postMessage({
270
270
  id: "fetch",
271
271
  seq: seqno,
272
- version: "1.0.7+2",
272
+ version: "1.0.8+1",
273
273
  request: {
274
274
  method: event.request.method,
275
275
  url: event.request.url
@@ -317,7 +317,7 @@ function GetClientResponse(event, urlpath) {
317
317
  */
318
318
 
319
319
  self.addEventListener('install', function(event) {
320
- console.log("[1.0.7+2] install");
320
+ console.log("[1.0.8+1] install");
321
321
  self.skipWaiting();
322
322
  });
323
323
 
@@ -339,7 +339,7 @@ self.addEventListener('fetch', function(event) {
339
339
  var promise;
340
340
  var url = new URL(event.request.url);
341
341
  var nocache = event.request.method != "GET"
342
- || url.search.length !== 0 && url.searchParams.get("naanver") !== "cb-1.0.7+2"
342
+ || url.search.length !== 0 && url.searchParams.get("naanver") !== "09e820a5a47c4b099bacaa5d8a7d3f7a"
343
343
  || event.request.headers.get('range');
344
344
  if (url.pathname.startsWith("/run/")) {
345
345
  nocache = true;
@@ -356,7 +356,7 @@ self.addEventListener('fetch', function(event) {
356
356
  }
357
357
  else
358
358
  promise = fetch(event.request).catch(function (e) {
359
- console.log("[1.0.7+2] fetch failed", e);
359
+ console.log("[1.0.8+1] fetch failed", e);
360
360
  return (new Response(undefined, {
361
361
  status: 404,
362
362
  statusText: "Fetch Failed"
@@ -385,14 +385,14 @@ self.addEventListener('fetch', function(event) {
385
385
  */
386
386
 
387
387
  self.addEventListener('activate', function(event) {
388
- console.log("[1.0.7+2] activate");
388
+ console.log("[1.0.8+1] activate");
389
389
  self.clients.matchAll({ // for debugging, list controlled clients
390
390
  includeUncontrolled: true
391
391
  }).then(function(clientList) {
392
392
  var urls = clientList.map(function(client) {
393
393
  return (client.url);
394
394
  });
395
- console.log('[1.0.7+2] matching clients:', urls.join(', '));
395
+ console.log('[1.0.8+1] matching clients:', urls.join(', '));
396
396
  });
397
397
  var promise = ClearCaches();
398
398
  if (event.waitUntil)
@@ -56,6 +56,7 @@ closure ServiceWorker(pubID, pubVersion, local serv, callback) {
56
56
  })
57
57
  } else if msg.id == "upgrade" {
58
58
  if serv.upgrade != msg.version {
59
+ debuglog("service worker upgrade:", serv.upgrade, "to", msg.version)
59
60
  serv.upgrade = msg.version // only report once
60
61
  callback(false, {
61
62
  message: "upgrade"
@@ -134,6 +135,12 @@ closure ServiceWorker(pubID, pubVersion, local serv, callback) {
134
135
  serv.sw = serv.reg.installing // worker version was updated
135
136
  updateReg()
136
137
  })
138
+ reg.addEventListener("statechange", function() {
139
+ debuglog("service worker state change:", serv.reg.state)
140
+ })
141
+ reg.addEventListener("controllerchange", function() {
142
+ debuglog("service worker controller change:", serv.upgrade)
143
+ })
137
144
  result = makeResult(false, {
138
145
  message: "opened"
139
146
  })
@@ -63,6 +63,7 @@ closure psmcFsView(api, rootpath, local view, pathmod) {
63
63
  pathmod = JSpath.win32
64
64
  else
65
65
  pathmod = JSpath.posix
66
+ view.path.sep = pathmod.sep
66
67
  false
67
68
  }
68
69
  }
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * column positioning: // // !
8
8
  *
9
- * Copyright (c) 2020-2022 by Richard C. Zulch
9
+ * Copyright (c) 2020-2023 by Richard C. Zulch
10
10
  *
11
11
  */
12
12
 
@@ -96,6 +96,27 @@ function UUID(local rando, cc) {
96
96
  };
97
97
 
98
98
 
99
+ /*
100
+ * VersionCheck
101
+ *
102
+ * Check if the test version is new enough compared to the reference version. This returns false
103
+ * if the test version is out of date, or the difference between the build numbers otherwise, which
104
+ * is positive if the test is larger than the reference.
105
+ *
106
+ */
107
+
108
+ function VersionCheck(testv, refv, local rxver, test, ref) {
109
+ rxver = RegExp("([0-9]+)[.]([0-9]+)[.]([0-9]+)-?[A-Za-z_]*[+]?([0-9]+)")
110
+ function numerify(x){ Number.parseInt(x) }
111
+ test = testv.match(rxver).map(numerify.proc)
112
+ ref = refv.match(rxver).map(numerify.proc)
113
+ if test.1 == ref.1 && test.2 == ref.2 && test.3 == ref.3
114
+ test.4 - ref.4 // build number difference
115
+ else
116
+ false
117
+ };
118
+
119
+
99
120
  /*
100
121
  * JsonParse
101
122
  *
@@ -303,8 +324,8 @@ JSONparse = false;
303
324
  Uint8ArrayFromString = false;
304
325
 
305
326
  function comrInit(local manifest) {
306
- manifest = `(EncodeQuery, ContentTypeFromFileExt, UUID, JsonParse, JsonStringify, JsLoadScript,
307
- LoadComponentOnDemand, LiveExport, comrInit)
327
+ manifest = `(EncodeQuery, ContentTypeFromFileExt, UUID, VersionCheck, JsonParse, JsonStringify,
328
+ JsLoadScript, LoadComponentOnDemand, LiveExport, comrInit)
308
329
 
309
330
  Naan.module.build(module.id, "common", closure(modobj, compobj) {
310
331
  compobj.manifest = manifest
@@ -477,12 +498,18 @@ function comrInit(local manifest) {
477
498
  //
478
499
  // binary to Base64
479
500
  EncodeBase64 = function nodejsEncodeBase64(data) {
480
- wsg.Buffer.from(data, "binary").toString("base64")
501
+ if data
502
+ wsg.Buffer.from(data, "binary").toString("base64")
503
+ else
504
+ ""
481
505
  }
482
506
  //
483
507
  // Base64 to binary
484
508
  DecodeBase64 = function nodejsDecodeBase64(data) {
485
- wsg.Buffer.from(data, "base64").toString("binary")
509
+ if data
510
+ wsg.Buffer.from(data, "base64").toString("binary")
511
+ else
512
+ xnew(wsg.Buffer, "") // empty buffer
486
513
  }
487
514
  if !crypto
488
515
  crypto = js.r("crypto")
@@ -535,6 +562,7 @@ function comrInit(local manifest) {
535
562
  modobj.exports.JSONparse = JSONparse
536
563
  modobj.exports.JsonStringify = JsonStringify
537
564
  modobj.exports.JsonParse = JsonParse
565
+ modobj.exports.VersionCheck = VersionCheck
538
566
  modobj.exports.Uint8ArrayFromString = Uint8ArrayFromString
539
567
  modobj.exports.EncodeBase64url = EncodeBase64url
540
568
  modobj.exports.DecodeBase64url = DecodeBase64url
@@ -567,7 +567,7 @@ closure Filesystem(rootpath, local files, badCreatePathRegEx) {
567
567
  // info for each file as well.
568
568
 
569
569
  files.dirList = closure dirList(path, options, callback, local error, localpath, output, nodelist, file) {
570
- if path == "" && js.g.process.platform == "win32" && rootpath == "\\"
570
+ if js.g.process.platform == "win32" && rootpath == "\\" && (path == "" || path == "\\")
571
571
  return (files.winDrives(callback)) // top level is drive letters in Windows
572
572
  if !callback
573
573
  return (syncAdapter(dirList, path, options))
@@ -867,31 +867,37 @@ closure Filesystem(rootpath, local files, badCreatePathRegEx) {
867
867
  if !callback
868
868
  return (syncAdapter(reveal, path))
869
869
 
870
- function addpath(path, local error, localpath) {
871
- `(error, localpath) = localPath(path)
872
- if error
873
- errors.push(error)
874
- else
875
- pathargs.push("file://localhost".concat(localpath))
876
- }
877
-
878
- errors = []
879
- pathargs = ["-R", "--"] // reveal, then stop using '-' for ags
880
- if array(path)
881
- for item in path
882
- addpath(item)
883
- else
884
- addpath(path)
885
- nodecp.execFile("open",
886
- pathargs, // command-line options
887
- { }, // execution options
888
- function(err, stdout, stderr) {
889
- if err
890
- callback(Error("open failed", err, stderr))
891
- else
892
- callback(false, errors)
893
- }
894
- )
870
+ if js.g.process.platform == "win32" { // ### windows only allows one path
871
+ nodecp.exec('explorer.exe /select,"'.concat(path, '"'), function(err, stdout, stderr) {
872
+ callback(false, { ok: true }) // reports failure even if it works
873
+ })
874
+ } else {
875
+ function addpath(path, local error, localpath) {
876
+ `(error, localpath) = localPath(path)
877
+ if error
878
+ errors.push(error)
879
+ else
880
+ pathargs.push("file://localhost".concat(localpath))
881
+ }
882
+
883
+ errors = []
884
+ pathargs = ["-R", "--"] // reveal, then stop using '-' for ags
885
+ if array(path)
886
+ for item in path
887
+ addpath(item)
888
+ else
889
+ addpath(path)
890
+ nodecp.execFile("open",
891
+ pathargs, // command-line options
892
+ { }, // execution options
893
+ function(err, stdout, stderr) {
894
+ if err
895
+ callback(Error("open failed", err, stderr))
896
+ else
897
+ callback(false, errors)
898
+ }
899
+ )
900
+ }
895
901
  }
896
902
 
897
903
  //
@@ -76,10 +76,15 @@ closure Gitter(fs, local gitt) {
76
76
  // Compute the bridge path to an absolute repopath (which can point inside a repo) from the
77
77
  // phyiscal repo root. If these are the same, or an error occurs, then the result is "".
78
78
  //
79
- function bridgePath(repopath, local top) {
80
- top = repoRoot(repopath).1
81
- if top && repopath.startsWith(top) && repopath.length > top.length
82
- top = repopath.slice(top.length+1).concat(fs.path.sep) // move leading "/" of bridge path to trailing
79
+ function bridgePath(repopath, local above) {
80
+ above = repoRoot(repopath).1
81
+ if above
82
+ above = fs.path.normalize(above)
83
+ if above && repopath.startsWith(above) && repopath.length > above.length {
84
+ above = fs.path.relative(above, repopath).split(fs.path.sep).join("/")
85
+ if above != ""
86
+ above = above.concat("/")
87
+ }
83
88
  else
84
89
  "" // we are looking at the root, or an error
85
90
  }
@@ -23,6 +23,7 @@
23
23
  * contentType: <string> // sets Content-Type header, otherwise auto-determined
24
24
  * range: <string> // sets range header
25
25
  * headers: [`(key, value)] // add header(s) to the request, overriding defaults
26
+ * debug: <boolean> // log errors and status results
26
27
  * }
27
28
  *
28
29
  */
@@ -52,25 +53,27 @@ closure HttpsApiRequest(url, options, local urlq, reqOptions, putdata, item, pen
52
53
  if error
53
54
  return (list(Error("HttpsApiRequest encode:", url)))
54
55
  }
55
- fetchOptions.body = putdata
56
+ reqOptions.body = putdata
56
57
  }
57
58
  if array(options.headers)
58
59
  for item in options.headers
59
60
  reqOptions.headers[item.0] = item.1
60
61
  pending = new(nonce)
61
62
  chunks = []
62
- request = nodeHttps.request(url, reqOptions, function (response) {
63
- if response.statusCode < 200 || response.statusCode >= 300 {
64
- pending.signal(list(Error("HttpsApiRequest statusCode:", url, response.statusCode, {
65
- status: response.statusCode
66
- })))
67
- return
68
- }
63
+ request = nodeHttps.request(url, reqOptions, closure (response) {
69
64
  response.on("data", function (chunk) {
70
65
  chunks.push(chunk)
71
66
  })
72
67
  response.on("end", function (local content, error) {
73
- content = Buffer.concat(chunks)
68
+ content = js.g.Buffer.concat(chunks)
69
+ if response.statusCode < 200 || response.statusCode >= 300 {
70
+ if options.debug
71
+ debuglog("HttpsApiRequest status:", url, response.statusCode, "message:", content)
72
+ pending.signal(list(Error("HttpsApiRequest statusCode:", url, response.statusCode, {
73
+ status: response.statusCode
74
+ })))
75
+ return
76
+ }
74
77
  if response.complete {
75
78
  if response.headers["content-type"].startsWith("application/json") {
76
79
  `(error, content) = JsonParse(content.toString())
@@ -86,16 +89,18 @@ closure HttpsApiRequest(url, options, local urlq, reqOptions, putdata, item, pen
86
89
  }
87
90
  }
88
91
  else
89
- error = Error("HttpsApiRequest terminated prematurely:", url)
92
+ error = Error("HttpsApiRequest terminated prematurely:", url, response.statusCode)
90
93
  pending.signal(list(error, content))
91
94
  })
92
95
  })
93
- request.on("error", function(error) {
96
+ request.on("error", function hre(error) {
97
+ if options.debug
98
+ debuglog("HttpsApiRequest error:", url, "error:", error)
94
99
  error = Error("HttpsApiRequest failed:", url, error)
95
100
  pending.signal(list(error))
96
101
  })
97
- if data
98
- request.write(data)
102
+ if putdata
103
+ request.write(putdata)
99
104
  request.end()
100
105
  pending.wait()
101
106
  };
@@ -109,7 +114,7 @@ closure HttpsApiRequest(url, options, local urlq, reqOptions, putdata, item, pen
109
114
  */
110
115
 
111
116
  function https_nodeInit(local manifest) {
112
- manifest = `(HttpsGetJson, HttpsPutJson, https_nodeInit)
117
+ manifest = `(HttpsApiRequest, https_nodeInit)
113
118
 
114
119
  Naan.module.build(module.id, "https_request", function(modobj, compobj) {
115
120
  require("./node.nlg")