@naanlang/naan 1.0.3 → 1.0.6
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 +8 -6
- package/bin/index.js +2 -2
- package/dist/env_web.js +30 -6
- package/dist/naan.min.js +4 -4
- package/frameworks/browser/https_request.nlg +120 -0
- package/frameworks/browser/sworker.js +29 -39
- package/frameworks/browser/terminals.nlg +6 -4
- package/frameworks/browser/workers.nlg +13 -6
- package/frameworks/client/apiclient.nlg +1 -1
- package/frameworks/client/psm_client.nlg +80 -32
- package/frameworks/common/common.nlg +104 -26
- package/frameworks/common/preferences.nlg +1 -0
- package/frameworks/common/watching.nlg +1 -0
- package/frameworks/node/apiserver.nlg +9 -5
- package/frameworks/node/filesystem.nlg +89 -31
- 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 +29 -7
- package/frameworks/project/build.nlg +13 -7
- 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 +102 -20
- package/lib/browser/env_web.js +32 -8
- package/lib/core/naanlib.js +4 -4
- 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 +7 -6
- package/plugins/serviceAws/aws_dynamo.nlg +128 -45
- package/plugins/serviceAws/aws_lambda.nlg +11 -4
- package/plugins/serviceAws/aws_s3.nlg +44 -14
- package/plugins/serviceAws/dbt_aws.nlg +29 -36
- package/plugins/serviceAws/psm_aws.nlg +21 -16
- package/plugins/serviceAws/serviceAws.nlg +6 -4
- 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
|
@@ -27,6 +27,7 @@ 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)
|
|
@@ -86,16 +87,27 @@ closure psmsFsView(rootpath, local view, gitter) {
|
|
|
86
87
|
}
|
|
87
88
|
res.send(new(array, result))
|
|
88
89
|
}
|
|
89
|
-
|
|
90
|
+
|
|
91
|
+
// op: folderPath
|
|
92
|
+
function folderPathApi() {
|
|
93
|
+
res.send(new(array, view.folderPath(req.query.folderid)))
|
|
94
|
+
}
|
|
95
|
+
|
|
90
96
|
// op: readLines
|
|
91
97
|
function readLinesApi() {
|
|
92
98
|
res.send(new(array, view.readLines(path, req.query)))
|
|
93
99
|
}
|
|
94
100
|
|
|
95
101
|
// op: readFile
|
|
96
|
-
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
|
+
}
|
|
97
108
|
options = {
|
|
98
|
-
dotfiles: "allow"
|
|
109
|
+
dotfiles: "allow"
|
|
110
|
+
}
|
|
99
111
|
if req.query.encoding == "binary"
|
|
100
112
|
options.headers = {
|
|
101
113
|
"Content-Type": "application/octet-stream"
|
|
@@ -104,7 +116,7 @@ closure psmsFsView(rootpath, local view, gitter) {
|
|
|
104
116
|
options.headers = { // ### is this always the right default?
|
|
105
117
|
"Content-Type": "text/html; charset=UTF-8"
|
|
106
118
|
}
|
|
107
|
-
res.sendFile(
|
|
119
|
+
res.sendFile(localpath, options, function (err, local status) {
|
|
108
120
|
if err {
|
|
109
121
|
if err.code == "ENOENT"
|
|
110
122
|
status = 404
|
|
@@ -187,11 +199,12 @@ closure psmsFsView(rootpath, local view, gitter) {
|
|
|
187
199
|
|
|
188
200
|
// op: tree
|
|
189
201
|
function treeApi() {
|
|
190
|
-
res.send(new(array, view.tree(path, req.query.depthlimit)))
|
|
202
|
+
res.send(new(array, view.tree(path, toint(req.query.depthlimit))))
|
|
191
203
|
}
|
|
192
204
|
|
|
193
205
|
// op: dirSearch
|
|
194
206
|
function dirSearchApi() {
|
|
207
|
+
req.query.excludeDirs = JSONparse(req.query.excludeDirs)
|
|
195
208
|
res.send(new(array, view.dirSearch(path, req.query)))
|
|
196
209
|
}
|
|
197
210
|
|
|
@@ -227,6 +240,7 @@ closure psmsFsView(rootpath, local view, gitter) {
|
|
|
227
240
|
|
|
228
241
|
// op: grepLines
|
|
229
242
|
function grepLinesApi() {
|
|
243
|
+
req.query.excludeDirs = JSONparse(req.query.excludeDirs)
|
|
230
244
|
res.send(new(array, view.grepLines(path, req.query)))
|
|
231
245
|
}
|
|
232
246
|
|
|
@@ -250,6 +264,7 @@ closure psmsFsView(rootpath, local view, gitter) {
|
|
|
250
264
|
|
|
251
265
|
proc = {
|
|
252
266
|
pathOp: pathOpApi
|
|
267
|
+
folderPath: folderPathApi
|
|
253
268
|
readFile: readFileApi
|
|
254
269
|
readLines: readLinesApi
|
|
255
270
|
writeFile: writeFileApi
|
|
@@ -276,8 +291,15 @@ closure psmsFsView(rootpath, local view, gitter) {
|
|
|
276
291
|
gitLog: gitLogApi
|
|
277
292
|
gitShowFile: gitShowFileApi
|
|
278
293
|
}[req.query.op]
|
|
279
|
-
if proc
|
|
280
|
-
|
|
294
|
+
if proc {
|
|
295
|
+
try {
|
|
296
|
+
proc()
|
|
297
|
+
} catch {
|
|
298
|
+
if true {
|
|
299
|
+
res.status(400).send("psm op failed: ".concat(req.query.op, ": ", exception))
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
281
303
|
else
|
|
282
304
|
res.status(400).send("invalid psm op: ".concat(req.query.op))
|
|
283
305
|
}
|
|
@@ -1024,13 +1024,14 @@ closure Builder(rules, operation, fs, srcpath, destpath, local build, group, new
|
|
|
1024
1024
|
// } ... ]
|
|
1025
1025
|
// }
|
|
1026
1026
|
//
|
|
1027
|
-
build.make = closure make(
|
|
1027
|
+
build.make = closure make(options, local sink, xchan, entry, outext, error) {
|
|
1028
1028
|
sink = new(textstream, "", `string) // log all output
|
|
1029
1029
|
xchan = textstreams(list(sink, sink))
|
|
1030
1030
|
try {
|
|
1031
1031
|
resetlist()
|
|
1032
|
-
analyze(debugMake)
|
|
1033
|
-
if debugMake {
|
|
1032
|
+
analyze(options.debugMake)
|
|
1033
|
+
if options.debugMake {
|
|
1034
|
+
printline("Debugging make for ", options.buildnum, "-", options.stage)
|
|
1034
1035
|
if build.errorlist.length == 0 {
|
|
1035
1036
|
printline("build operations (", build.filelist.length, ") for ", operation)
|
|
1036
1037
|
for entry in build.filelist
|
|
@@ -1052,6 +1053,8 @@ closure Builder(rules, operation, fs, srcpath, destpath, local build, group, new
|
|
|
1052
1053
|
"\ndate: ", Date(),
|
|
1053
1054
|
"\nfrom: ", JSpath.join(fs.rootpath, build.srcpath),
|
|
1054
1055
|
"\n to: ", build.destpath,
|
|
1056
|
+
"\ntype: ", options.stage,
|
|
1057
|
+
"\nvers: ", options.buildnum,
|
|
1055
1058
|
"\n", sink.taketext())
|
|
1056
1059
|
`(error) = fs.writeFile(JSpath.join(build.destpath, "build_log.txt"), outext)
|
|
1057
1060
|
if error
|
|
@@ -1153,14 +1156,17 @@ closure Builder(rules, operation, fs, srcpath, destpath, local build, group, new
|
|
|
1153
1156
|
//
|
|
1154
1157
|
// build.refresh
|
|
1155
1158
|
//
|
|
1156
|
-
// Refresh after updating the v-site
|
|
1159
|
+
// Refresh after updating the v-site, returning true iff an existing vsite was found.
|
|
1157
1160
|
//
|
|
1158
|
-
build.refresh = function refresh(track local main, url_origin) {
|
|
1161
|
+
build.refresh = function refresh(track local main, url_origin, found) {
|
|
1159
1162
|
if build.runway."v-site" {
|
|
1160
1163
|
url_origin = js.w.location.origin.concat("/run", build.runway."v-site")
|
|
1161
|
-
for target in track.enumlist()
|
|
1162
|
-
target.vsiteRefresh(url_origin)
|
|
1164
|
+
for target in track.enumlist() {
|
|
1165
|
+
if target.vsiteRefresh(url_origin)
|
|
1166
|
+
found = true
|
|
1167
|
+
}
|
|
1163
1168
|
}
|
|
1169
|
+
found
|
|
1164
1170
|
}
|
|
1165
1171
|
|
|
1166
1172
|
//
|
|
@@ -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()
|
|
@@ -23,6 +23,7 @@ closure ProjectManager(locate, track, dbname, local error, proj) {
|
|
|
23
23
|
`(error, proj) = storageResources.ResourceManager(dbname, "Projects/")
|
|
24
24
|
if error
|
|
25
25
|
return(list(error))
|
|
26
|
+
proj.configLocal = proj.vault("configlocal") // local config storage
|
|
26
27
|
proj.locate = locate // storage locations
|
|
27
28
|
proj.track = track // execution tracking
|
|
28
29
|
proj.types = []
|
|
@@ -226,7 +227,9 @@ closure projConnector(projman, projtype, local connector, watch) {
|
|
|
226
227
|
// deleteResource
|
|
227
228
|
//
|
|
228
229
|
// Delete information for a project. The return value is (error, result) tuple.
|
|
229
|
-
connector.deleteResource = function deleteResource(resID) {
|
|
230
|
+
connector.deleteResource = function deleteResource(resID, local localID) {
|
|
231
|
+
localID = resID.concat("-data")
|
|
232
|
+
projman.configLocal.deleteResource(localID) // remove local storage if there is any
|
|
230
233
|
connector.vault.deleteResource(resID)
|
|
231
234
|
watch.notify(projtype.classID, { deleted: [resID] })
|
|
232
235
|
list(false, { ok: true})
|
|
@@ -293,7 +296,7 @@ closure projConnector(projman, projtype, local connector, watch) {
|
|
|
293
296
|
*
|
|
294
297
|
* Nide.proj/
|
|
295
298
|
* nide_cliser.cfg - JSON definition of the project (see below)
|
|
296
|
-
* NaanIDE_version.txt - [default] substitution file defining 1.0.
|
|
299
|
+
* NaanIDE_version.txt - [default] substitution file defining 1.0.6-1 etc.
|
|
297
300
|
* NaanIDE_version_builds.txt - [default] contains current build number as decimal string
|
|
298
301
|
* build/ - [optional] default build output location
|
|
299
302
|
* NaanIDE.lic - [optional] defines Zulch Laboratories, Inc. and other license info
|
|
@@ -306,6 +309,10 @@ closure projConnector(projman, projtype, local connector, watch) {
|
|
|
306
309
|
* build: <build instructions dictionary>
|
|
307
310
|
* }
|
|
308
311
|
*
|
|
312
|
+
* A project configuration also stores local data that is not in any file, which is useful for
|
|
313
|
+
* items like accounts & locations, or credentials that should not be "on disk". Project data from
|
|
314
|
+
* the .cfg file is available in config.configDict, while local data is in config.localDict.
|
|
315
|
+
*
|
|
309
316
|
* Given a new projConfig instance, you can either load (which fails of the project is not valid)
|
|
310
317
|
* or create (which fails if the project already exists.) The load operation will update the where
|
|
311
318
|
* argument with the actual name and type found. Unless other noted the methods all return standard
|
|
@@ -316,9 +323,12 @@ closure projConnector(projman, projtype, local connector, watch) {
|
|
|
316
323
|
proj_configDataFolder = "Nide.proj/";
|
|
317
324
|
proj_cliserConfigFile = "nide_cliser.cfg";
|
|
318
325
|
|
|
319
|
-
closure projConfig(projman, where, local procon, fs, configpath) {
|
|
326
|
+
closure projConfig(projman, where, projID, local procon, fs, configpath) {
|
|
320
327
|
procon = new(object, this)
|
|
321
328
|
procon.name = where.name
|
|
329
|
+
procon.dirName = proj_configDataFolder.slice(0,-1) // remove terminal "/"
|
|
330
|
+
if projID
|
|
331
|
+
procon.localID = projID.concat("-data")
|
|
322
332
|
|
|
323
333
|
// validate
|
|
324
334
|
//
|
|
@@ -376,6 +386,15 @@ closure projConfig(projman, where, local procon, fs, configpath) {
|
|
|
376
386
|
return (list(Error("can't parse project configuration", where.path, exception))) }
|
|
377
387
|
procon.where_name = where.name // copy name to config
|
|
378
388
|
procon.where_typeID = where.typeID // copy typeID to config
|
|
389
|
+
if procon.localID {
|
|
390
|
+
`(error, data) = projman.configLocal.accessResource(procon.localID)
|
|
391
|
+
if data
|
|
392
|
+
procon.localDict = data
|
|
393
|
+
else {
|
|
394
|
+
procon.localDict = { }
|
|
395
|
+
projman.configLocal.addResource(procon.localID, procon.localDict)
|
|
396
|
+
}
|
|
397
|
+
}
|
|
379
398
|
list(false, procon.configDict)
|
|
380
399
|
}
|
|
381
400
|
|
|
@@ -384,6 +403,11 @@ closure projConfig(projman, where, local procon, fs, configpath) {
|
|
|
384
403
|
// Write procon.configDict to our configuration file, returning a result tuple.
|
|
385
404
|
//
|
|
386
405
|
closure writeConfig(local error, info, data) {
|
|
406
|
+
if procon.localID {
|
|
407
|
+
`(error, data) = projman.configLocal.updateResource(procon.localID, procon.localDict)
|
|
408
|
+
if error
|
|
409
|
+
debuglog("projConfig.writeConfig cannot write local storage:", ErrorString(error))
|
|
410
|
+
}
|
|
387
411
|
`(error, data) = fs.writeFile(configpath, JSONstringify(procon.configDict))
|
|
388
412
|
if !error {
|
|
389
413
|
procon.configMD5 = data
|
|
@@ -402,6 +426,8 @@ closure projConfig(projman, where, local procon, fs, configpath) {
|
|
|
402
426
|
// not already be loaded. The provided name overrides any name in the where argument above, but
|
|
403
427
|
// path and locationID must be specified. Returns a standard result tuple.
|
|
404
428
|
//
|
|
429
|
+
// ### we need to update this for optional multiple-configuraiton builds
|
|
430
|
+
//
|
|
405
431
|
procon.create = closure create(name, local error, data, configpath) {
|
|
406
432
|
if procon.loaded
|
|
407
433
|
return (list(Error("Project.create: project already loaded")))
|
|
@@ -457,7 +483,9 @@ closure projConfig(projman, where, local procon, fs, configpath) {
|
|
|
457
483
|
error = Error("project configuration not a directory", where.path)
|
|
458
484
|
else
|
|
459
485
|
`(error, data) = readConfig() }
|
|
460
|
-
if error
|
|
486
|
+
if error.code == "ENOENT"
|
|
487
|
+
return (list(Error("Project <b>".concat(where.name, "</b>:<br>not found at ", where.path))))
|
|
488
|
+
else if error
|
|
461
489
|
return (list(Error("Project.load failed", error)))
|
|
462
490
|
procon.loaded = true
|
|
463
491
|
list(false, procon.configDict)
|
|
@@ -496,15 +524,63 @@ closure projConfig(projman, where, local procon, fs, configpath) {
|
|
|
496
524
|
procon.configDict = newconfig
|
|
497
525
|
`(error, data) = writeConfig()
|
|
498
526
|
}
|
|
499
|
-
|
|
527
|
+
|
|
528
|
+
// stages
|
|
529
|
+
//
|
|
530
|
+
// Return a tuple of stages in the project configuration.
|
|
531
|
+
//
|
|
532
|
+
procon.stages = function stages() {
|
|
533
|
+
procon.configDict."build-rules".*
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// currentStage
|
|
537
|
+
//
|
|
538
|
+
// Validate and return the current stage of the project, or the first one if there isn't a
|
|
539
|
+
// previous selection, or false if no valid stages exist.
|
|
540
|
+
//
|
|
541
|
+
procon.currentStage = function currentStage(local stage, stagelist) {
|
|
542
|
+
stage = procon.localDict.currentStage
|
|
543
|
+
stagelist = stages()
|
|
544
|
+
if stage && !member(stage, stagelist)
|
|
545
|
+
stage = false
|
|
546
|
+
if stagelist && !stage
|
|
547
|
+
stage = stagelist.0
|
|
548
|
+
stage
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
// setCurrentStage
|
|
552
|
+
//
|
|
553
|
+
// Set the current stage.
|
|
554
|
+
//
|
|
555
|
+
procon.setCurrentStage = function setCurrentStage(stage) {
|
|
556
|
+
if member(stage, stages()) {
|
|
557
|
+
procon.localDict.currentStage = stage
|
|
558
|
+
update() // ### errors here are never reported
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
500
562
|
// buildrules
|
|
501
563
|
//
|
|
502
|
-
// Get the
|
|
564
|
+
// Get the build rules for the named stage.
|
|
503
565
|
//
|
|
504
|
-
function buildrules(local rules) {
|
|
505
|
-
rules = procon.configDict."build-rules"
|
|
566
|
+
function buildrules(stage, local rules, common, rule, key) {
|
|
567
|
+
rules = procon.configDict."build-rules"[stage]
|
|
506
568
|
if !rules
|
|
507
569
|
rules = procon.configDict.build // fallback to old config structure
|
|
570
|
+
rules = new(rules)
|
|
571
|
+
common = procon.configDict."build-common"
|
|
572
|
+
if common {
|
|
573
|
+
for rule in common
|
|
574
|
+
if !rules[rule]
|
|
575
|
+
rules[rule] = common[rule] // common rule was not overridden
|
|
576
|
+
else if array(common[rule], rules[rule])
|
|
577
|
+
rules[rule] = common[rule].concat(rules[rule]) // merge common array with rule
|
|
578
|
+
else if dictionary(common[rule], rules[rule]) {
|
|
579
|
+
for key in common[rule] // merge common dictionary with rule
|
|
580
|
+
if !rules[rule][key]
|
|
581
|
+
rules[rule][key] = common[rule][key]
|
|
582
|
+
}
|
|
583
|
+
}
|
|
508
584
|
rules
|
|
509
585
|
}
|
|
510
586
|
|
|
@@ -512,16 +588,18 @@ closure projConfig(projman, where, local procon, fs, configpath) {
|
|
|
512
588
|
//
|
|
513
589
|
// Run the project by building and then launching.
|
|
514
590
|
//
|
|
515
|
-
procon.run = closure run(buildonly, local rules, builder, buildpath, error, buildnum) {
|
|
591
|
+
procon.run = closure run(stage, buildonly, local rules, builder, buildpath, error, buildnum) {
|
|
516
592
|
if !procon.loaded
|
|
517
593
|
return (list(Error("project not loaded")))
|
|
518
|
-
rules = buildrules()
|
|
594
|
+
rules = buildrules(stage)
|
|
519
595
|
if !rules || !rules.products
|
|
520
596
|
return (list(Error("build rules missing or incomplete")))
|
|
521
597
|
buildpath = fs.path.join(proj_configDataFolder, rules.products)
|
|
522
598
|
rules.name = procon.where_name
|
|
523
599
|
rules.typeID = procon.where_typeID
|
|
524
|
-
|
|
600
|
+
if !rules.operation
|
|
601
|
+
rules.operation = "debug"
|
|
602
|
+
`(error, builder) = Builder(rules, rules.operation, fs, "", buildpath)
|
|
525
603
|
if error
|
|
526
604
|
return (list(error))
|
|
527
605
|
`(error, buildnum) = builder.increment()
|
|
@@ -529,11 +607,14 @@ closure projConfig(projman, where, local procon, fs, configpath) {
|
|
|
529
607
|
ErrorDebuglog("build number increment failed", error)
|
|
530
608
|
return (list(error))
|
|
531
609
|
}
|
|
532
|
-
`(error) = builder.make(
|
|
610
|
+
`(error) = builder.make({
|
|
611
|
+
stage: stage
|
|
612
|
+
buildnum: buildnum
|
|
613
|
+
})
|
|
533
614
|
if !error {
|
|
534
|
-
if
|
|
535
|
-
|
|
536
|
-
|
|
615
|
+
if builder.refresh(projman.track)
|
|
616
|
+
buildonly = !buildonly // reverse if refresh
|
|
617
|
+
if !buildonly
|
|
537
618
|
`(error) = builder.run(projman.track)
|
|
538
619
|
}
|
|
539
620
|
builder.destroy()
|
|
@@ -547,12 +628,13 @@ closure projConfig(projman, where, local procon, fs, configpath) {
|
|
|
547
628
|
//
|
|
548
629
|
// Publish the project to its configured location.
|
|
549
630
|
//
|
|
550
|
-
procon.publish = closure publish(local rules, publish, error, outfs, inpath) {
|
|
551
|
-
rules = buildrules()
|
|
552
|
-
publish =
|
|
553
|
-
|
|
631
|
+
procon.publish = closure publish(stage, local rules, where, publish, error, outfs, inpath) {
|
|
632
|
+
rules = buildrules(stage)
|
|
633
|
+
publish = rules.publish
|
|
634
|
+
where = procon.localDict.publish[stage].where
|
|
635
|
+
if !rules || !where
|
|
554
636
|
return (list(Error("no project publish location configured")))
|
|
555
|
-
`(error, outfs) = projman.locate.connect(
|
|
637
|
+
`(error, outfs) = projman.locate.connect(where.locationID, "NideFS", where.path)
|
|
556
638
|
if error
|
|
557
639
|
return (list(Error("can't access publishing filesystem", error)))
|
|
558
640
|
inpath = fs.path.join(proj_configDataFolder, rules.products, publish.input)
|