@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,122 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* lambda_rest_index.js
|
|
3
|
+
* serviceAws
|
|
4
|
+
*
|
|
5
|
+
* AWS Lambda startup code for REST interfaces.
|
|
6
|
+
*
|
|
7
|
+
* column positioning: // // !
|
|
8
|
+
*
|
|
9
|
+
* Copyright (c) 2019-2021 by Richard C. Zulch
|
|
10
|
+
*
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/*
|
|
14
|
+
* awsHandler
|
|
15
|
+
*
|
|
16
|
+
* Execute Naan in an AWS REST Lambda.
|
|
17
|
+
*
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
var save_naanlib;
|
|
21
|
+
|
|
22
|
+
exports.handler = function awsHandler(event, context, callback) {
|
|
23
|
+
logOut("awsHandler: " + context.awsRequestId.toString());
|
|
24
|
+
|
|
25
|
+
"use strict";
|
|
26
|
+
/*jshint -W024 */
|
|
27
|
+
var undefined;
|
|
28
|
+
|
|
29
|
+
//
|
|
30
|
+
// Initialization
|
|
31
|
+
//
|
|
32
|
+
|
|
33
|
+
var Naan = require('/opt/core/naanlib');
|
|
34
|
+
var naanlib;
|
|
35
|
+
if (save_naanlib) {
|
|
36
|
+
naanlib = save_naanlib;
|
|
37
|
+
logOut("naanlib reused");
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
save_naanlib = naanlib = new Naan.Naanlib();
|
|
41
|
+
logOut("naanlib built");
|
|
42
|
+
}
|
|
43
|
+
var servSelf = this;
|
|
44
|
+
|
|
45
|
+
//==========================================================================
|
|
46
|
+
// AWS Lambda interface
|
|
47
|
+
//--------------------------------------------------------------------------
|
|
48
|
+
|
|
49
|
+
//
|
|
50
|
+
// respond
|
|
51
|
+
//
|
|
52
|
+
|
|
53
|
+
function respond(message, response)
|
|
54
|
+
{
|
|
55
|
+
callback(message, response);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
naanlib.js.lambda = {
|
|
59
|
+
event: event,
|
|
60
|
+
context: context,
|
|
61
|
+
respond: respond,
|
|
62
|
+
id: context.awsRequestId.toString(),
|
|
63
|
+
aws: require('aws-sdk')
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
//==========================================================================
|
|
67
|
+
// API
|
|
68
|
+
//--------------------------------------------------------------------------
|
|
69
|
+
|
|
70
|
+
this.setRequire = function setRequire(req) { // override require function
|
|
71
|
+
naanlib.js.r = req;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
this.setDirectory = function setDirectory(path) { // override base directory
|
|
75
|
+
naanlib.js.d = path;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
this.textCommand = function textCommand(cmd) { // send a command without echo
|
|
79
|
+
logOut("command:" + cmd);
|
|
80
|
+
naanlib.textLine(cmd);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
//==========================================================================
|
|
84
|
+
// NodeJS Terminal Interface
|
|
85
|
+
//--------------------------------------------------------------------------
|
|
86
|
+
|
|
87
|
+
//
|
|
88
|
+
// logOut
|
|
89
|
+
//
|
|
90
|
+
// Log the specified string for CloudWatch reporting.
|
|
91
|
+
//
|
|
92
|
+
|
|
93
|
+
function logOut(text, level)
|
|
94
|
+
{
|
|
95
|
+
if (!(level >= 0 && level <= 5))
|
|
96
|
+
level = 0;
|
|
97
|
+
var levelstr = ["[INFO]", "[ERRR]", "[DBUG]", "[WARN]", "[NAAN]", "[BTIN]"][level];
|
|
98
|
+
console.log(levelstr + " " + text);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
//
|
|
102
|
+
// Interpreter's console/debug output
|
|
103
|
+
//
|
|
104
|
+
|
|
105
|
+
naanlib.onText(function (text, level) {
|
|
106
|
+
if (level)
|
|
107
|
+
logOut(text, level);
|
|
108
|
+
else
|
|
109
|
+
console.log(text);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
//==========================================================================
|
|
114
|
+
// Start the Naan Interpreter
|
|
115
|
+
//--------------------------------------------------------------------------
|
|
116
|
+
|
|
117
|
+
naanlib.banner();
|
|
118
|
+
naanlib.start();
|
|
119
|
+
var path = require("path").resolve(__dirname, './lambda_rest_init.nlg');
|
|
120
|
+
this.textCommand("nodeparse('" + path + "');\n");
|
|
121
|
+
logOut("completed" + naanlib);
|
|
122
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* lambda_rest_init.nlg
|
|
3
|
+
* serviceAws
|
|
4
|
+
*
|
|
5
|
+
* Initialize the AWS Lambda function in Naan for REST.
|
|
6
|
+
*
|
|
7
|
+
* column positioning: // // !
|
|
8
|
+
*
|
|
9
|
+
* Copyright (c) 2019-2021 by Richard C. Zulch
|
|
10
|
+
*
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
/*
|
|
15
|
+
* initPreload
|
|
16
|
+
*
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
loglevel(3);
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
/*
|
|
23
|
+
* versionCheck
|
|
24
|
+
*
|
|
25
|
+
* Ensure that Node is at least as new as the specified version.
|
|
26
|
+
*
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
function versionCheck(minver, local rxver, curver) {
|
|
30
|
+
rxver = RegExp("([0-9]+)[.]([0-9]+)[.]([0-9]+)")
|
|
31
|
+
minver = minver.match(rxver).map(function(x){Number.parseInt(x)})
|
|
32
|
+
curver = js.g.process.version.match(rxver).map(function(x){Number.parseInt(x)})
|
|
33
|
+
minver[1] < curver[1] || minver[1] == curver[1] && (minver[2] < curver[2] || minver[2] == curver[2] && minver[3] <= curver[3])
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
cond (
|
|
37
|
+
if not versionCheck("10.0.0") {
|
|
38
|
+
debuglog("NodeJS too old; version 10.0.0 required.")
|
|
39
|
+
js.r("process").exit(2)
|
|
40
|
+
}
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
/*
|
|
45
|
+
* process the request
|
|
46
|
+
*
|
|
47
|
+
*/
|
|
48
|
+
|
|
49
|
+
debuglog("about to respond");
|
|
50
|
+
|
|
51
|
+
js.lambda.respond(null, {
|
|
52
|
+
statusCode: 200,
|
|
53
|
+
body: "Hello Cruel World!\n".concat(js.lambda.context.awsRequestId)
|
|
54
|
+
headers: {
|
|
55
|
+
'Access-Control-Allow-Origin': '*',
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
@@ -0,0 +1,498 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* lambda_ws_index.js
|
|
3
|
+
* serviceAws
|
|
4
|
+
*
|
|
5
|
+
* AWS Lambda startup code for WebSocket interfaces.
|
|
6
|
+
*
|
|
7
|
+
* column positioning: // // !
|
|
8
|
+
*
|
|
9
|
+
* Copyright (c) 2020 by Richard C. Zulch
|
|
10
|
+
*
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
/*
|
|
15
|
+
* Imports & Utilities
|
|
16
|
+
*
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
var AWS = require('aws-sdk');
|
|
20
|
+
require('./patch.js');
|
|
21
|
+
var s3 = new AWS.S3();
|
|
22
|
+
var process = require('process');
|
|
23
|
+
var naan = require('/opt/core/naan_interpreter.js');
|
|
24
|
+
var naan_start = require('/opt/core/naan_start.js');
|
|
25
|
+
var naan_module = require('/opt/core/naan_module.js');
|
|
26
|
+
var naan_lingo = require('/opt/core/naan_lingo.js');
|
|
27
|
+
|
|
28
|
+
var kLogError = 1;
|
|
29
|
+
var kLogWarn = 3;
|
|
30
|
+
|
|
31
|
+
var activeWorkerID; // workerID of the active Naan instance, or false
|
|
32
|
+
var activeCounter = 0; // message counter for the active worker
|
|
33
|
+
var activeController; // active NaanController, or false
|
|
34
|
+
var activeOptions; // active options, saved with state
|
|
35
|
+
|
|
36
|
+
var instance_counter = 0;
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
//===================================================================================================
|
|
40
|
+
// AWS Interface
|
|
41
|
+
//---------------------------------------------------------------------------------------------------
|
|
42
|
+
//
|
|
43
|
+
// The awsHandler protocol is mandated by Amazon's Lambda API for NodeJS. It is called for each
|
|
44
|
+
// message received from the client side.
|
|
45
|
+
//
|
|
46
|
+
|
|
47
|
+
exports.handler = function awsHandler(event, context, callback) {
|
|
48
|
+
var messageIn;
|
|
49
|
+
var connectionId = event.requestContext.connectionId;
|
|
50
|
+
logOut("awsHandler connectionID: " + connectionId + " " + instance_counter++);
|
|
51
|
+
|
|
52
|
+
//
|
|
53
|
+
// initialize
|
|
54
|
+
//
|
|
55
|
+
|
|
56
|
+
var apigwManagementApi = new AWS.ApiGatewayManagementApi({
|
|
57
|
+
apiVersion: '2018-11-29',
|
|
58
|
+
endpoint: event.requestContext.domainName + '/' + event.requestContext.stage
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
//
|
|
62
|
+
// finished
|
|
63
|
+
//
|
|
64
|
+
// Terminate execution with the specified code, defaulting to 200.
|
|
65
|
+
//
|
|
66
|
+
|
|
67
|
+
function finished(code)
|
|
68
|
+
{
|
|
69
|
+
if (!code)
|
|
70
|
+
code = 200; // default success
|
|
71
|
+
logOut("callback finished: " + code);
|
|
72
|
+
callback(null, {
|
|
73
|
+
statusCode: code,
|
|
74
|
+
headers: { 'Content-Type': 'application/json' },
|
|
75
|
+
body: ""
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
//
|
|
80
|
+
// logOut
|
|
81
|
+
//
|
|
82
|
+
// Log the specified string for CloudWatch reporting.
|
|
83
|
+
//
|
|
84
|
+
|
|
85
|
+
function logOut(text, level)
|
|
86
|
+
{
|
|
87
|
+
if (!(level >= 0 && level <= 5))
|
|
88
|
+
level = 0;
|
|
89
|
+
var levelstr = ["[INFO]", "[ERRR]", "[DBUG]", "[WARN]", "[NAAN]", "[BTIN]"][level];
|
|
90
|
+
process.stdout.write(levelstr + " " + text + "\n");
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
//
|
|
94
|
+
// stateName
|
|
95
|
+
//
|
|
96
|
+
// Return the name of the active saved state file.
|
|
97
|
+
//
|
|
98
|
+
|
|
99
|
+
function stateName()
|
|
100
|
+
{
|
|
101
|
+
return ("naan-" + activeWorkerID + ".state");
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
//
|
|
105
|
+
// sendData
|
|
106
|
+
//
|
|
107
|
+
// Send data back to the originating client. Generally this should be a dictionary. The
|
|
108
|
+
// callback is required or this will fail silently.
|
|
109
|
+
//
|
|
110
|
+
|
|
111
|
+
function sendData(data, callback)
|
|
112
|
+
{
|
|
113
|
+
if (typeof(data) === "object")
|
|
114
|
+
data = JSON.stringify(data);
|
|
115
|
+
apigwManagementApi.postToConnection({
|
|
116
|
+
ConnectionId: connectionId,
|
|
117
|
+
Data: data
|
|
118
|
+
}, callback);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
//
|
|
122
|
+
// execDone
|
|
123
|
+
//
|
|
124
|
+
// Called by the NaanController when it's done executing the request. The specified array of
|
|
125
|
+
// messages is sent back to the client. These are sent all at once as an array to avoid ordering
|
|
126
|
+
// issues that are otherwise inevitable.
|
|
127
|
+
//
|
|
128
|
+
|
|
129
|
+
function execDone(sendqueue, save)
|
|
130
|
+
{
|
|
131
|
+
sendData({ // first send our response
|
|
132
|
+
clientID: messageIn.clientID,
|
|
133
|
+
serverID: messageIn.serverID,
|
|
134
|
+
workerID: messageIn.workerID,
|
|
135
|
+
respOp: "msgarray",
|
|
136
|
+
payload: sendqueue
|
|
137
|
+
}, function() {
|
|
138
|
+
if (save)
|
|
139
|
+
{
|
|
140
|
+
saveState(function() { // then save the Naan state
|
|
141
|
+
finished(); // then finish the lambda
|
|
142
|
+
});
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
finished();
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
//
|
|
150
|
+
// saveState
|
|
151
|
+
//
|
|
152
|
+
// Save the state of the active Naan instance.
|
|
153
|
+
//
|
|
154
|
+
|
|
155
|
+
function saveState(callback)
|
|
156
|
+
{
|
|
157
|
+
var saved = {
|
|
158
|
+
workerID: activeWorkerID,
|
|
159
|
+
};
|
|
160
|
+
if (activeOptions)
|
|
161
|
+
saved.options = activeOptions;
|
|
162
|
+
saved.state = activeController.StateSave();
|
|
163
|
+
s3.putObject({
|
|
164
|
+
Body: JSON.stringify(saved),
|
|
165
|
+
Bucket: "zulchlab-naan",
|
|
166
|
+
Key: stateName(),
|
|
167
|
+
ContentType: "utf8"
|
|
168
|
+
}, function(err, data) {
|
|
169
|
+
if (err)
|
|
170
|
+
logOut("putObject failed" + err, kLogError);
|
|
171
|
+
else
|
|
172
|
+
logOut("putObject successful");
|
|
173
|
+
if (callback)
|
|
174
|
+
callback();
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
//
|
|
179
|
+
// processMessage
|
|
180
|
+
//
|
|
181
|
+
// Process an incoming message from Naan.
|
|
182
|
+
//
|
|
183
|
+
|
|
184
|
+
function processMessage()
|
|
185
|
+
{
|
|
186
|
+
logOut("processing action " + event.requestContext.routeKey);
|
|
187
|
+
if (!event.body) {
|
|
188
|
+
finished(200); // must return success for $connect route
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
try {
|
|
192
|
+
messageIn = JSON.parse(event.body); // parse incoming message from Naan client
|
|
193
|
+
if (messageIn.serverID != "Workers")
|
|
194
|
+
{ // unknown server-side functionality
|
|
195
|
+
logOut("invalid serverID rejected: " + messageIn.serverID, kLogError);
|
|
196
|
+
finished(404); // not found
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
} catch(e) {
|
|
200
|
+
logOut("cannot parse incoming message JSON", e.toString(), kLogError);
|
|
201
|
+
finished(400); // bad request
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
if (typeof(messageIn.workerID) !== "string" || messageIn.workerID.length === 0)
|
|
205
|
+
{
|
|
206
|
+
logOut("invalid workerID rejected: " + messageIn.workerID, kLogError);
|
|
207
|
+
finished(400); // bad request
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
if (messageIn.workerOp == "spawn" && messageIn.payload.reset)
|
|
211
|
+
{ // clean start
|
|
212
|
+
activeOptions = messageIn.payload.options;
|
|
213
|
+
activeWorkerID = messageIn.workerID;
|
|
214
|
+
activeCounter = messageIn.msgCounter;
|
|
215
|
+
logOut("reset instance: " + activeWorkerID + " " + activeCounter);
|
|
216
|
+
activeController = new NaanController(logOut, execDone);
|
|
217
|
+
activeController.reset();
|
|
218
|
+
activeController.execute(event, messageIn);
|
|
219
|
+
}
|
|
220
|
+
else if (activeWorkerID == messageIn.workerID && activeCounter+1 == messageIn.msgCounter)
|
|
221
|
+
{ // already have correct instance
|
|
222
|
+
activeCounter = messageIn.msgCounter; // update our counter
|
|
223
|
+
logOut("reusing instance: " + activeWorkerID + " " + activeCounter);
|
|
224
|
+
activeController.reuse(logOut, execDone);
|
|
225
|
+
activeController.execute(event, messageIn);
|
|
226
|
+
}
|
|
227
|
+
else
|
|
228
|
+
{ // need new Naan instance
|
|
229
|
+
activeOptions = false;
|
|
230
|
+
activeWorkerID = messageIn.workerID;
|
|
231
|
+
activeCounter = messageIn.msgCounter; // start with specified counter
|
|
232
|
+
logOut("new instance: " + activeWorkerID + " " + activeCounter);
|
|
233
|
+
activeController = new NaanController(logOut, execDone);
|
|
234
|
+
s3.getObject({
|
|
235
|
+
Bucket: "zulchlab-naan",
|
|
236
|
+
Key: stateName()
|
|
237
|
+
}, function(err, data) {
|
|
238
|
+
if (err)
|
|
239
|
+
logOut("getObject failed: " + err.toString(), kLogWarn);
|
|
240
|
+
else {
|
|
241
|
+
try {
|
|
242
|
+
var saved = JSON.parse(data.Body.toString("utf8"));
|
|
243
|
+
activeOptions = saved.options;
|
|
244
|
+
if (activeController.StateLoad(saved.state))
|
|
245
|
+
logOut("getObject succeeded: " + saved.state.length);
|
|
246
|
+
else
|
|
247
|
+
err = true;
|
|
248
|
+
} catch (e) {
|
|
249
|
+
logOut("stateLoad failed: " + e.toString(), kLogWarn);
|
|
250
|
+
err = true;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
if (err)
|
|
254
|
+
activeController.reset();
|
|
255
|
+
activeController.execute(event, messageIn);
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
processMessage();
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
//===================================================================================================
|
|
265
|
+
// Naan Controller
|
|
266
|
+
//---------------------------------------------------------------------------------------------------
|
|
267
|
+
//
|
|
268
|
+
// The Naan controller executes Naan until there is nothing more to do, which one hopes is before
|
|
269
|
+
// the configured AWS Lambda timeout. After execution completes the state of the interpreter can be
|
|
270
|
+
// saved if desired. This is done by either a) setting the msgin.payload.save flag on the client side
|
|
271
|
+
// or b) calling js.t.SetSave(boolean) from within the invocation to be saved.
|
|
272
|
+
//
|
|
273
|
+
|
|
274
|
+
function NaanController(logOut, execDone)
|
|
275
|
+
{
|
|
276
|
+
var self = this;
|
|
277
|
+
var typeahead = "";
|
|
278
|
+
var keyboard = false;
|
|
279
|
+
var sendqueue = [];
|
|
280
|
+
var timerID;
|
|
281
|
+
var saveInvocation;
|
|
282
|
+
var anaan = new naan.NaanInterpreter();
|
|
283
|
+
var jsvar = {
|
|
284
|
+
d: __dirname,
|
|
285
|
+
r: require,
|
|
286
|
+
t: this,
|
|
287
|
+
n: anaan,
|
|
288
|
+
o: Object,
|
|
289
|
+
g: global
|
|
290
|
+
};
|
|
291
|
+
anaan.On("init-load", function () {
|
|
292
|
+
anaan._AddNamedObject("js", jsvar);
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
//
|
|
296
|
+
// debugWrite
|
|
297
|
+
// textWrite
|
|
298
|
+
//
|
|
299
|
+
// Naan hooks for text output.
|
|
300
|
+
//
|
|
301
|
+
anaan.On("debug-write", function(text, level) {
|
|
302
|
+
logOut(text, level);
|
|
303
|
+
sendqueue.push({
|
|
304
|
+
respOp: "msgout",
|
|
305
|
+
payload: {
|
|
306
|
+
id: "debugtext",
|
|
307
|
+
text: text,
|
|
308
|
+
level: level
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
anaan.On("console-out", function(who, text) {
|
|
314
|
+
process.stdout.write(text);
|
|
315
|
+
sendqueue.push({
|
|
316
|
+
respOp: "msgout",
|
|
317
|
+
payload: {
|
|
318
|
+
id: "textout",
|
|
319
|
+
text: text
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
//
|
|
325
|
+
// naanFlush
|
|
326
|
+
//
|
|
327
|
+
// Run until there is nothing else to do
|
|
328
|
+
//
|
|
329
|
+
function naanFlush()
|
|
330
|
+
{
|
|
331
|
+
var outext;
|
|
332
|
+
for (;;)
|
|
333
|
+
{
|
|
334
|
+
if ((outext = anaan.RunOutput()) !== "")
|
|
335
|
+
{
|
|
336
|
+
process.stdout.write(outext);
|
|
337
|
+
outext = "";
|
|
338
|
+
}
|
|
339
|
+
if (!anaan.Run())
|
|
340
|
+
break;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
//
|
|
345
|
+
// runOne
|
|
346
|
+
//
|
|
347
|
+
// Process input text when idle, returning without reschedule when there is nothing left to
|
|
348
|
+
// do here. (But there may be things going on in the background, waiting for a callback.)
|
|
349
|
+
//
|
|
350
|
+
function runOne()
|
|
351
|
+
{
|
|
352
|
+
if (timerID) {
|
|
353
|
+
clearTimeout(timerID);
|
|
354
|
+
timerID = false;
|
|
355
|
+
}
|
|
356
|
+
if (!anaan.Run())
|
|
357
|
+
{
|
|
358
|
+
if (typeahead.length === 0) {
|
|
359
|
+
logOut("runOne idle");
|
|
360
|
+
timerID = setTimeout(function() {
|
|
361
|
+
logOut("save timeout completed");
|
|
362
|
+
execDone(sendqueue, saveInvocation);
|
|
363
|
+
}, 10);
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
var cmds = typeahead + "\n";
|
|
367
|
+
typeahead = "";
|
|
368
|
+
anaan.Process(cmds, keyboard);
|
|
369
|
+
}
|
|
370
|
+
reschedule(anaan);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
//
|
|
374
|
+
// reschedule
|
|
375
|
+
//
|
|
376
|
+
// Run us again from the NodeJS event loop.
|
|
377
|
+
//
|
|
378
|
+
function reschedule(who)
|
|
379
|
+
{
|
|
380
|
+
Promise.resolve().then(runOne);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
anaan.On("interrupted", function (who) {
|
|
384
|
+
reschedule(); // need to reschedule again in this case
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
//
|
|
388
|
+
// scheduleInitFile
|
|
389
|
+
//
|
|
390
|
+
// Schedule a file to be parsed and executed for initialization.
|
|
391
|
+
//
|
|
392
|
+
function scheduleInitFile(path)
|
|
393
|
+
{
|
|
394
|
+
path = require("path").resolve(__dirname, path);
|
|
395
|
+
typeahead += 'Naan.module.nodeparse("' + path + '");;\n';
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
//
|
|
399
|
+
// reuse
|
|
400
|
+
//
|
|
401
|
+
// Reuse the active controller.
|
|
402
|
+
//
|
|
403
|
+
|
|
404
|
+
this.reuse = function reuse(_logout, _execdone)
|
|
405
|
+
{
|
|
406
|
+
logOut = _logout;
|
|
407
|
+
execDone = _execdone;
|
|
408
|
+
typeahead = "";
|
|
409
|
+
keyboard = false;
|
|
410
|
+
sendqueue = [];
|
|
411
|
+
timerID = false;
|
|
412
|
+
saveInvocation = false;
|
|
413
|
+
};
|
|
414
|
+
|
|
415
|
+
//
|
|
416
|
+
// reset
|
|
417
|
+
//
|
|
418
|
+
// Initialize Naan instance to run the first time.
|
|
419
|
+
//
|
|
420
|
+
this.reset = function reset()
|
|
421
|
+
{
|
|
422
|
+
logOut("Naan reboot");
|
|
423
|
+
self.reuse(logOut, execDone);
|
|
424
|
+
anaan.StateDefault();
|
|
425
|
+
anaan.Banner();
|
|
426
|
+
naan_start.BootRoot(anaan);
|
|
427
|
+
naan_module.BootModule(anaan);
|
|
428
|
+
naan_lingo.BootLingo(anaan);
|
|
429
|
+
naan_start.BootPlayNG(anaan);
|
|
430
|
+
anaan.Process("");
|
|
431
|
+
naanFlush();
|
|
432
|
+
scheduleInitFile("./lambda_init.nlg");
|
|
433
|
+
};
|
|
434
|
+
|
|
435
|
+
// execute
|
|
436
|
+
//
|
|
437
|
+
// Execute Naan until there is no more to do.
|
|
438
|
+
//
|
|
439
|
+
this.execute = function execute(event, messageIn)
|
|
440
|
+
{
|
|
441
|
+
jsvar.lambda = {
|
|
442
|
+
event: event
|
|
443
|
+
};
|
|
444
|
+
if (messageIn.workerOp == "spawn")
|
|
445
|
+
{ // configure instance with options
|
|
446
|
+
activeOptions = messageIn.payload.options;
|
|
447
|
+
sendqueue.push({
|
|
448
|
+
respOp: "msgout",
|
|
449
|
+
payload: {
|
|
450
|
+
id: "started",
|
|
451
|
+
connectionId: event.requestContext.connectionId
|
|
452
|
+
}
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
else if (messageIn.workerOp == "msgin")
|
|
456
|
+
{ // execute Naan
|
|
457
|
+
if (messageIn.payload.save)
|
|
458
|
+
saveInvocation = messageIn.payload.save; // set the save flag
|
|
459
|
+
if (messageIn.payload.id == "interrupt")
|
|
460
|
+
anaan.Escape();
|
|
461
|
+
else if (messageIn.payload.id == "keyline")
|
|
462
|
+
{
|
|
463
|
+
keyboard = true;
|
|
464
|
+
typeahead += messageIn.payload.text;
|
|
465
|
+
} else
|
|
466
|
+
logOut("msgin.id not recognized" + messageIn.payload.id, kLogWarn);
|
|
467
|
+
} else
|
|
468
|
+
logOut("workerOp not recognized" + messageIn.workerOp, kLogWarn);
|
|
469
|
+
runOne();
|
|
470
|
+
};
|
|
471
|
+
|
|
472
|
+
// SetSave
|
|
473
|
+
//
|
|
474
|
+
// Set the save flag for the current invocation.
|
|
475
|
+
//
|
|
476
|
+
this.SetSave = function SetSave(dosave)
|
|
477
|
+
{
|
|
478
|
+
saveInvocation = dosave
|
|
479
|
+
};
|
|
480
|
+
|
|
481
|
+
// StateLoad
|
|
482
|
+
//
|
|
483
|
+
// Load the interpreter state from the specified string.
|
|
484
|
+
//
|
|
485
|
+
this.StateLoad = function StateLoad(state)
|
|
486
|
+
{
|
|
487
|
+
return (anaan.StateLoad(state));
|
|
488
|
+
};
|
|
489
|
+
|
|
490
|
+
// StateSave
|
|
491
|
+
//
|
|
492
|
+
// Return the interpreter state as a string.
|
|
493
|
+
//
|
|
494
|
+
this.StateSave = function StateSave()
|
|
495
|
+
{
|
|
496
|
+
return (anaan.StateSave());
|
|
497
|
+
};
|
|
498
|
+
}
|