Skip to content

Commit

Permalink
V4P4: feat(buildpack): scaffolding creation (#1500)
Browse files Browse the repository at this point in the history
* feat(buildpack): scaffolding creation. Closes #1693.

test: add tests for createProject

feat: CLI wizard for npm init @magento/pwa

fix: scaffolding fixes and docs

chore: remove lockfiles until we can maintain them

Revise scaffolding docs (#1635)

* Revise scaffolding overview docs

* Revise create-project reference topic

* Revise custom project template draft topic

* Make changes based on PR review

fixup: make create-pwa messages less venia-specific

Co-Authored-By: Andy Terranova <13182778+supernova-at@users.noreply.github.com>

fixup: log message and doc feedback

Co-Authored-By: Andy Terranova <13182778+supernova-at@users.noreply.github.com>

fixup: fix tests

fixup prettier updates

fixup debug mode in buildpack create

* fixup remove is-valid-npm-name

* enhancement: better post-install logging
  • Loading branch information
James Zetlen authored and dpatil-magento committed Sep 26, 2019
1 parent 56fff7b commit baa1e00
Show file tree
Hide file tree
Showing 46 changed files with 1,728 additions and 54 deletions.
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,4 @@ Add any ideas about possible solutions to the problem here.
- [ ] `pwa-devdocs`
- [ ] `upward-js`
- [ ] `upward-spec`
- [ ] `create-pwa`
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,4 @@ Add any other context or screenshots about the feature request here.
- [ ] `pwa-devdocs`
- [ ] `upward-js`
- [ ] `upward-spec`
- [ ] `create-pwa`
1 change: 1 addition & 0 deletions Dockerfile.dev
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ RUN apk --no-cache --virtual add \
yarn

# copy just the dependency files and configs needed for install
COPY packages/create-pwa/package.json ./packages/create-pwa/package.json
COPY packages/babel-preset-peregrine/package.json ./packages/babel-preset-peregrine/package.json
COPY packages/graphql-cli-validate-magento-pwa-queries/package.json ./packages/graphql-cli-validate-magento-pwa-queries/package.json
COPY packages/peregrine/package.json ./packages/peregrine/package.json
Expand Down
1 change: 1 addition & 0 deletions Dockerfile.prod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ RUN apk --no-cache --virtual add \
yarn

# copy just the dependency files and configs needed for install
COPY packages/create-pwa/package.json ./packages/create-pwa/package.json
COPY packages/babel-preset-peregrine/package.json ./packages/babel-preset-peregrine/package.json
COPY packages/graphql-cli-validate-magento-pwa-queries/package.json ./packages/graphql-cli-validate-magento-pwa-queries/package.json
COPY packages/peregrine/package.json ./packages/peregrine/package.json
Expand Down
12 changes: 9 additions & 3 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const path = require('path');
// Reusable glob string for building `testMatch` patterns.
// All testable code in packages lives at either 'src' for code that must
// transpile, or 'lib' for code that doesn't have to.
const testGlob = '/**/{src,lib}/**/__tests__/*.(test|spec).js';
const testGlob = '/**/{src,lib,_buildpack}/**/__tests__/*.(test|spec).js';

// Reusable test configuration for Venia UI and storefront packages.
const testVenia = inPackage => ({
Expand Down Expand Up @@ -72,7 +72,7 @@ const testVenia = inPackage => ({
// import `.graphql` files into JS.
'\\.(gql|graphql)$': 'jest-transform-graphql',
// Use the default babel-jest for everything else.
'.*': 'babel-jest'
'\\.(js|css)$': 'babel-jest'
},
// Normally babel-jest ignores node_modules and only transpiles the current
// package's source. The below setting forces babel-jest to transpile
Expand Down Expand Up @@ -132,6 +132,9 @@ const jestConfig = {
})),
configureProject('pwa-buildpack', 'Buildpack', inPackage => ({
testEnvironment: 'node',
modulePaths: [
inPackage('lib/Utilities/__tests__/__fixtures__/modules')
],
setupFiles: [inPackage('scripts/fetch-mock.js')]
})),
configureProject('upward-js', 'Upward JS', () => ({
Expand Down Expand Up @@ -164,11 +167,14 @@ const jestConfig = {
collectCoverage: true,
collectCoverageFrom: [
// Code directories
'packages/*/{src,lib}/**/*.js',
'packages/*/{src,lib,_buildpack}/**/*.js',
// Not the create-pwa package, which requires manual testing
'!packages/create-pwa/**/*.js',
// Not node_modules
'!**/node_modules/**',
// Not __tests__, __helpers__, or __any_double_underscore_folders__
'!**/__[[:alpha:]]*__/**',
'!**/.*/__[[:alpha:]]*__/**',
// Not this file itself
'!jest.config.js'
],
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"private": true,
"workspaces": [
"packages/babel-preset-peregrine",
"packages/create-pwa",
"packages/graphql-cli-validate-magento-pwa-queries",
"packages/peregrine",
"packages/pwa-buildpack",
Expand Down Expand Up @@ -56,7 +57,7 @@
"eslint-plugin-node": "~8.0.1",
"eslint-plugin-package-json": "~0.1.3",
"eslint-plugin-react": "~7.12.4",
"eslint-plugin-react-hooks": "~1.6.0",
"eslint-plugin-react-hooks": "~2.0.1",
"execa": "~1.0.0",
"figures": "~2.0.0",
"first-run": "~2.0.0",
Expand Down
Empty file added packages/create-pwa/README.md
Empty file.
3 changes: 3 additions & 0 deletions packages/create-pwa/bin/create-pwa
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env node

require('../')();
143 changes: 143 additions & 0 deletions packages/create-pwa/lib/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
const { basename, resolve } = require('path');
const os = require('os');
const changeCase = require('change-case');
const inquirer = require('inquirer');
const execa = require('execa');
const chalk = require('chalk');
const gitUserInfo = require('git-user-info');
const isInvalidPath = require('is-invalid-path');
const isValidNpmName = require('is-valid-npm-name');
const pkg = require('../package.json');
const {
sampleBackends
} = require('@magento/pwa-buildpack/lib/cli/create-project');

module.exports = async () => {
console.log(chalk.greenBright(`${pkg.name} v${pkg.version}`));
console.log(
chalk.white(`Creating a ${chalk.whiteBright('PWA Studio')} project`)
);
const userAgent = process.env.npm_config_user_agent || '';
const isYarn = userAgent.includes('yarn');

const questions = [
{
name: 'directory',
message:
'Project root directory (will be created if it does not exist)',
validate: dir =>
!dir
? 'Please enter a directory path'
: isInvalidPath(dir)
? 'Invalid directory path; contains illegal characters'
: true
},
{
name: 'name',
message:
'Short name of the project to put in the package.json "name" field',
validate: isValidNpmName,
default: ({ directory }) => basename(directory)
},
{
name: 'author',
message:
'Name of the author to put in the package.json "author" field',
default: () => {
const userInfo = os.userInfo();
let author = userInfo.username;
const gitInfo = gitUserInfo({
path: resolve(userInfo.homedir, '.gitconfig')
});

if (gitInfo) {
author = gitInfo.name || author;
if (gitInfo.email) {
author += ` <${gitInfo.email}>`;
}
}
return author;
}
},
{
name: 'backendUrl',
type: 'list',
message:
'Magento instance to use as a backend (will be added to `.env` file)',
choices: sampleBackends.environments
.map(({ name, description, url }) => ({
name: description,
value: url,
short: name
}))
.concat([
{
name:
'Other (I will provide my own backing Magento instance)',
value: false,
short: 'Other'
}
])
},
{
name: 'customBackendUrl',
message:
'URL of a Magento instance to use as a backend (will be added to `.env` file)',
default: 'https://magento2.localhost',
when: ({ backendUrl }) => !backendUrl
},
{
name: 'npmClient',
type: 'list',
message: 'NPM package management client to use',
choices: ['npm', 'yarn'],
default: isYarn ? 'yarn' : 'npm'
},
{
name: 'install',
type: 'confirm',
message: ({ npmClient }) =>
`Install package dependencies with ${npmClient} after creating project`,
default: true
}
];
let answers;
try {
answers = await inquirer.prompt(questions);
} catch (e) {
console.error('App creation cancelled.');
}
answers.backendUrl = answers.backendUrl || answers.customBackendUrl;
const args = questions.reduce(
(args, q) => {
if (q.name === 'customBackendUrl' || q.name === 'directory') {
return args;
}
const answer = answers[q.name];
const option = changeCase.paramCase(q.name);
if (q.type === 'confirm') {
if (answer !== q.default) {
return [...args, answer ? `--${option}` : `--no-${option}`];
}
return args;
}
return [...args, `--${option}`, `"${answer}"`];
},
['create-project', answers.directory, '--template', '"venia-concept"']
);

const argsString = args.join(' ');

console.log(
'\nRunning command: \n\n' +
chalk.whiteBright(`buildpack ${argsString}\n\n`)
);

const buildpackBinLoc = resolve(
require.resolve('@magento/pwa-buildpack'),
'../../bin/buildpack'
);
await execa.shell(`${buildpackBinLoc} ${argsString}`, {
stdio: 'inherit'
});
};
42 changes: 42 additions & 0 deletions packages/create-pwa/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"name": "@magento/create-pwa",
"version": "1.0.0",
"publishConfig": {
"access": "public"
},
"description": "Create a PWA Studio app with a single command.",
"main": "./lib/index.js",
"bin": "./bin/create-pwa",
"scripts": {
"build": " ",
"build:ci": " ",
"build:dev": " ",
"clean": " ",
"test": " "
},
"repository": "github:magento-research/pwa-studio",
"keywords": [
"magento",
"pwa",
"create-pwa",
"create-pwa-app",
"pwa-studio"
],
"author": "Magento Commerce",
"license": "(OSL-3.0 OR AFL-3.0)",
"bugs": {
"url": "https://github.com/magento-research/pwa-studio/issues"
},
"homepage": "https://github.com/magento-research/pwa-studio/tree/master/packages/create-pwa#readme",
"dependencies": {
"@magento/pwa-buildpack": "~3.0.0",
"chalk": "^2.4.2",
"change-case": "^3.1.0",
"execa": "^1.0.0",
"git-user-info": "^1.0.1",
"inquirer": "^6.3.1",
"is-invalid-path": "^1.0.2",
"is-valid-npm-name": "^0.0.4",
"webpack": "^4.29.5"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const mock = {
after: jest.fn(),
visitor: {
'index.js': jest.fn(),
'**/*.css': jest.fn(),
'ignoreexp/*': jest.fn()
}
};

const factory = () => mock;

factory.mock = mock;

module.exports = factory;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
_gitignore_test
ignorefile
ignoreexp/*.txt
ignoredir
nonexistentfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ignore me
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log('buildpack-template-package index.js');
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "buildpack-template-package",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
html {
display: none;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
* {
display: block;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = () => {
throw new Error('Failed to run a bad instruction');
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "package-with-bad-instruction",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = ({ fs }) => fs.readJsonSync;
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "package-with-instruction",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "package-with-no-instructions",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = ({ fs }) => fs.readJsonSync;
Loading

0 comments on commit baa1e00

Please sign in to comment.