@leverege/build-tools 2.4.8 → 2.5.0-beta.39

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.
Files changed (41) hide show
  1. package/README.md +0 -1
  2. package/lib/server/build-tools.js +144 -0
  3. package/lib/server/getfbcfg.js +25 -0
  4. package/lib/server/getjson.js +74 -0
  5. package/lib/server/helmify/helm.js +5 -5
  6. package/lib/server/npm-scripts/postinstall.js +19 -0
  7. package/lib/server/overwhelm.js +373 -0
  8. package/lib/server/repo-init/Config.js +45 -0
  9. package/lib/server/repo-init/RepoInit.js +176 -0
  10. package/lib/server/repo-init/config.tgz +0 -0
  11. package/lib/server/repo-init/gitter/Gitter.js +241 -0
  12. package/lib/server/repo-init/gitter/RepoHosting.js +106 -0
  13. package/lib/server/repo-init/gitter/index.js +9 -0
  14. package/lib/server/repo-init/index.js +6 -0
  15. package/lib/server/repo-init/templates/Templates.js +279 -0
  16. package/lib/server/repo-init/templates/ToBuildSpec.js +95 -0
  17. package/lib/server/repo-init/templates/index.js +9 -0
  18. package/lib/server/repo-init/utils/Shell.js +102 -0
  19. package/lib/server/repo-init/utils/VersionCheck.js +82 -0
  20. package/lib/server/repo-init/utils/index.js +67 -0
  21. package/lib/web/build-tools.js +144 -0
  22. package/lib/web/getfbcfg.js +25 -0
  23. package/lib/web/getjson.js +74 -0
  24. package/lib/web/npm-scripts/postinstall.js +19 -0
  25. package/lib/web/overwhelm.js +373 -0
  26. package/package.json +30 -29
  27. package/src/bash-funcs +61 -0
  28. package/src/build-tools.js +137 -0
  29. package/src/{getfbcfg → getfbcfg.js} +7 -6
  30. package/src/getjson.js +74 -0
  31. package/src/helmdn +1 -1
  32. package/src/helminit-dp +2 -0
  33. package/src/npm-scripts/postinstall.js +17 -0
  34. package/src/{overwhelm → overwhelm.js} +83 -83
  35. package/lib/server/packleate/Packleator.js +0 -280
  36. package/lib/server/packleate/index.js +0 -98
  37. package/lib/server/packleate/logo-ansi.js +0 -17
  38. package/lib/web/packleate/Packleator.js +0 -623
  39. package/lib/web/packleate/index.js +0 -163
  40. package/lib/web/packleate/logo-ansi.js +0 -3
  41. 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,9 @@
1
+ "use strict";
2
+
3
+ const {
4
+ Templates
5
+ } = require('./Templates');
6
+
7
+ module.exports = {
8
+ Templates
9
+ };
@@ -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
+ };