@leverege/build-tools 2.4.9 → 2.5.0-beta.40
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/README.md +0 -1
- package/lib/server/build-tools.js +144 -0
- package/lib/server/getfbcfg.js +25 -0
- package/lib/server/getjson.js +74 -0
- package/lib/server/npm-scripts/postinstall.js +19 -0
- package/lib/server/overwhelm.js +373 -0
- package/lib/server/repo-init/Config.js +45 -0
- package/lib/server/repo-init/RepoInit.js +176 -0
- package/lib/server/repo-init/config.tgz +0 -0
- package/lib/server/repo-init/gitter/Gitter.js +241 -0
- package/lib/server/repo-init/gitter/RepoHosting.js +106 -0
- package/lib/server/repo-init/gitter/index.js +9 -0
- package/lib/server/repo-init/index.js +6 -0
- package/lib/server/repo-init/templates/Templates.js +279 -0
- package/lib/server/repo-init/templates/ToBuildSpec.js +95 -0
- package/lib/server/repo-init/templates/index.js +9 -0
- package/lib/server/repo-init/utils/Shell.js +102 -0
- package/lib/server/repo-init/utils/VersionCheck.js +82 -0
- package/lib/server/repo-init/utils/index.js +67 -0
- package/lib/web/build-tools.js +144 -0
- package/lib/web/getfbcfg.js +25 -0
- package/lib/web/getjson.js +74 -0
- package/lib/web/npm-scripts/postinstall.js +19 -0
- package/lib/web/overwhelm.js +373 -0
- package/package.json +30 -29
- package/src/bash-funcs +61 -0
- package/src/build-tools.js +137 -0
- package/src/{getfbcfg → getfbcfg.js} +7 -6
- package/src/getjson.js +74 -0
- package/src/helmdn +1 -1
- package/src/npm-scripts/postinstall.js +17 -0
- package/src/{overwhelm → overwhelm.js} +83 -83
- package/lib/server/packleate/Packleator.js +0 -280
- package/lib/server/packleate/index.js +0 -98
- package/lib/server/packleate/logo-ansi.js +0 -17
- package/lib/web/packleate/Packleator.js +0 -623
- package/lib/web/packleate/index.js +0 -163
- package/lib/web/packleate/logo-ansi.js +0 -3
- package/src/getjson +0 -48
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Contains the available templates and potential files common to all
|
|
5
|
+
* templates, along with a JSON config controlling certain aspects of
|
|
6
|
+
* the available templates.
|
|
7
|
+
*/
|
|
8
|
+
const chalk = require('chalk');
|
|
9
|
+
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
|
|
12
|
+
const inquirer = require('inquirer');
|
|
13
|
+
|
|
14
|
+
const ncp = require('ncp').ncp;
|
|
15
|
+
|
|
16
|
+
const path = require('path');
|
|
17
|
+
|
|
18
|
+
const ToBuildSpec = require('./ToBuildSpec');
|
|
19
|
+
|
|
20
|
+
class Templates {
|
|
21
|
+
constructor(config) {
|
|
22
|
+
Object.assign(this, config);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
getAll() {
|
|
26
|
+
return this.config.templates.filter(entry => entry.enabled);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
lookupTemplateByType(type) {
|
|
30
|
+
return this.config.templates.find(entry => entry.type === type);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
lookupTypeByName(name) {
|
|
34
|
+
const template = this.config.templates.find(entry => entry.name === name);
|
|
35
|
+
return template.type || 'unknown';
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
lookupSubTypesByType(type) {
|
|
39
|
+
const template = this.lookupTemplateByType(type);
|
|
40
|
+
return template.subTypes || [];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
lookupLogConfig(type) {
|
|
44
|
+
const logConfigs = {
|
|
45
|
+
/* eslint-disable key-spacing */
|
|
46
|
+
'Pino Streaming': '{"type":"pino","level":"debug"}',
|
|
47
|
+
'Bunyan Streaming': '{"type":"bunyan",level": "debug"',
|
|
48
|
+
'Bunyan Rotating Files': '{"type":"bunyan-rotating","level":"debug"}'
|
|
49
|
+
/* eslint-enable key-spacing */
|
|
50
|
+
|
|
51
|
+
};
|
|
52
|
+
return !type ? Object.keys(logConfigs) : logConfigs[type];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
needsAnIngestionPort(template) {
|
|
56
|
+
return template.type === 'ingestor' && template.subType !== 'PubSub';
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async runInquiry(spec) {
|
|
60
|
+
const templateQs = [{
|
|
61
|
+
type: 'input',
|
|
62
|
+
name: 'template.serviceName',
|
|
63
|
+
message: 'The library or service name to use for logging and such?',
|
|
64
|
+
default: spec.git.name
|
|
65
|
+
}, {
|
|
66
|
+
type: 'list',
|
|
67
|
+
name: 'template.type',
|
|
68
|
+
message: 'What type of repository do you wish to create?',
|
|
69
|
+
choices: this.getAll(),
|
|
70
|
+
filter: name => {
|
|
71
|
+
return this.lookupTypeByName(name);
|
|
72
|
+
}
|
|
73
|
+
}, {
|
|
74
|
+
type: 'list',
|
|
75
|
+
name: 'template.subType',
|
|
76
|
+
message: 'Select the type of ingestor to create:',
|
|
77
|
+
choices: this.lookupSubTypesByType('ingestor'),
|
|
78
|
+
default: 'PubSub',
|
|
79
|
+
when: answers => {
|
|
80
|
+
return answers.template.type === 'ingestor';
|
|
81
|
+
}
|
|
82
|
+
}, {
|
|
83
|
+
type: 'number',
|
|
84
|
+
name: 'template.ingestionPort',
|
|
85
|
+
message: 'Enter the Ingestion port to use',
|
|
86
|
+
default: 9999,
|
|
87
|
+
when: answers => {
|
|
88
|
+
return this.needsAnIngestionPort(answers.template);
|
|
89
|
+
}
|
|
90
|
+
}, {
|
|
91
|
+
type: 'number',
|
|
92
|
+
name: 'template.expressPort',
|
|
93
|
+
message: 'Enter the HTTP/Express port to use',
|
|
94
|
+
default: 8080,
|
|
95
|
+
when: answers => {
|
|
96
|
+
return answers.template.type.match(/express|ingestor/);
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
/**
|
|
100
|
+
{
|
|
101
|
+
type : 'number',
|
|
102
|
+
name : 'template.port',
|
|
103
|
+
message : 'Enter the network port to use',
|
|
104
|
+
default : 8080,
|
|
105
|
+
when : ( answers ) => {
|
|
106
|
+
condir( 'Current Answers=>', answers )//XXX
|
|
107
|
+
const template = this.lookupTemplateByType( answers.template.type )
|
|
108
|
+
return (
|
|
109
|
+
typeof template.port !== 'undefined' &&
|
|
110
|
+
answers.template.subType !== 'PubSub'
|
|
111
|
+
)
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
*/
|
|
115
|
+
{
|
|
116
|
+
type: 'confirm',
|
|
117
|
+
name: 'template.helmify',
|
|
118
|
+
message: 'Run helmify to generate Helm Charts?',
|
|
119
|
+
default: false,
|
|
120
|
+
when: answers => {
|
|
121
|
+
const template = this.lookupTemplateByType(answers.template.type);
|
|
122
|
+
return typeof template.helm !== 'undefined';
|
|
123
|
+
}
|
|
124
|
+
}, {
|
|
125
|
+
type: 'list',
|
|
126
|
+
name: 'dotenv.logConfig',
|
|
127
|
+
message: 'Your preferred logging method (.env)?',
|
|
128
|
+
choices: this.lookupLogConfig(),
|
|
129
|
+
filter: logType => {
|
|
130
|
+
return this.lookupLogConfig(logType);
|
|
131
|
+
},
|
|
132
|
+
when: answers => {
|
|
133
|
+
return answers.template.type.match(/express|ingestor/);
|
|
134
|
+
}
|
|
135
|
+
}, {
|
|
136
|
+
type: 'input',
|
|
137
|
+
name: 'dotenv.cmWebServerPort',
|
|
138
|
+
message: 'The cluster manager web port to use (.env)?',
|
|
139
|
+
default: 5121,
|
|
140
|
+
when: answers => {
|
|
141
|
+
return answers.template.type.match(/express|ingestor/);
|
|
142
|
+
}
|
|
143
|
+
}, {
|
|
144
|
+
type: 'input',
|
|
145
|
+
name: 'dotenv.imagineURL',
|
|
146
|
+
message: 'The URL to use to get to the api (.env)?',
|
|
147
|
+
default: 'http://localhost:8181',
|
|
148
|
+
when: answers => {
|
|
149
|
+
return answers.template.type.match(/express|ingestor/);
|
|
150
|
+
}
|
|
151
|
+
}];
|
|
152
|
+
console.log(chalk.green(`
|
|
153
|
+
The answers to the following questions will describe the type of software
|
|
154
|
+
repository to generate, as well as define certain configuration parameters
|
|
155
|
+
expected by the resultant code.
|
|
156
|
+
`));
|
|
157
|
+
const answers = await inquirer.prompt(templateQs);
|
|
158
|
+
/**
|
|
159
|
+
* Augment the answers with the proper config to make it easier to use
|
|
160
|
+
* that info downstream.
|
|
161
|
+
*/
|
|
162
|
+
|
|
163
|
+
return { ...answers,
|
|
164
|
+
config: this.lookupTemplateByType(answers.template.type)
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
async build(buildSpec) {
|
|
169
|
+
/**
|
|
170
|
+
* Start assembling the desired template by attempting to create
|
|
171
|
+
* the top level directory.
|
|
172
|
+
*/
|
|
173
|
+
try {
|
|
174
|
+
fs.mkdirSync(buildSpec.git.name);
|
|
175
|
+
} catch (err) {
|
|
176
|
+
console.log(chalk.yellow.bold(`
|
|
177
|
+
${chalk.red.bold(err)}
|
|
178
|
+
^^Fix this and try again.
|
|
179
|
+
`));
|
|
180
|
+
process.exit(1);
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* The ncp recursive file copying library supports the notion of
|
|
184
|
+
* filters, and stream transforming. The filter is created to
|
|
185
|
+
* disallow the copying of any special files that begin with an
|
|
186
|
+
* underscore character. The transform function connects the spec
|
|
187
|
+
* building logic to transform special strings into the values in the
|
|
188
|
+
* active build specification.
|
|
189
|
+
*/
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
const NcpOptions = {
|
|
193
|
+
clobber: true,
|
|
194
|
+
filter: fullName => {
|
|
195
|
+
const fileRegExp = new RegExp('^[^_]');
|
|
196
|
+
return fileRegExp.test(path.basename(fullName));
|
|
197
|
+
},
|
|
198
|
+
transform: (readStream, writeStream, file) => {
|
|
199
|
+
const transformer = new ToBuildSpec(buildSpec);
|
|
200
|
+
readStream.pipe(transformer).pipe(writeStream);
|
|
201
|
+
}
|
|
202
|
+
}; // a simple helper to convey _UNDER_CONSTRUCTION_ notes / suggestions
|
|
203
|
+
|
|
204
|
+
const warnIfUnderConstruction = (dir, constructionArea) => {
|
|
205
|
+
const constructionFile = `${dir}/_UNDER_CONSTRUCTION_`;
|
|
206
|
+
|
|
207
|
+
if (fs.existsSync(constructionFile)) {
|
|
208
|
+
const message = fs.readFileSync(constructionFile);
|
|
209
|
+
console.log(`
|
|
210
|
+
${chalk.yellow.bold(`***WARNING: ${constructionArea} template is marked as Under Construction`)}
|
|
211
|
+
${chalk.blue.bold(message)}
|
|
212
|
+
`);
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
const checkForPackageAdds = async (source, destination) => {
|
|
217
|
+
const packageAddsFile = `${source}/_PACKAGE_ADDS_`;
|
|
218
|
+
|
|
219
|
+
if (fs.existsSync(packageAddsFile)) {
|
|
220
|
+
const npmCommands = fs.readFileSync(packageAddsFile).toString('utf-8').split('\n');
|
|
221
|
+
console.log(`${chalk.yellow.bold('***WARNING: Running Package Adds')}`);
|
|
222
|
+
const regexp = new RegExp('^([+-]) (\\@*\\w+/*\\w*\\-*\\w*)');
|
|
223
|
+
|
|
224
|
+
for (let i = 0; i < npmCommands.length; i++) {
|
|
225
|
+
const match = npmCommands[i].match(regexp);
|
|
226
|
+
|
|
227
|
+
if (!match) {
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const npmAction = `${match[1] === '+' ? 'install' : 'uninstall'} ${match[2]}`;
|
|
232
|
+
buildSpec.npmActions.push(`${npmAction} --save`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
const ncpSync = async (source, destination, options) => {
|
|
238
|
+
return new Promise((resolve, reject) => {
|
|
239
|
+
ncp(source, destination, options, err => {
|
|
240
|
+
if (err) {
|
|
241
|
+
reject(err);
|
|
242
|
+
} else {
|
|
243
|
+
resolve({
|
|
244
|
+
status: `ncpSync: completed ${source} => ${destination}`
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
}; // start copying the template files in to the tree.
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
const destination = buildSpec.git.name;
|
|
253
|
+
const template = this.config.templates.find(tmpl => tmpl.type === buildSpec.template.type); // copy the typical files to the target tree
|
|
254
|
+
|
|
255
|
+
for (let i = 0; i < template.sources.length; i++) {
|
|
256
|
+
const source = template.sources[i];
|
|
257
|
+
const sourceDir = `${this.configDir}/${source}`;
|
|
258
|
+
warnIfUnderConstruction(sourceDir, buildSpec.template.type);
|
|
259
|
+
await ncpSync(sourceDir, destination, NcpOptions); // eslint-disable-line
|
|
260
|
+
|
|
261
|
+
checkForPackageAdds(sourceDir, destination); // check for _subTypes
|
|
262
|
+
|
|
263
|
+
const subTypeRoot = `${sourceDir}/_subTypes/${buildSpec.template.subType}`;
|
|
264
|
+
warnIfUnderConstruction(subTypeRoot, `${buildSpec.template.type}/${buildSpec.template.subType}`);
|
|
265
|
+
const subTypeDest = `${buildSpec.git.name}/src`;
|
|
266
|
+
|
|
267
|
+
if (fs.existsSync(subTypeRoot)) {
|
|
268
|
+
await ncpSync(subTypeRoot, subTypeDest, NcpOptions); // eslint-disable-line
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
checkForPackageAdds(subTypeRoot, destination);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
module.exports = {
|
|
278
|
+
Templates
|
|
279
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
4
|
+
|
|
5
|
+
const {
|
|
6
|
+
Transform
|
|
7
|
+
} = require('stream');
|
|
8
|
+
/**
|
|
9
|
+
* This is the stream transform logic that replaces the repo-init special
|
|
10
|
+
* string of REPI:<BuildSpecVariable> with the contents of the referenced
|
|
11
|
+
* variable from the buildSpec.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ToBuildSpec extends Transform {
|
|
16
|
+
constructor(buildSpec) {
|
|
17
|
+
super({
|
|
18
|
+
objectMode: true
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
_defineProperty(this, "_transform", function _transformFunc(chunk, encoding, done) {
|
|
22
|
+
const chunkStr = chunk.toString();
|
|
23
|
+
/**
|
|
24
|
+
* Concern of possible partial strings when working with large files.
|
|
25
|
+
* In this case, most source will be less than 10K so this should not
|
|
26
|
+
* be a problem for the most part, but error out if it occurs.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
if (!chunkStr.endsWith('\n')) {
|
|
30
|
+
// TODO: This logic if flawed looking for \n
|
|
31
|
+
console.error(`***PARTIAL LINE***[${chunkStr}]`);
|
|
32
|
+
process.exit(1); // TODO: throw something not exit
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Used for pulling nested or flat values from the buildSpec. This allows
|
|
36
|
+
* the build spec to look like this:
|
|
37
|
+
* {
|
|
38
|
+
* gitName : 'myName',
|
|
39
|
+
* git : {
|
|
40
|
+
* name : 'myName',
|
|
41
|
+
* }
|
|
42
|
+
* }
|
|
43
|
+
* and either can be retrieved with a key of gitName or git.name.
|
|
44
|
+
*/
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
const valueFromSpec = (key, spec = this.buildSpec) => {
|
|
48
|
+
if (!key.match(/\.+/)) {
|
|
49
|
+
return spec[key];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const keys = key.split('.');
|
|
53
|
+
return valueFromSpec(keys[1], spec[keys[0]]);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const splitLines = chunkStr.split('\n');
|
|
57
|
+
const xfmLines = splitLines.map(line => {
|
|
58
|
+
let replaced = line;
|
|
59
|
+
|
|
60
|
+
for (const match of line.matchAll(this.regexp)) {
|
|
61
|
+
// eslint-disable-line no-restricted-syntax
|
|
62
|
+
const replaceWith = valueFromSpec(match[1]);
|
|
63
|
+
|
|
64
|
+
if (typeof replaceWith === 'undefined') {
|
|
65
|
+
// console.log( `Skipping unknown build spec property =>[${match[1]}]` )//XXX
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
replaced = replaced.replace(match[0], replaceWith);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return replaced;
|
|
73
|
+
});
|
|
74
|
+
const xfmString = xfmLines.join('\n');
|
|
75
|
+
this.push(Buffer.from(xfmString));
|
|
76
|
+
done();
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
_defineProperty(this, "_flush", function _flushFunc(done) {
|
|
80
|
+
/**
|
|
81
|
+
if ( this._partialLine ) {
|
|
82
|
+
this.push( [ this._partialLine ] )
|
|
83
|
+
}
|
|
84
|
+
this._partialLine = null
|
|
85
|
+
*/
|
|
86
|
+
done();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
this.buildSpec = buildSpec;
|
|
90
|
+
this.regexp = new RegExp('REPI:<(\\w+\\.*\\w*)>', 'g');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
module.exports = ToBuildSpec;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shell like things can go in here. I mostly created this to make it
|
|
5
|
+
* easier to push and pop around the directory trees for repo-init. It
|
|
6
|
+
* might make sense to add other things in here to make writing node CLI
|
|
7
|
+
* commands a little less painful.
|
|
8
|
+
*/
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
|
|
11
|
+
const process = require('process');
|
|
12
|
+
|
|
13
|
+
const dirStack = [];
|
|
14
|
+
/**
|
|
15
|
+
* Simple wrapper functions for debugging.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const cwd = () => {
|
|
19
|
+
return process.cwd();
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const chdir = dir => {
|
|
23
|
+
return process.chdir(dir);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const dirs = () => {
|
|
27
|
+
console.log(dirStack);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const pushd = dir => {
|
|
31
|
+
if (!dir) {
|
|
32
|
+
throw new Error('pushd: no other directory');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
dirStack.push(cwd());
|
|
36
|
+
chdir(dir);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const throwIfEmptyStack = () => {
|
|
40
|
+
if (dirStack.length === 0) {
|
|
41
|
+
throw new Error('popd: directory stack empty');
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const popd = all => {
|
|
46
|
+
throwIfEmptyStack();
|
|
47
|
+
chdir(dirStack.pop());
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const popdAll = () => {
|
|
51
|
+
throwIfEmptyStack();
|
|
52
|
+
chdir(dirStack[0]);
|
|
53
|
+
dirStack.length = 0;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* This function will do an upwards traversal of a file tree looking for the
|
|
57
|
+
* specified file. An error will be thrown if the file is not found within
|
|
58
|
+
* maxLevels.
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
const reverseFindFile = (findFile, options) => {
|
|
63
|
+
pushd(options.startDir || cwd());
|
|
64
|
+
let maxLevels = options.maxLevels || 5;
|
|
65
|
+
let fileRoot;
|
|
66
|
+
|
|
67
|
+
while (maxLevels > 0) {
|
|
68
|
+
if (fs.existsSync(findFile)) {
|
|
69
|
+
fileRoot = cwd();
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
pushd('..'); // walk up the tree
|
|
74
|
+
|
|
75
|
+
maxLevels -= 1;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
popdAll();
|
|
79
|
+
|
|
80
|
+
if (!fileRoot) {
|
|
81
|
+
throw new Error(`reverseFindFile: ${findFile} not found`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return fileRoot;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const findRepoRoot = () => {
|
|
88
|
+
return reverseFindFile('package.json', {
|
|
89
|
+
startDir: __dirname
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
module.exports = {
|
|
94
|
+
dirs,
|
|
95
|
+
pushd,
|
|
96
|
+
popd,
|
|
97
|
+
popdAll,
|
|
98
|
+
reverseFindFile,
|
|
99
|
+
findRepoRoot,
|
|
100
|
+
cwd,
|
|
101
|
+
chdir
|
|
102
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
|
|
5
|
+
const coerce = require('semver/functions/coerce');
|
|
6
|
+
|
|
7
|
+
const semverLt = require('semver/functions/lt');
|
|
8
|
+
|
|
9
|
+
const satisfies = require('semver/functions/satisfies');
|
|
10
|
+
/**
|
|
11
|
+
* This function verifies the specified version falls in this range:
|
|
12
|
+
*
|
|
13
|
+
* minimum >= current < maximum
|
|
14
|
+
*
|
|
15
|
+
* The params will be semver coerced where a version of 12 will be coerced
|
|
16
|
+
* to 12.0.0, a version of 12.18.4-beta.3 will be coerced to 12.18.4.
|
|
17
|
+
*
|
|
18
|
+
* Note that this function still has its references to node, but could be
|
|
19
|
+
* made entirely generic if need be.
|
|
20
|
+
*
|
|
21
|
+
* @param {Object} params
|
|
22
|
+
* @param {String} params.current - version to check
|
|
23
|
+
* @param {String} params.minimum - can be equal or greater to this
|
|
24
|
+
* @param {String} params.maximum - must be less than this
|
|
25
|
+
* @param {String} params.preferred - the most acceptable version
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
function validate(params = {}) {
|
|
30
|
+
const throwChalk = error => {
|
|
31
|
+
const errorStr = chalk.red.bold('***ERROR =>');
|
|
32
|
+
throw new Error(chalk.keyword('orange').bold(`\n${errorStr} ${error}`));
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
if (!params || !params.current || !params.minimum || !params.maximum) {
|
|
36
|
+
throwChalk('current, minimum and maximum parameters are required by validate');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const coercedVersions = sems => {
|
|
40
|
+
return Object.keys(sems).reduce((obj, key) => {
|
|
41
|
+
const coerced = obj; // avoid eslint warning
|
|
42
|
+
|
|
43
|
+
coerced[key] = coerce(sems[key]).version;
|
|
44
|
+
return coerced;
|
|
45
|
+
}, {});
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const {
|
|
49
|
+
current,
|
|
50
|
+
minimum,
|
|
51
|
+
maximum,
|
|
52
|
+
preferred
|
|
53
|
+
} = coercedVersions(params);
|
|
54
|
+
/**
|
|
55
|
+
* Verify that the current version falls within the accepted ranges.
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
const rangeStr = `>=${minimum} <${maximum}`;
|
|
59
|
+
|
|
60
|
+
if (!satisfies(current, rangeStr)) {
|
|
61
|
+
throwChalk(`Version ${current} is outside the accepted range of ${rangeStr}`);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Suggest upgrading to the currently recommended version.
|
|
65
|
+
*/
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
if (preferred && semverLt(current, preferred)) {
|
|
69
|
+
console.log(chalk.keyword('orange').bold(`
|
|
70
|
+
${chalk.yellow.bold(' *** HEADS UP ***')}
|
|
71
|
+
Running node version => ${chalk.yellow.bold(`v${current}`)} (which should work)
|
|
72
|
+
Preferred version is => ${chalk.green.bold(`v${preferred}`)}
|
|
73
|
+
|
|
74
|
+
Also, a reinstall of the build-tools may be necessary after any node upgrade
|
|
75
|
+
${chalk.cyan.bold('npm i -g @leverege/build-tools')}
|
|
76
|
+
`));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
module.exports = {
|
|
81
|
+
validate
|
|
82
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const inquirer = require('inquirer');
|
|
4
|
+
|
|
5
|
+
const Shell = require('./Shell');
|
|
6
|
+
|
|
7
|
+
const VersionCheck = require('./VersionCheck');
|
|
8
|
+
/**
|
|
9
|
+
* Clears the screen and optionally homes the cursor.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
const clear = (home = true) => {
|
|
14
|
+
// console.log( ( home ? '\x1B[0f' : '' ) + '\x1B[2J' )
|
|
15
|
+
console.log(`${home ? '\x1B[0f' : ''}\x1B[2J`);
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* A simple object dumping convenience.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
const condir = (log, thing) => {
|
|
23
|
+
console.dir({
|
|
24
|
+
log,
|
|
25
|
+
thing
|
|
26
|
+
}, {
|
|
27
|
+
depth: 8,
|
|
28
|
+
colors: true
|
|
29
|
+
}); // eslint-disable-line
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* General "yes" to proceed function.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
const proceed = async (query = 'Do you wish to proceed?') => {
|
|
37
|
+
await inquirer.prompt([{
|
|
38
|
+
type: 'confirm',
|
|
39
|
+
name: 'proceed',
|
|
40
|
+
message: query,
|
|
41
|
+
default: true
|
|
42
|
+
}]).then(answer => {
|
|
43
|
+
if (!answer.proceed) {
|
|
44
|
+
process.exit(0);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* A simple mS sleeper.
|
|
50
|
+
*/
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
const sleep = (ms = 0) => {
|
|
54
|
+
return new Promise(resolve => {
|
|
55
|
+
setTimeout(resolve, ms);
|
|
56
|
+
});
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
module.exports = {
|
|
60
|
+
clear,
|
|
61
|
+
condir,
|
|
62
|
+
proceed,
|
|
63
|
+
sleep,
|
|
64
|
+
pause: sleep,
|
|
65
|
+
Shell,
|
|
66
|
+
VersionCheck
|
|
67
|
+
};
|