mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-09 12:57:46 +00:00
[now dev] Allow now dev as package.json script (#2559)
* [now dev] Allow `now dev` as package.json script * Fix absolute path for now dev * Fix directory issue * Typo * Update src/commands/dev/dev.ts Co-Authored-By: Nathan Rajlich <n@n8.io> * Whitespace * Make code simpler * Extend type * Update errors/now-dev-as-dev-script.md Co-Authored-By: Nathan Rajlich <n@n8.io> * Update errors/now-dev-as-dev-script.md Co-Authored-By: Nathan Rajlich <n@n8.io>
This commit is contained in:
9
errors/now-dev-as-dev-script.md
Normal file
9
errors/now-dev-as-dev-script.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# `now dev` as `dev` script
|
||||
|
||||
#### Why This Error Occurred
|
||||
|
||||
The `package.json` file of the used project invokes `now dev` as `dev` script. This would cause `now dev` to recursively invoke itself.
|
||||
|
||||
#### Possible Ways to Fix It
|
||||
|
||||
Adjust the `dev` script inside the `package.json` file to match what your framework uses to begin development mode, e.g. `next` for Next.js or `gatsby develop` for Gatsby.
|
||||
@@ -24,7 +24,7 @@ export default async function dev(
|
||||
);
|
||||
|
||||
const [dir = '.'] = args;
|
||||
const cwd = path.join(process.cwd(), dir);
|
||||
const cwd = path.resolve(dir);
|
||||
const port = opts['-p'] || opts['--port'];
|
||||
const debug = opts['-d'] || opts['--debug'];
|
||||
const devServer = new DevServer(cwd, { output, debug });
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
import path from 'path';
|
||||
import chalk from 'chalk';
|
||||
|
||||
import getArgs from '../../util/get-args';
|
||||
import getSubcommand from '../../util/get-subcommand';
|
||||
import { NowContext } from '../../types';
|
||||
import { NowContext, Config } from '../../types';
|
||||
import { NowError } from '../../util/now-error';
|
||||
import handleError from '../../util/handle-error';
|
||||
import createOutput from '../../util/output/create-output';
|
||||
import logo from '../../util/output/logo';
|
||||
import cmd from '../../util/output/cmd';
|
||||
import dev from './dev';
|
||||
import readPackage from '../../util/read-package'
|
||||
import readPackage from '../../util/read-package';
|
||||
import { Package } from '../../util/dev/types';
|
||||
import readConfig from '../../util/config/read-config';
|
||||
|
||||
const COMMAND_CONFIG = {
|
||||
dev: ['dev']
|
||||
@@ -58,15 +60,25 @@ export default async function main(ctx: NowContext) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
const pkg = await readPackage();
|
||||
const [dir = '.'] = args;
|
||||
|
||||
const nowJson = await readConfig(path.join(dir, 'now.json'));
|
||||
// @ts-ignore: Because `nowJson` could be one of three different types
|
||||
const hasBuilds = nowJson && nowJson.builds && nowJson.builds.length > 0;
|
||||
|
||||
if (!nowJson || !hasBuilds) {
|
||||
const pkg = await readPackage(path.join(dir, 'package.json'));
|
||||
|
||||
if (pkg) {
|
||||
const { scripts } = pkg as Package;
|
||||
|
||||
if (scripts && scripts.dev && /\bnow\b\W+\bdev\b/.test(scripts.dev)) {
|
||||
output.error(`The ${cmd('dev')} script in ${cmd('package.json')} must not contain ${cmd('now dev')}`);
|
||||
output.error(`More details: http://err.sh/now-cli/now-dev-as-dev-script`);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (argv._.length > 2) {
|
||||
output.error(`${cmd('now dev [dir]')} accepts at most one argument`);
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { NowConfig } from './util/dev/types';
|
||||
|
||||
export type ThenArg<T> = T extends Promise<infer U> ? U : T;
|
||||
|
||||
export interface Config {
|
||||
export interface Config extends NowConfig {
|
||||
alias?: string[] | string;
|
||||
aliases?: string[] | string;
|
||||
name?: string;
|
||||
|
||||
20
src/util/config/read-config.ts
Normal file
20
src/util/config/read-config.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import path from 'path';
|
||||
import { CantParseJSONFile } from '../errors-ts';
|
||||
import readJSONFile from '../read-json-file';
|
||||
import { Config } from '../../types';
|
||||
import getLocalConfigPath from './local-path';
|
||||
|
||||
export default async function readConfig(file?: string) {
|
||||
const pkgFilePath = file || getLocalConfigPath(process.cwd());
|
||||
const result = await readJSONFile(pkgFilePath);
|
||||
|
||||
if (result instanceof CantParseJSONFile) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (result) {
|
||||
return result as Config;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -11,14 +11,14 @@ type Package = {
|
||||
export default async function readPackage(file?: string) {
|
||||
const pkgFilePath = file || path.resolve(process.cwd(), 'package.json');
|
||||
const result = await readJSONFile(pkgFilePath);
|
||||
|
||||
if (result instanceof CantParseJSONFile) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (result !== null) {
|
||||
const pkg = result as Package;
|
||||
return pkg;
|
||||
if (result){
|
||||
return result as Package
|
||||
}
|
||||
|
||||
return result;
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -198,6 +198,13 @@ RUN echo $NONCE > /public/index.html
|
||||
'now-revert-alias-2': {
|
||||
'index.json': JSON.stringify({ name: 'now-revert-alias-2' }),
|
||||
'now.json': getRevertAliasConfigFile()
|
||||
},
|
||||
'now-dev-fail-dev-script': {
|
||||
'package.json': JSON.stringify({
|
||||
scripts: {
|
||||
dev: 'now dev'
|
||||
}
|
||||
}, null, 2)
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -31,6 +31,9 @@ const pickUrl = stdout => {
|
||||
return lines[lines.length - 1];
|
||||
};
|
||||
|
||||
const createFile = dest => fs.closeSync(fs.openSync(dest, 'w'));
|
||||
const createDirectory = dest => fs.mkdirSync(dest);
|
||||
|
||||
const waitForDeployment = async href => {
|
||||
// eslint-disable-next-line
|
||||
while (true) {
|
||||
@@ -1255,8 +1258,6 @@ test('try to deploy with non-existing team', async t => {
|
||||
t.true(stderr.includes(goal));
|
||||
});
|
||||
|
||||
const createFile = dest => fs.closeSync(fs.openSync(dest, 'w'));
|
||||
const createDirectory = dest => fs.mkdirSync(dest);
|
||||
const verifyExampleApollo = (cwd, dir) =>
|
||||
fs.existsSync(path.join(cwd, dir, 'package.json')) &&
|
||||
fs.existsSync(path.join(cwd, dir, 'now.json')) &&
|
||||
@@ -1426,6 +1427,14 @@ test('try to update now to canary', async t => {
|
||||
t.true(stdout.includes('canary'));
|
||||
});
|
||||
|
||||
test('fail `now dev` dev script without now.json', async t => {
|
||||
const deploymentPath = fixture('now-dev-fail-dev-script');
|
||||
const { code, stderr } = await execute(['dev', deploymentPath]);
|
||||
|
||||
t.is(code, 1);
|
||||
t.true(stderr.includes('must not contain `now dev`'), `Received instead: "${stderr}"`);
|
||||
});
|
||||
|
||||
test.after.always(async () => {
|
||||
// Make sure the token gets revoked
|
||||
await execa(binaryPath, ['logout', ...defaultArgs]);
|
||||
|
||||
Reference in New Issue
Block a user