@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.
- package/LICENSE.md +21 -0
- package/README.md +46 -0
- package/dist/env_web.js +431 -0
- package/dist/naan.min.js +73 -0
- package/frameworks/browser/browser.nlg +30 -0
- package/frameworks/browser/pouchdb/pouchdb.min.js +7 -0
- package/frameworks/browser/spark-md5/spark-md5.min.js +1 -0
- package/frameworks/browser/sworker.js +192 -0
- package/frameworks/browser/terminals.nlg +787 -0
- package/frameworks/browser/workers.nlg +386 -0
- package/frameworks/client/apiclient.nlg +183 -0
- package/frameworks/client/client.nlg +29 -0
- package/frameworks/client/psm_client.nlg +572 -0
- package/frameworks/common/common.nlg +464 -0
- package/frameworks/common/preferences.nlg +131 -0
- package/frameworks/common/repltools.nlg +100 -0
- package/frameworks/common/watching.nlg +97 -0
- package/frameworks/node/apiserver.nlg +399 -0
- package/frameworks/node/filesystem.nlg +1012 -0
- package/frameworks/node/gitter.nlg +234 -0
- package/frameworks/node/node.nlg +81 -0
- package/frameworks/node/psm_server.nlg +465 -0
- package/frameworks/node/worker.nlg +560 -0
- package/frameworks/project/build.nlg +1229 -0
- package/frameworks/project/jszip.js +30 -0
- package/frameworks/project/jszip.nlg +87 -0
- package/frameworks/project/proj_cliser.nlg +139 -0
- package/frameworks/project/proj_console.nlg +137 -0
- package/frameworks/project/proj_folder.nlg +143 -0
- package/frameworks/project/proj_lambda.nlg +137 -0
- package/frameworks/project/proj_static.nlg +138 -0
- package/frameworks/project/project.nlg +29 -0
- package/frameworks/project/projects.nlg +587 -0
- package/frameworks/project/uglifyjs.js +1 -0
- package/frameworks/project/uglifyjs.nlg +79 -0
- package/frameworks/running/debugcom.nlg +163 -0
- package/frameworks/running/debugnub.nlg +565 -0
- package/frameworks/running/debugutil.nlg +510 -0
- package/frameworks/running/executors.nlg +767 -0
- package/frameworks/running/running.nlg +151 -0
- package/frameworks/running/sourcecode.nlg +346 -0
- package/frameworks/running/taskexec.nlg +196 -0
- package/frameworks/storage/dbt_pouch.nlg +773 -0
- package/frameworks/storage/file_manager.nlg +772 -0
- package/frameworks/storage/psm.nlg +326 -0
- package/frameworks/storage/psm_dbtables.nlg +814 -0
- package/frameworks/storage/resources.nlg +445 -0
- package/frameworks/storage/storage.nlg +52 -0
- package/lib/browser/env_web.js +431 -0
- package/lib/browser/env_webworker.js +146 -0
- package/lib/browser/require.js +1653 -0
- package/lib/core/naanlib.js +73 -0
- package/lib/env_node.js +282 -0
- package/lib/env_nodeworker.js +165 -0
- package/lib/node_repl.js +25 -0
- package/lib/node_repl_init.nlg +52 -0
- package/package.json +13 -0
- package/plugins/gitClient/clientops.nlg +317 -0
- package/plugins/gitClient/gitClient.nlg +63 -0
- package/plugins/gitClient/gitutils.nlg +1331 -0
- package/plugins/gitClient/minimatch.js +945 -0
- package/plugins/gitClient/minimatch_license.txt +15 -0
- package/plugins/gitClient/minimatch_readme.md +208 -0
- package/plugins/nodeLib/nodeLib.nlg +26 -0
- package/plugins/nodeLib/node_cp.nlg +65 -0
- package/plugins/nodeLib/node_fs.nlg +137 -0
- package/plugins/nodeLib/node_https.nlg +172 -0
- package/plugins/nodeLib/node_util.nlg +180 -0
- package/plugins/serviceAws/aws/aws-sdk.min.js +88 -0
- package/plugins/serviceAws/aws/lambda_rest_index.js +122 -0
- package/plugins/serviceAws/aws/lambda_rest_init.nlg +58 -0
- package/plugins/serviceAws/aws/lambda_ws_index.js +498 -0
- package/plugins/serviceAws/aws/lambda_ws_init.nlg +49 -0
- package/plugins/serviceAws/aws_cloudwatchlogs.nlg +122 -0
- package/plugins/serviceAws/aws_cognito.nlg +76 -0
- package/plugins/serviceAws/aws_dynamo.nlg +509 -0
- package/plugins/serviceAws/aws_lambda.nlg +95 -0
- package/plugins/serviceAws/aws_s3.nlg +134 -0
- package/plugins/serviceAws/aws_utils.nlg +86 -0
- package/plugins/serviceAws/dbt_aws.nlg +769 -0
- package/plugins/serviceAws/lambda_naan_control.nlg +175 -0
- package/plugins/serviceAws/psm_aws.nlg +258 -0
- package/plugins/serviceAws/serviceAws.nlg +38 -0
- package/plugins/serviceGitHub/gitops.nlg +522 -0
- package/plugins/serviceGitHub/psm_github.nlg +205 -0
- package/plugins/serviceGitHub/serviceGitHub.nlg +65 -0
- package/plugins/serviceGitLab/gitops.nlg +528 -0
- package/plugins/serviceGitLab/psm_gitlab.nlg +205 -0
- package/plugins/serviceGitLab/serviceGitLab.nlg +65 -0
- package/test/harness.nlg +312 -0
- package/test/node_test.js +33 -0
- package/test/test_01_core.nlg +768 -0
- package/test/test_02_context.nlg +269 -0
- package/test/test_03_jsinterop.nlg +137 -0
- package/test/test_04_numerics.nlg +450 -0
- package/test/test_05_strings.nlg +63 -0
- package/test/test_06_lingoparse.nlg +500 -0
- 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
|
+
} ();
|