@leverege/build-tools 2.21.0-beta.4 → 2.21.1
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/package.json +4 -15
- package/src/helmup +3 -1
- package/lib/server/repo-init/Config.js +0 -45
- package/lib/server/repo-init/RepoInit.js +0 -177
- package/lib/server/repo-init/config.tgz +0 -0
- package/lib/server/repo-init/gitter/Gitter.js +0 -256
- package/lib/server/repo-init/gitter/RepoHosting.js +0 -105
- package/lib/server/repo-init/gitter/index.js +0 -9
- package/lib/server/repo-init/index.js +0 -6
- package/lib/server/repo-init/templates/Templates.js +0 -300
- package/lib/server/repo-init/templates/ToBuildSpec.js +0 -90
- package/lib/server/repo-init/templates/index.js +0 -9
- package/lib/server/repo-init/utils/Shell.js +0 -102
- package/lib/server/repo-init/utils/VersionCheck.js +0 -82
- package/lib/server/repo-init/utils/index.js +0 -67
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leverege/build-tools",
|
|
3
|
-
"version": "2.21.
|
|
3
|
+
"version": "2.21.1",
|
|
4
4
|
"description": "A collection of build / support tools for Leverege developers",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
@@ -11,12 +11,11 @@
|
|
|
11
11
|
"build": "npm run compile",
|
|
12
12
|
"clean": "rm -rf lib",
|
|
13
13
|
"compile": "npm run clean && npm run compile_server && npm run compile_web",
|
|
14
|
-
"compile_server": "NODE_ENV=server babel -d lib/server src/
|
|
14
|
+
"compile_server": "NODE_ENV=server babel -d lib/server src/",
|
|
15
15
|
"compile_web": "NODE_ENV=web babel -d lib/web src/",
|
|
16
16
|
"postinstall": "src/npm-scripts/postinstall.js",
|
|
17
17
|
"prepublintOnly": "npm run lint && npm run build",
|
|
18
18
|
"prepublishOnly": "npm run compile",
|
|
19
|
-
"repo_init_publisher": "src/repo-init/scripts/augment-npmpublish",
|
|
20
19
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
21
20
|
},
|
|
22
21
|
"bin": {
|
|
@@ -43,7 +42,6 @@
|
|
|
43
42
|
"prune-git": "src/prune-git",
|
|
44
43
|
"pull-git": "src/pull-git",
|
|
45
44
|
"push-my-chart": "src/push-my-chart",
|
|
46
|
-
"repo-init": "lib/server/repo-init/index.js",
|
|
47
45
|
"unleash": "src/unleash.js",
|
|
48
46
|
"firebaseDeploy": "src/firebaseDeploy.mjs",
|
|
49
47
|
"firebaseServe": "src/firebaseServe.mjs"
|
|
@@ -52,31 +50,22 @@
|
|
|
52
50
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
53
51
|
"dependencies": {
|
|
54
52
|
"chalk": "^4.1.2",
|
|
55
|
-
"clipboardy": "^2.3.0",
|
|
56
53
|
"command-line-args": "^5.2.1",
|
|
57
54
|
"command-line-usage": "^6.1.3",
|
|
58
55
|
"deepmerge": "^4.2.2",
|
|
59
56
|
"dotenv": "^16.0.1",
|
|
60
|
-
"enquirer": "^2.3.6",
|
|
61
57
|
"execa": "^5.1.1",
|
|
62
|
-
"figlet": "^1.5.2",
|
|
63
58
|
"glob": "^8.0.3",
|
|
64
|
-
"inquirer": "^8.2.4",
|
|
65
59
|
"js-yaml": "^4.1.0",
|
|
66
|
-
"ncp": "^2.0.0",
|
|
67
60
|
"npm-registry-fetch": "^13.3.1",
|
|
68
|
-
"open": "^8.4.0",
|
|
69
|
-
"ora": "^5.4.1",
|
|
70
61
|
"parse-gitignore": "^2.0.0",
|
|
71
62
|
"readline-sync": "^1.4.10",
|
|
72
63
|
"semver": "^7.3.7",
|
|
73
|
-
"simple-git": "^3.
|
|
74
|
-
"zx": "^7.0.8"
|
|
64
|
+
"simple-git": "^3.13.0"
|
|
75
65
|
},
|
|
76
66
|
"devDependencies": {
|
|
77
67
|
"@babel/cli": "^7.18.10",
|
|
78
|
-
"@babel/core": "^7.18.
|
|
79
|
-
"@babel/node": "^7.18.10",
|
|
68
|
+
"@babel/core": "^7.18.13",
|
|
80
69
|
"@leverege/babel-preset-leverege-node": "^2.0.0",
|
|
81
70
|
"@leverege/eslint-config-leverege": "^3.0.1",
|
|
82
71
|
"npm": "^8.18.0"
|
package/src/helmup
CHANGED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const chalk = require('chalk');
|
|
4
|
-
|
|
5
|
-
const fs = require('fs');
|
|
6
|
-
|
|
7
|
-
class Config {
|
|
8
|
-
constructor() {
|
|
9
|
-
this.configDir = `${__dirname}/config`;
|
|
10
|
-
const jsonText = fs.readFileSync(`${this.configDir}/config.json`);
|
|
11
|
-
this.config = JSON.parse(jsonText);
|
|
12
|
-
this.verifyConfig(this.config);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
verifyConfig(config) {
|
|
16
|
-
/**
|
|
17
|
-
* Verify reference sources exist.
|
|
18
|
-
*/
|
|
19
|
-
let errors;
|
|
20
|
-
config.templates.forEach(template => {
|
|
21
|
-
if (!template.enabled) return;
|
|
22
|
-
template.sources.forEach(source => {
|
|
23
|
-
if (typeof source === 'object') {
|
|
24
|
-
console.log(source, 'STILL TODO');
|
|
25
|
-
} else {
|
|
26
|
-
const fullName = `${this.configDir}/${source}`;
|
|
27
|
-
|
|
28
|
-
if (!fs.existsSync(fullName)) {
|
|
29
|
-
console.log(chalk.red(`***ERROR: missing source ${fullName}`));
|
|
30
|
-
errors = true;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
if (errors) {
|
|
37
|
-
process.exit(1);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
module.exports = {
|
|
44
|
-
Config
|
|
45
|
-
};
|
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const chalk = require('chalk');
|
|
4
|
-
|
|
5
|
-
const cliArgs = require('command-line-args');
|
|
6
|
-
|
|
7
|
-
const cliHelp = require('command-line-usage');
|
|
8
|
-
|
|
9
|
-
const execa = require('execa');
|
|
10
|
-
|
|
11
|
-
const figlet = require('figlet');
|
|
12
|
-
|
|
13
|
-
const {
|
|
14
|
-
Config
|
|
15
|
-
} = require('./Config');
|
|
16
|
-
|
|
17
|
-
const {
|
|
18
|
-
Gitter
|
|
19
|
-
} = require('./gitter');
|
|
20
|
-
|
|
21
|
-
const {
|
|
22
|
-
Templates
|
|
23
|
-
} = require('./templates');
|
|
24
|
-
|
|
25
|
-
const {
|
|
26
|
-
clear,
|
|
27
|
-
condir,
|
|
28
|
-
proceed,
|
|
29
|
-
Shell,
|
|
30
|
-
VersionCheck
|
|
31
|
-
} = require('./utils');
|
|
32
|
-
|
|
33
|
-
const thisPackage = require(`${Shell.findRepoRoot()}/package.json`); // eslint-disable-line
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const thisVersion = thisPackage.version;
|
|
37
|
-
const optionList = [// Use optionList to tie into the Usage statements
|
|
38
|
-
{
|
|
39
|
-
name: 'help',
|
|
40
|
-
type: Boolean,
|
|
41
|
-
default: false,
|
|
42
|
-
description: 'display this help screen'
|
|
43
|
-
}, {
|
|
44
|
-
name: 'version',
|
|
45
|
-
type: Boolean,
|
|
46
|
-
default: false,
|
|
47
|
-
description: 'returns the build-tools repo version'
|
|
48
|
-
}, {
|
|
49
|
-
name: 'verbose',
|
|
50
|
-
alias: 'v',
|
|
51
|
-
type: Boolean,
|
|
52
|
-
default: false,
|
|
53
|
-
description: 'emit additional info at run time'
|
|
54
|
-
}];
|
|
55
|
-
const sections = [{
|
|
56
|
-
header: 'The Leverege Repository Initialization Tool',
|
|
57
|
-
content: `
|
|
58
|
-
Generate something {italic very} important.
|
|
59
|
-
More stuff {blue rawr}
|
|
60
|
-
`
|
|
61
|
-
}, {
|
|
62
|
-
header: 'Options',
|
|
63
|
-
optionList
|
|
64
|
-
}];
|
|
65
|
-
const args = cliArgs(optionList, {
|
|
66
|
-
partial: true
|
|
67
|
-
});
|
|
68
|
-
const help = cliHelp(sections);
|
|
69
|
-
|
|
70
|
-
if (args.version) {
|
|
71
|
-
console.log(`v${thisVersion}`);
|
|
72
|
-
process.exit(0);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (args.help) {
|
|
76
|
-
console.log(help);
|
|
77
|
-
process.exit(0);
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Checks the node and build-tools versions.
|
|
81
|
-
*/
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const doVersionChecks = async () => {
|
|
85
|
-
/**
|
|
86
|
-
* Verify that node meets our minimum needs.
|
|
87
|
-
*/
|
|
88
|
-
try {
|
|
89
|
-
VersionCheck.validate({
|
|
90
|
-
current: process.version,
|
|
91
|
-
// this is the node version
|
|
92
|
-
minimum: '16.12.0',
|
|
93
|
-
maximum: '17',
|
|
94
|
-
// must be less than this
|
|
95
|
-
preferred: '16.13.0'
|
|
96
|
-
});
|
|
97
|
-
} catch (err) {
|
|
98
|
-
console.log(err);
|
|
99
|
-
process.exit(1);
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Check to see if we're running the latest version of build-tools.
|
|
103
|
-
*/
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
try {
|
|
107
|
-
await execa('build-tools', ['--latest'], {
|
|
108
|
-
stdout: 'inherit'
|
|
109
|
-
});
|
|
110
|
-
} catch (err) {
|
|
111
|
-
/**
|
|
112
|
-
* An exitCode of 1 is simply how build-tools lets us know that an update
|
|
113
|
-
* exists for the build-tools repository.
|
|
114
|
-
*/
|
|
115
|
-
if (err.exitCode !== 1) {
|
|
116
|
-
console.error(err);
|
|
117
|
-
process.exit(1);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
/**
|
|
122
|
-
* Presents the opening greeting and then to proceed, or not to proceed,
|
|
123
|
-
* that is the question.
|
|
124
|
-
*/
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
const greet = async () => {
|
|
128
|
-
clear();
|
|
129
|
-
console.log(chalk.keyword('orange').bold(figlet.textSync('repo-init', {
|
|
130
|
-
horizontalLayout: 'full'
|
|
131
|
-
})), chalk.green`
|
|
132
|
-
|
|
133
|
-
Welcome to the Leverege repository bootstrapping utility. This utility
|
|
134
|
-
will help with the creation of a new git repository based on the standard
|
|
135
|
-
templates that are currently supported. It will also attempt to tune the
|
|
136
|
-
initial files based on the answers provided during this process.
|
|
137
|
-
`);
|
|
138
|
-
await doVersionChecks();
|
|
139
|
-
await proceed();
|
|
140
|
-
};
|
|
141
|
-
/**
|
|
142
|
-
* Usage:
|
|
143
|
-
*/
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
const start = async () => {
|
|
147
|
-
await greet();
|
|
148
|
-
const config = new Config();
|
|
149
|
-
const gitter = new Gitter(config);
|
|
150
|
-
const gitSpec = await gitter.runInquiry();
|
|
151
|
-
const templates = new Templates(config);
|
|
152
|
-
const templateSpec = await templates.runInquiry(gitSpec);
|
|
153
|
-
const npmActions = ['install'];
|
|
154
|
-
const buildSpec = { ...gitSpec,
|
|
155
|
-
...templateSpec,
|
|
156
|
-
npmActions
|
|
157
|
-
};
|
|
158
|
-
condir('Current Build Spec', buildSpec); // TODO: Clean this up to be a better info dump
|
|
159
|
-
|
|
160
|
-
await proceed('Proceed to populate and build the repository?');
|
|
161
|
-
await templates.build(buildSpec);
|
|
162
|
-
await gitter.build(buildSpec);
|
|
163
|
-
console.log(chalk.green.bold`
|
|
164
|
-
Repository setup complete.
|
|
165
|
-
` // chalk.green.bold`Still to work out:`,
|
|
166
|
-
// chalk.yellow`
|
|
167
|
-
// - figure out better approach for partial file read on transform
|
|
168
|
-
// - add / flesh out remaining templates
|
|
169
|
-
// - express-server
|
|
170
|
-
// - library
|
|
171
|
-
// - ui-lib
|
|
172
|
-
// - ui-???
|
|
173
|
-
// `
|
|
174
|
-
);
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
exports.start = start;
|
|
Binary file
|
|
@@ -1,256 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* All git interactions come through here.
|
|
5
|
-
*/
|
|
6
|
-
const chalk = require('chalk');
|
|
7
|
-
|
|
8
|
-
const execa = require('execa');
|
|
9
|
-
|
|
10
|
-
const fs = require('fs');
|
|
11
|
-
|
|
12
|
-
const inquirer = require('inquirer');
|
|
13
|
-
|
|
14
|
-
const Ora = require('ora');
|
|
15
|
-
|
|
16
|
-
const SimpleGit = require('simple-git');
|
|
17
|
-
|
|
18
|
-
const {
|
|
19
|
-
pause,
|
|
20
|
-
Shell
|
|
21
|
-
} = require('../utils');
|
|
22
|
-
|
|
23
|
-
const repoHosting = require('./RepoHosting');
|
|
24
|
-
|
|
25
|
-
class Gitter {
|
|
26
|
-
constructor() {
|
|
27
|
-
this.git = new SimpleGit();
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
async runInquiry() {
|
|
31
|
-
if (await this.git.checkIsRepo()) {
|
|
32
|
-
console.log(chalk.keyword('orange').bold(`
|
|
33
|
-
The current working directory is a git repository, and continuing this
|
|
34
|
-
operation would create a nested repository, which is not supported. Try
|
|
35
|
-
changing to a plain old subdirectory before attempting to run repo-init.
|
|
36
|
-
|
|
37
|
-
`));
|
|
38
|
-
process.exit(1);
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Validates the name and checks to see if the subdirectory already exists.
|
|
42
|
-
*/
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const verifyRepositoryName = name => {
|
|
46
|
-
if (!RegExp('^\\w+(\\-*\\w*)+$').test(name)) {
|
|
47
|
-
console.log(chalk.yellow.bold(`
|
|
48
|
-
Invalid git repo name => [${chalk.red.bold(name)}]`));
|
|
49
|
-
return false;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (fs.existsSync(name)) {
|
|
53
|
-
console.log(chalk.yellow.bold(`
|
|
54
|
-
A local file or directory named ${name} already exists - remove it and try again.`));
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return true;
|
|
59
|
-
};
|
|
60
|
-
/**
|
|
61
|
-
* The questions that we need to ask about this git build.
|
|
62
|
-
*/
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const gitterQs = [{
|
|
66
|
-
type: 'input',
|
|
67
|
-
name: 'git.name',
|
|
68
|
-
message: 'What is the desired name of the git repository?',
|
|
69
|
-
validate: value => {
|
|
70
|
-
return verifyRepositoryName(value);
|
|
71
|
-
}
|
|
72
|
-
}, {
|
|
73
|
-
type: 'list',
|
|
74
|
-
name: 'git.host',
|
|
75
|
-
message: 'Where will the repository be hosted?',
|
|
76
|
-
choices: ['bitbucket', 'github', 'local']
|
|
77
|
-
}, // {
|
|
78
|
-
// type : 'input',
|
|
79
|
-
// name : 'git.owner',
|
|
80
|
-
// message : 'Who is the owner of the git repository?',
|
|
81
|
-
// default : 'leverege',
|
|
82
|
-
// when : ( answer ) => {
|
|
83
|
-
// return answer.git.host !== 'local'
|
|
84
|
-
// },
|
|
85
|
-
// },
|
|
86
|
-
{
|
|
87
|
-
type: 'list',
|
|
88
|
-
name: 'git.createRemote',
|
|
89
|
-
message: 'Let repo-init create the remote git repository?',
|
|
90
|
-
choices: ['yes', 'skip'],
|
|
91
|
-
when: answer => {
|
|
92
|
-
return answer.git.host !== 'local';
|
|
93
|
-
}
|
|
94
|
-
}];
|
|
95
|
-
return inquirer.prompt(gitterQs);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
async build(buildSpec) {
|
|
99
|
-
if (!fs.existsSync(buildSpec.git.name)) {
|
|
100
|
-
console.log(chalk.yellow.bold(`
|
|
101
|
-
${chalk.red.bold('***ERROR: source directory does not exist')}
|
|
102
|
-
Did the template generation for ${chalk.red.bold(buildSpec.git.name)} fail?
|
|
103
|
-
`));
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const initialCommit = `repo-init => bootstrapped ${buildSpec.template.type} ${buildSpec.git.name}`;
|
|
107
|
-
/**
|
|
108
|
-
* We need to have an initialized git repo before attempting to do an
|
|
109
|
-
* npm install since there are husky rules and it needs git.
|
|
110
|
-
*/
|
|
111
|
-
|
|
112
|
-
const git = SimpleGit(buildSpec.git.name);
|
|
113
|
-
|
|
114
|
-
try {
|
|
115
|
-
await git.init(['--initial-branch', 'development']).add(['--all', '--force']); // we want it all!
|
|
116
|
-
} catch (initErr) {
|
|
117
|
-
console.log(initErr);
|
|
118
|
-
process.exit(1);
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* Keep in mind that all of the git commands will be relevant to the cwd
|
|
122
|
-
* at the time the SimpleGit interface was instantiated. That has nothing
|
|
123
|
-
* to do with the set of commands that are about to execute.
|
|
124
|
-
*/
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
Shell.pushd(buildSpec.git.name);
|
|
128
|
-
const spinner = new Ora();
|
|
129
|
-
|
|
130
|
-
if (buildSpec.config.npmCheck) {
|
|
131
|
-
// console.log( chalk.keyword( 'orange' ).bold( `
|
|
132
|
-
// Running npm-check-updates interactively to verify all of the package
|
|
133
|
-
// versions in package.json are up to date prior to committing everything.` ),
|
|
134
|
-
// chalk.yellow.bold( `
|
|
135
|
-
// Pay attention! You may be asked to answer Y/n if any are out of date!` )
|
|
136
|
-
// )
|
|
137
|
-
// spinner.start( 'Preparing for dependency checks prior to install.' )
|
|
138
|
-
// await pause( 3000 )
|
|
139
|
-
// spinner.succeed()
|
|
140
|
-
// setup husky
|
|
141
|
-
await execa('npm', ['install', 'husky', '--save-dev'], {
|
|
142
|
-
stdio: 'inherit'
|
|
143
|
-
});
|
|
144
|
-
await execa('npm', ['run', 'prepare'], {
|
|
145
|
-
stdio: 'inherit'
|
|
146
|
-
});
|
|
147
|
-
await execa('npx', ['husky', 'add', '.husky/pre-commit', 'unleash'], {
|
|
148
|
-
stdio: 'inherit'
|
|
149
|
-
});
|
|
150
|
-
await execa('npx', ['husky', 'add', '.husky/pre-push', 'unleash'], {
|
|
151
|
-
stdio: 'inherit'
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
try {
|
|
156
|
-
for (let i = 0; i < buildSpec.npmActions.length; i++) {
|
|
157
|
-
const npmAction = buildSpec.npmActions[i];
|
|
158
|
-
spinner.start(`Running npm ${npmAction}`);
|
|
159
|
-
await pause(2000); // eslint-disable-line
|
|
160
|
-
|
|
161
|
-
spinner.stop();
|
|
162
|
-
await execa('npm', npmAction.split(' '), {
|
|
163
|
-
stdio: 'inherit'
|
|
164
|
-
}); // eslint-disable-line
|
|
165
|
-
|
|
166
|
-
spinner.succeed();
|
|
167
|
-
await pause(1000); // eslint-disable-line
|
|
168
|
-
}
|
|
169
|
-
} catch (err) {
|
|
170
|
-
console.error(`${chalk.red.bold(err)}\n\n`);
|
|
171
|
-
spinner.fail('Running npm install');
|
|
172
|
-
process.exit(1);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
if (buildSpec.template.helmify) {
|
|
176
|
-
try {
|
|
177
|
-
await execa('helmify', {
|
|
178
|
-
stdio: 'inherit'
|
|
179
|
-
});
|
|
180
|
-
} catch (err) {
|
|
181
|
-
console.log(err);
|
|
182
|
-
process.exit(1);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
Shell.popd();
|
|
187
|
-
/**
|
|
188
|
-
* Complete the standard git repo setup by adding all,
|
|
189
|
-
* to push to host unless the repo already exists.
|
|
190
|
-
*/
|
|
191
|
-
|
|
192
|
-
try {
|
|
193
|
-
spinner.start('Adding all source to the git repository');
|
|
194
|
-
await git.add(['--all']).commit(initialCommit); // try {
|
|
195
|
-
// await git.branch( [ 'development' ] )
|
|
196
|
-
// } catch ( brerr ) {
|
|
197
|
-
// console.log( brerr, '***CONTINUING ON' )//XXX
|
|
198
|
-
// }
|
|
199
|
-
// await git.checkout( [ 'development' ] )
|
|
200
|
-
|
|
201
|
-
spinner.succeed();
|
|
202
|
-
} catch (err) {
|
|
203
|
-
console.log(err);
|
|
204
|
-
spinner.fail('Repository initialization failed - this is very bad');
|
|
205
|
-
process.exit(1);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
if (buildSpec.template.type === 'ingestor') {
|
|
209
|
-
/**
|
|
210
|
-
* Drop back down into the newly created git repo before creating the
|
|
211
|
-
* .env file in the repository. This file will not be tracked. Note that
|
|
212
|
-
* the pause here is an artificial delay to make this step noticable to
|
|
213
|
-
* the user.
|
|
214
|
-
*/
|
|
215
|
-
Shell.pushd(buildSpec.git.name);
|
|
216
|
-
const makeDot = 'scripts/make-dot';
|
|
217
|
-
spinner.start(`Executing ${chalk.green.bold(makeDot)} to generate a simple .env file.`);
|
|
218
|
-
await execa('bash', [makeDot]);
|
|
219
|
-
await pause(1500); // eslint-disable-line
|
|
220
|
-
|
|
221
|
-
spinner.succeed();
|
|
222
|
-
Shell.popd();
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
if (buildSpec.git.host === 'local' || buildSpec.git.createRemote === 'skip') {
|
|
226
|
-
console.log(chalk.keyword('orange').bold(`
|
|
227
|
-
The repository is now configured with the initial commit and a development
|
|
228
|
-
branch. Since you selected to skip the creation of the remote hosted repository
|
|
229
|
-
it is up to you to complete those steps manually.`));
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
await repoHosting.build(buildSpec);
|
|
234
|
-
console.log(chalk.keyword('orange').bold(`
|
|
235
|
-
The repository is now configured with the initial commit and a development
|
|
236
|
-
branch. The upstream push may take up to 30 seconds to complete.
|
|
237
|
-
`));
|
|
238
|
-
|
|
239
|
-
try {
|
|
240
|
-
spinner.start(`Pushing ${buildSpec.git.name} repository upstream`);
|
|
241
|
-
await git.addRemote('origin', repoHosting.getGitURL('remote', buildSpec)).push(['--set-upstream', 'origin', 'development']).branch(['main']).push(['--set-upstream', 'origin', 'main']).checkout(['development']);
|
|
242
|
-
spinner.succeed();
|
|
243
|
-
} catch (err) {
|
|
244
|
-
console.log(err);
|
|
245
|
-
spinner.fail(`git push ${buildSpec.git.name}`);
|
|
246
|
-
process.exit(1);
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
await repoHosting.openAdmin(buildSpec);
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
module.exports = {
|
|
255
|
-
Gitter
|
|
256
|
-
};
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const chalk = require('chalk');
|
|
4
|
-
|
|
5
|
-
const clipboardy = require('clipboardy');
|
|
6
|
-
|
|
7
|
-
const open = require('open');
|
|
8
|
-
|
|
9
|
-
const {
|
|
10
|
-
clear,
|
|
11
|
-
proceed
|
|
12
|
-
} = require('../utils');
|
|
13
|
-
|
|
14
|
-
const greet = async () => {
|
|
15
|
-
console.log(chalk.keyword('orange').bold(`
|
|
16
|
-
Setting up the initial repository on the git hosting service is a manual
|
|
17
|
-
process which will require the setting of a handful of fields via the UI.
|
|
18
|
-
Proceeding forward with this step will result in a browser window being
|
|
19
|
-
opened at the repository creation page.
|
|
20
|
-
`));
|
|
21
|
-
await proceed('Do you wish to continue to the repo creation page?');
|
|
22
|
-
clear();
|
|
23
|
-
};
|
|
24
|
-
/**
|
|
25
|
-
* This could come from a config file but we're keeping it simple, for now.
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const getGitURL = (type, buildSpec) => {
|
|
30
|
-
const gitHostURLs = {
|
|
31
|
-
control: {
|
|
32
|
-
admin: 'admin',
|
|
33
|
-
create: 'create',
|
|
34
|
-
remote: 'remote'
|
|
35
|
-
},
|
|
36
|
-
bitbucket: {
|
|
37
|
-
admin: `https://bitbucket.org/${buildSpec.git.owner}/${buildSpec.git.name}/admin`,
|
|
38
|
-
create: `https://bitbucket.org/repo/create?owner=${buildSpec.git.owner}`,
|
|
39
|
-
remote: `git@bitbucket-leverege:${buildSpec.git.owner}/${buildSpec.git.name}.git`
|
|
40
|
-
},
|
|
41
|
-
github: {
|
|
42
|
-
admin: `https://github.com/${buildSpec.git.owner}/${buildSpec.git.name}/settings/branches`,
|
|
43
|
-
create: `https://github.com/organizations/${buildSpec.git.owner}/repositories/new`,
|
|
44
|
-
remote: `git@github.com:${buildSpec.git.owner}/${buildSpec.git.name}.git`
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
if (!Object.keys(gitHostURLs.control).includes(type)) {
|
|
49
|
-
throw new Error(`Unknown git URL type of ${type}`);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return gitHostURLs[buildSpec.git.host][type];
|
|
53
|
-
};
|
|
54
|
-
/**
|
|
55
|
-
*/
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const build = async buildSpec => {
|
|
59
|
-
await greet();
|
|
60
|
-
console.log(`${chalk.keyword('orange').bold(`
|
|
61
|
-
Before proceeding you will want to verify that your browser has access to the
|
|
62
|
-
git hosting service you are about to use. The easiest way to do this is to
|
|
63
|
-
simply open a browser window on bitbucket or github with the desired account.
|
|
64
|
-
|
|
65
|
-
Once you proceed from this step a browser window will be opened and you will
|
|
66
|
-
enter the relevant information into the repository creation page. Click the
|
|
67
|
-
${chalk.blue.bold('Create repository')} button to complete the process.
|
|
68
|
-
${chalk.keyword('green').bold(`
|
|
69
|
-
Git Host => ${chalk.yellow.bold(buildSpec.git.host)}
|
|
70
|
-
Project => ${chalk.yellow.bold('Testing or something appropriate')}
|
|
71
|
-
Repository name => ${chalk.yellow.bold(buildSpec.git.name)} <= copied to clipboard`)}
|
|
72
|
-
|
|
73
|
-
${chalk.red.bold('DO NOT initialize a README, gitignore or License file')}
|
|
74
|
-
|
|
75
|
-
This window may be covered by the browser window so be sure to come back here
|
|
76
|
-
after you ${chalk.blue.bold('create the repository')}.`)}
|
|
77
|
-
`);
|
|
78
|
-
await proceed(`You at least read the ${chalk.red.bold('red')} line above and are ready to proceed?`);
|
|
79
|
-
clipboardy.writeSync(buildSpec.git.name);
|
|
80
|
-
await open(getGitURL('create', buildSpec));
|
|
81
|
-
console.log(`${chalk.keyword('orange').bold('Waiting on repo creation to complete...')}`);
|
|
82
|
-
await proceed('Continue after the initial repository has been created?');
|
|
83
|
-
};
|
|
84
|
-
/**
|
|
85
|
-
*/
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const openAdmin = async buildSpec => {
|
|
89
|
-
console.log(chalk.keyword('orange').bold(`
|
|
90
|
-
The admin page for the repository will now be opened in the browser. Please
|
|
91
|
-
take a moment to tweak the following settings:
|
|
92
|
-
|
|
93
|
-
${chalk.keyword('green')('Project')} - adjust if the original selection was slightly off
|
|
94
|
-
${chalk.keyword('green').bold('Description')} - a few words here wouldn't hurt
|
|
95
|
-
${chalk.keyword('green').bold('Language')} - set this to Node.js or Javascript?
|
|
96
|
-
`));
|
|
97
|
-
await open(getGitURL('admin', buildSpec));
|
|
98
|
-
await proceed('Please take a moment to at least set the Language and Main branch?');
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
module.exports = {
|
|
102
|
-
build,
|
|
103
|
-
getGitURL,
|
|
104
|
-
openAdmin
|
|
105
|
-
};
|
|
@@ -1,300 +0,0 @@
|
|
|
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' && template.subType !== 'HTTP' && template.subType !== 'MQTT';
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
isMqtt(template) {
|
|
60
|
-
return template.type === 'ingestor' && template.subType === 'MQTT';
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
async runInquiry(spec) {
|
|
64
|
-
const templateQs = [{
|
|
65
|
-
type: 'input',
|
|
66
|
-
name: 'template.serviceName',
|
|
67
|
-
message: 'The library or service name to use for logging and such?',
|
|
68
|
-
default: spec.git.name
|
|
69
|
-
}, {
|
|
70
|
-
type: 'list',
|
|
71
|
-
name: 'template.type',
|
|
72
|
-
message: 'What type of repository do you wish to create?',
|
|
73
|
-
choices: this.getAll(),
|
|
74
|
-
filter: name => {
|
|
75
|
-
return this.lookupTypeByName(name);
|
|
76
|
-
}
|
|
77
|
-
}, {
|
|
78
|
-
type: 'list',
|
|
79
|
-
name: 'template.subType',
|
|
80
|
-
message: 'Select the type of ingestor to create:',
|
|
81
|
-
choices: this.lookupSubTypesByType('ingestor'),
|
|
82
|
-
default: 'PubSub',
|
|
83
|
-
when: answers => {
|
|
84
|
-
return answers.template.type === 'ingestor';
|
|
85
|
-
}
|
|
86
|
-
}, {
|
|
87
|
-
type: 'number',
|
|
88
|
-
name: 'template.ingestionPort',
|
|
89
|
-
message: 'Enter the Ingestion port to use',
|
|
90
|
-
default: 9999,
|
|
91
|
-
when: answers => {
|
|
92
|
-
return this.needsAnIngestionPort(answers.template);
|
|
93
|
-
}
|
|
94
|
-
}, {
|
|
95
|
-
type: 'string',
|
|
96
|
-
name: 'template.mqttHost',
|
|
97
|
-
message: 'Enter the MQTT Broker address to use',
|
|
98
|
-
default: 'mqtt://broker.emqx.io',
|
|
99
|
-
when: answers => {
|
|
100
|
-
return this.isMqtt(answers.template);
|
|
101
|
-
}
|
|
102
|
-
}, {
|
|
103
|
-
type: 'number',
|
|
104
|
-
name: 'template.mqttPort',
|
|
105
|
-
message: 'Enter the MQTT Broker port to use',
|
|
106
|
-
default: 1883,
|
|
107
|
-
when: answers => {
|
|
108
|
-
return this.isMqtt(answers.template);
|
|
109
|
-
}
|
|
110
|
-
}, {
|
|
111
|
-
type: 'number',
|
|
112
|
-
name: 'template.expressPort',
|
|
113
|
-
message: 'Enter the HTTP/Express port to use',
|
|
114
|
-
default: 8080,
|
|
115
|
-
when: answers => {
|
|
116
|
-
return answers.template.type.match(/express|ingestor/);
|
|
117
|
-
}
|
|
118
|
-
},
|
|
119
|
-
/**
|
|
120
|
-
{
|
|
121
|
-
type : 'number',
|
|
122
|
-
name : 'template.port',
|
|
123
|
-
message : 'Enter the network port to use',
|
|
124
|
-
default : 8080,
|
|
125
|
-
when : ( answers ) => {
|
|
126
|
-
condir( 'Current Answers=>', answers )//XXX
|
|
127
|
-
const template = this.lookupTemplateByType( answers.template.type )
|
|
128
|
-
return (
|
|
129
|
-
typeof template.port !== 'undefined' &&
|
|
130
|
-
answers.template.subType !== 'PubSub'
|
|
131
|
-
)
|
|
132
|
-
},
|
|
133
|
-
},
|
|
134
|
-
*/
|
|
135
|
-
// {
|
|
136
|
-
// type : 'confirm',
|
|
137
|
-
// name : 'template.helmify',
|
|
138
|
-
// message : 'Run helmify to generate Helm Charts?',
|
|
139
|
-
// default : false,
|
|
140
|
-
// when : ( answers ) => {
|
|
141
|
-
// const template = this.lookupTemplateByType( answers.template.type )
|
|
142
|
-
// return typeof template.helm !== 'undefined'
|
|
143
|
-
// },
|
|
144
|
-
// },
|
|
145
|
-
{
|
|
146
|
-
type: 'list',
|
|
147
|
-
name: 'dotenv.logConfig',
|
|
148
|
-
message: 'Your preferred logging method (.env)?',
|
|
149
|
-
choices: this.lookupLogConfig(),
|
|
150
|
-
filter: logType => {
|
|
151
|
-
return this.lookupLogConfig(logType);
|
|
152
|
-
},
|
|
153
|
-
when: answers => {
|
|
154
|
-
return answers.template.type.match(/express|ingestor/);
|
|
155
|
-
}
|
|
156
|
-
}, {
|
|
157
|
-
type: 'input',
|
|
158
|
-
name: 'dotenv.cmWebServerPort',
|
|
159
|
-
message: 'The cluster manager web port to use (.env)?',
|
|
160
|
-
default: 5121,
|
|
161
|
-
when: answers => {
|
|
162
|
-
return answers.template.type.match(/express|ingestor/);
|
|
163
|
-
}
|
|
164
|
-
}, {
|
|
165
|
-
type: 'input',
|
|
166
|
-
name: 'dotenv.imagineURL',
|
|
167
|
-
message: 'The URL to use to get to the api (.env)?',
|
|
168
|
-
default: 'http://localhost:8181',
|
|
169
|
-
when: answers => {
|
|
170
|
-
return answers.template.type.match(/express|ingestor/);
|
|
171
|
-
}
|
|
172
|
-
}];
|
|
173
|
-
console.log(chalk.green(`
|
|
174
|
-
The answers to the following questions will describe the type of software
|
|
175
|
-
repository to generate, as well as define certain configuration parameters
|
|
176
|
-
expected by the resultant code.
|
|
177
|
-
`));
|
|
178
|
-
const answers = await inquirer.prompt(templateQs);
|
|
179
|
-
/**
|
|
180
|
-
* Augment the answers with the proper config to make it easier to use
|
|
181
|
-
* that info downstream.
|
|
182
|
-
*/
|
|
183
|
-
|
|
184
|
-
return { ...answers,
|
|
185
|
-
config: this.lookupTemplateByType(answers.template.type)
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
async build(buildSpec) {
|
|
190
|
-
/**
|
|
191
|
-
* Start assembling the desired template by attempting to create
|
|
192
|
-
* the top level directory.
|
|
193
|
-
*/
|
|
194
|
-
try {
|
|
195
|
-
fs.mkdirSync(buildSpec.git.name);
|
|
196
|
-
} catch (err) {
|
|
197
|
-
console.log(chalk.yellow.bold(`
|
|
198
|
-
${chalk.red.bold(err)}
|
|
199
|
-
^^Fix this and try again.
|
|
200
|
-
`));
|
|
201
|
-
process.exit(1);
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* The ncp recursive file copying library supports the notion of
|
|
205
|
-
* filters, and stream transforming. The filter is created to
|
|
206
|
-
* disallow the copying of any special files that begin with an
|
|
207
|
-
* underscore character. The transform function connects the spec
|
|
208
|
-
* building logic to transform special strings into the values in the
|
|
209
|
-
* active build specification.
|
|
210
|
-
*/
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
const NcpOptions = {
|
|
214
|
-
clobber: true,
|
|
215
|
-
filter: fullName => {
|
|
216
|
-
const fileRegExp = new RegExp('^[^_]');
|
|
217
|
-
return fileRegExp.test(path.basename(fullName));
|
|
218
|
-
},
|
|
219
|
-
transform: (readStream, writeStream, file) => {
|
|
220
|
-
const transformer = new ToBuildSpec(buildSpec);
|
|
221
|
-
readStream.pipe(transformer).pipe(writeStream);
|
|
222
|
-
}
|
|
223
|
-
}; // a simple helper to convey _UNDER_CONSTRUCTION_ notes / suggestions
|
|
224
|
-
|
|
225
|
-
const warnIfUnderConstruction = (dir, constructionArea) => {
|
|
226
|
-
const constructionFile = `${dir}/_UNDER_CONSTRUCTION_`;
|
|
227
|
-
|
|
228
|
-
if (fs.existsSync(constructionFile)) {
|
|
229
|
-
const message = fs.readFileSync(constructionFile);
|
|
230
|
-
console.log(`
|
|
231
|
-
${chalk.yellow.bold(`***WARNING: ${constructionArea} template is marked as Under Construction`)}
|
|
232
|
-
${chalk.blue.bold(message)}
|
|
233
|
-
`);
|
|
234
|
-
}
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
const checkForPackageAdds = async (source, destination) => {
|
|
238
|
-
const packageAddsFile = `${source}/_PACKAGE_ADDS_`;
|
|
239
|
-
|
|
240
|
-
if (fs.existsSync(packageAddsFile)) {
|
|
241
|
-
const npmCommands = fs.readFileSync(packageAddsFile).toString('utf-8').split('\n');
|
|
242
|
-
console.log(`${chalk.yellow.bold('***WARNING: Running Package Adds')}`);
|
|
243
|
-
const regexp = new RegExp('^([+-]) (\\@*\\w+/*\\w*\\-*\\w*)');
|
|
244
|
-
|
|
245
|
-
for (let i = 0; i < npmCommands.length; i++) {
|
|
246
|
-
const match = npmCommands[i].match(regexp);
|
|
247
|
-
|
|
248
|
-
if (!match) {
|
|
249
|
-
continue;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
const npmAction = `${match[1] === '+' ? 'install' : 'uninstall'} ${match[2]}`;
|
|
253
|
-
buildSpec.npmActions.push(`${npmAction} --save`);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
};
|
|
257
|
-
|
|
258
|
-
const ncpSync = async (source, destination, options) => {
|
|
259
|
-
return new Promise((resolve, reject) => {
|
|
260
|
-
ncp(source, destination, options, err => {
|
|
261
|
-
if (err) {
|
|
262
|
-
reject(err);
|
|
263
|
-
} else {
|
|
264
|
-
resolve({
|
|
265
|
-
status: `ncpSync: completed ${source} => ${destination}`
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
|
-
});
|
|
269
|
-
});
|
|
270
|
-
}; // start copying the template files in to the tree.
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
const destination = buildSpec.git.name;
|
|
274
|
-
const template = this.config.templates.find(tmpl => tmpl.type === buildSpec.template.type); // copy the typical files to the target tree
|
|
275
|
-
|
|
276
|
-
for (let i = 0; i < template.sources.length; i++) {
|
|
277
|
-
const source = template.sources[i];
|
|
278
|
-
const sourceDir = `${this.configDir}/${source}`;
|
|
279
|
-
warnIfUnderConstruction(sourceDir, buildSpec.template.type);
|
|
280
|
-
await ncpSync(sourceDir, destination, NcpOptions); // eslint-disable-line
|
|
281
|
-
|
|
282
|
-
checkForPackageAdds(sourceDir, destination); // check for _subTypes
|
|
283
|
-
|
|
284
|
-
const subTypeRoot = `${sourceDir}/_subTypes/${buildSpec.template.subType}`;
|
|
285
|
-
warnIfUnderConstruction(subTypeRoot, `${buildSpec.template.type}/${buildSpec.template.subType}`);
|
|
286
|
-
const subTypeDest = `${buildSpec.git.name}/src`;
|
|
287
|
-
|
|
288
|
-
if (fs.existsSync(subTypeRoot)) {
|
|
289
|
-
await ncpSync(subTypeRoot, subTypeDest, NcpOptions); // eslint-disable-line
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
checkForPackageAdds(subTypeRoot, destination);
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
module.exports = {
|
|
299
|
-
Templates
|
|
300
|
-
};
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const {
|
|
4
|
-
Transform
|
|
5
|
-
} = require('stream');
|
|
6
|
-
/**
|
|
7
|
-
* This is the stream transform logic that replaces the repo-init special
|
|
8
|
-
* string of REPI:<BuildSpecVariable> with the contents of the referenced
|
|
9
|
-
* variable from the buildSpec.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class ToBuildSpec extends Transform {
|
|
14
|
-
constructor(buildSpec) {
|
|
15
|
-
super({
|
|
16
|
-
objectMode: true
|
|
17
|
-
});
|
|
18
|
-
this.buildSpec = buildSpec;
|
|
19
|
-
this.regexp = new RegExp('REPI:<(\\w+\\.*\\w*)>', 'g');
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
_transform = function _transformFunc(chunk, encoding, done) {
|
|
23
|
-
const chunkStr = chunk.toString();
|
|
24
|
-
/**
|
|
25
|
-
* Concern of possible partial strings when working with large files.
|
|
26
|
-
* In this case, most source will be less than 10K so this should not
|
|
27
|
-
* be a problem for the most part, but error out if it occurs.
|
|
28
|
-
*/
|
|
29
|
-
|
|
30
|
-
if (!chunkStr.endsWith('\n')) {
|
|
31
|
-
// TODO: This logic if flawed looking for \n
|
|
32
|
-
console.error(`***PARTIAL LINE***[${chunkStr}]`);
|
|
33
|
-
process.exit(1); // TODO: throw something not exit
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Used for pulling nested or flat values from the buildSpec. This allows
|
|
37
|
-
* the build spec to look like this:
|
|
38
|
-
* {
|
|
39
|
-
* gitName : 'myName',
|
|
40
|
-
* git : {
|
|
41
|
-
* name : 'myName',
|
|
42
|
-
* }
|
|
43
|
-
* }
|
|
44
|
-
* and either can be retrieved with a key of gitName or git.name.
|
|
45
|
-
*/
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const valueFromSpec = (key, spec = this.buildSpec) => {
|
|
49
|
-
if (!key.match(/\.+/)) {
|
|
50
|
-
return spec[key];
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const keys = key.split('.');
|
|
54
|
-
return valueFromSpec(keys[1], spec[keys[0]]);
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
const splitLines = chunkStr.split('\n');
|
|
58
|
-
const xfmLines = splitLines.map(line => {
|
|
59
|
-
let replaced = line;
|
|
60
|
-
|
|
61
|
-
for (const match of line.matchAll(this.regexp)) {
|
|
62
|
-
// eslint-disable-line no-restricted-syntax
|
|
63
|
-
const replaceWith = valueFromSpec(match[1]);
|
|
64
|
-
|
|
65
|
-
if (typeof replaceWith === 'undefined') {
|
|
66
|
-
// console.log( `Skipping unknown build spec property =>[${match[1]}]` )//XXX
|
|
67
|
-
continue;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
replaced = replaced.replace(match[0], replaceWith);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return replaced;
|
|
74
|
-
});
|
|
75
|
-
const xfmString = xfmLines.join('\n');
|
|
76
|
-
this.push(Buffer.from(xfmString));
|
|
77
|
-
done();
|
|
78
|
-
};
|
|
79
|
-
_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
|
-
|
|
90
|
-
module.exports = ToBuildSpec;
|
|
@@ -1,102 +0,0 @@
|
|
|
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
|
-
};
|
|
@@ -1,82 +0,0 @@
|
|
|
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
|
-
};
|
|
@@ -1,67 +0,0 @@
|
|
|
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
|
-
};
|