Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add populate option when create api project #91

Open
wants to merge 3 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.env
.vscode
node_modules
mydir
myadmin
Expand Down
67 changes: 55 additions & 12 deletions commands/create-project-api.js
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -68,21 +68,28 @@ 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;
}

/**
* @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<Boolean>} 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);
Expand All @@ -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<Boolean>} 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<Boolean>} 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<boolean>} true for success
*/
async function addSampleDataPlugin(projectName) {
try {
await git.init();
await getGit(projectName).clone("[email protected]: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;
}
}

Expand All @@ -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`");
}
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ program
.description("Create a new Open Commerce project of one of several types")
.addArgument(new commander.Argument("<type>", "which project type to create").choices(["api", "storefront", "admin", "demo"]))
.argument("<name>", "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) => {
Expand Down
16 changes: 16 additions & 0 deletions tests/create-api-project.js
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -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 () => {
Expand Down