Skip to content

Commit

Permalink
feat(CLI): Script to create a basic typescript boilerplate with no bu…
Browse files Browse the repository at this point in the history
…ild configuration
  • Loading branch information
emyann committed Jul 21, 2017
1 parent 6d9607d commit 39f9c07
Show file tree
Hide file tree
Showing 2 changed files with 212 additions and 11 deletions.
221 changes: 210 additions & 11 deletions packages/cli/createTsLib.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,222 @@
'use strict';
"use strict";

const validateProjectName = require('validate-npm-package-name');
const chalk = require('chalk');
const commander = require('commander');
const path = require('path');
const validateProjectName = require("validate-npm-package-name");
const chalk = require("chalk");
const semver = require("semver");
const spawn = require('cross-spawn');
const commander = require("commander");
const fs = require("fs-extra");
const path = require("path");

const packageJson = require('./package.json');
const packageJson = require("./package.json");

let projectName;

const program = new commander.Command(packageJson.name)
.version(packageJson.version)
.arguments('<project-directory>')
.usage(`${chalk.green('<project-directory>')}`)
.arguments("<project-directory>")
.usage(`${chalk.green("<project-directory>")}`)
.action(name => {
projectName = name;
})
.on('--help', () => {
console.log(` Only ${chalk.green('<project-directory>')} is required.`);
.on("--help", () => {
console.log(` Only ${chalk.green("<project-directory>")} is required.`);
console.log();
})
.parse(process.argv);
.parse(process.argv);

if (typeof projectName === "undefined") {
console.error("Please specify the project directory:");
console.log(
` ${chalk.cyan(program.name())} ${chalk.green("<project-directory>")}`
);
console.log();
console.log("For example:");
console.log(
` ${chalk.cyan(program.name())} ${chalk.green("my-typescript-lib")}`
);
console.log();
console.log(
`Run ${chalk.cyan(`${program.name()} --help`)} to see all options.`
);
process.exit(1);
}

createApp(projectName);

function createApp(name) {
const root = path.resolve(name);
const appName = path.basename(root);

checkAppName(appName);
fs.ensureDirSync(name);
if (!isSafeToCreateProjectIn(root, name)) {
process.exit(1);
}

console.log(`Creating a new TypeScript library in ${chalk.green(root)}.`);
console.log();

const originalDirectory = process.cwd();
process.chdir(root);

if (!semver.satisfies(process.version, ">=6.0.0")) {
console.log(
chalk.yellow(
`You are using Node ${process.version} so the project will be bootstrapped with an old unsupported version of tools.\n\n` +
`Please update to Node 6 or higher for a better, fully supported experience.\n`
)
);
}

const npmInfo = checkNpmVersion();
if (!npmInfo.hasMinNpm) {
if (npmInfo.npmVersion) {
console.log(
chalk.yellow(
`You are using npm ${npmInfo.npmVersion} so the project will be boostrapped with an old unsupported version of tools.\n\n` +
`Please update to npm 3 or higher for a better, fully supported experience.\n`
)
);
}
}
run(root, appName, originalDirectory);
}

function run(root, appName, originalDirectory) {
console.log("debug creating library ", root, appName, originalDirectory);
const templatePath = path.resolve(__dirname, "template");
if (fs.existsSync(templatePath)) {
fs.copySync(templatePath, root);
let packageJsonPath = path.join(root, "package.json");
let packageJson = require(packageJsonPath);
packageJson.name = appName;
packageJson.version = "0.0.1";

fs.writeFileSync(
packageJsonPath,
JSON.stringify(packageJson, null, 2)
);
console.log('Installing packages. This might take a couple of minutes.');
return install();
} else {
console.error(
`Could not locate supplied template: ${chalk.green(templatePath)}`
);
return;
}
}

function install() {
return new Promise((resolve, reject) => {
let command;
let args;

command = 'npm';
args = [
'install',
'--save',
'--save-exact',
'--loglevel',
'error',
];

const child = spawn(command, args, { stdio: 'inherit' });
child.on('close', code => {
if (code !== 0) {
reject({
command: `${command} ${args.join(' ')}`,
});
return;
}
resolve();
});
});
}

function getInstallPackage(version) {
let packageToInstall = "react-scripts";
const validSemver = semver.valid(version);
if (validSemver) {
packageToInstall += `@${validSemver}`;
} else if (version) {
// for tar.gz or alternative paths
packageToInstall = version;
}
return packageToInstall;
}

function checkAppName(appName) {
const validationResult = validateProjectName(appName);
if (!validationResult.validForNewPackages) {
console.error(
`Could not create a project called ${chalk.red(
`"${appName}"`
)} because of npm naming restrictions:`
);
printValidationResults(validationResult.errors);
printValidationResults(validationResult.warnings);
process.exit(1);
}
}

function printValidationResults(results) {
if (typeof results !== "undefined") {
results.forEach(error => {
console.error(chalk.red(` * ${error}`));
});
}
}

function isSafeToCreateProjectIn(root, name) {
const validFiles = [
".DS_Store",
"Thumbs.db",
".git",
".gitignore",
".idea",
"README.md",
"LICENSE",
"web.iml",
".hg",
".hgignore",
".hgcheck"
];
console.log();

const conflicts = fs
.readdirSync(root)
.filter(file => !validFiles.includes(file));
if (conflicts.length < 1) {
return true;
}

console.log(
`The directory ${chalk.green(name)} contains files that could conflict:`
);
console.log();
for (const file of conflicts) {
console.log(` ${file}`);
}
console.log();
console.log(
"Either try using a new directory name, or remove the files listed above."
);

return false;
}

function checkNpmVersion() {
let hasMinNpm = false;
let npmVersion = null;
try {
npmVersion = execSync("npm --version").toString().trim();
hasMinNpm = semver.gte(npmVersion, "3.0.0");
} catch (err) {
// ignore
}
return {
hasMinNpm: hasMinNpm,
npmVersion: npmVersion
};
}
2 changes: 2 additions & 0 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
"dependencies": {
"chalk": "^2.0.1",
"commander": "^2.11.0",
"cross-spawn": "^5.1.0",
"fs-extra": "^4.0.0",
"semver": "^5.3.0",
"validate-npm-package-name": "^3.0.0"
}
Expand Down

0 comments on commit 39f9c07

Please sign in to comment.