@naanlang/naan 1.0.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 (98) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +46 -0
  3. package/dist/env_web.js +431 -0
  4. package/dist/naan.min.js +73 -0
  5. package/frameworks/browser/browser.nlg +30 -0
  6. package/frameworks/browser/pouchdb/pouchdb.min.js +7 -0
  7. package/frameworks/browser/spark-md5/spark-md5.min.js +1 -0
  8. package/frameworks/browser/sworker.js +192 -0
  9. package/frameworks/browser/terminals.nlg +787 -0
  10. package/frameworks/browser/workers.nlg +386 -0
  11. package/frameworks/client/apiclient.nlg +183 -0
  12. package/frameworks/client/client.nlg +29 -0
  13. package/frameworks/client/psm_client.nlg +572 -0
  14. package/frameworks/common/common.nlg +464 -0
  15. package/frameworks/common/preferences.nlg +131 -0
  16. package/frameworks/common/repltools.nlg +100 -0
  17. package/frameworks/common/watching.nlg +97 -0
  18. package/frameworks/node/apiserver.nlg +399 -0
  19. package/frameworks/node/filesystem.nlg +1012 -0
  20. package/frameworks/node/gitter.nlg +234 -0
  21. package/frameworks/node/node.nlg +81 -0
  22. package/frameworks/node/psm_server.nlg +465 -0
  23. package/frameworks/node/worker.nlg +560 -0
  24. package/frameworks/project/build.nlg +1229 -0
  25. package/frameworks/project/jszip.js +30 -0
  26. package/frameworks/project/jszip.nlg +87 -0
  27. package/frameworks/project/proj_cliser.nlg +139 -0
  28. package/frameworks/project/proj_console.nlg +137 -0
  29. package/frameworks/project/proj_folder.nlg +143 -0
  30. package/frameworks/project/proj_lambda.nlg +137 -0
  31. package/frameworks/project/proj_static.nlg +138 -0
  32. package/frameworks/project/project.nlg +29 -0
  33. package/frameworks/project/projects.nlg +587 -0
  34. package/frameworks/project/uglifyjs.js +1 -0
  35. package/frameworks/project/uglifyjs.nlg +79 -0
  36. package/frameworks/running/debugcom.nlg +163 -0
  37. package/frameworks/running/debugnub.nlg +565 -0
  38. package/frameworks/running/debugutil.nlg +510 -0
  39. package/frameworks/running/executors.nlg +767 -0
  40. package/frameworks/running/running.nlg +151 -0
  41. package/frameworks/running/sourcecode.nlg +346 -0
  42. package/frameworks/running/taskexec.nlg +196 -0
  43. package/frameworks/storage/dbt_pouch.nlg +773 -0
  44. package/frameworks/storage/file_manager.nlg +772 -0
  45. package/frameworks/storage/psm.nlg +326 -0
  46. package/frameworks/storage/psm_dbtables.nlg +814 -0
  47. package/frameworks/storage/resources.nlg +445 -0
  48. package/frameworks/storage/storage.nlg +52 -0
  49. package/lib/browser/env_web.js +431 -0
  50. package/lib/browser/env_webworker.js +146 -0
  51. package/lib/browser/require.js +1653 -0
  52. package/lib/core/naanlib.js +73 -0
  53. package/lib/env_node.js +282 -0
  54. package/lib/env_nodeworker.js +165 -0
  55. package/lib/node_repl.js +25 -0
  56. package/lib/node_repl_init.nlg +52 -0
  57. package/package.json +13 -0
  58. package/plugins/gitClient/clientops.nlg +317 -0
  59. package/plugins/gitClient/gitClient.nlg +63 -0
  60. package/plugins/gitClient/gitutils.nlg +1331 -0
  61. package/plugins/gitClient/minimatch.js +945 -0
  62. package/plugins/gitClient/minimatch_license.txt +15 -0
  63. package/plugins/gitClient/minimatch_readme.md +208 -0
  64. package/plugins/nodeLib/nodeLib.nlg +26 -0
  65. package/plugins/nodeLib/node_cp.nlg +65 -0
  66. package/plugins/nodeLib/node_fs.nlg +137 -0
  67. package/plugins/nodeLib/node_https.nlg +172 -0
  68. package/plugins/nodeLib/node_util.nlg +180 -0
  69. package/plugins/serviceAws/aws/aws-sdk.min.js +88 -0
  70. package/plugins/serviceAws/aws/lambda_rest_index.js +122 -0
  71. package/plugins/serviceAws/aws/lambda_rest_init.nlg +58 -0
  72. package/plugins/serviceAws/aws/lambda_ws_index.js +498 -0
  73. package/plugins/serviceAws/aws/lambda_ws_init.nlg +49 -0
  74. package/plugins/serviceAws/aws_cloudwatchlogs.nlg +122 -0
  75. package/plugins/serviceAws/aws_cognito.nlg +76 -0
  76. package/plugins/serviceAws/aws_dynamo.nlg +509 -0
  77. package/plugins/serviceAws/aws_lambda.nlg +95 -0
  78. package/plugins/serviceAws/aws_s3.nlg +134 -0
  79. package/plugins/serviceAws/aws_utils.nlg +86 -0
  80. package/plugins/serviceAws/dbt_aws.nlg +769 -0
  81. package/plugins/serviceAws/lambda_naan_control.nlg +175 -0
  82. package/plugins/serviceAws/psm_aws.nlg +258 -0
  83. package/plugins/serviceAws/serviceAws.nlg +38 -0
  84. package/plugins/serviceGitHub/gitops.nlg +522 -0
  85. package/plugins/serviceGitHub/psm_github.nlg +205 -0
  86. package/plugins/serviceGitHub/serviceGitHub.nlg +65 -0
  87. package/plugins/serviceGitLab/gitops.nlg +528 -0
  88. package/plugins/serviceGitLab/psm_gitlab.nlg +205 -0
  89. package/plugins/serviceGitLab/serviceGitLab.nlg +65 -0
  90. package/test/harness.nlg +312 -0
  91. package/test/node_test.js +33 -0
  92. package/test/test_01_core.nlg +768 -0
  93. package/test/test_02_context.nlg +269 -0
  94. package/test/test_03_jsinterop.nlg +137 -0
  95. package/test/test_04_numerics.nlg +450 -0
  96. package/test/test_05_strings.nlg +63 -0
  97. package/test/test_06_lingoparse.nlg +500 -0
  98. package/test/test_07_lingo.nlg +623 -0
@@ -0,0 +1,386 @@
1
+ /*
2
+ * workers.nlg
3
+ * Naanlib/frameworks/browser
4
+ *
5
+ * Service worker and worker pools for the browser.
6
+ *
7
+ * column positioning: // // !
8
+ *
9
+ * Copyright (c) 2020-2021 by Richard C. Zulch
10
+ *
11
+ */
12
+
13
+
14
+ /*
15
+ * ServiceWorker
16
+ *
17
+ * Manage the service worker lifecycle.
18
+ *
19
+ */
20
+
21
+ closure ServiceWorker(local serv, callback) {
22
+ serv = new(object, this)
23
+
24
+ //
25
+ // updateReg
26
+ //
27
+ // Registration has updated the service worker, so reestablish communication with the new one.
28
+
29
+ closure updateReg(local mchan) {
30
+ if !serv.sw
31
+ return
32
+ mchan = xnew(js.w.MessageChannel)
33
+ serv.msgport = mchan.port2
34
+ serv.msgport.onmessage = workerMsg.proc
35
+ serv.sw.postMessage({ hereIsYourPort: mchan.port1 }, [mchan.port1])
36
+ }
37
+
38
+ //
39
+ // workerMsg
40
+ //
41
+ // A message has come in from the service worker.
42
+ //
43
+
44
+ closure workerMsg(msg) {
45
+ msg = msg.data
46
+ if msg.id == "fetch" { // fetching a resource for the page
47
+ callback(false, {
48
+ message: "fetch"
49
+ seq: msg.seq
50
+ request: msg.request
51
+ version: msg.version
52
+ })
53
+ } else if msg.id == "text"
54
+ debuglog("sw[".concat(serv.scope, "]: "), msg.text) // handy remote debug capability
55
+ }
56
+
57
+ //
58
+ // defaultCB
59
+ //
60
+ // Default callback if one is not specified.
61
+
62
+ closure defaultCB(error, data) {
63
+ if error
64
+ return (ErrorDebugLog("service worker error", error))
65
+ debuglog("service worker", serv.scope.concat(":"), data.message, data.request.method, data.request.url)
66
+ if data.message == "fetch" {
67
+ serv.msgport.postMessage({
68
+ id: "response"
69
+ seq: data.seq
70
+ body: "body content stub - ".concat(data.request.method, " - ", data.request.url, " (", data.version, ")")
71
+ init: {
72
+ status: 200,
73
+ statusText: "OK"
74
+ }
75
+ })
76
+ }
77
+ }
78
+
79
+ //
80
+ // reportResult
81
+ //
82
+
83
+ closure makeResult(error, data) {
84
+ callback(error, data)
85
+ list(error, data)
86
+ }
87
+
88
+ //
89
+ // register
90
+ //
91
+ // Register our service worker object for a specific scope.
92
+
93
+ serv.register = closure register(scope, cb, local result) {
94
+ if !cb
95
+ cb = defaultCB
96
+ if serv.reg
97
+ unregister()
98
+ callback = cb
99
+ serv.scope = scope
100
+ if !scope
101
+ return (makeResult(Error("service worker scope required")))
102
+ if !js.w.navigator.serviceWorker
103
+ return (makeResult(Error("service workers not supported")))
104
+ js.w.navigator.serviceWorker.addEventListener("message", function(event) {
105
+ if event.data.msg == "Naan_need_fetch_port"
106
+ updateReg()
107
+ })
108
+ await(js.w.navigator.serviceWorker.register("sworker.js", { scope: scope }).then(function (reg) {
109
+ return (reg.update())
110
+ }).then(function (reg) {
111
+ serv.reg = reg
112
+ reg.update()
113
+ if reg.installing
114
+ serv.sw = reg.installing
115
+ else if reg.waiting
116
+ serv.sw = reg.waiting
117
+ else if reg.active
118
+ serv.sw = reg.active
119
+ updateReg()
120
+ reg.addEventListener("updatefound", function() {
121
+ serv.sw = serv.reg.installing // worker version was updated
122
+ updateReg()
123
+ })
124
+ result = makeResult(false, {
125
+ message: "opened"
126
+ })
127
+ }).catch(function (error) {
128
+ result = makeResult(Error("registration failed", error))
129
+ ErrorDebuglog("serv.register failed", result)
130
+ }))
131
+ result
132
+ }
133
+
134
+ //
135
+ // unregister
136
+ //
137
+ // Unregister our service worker.
138
+
139
+ serv.unregister = closure unregister(local result) {
140
+ if !serv.reg
141
+ return (makeResult(Error("already not registered")))
142
+ await(serv.reg.unregister().then(function(success) {
143
+ serv.reg = false // good or bad, don't try again
144
+ callback = defaultCB
145
+ if success
146
+ result = makeResult(false, {
147
+ message: "closed"
148
+ })
149
+ else
150
+ result = makeResult(Error("unregister failed"))
151
+ }))
152
+ result
153
+ }
154
+
155
+ // finis
156
+ serv
157
+ };
158
+
159
+
160
+ /*
161
+ * ScopedServiceWorker
162
+ *
163
+ * This implements service worker with multiple scope support, so that projects can register for
164
+ * a scope of the pathname space of the current website and redirect requests to PSM storage. This is
165
+ * useful for building and then using/testing a "website" in Naanide. For example, a console program
166
+ * can run in a worker thread, interact through the REPL, and access its built data using a SSW.
167
+ *
168
+ * /run/<scope-path>/<filename>
169
+ *
170
+ * The installed JavaScript service worker will only intercept fetch requests with a pathname that
171
+ * begins with /run/.
172
+ * All projects share a single ScopedServiceWorker instance, but each can specify its own scope
173
+ * so that it receives the content requests. This only supports the GET method for the time being.
174
+ *
175
+ */
176
+
177
+ closure ScopedServiceWorker(local scoper, result) {
178
+ scoper = new(object, ScopedServiceWorker)
179
+ scoper.scopes = {}
180
+ scoper.serv = ServiceWorker()
181
+ result = scoper.serv.register("/", closure(error, data, local response, filepath, scope) {
182
+ if data.message == "fetch" {
183
+ response = {
184
+ id: "response"
185
+ seq: data.seq
186
+ init: {
187
+ status: 200,
188
+ statusText: "OK"
189
+ }
190
+ }
191
+
192
+ // bad method
193
+ if data.request.method != "GET" {
194
+ response.init.status = 405
195
+ response.init.statusText = "Method Not Allowed"
196
+ scoper.serv.msgport.postMessage(response)
197
+ return
198
+ }
199
+
200
+ // read resource
201
+ filepath = xnew(js.w.URL, data.request.url).pathname
202
+ filepath = DecodeURIComponent(filepath) // "/run/<scope>/path..."
203
+ filepath = filepath.slice(4) // "/<scope>/path..."
204
+ error = true
205
+ for scope in scoper.scopes {
206
+ if filepath.startsWith(scope) {
207
+ filepath = filepath.slice(scope.length+1) // remove scope including "/"
208
+ `(error, data) = call(scoper.scopes[scope], filepath, scope, response.init)
209
+ break
210
+ }
211
+ }
212
+ if error === true
213
+ debuglog("ScopedServiceWorker: couldn't find scope", scope, "in", totuple(scoper.scopes))
214
+
215
+ // read resource failed
216
+ if error {
217
+ response.errorValue = error
218
+ response.errorText = ErrorString(error)
219
+ response.init.status = 404
220
+ response.init.statusText = "Not Found"
221
+ scoper.serv.msgport.postMessage(response)
222
+ return
223
+ }
224
+
225
+ // read resource succeeded
226
+ response.body = data
227
+ scoper.serv.msgport.postMessage(response)
228
+ return
229
+ }
230
+ })
231
+ if result.0 {
232
+ ErrorDebuglog("ScopedServiceWorker failed", result)
233
+ return (result)
234
+ }
235
+
236
+ // register
237
+ //
238
+ // Register a scope with a pathname. The specified procedure will be called while files are
239
+ // fetched from that location.
240
+
241
+ scoper.register = function register(scope, proc) {
242
+ scoper.scopes[scope] = proc
243
+ }
244
+
245
+ // unregister
246
+ //
247
+ // Unregister a scope pathname.
248
+
249
+ scoper.unregister = function unregister(scope) {
250
+ scoper.scopes[scope] = undefined
251
+ }
252
+
253
+ // destroy
254
+ //
255
+ // Destroy the service worker.
256
+
257
+ worker.destroy = function destroy() {
258
+ scoper.serv.unregister()
259
+ scoper.serv = false
260
+ }
261
+
262
+ // finis
263
+
264
+ list(false, scoper)
265
+ };
266
+
267
+
268
+ /*
269
+ * findTrackedScope
270
+ *
271
+ * Find a tracked scope that matches the specified scope.
272
+ *
273
+ */
274
+
275
+ closure findTrackedScope(track, scope, local exec) {
276
+ for exec in track.enumlist()
277
+ if exec.type == "ServiceWorkers" && exec.name == scope
278
+ return (exec)
279
+ false
280
+ };
281
+
282
+
283
+ /*
284
+ * TrackedScope
285
+ *
286
+ * Create a tracked serviceWorker scope and ensure that our service worker is active. At the
287
+ * present time, if the scope already exists this uses the existing object and does not replace the
288
+ * filesystem used to fulfill requests. Seems like it should work, absent better ideas.
289
+ * As of August 2021, it is evidently impossible for a service worker to learn the Content-Type
290
+ * from the fetch request header, so we infer it from the file extension. All unknown or non-text
291
+ * extensions are assumed to be binary, and all text files are assumed to be UTF-8.
292
+ *
293
+ */
294
+
295
+ closure TrackedScope(track, scope, fs, rootpath, local trope, result) {
296
+ trope = findTrackedScope(track, scope)
297
+ if trope
298
+ return (list(false, trope))
299
+ trope = runningExecutors.ExecutorBase(track, "ServiceWorkers", scope)
300
+ serviceWorker.register(scope, closure(filepath, scope, init,
301
+ local options, mimeType, error, data) {
302
+ mimeType = {
303
+ "css": "text/css",
304
+ "csv": "text/csv",
305
+ "htm": "text/html",
306
+ "html": "text/html",
307
+ "ico": "image/x-icon",
308
+ "ics": "application/octet-stream",
309
+ "jpeg": "image/jpeg",
310
+ "jpg": "image/jpeg",
311
+ "js": "text/javascript",
312
+ "json": "application/json",
313
+ "mp3": "audio/mpeg",
314
+ "mp4": "video/mp4",
315
+ "nlg": "text/plain",
316
+ "npk": "application/json",
317
+ "svg": "image/svg+xml",
318
+ "text": "text/plain",
319
+ "txt": "text/plain",
320
+ "zip": "application/octet-stream"
321
+ }[JSpath.extname(filepath).substring(1)]
322
+ if !mimeType
323
+ mimeType = "application/octet-stream"
324
+ if mimeType.startsWith("text/")
325
+ mimeType = mimeType.concat("; charset=UTF-8")
326
+ else
327
+ options = { encoding: "binary" }
328
+ init.headers = {
329
+ "Content-Type": mimeType
330
+ }
331
+ `(error, data) = fs.readFile(JSpath.join(rootpath, filepath), options)
332
+ if integer(data.length)
333
+ init.headers."Content-Length" = data.length
334
+ list(error, data)
335
+ })
336
+
337
+ // destroy
338
+ //
339
+ // Destroy the service worker.
340
+
341
+ trope.destroy = function destroy() {
342
+ serviceWorker.unregister(scope)
343
+ scope = false
344
+ }
345
+
346
+ // finis
347
+
348
+ track.add(trope)
349
+ list(false, trope)
350
+ };
351
+
352
+
353
+ /*
354
+ * TrackServiceWorkers
355
+ *
356
+ * Configure service workers to be tracked in the execution tracker.
357
+ *
358
+ */
359
+
360
+ closure TrackServiceWorkers(track, local error) {
361
+ `(error, serviceWorker) = ScopedServiceWorker()
362
+ if error
363
+ ErrorDebugLog("TrackServiceWorkers: cannot load service worker", error)
364
+ track.register(TrackedScope, "V-Site")
365
+ };
366
+
367
+
368
+ /*
369
+ * workInit
370
+ *
371
+ * Initialize the debugger page.
372
+ *
373
+ */
374
+
375
+ function workInit(local manifest) {
376
+
377
+ manifest = `(ServiceWorker, ScopedServiceWorker, findTrackedScope, TrackedScope,
378
+ TrackServiceWorkers, workInit)
379
+
380
+ Naan.module.build(module.id, "workers", function(modobj, compobj) {
381
+ require("./browser.nlg")
382
+ compobj.manifest = manifest
383
+ modobj.exports.ServiceWorker = ServiceWorker
384
+ modobj.exports.TrackServiceWorkers = TrackServiceWorkers
385
+ })
386
+ } ();
@@ -0,0 +1,183 @@
1
+ /*
2
+ * apiclient.nlg
3
+ * Naanlib/frameworks/client
4
+ *
5
+ * Access to Nide API with HTTP client.
6
+ *
7
+ * column positioning: // // !
8
+ *
9
+ * Copyright (c) 2017-2021 by Richard C. Zulch
10
+ *
11
+ */
12
+
13
+
14
+ /*
15
+ * MakeNideAPIclient
16
+ *
17
+ * Make a DAS API client object for browsers. This client API handles a single project at a
18
+ * time, from load() to close().
19
+ *
20
+ *
21
+ */
22
+
23
+ closure MakeNideAPIclient(url, local client) {
24
+ client = new(object, this)
25
+ client.url = url
26
+ client.notifyAfter = 0
27
+
28
+ // clientRequest() - general request routine
29
+
30
+ closure clientRequest(method, path, options, cbReq, local request) {
31
+ request = xnew(js.w.XMLHttpRequest)
32
+ request.addEventListener("load", function (event) {
33
+ cbReq(false, request, event)
34
+ })
35
+
36
+ request.addEventListener("error", function reqFailed(event, local errtext) {
37
+ if request.status == 0
38
+ errtext = "connectivity"
39
+ ellse
40
+ errtext = "request failed"
41
+ error = Error(errtext, {
42
+ status: request.status
43
+ method: method
44
+ path: path
45
+ })
46
+ cbReq(error, request, event)
47
+ })
48
+
49
+ request.open(method, path)
50
+ if options.responseType
51
+ request.responseType = options.responseType
52
+ if options.contentType
53
+ request.setRequestHeader("Content-Type", options.contentType)
54
+ request.send(options.putdata)
55
+ }
56
+
57
+ //
58
+ // docs()
59
+ //
60
+
61
+ client.docs = closure docs() {
62
+ clientRequest("GET", url.concat("/"), false, function (error, req, event) {
63
+ printline(req.responseText)
64
+ })
65
+ }
66
+
67
+ //
68
+ // status(callback, timeoutMS)
69
+ //
70
+
71
+ client.status = closure status(cbStatus, timeoutms, local query, options, queued) {
72
+ options = new(dictionary)
73
+ options.timeout = timeoutms
74
+ options.after = client.notifyAfter
75
+ query = EncodeQuery("/status/?", options)
76
+ clientRequest("GET", url.concat(query), false, function (error, req, event) {
77
+ if (error || req.status != 200)
78
+ cbStatus()
79
+ else if (length(req.responseText) == 0)
80
+ cbStatus([])
81
+ else {
82
+ queued = new(JSONparse(req.responseText))
83
+ queued.forEach(function(item,index,array) {
84
+ if client.notifyAfter < item.stamp
85
+ client.notifyAfter = item.stamp
86
+ })
87
+ cbStatus(queued)
88
+ }
89
+ })
90
+ }
91
+
92
+ //
93
+ // get
94
+ //
95
+
96
+ client.get = closure get(path, cbRead) {
97
+ options.path = filepath
98
+ clientRequest("GET", url.concat("/", path), false, cbRead)
99
+ }
100
+
101
+ //
102
+ // readFile(filepath, cbRead)
103
+ //
104
+
105
+ client.readFile = closure readFile(filepath, cbRead, local query, options) {
106
+ options = new(dictionary)
107
+ options.path = filepath
108
+ query = EncodeQuery("/readfile/?", options)
109
+ clientRequest("GET", url.concat(query), false, cbRead)
110
+ }
111
+
112
+ //
113
+ // psmRemote(options, data, callback)
114
+ //
115
+ // Perform an operation and call back when done. If the communication works then the result is:
116
+ // callback(false, (remote_error, remote_data)).
117
+ // Otherwise if communication failed then the result is:
118
+ // callback(<error>).
119
+
120
+ client.psmRemote = closure psmRemote(options, data, callback, local query, method, reqOptions) {
121
+ query = EncodeQuery("/psm/?", options)
122
+ if data
123
+ method = "PUT"
124
+ else
125
+ method = "GET"
126
+ reqOptions = {
127
+ putdata: data
128
+ }
129
+ if options.encoding == "binary" {
130
+ if data
131
+ reqOptions.contentType = "application/octet-stream" // we are sending binary data
132
+ else
133
+ reqOptions.responseType = "arraybuffer" // we are requesting binary data
134
+ }
135
+ clientRequest(method, url.concat(query), reqOptions, function (error, req, event, local data) {
136
+ if !error && req.status != 200
137
+ error = Error("NodeFS request failed: ".concat(req.status), {
138
+ status: req.status
139
+ method: method
140
+ query: query
141
+ })
142
+ if error
143
+ callback(error)
144
+ else {
145
+ if req.getResponseHeader("content-type").startsWith("application/json")
146
+ try { // attempt to decode JSON response
147
+ data = new(JSONparse(req.responseText))
148
+ if array(data) {
149
+ data = totuple(data)
150
+ error = data.0
151
+ data = data.1 }
152
+ } catch {
153
+ if true
154
+ data = req.responseText // just return text on failure
155
+ }
156
+ else
157
+ data = req.response // e.g. when reading binary content
158
+ callback(error, data) }
159
+ })
160
+ }
161
+
162
+ client
163
+ };
164
+
165
+
166
+ /*
167
+ * apicInit
168
+ *
169
+ * Initialize the apic component.
170
+ *
171
+ */
172
+
173
+ function apicInit(local manifest) {
174
+
175
+ manifest = `(apic, apicInit)
176
+
177
+ Naan.module.build(module.id, "apiclient", function(modobj, compobj) {
178
+ Naan.module.require("./client.nlg")
179
+ compobj.manifest = manifest
180
+ modobj.exports.MakeNideAPIclient = MakeNideAPIclient
181
+ })
182
+
183
+ } ();
@@ -0,0 +1,29 @@
1
+ /*
2
+ * client.nlg
3
+ * Naanlib/frameworks/client
4
+ *
5
+ * Root component for client-specific functionality, that communicates with servers.
6
+ *
7
+ * column positioning: // // !
8
+ *
9
+ * Copyright (c) 2020-2021 by Richard C. Zulch
10
+ *
11
+ */
12
+
13
+
14
+ /*
15
+ * clirInit
16
+ *
17
+ * Initialize the client module.
18
+ *
19
+ *
20
+ */
21
+
22
+ function clirInit(local manifest) {
23
+ manifest = `(clirInit)
24
+
25
+ Naan.module.build(module.id, "client", function(modobj, compobj) {
26
+ require("../common/").LiveImport()
27
+ compobj.manifest = manifest
28
+ })
29
+ } ();