Skip to content

Commit

Permalink
consolidate CLI logic and depend on it in gatsby
Browse files Browse the repository at this point in the history
  • Loading branch information
jquense committed Aug 22, 2017
1 parent 8d41f7a commit dc991d0
Show file tree
Hide file tree
Showing 31 changed files with 653 additions and 7,968 deletions.
2 changes: 1 addition & 1 deletion packages/gatsby-cli/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
/*.js
/lib
yarn.lock
18 changes: 13 additions & 5 deletions packages/gatsby-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,25 @@
"version": "1.0.12",
"author": "Kyle Mathews <mathews.kyle@gmail.com>",
"bin": {
"gatsby": "./index.js"
"gatsby": "lib/index.js"
},
"dependencies": {
"babel-runtime": "^6.25.0",
"bluebird": "^3.5.0",
"commander": "^2.11.0",
"common-tags": "^1.4.0",
"convert-hrtime": "^2.0.0",
"core-js": "^2.5.0",
"execa": "^0.8.0",
"fs-extra": "^4.0.1",
"hosted-git-info": "^2.5.0",
"lodash": "^4.17.4",
"pretty-error": "^2.1.1",
"resolve-cwd": "^2.0.0",
"tracer": "^0.8.9"
"strong-log-transformer": "^1.0.6",
"tracer": "^0.8.9",
"yargs": "^8.0.2",
"yurnalist": "^0.2.1"
},
"devDependencies": {
"babel-cli": "^6.24.1"
Expand All @@ -23,9 +31,9 @@
"gatsby"
],
"license": "MIT",
"main": "index.js",
"main": "lib/index.js",
"scripts": {
"build": "babel src --out-dir . --ignore __tests__",
"watch": "babel -w src --out-dir . --ignore __tests__"
"build": "babel src --out-dir lib --ignore __tests__",
"watch": "babel -w src --out-dir lib --ignore __tests__"
}
}
Empty file removed packages/gatsby-cli/src/.gitkeep
Empty file.
172 changes: 172 additions & 0 deletions packages/gatsby-cli/src/create-cli.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
const path = require(`path`)
const resolveCwd = require(`resolve-cwd`)
const yargs = require(`yargs`)
const report = require(`./reporter`)

const DEFAULT_BROWSERS = [
`> 1%`,
`last 2 versions`,
`IE >= 9`,
]

function buildLocalCommands(cli, isLocalSite) {
const defaultHost = `localhost`
const directory = path.resolve(`.`)

function getSiteInfo() {
if (!isLocalSite) return {}

const sitePackageJson = require(path.join(directory, `package.json`))
const browserslist = sitePackageJson.browserslist || DEFAULT_BROWSERS
return { sitePackageJson, browserslist }
}

function resolveLocalCommand(command) {
if (!isLocalSite) {
cli.showHelp()
report.verbose(`current directory: ${directory}`)
return report.panic(
`gatsby <${command}> can only be run for a gatsby site. \n` +
`Either the current working directory does not contain a package.json or ` +
`'gatsby' is not specified as a dependency`
)
}
try {
return require(resolveCwd(`gatsby/dist/commands/${command}`))
} catch (err) {
cli.showHelp()
return report.panic(
`There was a problem loading the local ${command} command. Gatsby may not be installed.`,
err
)
}
}

cli.command({
command: `develop`,
desc:
`Start development server. Watches files, rebuilds, and hot reloads ` +
`if something changes`,
builder: _ => _
.option(`H`, {
alias: `host`,
type: `string`,
describe: `Set host. Defaults to ${defaultHost}`,
})
.option(`p`, {
alias: `port`,
type: `string`,
default: `8000`,
describe: `Set port. Defaults to 8000`,
})
.option(`o`, {
alias: `open`,
type: `boolean`,
describe: `Open the site in your browser for you.`,
}),
handler: argv => {
const { sitePackageJson, browserslist } = getSiteInfo()

resolveLocalCommand(`develop`)({
...argv,
directory,
sitePackageJson,
browserslist,
})
},
})

cli
.command({
command: `build`,
desc: `Build a Gatsby project.`,
builder: _ => _
.option(`prefix-paths`, {
type: `string`,
describe: `Build site with link paths prefixed (set prefix in your config).`,
}),
handler: argv => {
process.env.NODE_ENV = `production`
const { sitePackageJson, browserslist } = getSiteInfo()

resolveLocalCommand(`build`)({
...argv,
directory,
sitePackageJson,
browserslist,
})
},
})

cli
.command({
command: `serve`,
desc: `Serve previously built Gatsby site.`,
builder: _ => _
.option(`H`, {
alias: `host`,
type: `string`,
describe: `Set host. Defaults to ${defaultHost}`,
})
.option(`p`, {
alias: `port`,
type: `string`,
default: `8000`,
describe: `Set port. Defaults to 8000`,
})
.option(`o`, {
alias: `open`,
type: `boolean`,
default: `8000`,
describe: `Open the site in your browser for you.`,
}),

handler: argv => {
const { sitePackageJson, browserslist } = getSiteInfo()

resolveLocalCommand(`serve`)({
...argv,
directory,
sitePackageJson,
browserslist,
})
},
})
}

function isLocalGatsbySite() {
let inGatsbySite = false
try {
let { dependencies, devDependencies } = require(path.resolve(`./package.json`))
inGatsbySite = (
(dependencies && dependencies.gatsby) ||
(devDependencies && devDependencies.gatsby)
)
} catch (err) { /* ignore */ }
return inGatsbySite
}

module.exports = (argv, handlers) => {
let cli = yargs()
let isLocalSite = isLocalGatsbySite()

cli
.usage(`Usage: $0 <command> [options]`)
.help(`h`).alias(`h`, `help`)
.version().alias(`v`, `version`)

buildLocalCommands(cli, isLocalSite)

return cli
.command({
command: `new [rootPath] [starter]`,
desc: `Create new Gatsby project.`,
handler: ({ rootPath, starter = `gatsbyjs/gatsby-starter-default` }) => {
require(`./init-starter`)(starter, { rootPath })
},
})
.wrap(cli.terminalWidth())
.demandCommand(1, `Pass --help to see all available commands and options.`)
.showHelpOnFail(true, `A command is required.`)
.parse(argv.slice(2))
}
162 changes: 26 additions & 136 deletions packages/gatsby-cli/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,150 +4,40 @@
// use require() with backtick strings so use the es6 syntax
import "babel-polyfill"

const program = require(`commander`)
const packageJson = require(`./package.json`)
const path = require(`path`)
const _ = require(`lodash`)
const resolveCwd = require(`resolve-cwd`)
const createCli = require(`./create-cli`)
const report = require(`./reporter`)

program.version(packageJson.version).usage(`[command] [options]`)
global.Promise = require(`bluebird`)

let inGatsbySite = false
let localPackageJSON
try {
localPackageJSON = require(path.resolve(`./package.json`))
if (
(localPackageJSON.dependencies && localPackageJSON.dependencies.gatsby) ||
(localPackageJSON.devDependencies &&
localPackageJSON.devDependencies.gatsby)
) {
inGatsbySite = true
} else if (
localPackageJSON.devDependencies &&
localPackageJSON.devDependencies.gatsby
) {
inGatsbySite = true
}
} catch (err) {
// ignore
}

const defaultHost = `localhost`

const directory = path.resolve(`.`)
const getSiteInfo = () => {
const sitePackageJson = require(path.join(directory, `package.json`))
const browserslist = sitePackageJson.browserslist || [
`> 1%`,
`last 2 versions`,
`IE >= 9`,
]
return { sitePackageJson, browserslist }
}

// If there's a package.json in the current directory w/ a gatsby dependency
// include the develop/build/serve commands. Otherwise, just the new.
if (inGatsbySite) {
program
.command(`develop`)
.description(
`Start development server. Watches files and rebuilds and hot reloads ` +
`if something changes`
) // eslint-disable-line max-len
.option(
`-H, --host <url>`,
`Set host. Defaults to ${defaultHost}`,
defaultHost
)
.option(`-p, --port <port>`, `Set port. Defaults to 8000`, `8000`)
.option(`-o, --open`, `Open the site in your browser for you.`)
.action(command => {
const developPath = resolveCwd(`gatsby/dist/utils/develop`)
const develop = require(developPath)
const { sitePackageJson, browserslist } = getSiteInfo()
const p = {
...command,
directory,
sitePackageJson,
browserslist,
}
develop(p)
})

program
.command(`build`)
.description(`Build a Gatsby project.`)
.option(
`--prefix-paths`,
`Build site with link paths prefixed (set prefix in your config).`
)
.action(command => {
// Set NODE_ENV to 'production'
process.env.NODE_ENV = `production`

const buildPath = resolveCwd(`gatsby/dist/utils/build`)
const build = require(buildPath)
const { sitePackageJson, browserslist } = getSiteInfo()
const p = {
...command,
directory,
sitePackageJson,
browserslist,
}
build(p).then(() => {
console.log(`Done building in`, process.uptime(), `seconds`)
process.exit()
})
})
const version = process.version
const verDigit = Number(version.match(/\d+/)[0])

program
.command(`serve`)
.description(`Serve built site.`)
.option(
`-H, --host <url>`,
`Set host. Defaults to ${defaultHost}`,
defaultHost
)
.option(`-p, --port <port>`, `Set port. Defaults to 9000`, `9000`)
.option(`-o, --open`, `Open the site in your browser for you.`)
.action(command => {
const servePath = resolveCwd(`gatsby/dist/utils/serve`)
const serve = require(servePath)
const { sitePackageJson, browserslist } = getSiteInfo()
const p = {
...command,
directory,
sitePackageJson,
browserslist,
}
serve(p)
})
if (verDigit < 4) {
report.panic(
`Gatsby 1.0+ requires node.js v4 or higher (you have ${version}). \n` +
`Upgrade node to the latest stable release.`
)
}

program
.command(`new [rootPath] [starter]`)
.description(`Create new Gatsby project.`)
.action((rootPath, starter) => {
const newCommand = require(`./new`)
newCommand(rootPath, starter)
})
Promise.onPossiblyUnhandledRejection(error => {
report.error(error)
throw error
})

program.on(`--help`, () => {
console.log(
`To show subcommand help:
process.on(`unhandledRejection`, error => {
// This will exit the process in newer Node anyway so lets be consistent
// across versions and crash
report.panic(`UNHANDLED REJECTION`, error)
})

gatsby [command] -h
`
)
process.on(`uncaughtException`, error => {
report.panic(`UNHANDLED EXCEPTION`, error)
})

// If the user types an unknown sub-command, just display the help.
const subCmd = process.argv.slice(2, 3)[0]
let cmds = _.map(program.commands, `_name`)
cmds = cmds.concat([`--version`, `-V`])

if (!_.includes(cmds, subCmd)) {
program.help()
} else {
program.parse(process.argv)
}
createCli(process.argv, {
develop: () => require(resolveCwd(`gatsby/dist/commands/develop`)),
build: () => require(resolveCwd(`gatsby/dist/commands/build`)),
serve: () => require(resolveCwd(`gatsby/dist/commands/serve`)),
})
Loading

0 comments on commit dc991d0

Please sign in to comment.