@strapi/generate-new
Version: 
Generate a new Strapi application.
194 lines (193 loc) • 7.19 kB
JavaScript
import { join } from "path";
import fse from "fs-extra";
import chalk from "chalk";
import execa from "execa";
import ora from "ora";
import _ from "lodash";
import stopProcess from "./utils/stop-process.mjs";
import { trackUsage, captureStderr } from "./utils/usage.mjs";
import mergeTemplate from "./utils/merge-template.mjs";
import tryGitInit from "./utils/git.mjs";
import packageJSON from "./resources/json/common/package.json.mjs";
import jsconfig from "./resources/json/js/jsconfig.json.mjs";
import adminTsconfig from "./resources/json/ts/tsconfig-admin.json.mjs";
import serverTsconfig from "./resources/json/ts/tsconfig-server.json.mjs";
import { generateDbEnvariables, createDatabaseConfig } from "./resources/templates/database.mjs";
import createEnvFile from "./resources/templates/env.mjs";
import { isStderrError } from "./types.mjs";
async function createProject(scope, { client, connection, dependencies }) {
  console.log(`Creating a new Strapi application at ${chalk.green(scope.rootPath)}.`);
  console.log("Creating files.");
  const { rootPath, useTypescript } = scope;
  const resources = join(__dirname, "resources");
  const language = useTypescript ? "ts" : "js";
  try {
    await fse.copy(join(resources, "files", language), rootPath);
    await fse.writeFile(join(rootPath, ".env"), createEnvFile());
    const copyDotFilesFromSubDirectory = (subDirectory) => {
      const files = fse.readdirSync(join(resources, "dot-files", subDirectory));
      return Promise.all(
        files.map((file) => {
          const src = join(resources, "dot-files", subDirectory, file);
          const dest = join(rootPath, `.${file}`);
          return fse.copy(src, dest);
        })
      );
    };
    copyDotFilesFromSubDirectory("common");
    if (!useTypescript) {
      copyDotFilesFromSubDirectory("js");
    }
    await trackUsage({ event: "didCopyProjectFiles", scope });
    await fse.writeJSON(
      join(rootPath, "package.json"),
      packageJSON({
        strapiDependencies: scope.strapiDependencies,
        additionalsDependencies: dependencies,
        strapiVersion: scope.strapiVersion,
        projectName: _.kebabCase(scope.name),
        uuid: scope.uuid,
        packageJsonStrapi: scope.packageJsonStrapi
      }),
      {
        spaces: 2
      }
    );
    await trackUsage({ event: "didWritePackageJSON", scope });
    if (useTypescript) {
      const filesMap = {
        "tsconfig-admin.json.js": "src/admin",
        "tsconfig-server.json.js": "."
      };
      for (const [fileName, path] of Object.entries(filesMap)) {
        const destPath = join(rootPath, path, "tsconfig.json");
        if (fileName === "tsconfig-admin.json.js") {
          await fse.writeJSON(destPath, adminTsconfig(), { spaces: 2 });
        }
        if (fileName === "tsconfig-server.json.js") {
          await fse.writeJSON(destPath, serverTsconfig(), { spaces: 2 });
        }
      }
    } else {
      const filesMap = { "jsconfig.json.js": "." };
      for (const [, path] of Object.entries(filesMap)) {
        const destPath = join(rootPath, path, "jsconfig.json");
        await fse.writeJSON(destPath, jsconfig(), { spaces: 2 });
      }
    }
    await fse.ensureDir(join(rootPath, "node_modules"));
    await fse.appendFile(join(rootPath, ".env"), generateDbEnvariables({ client, connection }));
    await fse.writeFile(
      join(rootPath, `config/database.${language}`),
      createDatabaseConfig({ useTypescript })
    );
    await trackUsage({ event: "didCopyConfigurationFiles", scope });
    const hasTemplate = Boolean(scope.template);
    if (hasTemplate) {
      try {
        await mergeTemplate(scope, rootPath);
      } catch (error) {
        if (error instanceof Error) {
          throw new Error(`⛔️ Template installation failed: ${error.message}`);
        }
        throw error;
      }
    }
  } catch (err) {
    await fse.remove(scope.rootPath);
    throw err;
  }
  await trackUsage({ event: "willInstallProjectDependencies", scope });
  const installPrefix = chalk.yellow("Installing dependencies:");
  const loader = ora(installPrefix).start();
  const logInstall = (chunk = "") => {
    loader.text = `${installPrefix} ${chunk.toString().split("\n").join(" ")}`;
  };
  try {
    if (scope.installDependencies !== false) {
      const runner = runInstall(scope);
      runner.stdout?.on("data", logInstall);
      runner.stderr?.on("data", logInstall);
      await runner;
    }
    loader.stop();
    console.log(`Dependencies installed ${chalk.green("successfully")}.`);
    await trackUsage({ event: "didInstallProjectDependencies", scope });
  } catch (error) {
    const stderr = isStderrError(error) ? error.stderr : "";
    loader.stop();
    await trackUsage({
      event: "didNotInstallProjectDependencies",
      scope,
      error: stderr.slice(-1024)
    });
    console.error(`${chalk.red("Error")} while installing dependencies:`);
    console.error(stderr);
    await captureStderr("didNotInstallProjectDependencies", error);
    console.log(chalk.black.bgWhite(" Keep trying!"));
    console.log();
    console.log(
      chalk.bold(
        "Oh, it seems that you encountered errors while installing dependencies in your project."
      )
    );
    console.log(`Don't give up, your project was created correctly.`);
    console.log(
      `Fix the issues mentioned in the installation errors and try to run the following command:`
    );
    console.log();
    console.log(
      `cd ${chalk.green(rootPath)} && ${chalk.cyan(scope.useYarn ? "yarn" : "npm")} install`
    );
    console.log();
    stopProcess();
  }
  await trackUsage({ event: "didCreateProject", scope });
  if (await tryGitInit(rootPath)) {
    console.log("Initialized a git repository.");
    console.log();
  }
  console.log();
  console.log(`Your application was created at ${chalk.green(rootPath)}.
`);
  const cmd = chalk.cyan(scope.useYarn ? "yarn" : "npm run");
  console.log("Available commands in your project:");
  console.log();
  console.log(`  ${cmd} develop`);
  console.log(
    "  Start Strapi in watch mode. (Changes in Strapi project files will trigger a server restart)"
  );
  console.log();
  console.log(`  ${cmd} start`);
  console.log("  Start Strapi without watch mode.");
  console.log();
  console.log(`  ${cmd} build`);
  console.log("  Build Strapi admin panel.");
  console.log();
  console.log(`  ${cmd} deploy`);
  console.log("  Deploy Strapi project.");
  console.log();
  console.log(`  ${cmd} strapi`);
  console.log(`  Display all available commands.`);
  console.log();
  console.log("You can start by doing:");
  console.log();
  console.log(`  ${chalk.cyan("cd")} ${rootPath}`);
  console.log(`  ${cmd} develop`);
  console.log();
}
const installArguments = ["install", "--production", "--no-optional"];
function runInstall({ rootPath, useYarn }) {
  if (useYarn) {
    installArguments.push("--network-timeout 1000000");
    return execa("yarnpkg", installArguments, {
      cwd: rootPath,
      stdin: "ignore"
    });
  }
  return execa("npm", installArguments, { cwd: rootPath, stdin: "ignore" });
}
export {
  createProject as default
};
//# sourceMappingURL=create-project.mjs.map