rsnext/packages/create-next-app/create-app.ts
Joe Haddad 00badd4d58
Initialize Git repo on app creation (#9376)
* Initialize Git repo on app creation
This PR initializes a Git repository after Create Next App runs.

We ensure the app was not created in an already-existing Git or Mercurial repo.

Failures of setup (no Git installed) do not fail the application bootstrapping.

Closes #9077 (replaces)

* Add test

* Update index.test.js
2019-11-10 21:42:51 -08:00

147 lines
3.9 KiB
TypeScript

import chalk from 'chalk'
import cpy from 'cpy'
import fs from 'fs'
import makeDir from 'make-dir'
import os from 'os'
import path from 'path'
import { downloadAndExtractExample, hasExample } from './helpers/examples'
import { tryGitInit } from './helpers/git'
import { install } from './helpers/install'
import { isFolderEmpty } from './helpers/is-folder-empty'
import { getOnline } from './helpers/is-online'
import { shouldUseYarn } from './helpers/should-use-yarn'
export async function createApp({
appPath,
useNpm,
example,
}: {
appPath: string
useNpm: boolean
example?: string
}) {
if (example) {
const found = await hasExample(example)
if (!found) {
console.error(
`Could not locate an example named ${chalk.red(
`"${example}"`
)}. Please check your spelling and try again.`
)
process.exit(1)
}
}
const root = path.resolve(appPath)
const appName = path.basename(root)
await makeDir(root)
if (!isFolderEmpty(root, appName)) {
process.exit(1)
}
const useYarn = useNpm ? false : shouldUseYarn()
const isOnline = !useYarn || (await getOnline())
const originalDirectory = process.cwd()
const displayedCommand = useYarn ? 'yarn' : 'npm'
console.log(`Creating a new Next.js app in ${chalk.green(root)}.`)
console.log()
await makeDir(root)
process.chdir(root)
if (example) {
console.log(
`Downloading files for example ${chalk.cyan(
example
)}. This might take a moment.`
)
console.log()
await downloadAndExtractExample(root, example)
// Copy our default `.gitignore` if the application did not provide one
const ignorePath = path.join(root, '.gitignore')
if (!fs.existsSync(ignorePath)) {
fs.copyFileSync(
path.join(__dirname, 'templates', 'default', 'gitignore'),
ignorePath
)
}
console.log('Installing packages. This might take a couple of minutes.')
console.log()
await install(root, null, { useYarn, isOnline })
console.log()
} else {
const packageJson = {
name: appName,
version: '0.1.0',
private: true,
scripts: { dev: 'next dev', build: 'next build', start: 'next start' },
}
fs.writeFileSync(
path.join(root, 'package.json'),
JSON.stringify(packageJson, null, 2) + os.EOL
)
console.log(
`Installing ${chalk.cyan('react')}, ${chalk.cyan(
'react-dom'
)}, and ${chalk.cyan('next')} using ${displayedCommand}...`
)
console.log()
await install(root, ['react', 'react-dom', 'next'], { useYarn, isOnline })
console.log()
await cpy('**', root, {
parents: true,
cwd: path.join(__dirname, 'templates', 'default'),
rename: name => {
switch (name) {
case 'gitignore': {
return '.'.concat(name)
}
default: {
return name
}
}
},
})
}
if (tryGitInit(root)) {
console.log('Initialized a git repository.')
console.log()
}
let cdpath: string
if (path.join(originalDirectory, appName) === appPath) {
cdpath = appName
} else {
cdpath = appPath
}
console.log(`${chalk.green('Success!')} Created ${appName} at ${appPath}`)
console.log('Inside that directory, you can run several commands:')
console.log()
console.log(chalk.cyan(` ${displayedCommand} ${useYarn ? '' : 'run '}dev`))
console.log(' Starts the development server.')
console.log()
console.log(chalk.cyan(` ${displayedCommand} ${useYarn ? '' : 'run '}build`))
console.log(' Builds the app for production.')
console.log()
console.log(chalk.cyan(` ${displayedCommand} start`))
console.log(' Runs the built app in production mode.')
console.log()
console.log('We suggest that you begin by typing:')
console.log()
console.log(chalk.cyan(' cd'), cdpath)
console.log(
` ${chalk.cyan(`${displayedCommand} ${useYarn ? '' : 'run '}dev`)}`
)
console.log()
}