Compare commits

..

6 Commits

Author SHA1 Message Date
Nathan Rajlich
624da9170d Publish Canary
- @vercel/frameworks@0.0.15-canary.5
 - @vercel/build-utils@2.3.2-canary.6
 - vercel@19.0.2-canary.16
 - @vercel/client@8.0.2-canary.3
 - @vercel/node@1.6.2-canary.6
2020-06-10 14:27:18 -07:00
Nathan Rajlich
fb5b013a03 [node] Force module: "commonjs" in startDevServer() (#4621)
This is a follow up to #4514 to handle the case where there is no
`tsconfig.json` closer to the entrypoint. This is likely the case when
`.js` files with ES Modules syntax are being used instead of `.ts`.
2020-06-10 14:26:28 -07:00
Mark Glagola
0a4bb53a58 [cli] Handle aliasWarning and bump to v13/now/deployments (#4605)
* Handle aliasWarning

* Pick best production project domain

* Fix currentTeam assignment

* Adds `https` url check to cli integration tests
2020-06-10 16:00:50 -05:00
Nathan Rajlich
2fbd9c78e3 [cli] Better errors for conflicting configuration files (#4612)
* [cli] Better errors for conflicting configuration files

Renders the link https://vercel.link/combining-old-and-new-config
for all conflicting config errors.

* Fix unit test

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-06-10 12:38:02 -07:00
Nathan Rajlich
1ed2b7a57d [cli] Update @vercel/next to v2.6.5 (#4611)
It got out of sync somehow in 55c60d30e6.
2020-06-10 03:37:58 +00:00
Nathan Rajlich
88cd9ca3c3 [cli] Invalidate build match for changes to config in builds (#4603)
* Fixes changing a `config` value in the `builds` array (such as `helpers: false` for `@vercel/node`) and having it be reflected in `vc dev` without restarting the dev server.
* Re-validates the env vars configuration when a `.env` file changes or the `env` object is changed in `vercel.json` (same for the builds equivalents).
* Ensures that the `NODEJS_HELPERS` build env var is being properly checked in `startDevServer()`.
* Regenerated the `yarn.lock` file because yarn was erroring when trying to add the `fast-deep-equal` dependency.
2020-06-09 19:56:55 +00:00
33 changed files with 6092 additions and 164 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/frameworks",
"version": "0.0.15-canary.4",
"version": "0.0.15-canary.5",
"main": "frameworks.json",
"license": "UNLICENSED",
"scripts": {
@@ -9,7 +9,7 @@
"devDependencies": {
"@types/jest": "24.0.22",
"@types/node": "12.0.4",
"ajv": "6.10.2",
"ajv": "6.12.2",
"jest": "24.9.0",
"ts-jest": "24.1.0",
"typescript": "3.9.3"

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/build-utils",
"version": "2.3.2-canary.5",
"version": "2.3.2-canary.6",
"license": "MIT",
"main": "./dist/index.js",
"types": "./dist/index.d.js",

View File

@@ -27,6 +27,7 @@ import {
getLatestNodeVersion,
getDiscontinuedNodeVersions,
} from './fs/node-version';
import { NowBuildError } from './errors';
import streamToBuffer from './fs/stream-to-buffer';
import shouldServe from './should-serve';
import debug from './debug';
@@ -111,9 +112,11 @@ export const getPlatformEnv = (name: string): string | undefined => {
const n = process.env[nName];
if (typeof v === 'string') {
if (typeof n === 'string') {
throw new Error(
`Both "${vName}" and "${nName}" env vars are defined. Please only define the "${vName}" env var`
);
throw new NowBuildError({
code: 'CONFLICTING_ENV_VAR_NAMES',
message: `Both "${vName}" and "${nName}" env vars are defined. Please only define the "${vName}" env var.`,
link: 'https://vercel.link/combining-old-and-new-config',
});
}
return v;
}

View File

@@ -39,7 +39,7 @@ describe('Test `getPlatformEnv()`', () => {
assert(err);
assert.equal(
err!.message,
'Both "VERCEL_FOO" and "NOW_FOO" env vars are defined. Please only define the "VERCEL_FOO" env var'
'Both "VERCEL_FOO" and "NOW_FOO" env vars are defined. Please only define the "VERCEL_FOO" env var.'
);
});
});

View File

@@ -1,6 +1,6 @@
{
"name": "vercel",
"version": "19.0.2-canary.15",
"version": "19.0.2-canary.16",
"preferGlobal": true,
"license": "Apache-2.0",
"description": "The command-line interface for Now",
@@ -62,10 +62,10 @@
"node": ">= 10"
},
"dependencies": {
"@vercel/build-utils": "2.3.2-canary.5",
"@vercel/build-utils": "2.3.2-canary.6",
"@vercel/go": "1.1.2-canary.2",
"@vercel/next": "2.6.3-canary.6",
"@vercel/node": "1.6.2-canary.5",
"@vercel/next": "2.6.5",
"@vercel/node": "1.6.2-canary.6",
"@vercel/python": "1.2.2-canary.2",
"@vercel/ruby": "1.2.2-canary.1",
"@vercel/static-build": "0.17.2-canary.1"
@@ -106,7 +106,7 @@
"@zeit/fun": "0.11.2",
"@zeit/ncc": "0.18.5",
"@zeit/source-map-support": "0.6.2",
"ajv": "6.10.2",
"ajv": "6.12.2",
"alpha-sort": "2.0.1",
"ansi-escapes": "3.0.0",
"ansi-regex": "3.0.0",
@@ -136,6 +136,7 @@
"escape-html": "1.0.3",
"esm": "3.1.4",
"execa": "3.2.0",
"fast-deep-equal": "3.1.3",
"fs-extra": "7.0.1",
"get-port": "5.1.1",
"glob": "7.1.2",

View File

@@ -39,7 +39,6 @@ import {
} from '../../util/errors-ts';
import { SchemaValidationFailed } from '../../util/errors';
import purchaseDomainIfAvailable from '../../util/domains/purchase-domain-if-available';
import isWildcardAlias from '../../util/alias/is-wildcard-alias';
import confirm from '../../util/input/confirm';
import editProjectSettings from '../../util/input/edit-project-settings';
import {
@@ -56,6 +55,7 @@ import validatePaths, {
} from '../../util/validate-paths';
import { readLocalConfig } from '../../util/config/files';
import { getCommandName } from '../../util/pkg-name.ts';
import { getPreferredPreviewURL } from '../../util/deploy/get-preferred-preview-url.ts';
const addProcessEnv = async (log, env) => {
let val;
@@ -87,6 +87,7 @@ const addProcessEnv = async (log, env) => {
const printDeploymentStatus = async (
output,
client,
{
readyState,
alias: aliasList,
@@ -119,18 +120,14 @@ const printDeploymentStatus = async (
let previewUrl;
let isWildcard;
if (!isFile && Array.isArray(aliasList) && aliasList.length > 0) {
// search for a non now.sh/non wildcard domain
// but fallback to the first alias in the list
const mainAlias =
aliasList.find(
alias =>
!alias.endsWith('.now.sh') &&
!alias.endsWith('.vercel.app') &&
!isWildcardAlias(alias)
) || aliasList[0];
isWildcard = isWildcardAlias(mainAlias);
previewUrl = isWildcard ? mainAlias : `https://${mainAlias}`;
const previewUrlInfo = await getPreferredPreviewURL(client, aliasList);
if (previewUrlInfo) {
isWildcard = previewUrlInfo.isWildcard;
previewUrl = previewUrlInfo.previewUrl;
} else {
isWildcard = false;
previewUrl = `https://${deploymentUrl}`;
}
} else {
// fallback to deployment url
isWildcard = false;
@@ -706,6 +703,12 @@ export default async function main(
return printDeploymentStatus(
output,
new Client({
apiUrl: ctx.apiUrl,
token: ctx.authConfig.token,
currentTeam: org.type === 'team' ? org.id : null,
debug: debugEnabled,
}),
deployment,
deployStamp,
!argv['--no-clipboard'],

View File

@@ -24,6 +24,7 @@ import checkForUpdate from 'update-check';
import ms from 'ms';
import { URL } from 'url';
import * as Sentry from '@sentry/node';
import { NowBuildError } from '@vercel/build-utils';
import getGlobalPathConfig from './util/config/global-path';
import {
getDefaultConfig,
@@ -114,10 +115,10 @@ const main = async argv_ => {
}
if (
localConfig instanceof NowError &&
(localConfig instanceof NowError || localConfig instanceof NowBuildError) &&
!(localConfig instanceof ERRORS.CantFindConfig)
) {
output.error(`Failed to load local config file: ${localConfig.message}`);
output.prettyError(localConfig);
return 1;
}
@@ -644,27 +645,6 @@ const main = async argv_ => {
)} could not be resolved. Please verify your internet connectivity and DNS configuration.`
);
output.debug(err.stack);
return 1;
}
await reportError(Sentry, err, apiUrl, configFiles);
// If there is a code we should not consider the error unexpected
// but instead show the message. Any error that is handled by this should
// actually be handled in the sub command instead. Please make sure
// that happens for anything that lands here. It should NOT bubble up to here.
if (err.code) {
output.debug(err.stack);
output.error(err.message);
if (shouldCollectMetrics) {
metric
.event(eventCategory, '1', pkg.version)
.exception(err.message)
.send();
}
return 1;
}
@@ -675,9 +655,23 @@ const main = async argv_ => {
.send();
}
// Otherwise it is an unexpected error and we should show the trace
// and an unexpected error message
output.error(`An unexpected error occurred in ${subcommand}: ${err.stack}`);
// If there is a code we should not consider the error unexpected
// but instead show the message. Any error that is handled by this should
// actually be handled in the sub command instead. Please make sure
// that happens for anything that lands here. It should NOT bubble up to here.
if (err.code) {
output.debug(err.stack);
output.prettyError(err);
} else {
await reportError(Sentry, err, apiUrl, configFiles);
// Otherwise it is an unexpected error and we should show the trace
// and an unexpected error message
output.error(
`An unexpected error occurred in ${subcommand}: ${err.stack}`
);
}
return 1;
}
@@ -688,8 +682,6 @@ const main = async argv_ => {
return exitCode;
};
debug('start');
const handleRejection = async err => {
debug('handling rejection');

View File

@@ -0,0 +1,17 @@
import { stringify } from 'querystring';
import { Cert } from '../../types';
import Client from '../client';
/**
* Returns certs that contain @param cn.
*/
export async function getCertsForCn(
client: Client,
cn: string,
{ limit }: { limit?: number } = {}
) {
const { certs } = await client.fetch<{
certs: Cert[];
}>(`/v4/now/certs?${stringify({ cn, ...(limit ? { limit } : {}) })}`);
return certs;
}

View File

@@ -24,7 +24,7 @@ export default class Client extends EventEmitter {
_withCache: boolean;
_output: Output;
_token: string;
currentTeam?: string;
currentTeam?: string | null;
constructor({
apiUrl,
@@ -36,7 +36,7 @@ export default class Client extends EventEmitter {
}: {
apiUrl: string;
token: string;
currentTeam?: string;
currentTeam?: string | null;
forceNew?: boolean;
withCache?: boolean;
debug?: boolean;

View File

@@ -0,0 +1,48 @@
import isWildcardAlias from '../alias/is-wildcard-alias';
import { getCertsForCn } from '../certs/get-certs-for-cn';
import Client from '../client';
/**
* Tries to find the "best" alias url.
* @param aliasList
*/
export async function getPreferredPreviewURL(
client: Client,
aliasList: string[]
) {
if (aliasList.length === 0) {
return null;
}
/**
* First checks for non public aliases and non wildcard domains.
*/
const preferredAliases = aliasList.filter(
alias =>
!alias.endsWith('.now.sh') &&
!alias.endsWith('.vercel.app') &&
!isWildcardAlias(alias)
);
for (const alias of preferredAliases) {
const certs = await getCertsForCn(client, alias, { limit: 1 }).catch(() => {
return null;
});
if (certs && certs.length > 0) {
return { previewUrl: `https://${alias}`, isWildcard: false };
}
}
/**
* Fallback to first alias
*/
const [firstAlias] = aliasList;
if (isWildcardAlias(firstAlias)) {
return { previewUrl: firstAlias, isWildcard: true };
}
if (firstAlias.endsWith('.vercel.app') || firstAlias.endsWith('.now.sh')) {
return { previewUrl: `https://${firstAlias}`, isWildcard: false };
}
return { previewUrl: `http://${firstAlias}`, isWildcard: false };
}

View File

@@ -18,6 +18,7 @@ import directoryTemplate from 'serve-handler/src/directory';
import getPort from 'get-port';
import { ChildProcess } from 'child_process';
import isPortReachable from 'is-port-reachable';
import deepEqual from 'fast-deep-equal';
import which from 'which';
import { getVercelIgnore, fileNameSymbol } from '@vercel/client';
@@ -234,8 +235,18 @@ export default class DevServer {
}
}
// Update the build matches in case an entrypoint was created or deleted
const nowConfig = await this.getNowConfig(false);
// Update the env vars configuration
const nowConfigBuild = nowConfig.build || {};
const [runEnv, buildEnv] = await Promise.all([
this.getLocalEnv('.env', nowConfig.env),
this.getLocalEnv('.env.build', nowConfigBuild.env),
]);
const allEnv = { ...buildEnv, ...runEnv };
this.envConfigs = { buildEnv, runEnv, allEnv };
// Update the build matches in case an entrypoint was created or deleted
await this.updateBuildMatches(nowConfig);
const filesChangedArray = [...filesChanged];
@@ -400,7 +411,7 @@ export default class DevServer {
const blockingBuilds: Promise<void>[] = [];
for (const match of matches) {
const currentMatch = this.buildMatches.get(match.src);
if (!currentMatch || currentMatch.use !== match.use) {
if (!buildMatchEquals(currentMatch, match)) {
this.output.debug(
`Adding build match for "${match.src}" with "${match.use}"`
);
@@ -2261,3 +2272,11 @@ function hasNewRoutingProperties(nowConfig: NowConfig) {
typeof nowConfig.trailingSlash !== undefined
);
}
function buildMatchEquals(a?: BuildMatch, b?: BuildMatch): boolean {
if (!a || !b) return false;
if (a.src !== b.src) return false;
if (a.use !== b.use) return false;
if (!deepEqual(a.config || {}, b.config || {})) return false;
return true;
}

View File

@@ -1,5 +1,6 @@
import bytes from 'bytes';
import { Response } from 'node-fetch';
import { NowBuildError } from '@vercel/build-utils';
import { NowError } from './now-error';
import code from './output/code';
import { getCommandName } from './pkg-name';
@@ -771,17 +772,17 @@ export class CantParseJSONFile extends NowError<
}
}
export class ConflictingConfigFiles extends NowError<
'CONFLICTING_CONFIG_FILES',
{ files: string[] }
> {
export class ConflictingConfigFiles extends NowBuildError {
files: string[];
constructor(files: string[]) {
super({
code: 'CONFLICTING_CONFIG_FILES',
meta: { files },
message:
'Cannot use both a `vercel.json` and `now.json` file. Please delete the `now.json` file.',
link: 'https://vercel.link/combining-old-and-new-config',
});
this.files = files;
}
}

View File

@@ -1,6 +1,7 @@
import chalk from 'chalk';
import { metrics, shouldCollectMetrics } from '../metrics';
import { APIError } from '../errors-ts';
import renderLink from './link';
const metric = metrics();
@@ -9,10 +10,9 @@ export default function error(...input: string[] | [APIError]) {
if (typeof input[0] === 'object') {
const { slug, message, link } = input[0];
messages = [message];
if (slug) {
messages.push(`> More details: https://err.sh/now/${slug}`);
} else if (link) {
messages.push(`> More details: ${link}`);
const details = slug ? `https://err.sh/now/${slug}` : link;
if (details) {
messages.push(`${chalk.bold('More details')}: ${renderLink(details)}`);
}
}

View File

@@ -14,7 +14,7 @@ import chalk from 'chalk';
import { prependEmoji, emoji } from '../emoji';
import AJV from 'ajv';
import { isDirectory } from '../config/global-path';
import { getPlatformEnv } from '@vercel/build-utils';
import { NowBuildError, getPlatformEnv } from '@vercel/build-utils';
const readFile = promisify(fs.readFile);
const writeFile = promisify(fs.writeFile);
@@ -49,9 +49,12 @@ export function getVercelDirectory(cwd: string = process.cwd()): string {
const possibleDirs = [join(cwd, VERCEL_DIR), join(cwd, VERCEL_DIR_FALLBACK)];
const existingDirs = possibleDirs.filter(d => isDirectory(d));
if (existingDirs.length > 1) {
throw new Error(
'Both `.vercel` and `.now` directories exist. Please remove the `.now` directory.'
);
throw new NowBuildError({
code: 'CONFLICTING_CONFIG_DIRECTORIES',
message:
'Both `.vercel` and `.now` directories exist. Please remove the `.now` directory.',
link: 'https://vercel.link/combining-old-and-new-config',
});
}
return existingDirs[0] || possibleDirs[0];
}

View File

@@ -0,0 +1 @@
.vercel

View File

@@ -0,0 +1,3 @@
export default function(req, res) {
res.end('Force "module: commonjs" JavaScript with ES Modules API endpoint');
}

View File

@@ -0,0 +1,5 @@
import { IncomingMessage, ServerResponse } from 'http';
export default function(req: IncomingMessage, res: ServerResponse) {
res.end('Force "module: commonjs" TypeScript API endpoint');
}

View File

@@ -0,0 +1,2 @@
/// <reference types="next" />
/// <reference types="next/types/global" />

View File

@@ -0,0 +1,19 @@
{
"name": "force-module-commonjs",
"private": true,
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
},
"dependencies": {
"next": "^9.3.4",
"react": "^16.13.1",
"react-dom": "^16.13.1"
},
"devDependencies": {
"@types/node": "14.0.9",
"@types/react": "^16.9.32",
"typescript": "^3.8.3"
}
}

View File

@@ -0,0 +1,3 @@
export default function () {
return <div>Force "module: commonjs" test page</div>;
}

View File

@@ -0,0 +1,25 @@
{
"compilerOptions": {
"baseUrl": ".",
"target": "esnext",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"paths": {
"@components/*": ["components/*"],
"@lib/*": ["lib/*"]
}
},
"exclude": ["node_modules", "api"],
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,10 @@
export default (req, res) => {
const hasHelpers = typeof req.query !== 'undefined';
res.setHeader('Content-Type', 'application/json');
res.end(
JSON.stringify({
hasHelpers,
query: req.query,
})
);
};

View File

@@ -0,0 +1 @@
{ "builds": [{ "src": "index.js", "use": "@vercel/node@canary" }] }

View File

@@ -161,7 +161,7 @@ async function testPath(
Object.entries(headers).forEach(([key, expectedValue]) => {
let actualValue = res.headers.get(key);
if (key.toLowerCase() === 'location' && actualValue === '//') {
// HACK: `node-fetch` has strang behavior for location header so fix it
// HACK: `node-fetch` has strange behavior for location header so fix it
// with `manual-dont-change` opt and convert double slash to single.
// See https://github.com/node-fetch/node-fetch/issues/417#issuecomment-587233352
actualValue = '/';
@@ -187,20 +187,29 @@ async function testFixture(directory, opts = {}, args = []) {
}
);
const stdoutList = [];
const stderrList = [];
let stdout = '';
let stderr = '';
const readyResolver = createResolver();
const exitResolver = createResolver();
dev.stderr.on('data', data => stderrList.push(Buffer.from(data)));
dev.stdout.on('data', data => stdoutList.push(Buffer.from(data)));
dev.stdout.setEncoding('utf8');
dev.stderr.setEncoding('utf8');
dev.stdout.on('data', data => {
stdout += data;
});
dev.stderr.on('data', data => {
stderr += data;
if (stderr.includes('Ready! Available at')) {
readyResolver.resolve();
}
});
let printedOutput = false;
dev.on('exit', () => {
if (!printedOutput) {
const stdout = Buffer.concat(stdoutList).toString();
const stderr = Buffer.concat(stderrList).toString();
printOutput(directory, stdout, stderr);
printedOutput = true;
}
@@ -209,8 +218,6 @@ async function testFixture(directory, opts = {}, args = []) {
dev.on('error', () => {
if (!printedOutput) {
const stdout = Buffer.concat(stdoutList).toString();
const stderr = Buffer.concat(stderrList).toString();
printOutput(directory, stdout, stderr);
printedOutput = true;
}
@@ -226,6 +233,7 @@ async function testFixture(directory, opts = {}, args = []) {
return {
dev,
port,
readyResolver,
};
}
@@ -267,14 +275,12 @@ function testFixtureStdio(
await runNpmInstall(cwd);
const stdoutList = [];
const stderrList = [];
let stdout = '';
let stderr = '';
const readyResolver = createResolver();
const exitResolver = createResolver();
try {
let stderr = '';
let printedOutput = false;
const env = skipDeploy
@@ -285,17 +291,19 @@ function testFixtureStdio(
env,
});
dev.stdout.setEncoding('utf8');
dev.stderr.setEncoding('utf8');
dev.stdout.pipe(process.stdout);
dev.stderr.pipe(process.stderr);
dev.stdout.on('data', data => {
stdoutList.push(data);
stdout += data;
});
dev.stderr.on('data', data => {
stderrList.push(data);
stderr += data;
stderr += data.toString();
if (stderr.includes('Ready! Available at')) {
readyResolver.resolve();
}
@@ -315,8 +323,6 @@ function testFixtureStdio(
dev.on('exit', () => {
if (!printedOutput) {
const stdout = Buffer.concat(stdoutList).toString();
const stderr = Buffer.concat(stderrList).toString();
printOutput(directory, stdout, stderr);
printedOutput = true;
}
@@ -325,8 +331,6 @@ function testFixtureStdio(
dev.on('error', () => {
if (!printedOutput) {
const stdout = Buffer.concat(stdoutList).toString();
const stderr = Buffer.concat(stderrList).toString();
printOutput(directory, stdout, stderr);
printedOutput = true;
}
@@ -385,6 +389,110 @@ test('[vercel dev] prints `npm install` errors', async t => {
t.truthy(result.stderr.includes('https://vercel.link/npm-install-error'));
});
test('[vercel dev] reflects changes to config and env without restart', async t => {
const dir = fixture('node-helpers');
const configPath = join(dir, 'vercel.json');
const originalConfig = await fs.readJSON(configPath);
const { dev, port, readyResolver } = await testFixture(dir);
try {
await readyResolver;
{
// Node.js helpers should be available by default
const res = await fetch(`http://localhost:${port}/?foo=bar`);
const body = await res.json();
t.is(body.hasHelpers, true);
t.is(body.query.foo, 'bar');
}
{
// Disable the helpers via `config.helpers = false`
const config = {
...originalConfig,
builds: [
{
...originalConfig.builds[0],
config: {
helpers: false,
},
},
],
};
await fs.writeJSON(configPath, config);
await sleep(1000);
const res = await fetch(`http://localhost:${port}/?foo=bar`);
const body = await res.json();
t.is(body.hasHelpers, false);
t.is(body.query, undefined);
}
{
// Enable the helpers via `config.helpers = true`
const config = {
...originalConfig,
builds: [
{
...originalConfig.builds[0],
config: {
helpers: true,
},
},
],
};
await fs.writeJSON(configPath, config);
await sleep(1000);
const res = await fetch(`http://localhost:${port}/?foo=baz`);
const body = await res.json();
t.is(body.hasHelpers, true);
t.is(body.query.foo, 'baz');
}
{
// Disable the helpers via `NODEJS_HELPERS = '0'`
const config = {
...originalConfig,
build: {
env: {
NODEJS_HELPERS: '0',
},
},
};
await fs.writeJSON(configPath, config);
await sleep(1000);
const res = await fetch(`http://localhost:${port}/?foo=baz`);
const body = await res.json();
t.is(body.hasHelpers, false);
t.is(body.query, undefined);
}
{
// Enable the helpers via `NODEJS_HELPERS = '1'`
const config = {
...originalConfig,
build: {
env: {
NODEJS_HELPERS: '1',
},
},
};
await fs.writeJSON(configPath, config);
await sleep(1000);
const res = await fetch(`http://localhost:${port}/?foo=boo`);
const body = await res.json();
t.is(body.hasHelpers, true);
t.is(body.query.foo, 'boo');
}
} finally {
await dev.kill('SIGTERM');
await fs.writeJSON(configPath, originalConfig);
}
});
test(
'[vercel dev] validate routes that use `check: true`',
testFixtureStdio('routes-check-true', async testPath => {
@@ -1401,6 +1509,23 @@ test(
})
);
test(
'[vercel dev] Should force `tsc` option "module: commonjs" for `startDevServer()`',
testFixtureStdio('force-module-commonjs', async testPath => {
await testPath(200, `/`, /Force &quot;module: commonjs&quot; test page/);
await testPath(
200,
`/api`,
'Force "module: commonjs" JavaScript with ES Modules API endpoint'
);
await testPath(
200,
`/api/ts`,
'Force "module: commonjs" TypeScript API endpoint'
);
})
);
test(
'[vercel dev] should prioritize index.html over other file named index.*',
testFixtureStdio('index-html-priority', async testPath => {

View File

@@ -1589,7 +1589,7 @@ test('create a staging deployment', async t => {
/Setting target to staging/gm,
formatOutput(targetCall)
);
t.regex(targetCall.stdout, /https:\/\//gm);
t.is(targetCall.exitCode, 0, formatOutput(targetCall));
const { host } = new URL(targetCall.stdout);
@@ -1625,6 +1625,7 @@ test('create a production deployment', async t => {
/Setting target to production/gm,
formatOutput(targetCall)
);
t.regex(targetCall.stdout, /https:\/\//gm);
const { host: targetHost } = new URL(targetCall.stdout);
const targetDeployment = await apiFetch(
@@ -1648,6 +1649,7 @@ test('create a production deployment', async t => {
/Setting target to production/gm,
formatOutput(targetCall)
);
t.regex(call.stdout, /https:\/\//gm);
const { host } = new URL(call.stdout);
const deployment = await apiFetch(

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/client",
"version": "8.0.2-canary.2",
"version": "8.0.2-canary.3",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"homepage": "https://vercel.com",

View File

@@ -93,6 +93,16 @@ export async function* checkDeploymentStatus(
}
if (isAliasAssigned(deploymentUpdate)) {
if (
deploymentUpdate.aliasWarning &&
deploymentUpdate.aliasWarning.message
) {
yield {
type: 'warning',
payload: deploymentUpdate.aliasWarning.message,
};
}
debug('Deployment alias assigned');
return yield { type: 'alias-assigned', payload: deploymentUpdate };
}

View File

@@ -7,6 +7,7 @@ import qs from 'querystring';
import ignore from 'ignore';
type Ignore = ReturnType<typeof ignore>;
import { pkgVersion } from '../pkg';
import { NowBuildError } from '@vercel/build-utils';
import { NowClientOptions, DeploymentOptions, NowConfig } from '../types';
import { Sema } from 'async-sema';
import { readFile } from 'fs-extra';
@@ -48,7 +49,7 @@ export function getApiDeploymentsUrl(
return '/v10/now/deployments';
}
return '/v12/now/deployments';
return '/v13/now/deployments';
}
export async function parseVercelConfig(filePath?: string): Promise<NowConfig> {
@@ -166,9 +167,12 @@ export async function getVercelIgnore(
maybeRead(join(cwd, '.nowignore'), ''),
]);
if (vercelignore && nowignore) {
throw new Error(
'Cannot use both a `.vercelignore` and `.nowignore` file. Please delete the `.nowignore` file.'
);
throw new NowBuildError({
code: 'CONFLICTING_IGNORE_FILES',
message:
'Cannot use both a `.vercelignore` and `.nowignore` file. Please delete the `.nowignore` file.',
link: 'https://vercel.link/combining-old-and-new-config',
});
}
return vercelignore || nowignore;
})

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/node",
"version": "1.6.2-canary.5",
"version": "1.6.2-canary.6",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/node-js",

View File

@@ -1,11 +1,11 @@
const entrypoint = process.env.NOW_DEV_ENTRYPOINT;
delete process.env.NOW_DEV_ENTRYPOINT;
const entrypoint = process.env.VERCEL_DEV_ENTRYPOINT;
delete process.env.VERCEL_DEV_ENTRYPOINT;
const tsconfig = process.env.NOW_DEV_TSCONFIG;
delete process.env.NOW_DEV_TSCONFIG;
const tsconfig = process.env.VERCEL_DEV_TSCONFIG;
delete process.env.VERCEL_DEV_TSCONFIG;
if (!entrypoint) {
throw new Error('`NOW_DEV_ENTRYPOINT` must be defined');
throw new Error('`VERCEL_DEV_ENTRYPOINT` must be defined');
}
import { register } from 'ts-node';
@@ -27,6 +27,7 @@ register({
allowJs: true,
esModuleInterop: true,
jsx: 'react',
module: 'commonjs',
},
project: tsconfig || undefined, // Resolve `tsconfig.json` from entrypoint dir
transpileOnly: true,
@@ -49,11 +50,14 @@ function listen(server: Server, port: number, host: string): Promise<void> {
let bridge: Bridge | undefined = undefined;
async function main() {
const config = JSON.parse(process.env.NOW_DEV_CONFIG || '{}');
delete process.env.NOW_DEV_CONFIG;
const config = JSON.parse(process.env.VERCEL_DEV_CONFIG || '{}');
delete process.env.VERCEL_DEV_CONFIG;
const buildEnv = JSON.parse(process.env.VERCEL_DEV_BUILD_ENV || '{}');
delete process.env.VERCEL_DEV_BUILD_ENV;
const shouldAddHelpers = !(
config.helpers === false || process.env.NODEJS_HELPERS === '0'
config.helpers === false || buildEnv.NODEJS_HELPERS === '0'
);
bridge = getNowLauncher({

View File

@@ -445,9 +445,10 @@ export async function startDevServer(
env: {
...process.env,
...meta.env,
NOW_DEV_ENTRYPOINT: entrypoint,
NOW_DEV_TSCONFIG: projectTsConfig || '',
NOW_DEV_CONFIG: JSON.stringify(config),
VERCEL_DEV_ENTRYPOINT: entrypoint,
VERCEL_DEV_TSCONFIG: projectTsConfig || '',
VERCEL_DEV_CONFIG: JSON.stringify(config),
VERCEL_DEV_BUILD_ENV: JSON.stringify(meta.buildEnv || {}),
},
});

103
yarn.lock
View File

@@ -1402,9 +1402,9 @@
"@types/node" ">= 8"
"@octokit/types@^4.0.1":
version "4.1.5"
resolved "https://registry.yarnpkg.com/@octokit/types/-/types-4.1.5.tgz#465872f9f5f5e6bb85c6ed763053486bba9b251b"
integrity sha512-/MKeipxtwMorckj1bfP+SKhbzKhqQimT5JuXKGtwnLazqDwj/noYYSPChpLzstVAwF8JVPygJ7L75cKCK47Ikg==
version "4.1.9"
resolved "https://registry.yarnpkg.com/@octokit/types/-/types-4.1.9.tgz#a3e1ff1a15637ab830fbab0268c2d7ca824bc969"
integrity sha512-hinM/BA2c1vebN2HSR3JtVdYtrSbmvn/doUBZXXuQuh/9o60hYwitQQAGTpJu+k6pjtjURskDHQxUFvqLvYCeA==
dependencies:
"@types/node" ">= 8"
@@ -1485,9 +1485,9 @@
escape-string-regexp "^2.0.0"
"@sindresorhus/transliterate@^0.1.0":
version "0.1.0"
resolved "https://registry.yarnpkg.com/@sindresorhus/transliterate/-/transliterate-0.1.0.tgz#c063bfc4102783fb19c91c2f8c1efb3adfb754be"
integrity sha512-bO6v0M0EuJPjm5Ntfow4nk+r3EZQ41n0ahvAmh766FzPqlm6V/2uDc01vZI3gLeI/1lgV2BTMb6QvxOk9z73ng==
version "0.1.1"
resolved "https://registry.yarnpkg.com/@sindresorhus/transliterate/-/transliterate-0.1.1.tgz#779b31244781d3c898f185b61d58c89e7c782674"
integrity sha512-QSdIQ5keUFAZ3KLbfbsntW39ox0Ym8183RqTwBq/ZEFoN3NQAtGV+qWaNdzKpIDHgj9J2CQ2iNDRVU11Zyr7MQ==
dependencies:
escape-string-regexp "^2.0.0"
lodash.deburr "^4.1.0"
@@ -1731,7 +1731,7 @@
dependencies:
"@types/node" "*"
"@types/glob@7.1.1", "@types/glob@^7.1.1":
"@types/glob@7.1.1":
version "7.1.1"
resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575"
integrity sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==
@@ -1740,6 +1740,14 @@
"@types/minimatch" "*"
"@types/node" "*"
"@types/glob@^7.1.1":
version "7.1.2"
resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.2.tgz#06ca26521353a545d94a0adc74f38a59d232c987"
integrity sha512-VgNIkxK+j7Nz5P7jvUZlRvhuPSmsEfS03b0alKcq5V/STUKAa3Plemsn5mrQUO7am6OErJ4rhGEGJbACclrtRA==
dependencies:
"@types/minimatch" "*"
"@types/node" "*"
"@types/http-proxy@1.16.2":
version "1.16.2"
resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.16.2.tgz#16cb373b52fff2aa2f389d23d940ed4a642349e5"
@@ -1892,9 +1900,9 @@
form-data "^3.0.0"
"@types/node@*", "@types/node@>= 8":
version "14.0.9"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.9.tgz#43896ab87fc82bda1dfd600cdf44a0c8a64e11d2"
integrity sha512-0sCTiXKXELOBxvZLN4krQ0FPOAA7ij+6WwvD0k/PHd9/KAkr4dXel5J9fh6F4x1FwAQILqAWkmpeuS6mjf1iKA==
version "14.0.12"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.12.tgz#9c1d8ffb8084e8936603a6122a7649e40e68e04b"
integrity sha512-/sjzehvjkkpvLpYtN6/2dv5kg41otMGuHQUt9T2aiAuIfleCQRQHXXzF1eAw/qkZTj5Kcf4JSTf7EIizHocy6Q==
"@types/node@10.12.18":
version "10.12.18"
@@ -1902,9 +1910,9 @@
integrity sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==
"@types/node@10.x":
version "10.17.24"
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.24.tgz#c57511e3a19c4b5e9692bb2995c40a3a52167944"
integrity sha512-5SCfvCxV74kzR3uWgTYiGxrd69TbT1I6+cMx1A5kEly/IVveJBimtAMlXiEyVFn5DvUFewQWxOOiJhlxeQwxgA==
version "10.17.25"
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.25.tgz#64f64cd3e8641e8163c81045e545d2825d300e37"
integrity sha512-EWPw3jDB0jip4HafDkoezNOwG00TtVZ1TOe74MaxIBWgpyM60UF/LXzFVx9+8AdSYNNOPgx7TuJoRmgnhHZ/7g==
"@types/node@11.11.0":
version "11.11.0"
@@ -2429,17 +2437,7 @@ aggregate-error@3.0.1, aggregate-error@^3.0.0:
clean-stack "^2.0.0"
indent-string "^4.0.0"
ajv@6.10.2:
version "6.10.2"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52"
integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==
dependencies:
fast-deep-equal "^2.0.1"
fast-json-stable-stringify "^2.0.0"
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
ajv@^6.0.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5:
ajv@6.12.2, ajv@^6.0.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5:
version "6.12.2"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.2.tgz#c629c5eced17baf314437918d2da88c99d5958cd"
integrity sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==
@@ -4614,9 +4612,9 @@ escape-string-regexp@^2.0.0:
integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==
escodegen@^1.9.1:
version "1.14.1"
resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.1.tgz#ba01d0c8278b5e95a9a45350142026659027a457"
integrity sha512-Bmt7NcRySdIfNPfU2ZoXDrrXsG9ZjvDxcAlMfDUgRBjLOWTuIACXPBFJH7Z+cLb40JeQco5toikyc9t9P8E9SQ==
version "1.14.2"
resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.2.tgz#14ab71bf5026c2aa08173afba22c6f3173284a84"
integrity sha512-InuOIiKk8wwuOFg6x9BQXbzjrQhtyXh46K9bqVTPzSo2FnyMBaYGBMC6PhQy7yxxil9vIedFBweQBMK74/7o8A==
dependencies:
esprima "^4.0.1"
estraverse "^4.2.0"
@@ -4648,9 +4646,9 @@ eslint-scope@^4.0.0:
estraverse "^4.1.1"
eslint-scope@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9"
integrity sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==
version "5.1.0"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.0.tgz#d0f971dfe59c69e0cada684b23d49dbf82600ce5"
integrity sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==
dependencies:
esrecurse "^4.1.0"
estraverse "^4.1.1"
@@ -4670,9 +4668,9 @@ eslint-utils@^2.0.0:
eslint-visitor-keys "^1.1.0"
eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2"
integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==
version "1.2.0"
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.2.0.tgz#74415ac884874495f78ec2a97349525344c981fa"
integrity sha512-WFb4ihckKil6hu3Dp798xdzSfddwKKU3+nGniKF6HfeW6OLd2OUDEPP7TcHtB5+QXOKg2s6B2DaMPE1Nn/kxKQ==
eslint@6.2.2:
version "6.2.2"
@@ -4995,15 +4993,10 @@ extsprintf@^1.2.0:
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
fast-deep-equal@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=
fast-deep-equal@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4"
integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==
fast-deep-equal@3.1.3, fast-deep-equal@^3.1.1:
version "3.1.3"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
fast-diff@^1.1.2:
version "1.2.0"
@@ -6506,11 +6499,11 @@ is-promise@^2.1.0:
integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==
is-regex@^1.0.4, is-regex@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae"
integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.0.tgz#ece38e389e490df0dc21caea2bd596f987f767ff"
integrity sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==
dependencies:
has "^1.0.3"
has-symbols "^1.0.1"
is-regexp@^1.0.0:
version "1.0.0"
@@ -7838,9 +7831,9 @@ merge-stream@^2.0.0:
integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
merge2@^1.2.3, merge2@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81"
integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==
version "1.4.1"
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
micro@9.1.2:
version "9.1.2"
@@ -9536,9 +9529,9 @@ regenerate-unicode-properties@^8.2.0:
regenerate "^1.4.0"
regenerate@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11"
integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==
version "1.4.1"
resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.1.tgz#cad92ad8e6b591773485fbe05a485caf4f457e6f"
integrity sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A==
regex-not@^1.0.0, regex-not@^1.0.2:
version "1.0.2"
@@ -11522,9 +11515,9 @@ widest-line@^3.1.0:
string-width "^4.0.0"
windows-release@^3.1.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-3.3.0.tgz#dce167e9f8be733f21c849ebd4d03fe66b29b9f0"
integrity sha512-2HetyTg1Y+R+rUgrKeUEhAG/ZuOmTrI1NBb3ZyAGQMYmOJjBBPe4MTodghRkmLJZHwkuPi02anbeGP+Zf401LQ==
version "3.3.1"
resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-3.3.1.tgz#cb4e80385f8550f709727287bf71035e209c4ace"
integrity sha512-Pngk/RDCaI/DkuHPlGTdIkDiTAnAkyMjoQMZqRsxydNl1qGXNIoZrB7RK8g53F2tEgQBMqQJHQdYZuQEEAu54A==
dependencies:
execa "^1.0.0"