Skip to content

Commit

Permalink
Merge pull request #133 from aditya-padhi-kbl/trunk
Browse files Browse the repository at this point in the history
add ability to run tests and linting in new projects
  • Loading branch information
brent-hoover authored Oct 26, 2022
2 parents 073d83b + 61cc0f3 commit 07e5deb
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 12 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ mydir
myadmin
mystore
myapi
.idea
42 changes: 31 additions & 11 deletions commands/create-project-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import getFilesFromRepo from "../utils/getFilesFromRepo.js";
import pathExists from "../utils/pathExists.js";
import Logger from "../utils/logger.js";
import getFileFromCore, { reactionRoot } from "../utils/getFileFromCore.js";
import copyTests from "../utils/copyTests.js";

/**
* @summary create project directory
Expand All @@ -13,19 +14,20 @@ import getFileFromCore, { reactionRoot } from "../utils/getFileFromCore.js";
*/
async function makeProject(projectName) {
await mkdir(projectName);
// create utils directory
await mkdir(`${projectName}/utils`);
// create src, custom-packages & tests directory
await mkdir(`${projectName}/src`);
await mkdir(`${projectName}/custom-packages`);
await mkdir(`${projectName}/tests`);
}

/**
* @summary fetch the right nodemon from root
* @return {Promise<string>} - the nodemon package.json line
*/
async function getNodeMonVersionFromRoot() {
async function getDevDependenciesFromRoot() {
const rootPackage = await getFileFromCore("package.json", reactionRoot);
const packageData = JSON.parse(rootPackage);
return packageData.devDependencies.nodemon;
return packageData.devDependencies;
}


Expand All @@ -41,7 +43,7 @@ async function updatePackageJson(packageJson, projectName) {
"start:dev": "npm run check-node-version && NODE_ENV=development NODE_OPTIONS='--experimental-modules --experimental-json-modules' nodemon ./index.js",
"inspect": "NODE_ENV=development node --experimental-modules --experimental-json-modules --inspect ./src/index.js",
"inspect-brk": "NODE_ENV=development node --experimental-modules --experimental-json-modules --inspect-brk ./src/index.js",
"check-node-version": "node ./utils/checkNodeVersion.cjs",
"check-node-version": "node ./src/checkNodeVersion.cjs",
"test": "jest --runInBand",
"lint": "eslint ."
};
Expand All @@ -59,7 +61,13 @@ async function updatePackageJson(packageJson, projectName) {
delete packageData.bugs;
packageData.main = "./index.js";
packageData.nodemonConfig.watch.push("custom-packages");
packageData.devDependencies.nodemon = await getNodeMonVersionFromRoot();
packageData.devDependencies = {
...packageData.devDependencies,
...(await getDevDependenciesFromRoot())
};

delete packageData?.devDependencies["graphql-schema-linter"];
delete packageData["graphql-schema-linter"];
return JSON.stringify(packageData, null, 2);
}

Expand All @@ -74,6 +82,14 @@ function updateEnv(envData) {
return stringify(env);
}

/**
* @summary update npmrc configuration
* @param {String} npmrcData - file extracted from the reaction repo
* @returns {string} update npmrc content
*/
function updateNpmrc(npmrcData) {
return npmrcData.indexOf("legacy-peer-deps") > -1 ? npmrcData : `${npmrcData}legacy-peer-deps=true\n`;
}
/**
* @summary get files directory from core repo
* @param {String} projectName - The name of the project we are creating
Expand All @@ -84,25 +100,29 @@ async function getFilesFromCore(projectName) {
const packageJson = await getFileFromCore("package.json");
const updatedPackageJson = await updatePackageJson(packageJson, projectName);
await writeFile(`${projectName}/package.json`, updatedPackageJson);

const packageLock = await getFileFromCore("package-lock.json");
await writeFile(`${projectName}/package-lock.json`, packageLock);

const pluginsJson = await getFileFromCore("plugins.json");
// Add example plugin to plugins.json
const pluginsData = JSON.parse(pluginsJson);
pluginsData.example = "./custom-packages/simple-example/index.js";
await writeFile(`${projectName}/plugins.json`, JSON.stringify(pluginsData, null, 2));

const checkNode = await getFileFromCore("src/checkNodeVersion.cjs");
await writeFile(`${projectName}/utils/checkNodeVersion.cjs`, checkNode);
await writeFile(`${projectName}/src/checkNodeVersion.cjs`, checkNode);

const nvmrc = await getFileFromCore(".nvmrc", reactionRoot);
await writeFile(`${projectName}/.nvmrc`, nvmrc);

const npmrc = await getFileFromCore(".npmrc", reactionRoot);
await writeFile(`${projectName}/.npmrc`, updateNpmrc(npmrc));
const dotenv = await getFileFromCore(".env.example");
const updatedDotEnv = updateEnv(dotenv);
await writeFile(`${projectName}/.env`, updatedDotEnv);
const babelConfig = await getFileFromCore("babel.config.cjs");
const eslintConfig = await getFileFromCore(".eslintrc.cjs", reactionRoot);
await Promise.all([
copyTests("/apps/reaction/tests/", `${projectName}`),
writeFile(`${projectName}/babel.config.cjs`, babelConfig),
writeFile(`${projectName}/.eslintrc.cjs`, eslintConfig)]);
return true;
}

Expand Down
2 changes: 1 addition & 1 deletion commands/create-project.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const extraDependencyMap = {
* @summary creates api, admin, and storefront projects at same time in separate directories.
* @param {String} projectName - The name of the project to create
* @param {Object} options - Project options
* @returns {Boolean} true if success
* @returns {Boolean} {Promise<boolean>} return true when successful
*/
export async function createProjectAll(projectName, options) {
createProjectApi(`${projectName}Api`, options);
Expand Down
31 changes: 31 additions & 0 deletions utils/copyTests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import path from "path";
import os from "os";
import fs from "fs";
import { writeFile, rm, readFile } from "fs/promises";
import { copy } from "fs-extra";
import getFilesFromReactionRepo from "./getFilesFromReactionRepo.js";
import updateJestProcessEnv from "./updateJestProcessEnv.js";
import getFileFromCore from "./getFileFromCore.js";

/**
* This only copies the test utilities from upstream (git) to the target folder
* @param {String} sourcePath git sub-path from which the document will be fetched
* @param {String} destinationPath destination folder
* @returns {Boolean} {Promise<boolean>} return true when successful
*/
export default async function copyTests(sourcePath, destinationPath) {
const appPrefix = `test_utils${(Math.random() + 1).toString(36).substring(7)}`;
/**
* Create a temporary directory to update the jestProcessEnv received from upstream
*/
const tempDirectory = fs.mkdtempSync(path.join(os.tmpdir(), appPrefix));
await getFilesFromReactionRepo(sourcePath, tempDirectory);
const jestProcessEnvConfig = await readFile(path.join(tempDirectory, "util", "jestProcessEnv.json"));
/* write the updated jestProcessEnv in the file available in the temporary directory*/
await writeFile(path.join(tempDirectory, "util", "jestProcessEnv.json"), JSON.stringify(updateJestProcessEnv(jestProcessEnvConfig), null, 2));
const jestConfig = await getFileFromCore("jest.config.cjs");
await Promise.all([copy(tempDirectory, `${destinationPath}/tests`), writeFile(`${destinationPath}/jest.config.cjs`, jestConfig)]);
/* Clean up the temporary directory*/
await rm(tempDirectory, { recursive: true });
return true;
}
43 changes: 43 additions & 0 deletions utils/getFilesFromReactionRepo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import fs from "fs";
import path from "path";
import os from "os";
import simpleGit from "simple-git";
import isCI from "is-ci";
import { copy } from "fs-extra";
import rimraf from "rimraf";
import Logger from "./logger.js";
import getFileFromCore from "./getFileFromCore.js";

/**
* @summary Make local copies of files from remote git repository. It only fetches the contents from reactCommerce.reaction
* @param {String} sourcePath - Where to get the files from the local clone
* @param {String} destinationPath - Where to put the copied files
* @returns {Promise<Boolean>} - true if successful
*/
const getFilesFromReactionRepo = async (sourcePath, destinationPath) => {
const appPrefix = "reactioncommerce-reaction";
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), appPrefix));
const gitOptions = {
baseDir: `${tmpDir}`,
binary: "git",
maxConcurrentProcesses: 6
};
const git = await simpleGit(gitOptions);
const reactCommerceReactionPackage = await getFileFromCore("package.json");
const parsedPackage = JSON.parse(reactCommerceReactionPackage);
const { repository: { url: cliRepo } } = parsedPackage;
// On the CI, we need token to access the repo till it's private
const gitRepo = isCI ? `https://${process.env.GH_PUBLISHING_TOKEN}@github.com/reactioncommerce/reaction.git` : cliRepo;
try {
await git.clone(gitRepo, tmpDir, {
"--depth": 1
});
} catch (error) {
Logger.error(error);
}
await copy(`${tmpDir}${sourcePath}`, destinationPath);
await rimraf.sync(tmpDir);
return true;
};

export default getFilesFromReactionRepo;
6 changes: 6 additions & 0 deletions utils/updateJestProcessEnv.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const updateJestProcessEnv = (jestProcessEnv) => ({
...JSON.parse(jestProcessEnv),
MONGO_URL: "mongodb://localhost:27017/test"
});

export default updateJestProcessEnv;

0 comments on commit 07e5deb

Please sign in to comment.