diff --git a/.gitignore b/.gitignore index e37f118..d1b9d85 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .env +.vscode node_modules mydir myadmin diff --git a/commands/create-project-api.js b/commands/create-project-api.js index f1b6f19..a47c8b6 100644 --- a/commands/create-project-api.js +++ b/commands/create-project-api.js @@ -1,4 +1,4 @@ -import { mkdir, writeFile } from "fs/promises"; +import { mkdir, writeFile, readFile } from "fs/promises"; import { parse, stringify } from "envfile"; import simpleGit from "simple-git"; import wget from "../utils/wget.js"; @@ -68,11 +68,17 @@ async function getFileFromCore(fileName) { /** * @summary update dotenv file to point to local mongo * @param {String} envData - file extracted from the reaction repo + * @param {Object} options - Any options for project creation * @returns {String} updated env file */ -function updateEnv(envData) { +function updateEnv(envData, options = {}) { const env = parse(envData); env.MONGO_URL = "mongodb://localhost:27017/reaction"; + + if (options.populate) { + env.LOAD_SAMPLE_DATA = true; + } + const updatedEnv = stringify(env); return updatedEnv; } @@ -80,9 +86,10 @@ function updateEnv(envData) { /** * @summary get files directory from core repo * @param {String} projectName - The name of the project we are creating + * @param {Object} options - Any options for project creation * @returns {Promise} True if success */ -async function getFilesFromCore(projectName) { +async function getFilesFromCore(projectName, options) { // get files directly from repo so it's always up-to-date const packageJson = await getFileFromCore("package.json"); const updatedPackageJson = await updatePackageJson(packageJson, projectName); @@ -104,28 +111,60 @@ async function getFilesFromCore(projectName) { await writeFile(`${projectName}/.nvmrc`, nvmrc); const dotenv = await getFileFromCore(".env.example"); - const updatedDotEnv = updateEnv(dotenv); + const updatedDotEnv = updateEnv(dotenv, options); await writeFile(`${projectName}/.env`, updatedDotEnv); return true; } - /** - * @summary git init the newly created project - * @param {String} projectName - The project to init - * @returns {Promise} true if success + * @summary create the git instance + * @param {String} projectName - The name of the directory to create + * @returns {Object} - the git instance */ -async function gitInitDirectory(projectName) { +function getGit(projectName) { const gitOptions = { baseDir: `${process.cwd()}/${projectName}`, binary: "git", maxConcurrentProcesses: 6 }; - const git = simpleGit(gitOptions); + return simpleGit(gitOptions); +} + +/** + * @summary git init the newly created project + * @param {String} projectName - The project to init + * @returns {Promise} true if success + */ +async function gitInitDirectory(projectName) { + try { + await getGit(projectName).init(); + } catch (error) { + Logger.error(error); + } +} + +/** + * @summary add the sample data plugin to project + * @param {String} projectName name of the project to create + * @param {String} pluginName The plugin name + * @returns {Promise} true for success + */ +async function addSampleDataPlugin(projectName) { try { - await git.init(); + await getGit(projectName).clone("git@github.com:reactioncommerce/api-plugin-sample-data.git", "./custom-packages/api-plugin-sample-data"); + + const pluginJsonPath = `${projectName}/plugins.json`; + const plugins = JSON.parse(await readFile(pluginJsonPath)); + plugins.sampleData = "./custom-packages/api-plugin-sample-data/index.js"; + + await writeFile(pluginJsonPath, JSON.stringify(plugins, null, "\t")); + + Logger.info("Added the sample data plugin successfully."); + return true; } catch (error) { Logger.error(error); + Logger.warn("Can't add the sample data plugin by error. Please add it manual."); + return false; } } @@ -148,10 +187,14 @@ export default async function createProjectApi(projectName, options) { await getFilesFromRepo("/templates/api-project/", projectName); // copy files directly from core that we want to be current - await getFilesFromCore(projectName); + await getFilesFromCore(projectName, options); // git init the new project await gitInitDirectory(projectName); + if (options.populate) { + await addSampleDataPlugin(projectName); + } + Logger.success("Project creation complete. Change to your directory and run `npm install`"); } diff --git a/index.js b/index.js index 1fd78f8..862966b 100755 --- a/index.js +++ b/index.js @@ -17,7 +17,7 @@ program .description("Create a new Open Commerce project of one of several types") .addArgument(new commander.Argument("", "which project type to create").choices(["api", "storefront", "admin", "demo"])) .argument("", "what to name the project") - // .option("--populate") + .option("--populate", "Install the sample data plugin") .option("--skip-meteor-install", "Skip Meteor install when creating admin project") .option("--dont-start-demo", "Don't auto start the demo project after creation") .action((type, name, options) => { diff --git a/tests/create-api-project.js b/tests/create-api-project.js index d63777b..70291cc 100644 --- a/tests/create-api-project.js +++ b/tests/create-api-project.js @@ -1,4 +1,5 @@ import { EOL } from "os"; +import fs from "fs/promises"; import { v4 as uuidv4 } from "uuid"; import rimraf from "rimraf"; import { expect } from "chai"; @@ -28,6 +29,21 @@ describe("The create-project-api command", () => { // eslint-disable-next-line jest/valid-expect expect(responseLines[1]).to.equal("reaction-cli: Project creation complete. Change to your directory and run `npm install`"); }).timeout(5000); + + it("should print the correct output when user run with --populate option", async () => { + const response = await execute("./index.js", ["create-project", "api", "myshop", "--populate"]); + const responseLines = response.trim().split(EOL); + // eslint-disable-next-line no-console + console.log(response); + expect(responseLines[1]).equal("reaction-cli: Added the sample data plugin successfully."); + expect(responseLines[2]).equal("reaction-cli: Project creation complete. Change to your directory and run `npm install`"); + + const pluginsData = JSON.parse(await fs.readFile("./myshop/plugins.json")); + expect(pluginsData.sampleData).eq("./custom-packages/api-plugin-sample-data/index.js"); + + const envData = await fs.readFile("./myshop/.env", { encoding: "utf-8" }); + expect(envData).contain("LOAD_SAMPLE_DATA=true"); + }).timeout(350000); }); afterEach(async () => {