secret-polar-reworks
Version:
Polar is a development environment to compile, deploy, test, run scrt contracts on different networks.
275 lines (226 loc) • 7.79 kB
text/typescript
/* eslint-disable @typescript-eslint/no-this-alias */
import chalk from "chalk";
import fsExtra from "fs-extra";
import os from "os";
import path from "path";
import { POLAR_NAME } from "../../lib/contants";
import { PolarError } from "../core/errors";
import { ERRORS } from "../core/errors-list";
import { ExecutionMode, getExecutionMode } from "../core/execution-mode";
import { getPackageJson, getPackageRoot } from "../util/packageInfo";
import { initialize } from "./initialize-template";
const SAMPLE_PROJECT_DEPENDENCIES = [
"chai"
];
export async function printWelcomeMessage (): Promise<void> {
const packageJson = await getPackageJson();
console.log(
chalk.cyan(`★ Welcome to ${POLAR_NAME} v${packageJson.version}`));
}
function copySampleProject (projectName: string): void {
const packageRoot = getPackageRoot();
const sampleProjDir = path.join(packageRoot, "sample-project");
const currDir = process.cwd();
const projectPath = path.join(currDir, projectName);
console.log(chalk.greenBright("Initializing new project in " + projectPath + "."));
fsExtra.copySync(sampleProjDir, projectPath, {
// User doesn't choose the directory so overwrite should be avoided
overwrite: false,
filter: (src: string, dest: string) => {
const relPath = path.relative(process.cwd(), dest);
if (relPath === '') {
return true;
}
if (path.basename(dest) === ".gitkeep") {
return false;
}
if (fsExtra.pathExistsSync(dest)) {
throw new PolarError(ERRORS.GENERAL.INIT_INSIDE_PROJECT, {
clashingFile: relPath
});
}
return true;
}
});
}
export function printSuggestedCommands (projectName: string): void {
const currDir = process.cwd();
const projectPath = path.join(currDir, projectName);
console.log(`Success! Created project at ${chalk.greenBright(projectPath)}.`);
// TODO: console.log(`Inside that directory, you can run several commands:`);
// list commands and respective description
console.log(`Begin by typing:`);
console.log(` cd ${projectName}`);
console.log(` ${POLAR_NAME} help`);
console.log(` ${POLAR_NAME} compile`);
}
async function printPluginInstallationInstructions (): Promise<void> {
console.log(
`You need to install these dependencies to run the sample project:`
);
const cmd = await npmInstallCmd();
console.log(` ${cmd.join(" ")}`);
}
// eslint-disable-next-line
export async function createProject (
projectName: string, templateName?: string, destination?: string
): Promise<any> { // eslint-disable-line @typescript-eslint/no-explicit-any
if (templateName !== undefined) {
const currDir = process.cwd();
const projectPath = destination ?? path.join(currDir, projectName);
await initialize({
force: false,
projectName: projectName,
templateName: templateName,
destination: projectPath
});
return;
}
await printWelcomeMessage();
copySampleProject(projectName);
let shouldShowInstallationInstructions = true;
if (await canInstallPlugin()) {
const installedRecommendedDeps = SAMPLE_PROJECT_DEPENDENCIES.filter(
isInstalled
);
if (
installedRecommendedDeps.length === SAMPLE_PROJECT_DEPENDENCIES.length
) {
shouldShowInstallationInstructions = false;
} else if (installedRecommendedDeps.length === 0) {
const shouldInstall = await confirmPluginInstallation();
if (shouldInstall) {
const installed = await installRecommendedDependencies();
if (!installed) {
console.warn(
chalk.red("Failed to install the sample project's dependencies")
);
}
shouldShowInstallationInstructions = !installed;
}
}
}
console.log("\n★", chalk.cyan("Project created"), "★\n");
if (shouldShowInstallationInstructions) {
await printPluginInstallationInstructions();
console.log(``);
}
printSuggestedCommands(projectName);
}
export function createConfirmationPrompt (name: string, message: string): any { // eslint-disable-line @typescript-eslint/no-explicit-any
return {
type: "confirm",
name,
message,
initial: "y",
default: "(Y/n)",
isTrue (input: string | boolean) {
if (typeof input === "string") {
return input.toLowerCase() === "y";
}
return input;
},
isFalse (input: string | boolean) {
if (typeof input === "string") {
return input.toLowerCase() === "n";
}
return input;
},
format (): string {
const that = this; // eslint-disable-line @typescript-eslint/no-explicit-any
const value = that.value === true ? "y" : "n";
if (that.state.submitted === true) {
return that.styles.submitted(value);
}
return value;
}
};
}
async function canInstallPlugin (): Promise<boolean> {
return (
(await fsExtra.pathExists("package.json")) &&
(getExecutionMode() === ExecutionMode.EXECUTION_MODE_LOCAL_INSTALLATION ||
getExecutionMode() === ExecutionMode.EXECUTION_MODE_LINKED) &&
// TODO: Figure out why this doesn't work on Win
os.type() !== "Windows_NT"
);
}
function isInstalled (dep: string): boolean {
const packageJson = fsExtra.readJSONSync("package.json");
const allDependencies = {
...packageJson.dependencies,
...packageJson.devDependencies,
...packageJson.optionalDependencies
};
return dep in allDependencies;
}
function isYarnProject (): boolean {
return fsExtra.pathExistsSync("yarn.lock");
}
async function installRecommendedDependencies (): Promise<boolean> {
console.log("");
const installCmd = await npmInstallCmd();
return await installDependencies(installCmd[0], installCmd.slice(1));
}
async function confirmPluginInstallation (): Promise<boolean> {
const { default: enquirer } = await import("enquirer");
let responses: {
shouldInstallPlugin: boolean
};
const packageManager = isYarnProject() ? "yarn" : "npm";
try {
responses = await enquirer.prompt([
createConfirmationPrompt(
"shouldInstallPlugin",
`Do you want to install the sample project's dependencies with ${packageManager} (${SAMPLE_PROJECT_DEPENDENCIES.join(
" "
)})?`
)
]);
} catch (e) {
if (e === "") {
return false;
}
throw e;
}
return responses.shouldInstallPlugin;
}
export async function installDependencies (
packageManager: string,
args: string[],
location?: string
): Promise<boolean> {
const { spawn } = await import("child_process");
console.log(`${packageManager} ${args.join(" ")}`);
const childProcess = spawn(packageManager, args, {
stdio: "inherit" as any, // eslint-disable-line @typescript-eslint/no-explicit-any
cwd: location
});
return await new Promise<boolean>((resolve, reject) => {
childProcess.once("close", (status) => {
childProcess.removeAllListeners("error");
if (status === 0) {
resolve(true);
return;
}
reject(new Error("script process returned not 0 status"));
});
childProcess.once("error", (status) => {
childProcess.removeAllListeners("close");
reject(new Error("script process returned not 0 status"));
});
});
}
async function npmInstallCmd (): Promise<string[]> {
const isGlobal =
getExecutionMode() === ExecutionMode.EXECUTION_MODE_GLOBAL_INSTALLATION;
if (isYarnProject()) {
const cmd = ["yarn"];
if (isGlobal) { cmd.push("global"); }
cmd.push("add", "--dev", ...SAMPLE_PROJECT_DEPENDENCIES);
return cmd;
}
const npmInstall = ["npm", "install"];
if (isGlobal) { npmInstall.push("--global"); }
return [...npmInstall, "--save-dev", ...SAMPLE_PROJECT_DEPENDENCIES];
}