@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
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* https_node.nlg
|
|
3
|
+
*
|
|
4
|
+
* Https operations for NodeJS.
|
|
5
|
+
*
|
|
6
|
+
* column positioning: // // !
|
|
7
|
+
*
|
|
8
|
+
* Copyright (c) 2021-2022 by Richard C. Zulch
|
|
9
|
+
*
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
/*
|
|
14
|
+
* HttpsApiRequest
|
|
15
|
+
*
|
|
16
|
+
* Perform an API request from in NodeJS. This operates the same as HttpsApiRequest for browsers.
|
|
17
|
+
*
|
|
18
|
+
* Options:
|
|
19
|
+
* {
|
|
20
|
+
* method: <string> // HTTP method (defaults to GET/PUT)
|
|
21
|
+
* query: <dictionary> // query variables added to the URL
|
|
22
|
+
* putdata: <data> // data to put
|
|
23
|
+
* contentType: <string> // sets Content-Type header, otherwise auto-determined
|
|
24
|
+
* range: <string> // sets range header
|
|
25
|
+
* headers: [`(key, value)] // add header(s) to the request, overriding defaults
|
|
26
|
+
* }
|
|
27
|
+
*
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
closure HttpsApiRequest(url, options, local urlq, reqOptions, putdata, item, pending, chunks, request) {
|
|
31
|
+
if options.query
|
|
32
|
+
urlq = url.concat(EncodeQuery("?", options.query))
|
|
33
|
+
else
|
|
34
|
+
urlq = url
|
|
35
|
+
putdata = options.putdata
|
|
36
|
+
reqOptions = { }
|
|
37
|
+
if options.method
|
|
38
|
+
reqOptions.method = options.method
|
|
39
|
+
else if putdata
|
|
40
|
+
reqOptions.method = "POST"
|
|
41
|
+
else
|
|
42
|
+
reqOptions.method = "GET"
|
|
43
|
+
reqOptions.headers = { }
|
|
44
|
+
if putdata {
|
|
45
|
+
if options.contentType
|
|
46
|
+
reqOptions.headers['Content-Type'] = options.contentType
|
|
47
|
+
else if jsTypedArray(options.putdata)
|
|
48
|
+
reqOptions.headers['Content-Type'] = "application/octet-stream"
|
|
49
|
+
else if member(typeof(options.putdata), `(dictionary, array, xobject)) {
|
|
50
|
+
reqOptions.headers['Content-Type'] = "application/json"
|
|
51
|
+
`(error, putdata) = JsonStringify(options.putdata)
|
|
52
|
+
if error
|
|
53
|
+
return (list(Error("HttpsApiRequest encode:", url)))
|
|
54
|
+
}
|
|
55
|
+
fetchOptions.body = putdata
|
|
56
|
+
}
|
|
57
|
+
if array(options.headers)
|
|
58
|
+
for item in options.headers
|
|
59
|
+
reqOptions.headers[item.0] = item.1
|
|
60
|
+
pending = new(nonce)
|
|
61
|
+
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
|
+
}
|
|
69
|
+
response.on("data", function (chunk) {
|
|
70
|
+
chunks.push(chunk)
|
|
71
|
+
})
|
|
72
|
+
response.on("end", function (local content, error) {
|
|
73
|
+
content = Buffer.concat(chunks)
|
|
74
|
+
if response.complete {
|
|
75
|
+
if response.headers["content-type"].startsWith("application/json") {
|
|
76
|
+
`(error, content) = JsonParse(content.toString())
|
|
77
|
+
if error
|
|
78
|
+
error = Error("HttpsApiRequest decode:", url, error)
|
|
79
|
+
else
|
|
80
|
+
content = new(content)
|
|
81
|
+
if array(content) { // deencapsulate to get API result
|
|
82
|
+
content = totuple(content)
|
|
83
|
+
error = content.0
|
|
84
|
+
content = content.1
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
else
|
|
89
|
+
error = Error("HttpsApiRequest terminated prematurely:", url)
|
|
90
|
+
pending.signal(list(error, content))
|
|
91
|
+
})
|
|
92
|
+
})
|
|
93
|
+
request.on("error", function(error) {
|
|
94
|
+
error = Error("HttpsApiRequest failed:", url, error)
|
|
95
|
+
pending.signal(list(error))
|
|
96
|
+
})
|
|
97
|
+
if data
|
|
98
|
+
request.write(data)
|
|
99
|
+
request.end()
|
|
100
|
+
pending.wait()
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
/*
|
|
105
|
+
* https_nodeInit
|
|
106
|
+
*
|
|
107
|
+
* Initialize HTTPS request operations for NodeJS.
|
|
108
|
+
*
|
|
109
|
+
*/
|
|
110
|
+
|
|
111
|
+
function https_nodeInit(local manifest) {
|
|
112
|
+
manifest = `(HttpsGetJson, HttpsPutJson, https_nodeInit)
|
|
113
|
+
|
|
114
|
+
Naan.module.build(module.id, "https_request", function(modobj, compobj) {
|
|
115
|
+
require("./node.nlg")
|
|
116
|
+
compobj.manifest = manifest
|
|
117
|
+
modobj.exports.HttpsApiRequest = HttpsApiRequest
|
|
118
|
+
})
|
|
119
|
+
}();
|
package/frameworks/node/node.nlg
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* column positioning: // // !
|
|
8
8
|
*
|
|
9
|
-
* Copyright (c) 2019-
|
|
9
|
+
* Copyright (c) 2019-2022 by Richard C. Zulch
|
|
10
10
|
*
|
|
11
11
|
*/
|
|
12
12
|
|
|
@@ -27,12 +27,18 @@ closure psmsFsView(rootpath, local view, gitter) {
|
|
|
27
27
|
view = view.1
|
|
28
28
|
|
|
29
29
|
// inherited
|
|
30
|
+
// -- view.folderPath(folderid, callback)
|
|
30
31
|
// -- view.winDrives(callback)
|
|
31
32
|
// -- view.testHidden(path, callback)
|
|
32
33
|
// -- view.readLines(path, options, callback)
|
|
33
34
|
// -- view.readFile(path, options, callback)
|
|
34
35
|
// -- view.writeFile(path, data, options, callback)
|
|
35
|
-
// -- view.
|
|
36
|
+
// -- view.readlink(path, options, callback)
|
|
37
|
+
// -- view.symlink(target, path, options, callback)
|
|
38
|
+
// -- view.info(path, options, callback)
|
|
39
|
+
// -- view.setInfo(path, info, callback)
|
|
40
|
+
// -- view.setOwnerGroup(path, uid, gid, callback)
|
|
41
|
+
// -- view.setMode(path, mode, callback)
|
|
36
42
|
// -- view.setTimes(path, atime, mtime, callback)
|
|
37
43
|
// -- view.dirList(path, options, callback)
|
|
38
44
|
// -- view.mkdir(path, callback)
|
|
@@ -81,16 +87,27 @@ closure psmsFsView(rootpath, local view, gitter) {
|
|
|
81
87
|
}
|
|
82
88
|
res.send(new(array, result))
|
|
83
89
|
}
|
|
84
|
-
|
|
90
|
+
|
|
91
|
+
// op: folderPath
|
|
92
|
+
function folderPathApi() {
|
|
93
|
+
res.send(new(array, view.folderPath(req.query.folderid)))
|
|
94
|
+
}
|
|
95
|
+
|
|
85
96
|
// op: readLines
|
|
86
97
|
function readLinesApi() {
|
|
87
98
|
res.send(new(array, view.readLines(path, req.query)))
|
|
88
99
|
}
|
|
89
100
|
|
|
90
101
|
// op: readFile
|
|
91
|
-
function readFileApi(local options) {
|
|
102
|
+
function readFileApi(local error, localpath, options) {
|
|
103
|
+
`(error, localpath) = view.localPath(path)
|
|
104
|
+
if error {
|
|
105
|
+
res.send(new(array, list(error)))
|
|
106
|
+
return
|
|
107
|
+
}
|
|
92
108
|
options = {
|
|
93
|
-
dotfiles: "allow"
|
|
109
|
+
dotfiles: "allow"
|
|
110
|
+
}
|
|
94
111
|
if req.query.encoding == "binary"
|
|
95
112
|
options.headers = {
|
|
96
113
|
"Content-Type": "application/octet-stream"
|
|
@@ -99,7 +116,7 @@ closure psmsFsView(rootpath, local view, gitter) {
|
|
|
99
116
|
options.headers = { // ### is this always the right default?
|
|
100
117
|
"Content-Type": "text/html; charset=UTF-8"
|
|
101
118
|
}
|
|
102
|
-
res.sendFile(
|
|
119
|
+
res.sendFile(localpath, options, function (err, local status) {
|
|
103
120
|
if err {
|
|
104
121
|
if err.code == "ENOENT"
|
|
105
122
|
status = 404
|
|
@@ -118,7 +135,18 @@ closure psmsFsView(rootpath, local view, gitter) {
|
|
|
118
135
|
options.encoding = req.query.encoding
|
|
119
136
|
res.send(new(array, view.writeFile(path, req.body, options)))
|
|
120
137
|
}
|
|
121
|
-
|
|
138
|
+
|
|
139
|
+
// op: readlink
|
|
140
|
+
function readlinkApi() {
|
|
141
|
+
res.send(new(array, view.readlink(path)))
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// op: symlink
|
|
145
|
+
function symlinkApi(local options) {
|
|
146
|
+
options = { }
|
|
147
|
+
res.send(new(array, view.symlink(req.query.target, path, options)))
|
|
148
|
+
}
|
|
149
|
+
|
|
122
150
|
// op: delete
|
|
123
151
|
function deleteApi(local options) {
|
|
124
152
|
options = { }
|
|
@@ -130,8 +158,26 @@ closure psmsFsView(rootpath, local view, gitter) {
|
|
|
130
158
|
}
|
|
131
159
|
|
|
132
160
|
// op: info
|
|
133
|
-
function infoApi() {
|
|
134
|
-
|
|
161
|
+
function infoApi(local options) {
|
|
162
|
+
options - { }
|
|
163
|
+
if req.query.follow
|
|
164
|
+
options.follow = req.query.follow
|
|
165
|
+
res.send(new(array, view.info(path, options)))
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// op: setInfo
|
|
169
|
+
function setInfoApi() {
|
|
170
|
+
res.send(new(array, view.setInfo(path, req.body)))
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// op: setOwnerGroup
|
|
174
|
+
function setOwnerGroupApi() {
|
|
175
|
+
res.send(new(array, view.setOwnerGroup(path, req.query.uid, req.query.gid)))
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// op: setMode
|
|
179
|
+
function setModeApi() {
|
|
180
|
+
res.send(new(array, view.setMode(path, req.query.mode)))
|
|
135
181
|
}
|
|
136
182
|
|
|
137
183
|
// op: setTimes
|
|
@@ -141,8 +187,8 @@ closure psmsFsView(rootpath, local view, gitter) {
|
|
|
141
187
|
|
|
142
188
|
// op: dirList
|
|
143
189
|
function dirListApi(local options) {
|
|
144
|
-
if req.query.
|
|
145
|
-
options = {
|
|
190
|
+
if req.query.stat
|
|
191
|
+
options = { stat: true }
|
|
146
192
|
res.send(new(array, view.dirList(path, options)))
|
|
147
193
|
}
|
|
148
194
|
|
|
@@ -153,7 +199,7 @@ closure psmsFsView(rootpath, local view, gitter) {
|
|
|
153
199
|
|
|
154
200
|
// op: tree
|
|
155
201
|
function treeApi() {
|
|
156
|
-
res.send(new(array, view.tree(path, req.query.depthlimit)))
|
|
202
|
+
res.send(new(array, view.tree(path, toint(req.query.depthlimit))))
|
|
157
203
|
}
|
|
158
204
|
|
|
159
205
|
// op: dirSearch
|
|
@@ -216,11 +262,17 @@ closure psmsFsView(rootpath, local view, gitter) {
|
|
|
216
262
|
|
|
217
263
|
proc = {
|
|
218
264
|
pathOp: pathOpApi
|
|
265
|
+
folderPath: folderPathApi
|
|
219
266
|
readFile: readFileApi
|
|
220
267
|
readLines: readLinesApi
|
|
221
268
|
writeFile: writeFileApi
|
|
269
|
+
readlink: readlinkApi
|
|
270
|
+
symlink: symlinkApi
|
|
222
271
|
delete: deleteApi
|
|
223
272
|
info: infoApi
|
|
273
|
+
setInfo: setInfoApi
|
|
274
|
+
setOwnerGroup: setOwnerGroupApi
|
|
275
|
+
setMode: setModeApi
|
|
224
276
|
setTimes: setTimesApi
|
|
225
277
|
dirList: dirListApi
|
|
226
278
|
mkdir: mkdirApi
|
|
@@ -263,38 +315,38 @@ closure psmsFsConnector(psm, api, local connClassID, connector, watch) {
|
|
|
263
315
|
connector.vault = psm.vault(connClassID)
|
|
264
316
|
connector.label = "Naan IDE Server"
|
|
265
317
|
watch = psm.watchable(connector)
|
|
266
|
-
|
|
267
|
-
// hashResourceID
|
|
268
|
-
//
|
|
269
|
-
// Make a stable hash based on the resource credentials that we can persist or share between
|
|
270
|
-
// different domains accessing the same resource.
|
|
271
|
-
connector.hashResourceID = function hashResourceID(resource, local ident) {
|
|
272
|
-
ident = resource.urlName
|
|
273
|
-
if resource.label
|
|
274
|
-
ident = ident.concat(resource.label)
|
|
275
|
-
HashSHA256(ident)
|
|
276
|
-
}
|
|
277
|
-
|
|
318
|
+
|
|
278
319
|
// findResource
|
|
279
320
|
//
|
|
280
|
-
// Find a resource with the specified contents, returning the resID or false.
|
|
281
|
-
// is: if added, would the specified contents be redundant to an existing resource?
|
|
321
|
+
// Find a resource with the specified contents, returning the resID or false.
|
|
282
322
|
connector.findResource = function findResource(resource, local resID, creds) {
|
|
283
323
|
for resID in listResources().1 {
|
|
284
324
|
creds = access(resID).1
|
|
285
|
-
if resource.urlName == creds.urlName
|
|
286
|
-
&& (!resource.label || resource.label == creds.label)
|
|
325
|
+
if ((!resource.urlName || resource.urlName == creds.urlName)
|
|
326
|
+
&& (!resource.label || resource.label == creds.label))
|
|
287
327
|
return (resID)
|
|
288
328
|
}
|
|
289
329
|
false
|
|
290
330
|
}
|
|
291
331
|
|
|
292
|
-
//
|
|
332
|
+
// writeResource
|
|
293
333
|
//
|
|
294
|
-
// Add credentials for a named resource.
|
|
295
|
-
|
|
296
|
-
|
|
334
|
+
// Add or update credentials for a named resource. If no resID is specified this adds a new
|
|
335
|
+
// resource; otherwise it updates an existing one. The resource is a dictionary comprising these
|
|
336
|
+
// keys:
|
|
337
|
+
// label - [optional] label we use for this resource
|
|
338
|
+
// urlName - URL (e.g. "http://host.com/node/fsapi")
|
|
339
|
+
// authSecret - access-control token for this URL
|
|
340
|
+
// hidden - [optional] don't enumerate to user
|
|
341
|
+
// locked - [optional] don't allow user delete
|
|
342
|
+
//
|
|
343
|
+
// The return value is an (error, resID) tuple. Error, if non-false, is a dictionary of field
|
|
344
|
+
// keys and error diagnostic strings.
|
|
345
|
+
connector.writeResource = function writeResource(resource, resID,
|
|
346
|
+
local creds, errors, error, data, change) {
|
|
347
|
+
// badField - test for a bad string
|
|
297
348
|
function badField(str) { !string(str) || str.trim().length == 0 }
|
|
349
|
+
|
|
298
350
|
creds = { urlName: resource.urlName }
|
|
299
351
|
errors = { }
|
|
300
352
|
if resource.label
|
|
@@ -303,6 +355,8 @@ closure psmsFsConnector(psm, api, local connClassID, connector, watch) {
|
|
|
303
355
|
creds.label = resource.urlName
|
|
304
356
|
if badField(creds.label)
|
|
305
357
|
errors.label = "invalid label"
|
|
358
|
+
else if !resID && findResource({ label: creds.label })
|
|
359
|
+
errors.label = "duplicate name"
|
|
306
360
|
if badField(resource.urlName)
|
|
307
361
|
errors.urlName = "required field"
|
|
308
362
|
if length(errors) > 0
|
|
@@ -312,14 +366,36 @@ closure psmsFsConnector(psm, api, local connClassID, connector, watch) {
|
|
|
312
366
|
creds.hidden = resource.hidden
|
|
313
367
|
if resource.locked
|
|
314
368
|
creds.locked = resource.locked
|
|
315
|
-
resID
|
|
316
|
-
|
|
369
|
+
if resID {
|
|
370
|
+
`(error, data) = connector.vault.updateResource(resID, creds)
|
|
371
|
+
change = { changed: [resID] }
|
|
372
|
+
} else {
|
|
373
|
+
resID = UUID()
|
|
374
|
+
`(error, data) = connector.vault.addResource(resID, creds)
|
|
375
|
+
change = { added: [resID] }
|
|
376
|
+
}
|
|
317
377
|
if data {
|
|
318
|
-
watch.notify(connClassID,
|
|
319
|
-
data = resID
|
|
378
|
+
watch.notify(connClassID, change)
|
|
379
|
+
data = resID
|
|
380
|
+
}
|
|
381
|
+
}
|
|
320
382
|
list(error, data)
|
|
321
383
|
}
|
|
322
|
-
|
|
384
|
+
|
|
385
|
+
// addResource
|
|
386
|
+
//
|
|
387
|
+
// Add a new resource, returning a standard error tuple per writeResource.
|
|
388
|
+
connector.addResource = function addResource(resource) {
|
|
389
|
+
writeResource(resource)
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// updateResource
|
|
393
|
+
//
|
|
394
|
+
// Update an existing resource, returning a standard error tuple per writeResource.
|
|
395
|
+
connector.updateResource = function updateResource(resID, resource) {
|
|
396
|
+
writeResource(resource, resID)
|
|
397
|
+
}
|
|
398
|
+
|
|
323
399
|
// getResource
|
|
324
400
|
//
|
|
325
401
|
// Get credentials for a named resource, matching the dictionary semantics of addResource. The
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* column positioning: // // !
|
|
8
8
|
*
|
|
9
|
-
* Copyright (c) 2019-
|
|
9
|
+
* Copyright (c) 2019-2022 by Richard C. Zulch
|
|
10
10
|
*
|
|
11
11
|
*/
|
|
12
12
|
|
|
@@ -267,15 +267,20 @@ closure Builder(rules, operation, fs, srcpath, destpath, local build, group, new
|
|
|
267
267
|
//
|
|
268
268
|
// applySubstitutions
|
|
269
269
|
//
|
|
270
|
-
// Apply substitutions from readSubstitutionFile to string, returning a
|
|
270
|
+
// Apply substitutions from readSubstitutionFile to string, returning a tuple of the resulting
|
|
271
|
+
// text and the number of substitution patterns actually used from the supplied dictionary.
|
|
271
272
|
//
|
|
272
|
-
function applySubstitutions(text, subs) {
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
273
|
+
function applySubstitutions(text, subs, local subbed) {
|
|
274
|
+
subbed = { }
|
|
275
|
+
list(text.replace(RegExp("[$][-A-Za-z0-9_./()\\\\]+[$]", "g"), function(match, local subst) {
|
|
276
|
+
subst = subs[match.slice(1,-1)]
|
|
277
|
+
if subst {
|
|
278
|
+
subbed[match] = true
|
|
279
|
+
subst
|
|
280
|
+
}
|
|
276
281
|
else
|
|
277
282
|
match
|
|
278
|
-
})
|
|
283
|
+
}), length(subbed))
|
|
279
284
|
}
|
|
280
285
|
|
|
281
286
|
//
|
|
@@ -573,7 +578,7 @@ closure Builder(rules, operation, fs, srcpath, destpath, local build, group, new
|
|
|
573
578
|
//
|
|
574
579
|
// Handling the catenates is a bit tricky. One set of buildrules can have multiple catentates,
|
|
575
580
|
// distinguished by having a unique writepath derived from the destfile parameter. All groups
|
|
576
|
-
// having the same writepath contribute to a single catenate, with the sources
|
|
581
|
+
// having the same writepath contribute to a single catenate, with the sources ordered first by
|
|
577
582
|
// group number (low to high) and then order in the source list, first to last. If any component
|
|
578
583
|
// contributing to a catenate is out-of-date with respect to it then they are all built and
|
|
579
584
|
// combined into the single output file. This computes a set of ordering integers for the parts
|
|
@@ -649,13 +654,13 @@ closure Builder(rules, operation, fs, srcpath, destpath, local build, group, new
|
|
|
649
654
|
outfile = JSpath.join(outdirpath, group.destfile)
|
|
650
655
|
else
|
|
651
656
|
outfile = JSpath.join(outdirpath, source)
|
|
652
|
-
fs.info(infile, function(error, instat, local listing, addgroup, file) {
|
|
657
|
+
fs.info(infile, false, function(error, instat, local listing, addgroup, file) {
|
|
653
658
|
if error
|
|
654
659
|
build.errorlist.push(error)
|
|
655
660
|
else if instat.type != "directory"
|
|
656
661
|
addEntry(infile, outfile, instat, sdex) // add execution entry if needed
|
|
657
662
|
else { // add a new group for directory source
|
|
658
|
-
`(error, listing) = fs.dirList(infile, {
|
|
663
|
+
`(error, listing) = fs.dirList(infile, { stat: true })
|
|
659
664
|
if error
|
|
660
665
|
build.errorlist.push(error)
|
|
661
666
|
else {
|
|
@@ -754,19 +759,20 @@ closure Builder(rules, operation, fs, srcpath, destpath, local build, group, new
|
|
|
754
759
|
entry.zip = true
|
|
755
760
|
if !entry.writepath.toLowerCase().endsWith(".zip")
|
|
756
761
|
entry.writepath = entry.writepath.concat(".zip") // always ends with .zip
|
|
762
|
+
outfile = entry.writepath
|
|
757
763
|
}
|
|
758
764
|
if entry.catenate || entry.zip {
|
|
759
765
|
entry.catorder = group.groupno * sourcemax + sdex // order of groups then sources
|
|
760
766
|
if build.testats[outfile] && instat.mtimeMs < build.testats[outfile].mtimeMs
|
|
761
767
|
instat = build.testats[outfile] // make source at least as recent as template
|
|
762
|
-
} else
|
|
768
|
+
} else if !entry.unzip
|
|
763
769
|
entry.writepath = outfile
|
|
764
770
|
++pending.active
|
|
765
771
|
if destcheck { // destcheck is special target for determining if task needed
|
|
766
772
|
entry.destcheck = JSpath.join(outdirpath, destcheck.pop())
|
|
767
|
-
fs.info(entry.destcheck, addIfOutOfDate)
|
|
773
|
+
fs.info(entry.destcheck, false, addIfOutOfDate)
|
|
768
774
|
} else
|
|
769
|
-
fs.info(outfile, addIfOutOfDate)
|
|
775
|
+
fs.info(outfile, false, addIfOutOfDate)
|
|
770
776
|
|
|
771
777
|
function addIfOutOfDate(error, outstat, local entryop) {
|
|
772
778
|
if error || toint(instat.mtimeMs) > toint(outstat.mtimeMs) {
|
|
@@ -861,9 +867,8 @@ closure Builder(rules, operation, fs, srcpath, destpath, local build, group, new
|
|
|
861
867
|
if error
|
|
862
868
|
build.errorlist.push(error)
|
|
863
869
|
else if content.startsWith("$$") // prefix to cause version substitution
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
build.templates[writepath] = content
|
|
870
|
+
`(content) = applySubstitutions(content.slice(2), verFileDefs)
|
|
871
|
+
build.templates[writepath] = content
|
|
867
872
|
}
|
|
868
873
|
} ()
|
|
869
874
|
}
|
|
@@ -890,13 +895,21 @@ closure Builder(rules, operation, fs, srcpath, destpath, local build, group, new
|
|
|
890
895
|
`(error, result) = fs.unzip(entry.readpath, entry.writepath) // unzip source into destination
|
|
891
896
|
if !error && entry.destcheck
|
|
892
897
|
fs.touch(entry.destcheck) // show we completed
|
|
893
|
-
} else if entry.copy
|
|
894
|
-
`(error, result) = fs.
|
|
898
|
+
} else if entry.copy {
|
|
899
|
+
`(error, result) = fs.util.deepcopy(entry.readpath, false, fs, dirpath, {
|
|
900
|
+
erase: true // not really needed
|
|
901
|
+
overwrite: true // overwrite files
|
|
902
|
+
force: true // ignore modify date
|
|
903
|
+
preserve: true // preserve attributes
|
|
904
|
+
})
|
|
905
|
+
if error // deepcopy returns a list of errors
|
|
906
|
+
error = error.0 // but we're only doing one item
|
|
907
|
+
}
|
|
895
908
|
else if ((`(error, content) = fs.readFile(entry.readpath)) && !error) {
|
|
896
909
|
if entry.license
|
|
897
|
-
content = applySubstitutions(content, licFileDefs)
|
|
910
|
+
`(content) = applySubstitutions(content, licFileDefs)
|
|
898
911
|
if entry.version
|
|
899
|
-
content = applySubstitutions(content, verFileDefs)
|
|
912
|
+
`(content) = applySubstitutions(content, verFileDefs)
|
|
900
913
|
if entry.naanpack
|
|
901
914
|
`(error, content) = parseAndPack(content, entry.readpath, { naanpack: true })
|
|
902
915
|
else if entry.jspack
|
|
@@ -962,11 +975,15 @@ closure Builder(rules, operation, fs, srcpath, destpath, local build, group, new
|
|
|
962
975
|
docat = true
|
|
963
976
|
}
|
|
964
977
|
if docat { // catenate the files
|
|
965
|
-
if template
|
|
966
|
-
content = applySubstitutions(template, catsub)
|
|
978
|
+
if template {
|
|
979
|
+
`(content, result) = applySubstitutions(template, catsub)
|
|
980
|
+
if length(catsub) != result
|
|
981
|
+
build.errorlist.push(Error("Matched ", result, " of ", length(catsub),
|
|
982
|
+
"substitutions in template:", build.tepaths[writepath]))
|
|
983
|
+
}
|
|
967
984
|
else
|
|
968
985
|
content = catenates[writepath].map(function(entry){entry.content}).join("\n")
|
|
969
|
-
if
|
|
986
|
+
if dozip {
|
|
970
987
|
zipmap = { }
|
|
971
988
|
zipmap[JSpath.basename(writepath)] = content
|
|
972
989
|
`(error, content) = zip(zipmap) // compress the catenated file
|
|
@@ -27,7 +27,7 @@ closure proj_cliserInstance(projman, where, projID, local project) {
|
|
|
27
27
|
project.name = where.name
|
|
28
28
|
project.where = where
|
|
29
29
|
project.projID = projID
|
|
30
|
-
project.config = projConfig(projman, where)
|
|
30
|
+
project.config = projConfig(projman, where, projID)
|
|
31
31
|
|
|
32
32
|
// create
|
|
33
33
|
//
|
|
@@ -63,8 +63,16 @@ closure proj_cliserInstance(projman, where, projID, local project) {
|
|
|
63
63
|
//
|
|
64
64
|
// Run the project by building and then launching.
|
|
65
65
|
//
|
|
66
|
-
project.run = closure run(buildonly) {
|
|
67
|
-
project.config.run(buildonly)
|
|
66
|
+
project.run = closure run(stage, buildonly) {
|
|
67
|
+
project.config.run(stage, buildonly)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// publish
|
|
71
|
+
//
|
|
72
|
+
// Publish the project according to the stage.
|
|
73
|
+
//
|
|
74
|
+
project.publish = closure publish(stage) {
|
|
75
|
+
project.config.publish(stage)
|
|
68
76
|
}
|
|
69
77
|
|
|
70
78
|
// close()
|
|
@@ -27,7 +27,7 @@ closure proj_consoleInstance(projman, where, projID, local project) {
|
|
|
27
27
|
project.name = where.name
|
|
28
28
|
project.where = where
|
|
29
29
|
project.projID = projID
|
|
30
|
-
project.config = projConfig(projman, where)
|
|
30
|
+
project.config = projConfig(projman, where, projID)
|
|
31
31
|
project.runPageDebug = true // switch to Debug page on run
|
|
32
32
|
|
|
33
33
|
// create
|
|
@@ -60,9 +60,18 @@ closure proj_consoleInstance(projman, where, projID, local project) {
|
|
|
60
60
|
|
|
61
61
|
// run
|
|
62
62
|
//
|
|
63
|
-
//
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
// Run the project by building and then launching.
|
|
64
|
+
//
|
|
65
|
+
project.run = closure run(stage, buildonly) {
|
|
66
|
+
project.config.run(stage, buildonly)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// publish
|
|
70
|
+
//
|
|
71
|
+
// Publish the project according to the stage.
|
|
72
|
+
//
|
|
73
|
+
project.publish = closure publish(stage) {
|
|
74
|
+
project.config.publish(stage)
|
|
66
75
|
}
|
|
67
76
|
|
|
68
77
|
// close
|
|
@@ -61,11 +61,20 @@ closure proj_folderInstance(projman, where, projID, local project) {
|
|
|
61
61
|
// run
|
|
62
62
|
//
|
|
63
63
|
// Run the project by building and then launching.
|
|
64
|
-
project.run = closure run(buildonly) {
|
|
64
|
+
project.run = closure run(stage, buildonly) {
|
|
65
65
|
debuglog("folder run project stub")
|
|
66
66
|
list(false, { ok: true })
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
// publish
|
|
70
|
+
//
|
|
71
|
+
// Publish the project according to the stage.
|
|
72
|
+
//
|
|
73
|
+
project.publish = closure publish(stage) {
|
|
74
|
+
debuglog("folder publish project stub")
|
|
75
|
+
list(false, { ok: true })
|
|
76
|
+
}
|
|
77
|
+
|
|
69
78
|
// close
|
|
70
79
|
//
|
|
71
80
|
// Close the project, releasing resources.
|
|
@@ -27,7 +27,7 @@ closure proj_lambdaInstance(projman, where, projID, local project) {
|
|
|
27
27
|
project.name = where.name
|
|
28
28
|
project.where = where
|
|
29
29
|
project.projID = projID
|
|
30
|
-
project.config = projConfig(projman, where)
|
|
30
|
+
project.config = projConfig(projman, where, projID)
|
|
31
31
|
project.runPageDebug = true // switch to Debug page on run
|
|
32
32
|
|
|
33
33
|
// create
|
|
@@ -60,9 +60,18 @@ closure proj_lambdaInstance(projman, where, projID, local project) {
|
|
|
60
60
|
|
|
61
61
|
// run
|
|
62
62
|
//
|
|
63
|
-
//
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
// Run the project by building and then launching.
|
|
64
|
+
//
|
|
65
|
+
project.run = closure run(stage, buildonly) {
|
|
66
|
+
project.config.run(stage, buildonly)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// publish
|
|
70
|
+
//
|
|
71
|
+
// Publish the project according to the stage.
|
|
72
|
+
//
|
|
73
|
+
project.publish = closure publish(stage) {
|
|
74
|
+
project.config.publish(stage)
|
|
66
75
|
}
|
|
67
76
|
|
|
68
77
|
// close
|
|
@@ -26,7 +26,7 @@ closure proj_staticInstance(projman, where, projID, local project) {
|
|
|
26
26
|
project.name = where.name
|
|
27
27
|
project.where = where
|
|
28
28
|
project.projID = projID
|
|
29
|
-
project.config = projConfig(projman, where)
|
|
29
|
+
project.config = projConfig(projman, where, projID)
|
|
30
30
|
|
|
31
31
|
// create
|
|
32
32
|
//
|
|
@@ -62,8 +62,16 @@ closure proj_staticInstance(projman, where, projID, local project) {
|
|
|
62
62
|
//
|
|
63
63
|
// Run the project by building and then launching.
|
|
64
64
|
//
|
|
65
|
-
project.run = closure run(buildonly) {
|
|
66
|
-
project.config.run(buildonly)
|
|
65
|
+
project.run = closure run(stage, buildonly) {
|
|
66
|
+
project.config.run(stage, buildonly)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// publish
|
|
70
|
+
//
|
|
71
|
+
// Publish the project according to the stage.
|
|
72
|
+
//
|
|
73
|
+
project.publish = closure publish(stage) {
|
|
74
|
+
project.config.publish(stage)
|
|
67
75
|
}
|
|
68
76
|
|
|
69
77
|
// close()
|