diff --git a/.eslintignore b/.eslintignore
index 8085b7f92..216d536ef 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -3,6 +3,8 @@
**/node_modules/**
!.eslintrc.cjs
!.mocharc.js
-packages/init/src/template/src/**/*.js
+packages/init/src/template/**
+packages/init/test/cases/**/output/**
+packages/init/test/cases/**/my-app/**
packages/plugin-babel/test/cases/**/*main.js
TODO.md
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index bd89ae68f..5acf30c1f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,7 @@
coverage/
node_modules/
packages/init/test/**/my-app
+packages/init/test/**/output
packages/**/test/**/yarn.lock
packages/**/test/**/package-lock.json
packages/**/test/**/netlify
diff --git a/packages/init/README.md b/packages/init/README.md
index 4626e9ee3..c6a82f497 100644
--- a/packages/init/README.md
+++ b/packages/init/README.md
@@ -1,29 +1,41 @@
# @greenwood/init
## Overview
+
Init package for scaffolding out a new Greenwood project. For more information and complete docs, please visit the [Greenwood website](https://www.greenwoodjs.io/docs).
## Usage
-Create a directory and then run the `init` command to scaffold a minimal Greenwood project.
+Run the `init` command to scaffold a minimal Greenwood project into a directory of your choosing.
```bash
-mkdir my-app && cd my-app
-npx @greenwood/init@latest
+# providing an output directory of my-app
+npx @greenwood/init@latest my-app
```
-This will then output the following
+This will then output your project files into a directory called _my-app_
```bash
-├── greenwood.config.js
+my-app
├── .gitignore
+├── greenwood.config.js
├── package.json
└── src/
- └─ pages/
- └─ index.md
+ └─ ...
```
## API
+### Project Name
+
+By providing a name as the first argument, the `init` command will output the project files into a directory of the same name and configure the `name` property _package.json_.
+
+```bash
+# example
+npx @greenwood/init@latest my-app
+```
+
+> _Omitting my-app will install project files into the current directory._
+
### Template
To scaffold your new project based on one of [Greenwood's starter templates](https://github.com/orgs/ProjectEvergreen/repositories?q=greenwood-template-&type=all&language=&sort=), pass the `--template` flag and then follow the prompts to complete the scaffolding.
diff --git a/packages/init/src/index.js b/packages/init/src/index.js
index 9cdd3eea6..691c6db2f 100755
--- a/packages/init/src/index.js
+++ b/packages/init/src/index.js
@@ -28,11 +28,11 @@ const templateStandardName = 'greenwood-template-';
let selectedTemplate = null;
const scriptPkg = JSON.parse(fs.readFileSync(fileURLToPath(new URL('../package.json', import.meta.url)), 'utf-8'));
let templateDir = fileURLToPath(new URL('./template', import.meta.url));
-const TARGET_DIR = process.cwd();
+let TARGET_DIR = process.cwd();
const clonedTemplateDir = path.join(TARGET_DIR, '.greenwood', '.template');
console.log(`${chalk.rgb(175, 207, 71)('-------------------------------------------------------')}`);
-console.log(`${chalk.rgb(175, 207, 71)('Initialize Greenwood Template ♻️')}`);
+console.log(`${chalk.rgb(175, 207, 71)('Initialize a Greenwood Project ♻️')}`);
console.log(`${chalk.rgb(175, 207, 71)('-------------------------------------------------------')}`);
const program = new commander.Command(scriptPkg.name)
@@ -53,7 +53,7 @@ const npmInit = async () => {
const appPkg = JSON.parse(await fs.promises.readFile(path.join(templateDir, '/package.json'), 'utf-8'));
// use installation path's folder name for packages
- appPkg.name = path.basename(process.cwd());
+ appPkg.name = path.basename(TARGET_DIR);
// make sure users get latest and greatest version of Greenwood
// https://github.com/ProjectEvergreen/greenwood/issues/781
@@ -68,7 +68,7 @@ const npmInit = async () => {
// Copy root and src files to target directory
const srcInit = async () => {
- const templateFiles = [];
+ let templateFiles = [];
await createGitIgnore();
@@ -76,6 +76,12 @@ const srcInit = async () => {
templateFiles.push(file);
});
+ if (program.yarn) {
+ // we only need .npmrc if we're using npm
+ // because npm struggles with peer dependencies :/
+ templateFiles = templateFiles.filter(file => file !== '.npmrc');
+ }
+
await Promise.all(
templateFiles.map(async file => {
const resolvedPath = path.join(templateDir, file);
@@ -217,7 +223,7 @@ const listAndSelectTemplate = async () => {
});
if (selectedTemplate) {
- console.log('\Installing Selected Template:', selectedTemplate.name);
+ console.log('Installing Selected Template:', selectedTemplate.name);
}
});
}
@@ -247,6 +253,20 @@ const cleanUp = async () => {
const run = async () => {
try {
+ const firstArg = process.argv[process.argv.length - 1].split(' ')[0];
+ const taskRunner = program.yarn ? 'yarn' : 'npm run';
+ const shouldChangeDirectory = !firstArg.startsWith('--') && firstArg !== '';
+
+ if (!firstArg.startsWith('--') && firstArg !== '') {
+ TARGET_DIR = path.join(TARGET_DIR, `./${firstArg}`);
+
+ if (!fs.existsSync(TARGET_DIR)) {
+ fs.mkdirSync(TARGET_DIR);
+ }
+ }
+
+ console.log(`Initializing into project directory... ${TARGET_DIR}`);
+
if (program.template) {
await listAndSelectTemplate();
@@ -260,7 +280,7 @@ const run = async () => {
console.log('Initializing project with files...');
await srcInit();
- console.log('Creating manifest (package.json)...');
+ console.log('Creating package.json...');
await npmInit();
if (program.install || program.yarn) {
@@ -271,6 +291,12 @@ const run = async () => {
await cleanUp();
console.log(`${chalk.rgb(175, 207, 71)('Initializing new project complete!')}`);
+
+ if (shouldChangeDirectory) {
+ console.log(`Change directories by running => cd ${firstArg}`);
+ }
+
+ console.log(`To start developing run => ${taskRunner} dev`);
} catch (err) {
console.error(err);
}
diff --git a/packages/init/src/template/.npmrc b/packages/init/src/template/.npmrc
new file mode 100644
index 000000000..e9ee3cb4d
--- /dev/null
+++ b/packages/init/src/template/.npmrc
@@ -0,0 +1 @@
+legacy-peer-deps=true
\ No newline at end of file
diff --git a/packages/init/src/template/package.json b/packages/init/src/template/package.json
index c52c8c51f..4bc36f1c5 100644
--- a/packages/init/src/template/package.json
+++ b/packages/init/src/template/package.json
@@ -4,6 +4,7 @@
"description": "",
"type": "module",
"scripts": {
+ "dev": "greenwood develop",
"start": "greenwood develop",
"build": "greenwood build",
"serve": "greenwood serve"
diff --git a/packages/init/src/template/src/pages/index.html b/packages/init/src/template/src/pages/index.html
index 908ffcce6..a519f44b2 100644
--- a/packages/init/src/template/src/pages/index.html
+++ b/packages/init/src/template/src/pages/index.html
@@ -2,11 +2,6 @@
Greenwood
-
-
-
-
-
diff --git a/packages/init/test/cases/build.default/build.default.spec.js b/packages/init/test/cases/build.default/build.default.spec.js
index 16a45e617..fe53e530d 100644
--- a/packages/init/test/cases/build.default/build.default.spec.js
+++ b/packages/init/test/cases/build.default/build.default.spec.js
@@ -3,10 +3,10 @@
* Scaffold from minimal template and run Greenwood build command.
*
* User Result
- * Should scaffold from template and run the buildå.
+ * Should scaffold from template and run the build.
*
* User Command
- * @greenwood/init --install && greenwood buildå
+ * @greenwood/init --install && greenwood build
*
* User Workspace
* N / A
diff --git a/packages/init/test/cases/develop.default/develop.default.spec.js b/packages/init/test/cases/develop.default/develop.default.spec.js
index febd785c0..0f8f44620 100644
--- a/packages/init/test/cases/develop.default/develop.default.spec.js
+++ b/packages/init/test/cases/develop.default/develop.default.spec.js
@@ -108,18 +108,10 @@ xdescribe('Scaffold Greenwood and Run Develop command: ', function() {
done();
});
- it('should display My Project heading', function(done) {
- const heading = dom.window.document.querySelector('body > h2');
-
- expect(heading.textContent).to.equal('My Project');
-
- done();
- });
-
- it('should display My Project title', function(done) {
+ it('should display default project title', function(done) {
const title = dom.window.document.querySelector('head > title');
- expect(title.textContent).to.equal('My App');
+ expect(title.textContent).to.equal('Greenwood');
done();
});
diff --git a/packages/init/test/cases/init.default/init.default.spec.js b/packages/init/test/cases/init.default/init.default.spec.js
index d83b9a6b4..73e2c046a 100644
--- a/packages/init/test/cases/init.default/init.default.spec.js
+++ b/packages/init/test/cases/init.default/init.default.spec.js
@@ -58,6 +58,10 @@ describe('Scaffold Greenwood With Default Template: ', function() {
expect(fs.existsSync(path.join(outputPath, 'package-lock.json'))).to.be.false;
});
+ it('should generate a .npmrc file', function() {
+ expect(fs.existsSync(path.join(outputPath, '.npmrc'))).to.be.true;
+ });
+
it('should not generate a yarn.lock file', function() {
expect(fs.existsSync(path.join(outputPath, 'yarn.lock'))).to.be.false;
});
@@ -77,7 +81,8 @@ describe('Scaffold Greenwood With Default Template: ', function() {
it('the should have the correct Greenwood scripts', function() {
const scripts = pkgJson.scripts;
- expect(scripts.start).to.equal('greenwood develop');
+ expect(scripts.dev).to.equal('greenwood develop');
+ expect(scripts.start).to.equal(scripts.dev);
expect(scripts.build).to.equal('greenwood build');
expect(scripts.serve).to.equal('greenwood serve');
});
diff --git a/packages/init/test/cases/init.project-name/init.project-name.spec.js b/packages/init/test/cases/init.project-name/init.project-name.spec.js
new file mode 100644
index 000000000..38eedbc2e
--- /dev/null
+++ b/packages/init/test/cases/init.project-name/init.project-name.spec.js
@@ -0,0 +1,69 @@
+/*
+ * Use Case
+ * Scaffold into a custom project directory
+ *
+ * User Result
+ * Should scaffold out the new project into a my-app directory.
+ *
+ * User Command
+ * npx @greenwood/init my-app
+ *
+ * User Workspace
+ * N / A
+ */
+import chai from 'chai';
+import fs from 'fs';
+import path from 'path';
+import { Runner } from 'gallinago';
+import { fileURLToPath, URL } from 'url';
+
+const expect = chai.expect;
+
+describe('Scaffold Greenwood into a custom directory: ', function() {
+ const initPath = path.join(process.cwd(), 'packages/init/src/index.js');
+ const outputPath = fileURLToPath(new URL('./output', import.meta.url));
+ const projectName = 'my-app';
+ let runner;
+
+ before(function() {
+ this.context = {
+ publicDir: path.join(outputPath, 'public')
+ };
+ runner = new Runner();
+ });
+
+ describe(`Default output to a custom ${projectName} directory`, function () {
+
+ before(function() {
+ runner.setup(outputPath);
+ runner.runCommand(initPath, `${projectName} --foo=bar`);
+ });
+
+ describe('expected scaffolding output', function () {
+
+ it('should create a src/pages directory', function() {
+ expect(fs.existsSync(path.join(outputPath, projectName, 'src', 'pages'))).to.be.true;
+ });
+
+ it('should generate a .gitignore file', function() {
+ expect(fs.existsSync(path.join(outputPath, projectName, '.gitignore'))).to.be.true;
+ });
+
+ it('should generate a package.json file', function() {
+ expect(fs.existsSync(path.join(outputPath, projectName, 'package.json'))).to.be.true;
+ });
+
+ it('should have the name in package.json match the project name argument', function() {
+ const packageJson = JSON.parse(fs.readFileSync(path.join(outputPath, projectName, 'package.json'), 'utf-8'));
+
+ expect(packageJson.name).to.equal(projectName);
+ });
+ });
+
+ });
+
+ after(function() {
+ runner.teardown([outputPath]);
+ });
+
+});
\ No newline at end of file
diff --git a/packages/init/test/cases/init.yarn/init.yarn.spec.js b/packages/init/test/cases/init.yarn/init.yarn.spec.js
index 4728e9667..0782622a7 100644
--- a/packages/init/test/cases/init.yarn/init.yarn.spec.js
+++ b/packages/init/test/cases/init.yarn/init.yarn.spec.js
@@ -58,6 +58,10 @@ xdescribe('Scaffold Greenwood With Yarn: ', function() {
expect(fs.existsSync(path.join(outputPath, 'package-lock.json'))).to.be.false;
});
+ it('should not generate a .npmrc file', function() {
+ expect(fs.existsSync(path.join(outputPath, '.npmrc'))).to.be.false;
+ });
+
it('should generate a public directory', function() {
expect(fs.existsSync(path.join(outputPath, 'public'))).to.be.true;
});
diff --git a/www/pages/docs/index.md b/www/pages/docs/index.md
index c3af8caf5..9ae7e0dad 100644
--- a/www/pages/docs/index.md
+++ b/www/pages/docs/index.md
@@ -10,7 +10,7 @@ This is the documentation space for **Greenwood** that we hope will help you get
### Installation
-Greenwood can be installed with any of the common package managers available today.
+Greenwood can be installed manually with any of the common package managers available today or you scaffold a new project through our [`init` package](/getting-started/quick-start/#init-package).
```bash
# npm
diff --git a/www/pages/getting-started/quick-start.md b/www/pages/getting-started/quick-start.md
index aaf3962c8..3b05ed66a 100644
--- a/www/pages/getting-started/quick-start.md
+++ b/www/pages/getting-started/quick-start.md
@@ -17,12 +17,10 @@ If you want to get right into the code, we have a few options to get you started
### Init Package
-You can use Greenwood's [`init` package](https://github.com/ProjectEvergreen/greenwood/blob/master/packages/init/README.md) to scaffold out a new empty Greenwood project, or from a layout.
+You can use Greenwood's [`init` package](https://github.com/ProjectEvergreen/greenwood/blob/master/packages/init/README.md) to scaffold out a new empty Greenwood project or use one our template starter kits.
```bash
-mkdir my-app && cd my-app
-
-npx @greenwood/init@latest
+$ npx @greenwood/init@latest my-app
```
### Command Line