From f0517e072da8378841f910cde6b2e337ce7f05ff Mon Sep 17 00:00:00 2001 From: Fran Zekan Date: Tue, 5 May 2020 11:11:26 +0200 Subject: [PATCH] Add helpful error messages to CLI when trying to use commands outside an app (#319) (patch) --- package.json | 2 +- packages/cli/package.json | 7 ++- packages/cli/src/check-before-running.ts | 37 ++++++++++++ packages/cli/src/commands/generate.ts | 7 --- packages/cli/src/utils/is-blitz-root.ts | 68 +++++++++++++++++++++++ packages/generator/test/generator.test.js | 2 - packages/server/package.json | 1 + 7 files changed, 113 insertions(+), 11 deletions(-) create mode 100644 packages/cli/src/check-before-running.ts create mode 100644 packages/cli/src/utils/is-blitz-root.ts diff --git a/package.json b/package.json index 85fec699ef..9d7c953038 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,7 @@ }, "husky": { "hooks": { - "pre-commit": "pretty-quick --staged", + "pre-commit": "yarn lint && pretty-quick --staged", "pre-push": "yarn test" } }, diff --git a/packages/cli/package.json b/packages/cli/package.json index d20be018ee..5bb57a46ef 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -60,7 +60,12 @@ "plugins": [ "@oclif/plugin-help", "@oclif/plugin-not-found" - ] + ], + "hooks": { + "prerun": [ + "./src/check-before-running" + ] + } }, "keywords": [ "blitz", diff --git a/packages/cli/src/check-before-running.ts b/packages/cli/src/check-before-running.ts new file mode 100644 index 0000000000..178ff2211a --- /dev/null +++ b/packages/cli/src/check-before-running.ts @@ -0,0 +1,37 @@ +import {Hook} from '@oclif/config' +import chalk from 'chalk' + +import {isBlitzRoot, IsBlitzRootError} from './utils/is-blitz-root' + +const whitelistGlobal = ['new'] + +export const hook: Hook<'init'> = async function (options) { + // Bug with oclif + const id = (options as any).Command.id + if (id && whitelistGlobal.includes(id)) return + + const {err, message, depth} = await isBlitzRoot() + + if (err) { + switch (message) { + case IsBlitzRootError.NotBlitz: + return this.error( + `You are not inside a Blitz project, so this command won't work.\nYou can create a new app with ${chalk.bold( + 'blitz new myapp', + )} or see help with ${chalk.bold('blitz help')}`, + ) + case IsBlitzRootError.NotRoot: + const help = depth + ? `\nUse ${chalk.bold('cd ' + '../'.repeat(depth))} to get to the root of your project` + : '' + + return this.error( + `You are currently in a sub-folder of your Blitz app, but this command must be used from the root of your project.${help}`, + ) + case IsBlitzRootError.BadPackageJson: + return this.error(`Reading package.json file`) + default: + return this.error(`An error occurred`) + } + } +} diff --git a/packages/cli/src/commands/generate.ts b/packages/cli/src/commands/generate.ts index d5d43756cd..3a7c1a2d92 100644 --- a/packages/cli/src/commands/generate.ts +++ b/packages/cli/src/commands/generate.ts @@ -144,13 +144,6 @@ export class Generate extends Command { debug('args: ', args) debug('flags: ', flags) - const isInRoot = fs.existsSync(path.resolve('blitz.config.js')) - - if (!isInRoot) { - log.error('No blitz.config.js found. `generate` must be run from the root of the project.') - this.exit(1) - } - try { let singularRootContext: string diff --git a/packages/cli/src/utils/is-blitz-root.ts b/packages/cli/src/utils/is-blitz-root.ts new file mode 100644 index 0000000000..a8c69f811e --- /dev/null +++ b/packages/cli/src/utils/is-blitz-root.ts @@ -0,0 +1,68 @@ +import {readJSON} from 'fs-extra' +import pkgDir from 'pkg-dir' +import {resolve} from 'path' + +export enum IsBlitzRootError { + NotBlitz, + NotRoot, + BadPackageJson, +} + +const checkParent = async (): Promise => { + const rootDir = await pkgDir('./') + + if (rootDir) { + const file = await readJSON(resolve(rootDir, 'package.json')) + + if (file && Object.keys(file.dependencies || {}).includes('blitz')) { + return process.cwd().slice(rootDir.length).split('/').length - 1 + } + } + + return false +} + +/** + * @name isBlitzRoot + * @returns {IsBlitzRootError} + * notBlitz -> when can't find package.json in current folder and first found in parent + * doesn't have blitz in dependencies + * notRoot -> if in a nested folder of blitz project (found blitz as depend in a parent package.json) + * badPackageJson -> an error occurred while reading local package.json + */ + +export const isBlitzRoot = async (): Promise<{err: boolean; message?: IsBlitzRootError; depth?: number}> => { + try { + const local = await readJSON('./package.json') + if (local) { + if (Object.keys(local.dependencies || {}).includes('blitz')) { + return {err: false} + } else { + return { + err: true, + message: IsBlitzRootError.NotBlitz, + } + } + } + return {err: true, message: IsBlitzRootError.BadPackageJson} + } catch (err) { + // No local package.json + if (err.code === 'ENOENT') { + const out = await checkParent() + + if (out === false) { + return { + err: true, + message: IsBlitzRootError.NotBlitz, + } + } else { + return { + err: true, + message: IsBlitzRootError.NotRoot, + depth: out, + } + } + } + } + return {err: true} +} diff --git a/packages/generator/test/generator.test.js b/packages/generator/test/generator.test.js index d5e0c64f7e..02ec2dad9e 100644 --- a/packages/generator/test/generator.test.js +++ b/packages/generator/test/generator.test.js @@ -1,5 +1,3 @@ -'use strict' - describe('generator', () => { it('needs tests', () => { expect(1).toBe(1) diff --git a/packages/server/package.json b/packages/server/package.json index 1b226a3a78..f563567f26 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -12,6 +12,7 @@ "register" ], "scripts": { + "predev": "wait-on -d 500 ../core/dist/packages/core/src/index.d.ts", "dev": "tsdx watch --verbose", "build": "tsdx build", "test": "tsdx test",