diff --git a/bin/cli b/bin/cli index 5e3641fefc..7d84ec0d2f 100755 --- a/bin/cli +++ b/bin/cli @@ -1,7 +1,9 @@ #!/usr/bin/env node const fs = require('fs-extra') +const os = require('os') const path = require('path') + const { exec } = require('../lib/exec') const { runUpgrade } = require('../lib/upgradeToV13') @@ -29,6 +31,14 @@ public/ .idea ` +const packageJson = { + scripts: { + start: 'govuk-prototype-kit start' + } +} + +const packageJsonFormat = { encoding: 'utf8', EOL: os.EOL, spaces: 2 } + function usage () { const prog = 'npx govuk-prototype-kit' console.log(` @@ -84,34 +94,73 @@ const getChosenKitDependency = () => { (async () => { if (command === 'create') { + // Install as a two-stage bootstrap process. + // + // In stage one (`create`) we create an empty project folder and install + // govuk-prototype-kit and govuk-frontend, then bootstrap stage two from + // the newly installed package. + // + // In stage two (`init`) we do the actual setup of the starter files. + // + // Doing it this way means we can be sure the version of the cli matches + // the version of the kit the user ends up with. Try to put as much logic + // as possible into stage two; stage one should ideally be able to install + // any future version of the kit. + const installDirectory = getInstallLocation() const kitDependency = getChosenKitDependency() - const copyFile = (fileName) => fs.copy(path.join(kitRoot, fileName), path.join(installDirectory, fileName)) - await fs.ensureDir(installDirectory) if ((await fs.readdir(installDirectory)).length > 0) { console.error(`Directory ${installDirectory} is not empty, please specify an empty location.`) - process.exit(3) + process.exitCode = 3 + return } - await Promise.all([ - fs.copy(path.join(kitRoot, 'prototype-starter'), installDirectory), - fs.writeFile(path.join(installDirectory, '.gitignore'), gitignore, 'utf8'), - fs.writeFile(path.join(installDirectory, '.npmrc'), npmrc, 'utf8'), - copyFile('LICENCE.txt') - ]) + await fs.writeJson(path.join(installDirectory, 'package.json'), {}, packageJsonFormat) console.log('Creating your prototype') const dots = setInterval(() => { process.stdout.write('.') }, 500) + await exec(`npm install ${kitDependency} govuk-frontend`, { stdio: 'inherit', cwd: installDirectory }, console.log) + clearInterval(dots) + await exec(`npx govuk-prototype-kit init -- ${installDirectory}`, { + stdio: 'inherit', + cwd: installDirectory + }, console.log) + } else if (command === 'init') { + // `init` is stage two of the install process (see above), it should be + // called by `create` with the correct arguments. + + if (additionalOptions[0] !== '--') { + usage() + process.exitCode = 2 + return + } + + const installDirectory = additionalOptions[1] + + const copyFile = (fileName) => fs.copy(path.join(kitRoot, fileName), path.join(installDirectory, fileName)) + const updatePackageJson = async (packageJsonPath) => { + let newPackageJson = Object.assign({}, packageJson) + newPackageJson = Object.assign(newPackageJson, await fs.readJson(packageJsonPath)) + await fs.writeJson(packageJsonPath, newPackageJson, packageJsonFormat) + } + + await Promise.all([ + fs.copy(path.join(kitRoot, 'prototype-starter'), installDirectory), + fs.writeFile(path.join(installDirectory, '.gitignore'), gitignore, 'utf8'), + fs.writeFile(path.join(installDirectory, '.npmrc'), npmrc, 'utf8'), + copyFile('LICENCE.txt'), + updatePackageJson(path.join(installDirectory, 'package.json')) + ]) } else if (command === 'start') { require('../start') } else if (command === 'upgrade') { diff --git a/package.json b/package.json index 20aee3460a..ecab3c3305 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "tmp-kit": "mkdir -p $TMPDIR/govuk-prototype-kit-playground && cd $TMPDIR/govuk-prototype-kit-playground && rm -Rf ./* && govuk-prototype-kit create --version local . && npm start", "start": "echo 'This project cannot be started, in order to test this project please create a prototype kit using the cli.'", "start:package": "KIT_TEST_DIR=tmp/test-prototype-package node cypress/scripts/run-starter-prototype", - "lint": "standard '**/*.js' scripts/create-release-archive scripts/cli lib/build/dev-server lib/build/generate-assets", + "lint": "standard '**/*.js' bin/cli scripts/create-release-archive lib/build/dev-server lib/build/generate-assets", "rapidtest": "jest --bail", "cypress:open": "cypress open", "test:heroku": "echo 'test:heroku' needs to be implemented", diff --git a/prototype-starter/package.json b/prototype-starter/package.json deleted file mode 100644 index 4297742a10..0000000000 --- a/prototype-starter/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "scripts": { - "start": "govuk-prototype-kit start" - } -}