profoundjs 6.0.0-beta.3 → 6.0.0-beta.7
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/index.js +1 -0
- package/package.json +9 -9
- package/profound.jse +1 -1
- package/setup/completeInstall.js +465 -0
- package/setup/complete_install.js +22 -0
- package/setup/config.js +1 -1
- package/setup/install.js +63 -0
- package/setup/install_utils.js +123 -0
- package/setup/modules/puiscreens.json +23 -25
- package/setup/package.json +2 -2
- package/setup/pjsdist.savf +0 -0
- package/setup/setup.js +514 -864
- package/setup/start.js +12 -1
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
|
|
7
|
+
* This is NPM run script 'completeInstall'
|
|
8
|
+
|
|
9
|
+
* This script is intended to be run by the user at a shell after 'npm install', via 'complete_intall.js'.
|
|
10
|
+
|
|
11
|
+
* Prompts for configuration values and other installation options, if necessary, and creates config.js.
|
|
12
|
+
* Kicks off 'npm run setup' to complete installation.
|
|
13
|
+
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const child_process = require("child_process");
|
|
17
|
+
const fs = require("fs");
|
|
18
|
+
const minimist = require("minimist");
|
|
19
|
+
const os = require("os");
|
|
20
|
+
const path = require("path");
|
|
21
|
+
const readline = require("readline");
|
|
22
|
+
const iutils = require("./install_utils.js");
|
|
23
|
+
|
|
24
|
+
const IBMi = os.type() === "OS400";
|
|
25
|
+
|
|
26
|
+
(async () => {
|
|
27
|
+
try {
|
|
28
|
+
|
|
29
|
+
// Parse arguments.
|
|
30
|
+
const args = minimist(
|
|
31
|
+
process.argv.slice(2),
|
|
32
|
+
{
|
|
33
|
+
alias: {
|
|
34
|
+
"h": "help",
|
|
35
|
+
"c": "configure"
|
|
36
|
+
},
|
|
37
|
+
boolean: [
|
|
38
|
+
"h",
|
|
39
|
+
"c"
|
|
40
|
+
],
|
|
41
|
+
unknown: function(arg) {
|
|
42
|
+
console.error("Unknown argument:", arg);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
// Show help and quit, if requested.
|
|
49
|
+
if (args["help"]) {
|
|
50
|
+
const HELP = `Usage: node complete_install.js [OPTION]
|
|
51
|
+
-h, --help Print this help and exit.
|
|
52
|
+
-c, --configure Prompt for configuration values.
|
|
53
|
+
|
|
54
|
+
Creates config.js and completes installation.
|
|
55
|
+
If config.js is not present, this script prompts for values and creates it.
|
|
56
|
+
If config.js is already present, installation proceeds silently by default.
|
|
57
|
+
In this case, --configure can be used to prompt and update config.js first.
|
|
58
|
+
`;
|
|
59
|
+
console.log(HELP);
|
|
60
|
+
process.exit(0);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Validate arguments.
|
|
64
|
+
if (args._.length > 0) {
|
|
65
|
+
console.error("Unknown argument:", args._[0]);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const deployDir = iutils.getDeployDir();
|
|
70
|
+
if (!deployDir) {
|
|
71
|
+
console.error("Can't find deployment directory.");
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
const configPath = iutils.getConfigPath();
|
|
75
|
+
let config = fileExists(configPath) ? require(configPath) : {};
|
|
76
|
+
|
|
77
|
+
let downloadStaticFiles;
|
|
78
|
+
let svrname, autostart, ccsid, nodePath;
|
|
79
|
+
|
|
80
|
+
// If config.js doesn't exist, or if --configure is passed, prompt and create/update config.js.
|
|
81
|
+
if (!fileExists(configPath) || args["configure"] === true) {
|
|
82
|
+
|
|
83
|
+
let staticFilesDirectory, port, gitSupport;
|
|
84
|
+
let profounduiLibrary, connectorLibrary, connectorIASP;
|
|
85
|
+
|
|
86
|
+
let defaultStaticDir;
|
|
87
|
+
if (IBMi) {
|
|
88
|
+
defaultStaticDir = config.staticFilesDirectory || "/www/profoundui/htdocs"
|
|
89
|
+
if (!directoryExists(defaultStaticDir)) {
|
|
90
|
+
console.log("");
|
|
91
|
+
console.log("WARNING: Profound UI Installation not found in default location.");
|
|
92
|
+
console.log("");
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
defaultStaticDir = config.staticFilesDirectory || "htdocs";
|
|
97
|
+
console.log("");
|
|
98
|
+
console.log("You can provide the Profound UI directory as a remote URL (e.g. http://myibmi:8080) or as a local directory name. If the directory does not exist, the installer can create it for you.");
|
|
99
|
+
console.log("");
|
|
100
|
+
}
|
|
101
|
+
staticFilesDirectory = await ask("Specify Profound UI static files directory", defaultStaticDir, validateDirectory);
|
|
102
|
+
if (!IBMi && !isURL(staticFilesDirectory) && !directoryExists(path.resolve(deployDir, staticFilesDirectory))) {
|
|
103
|
+
console.log("");
|
|
104
|
+
console.log("The specified directory for Profound UI was not found.");
|
|
105
|
+
console.log("");
|
|
106
|
+
let answer = (await ask("Should the installer create the directory and download a copy of Profound UI static files?", "y", validateYesNo)).toUpperCase();
|
|
107
|
+
downloadStaticFiles = (answer === "Y");
|
|
108
|
+
}
|
|
109
|
+
port = Number(await ask("Specify port number for Profound.js server", config.port || 8081, validatePort));
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
if (["win32", "darwin", "linux"].includes(os.platform())) {
|
|
113
|
+
let answer = (await ask("Install with Git integration?", config.gitSupport === false ? "n" : "y" , validateYesNo)).toUpperCase();
|
|
114
|
+
gitSupport = (answer === "Y");
|
|
115
|
+
}
|
|
116
|
+
if (IBMi) {
|
|
117
|
+
console.log("");
|
|
118
|
+
profounduiLibrary = (await ask("Specify Profound UI installation library", config.profounduiLibrary || "PROFOUNDUI", validateName)).toUpperCase();
|
|
119
|
+
let answer = (await ask("Install Profound.js Connector IBM i ILE components?", "y", validateYesNo)).toUpperCase();
|
|
120
|
+
if (answer === "Y") {
|
|
121
|
+
connectorLibrary = (await ask("Enter Profound.js Connector library name:", config.connectorLibrary || "PROFOUNDJS", validateName)).toUpperCase();
|
|
122
|
+
connectorIASP = (await ask("Enter Profound.js Connector library IASP:", config.connectorIASP || "*SYSBAS", validateIASP)).toUpperCase();
|
|
123
|
+
}
|
|
124
|
+
const serverInstances = iutils.getIBMiInstances(deployDir);
|
|
125
|
+
if (serverInstances.length > 1) {
|
|
126
|
+
console.log("\nWARNING - Multiple STRTCPSVR/ENDTCPSVR instances found for this server in /profoundjs-base/instances:\n");
|
|
127
|
+
serverInstances.forEach(serverInstance => {
|
|
128
|
+
console.log(JSON.stringify(serverInstance));
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
answer = (await ask("\nCreate/replace server instance configuration for STRTCPSVR/ENDTCPSVR commands?", "y", validateYesNo)).toUpperCase();
|
|
132
|
+
if (answer === "Y") {
|
|
133
|
+
let defaultName = "PROFOUNDJS";
|
|
134
|
+
const defaultOpts = {
|
|
135
|
+
ccsid: "37",
|
|
136
|
+
nodePath: process.argv[0],
|
|
137
|
+
autostart: "1"
|
|
138
|
+
};
|
|
139
|
+
const serverInstance = serverInstances[0];
|
|
140
|
+
if (serverInstance) {
|
|
141
|
+
defaultName = serverInstance.name;
|
|
142
|
+
defaultOpts.autostart = "0";
|
|
143
|
+
for (const name in defaultOpts) {
|
|
144
|
+
const opt = serverInstance.options.find(option => option.name === name);
|
|
145
|
+
if (opt) {
|
|
146
|
+
defaultOpts[name] = opt.value.trim();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
svrname = (await ask("Server instance name:", defaultName, validateName)).toUpperCase();
|
|
151
|
+
ccsid = await ask("Specify CCSID for instance " + svrname, defaultOpts.ccsid, isValidCcsid);
|
|
152
|
+
nodePath = await ask("Specify Node.js path for instance " + svrname, defaultOpts.nodePath, isValidNodePath);
|
|
153
|
+
autostart = (await ask("Autostart server instance " + svrname + " when TCP/IP starts?", defaultOpts.autostart === "1" ? "y" : "n", validateYesNo)).toUpperCase();
|
|
154
|
+
autostart = (autostart === "Y");
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Create/update configuration file.
|
|
159
|
+
if (fileExists(configPath)) {
|
|
160
|
+
|
|
161
|
+
config.staticFilesDirectory = staticFilesDirectory;
|
|
162
|
+
config.port = port;
|
|
163
|
+
if (gitSupport === false) {
|
|
164
|
+
config.gitSupport = false;
|
|
165
|
+
}
|
|
166
|
+
else if (config.hasOwnProperty("gitSupport")) {
|
|
167
|
+
delete config.gitSupport;
|
|
168
|
+
}
|
|
169
|
+
if (IBMi) {
|
|
170
|
+
config.profounduiLibrary = profounduiLibrary;
|
|
171
|
+
if (connectorLibrary) {
|
|
172
|
+
config.connectorLibrary = connectorLibrary;
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
if (config.hasOwnProperty("connectorLibrary")) {
|
|
176
|
+
delete config.connectorLibrary;
|
|
177
|
+
}
|
|
178
|
+
if (config.hasOwnProperty("connectorIASP")) {
|
|
179
|
+
delete config.connectorIASP;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
if (connectorIASP && connectorIASP !== "*SYSBAS") {
|
|
183
|
+
config.connectorIASP = connectorIASP;
|
|
184
|
+
}
|
|
185
|
+
else if (config.hasOwnProperty("connectorIASP")) {
|
|
186
|
+
delete config.connectorIASP;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
fs.writeFileSync(configPath, stringifyConfig(config));
|
|
190
|
+
console.log("");
|
|
191
|
+
console.log("config.js updated.");
|
|
192
|
+
console.log("");
|
|
193
|
+
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
|
|
197
|
+
let content = fs.readFileSync(path.join(iutils.getSetupDir(), "config.js"), "utf8");
|
|
198
|
+
eval("config = " + content.substr(content.indexOf("{")));
|
|
199
|
+
config.staticFilesDirectory = staticFilesDirectory;
|
|
200
|
+
config.port = port;
|
|
201
|
+
if (connectorLibrary) {
|
|
202
|
+
config.connectorLibrary = connectorLibrary;
|
|
203
|
+
if (connectorIASP !== "*SYSBAS") {
|
|
204
|
+
config.connectorIASP = connectorIASP;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
if (profounduiLibrary) {
|
|
208
|
+
config.profounduiLibrary = profounduiLibrary;
|
|
209
|
+
}
|
|
210
|
+
if (IBMi) {
|
|
211
|
+
config.showIBMiParmDefn = true;
|
|
212
|
+
}
|
|
213
|
+
if (gitSupport === false) {
|
|
214
|
+
config.gitSupport = false;
|
|
215
|
+
}
|
|
216
|
+
// Check if this is a workspace (if so, default to mysql)
|
|
217
|
+
if (!IBMi && fileExists(path.join(deployDir, "modules", "app", ".noderun", "settings.json"))) {
|
|
218
|
+
if (config.databaseConnections) delete config.databaseConnections; // remove property so that it's appended at the end when we set it
|
|
219
|
+
config.databaseConnections = [{
|
|
220
|
+
name: "default",
|
|
221
|
+
default: true,
|
|
222
|
+
driver: "mysql",
|
|
223
|
+
driverOptions: {
|
|
224
|
+
user: "user-name",
|
|
225
|
+
password: "your-password",
|
|
226
|
+
host: "localhost",
|
|
227
|
+
database: "database-name"
|
|
228
|
+
}
|
|
229
|
+
}];
|
|
230
|
+
}
|
|
231
|
+
content = "\nmodule.exports = ";
|
|
232
|
+
content += JSON.stringify(config, null, " ");
|
|
233
|
+
content += "\n";
|
|
234
|
+
fs.writeFileSync(configPath, content);
|
|
235
|
+
console.log("");
|
|
236
|
+
console.log("config.js created.");
|
|
237
|
+
console.log("");
|
|
238
|
+
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Complete installation.
|
|
244
|
+
process.stdin.destroy();
|
|
245
|
+
let setupArgs = [];
|
|
246
|
+
if (IBMi) {
|
|
247
|
+
if (config.connectorLibrary !== undefined) {
|
|
248
|
+
setupArgs.push("--ibmi-connector-library");
|
|
249
|
+
}
|
|
250
|
+
if (svrname) {
|
|
251
|
+
setupArgs.push("--ibmi-instance=" + svrname);
|
|
252
|
+
if (autostart) {
|
|
253
|
+
setupArgs.push("--ibmi-instance-autostart");
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
setupArgs.push("--no-ibmi-instance-autostart");
|
|
257
|
+
}
|
|
258
|
+
if (ccsid) {
|
|
259
|
+
setupArgs.push("--ibmi-instance-ccsid=" + ccsid);
|
|
260
|
+
}
|
|
261
|
+
if (nodePath) {
|
|
262
|
+
setupArgs.push("--ibmi-instance-node-path=" + nodePath);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
if (downloadStaticFiles) {
|
|
267
|
+
setupArgs.push("--static-files");
|
|
268
|
+
}
|
|
269
|
+
if (["win32", "darwin", "linux"].includes(os.platform()) && config.gitSupport !== false) {
|
|
270
|
+
setupArgs.push("--nodegit");
|
|
271
|
+
}
|
|
272
|
+
if (setupArgs.length === 0) {
|
|
273
|
+
setupArgs = "";
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
setupArgs = "-- " + setupArgs.join(" ");
|
|
277
|
+
}
|
|
278
|
+
try {
|
|
279
|
+
child_process.execSync(
|
|
280
|
+
`npm run setup ${setupArgs}`,
|
|
281
|
+
{
|
|
282
|
+
cwd: iutils.getPackageDir(),
|
|
283
|
+
stdio: ["ignore", "inherit", "inherit"]
|
|
284
|
+
}
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
catch {
|
|
288
|
+
process.exit(1);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
}
|
|
292
|
+
catch (error) {
|
|
293
|
+
process.stdin.destroy();
|
|
294
|
+
console.error(error);
|
|
295
|
+
process.exit(1);
|
|
296
|
+
}
|
|
297
|
+
})();
|
|
298
|
+
|
|
299
|
+
async function ask(questionParm, defaultAnswer, validationFunction) {
|
|
300
|
+
|
|
301
|
+
let question = questionParm;
|
|
302
|
+
if (defaultAnswer == null) defaultAnswer = "";
|
|
303
|
+
if (typeof defaultAnswer !== "string") defaultAnswer = String(defaultAnswer);
|
|
304
|
+
|
|
305
|
+
if (defaultAnswer !== "") {
|
|
306
|
+
let lastChar = question.substr(question.length - 1, 1);
|
|
307
|
+
if (lastChar === ":" || lastChar === "?") {
|
|
308
|
+
question = question.substr(0, question.length - 1) + " (" + defaultAnswer + ")" + lastChar;
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
question = question + " (" + defaultAnswer + ")" + ":";
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
question += " ";
|
|
315
|
+
|
|
316
|
+
const readlineInterface = readline.createInterface({
|
|
317
|
+
input: process.stdin,
|
|
318
|
+
output: process.stdout,
|
|
319
|
+
terminal: false
|
|
320
|
+
});
|
|
321
|
+
let answer = await new Promise(resolve => {
|
|
322
|
+
readlineInterface.question(question, function(answer) {
|
|
323
|
+
readlineInterface.close();
|
|
324
|
+
resolve(answer);
|
|
325
|
+
});
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
if (answer == "") answer = defaultAnswer;
|
|
329
|
+
answer = answer.trim();
|
|
330
|
+
if (typeof validationFunction === "function" && validationFunction(answer) === false) {
|
|
331
|
+
answer = await ask(questionParm, defaultAnswer, validationFunction);
|
|
332
|
+
}
|
|
333
|
+
return answer;
|
|
334
|
+
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
function fileExists(file) {
|
|
338
|
+
var exists = false;
|
|
339
|
+
try {
|
|
340
|
+
var stat = fs.statSync(file);
|
|
341
|
+
if (stat && stat.isFile()) exists = true;
|
|
342
|
+
}
|
|
343
|
+
catch (err) {
|
|
344
|
+
exists = false;
|
|
345
|
+
}
|
|
346
|
+
return exists;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
function directoryExists(dir) {
|
|
350
|
+
var exists = false;
|
|
351
|
+
try {
|
|
352
|
+
var stat = fs.statSync(dir);
|
|
353
|
+
if (stat && stat.isDirectory()) exists = true;
|
|
354
|
+
}
|
|
355
|
+
catch (err) {
|
|
356
|
+
exists = false;
|
|
357
|
+
}
|
|
358
|
+
return exists;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
function validateName(name) {
|
|
362
|
+
|
|
363
|
+
const error = iutils.validateIBMiName(name);
|
|
364
|
+
if (error) {
|
|
365
|
+
console.log(error);
|
|
366
|
+
return false;
|
|
367
|
+
}
|
|
368
|
+
return true;
|
|
369
|
+
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
function validateIASP(name) {
|
|
373
|
+
|
|
374
|
+
const error = iutils.validateIBMiIASP(name);
|
|
375
|
+
if (error) {
|
|
376
|
+
console.log(error);
|
|
377
|
+
return false;
|
|
378
|
+
}
|
|
379
|
+
return true;
|
|
380
|
+
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
function isURL(path) {
|
|
384
|
+
if (typeof path !== "string") return false;
|
|
385
|
+
path = path.toLowerCase();
|
|
386
|
+
if (path.substr(0, 7) === "http://") return true;
|
|
387
|
+
if (path.substr(0, 8) === "https://") return true;
|
|
388
|
+
return false;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
function validateDirectory(directory) {
|
|
392
|
+
if (IBMi) {
|
|
393
|
+
var ch = directory.substr(0, 1);
|
|
394
|
+
if (ch !== "/" && ch !== "\\" && !isURL(directory)) {
|
|
395
|
+
directory = path.join(iutils.getDeployDir(), path.sep, directory);
|
|
396
|
+
}
|
|
397
|
+
if (!directoryExists(directory) && !isURL(directory)) {
|
|
398
|
+
console.log("WARNING: The specified directory was not found. You can create it later or modify the staticFilesDirectory property in config.js.");
|
|
399
|
+
console.log("");
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
return true; // accept any entry - if directory doesn't exist, simply warn
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
function validatePort(port) {
|
|
406
|
+
if (port === "0") return true;
|
|
407
|
+
port = Number(port);
|
|
408
|
+
if (!isNaN(port) && port >= 1 && port <= 65535) return true;
|
|
409
|
+
console.log("Invalid port number. Valid range is 0-65535.");
|
|
410
|
+
return false;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
function isValidNodePath(nodePath) {
|
|
414
|
+
|
|
415
|
+
if (!fileExists(nodePath)) {
|
|
416
|
+
console.log("Path " + nodePath + " does not exist. A valid path name must be entered.");
|
|
417
|
+
return false;
|
|
418
|
+
}
|
|
419
|
+
return true;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
function isValidCcsid(ccsid) {
|
|
423
|
+
|
|
424
|
+
const error = iutils.validateIBMiCCSID(parseInt(ccsid, 10));
|
|
425
|
+
if (error) {
|
|
426
|
+
console.log(error);
|
|
427
|
+
return false;
|
|
428
|
+
}
|
|
429
|
+
return true;
|
|
430
|
+
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
function validateYesNo(answer) {
|
|
434
|
+
answer = answer.toUpperCase();
|
|
435
|
+
if (answer === "Y" || answer === "YES" || answer === "N" || answer === "NO") return true;
|
|
436
|
+
console.log("Invalid answer. Use y or n.");
|
|
437
|
+
return false;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
function stringifyConfig(config) {
|
|
441
|
+
|
|
442
|
+
// JavaScript functions (like connectorIPFilter) will be lost when doing JSON.stringify,
|
|
443
|
+
// so we need to do some magic to preserve them.
|
|
444
|
+
|
|
445
|
+
let funkz = [];
|
|
446
|
+
let configString = "\nmodule.exports = ";
|
|
447
|
+
|
|
448
|
+
configString += JSON.stringify(config, (key, val) => {
|
|
449
|
+
if (typeof val === 'function') {
|
|
450
|
+
let n = funkz.length;
|
|
451
|
+
funkz.push(val.toString());
|
|
452
|
+
return `___function${n}___`;
|
|
453
|
+
}
|
|
454
|
+
return val;
|
|
455
|
+
}, " ");
|
|
456
|
+
|
|
457
|
+
configString += "\n";
|
|
458
|
+
|
|
459
|
+
for (var i=0; i<funkz.length; i++) {
|
|
460
|
+
configString = configString.replace(`"___function${i}___"`, funkz[i]);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
return configString;
|
|
464
|
+
|
|
465
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
|
|
2
|
+
const child_process = require("child_process");
|
|
3
|
+
|
|
4
|
+
let args = process.argv.slice(2);
|
|
5
|
+
if (args.length > 0) {
|
|
6
|
+
args = "-- " + args.join(" ");
|
|
7
|
+
}
|
|
8
|
+
else {
|
|
9
|
+
args = "";
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
try {
|
|
13
|
+
child_process.execSync(
|
|
14
|
+
`npm run --prefix=node_modules/profoundjs completeInstall ${args}`,
|
|
15
|
+
{
|
|
16
|
+
stdio: "inherit"
|
|
17
|
+
}
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
package/setup/config.js
CHANGED
package/setup/install.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
|
|
6
|
+
This is NPM lifecycle script: postinstall
|
|
7
|
+
|
|
8
|
+
* Installs minimal files into the users's deployment directory:
|
|
9
|
+
- package.json
|
|
10
|
+
- start.js
|
|
11
|
+
- complete_install.js
|
|
12
|
+
|
|
13
|
+
* All additional installation is done by script 'npm run setup'.
|
|
14
|
+
|
|
15
|
+
* After installation, user runs 'node complete_install.js', which creates configuration and kicks off 'npm run setup'.
|
|
16
|
+
|
|
17
|
+
NOTE: Output from this script will be suppressed by NPM 7+, unless process ends with non-zero exit code.
|
|
18
|
+
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
const fs = require("fs");
|
|
22
|
+
const iutils = require("./install_utils.js");
|
|
23
|
+
const path = require("path");
|
|
24
|
+
|
|
25
|
+
const deployDir = iutils.getDeployDir();
|
|
26
|
+
if (!deployDir) {
|
|
27
|
+
console.error("Can't find deployment directory.");
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Install files.
|
|
32
|
+
installFile("package.json");
|
|
33
|
+
installFile("start.js");
|
|
34
|
+
installFile("complete_install.js", true);
|
|
35
|
+
|
|
36
|
+
console.log("\nTo complete installation, run: node complete_install.js\n");
|
|
37
|
+
|
|
38
|
+
function fileExists(file) {
|
|
39
|
+
try {
|
|
40
|
+
const stats = fs.statSync(file);
|
|
41
|
+
return stats.isFile();
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function installFile(file, overwrite) {
|
|
49
|
+
const dest = path.join(deployDir, file);
|
|
50
|
+
if (overwrite !== true && fileExists(dest)) {
|
|
51
|
+
console.log(`${file} exists.`);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
fs.writeFileSync(
|
|
55
|
+
dest,
|
|
56
|
+
fs.readFileSync(path.join(__dirname, file)),
|
|
57
|
+
{
|
|
58
|
+
flag: overwrite === true ? "w" : "wx"
|
|
59
|
+
}
|
|
60
|
+
);
|
|
61
|
+
console.log(`${file} created.`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
Utilities for PJS install/setup process.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require("fs");
|
|
9
|
+
const path = require("path");
|
|
10
|
+
|
|
11
|
+
exports.getConfigPath = function() {
|
|
12
|
+
|
|
13
|
+
return path.join(exports.getDeployDir(), "config.js");
|
|
14
|
+
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
exports.getDeployDir = function() {
|
|
18
|
+
|
|
19
|
+
const dirParts = __dirname.split(path.sep);
|
|
20
|
+
while (dirParts.length > 0 && dirParts.pop() !== "node_modules") {};
|
|
21
|
+
if (dirParts.length > 0) {
|
|
22
|
+
return dirParts.join(path.sep);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
exports.getPackageDir = function() {
|
|
28
|
+
|
|
29
|
+
return path.resolve(__dirname, "..");
|
|
30
|
+
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
exports.getSetupDir = function() {
|
|
34
|
+
|
|
35
|
+
return path.join(exports.getPackageDir(), "setup");
|
|
36
|
+
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
exports.getIBMiInstances = function(installDir) {
|
|
40
|
+
|
|
41
|
+
const INSTANCES_DIR = "/profoundjs-base/instances";
|
|
42
|
+
|
|
43
|
+
if (!fs.existsSync(INSTANCES_DIR)) {
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const dirs = fs.readdirSync(
|
|
48
|
+
INSTANCES_DIR,
|
|
49
|
+
{
|
|
50
|
+
withFileTypes: true
|
|
51
|
+
}
|
|
52
|
+
)
|
|
53
|
+
.filter(el => el.isDirectory());
|
|
54
|
+
|
|
55
|
+
let instances = [];
|
|
56
|
+
for (const dir of dirs) {
|
|
57
|
+
let conf;
|
|
58
|
+
try {
|
|
59
|
+
conf = fs.readFileSync(path.join(INSTANCES_DIR, dir.name, "conf"), "utf8");
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
const instance ={
|
|
65
|
+
name: dir.name.toUpperCase(),
|
|
66
|
+
options: []
|
|
67
|
+
};
|
|
68
|
+
const lines = conf.split("\n");
|
|
69
|
+
for (const line of lines) {
|
|
70
|
+
const parts = line.split("=");
|
|
71
|
+
if (parts.length >= 2) {
|
|
72
|
+
instance.options.push({
|
|
73
|
+
name: parts[0].trim(),
|
|
74
|
+
value: parts.slice(1).join("=")
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
instances.push(instance);
|
|
79
|
+
}
|
|
80
|
+
if (installDir) {
|
|
81
|
+
instances = instances.filter(instance => {
|
|
82
|
+
const startFile = instance.options.find(option => option.name === "path");
|
|
83
|
+
return startFile && startFile.value.trim() === path.join(installDir, "start.js");
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
return instances;
|
|
87
|
+
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
exports.validateIBMiCCSID = function(ccsid) {
|
|
91
|
+
|
|
92
|
+
if (!Number.isInteger(ccsid) || ccsid < 1 || ccsid > 65535) {
|
|
93
|
+
return "CCSID must be a number 1-65535";
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
exports.validateIBMiIASP = function(name) {
|
|
99
|
+
|
|
100
|
+
if (name.toUpperCase() !== "*SYSBAS") {
|
|
101
|
+
return exports.validateIBMiName(name);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
exports.validateIBMiName = function(name) {
|
|
107
|
+
|
|
108
|
+
if (name.length < 1 || name.length > 10) {
|
|
109
|
+
return "Name must be from 1-10 characters.";
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const firstChar = name.substr(0, 1).toUpperCase();
|
|
113
|
+
if ((firstChar < "A" || firstChar > "Z") && firstChar != "#" && firstChar != "@" && firstChar != "$") {
|
|
114
|
+
return "Name must start with either a character A-Z, #, @, or $";
|
|
115
|
+
}
|
|
116
|
+
for (let i = 1; i < name.length; i++) {
|
|
117
|
+
const chr = name.substr(i, 1).toUpperCase();
|
|
118
|
+
if ((chr < "A" || chr > "Z") && (chr < "0" || chr > "9") && chr != "#" && chr != "@" && chr != "$" && chr != "_" && chr != ".") {
|
|
119
|
+
return "Name contains an invalid character: " + chr;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
}
|