UNPKG

@nomiclabs/buidler

Version:

Buidler is an extensible developer tool that helps smart contract developers increase productivity by reliably bringing together the tools they want.

310 lines 13 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result["default"] = mod; return result; }; Object.defineProperty(exports, "__esModule", { value: true }); const chalk_1 = __importDefault(require("chalk")); const fs_extra_1 = __importDefault(require("fs-extra")); const os_1 = __importDefault(require("os")); const path_1 = __importDefault(require("path")); const constants_1 = require("../constants"); const execution_mode_1 = require("../core/execution-mode"); const project_structure_1 = require("../core/project-structure"); const packageInfo_1 = require("../util/packageInfo"); const emoji_1 = require("./emoji"); const CREATE_SAMPLE_PROJECT_ACTION = "Create a sample project"; const CREATE_EMPTY_BUIDLER_CONFIG_ACTION = "Create an empty buidler.config.js"; const QUIT_ACTION = "Quit"; const SAMPLE_PROJECT_DEPENDENCIES = { "@nomiclabs/buidler-waffle": "^2.0.0", "ethereum-waffle": "^3.0.0", chai: "^4.2.0", "@nomiclabs/buidler-ethers": "^2.0.0", ethers: "^5.0.0", }; async function removeProjectDirIfPresent(projectRoot, dirName) { const dirPath = path_1.default.join(projectRoot, dirName); if (await fs_extra_1.default.pathExists(dirPath)) { await fs_extra_1.default.remove(dirPath); } } async function removeTempFilesIfPresent(projectRoot) { await removeProjectDirIfPresent(projectRoot, "cache"); await removeProjectDirIfPresent(projectRoot, "artifacts"); } function printAsciiLogo() { console.log(chalk_1.default.blue(`888 d8b 888 888`)); console.log(chalk_1.default.blue(`888 Y8P 888 888`)); console.log(chalk_1.default.blue("888 888 888")); console.log(chalk_1.default.blue("88888b. 888 888 888 .d88888 888 .d88b. 888d888")); console.log(chalk_1.default.blue('888 "88b 888 888 888 d88" 888 888 d8P Y8b 888P"')); console.log(chalk_1.default.blue("888 888 888 888 888 888 888 888 88888888 888")); console.log(chalk_1.default.blue("888 d88P Y88b 888 888 Y88b 888 888 Y8b. 888")); console.log(chalk_1.default.blue(`88888P" "Y88888 888 "Y88888 888 "Y8888 888`)); console.log(""); } async function printWelcomeMessage() { const packageJson = await packageInfo_1.getPackageJson(); console.log(chalk_1.default.cyan(`${emoji_1.emoji("👷 ")}Welcome to ${constants_1.BUIDLER_NAME} v${packageJson.version}${emoji_1.emoji(" 👷‍")}‍\n`)); } async function copySampleProject(projectRoot) { const packageRoot = await packageInfo_1.getPackageRoot(); await fs_extra_1.default.ensureDir(projectRoot); await fs_extra_1.default.copy(path_1.default.join(packageRoot, "sample-project"), projectRoot); // This is just in case we have been using the sample project for dev/testing await removeTempFilesIfPresent(projectRoot); await fs_extra_1.default.remove(path_1.default.join(projectRoot, "LICENSE.md")); } async function addGitIgnore(projectRoot) { const gitIgnorePath = path_1.default.join(projectRoot, ".gitignore"); let content = await project_structure_1.getRecommendedGitIgnore(); if (await fs_extra_1.default.pathExists(gitIgnorePath)) { const existingContent = await fs_extra_1.default.readFile(gitIgnorePath, "utf-8"); content = `${existingContent} ${content}`; } await fs_extra_1.default.writeFile(gitIgnorePath, content); } async function addGitAttributes(projectRoot) { const gitAttributesPath = path_1.default.join(projectRoot, ".gitattributes"); let content = "*.sol linguist-language=Solidity"; if (await fs_extra_1.default.pathExists(gitAttributesPath)) { const existingContent = await fs_extra_1.default.readFile(gitAttributesPath, "utf-8"); if (existingContent.includes(content)) { return; } content = `${existingContent} ${content}`; } await fs_extra_1.default.writeFile(gitAttributesPath, content); } function printSuggestedCommands() { const npx = execution_mode_1.getExecutionMode() === execution_mode_1.ExecutionMode.EXECUTION_MODE_GLOBAL_INSTALLATION ? "" : "npx "; console.log(`Try running some of the following tasks:`); console.log(` ${npx}buidler accounts`); console.log(` ${npx}buidler compile`); console.log(` ${npx}buidler test`); console.log(` ${npx}buidler node`); console.log(` node scripts/sample-script.js`); console.log(` ${npx}buidler help`); } async function printRecommendedDepsInstallationInstructions() { console.log(`You need to install these dependencies to run the sample project:`); const cmd = await getRecommendedDependenciesInstallationCommand(); console.log(` ${cmd.join(" ")}`); } async function writeEmptyBuidlerConfig() { return fs_extra_1.default.writeFile("buidler.config.js", "module.exports = {};\n", "utf-8"); } async function getAction() { const { default: enquirer } = await Promise.resolve().then(() => __importStar(require("enquirer"))); try { const actionResponse = await enquirer.prompt([ { name: "action", type: "select", message: "What do you want to do?", initial: 0, choices: [ { name: CREATE_SAMPLE_PROJECT_ACTION, message: CREATE_SAMPLE_PROJECT_ACTION, value: CREATE_SAMPLE_PROJECT_ACTION, }, { name: CREATE_EMPTY_BUIDLER_CONFIG_ACTION, message: CREATE_EMPTY_BUIDLER_CONFIG_ACTION, value: CREATE_EMPTY_BUIDLER_CONFIG_ACTION, }, { name: QUIT_ACTION, message: QUIT_ACTION, value: QUIT_ACTION }, ], }, ]); return actionResponse.action; } catch (e) { if (e === "") { return QUIT_ACTION; } // tslint:disable-next-line only-buidler-error throw e; } } async function createProject() { const { default: enquirer } = await Promise.resolve().then(() => __importStar(require("enquirer"))); printAsciiLogo(); await printWelcomeMessage(); const action = await getAction(); if (action === QUIT_ACTION) { return; } if (action === CREATE_EMPTY_BUIDLER_CONFIG_ACTION) { await writeEmptyBuidlerConfig(); console.log(`${emoji_1.emoji("✨ ")}${chalk_1.default.cyan(`Config file created`)}${emoji_1.emoji(" ✨")}`); return; } let responses; try { responses = await enquirer.prompt([ { name: "projectRoot", type: "input", initial: process.cwd(), message: "Buidler project root:", }, createConfirmationPrompt("shouldAddGitIgnore", "Do you want to add a .gitignore?"), createConfirmationPrompt("shouldAddGitAttributes", "Do you want to add a .gitattributes to enable Soldity highlighting on GitHub?"), ]); } catch (e) { if (e === "") { return; } // tslint:disable-next-line only-buidler-error throw e; } const { projectRoot, shouldAddGitIgnore, shouldAddGitAttributes } = responses; await copySampleProject(projectRoot); if (shouldAddGitIgnore) { await addGitIgnore(projectRoot); } if (shouldAddGitAttributes) { await addGitAttributes(projectRoot); } let shouldShowInstallationInstructions = true; if (await canInstallRecommendedDeps()) { const recommendedDeps = Object.keys(SAMPLE_PROJECT_DEPENDENCIES); const installedRecommendedDeps = recommendedDeps.filter(isInstalled); if (installedRecommendedDeps.length === recommendedDeps.length) { shouldShowInstallationInstructions = false; } else if (installedRecommendedDeps.length === 0) { const shouldInstall = await confirmRecommendedDepsInstallation(); if (shouldInstall) { const installed = await installRecommendedDependencies(); if (!installed) { console.warn(chalk_1.default.red("Failed to install the sample project's dependencies")); } shouldShowInstallationInstructions = !installed; } } } if (shouldShowInstallationInstructions) { console.log(``); await printRecommendedDepsInstallationInstructions(); } console.log(`\n${emoji_1.emoji("✨ ")}${chalk_1.default.cyan("Project created")}${emoji_1.emoji(" ✨")}`); console.log(``); printSuggestedCommands(); } exports.createProject = createProject; function createConfirmationPrompt(name, message) { return { type: "confirm", name, message, initial: "y", default: "(Y/n)", isTrue(input) { if (typeof input === "string") { return input.toLowerCase() === "y"; } return input; }, isFalse(input) { if (typeof input === "string") { return input.toLowerCase() === "n"; } return input; }, format() { const that = this; const value = that.value === true ? "y" : "n"; if (that.state.submitted === true) { return that.styles.submitted(value); } return value; }, }; } async function canInstallRecommendedDeps() { return ((await fs_extra_1.default.pathExists("package.json")) && (execution_mode_1.getExecutionMode() === execution_mode_1.ExecutionMode.EXECUTION_MODE_LOCAL_INSTALLATION || execution_mode_1.getExecutionMode() === execution_mode_1.ExecutionMode.EXECUTION_MODE_LINKED) && // TODO: Figure out why this doesn't work on Win os_1.default.type() !== "Windows_NT"); } function isInstalled(dep) { const packageJson = fs_extra_1.default.readJSONSync("package.json"); const allDependencies = Object.assign(Object.assign(Object.assign({}, packageJson.dependencies), packageJson.devDependencies), packageJson.optionalDependencies); return dep in allDependencies; } async function isYarnProject() { return fs_extra_1.default.pathExists("yarn.lock"); } async function installRecommendedDependencies() { console.log(""); const installCmd = await getRecommendedDependenciesInstallationCommand(); return installDependencies(installCmd[0], installCmd.slice(1)); } async function confirmRecommendedDepsInstallation() { const { default: enquirer } = await Promise.resolve().then(() => __importStar(require("enquirer"))); let responses; const packageManager = (await isYarnProject()) ? "yarn" : "npm"; try { responses = await enquirer.prompt([ createConfirmationPrompt("shouldInstallPlugin", `Do you want to install the sample project's dependencies with ${packageManager} (${Object.keys(SAMPLE_PROJECT_DEPENDENCIES).join(" ")})?`), ]); } catch (e) { if (e === "") { return false; } // tslint:disable-next-line only-buidler-error throw e; } return responses.shouldInstallPlugin === true; } async function installDependencies(packageManager, args) { const { spawn } = await Promise.resolve().then(() => __importStar(require("child_process"))); console.log(`${packageManager} ${args.join(" ")}`); const childProcess = spawn(packageManager, args, { stdio: "inherit", }); return new Promise((resolve, reject) => { childProcess.once("close", (status) => { childProcess.removeAllListeners("error"); if (status === 0) { resolve(true); return; } reject(false); }); childProcess.once("error", (status) => { childProcess.removeAllListeners("close"); reject(false); }); }); } async function getRecommendedDependenciesInstallationCommand() { const isGlobal = execution_mode_1.getExecutionMode() === execution_mode_1.ExecutionMode.EXECUTION_MODE_GLOBAL_INSTALLATION; const deps = Object.entries(SAMPLE_PROJECT_DEPENDENCIES).map(([name, version]) => `${name}@${version}`); if (!isGlobal && (await isYarnProject())) { return ["yarn", "add", "--dev", ...deps]; } const npmInstall = ["npm", "install"]; if (isGlobal) { npmInstall.push("--global"); } return [...npmInstall, "--save-dev", ...deps]; } //# sourceMappingURL=project-creation.js.map