| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- import { exec as shell_exec } from 'child_process';
- import fs from 'fs';
- import path from 'path';
- import util from 'util';
- const MAX_BUFFER = 10 * Math.pow(2, 20);
- export function exec(command: string, stdout?: ((...args) => void) | NodeJS.WriteStream, stderr?: ((...args) => void) | NodeJS.WriteStream) {
- return new Promise<string>((resolve, reject) => {
- try {
- let stdoutbuf = '';
- let stderrbuf = '';
- // EXEC CHILD PROCESS
- const p = shell_exec(command, { maxBuffer: MAX_BUFFER }, (err, out) => {
- if (err) return reject(err);
- if (stdoutbuf.length > 0 && typeof stdout === 'function') stdout(stdoutbuf);
- if (stderrbuf.length > 0 && typeof stderr === 'function') stderr(stderrbuf);
- resolve(out);
- });
- // PIPE STDOUT
- if (typeof stdout === 'function') {
- p.stdout.on('data', chunk => {
- stdoutbuf += chunk;
- let i = -1;
- while ((i = stdoutbuf.indexOf('\n')) >= 0) {
- const line = stdoutbuf.substring(0, i);
- stdoutbuf = stdoutbuf.substring(i + 1);
- if (typeof stdout === 'function') {
- stdout(line);
- }
- }
- });
- } else if (typeof stdout !== 'undefined') {
- p.stdout.pipe(stdout);
- }
- // PIPE STDERR
- if (typeof stderr === 'function') {
- p.stderr.on('data', chunk => {
- stderrbuf += chunk;
- let i = -1;
- while ((i = stderrbuf.indexOf('\n')) >= 0) {
- const line = stderrbuf.substring(0, i);
- stderrbuf = stderrbuf.substring(i + 1);
- if (typeof stderr === 'function') {
- stderr(line);
- }
- }
- });
- } else if (typeof stderr !== 'undefined') {
- p.stderr.pipe(stderr);
- }
- } catch (err) {
- reject(err);
- }
- });
- }
- const cli = {
- blue: v => `\x1b[34m${v}\x1b[0m`,
- green: v => `\x1b[32m${v}\x1b[0m`,
- yellow: v => `\x1b[33m${v}\x1b[0m`,
- red: v => `\x1b[31m${v}\x1b[0m`
- };
- async function readFile(path: string, encoding: BufferEncoding = 'utf8'): Promise<string> {
- return new Promise<string>((resolve, reject) => {
- fs.readFile(path, { encoding }, (err, data) => {
- if (err) return reject(err);
- try {
- resolve(data.toString());
- } catch (e) {
- reject(e);
- }
- });
- });
- }
- async function readJsonFile<T>(path: string, encoding: BufferEncoding = 'utf8'): Promise<T> {
- return new Promise<T>(async (resolve, reject) => {
- try {
- resolve(JSON.parse(await readFile(path, encoding)) as T);
- } catch (e) {
- reject(e);
- }
- });
- }
- (async () => {
- try {
- const projectRootDir = path.resolve(process.cwd());
- if (!fs.existsSync(path.resolve(projectRootDir, 'package.json'))) {
- console.log(cli.blue('[INFO]'), 'Not an NPM project yet - initializing...');
- await exec('npm init -y', process.stdout, process.stderr);
- }
- const cloneDir = path.resolve(projectRootDir, '.clone');
- if (fs.existsSync(cloneDir)) {
- console.log(cli.blue('[WARNING]'), `There's an old .clone directory. Removing first...`);
- await util.promisify(fs.rm)(cloneDir, { force: true, recursive: true });
- }
- console.log(cli.blue('[INFO]'), 'Cloning boilerplate repository (via SSH)...');
- await exec(`git clone ssh://git@bitbucket.siriusonline.de:7999/tsc/express-starter.git "${cloneDir}"`, process.stdout, process.stderr);
- let pkgJson = await readJsonFile<any>(path.resolve(cloneDir, 'package.json'));
- console.log(cli.blue('[INFO]'), 'Installing module dependencies...');
- let dependencies = Object.keys(pkgJson.dependencies).join('" "');
- await exec(`npm install "${dependencies}"`, process.stdout, process.stderr);
- dependencies = Object.keys(pkgJson.devDependencies).join('" "');
- await exec(`npm install --save-dev "${dependencies}"`, process.stdout, process.stderr);
- console.log(cli.blue('[INFO]'), 'Copying project files...');
- const copyFiles = ['.env', '.gitignore', '.prettierrc.js', 'tsconfig.json', '.vscode/settings.json', 'src', 'public', 'private'];
- for (const cpFile of copyFiles) {
- const sourceFile = path.resolve(cloneDir, cpFile);
- const targetFile = path.resolve(projectRootDir, cpFile);
- const targetDir = path.dirname(targetFile);
- if (!fs.existsSync(targetDir)) {
- await util.promisify(fs.mkdir)(targetDir, { recursive: true, mode: 0o777 });
- }
- const stat = await util.promisify(fs.stat)(sourceFile);
- if (stat.isFile()) {
- await util.promisify(fs.copyFile)(sourceFile, targetFile);
- } else {
- await exec(`cp -r "${sourceFile}" "${targetFile}"`);
- }
- }
- console.log(cli.blue('[INFO]'), 'Creating startup script');
- pkgJson = await readJsonFile<any>(path.resolve(projectRootDir, 'package.json'));
- pkgJson.scripts = {
- ...pkgJson.scripts,
- build: 'tsc -b',
- start: 'npm run build && node dist/index.js'
- };
- await util.promisify(fs.writeFile)(path.resolve(projectRootDir, 'package.json'), JSON.stringify(pkgJson, null, 2));
- console.log(cli.blue('[INFO]'), 'Cleanup: Removing .clone directory...');
- await util.promisify(fs.rm)(cloneDir, { force: true, recursive: true });
- console.log();
- console.log(cli.green('[SUCCESS] You can now start your express server with `npm start`'));
- process.exit(0);
- } catch (e) {
- console.error(e);
- process.exit(1);
- }
- })();
|