Skip to content

Commit 63afc18

Browse files
committed
feat: add populate option when create api project
Signed-off-by: Brian Nguyen <vanpho02@gmail.com>
1 parent d054356 commit 63afc18

File tree

4 files changed

+73
-12
lines changed

4 files changed

+73
-12
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
.env
2+
.vscode
23
node_modules
34
mydir
45
myadmin

commands/create-project-api.js

Lines changed: 57 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { mkdir, writeFile } from "fs/promises";
1+
import { mkdir, writeFile, readFile } from "fs/promises";
22
import { parse, stringify } from "envfile";
33
import simpleGit from "simple-git";
44
import wget from "../utils/wget.js";
@@ -9,6 +9,20 @@ import Logger from "../utils/logger.js";
99

1010
const reactionRepoRoot = "https://raw.githubusercontent.com/reactioncommerce/reaction/trunk";
1111

12+
/**
13+
* @summary create the git instance
14+
* @param {String} projectName - The name of the directory to create
15+
* @returns {Object} - the git instance
16+
*/
17+
function getGitInstance(projectName) {
18+
const gitOptions = {
19+
baseDir: `${process.cwd()}/${projectName}`,
20+
binary: "git",
21+
maxConcurrentProcesses: 6
22+
};
23+
return simpleGit(gitOptions);
24+
}
25+
1226
/**
1327
* @summary create project directory
1428
* @param {String} projectName - The name of the directory to create
@@ -68,21 +82,28 @@ async function getFileFromCore(fileName) {
6882
/**
6983
* @summary update dotenv file to point to local mongo
7084
* @param {String} envData - file extracted from the reaction repo
85+
* @param {Object} options - Any options for project creation
7186
* @returns {String} updated env file
7287
*/
73-
function updateEnv(envData) {
88+
function updateEnv(envData, options = {}) {
7489
const env = parse(envData);
7590
env.MONGO_URL = "mongodb://localhost:27017/reaction";
91+
92+
if (options.populate) {
93+
env.LOAD_SAMPLE_DATA = true;
94+
}
95+
7696
const updatedEnv = stringify(env);
7797
return updatedEnv;
7898
}
7999

80100
/**
81101
* @summary get files directory from core repo
82102
* @param {String} projectName - The name of the project we are creating
103+
* @param {Object} options - Any options for project creation
83104
* @returns {Promise<Boolean>} True if success
84105
*/
85-
async function getFilesFromCore(projectName) {
106+
async function getFilesFromCore(projectName, options) {
86107
// get files directly from repo so it's always up-to-date
87108
const packageJson = await getFileFromCore("package.json");
88109
const updatedPackageJson = await updatePackageJson(packageJson, projectName);
@@ -104,7 +125,7 @@ async function getFilesFromCore(projectName) {
104125
await writeFile(`${projectName}/.nvmrc`, nvmrc);
105126

106127
const dotenv = await getFileFromCore(".env.example");
107-
const updatedDotEnv = updateEnv(dotenv);
128+
const updatedDotEnv = updateEnv(dotenv, options);
108129
await writeFile(`${projectName}/.env`, updatedDotEnv);
109130
return true;
110131
}
@@ -116,19 +137,40 @@ async function getFilesFromCore(projectName) {
116137
* @returns {Promise<Boolean>} true if success
117138
*/
118139
async function gitInitDirectory(projectName) {
119-
const gitOptions = {
120-
baseDir: `${process.cwd()}/${projectName}`,
121-
binary: "git",
122-
maxConcurrentProcesses: 6
123-
};
124-
const git = simpleGit(gitOptions);
140+
const git = getGitInstance(projectName);
125141
try {
126142
await git.init();
127143
} catch (error) {
128144
Logger.error(error);
129145
}
130146
}
131147

148+
/**
149+
* @summary add the sample data plugin to project
150+
* @param {String} projectName name of the project to create
151+
* @param {String} pluginName The plugin name
152+
* @returns {Promise<boolean>} true for success
153+
*/
154+
async function addSampleDataPlugin(projectName) {
155+
const git = getGitInstance(projectName);
156+
try {
157+
await git.clone("git@github.com:reactioncommerce/api-plugin-sample-data.git", "custom-packages/api-plugin-sample-data");
158+
159+
const pluginJsonPath = `${projectName}/plugins.json`;
160+
const plugins = JSON.parse(await readFile(pluginJsonPath));
161+
plugins.sampleData = "./custom-packages/api-plugin-sample-data/index.js";
162+
163+
await writeFile(pluginJsonPath, JSON.stringify(plugins, null, "\t"));
164+
165+
Logger.info("Added the sample data plugin successfully.");
166+
return true;
167+
} catch (error) {
168+
Logger.error(error);
169+
Logger.warn("Can't add the sample data plugin by error. Please add it manual.");
170+
return false;
171+
}
172+
}
173+
132174

133175
/**
134176
* @summary clones projects locally from repo
@@ -148,10 +190,14 @@ export default async function createProjectApi(projectName, options) {
148190
await getFilesFromRepo("/templates/api-project/", projectName);
149191

150192
// copy files directly from core that we want to be current
151-
await getFilesFromCore(projectName);
193+
await getFilesFromCore(projectName, options);
152194

153195
// git init the new project
154196
await gitInitDirectory(projectName);
155197

198+
if (options.populate) {
199+
await addSampleDataPlugin(projectName);
200+
}
201+
156202
Logger.success("Project creation complete. Change to your directory and run `npm install`");
157203
}

index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ program
1717
.description("Create a new Open Commerce project of one of several types")
1818
.addArgument(new commander.Argument("<type>", "which project type to create").choices(["api", "storefront", "admin", "demo"]))
1919
.argument("<name>", "what to name the project")
20-
// .option("--populate")
20+
.option("--populate", "Install the sample data plugin")
2121
.option("--skip-meteor-install", "Skip Meteor install when creating admin project")
2222
.option("--dont-start-demo", "Don't auto start the demo project after creation")
2323
.action((type, name, options) => {

tests/create-api-project.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { EOL } from "os";
2+
import fs from "fs/promises";
23
import { v4 as uuidv4 } from "uuid";
34
import rimraf from "rimraf";
45
import { expect } from "chai";
@@ -28,6 +29,19 @@ describe("The create-project-api command", () => {
2829
// eslint-disable-next-line jest/valid-expect
2930
expect(responseLines[1]).to.equal("reaction-cli: Project creation complete. Change to your directory and run `npm install`");
3031
}).timeout(5000);
32+
33+
it("should print the correct output when user run with --populate option", async () => {
34+
const response = await execute("./index.js", ["create-project", "api", "myshop", "--populate"]);
35+
const responseLines = response.trim().split(EOL);
36+
expect(responseLines[1]).equal("reaction-cli: Added the sample data plugin successfully.");
37+
expect(responseLines[2]).equal("reaction-cli: Project creation complete. Change to your directory and run `npm install`");
38+
39+
const pluginsData = JSON.parse(await fs.readFile("./myshop/plugins.json"));
40+
expect(pluginsData.sampleData).eq("./custom-packages/api-plugin-sample-data/index.js");
41+
42+
const envData = await fs.readFile("./myshop/.env", { encoding: "utf-8" });
43+
expect(envData).contain("LOAD_SAMPLE_DATA=true");
44+
}).timeout(350000);
3145
});
3246

3347
afterEach(async () => {

0 commit comments

Comments
 (0)