@naanlang/naan 1.0.2 → 1.0.5
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 +1 -1
- package/README.md +10 -8
- package/bin/index.js +2 -2
- package/dist/env_web.js +172 -22
- package/dist/naan.min.js +6 -6
- package/frameworks/browser/https_request.nlg +120 -0
- package/frameworks/browser/sworker.js +299 -91
- package/frameworks/browser/terminals.nlg +28 -13
- package/frameworks/browser/workers.nlg +27 -12
- package/frameworks/client/apiclient.nlg +17 -4
- package/frameworks/client/psm_client.nlg +184 -81
- package/frameworks/common/common.nlg +105 -25
- package/frameworks/common/preferences.nlg +1 -0
- package/frameworks/common/watching.nlg +1 -0
- package/frameworks/node/apiserver.nlg +31 -15
- package/frameworks/node/filesystem.nlg +230 -46
- package/frameworks/node/gitter.nlg +27 -6
- package/frameworks/node/https_request.nlg +119 -0
- package/frameworks/node/node.nlg +1 -0
- package/frameworks/node/psm_server.nlg +113 -37
- package/frameworks/project/build.nlg +40 -23
- package/frameworks/project/proj_cliser.nlg +11 -3
- package/frameworks/project/proj_console.nlg +13 -4
- package/frameworks/project/proj_folder.nlg +10 -1
- package/frameworks/project/proj_lambda.nlg +13 -4
- package/frameworks/project/proj_static.nlg +11 -3
- package/frameworks/project/projects.nlg +128 -40
- package/frameworks/running/debugnub.nlg +2 -5
- package/frameworks/running/executors.nlg +1 -0
- package/frameworks/storage/csv.nlg +120 -0
- package/frameworks/storage/dbt_pouch.nlg +41 -25
- package/frameworks/storage/psm.nlg +108 -28
- package/frameworks/storage/psm_dbtables.nlg +7 -3
- package/frameworks/storage/resources.nlg +30 -2
- package/lib/browser/env_web.js +170 -20
- package/lib/browser/env_webworker.js +1 -1
- package/lib/browser/require.js +1 -1
- package/lib/core/naanlib.js +6 -6
- package/package.json +2 -1
- package/plugins/serviceAws/aws/aws-sdk-node.min.js +2 -0
- package/plugins/serviceAws/aws/aws-sdk.min.js +2 -88
- package/plugins/serviceAws/aws_cloudwatchlogs.nlg +8 -7
- package/plugins/serviceAws/aws_dynamo.nlg +715 -148
- package/plugins/serviceAws/aws_dynextra.nlg +294 -0
- package/plugins/serviceAws/aws_lambda.nlg +11 -4
- package/plugins/serviceAws/aws_s3.nlg +44 -14
- package/plugins/serviceAws/dbt_aws.nlg +58 -45
- package/plugins/serviceAws/psm_aws.nlg +61 -40
- package/plugins/serviceAws/serviceAws.nlg +7 -4
- package/plugins/serviceGitHub/psm_github.nlg +41 -25
- package/plugins/serviceGitLab/psm_gitlab.nlg +41 -25
- package/test/harness.nlg +3 -1
- package/test/test_01_core.nlg +5 -5
- package/test/test_02_context.nlg +4 -4
- package/test/test_03_jsinterop.nlg +9 -3
- package/plugins/serviceAws/aws_cognito.nlg +0 -76
|
@@ -22,6 +22,50 @@ closure psmcFsView(api, rootpath, local view, pathmod) {
|
|
|
22
22
|
view = new(object, this)
|
|
23
23
|
view.api = api
|
|
24
24
|
view.rootpath = rootpath
|
|
25
|
+
|
|
26
|
+
// data
|
|
27
|
+
//
|
|
28
|
+
// Return the filesystem data, i.e. the tree data field. The minimum information is:
|
|
29
|
+
// platform -- e.g. "darwin" or "win32"
|
|
30
|
+
// semantics -- e.g. "win32" or "posix"
|
|
31
|
+
// pathsep -- e.g. / or \
|
|
32
|
+
|
|
33
|
+
view.data = closure data(callback) {
|
|
34
|
+
if !callback
|
|
35
|
+
return (syncAdapter(data))
|
|
36
|
+
params = {
|
|
37
|
+
path: ""
|
|
38
|
+
op: "tree"
|
|
39
|
+
depthlimit: 0
|
|
40
|
+
}
|
|
41
|
+
api.psmRemote(params, false, function(error, tree) {
|
|
42
|
+
if error
|
|
43
|
+
debuglog("psmcFsView.data: can't get initial filesystem data:", ErrorString(error))
|
|
44
|
+
else {
|
|
45
|
+
view.fsdata = tree.data
|
|
46
|
+
if rootpath == ""
|
|
47
|
+
rootpath = tree.data.pathsep
|
|
48
|
+
}
|
|
49
|
+
callback(error, tree.data)
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// pathInit
|
|
54
|
+
//
|
|
55
|
+
// Initialize our path module for the applicable path type.
|
|
56
|
+
|
|
57
|
+
closure pathInit(local result) {
|
|
58
|
+
result = view.data()
|
|
59
|
+
if result.0
|
|
60
|
+
pathmod = false
|
|
61
|
+
else {
|
|
62
|
+
if view.fsdata.pathsep == "\\"
|
|
63
|
+
pathmod = JSpath.win32
|
|
64
|
+
else
|
|
65
|
+
pathmod = JSpath.posix
|
|
66
|
+
false
|
|
67
|
+
}
|
|
68
|
+
}
|
|
25
69
|
|
|
26
70
|
// psmRemote
|
|
27
71
|
//
|
|
@@ -30,10 +74,14 @@ closure psmcFsView(api, rootpath, local view, pathmod) {
|
|
|
30
74
|
closure psmRemote(path, op, options, putdata, callback, local params, item) {
|
|
31
75
|
if !callback
|
|
32
76
|
return (syncAdapter(psmRemote, path, op, options, putdata))
|
|
77
|
+
if !pathmod && pathInit()
|
|
78
|
+
return // failed to initialize path module
|
|
33
79
|
if !string(path)
|
|
34
80
|
return (asyncResult(callback, Error("invalid path:", typeof(path))))
|
|
81
|
+
if rootpath != ""
|
|
82
|
+
path = pathmod.resolve(rootpath, path)
|
|
35
83
|
params = {
|
|
36
|
-
path:
|
|
84
|
+
path: path
|
|
37
85
|
op: op
|
|
38
86
|
}
|
|
39
87
|
for item in options
|
|
@@ -59,38 +107,30 @@ closure psmcFsView(api, rootpath, local view, pathmod) {
|
|
|
59
107
|
|
|
60
108
|
// path
|
|
61
109
|
//
|
|
62
|
-
//
|
|
110
|
+
// Redirect path calls to module chosen for filesystem semantics. It is possible for this to fail
|
|
111
|
+
// on first connection to the filesystem, in which case we return false for the path result.
|
|
112
|
+
// Throwing an error would complicate our callers and testing. This way there's a small chance
|
|
113
|
+
// that a transient error will give a bad path, but that will be detected downstream.
|
|
63
114
|
|
|
64
115
|
view.path = new(object, this)
|
|
65
|
-
view.path[".undefined"] =
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if error
|
|
70
|
-
return (list(error))
|
|
71
|
-
if info.pathsep == "\\"
|
|
72
|
-
pathmod = JSpath.win32
|
|
73
|
-
else
|
|
74
|
-
pathmod = JSpath.posix
|
|
75
|
-
}
|
|
76
|
-
xapply(pathmod, selector, arglist)
|
|
77
|
-
} (args.0, args.-1)
|
|
116
|
+
view.path[".undefined"] = function path args {
|
|
117
|
+
if !pathmod
|
|
118
|
+
pathInit()
|
|
119
|
+
xapply(pathmod, args.0, args.-1)
|
|
78
120
|
}
|
|
79
121
|
|
|
80
|
-
//
|
|
122
|
+
// folderPath
|
|
81
123
|
//
|
|
82
|
-
// Return the
|
|
83
|
-
//
|
|
84
|
-
//
|
|
85
|
-
//
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
callback(error, tree.data)
|
|
93
|
-
})
|
|
124
|
+
// Return the path of the specified special folder:
|
|
125
|
+
// "HomeDir"
|
|
126
|
+
// "TempDir"
|
|
127
|
+
// "PackageDir"
|
|
128
|
+
// The returned path is relative to our root if within it, or absolute otherwise.
|
|
129
|
+
|
|
130
|
+
view.folderPath = function folderPath(folderID, callback) {
|
|
131
|
+
psmRemote("", "folderPath", {
|
|
132
|
+
folderid: folderID
|
|
133
|
+
}, false, callback)
|
|
94
134
|
}
|
|
95
135
|
|
|
96
136
|
// readLines
|
|
@@ -123,7 +163,28 @@ closure psmcFsView(api, rootpath, local view, pathmod) {
|
|
|
123
163
|
view.writeFile = function writeFile(path, data, options, callback) {
|
|
124
164
|
psmRemote(path, "writeFile", options, data, callback)
|
|
125
165
|
}
|
|
126
|
-
|
|
166
|
+
|
|
167
|
+
// readlink
|
|
168
|
+
//
|
|
169
|
+
// Read the contents of a symbolic link at the specified path
|
|
170
|
+
|
|
171
|
+
view.readlink = function readlink(path, callback) {
|
|
172
|
+
psmRemote(path, "readlink", { }, false, callback)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// symlink
|
|
176
|
+
//
|
|
177
|
+
// Create a symbolic link path pointing to (containing the string) target
|
|
178
|
+
|
|
179
|
+
view.symlink = function symlink(target, path, options, callback) {
|
|
180
|
+
if options
|
|
181
|
+
options = new(options)
|
|
182
|
+
else
|
|
183
|
+
options = { }
|
|
184
|
+
options.target = target
|
|
185
|
+
psmRemote(path, "symlink", options, false, callback)
|
|
186
|
+
}
|
|
187
|
+
|
|
127
188
|
// delete
|
|
128
189
|
//
|
|
129
190
|
// Delete a file or directory at the specified path
|
|
@@ -134,12 +195,45 @@ closure psmcFsView(api, rootpath, local view, pathmod) {
|
|
|
134
195
|
|
|
135
196
|
// info
|
|
136
197
|
//
|
|
137
|
-
// Get file info at the specified path
|
|
198
|
+
// Get file or directory info at the specified path
|
|
199
|
+
|
|
200
|
+
view.info = function info(path, options, callback) {
|
|
201
|
+
if !options
|
|
202
|
+
options = { }
|
|
203
|
+
psmRemote(path, "info", options, false, callback)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// setInfo
|
|
207
|
+
//
|
|
208
|
+
// Set file or directory info obtained from info() call.
|
|
138
209
|
|
|
139
|
-
view.
|
|
140
|
-
psmRemote(path, "
|
|
210
|
+
view.setInfo = function setInfo(path, info, callback) {
|
|
211
|
+
psmRemote(path, "setInfo", {
|
|
212
|
+
encoding: "json"
|
|
213
|
+
}, info, callback)
|
|
141
214
|
}
|
|
142
215
|
|
|
216
|
+
// setOwnerGroup
|
|
217
|
+
//
|
|
218
|
+
// Set file or directory owner or group at the specified path
|
|
219
|
+
|
|
220
|
+
view.setOwnerGroup = function setOwnerGroup(path, uid, gid, callback) {
|
|
221
|
+
psmRemote(path, "setOwnerGroup", {
|
|
222
|
+
uid: uid
|
|
223
|
+
gid: gid
|
|
224
|
+
}, false, callback)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// setMode
|
|
228
|
+
//
|
|
229
|
+
// Set file or directory mode at the specified path
|
|
230
|
+
|
|
231
|
+
view.setMode = function setMode(path, mode, callback) {
|
|
232
|
+
psmRemote(path, "setMode", {
|
|
233
|
+
mode: mode
|
|
234
|
+
}, false, callback)
|
|
235
|
+
}
|
|
236
|
+
|
|
143
237
|
// setTimes
|
|
144
238
|
//
|
|
145
239
|
// Set file modify and access times at the specified path
|
|
@@ -157,7 +251,7 @@ closure psmcFsView(api, rootpath, local view, pathmod) {
|
|
|
157
251
|
|
|
158
252
|
view.dirList = function dirList(path, options, callback) {
|
|
159
253
|
psmRemote(path, "dirList", {
|
|
160
|
-
|
|
254
|
+
stat: options.stat
|
|
161
255
|
}, false, callback)
|
|
162
256
|
}
|
|
163
257
|
|
|
@@ -167,7 +261,7 @@ closure psmcFsView(api, rootpath, local view, pathmod) {
|
|
|
167
261
|
|
|
168
262
|
view.readir = function readir(path, callback) {
|
|
169
263
|
psmRemote(path, "dirList", {
|
|
170
|
-
|
|
264
|
+
stat: true
|
|
171
265
|
}, false, callback)
|
|
172
266
|
}
|
|
173
267
|
|
|
@@ -209,7 +303,9 @@ closure psmcFsView(api, rootpath, local view, pathmod) {
|
|
|
209
303
|
// delete the source after the copy.
|
|
210
304
|
|
|
211
305
|
view.copy = closure copy(srcpath, dest, options, callback, local parameters) {
|
|
212
|
-
if
|
|
306
|
+
if options
|
|
307
|
+
options = new(options)
|
|
308
|
+
else
|
|
213
309
|
options = { }
|
|
214
310
|
options.destination = JSpath.resolve(rootpath, dest)
|
|
215
311
|
psmRemote(srcpath, "copy", options, false, callback)
|
|
@@ -325,7 +421,7 @@ closure psmcFsConnector(psm, nicc, local connClassID, connector, watch) {
|
|
|
325
421
|
connector.psm = psm
|
|
326
422
|
connector.api = nicc.api
|
|
327
423
|
connector.vault = psm.vault(connClassID)
|
|
328
|
-
connector.label = "Naan
|
|
424
|
+
connector.label = "Naan-Server"
|
|
329
425
|
watch = psm.watchable(connector)
|
|
330
426
|
|
|
331
427
|
// uifields
|
|
@@ -337,57 +433,44 @@ closure psmcFsConnector(psm, nicc, local connClassID, connector, watch) {
|
|
|
337
433
|
placeholder: "http://host.com/endpoint"
|
|
338
434
|
key: "urlName" },
|
|
339
435
|
{
|
|
340
|
-
label: "Auth
|
|
341
|
-
placeholder: "
|
|
342
|
-
key: "
|
|
343
|
-
{
|
|
344
|
-
label: "Auth Password"
|
|
345
|
-
placeholder: "account password"
|
|
346
|
-
key: "authPW"
|
|
347
|
-
type: "password" },
|
|
436
|
+
label: "Auth Secret"
|
|
437
|
+
placeholder: "guid"
|
|
438
|
+
key: "authSecret" }
|
|
348
439
|
]
|
|
349
440
|
}
|
|
350
|
-
|
|
351
|
-
// hashResourceID
|
|
352
|
-
//
|
|
353
|
-
// Make a stable hash based on the resource credentials that we can persist or share between
|
|
354
|
-
// different domains accessing the same resource.
|
|
355
|
-
connector.hashResourceID = function hashResourceID(resource, local ident) {
|
|
356
|
-
ident = resource.urlName
|
|
357
|
-
if resource.label
|
|
358
|
-
ident = ident.concat(resource.label)
|
|
359
|
-
HashSHA256(ident)
|
|
360
|
-
}
|
|
361
441
|
|
|
362
442
|
// findResource
|
|
363
443
|
//
|
|
364
|
-
// Find a resource with the specified contents, returning the resID or false.
|
|
365
|
-
// is: if added, would the specified contents be redundant to an existing resource?
|
|
444
|
+
// Find a resource with the specified contents, returning the resID or false.
|
|
366
445
|
connector.findResource = function findResource(resource, local resID, creds) {
|
|
367
446
|
for resID in listResources().1 {
|
|
368
447
|
creds = access(resID).1
|
|
369
|
-
if resource.urlName == creds.urlName
|
|
370
|
-
&& (!resource.label || resource.label == creds.label)
|
|
371
|
-
&& resource.authName == creds.authName
|
|
448
|
+
if ((!resource.urlName || resource.urlName == creds.urlName)
|
|
449
|
+
&& (!resource.label || resource.label == creds.label))
|
|
372
450
|
return (resID)
|
|
373
451
|
}
|
|
374
452
|
false
|
|
375
453
|
}
|
|
376
454
|
|
|
377
|
-
|
|
455
|
+
|
|
456
|
+
// writeResource
|
|
378
457
|
//
|
|
379
|
-
// Add credentials for a named resource.
|
|
458
|
+
// Add or update credentials for a named resource. If no resID is specified this adds a new
|
|
459
|
+
// resource; otherwise it updates an existing one. The resource is a dictionary comprising these
|
|
460
|
+
// keys:
|
|
380
461
|
// label - [optional] label we use for this resource
|
|
381
462
|
// urlName - URL (e.g. "http://host.com/node/fsapi")
|
|
382
|
-
//
|
|
383
|
-
// authPW - [optional] the autentication password, required if authname is provided
|
|
463
|
+
// authSecret - access-control token for this URL
|
|
384
464
|
// hidden - [optional] don't enumerate to user
|
|
385
465
|
// locked - [optional] don't allow user delete
|
|
386
466
|
//
|
|
387
|
-
// The return value is (error, resID) tuple. Error, if non-false, is a dictionary of field
|
|
467
|
+
// The return value is an (error, resID) tuple. Error, if non-false, is a dictionary of field
|
|
388
468
|
// keys and error diagnostic strings.
|
|
389
|
-
connector.
|
|
469
|
+
connector.writeResource = function writeResource(resource, resID,
|
|
470
|
+
local creds, errors, error, data, change) {
|
|
471
|
+
// badField - test for a bad string
|
|
390
472
|
function badField(str) { !string(str) || str.trim().length == 0 }
|
|
473
|
+
|
|
391
474
|
creds = { urlName: resource.urlName }
|
|
392
475
|
errors = { }
|
|
393
476
|
if resource.label
|
|
@@ -396,13 +479,13 @@ closure psmcFsConnector(psm, nicc, local connClassID, connector, watch) {
|
|
|
396
479
|
creds.label = resource.urlName
|
|
397
480
|
if badField(creds.label)
|
|
398
481
|
errors.label = "invalid label"
|
|
482
|
+
else if !resID && findResource({ label: creds.label })
|
|
483
|
+
errors.label = "duplicate name"
|
|
399
484
|
if badField(resource.urlName)
|
|
400
485
|
errors.urlName = "required field"
|
|
401
|
-
if
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
if badField(resource.authPW)
|
|
405
|
-
errors.authPW = "required if Auth Name specified" }
|
|
486
|
+
if badField(resource.authSecret)
|
|
487
|
+
errors.authSecret = "required field"
|
|
488
|
+
creds.authSecret = resource.authSecret
|
|
406
489
|
if length(errors) > 0
|
|
407
490
|
error = errors
|
|
408
491
|
else {
|
|
@@ -410,14 +493,36 @@ closure psmcFsConnector(psm, nicc, local connClassID, connector, watch) {
|
|
|
410
493
|
creds.hidden = resource.hidden
|
|
411
494
|
if resource.locked
|
|
412
495
|
creds.locked = resource.locked
|
|
413
|
-
resID
|
|
414
|
-
|
|
496
|
+
if resID {
|
|
497
|
+
`(error, data) = connector.vault.updateResource(resID, creds)
|
|
498
|
+
change = { changed: [resID] }
|
|
499
|
+
} else {
|
|
500
|
+
resID = UUID()
|
|
501
|
+
`(error, data) = connector.vault.addResource(resID, creds)
|
|
502
|
+
change = { added: [resID] }
|
|
503
|
+
}
|
|
415
504
|
if data {
|
|
416
|
-
watch.notify(connClassID,
|
|
417
|
-
data = resID
|
|
505
|
+
watch.notify(connClassID, change)
|
|
506
|
+
data = resID
|
|
507
|
+
}
|
|
508
|
+
}
|
|
418
509
|
list(error, data)
|
|
419
510
|
}
|
|
420
|
-
|
|
511
|
+
|
|
512
|
+
// addResource
|
|
513
|
+
//
|
|
514
|
+
// Add a new resource, returning a standard error tuple per writeResource.
|
|
515
|
+
connector.addResource = function addResource(resource) {
|
|
516
|
+
writeResource(resource)
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// updateResource
|
|
520
|
+
//
|
|
521
|
+
// Update an existing resource, returning a standard error tuple per writeResource.
|
|
522
|
+
connector.updateResource = function updateResource(resID, resource) {
|
|
523
|
+
writeResource(resource, resID)
|
|
524
|
+
}
|
|
525
|
+
|
|
421
526
|
// getResource
|
|
422
527
|
//
|
|
423
528
|
// Get credentials for a named resource, matching the dictionary semantics of addResource. The
|
|
@@ -432,10 +537,8 @@ closure psmcFsConnector(psm, nicc, local connClassID, connector, watch) {
|
|
|
432
537
|
}
|
|
433
538
|
if string(creds.urlName)
|
|
434
539
|
resource.urlName = creds.urlName
|
|
435
|
-
if string(creds.
|
|
436
|
-
resource.
|
|
437
|
-
if string(creds.authPW)
|
|
438
|
-
resource.authPW = creds.authPW
|
|
540
|
+
if string(creds.authSecret)
|
|
541
|
+
resource.authSecret = creds.authSecret
|
|
439
542
|
list(false, resource)
|
|
440
543
|
}
|
|
441
544
|
|
|
@@ -510,7 +613,7 @@ closure psmcFsConnector(psm, nicc, local connClassID, connector, watch) {
|
|
|
510
613
|
if creds == "HostFS"
|
|
511
614
|
api = connector.api
|
|
512
615
|
else
|
|
513
|
-
api = MakeNideAPIclient(creds.urlName)
|
|
616
|
+
api = MakeNideAPIclient(creds.urlName, creds.authSecret) // API to remote NodeJS filesystem
|
|
514
617
|
}
|
|
515
618
|
if error
|
|
516
619
|
list(error)
|
|
@@ -30,6 +30,49 @@ function EncodeQuery(prefix, items, local result, item) {
|
|
|
30
30
|
};
|
|
31
31
|
|
|
32
32
|
|
|
33
|
+
/*
|
|
34
|
+
* ContentTypeFromFileExt
|
|
35
|
+
*
|
|
36
|
+
* Given a filename with extension, return a tuple of the recommended contentType and encoding
|
|
37
|
+
* for that type of data: `(contentType, encoding). Currently the encoding is false for text and
|
|
38
|
+
* "binary" for everything else.
|
|
39
|
+
*
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
function ContentTypeFromFileExt(filepath, local mimeType, encoding) {
|
|
43
|
+
mimeType = {
|
|
44
|
+
"css": "text/css",
|
|
45
|
+
"csv": "text/csv",
|
|
46
|
+
"gif": "image/gif",
|
|
47
|
+
"htm": "text/html",
|
|
48
|
+
"html": "text/html",
|
|
49
|
+
"ico": "image/x-icon",
|
|
50
|
+
"ics": "application/octet-stream",
|
|
51
|
+
"jpeg": "image/jpeg",
|
|
52
|
+
"jpg": "image/jpeg",
|
|
53
|
+
"js": "text/javascript",
|
|
54
|
+
"json": "application/json",
|
|
55
|
+
"mov": "video/mp4",
|
|
56
|
+
"mp3": "audio/mpeg",
|
|
57
|
+
"mp4": "video/mp4",
|
|
58
|
+
"nlg": "text/plain",
|
|
59
|
+
"npk": "application/json",
|
|
60
|
+
"ogg": "video/ogg",
|
|
61
|
+
"svg": "image/svg+xml",
|
|
62
|
+
"text": "text/plain",
|
|
63
|
+
"txt": "text/plain",
|
|
64
|
+
"zip": "application/octet-stream"
|
|
65
|
+
}[JSpath.extname(filepath).substring(1)]
|
|
66
|
+
if !mimeType
|
|
67
|
+
mimeType = "application/octet-stream"
|
|
68
|
+
if mimeType.startsWith("text/")
|
|
69
|
+
mimeType = mimeType.concat("; charset=UTF-8")
|
|
70
|
+
else
|
|
71
|
+
encoding = "binary"
|
|
72
|
+
list(mimeType, encoding)
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
|
|
33
76
|
/*
|
|
34
77
|
* UUID
|
|
35
78
|
*
|
|
@@ -66,7 +109,7 @@ function JsonParse(data) {
|
|
|
66
109
|
list(false, data)
|
|
67
110
|
} catch {
|
|
68
111
|
if true
|
|
69
|
-
|
|
112
|
+
list(exception)
|
|
70
113
|
}
|
|
71
114
|
};
|
|
72
115
|
|
|
@@ -84,7 +127,7 @@ function JsonStringify(data) {
|
|
|
84
127
|
list(false, data)
|
|
85
128
|
} catch {
|
|
86
129
|
if true
|
|
87
|
-
|
|
130
|
+
list(exception)
|
|
88
131
|
}
|
|
89
132
|
};
|
|
90
133
|
|
|
@@ -125,11 +168,8 @@ function JsLoadScript(libpath, globalID, local scriptTag, fpath) {
|
|
|
125
168
|
}
|
|
126
169
|
js.w.document.body.appendChild(scriptTag)
|
|
127
170
|
pending.wait()
|
|
128
|
-
} else if js.g
|
|
129
|
-
|
|
130
|
-
fpath = "./".concat(libpath)
|
|
131
|
-
jsScripts[libpath] = js.r(fpath) // load in NodeJS context
|
|
132
|
-
}
|
|
171
|
+
} else if js.g
|
|
172
|
+
jsScripts[libpath] = js.r(libpath) // load in NodeJS context
|
|
133
173
|
jsScripts[libpath]
|
|
134
174
|
};
|
|
135
175
|
|
|
@@ -256,15 +296,19 @@ TextEncoder = false;
|
|
|
256
296
|
TextDecoder = false;
|
|
257
297
|
EncodeURIComponent = false;
|
|
258
298
|
DecodeURIComponent = false;
|
|
299
|
+
EncodeBase64 = false;
|
|
300
|
+
DecodeBase64 = false;
|
|
259
301
|
JSONstringify = false;
|
|
260
302
|
JSONparse = false;
|
|
303
|
+
Uint8ArrayFromString = false;
|
|
261
304
|
|
|
262
305
|
function comrInit(local manifest) {
|
|
263
|
-
manifest = `(EncodeQuery, UUID, JsLoadScript, LoadComponentOnDemand, LiveExport, comrInit)
|
|
306
|
+
manifest = `(EncodeQuery, ContentTypeFromFileExt, UUID, JsLoadScript, LoadComponentOnDemand, LiveExport, comrInit)
|
|
264
307
|
|
|
265
|
-
Naan.module.build(module.id, "
|
|
308
|
+
Naan.module.build(module.id, "common", closure(modobj, compobj) {
|
|
266
309
|
compobj.manifest = manifest
|
|
267
310
|
modobj.exports.EncodeQuery = EncodeQuery
|
|
311
|
+
modobj.exports.ContentTypeFromFileExt = ContentTypeFromFileExt
|
|
268
312
|
modobj.exports.UUID = UUID
|
|
269
313
|
modobj.exports.JsLoadScript = JsLoadScript
|
|
270
314
|
modobj.exports.LoadComponentOnDemand = LoadComponentOnDemand
|
|
@@ -293,6 +337,14 @@ function comrInit(local manifest) {
|
|
|
293
337
|
JSONstringify = wsg.JSON.stringify
|
|
294
338
|
JSONparse = wsg.JSON.parse
|
|
295
339
|
//
|
|
340
|
+
// everywhere: Uint8ArrayFromString
|
|
341
|
+
//
|
|
342
|
+
Uint8ArrayFromString = function uint8ArrayFromString(data) {
|
|
343
|
+
wsg.Uint8Array.from(Array.from(data).map(function(letter) {
|
|
344
|
+
letter.charCodeAt(0)
|
|
345
|
+
}))
|
|
346
|
+
}
|
|
347
|
+
//
|
|
296
348
|
// binaryFrom - convert arbitrary item to binary buffer or text.
|
|
297
349
|
//
|
|
298
350
|
function binaryFrom(data) {
|
|
@@ -321,29 +373,42 @@ function comrInit(local manifest) {
|
|
|
321
373
|
result
|
|
322
374
|
}
|
|
323
375
|
//
|
|
324
|
-
// base64Format - create base 64 string from binary array
|
|
325
|
-
//
|
|
326
|
-
function base64Format(data, local blob, reader, pending, result) {
|
|
327
|
-
blob = xnew(wsg.Blob, [data])
|
|
328
|
-
reader = xnew(wsg.FileReader)
|
|
329
|
-
pending = new(nonce)
|
|
330
|
-
reader.onload = function(event) { pending.signal(event.target.result) }
|
|
331
|
-
reader.readAsDataURL(blob)
|
|
332
|
-
result = pending.wait()
|
|
333
|
-
result.slice(37)
|
|
334
|
-
}
|
|
335
|
-
//
|
|
336
376
|
// DecodeBase64url - decode base64url to original string
|
|
337
377
|
// See https://en.wikipedia.org/wiki/Base64 for details on variants
|
|
338
378
|
//
|
|
339
379
|
DecodeBase64url = function decodeBase64url(base64url, local padding) {
|
|
340
380
|
base64url = base64url.replace(RegExp("-", "g"), '+').replace(RegExp("_", "g"), '/')
|
|
341
|
-
|
|
381
|
+
DecodeBase64(base64url)
|
|
342
382
|
}
|
|
343
383
|
//
|
|
344
384
|
// For browser windows and web workers
|
|
345
385
|
//
|
|
346
386
|
if js.w || js.s {
|
|
387
|
+
//
|
|
388
|
+
// base64Format - create base 64 string from binary array
|
|
389
|
+
//
|
|
390
|
+
function browserBase64Format(data, local blob, reader, pending, result) {
|
|
391
|
+
blob = xnew(wsg.Blob, [data])
|
|
392
|
+
reader = xnew(wsg.FileReader)
|
|
393
|
+
pending = new(nonce)
|
|
394
|
+
reader.onload = function(event) { pending.signal(event.target.result) }
|
|
395
|
+
reader.readAsDataURL(blob)
|
|
396
|
+
result = pending.wait()
|
|
397
|
+
result.slice(37)
|
|
398
|
+
}
|
|
399
|
+
//
|
|
400
|
+
// binary to Base64
|
|
401
|
+
EncodeBase64 = function browserEncodeBase64(data) {
|
|
402
|
+
if xobject(data)
|
|
403
|
+
browserBase64Format(data)
|
|
404
|
+
else
|
|
405
|
+
wsg.btoa(data)
|
|
406
|
+
}
|
|
407
|
+
//
|
|
408
|
+
// Base64 to binary
|
|
409
|
+
DecodeBase64 = function browserDecodeBase64(data) {
|
|
410
|
+
wsg.atob(data)
|
|
411
|
+
}
|
|
347
412
|
//
|
|
348
413
|
// MD5 functions
|
|
349
414
|
JsLoadScript("frameworks/browser/spark-md5/spark-md5.min.js", "SparkMD5")
|
|
@@ -358,7 +423,7 @@ function comrInit(local manifest) {
|
|
|
358
423
|
//
|
|
359
424
|
// HashMD5 in base64
|
|
360
425
|
HashMD5_base64 = function browserMD5_base64(data) {
|
|
361
|
-
|
|
426
|
+
EncodeBase64(browserMD5(data, true)) }
|
|
362
427
|
//
|
|
363
428
|
// browserDigest - only in secure contexts (localhost and HTTPS)
|
|
364
429
|
//
|
|
@@ -367,7 +432,7 @@ function comrInit(local manifest) {
|
|
|
367
432
|
throw(Error("crypto functions unavailable"))
|
|
368
433
|
data = binaryFrom(data)
|
|
369
434
|
if string(data)
|
|
370
|
-
data =
|
|
435
|
+
data = Uint8ArrayFromString(data)
|
|
371
436
|
`(error, result) = await(wsg.crypto.subtle.digest(algo, data))
|
|
372
437
|
if error
|
|
373
438
|
throw(Error("crypto digest failed", error))
|
|
@@ -386,7 +451,7 @@ function comrInit(local manifest) {
|
|
|
386
451
|
//
|
|
387
452
|
// HashSHA-256 in base64
|
|
388
453
|
HashSHA256_base64 = function browserSHA256_base64(data) {
|
|
389
|
-
|
|
454
|
+
browserBase64Format(browserDigest(data, "SHA-256"))
|
|
390
455
|
}
|
|
391
456
|
//
|
|
392
457
|
// random bytes as UInt8Array - use toint() for integer
|
|
@@ -399,6 +464,16 @@ function comrInit(local manifest) {
|
|
|
399
464
|
// For NodeJS
|
|
400
465
|
//
|
|
401
466
|
if js.g {
|
|
467
|
+
//
|
|
468
|
+
// binary to Base64
|
|
469
|
+
EncodeBase64 = function nodejsEncodeBase64(data) {
|
|
470
|
+
wsg.Buffer.from(data, "binary").toString("base64")
|
|
471
|
+
}
|
|
472
|
+
//
|
|
473
|
+
// Base64 to binary
|
|
474
|
+
DecodeBase64 = function nodejsDecodeBase64(data) {
|
|
475
|
+
wsg.Buffer.from(data, "base64").toString("binary")
|
|
476
|
+
}
|
|
402
477
|
if !crypto
|
|
403
478
|
crypto = js.r("crypto")
|
|
404
479
|
if crypto {
|
|
@@ -431,6 +506,8 @@ function comrInit(local manifest) {
|
|
|
431
506
|
HashMD5 =
|
|
432
507
|
HashMD5_base64 =
|
|
433
508
|
HashSHA1 =
|
|
509
|
+
HashSHA256 =
|
|
510
|
+
HashSHA256_base64 =
|
|
434
511
|
RandomBytes = function() { throw(Error("crypto functions unavailable")) }
|
|
435
512
|
}
|
|
436
513
|
}
|
|
@@ -442,10 +519,13 @@ function comrInit(local manifest) {
|
|
|
442
519
|
modobj.exports.TextDecoder = TextDecoder
|
|
443
520
|
modobj.exports.EncodeURIComponent = EncodeURIComponent
|
|
444
521
|
modobj.exports.DecodeURIComponent = DecodeURIComponent
|
|
522
|
+
modobj.exports.EncodeBase64 = EncodeBase64
|
|
523
|
+
modobj.exports.DecodeBase64 = DecodeBase64
|
|
445
524
|
modobj.exports.JSONstringify = JSONstringify
|
|
446
525
|
modobj.exports.JSONparse = JSONparse
|
|
447
526
|
modobj.exports.JsonStringify = JsonStringify
|
|
448
527
|
modobj.exports.JsonParse = JsonParse
|
|
528
|
+
modobj.exports.Uint8ArrayFromString = Uint8ArrayFromString
|
|
449
529
|
modobj.exports.DecodeBase64url = DecodeBase64url
|
|
450
530
|
modobj.exports.HashMD5 = HashMD5
|
|
451
531
|
modobj.exports.HashMD5_base64 = HashMD5_base64
|
|
@@ -125,6 +125,7 @@ function prefsInit(local manifest) {
|
|
|
125
125
|
Naan.module.build(module.id, "preferences", function(modobj, compobj) {
|
|
126
126
|
require("../common/common.nlg")
|
|
127
127
|
compobj.manifest = manifest
|
|
128
|
+
updateExports()
|
|
128
129
|
})
|
|
129
130
|
|
|
130
131
|
module.exports.Preferences = Preferences
|