Compare commits

...

16 Commits

Author SHA1 Message Date
Steven
981e4183c6 Publish Stable
- @vercel/build-utils@2.5.4
 - vercel@20.1.2
 - @vercel/client@9.0.3
 - @vercel/node@1.8.4
 - @vercel/routing-utils@1.9.0
2020-10-08 09:10:16 -04:00
Steven
1706a00cb9 Publish Canary
- @vercel/build-utils@2.5.4-canary.0
 - vercel@20.1.2-canary.5
 - @vercel/client@9.0.3-canary.0
2020-10-06 09:10:41 -04:00
Steven
d7bd03cf1d [build-utils] Fix framework "CRA" when Next.js is dependency (#5246)
Fixes https://github.com/vercel/vercel/discussions/4288#discussioncomment-88998

This was fixed when "Framework: Other" in #5009 but this PR fixes it when "Framework: CRA" or any framework selection.
2020-10-06 13:09:02 +00:00
dav-is
e27ff8d2e0 Publish Canary
- vercel@20.1.2-canary.4
2020-10-05 18:14:54 -04:00
RAJPRAKASH
bc6da39cc2 [examples] Fix link to gatsby live example (#5205)
Fixes the link in the gatsby example back to the repo.

Co-authored-by: Steven <steven@ceriously.com>
2020-10-05 18:08:29 -04:00
dav-is
727109c64a Publish Canary
- @vercel/routing-utils@1.8.5-canary.0
2020-10-05 18:03:21 -04:00
Connor Davis
817410a8e2 [routing-utils] Add locale to routes schema (#5259)
We need to add a `locale` property to `routes`: CH-12345, CH-12349
2020-10-05 21:25:21 +00:00
Steven
e022e7b79c Publish Canary
- vercel@20.1.2-canary.3
2020-10-05 15:20:29 -04:00
Steven
dda6c24a3d [cli] Fix progress bar completion (#5260)
In some rare cases, the progress bar will still be in progress when the deployment completes, which causes the  "Inspect" URL to print on the same line as the progress bar instead of a new line.

This PR fixes that corner case.
2020-10-05 19:10:20 +00:00
Steven
7c922a4092 [cli] Remove 1.0 path alias rules (#5258)
We don't support routing path aliases anymore, now that we've completely shut down the ZEIT Now 1.0 infrastructure. This PR removes path alias rules from Vercel CLI.
2020-10-05 17:48:37 +00:00
Steven
376dec8f33 Publish Canary
- vercel@20.1.2-canary.2
2020-10-02 19:18:35 -04:00
Steven
16e101d262 [cli] Fix dev routing when using routes with a frontend framework (#5253)
There was a regression when introducing multiple phases such as `hit` and `miss` which caused `routes` to stop working because the transition from `null` phase to the `filesystem` phase resets any dest rewrites.

The workaround is to detect when we don't have a `filesystem` phase and exit early.
2020-10-02 22:46:53 +00:00
Nathan Rajlich
41ce1a4291 Publish Canary
- vercel@20.1.2-canary.1
 - @vercel/node@1.8.4-canary.0
2020-09-25 10:00:24 -07:00
Nathan Rajlich
449f35cf33 [node] Only use the project's local "typescript" when it has compatible ScriptTarget (#5220)
https://app.clubhouse.io/vercel/story/8304
2020-09-24 15:18:09 -07:00
Nathan Rajlich
d683402bba Publish Canary
- vercel@20.1.2-canary.0
2020-09-23 13:23:44 -07:00
Nathan Rajlich
2051a1cd9b [cli] Ensure the devProcessPort is set during "upgrade" events (#5226)
Related to: https://twitter.com/raymondcamden/status/1308838251902521348
2020-09-23 20:16:51 +00:00
25 changed files with 5066 additions and 128 deletions

View File

@@ -31,7 +31,7 @@ function Index() {
</h2>
<p>
<a
href="https://github.com/vercel/vercel/blob/master/gatsby"
href="https://github.com/vercel/vercel/tree/master/examples/gatsby"
target="_blank"
rel="noreferrer noopener"
>

View File

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

View File

@@ -458,7 +458,10 @@ function detectFrontBuilder(
config.outputDirectory = projectSettings.outputDirectory;
}
if (pkg && (framework !== null || createdAt < Date.parse('2020-03-01'))) {
if (
pkg &&
(framework === undefined || createdAt < Date.parse('2020-03-01'))
) {
const deps: PackageJson['dependencies'] = {
...pkg.dependencies,
...pkg.devDependencies,

View File

@@ -1080,6 +1080,46 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
expect(errorRoutes).toStrictEqual([]);
});
it('Using "Create React App" framework with `next` in dependencies should NOT autodetect Next.js for new projects', async () => {
const pkg = {
scripts: {
dev: 'react-scripts start',
build: 'react-scripts build',
},
dependencies: {
next: '9.3.5',
react: '16.13.1',
'react-dom': '16.13.1',
'react-scripts': '2.1.1',
},
};
const files = ['package.json', 'src/index.js', 'public/favicon.ico'];
const projectSettings = {
framework: 'create-react-app',
buildCommand: 'react-scripts build',
createdAt: Date.parse('2020-07-01'),
};
const { builders, errorRoutes } = await detectBuilders(files, pkg, {
projectSettings,
featHandleMiss,
});
expect(builders).toEqual([
{
use: '@vercel/static-build',
src: 'package.json',
config: {
zeroConfig: true,
framework: projectSettings.framework,
buildCommand: projectSettings.buildCommand,
},
},
]);
expect(errorRoutes!.length).toBe(1);
expect((errorRoutes![0] as Source).status).toBe(404);
});
it('Using "Other" framework with Storybook should NOT autodetect Next.js for new projects', async () => {
const pkg = {
scripts: {

View File

@@ -1,6 +1,6 @@
{
"name": "vercel",
"version": "20.1.1",
"version": "20.1.2",
"preferGlobal": true,
"license": "Apache-2.0",
"description": "The command-line interface for Vercel",
@@ -61,9 +61,9 @@
"node": ">= 10"
},
"dependencies": {
"@vercel/build-utils": "2.5.3",
"@vercel/build-utils": "2.5.4",
"@vercel/go": "1.1.6",
"@vercel/node": "1.8.3",
"@vercel/node": "1.8.4",
"@vercel/python": "1.2.3",
"@vercel/ruby": "1.2.4",
"update-notifier": "4.1.0"

View File

@@ -18,7 +18,7 @@ const help = () => {
${chalk.dim('Commands:')}
ls [app] Show all aliases (or per app name)
ls Show all aliases
set <deployment> <alias> Create a new alias
rm <alias> Remove an alias using its hostname
@@ -39,19 +39,19 @@ const help = () => {
-N, --next Show next page of results
${chalk.dim('Examples:')}
${chalk.gray('')} Add a new alias to ${chalk.underline('my-api.now.sh')}
${chalk.gray('')} Add a new alias to ${chalk.underline('my-api.vercel.app')}
${chalk.cyan(
`$ ${getPkgName()} alias set ${chalk.underline(
'api-ownv3nc9f8.now.sh'
)} ${chalk.underline('my-api.now.sh')}`
'api-ownv3nc9f8.vercel.app'
)} ${chalk.underline('my-api.vercel.app')}`
)}
Custom domains work as alias targets
${chalk.cyan(
`$ ${getPkgName()} alias set ${chalk.underline(
'api-ownv3nc9f8.now.sh'
'api-ownv3nc9f8.vercel.app'
)} ${chalk.underline('my-api.com')}`
)}

View File

@@ -1,6 +1,5 @@
import chalk from 'chalk';
import ms from 'ms';
import plural from 'pluralize';
import table from 'text-table';
import Now from '../../util';
import Client from '../../util/client.ts';
@@ -52,21 +51,17 @@ export default async function ls(ctx, opts, args, output) {
const lsStamp = stamp();
let cancelWait;
if (args.length > 1) {
if (args.length > 0) {
output.error(
`Invalid number of arguments. Usage: ${chalk.cyan(
`${getCommandName('alias ls [alias]')}`
`${getCommandName('alias ls')}`
)}`
);
return 1;
}
cancelWait = output.spinner(
args[0]
? `Fetching alias details for "${args[0]}" under ${chalk.bold(
contextName
)}`
: `Fetching aliases under ${chalk.bold(contextName)}`
`Fetching aliases under ${chalk.bold(contextName)}`
);
const { aliases, pagination } = await getAliases(
@@ -76,32 +71,8 @@ export default async function ls(ctx, opts, args, output) {
);
if (cancelWait) cancelWait();
if (args[0]) {
const alias = aliases.find(
item => item.uid === args[0] || item.alias === args[0]
);
if (!alias) {
output.error(`Could not match path alias for: ${args[0]}`);
now.close();
return 1;
}
if (opts['--json']) {
console.log(JSON.stringify({ rules: alias.rules }, null, 2));
} else {
const rules = alias.rules || [];
output.log(
`${rules.length} path alias ${plural(
'rule',
rules.length
)} found under ${chalk.bold(contextName)} ${lsStamp()}`
);
output.print(`${printPathAliasTable(rules)}\n`);
}
} else {
output.log(`aliases found under ${chalk.bold(contextName)} ${lsStamp()}`);
console.log(printAliasTable(aliases));
}
output.log(`aliases found under ${chalk.bold(contextName)} ${lsStamp()}`);
console.log(printAliasTable(aliases));
if (pagination && pagination.count === 20) {
const flags = getCommandFlags(opts, ['_', '--next']);
@@ -121,14 +92,10 @@ function printAliasTable(aliases) {
[
['source', 'url', 'age'].map(h => chalk.gray(h)),
...aliases.map(a => [
a.rules && a.rules.length
? chalk.cyan(`[${plural('rule', a.rules.length, true)}]`)
: // for legacy reasons, we might have situations
// where the deployment was deleted and the alias
// not collected appropriately, and we need to handle it
a.deployment && a.deployment.url
? a.deployment.url
: chalk.gray(''),
// for legacy reasons, we might have situations
// where the deployment was deleted and the alias
// not collected appropriately, and we need to handle it
a.deployment && a.deployment.url ? a.deployment.url : chalk.gray(''),
a.alias,
ms(Date.now() - new Date(a.createdAt)),
]),
@@ -140,21 +107,3 @@ function printAliasTable(aliases) {
}
).replace(/^/gm, ' ')}\n\n`;
}
function printPathAliasTable(rules) {
const header = [['pathname', 'method', 'dest'].map(s => chalk.gray(s))];
return `${table(
header.concat(
rules.map(rule => [
rule.pathname ? rule.pathname : chalk.cyan('[fallthrough]'),
rule.method ? rule.method : '*',
rule.dest,
])
),
{
align: ['l', 'l', 'l', 'l'],
hsep: ' '.repeat(6),
stringLength: strlen,
}
).replace(/^(.*)/gm, ' $1')}\n`;
}

View File

@@ -388,7 +388,7 @@ function handleCreateAliasError<T>(
}
if (error instanceof ERRORS.InvalidAlias) {
output.error(
`Invalid alias. Please confirm that the alias you provided is a valid hostname. Note: For \`now.sh\`, only sub and sub-sub domains are supported.`
`Invalid alias. Please confirm that the alias you provided is a valid hostname. Note: For \`vercel.app\`, only sub and sub-sub domains are supported.`
);
return 1;
}

View File

@@ -117,12 +117,6 @@ export type Deployment = {
creator: { uid: string };
};
type PathAliasRule = {
pathname: string;
method: Array<'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'>;
dest: string;
};
export type Alias = {
uid: string;
alias: string;
@@ -137,13 +131,6 @@ export type Alias = {
email: string;
};
deploymentId?: string;
rules?: PathAliasRule[];
};
export type PathRule = {
dest: string;
pathname?: string;
method?: Array<string>;
};
export type DNSRecord = {

View File

@@ -172,6 +172,10 @@ export default async function processDeployment({
if (event.type === 'created') {
deployingSpinner();
if (bar && !bar.complete) {
bar.tick(bar.total + 1);
}
now._host = event.payload.url;
await linkFolderToProject(

View File

@@ -923,9 +923,17 @@ export default class DevServer {
await once(this.watcher, 'ready');
// Configure the server to forward WebSocket "upgrade" events to the proxy.
this.server.on('upgrade', (req, socket, head) => {
this.server.on('upgrade', async (req, socket, head) => {
await this.startPromise;
if (!this.devProcessPort) {
this.output.debug(
`Detected "upgrade" event, but closing socket because no frontend dev server is running`
);
socket.destroy();
return;
}
const target = `http://localhost:${this.devProcessPort}`;
this.output.debug(`Detected upgrade event, proxying to ${target}`);
this.output.debug(`Detected "upgrade" event, proxying to ${target}`);
this.proxy.ws(req, socket, head, { target });
});
@@ -1364,6 +1372,7 @@ export default class DevServer {
const missRoutes = handleMap.get('miss') || [];
const hitRoutes = handleMap.get('hit') || [];
const errorRoutes = handleMap.get('error') || [];
const filesystemRoutes = handleMap.get('filesystem') || [];
const phases: (HandleValue | null)[] = [null, 'filesystem'];
let routeResult: RouteResult | null = null;
@@ -1481,6 +1490,11 @@ export default class DevServer {
// end the phase
break;
}
if (phase === null && filesystemRoutes.length === 0) {
// hack to skip the reset from null to filesystem
break;
}
}
if (!match && routeResult && errorRoutes.length > 0) {

View File

@@ -0,0 +1,3 @@
node_modules
.next
.vercel

View File

@@ -0,0 +1,8 @@
{
"private": true,
"dependencies": {
"next": "9.5.3",
"react": "16.13.1",
"react-dom": "16.13.1"
}
}

View File

@@ -0,0 +1,3 @@
module.exports = (_req, res) => {
res.end('Hello Routes');
};

View File

@@ -0,0 +1,10 @@
function Index() {
return (
<main>
<h1>Next.js with routes</h1>
<a href="/hello">/hello</a>
</main>
);
}
export default Index;

View File

@@ -0,0 +1,3 @@
{
"routes": [{ "src": "/hello", "dest": "/api/hello" }]
}

File diff suppressed because it is too large Load Diff

View File

@@ -1180,6 +1180,14 @@ test(
})
);
test(
'[vercel dev] 10a-nextjs-routes',
testFixtureStdio('10a-nextjs-routes', async testPath => {
await testPath(200, '/', /Next.js with routes/m);
await testPath(200, '/hello', /Hello Routes/m);
})
);
test(
'[vercel dev] 12-polymer-node',
testFixtureStdio(

View File

@@ -28,9 +28,6 @@ module.exports = async function prepare(session) {
'first.png': getImageFile(session, { size: 30 }),
'second.png': getImageFile(session, { size: 20 }),
},
'single-dotfile': {
'.testing': 'i am a dotfile',
},
'empty-directory': {},
'config-scope-property-email': {
'now.json': `{ "scope": "${session}@zeit.pub", "builds": [ { "src": "*.html", "use": "@now/static" } ] }`,
@@ -207,23 +204,6 @@ module.exports = async function prepare(session) {
},
}),
},
'alias-rules': {
'rules.json': JSON.stringify({
rules: [
// for example:
// { pathname: '/', dest: '' },
// { pathname: '/', dest: '', method: 'GET' }
// Will be generated by the actual test
],
}),
'invalid-rules.json': JSON.stringify({
what: { what: 0 },
}),
'invalid-type-rules.json': JSON.stringify({
rules: { what: 0 },
}),
'invalid-json-rules.json': '==ok',
},
'zero-config-next-js': {
'pages/index.js':
'export default () => <div><h1>Now CLI test</h1><p>Zero-config + Next.js</p></div>',

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/client",
"version": "9.0.2",
"version": "9.0.3",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"homepage": "https://vercel.com",
@@ -37,7 +37,7 @@
]
},
"dependencies": {
"@vercel/build-utils": "2.5.3",
"@vercel/build-utils": "2.5.4",
"@zeit/fetch": "5.2.0",
"async-retry": "1.2.3",
"async-sema": "3.0.0",

View File

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

View File

@@ -8,33 +8,54 @@ if (!entrypoint) {
throw new Error('`VERCEL_DEV_ENTRYPOINT` must be defined');
}
import { join } from 'path';
import { register } from 'ts-node';
// Use the project's version of TypeScript if available,
// otherwise fall back to using the copy that `@vercel/node` uses.
let compiler: string;
try {
compiler = require.resolve('typescript', {
paths: [process.cwd()],
});
} catch (e) {
compiler = 'typescript';
}
type TypescriptModule = typeof import('typescript');
// Assume Node 10
let target = 'es2018';
const resolveTypescript = (p: string): string => {
try {
return require.resolve('typescript', {
paths: [p],
});
} catch (_) {
return '';
}
};
const requireTypescript = (p: string): TypescriptModule => {
// eslint-disable-next-line @typescript-eslint/no-var-requires
return require(p) as TypescriptModule;
};
let ts: TypescriptModule | null = null;
// Assume Node 10 as the lowest common denominator
let target = 'ES2018';
const nodeMajor = Number(process.versions.node.split('.')[0]);
if (nodeMajor >= 14) {
target = 'es2020';
target = 'ES2020';
} else if (nodeMajor >= 12) {
target = 'es2019';
target = 'ES2019';
}
// Use the project's version of Typescript if available and supports `target`
let compiler = resolveTypescript(process.cwd());
if (compiler) {
ts = requireTypescript(compiler);
if (!(target in ts.ScriptTarget)) {
ts = null;
}
}
// Otherwise fall back to using the copy that `@vercel/node` uses
if (!ts) {
compiler = resolveTypescript(join(__dirname, '..'));
ts = requireTypescript(compiler);
}
if (tsconfig) {
try {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const ts: typeof import('typescript') = require(compiler);
const { config } = ts.readConfigFile(tsconfig, ts.sys.readFile);
if (config?.compilerOptions?.target) {
target = config.compilerOptions.target;
@@ -61,7 +82,6 @@ register({
});
import { createServer, Server, IncomingMessage, ServerResponse } from 'http';
import { join } from 'path';
import { Readable } from 'stream';
import { Bridge } from './bridge';
import { getNowLauncher } from './launcher';

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/routing-utils",
"version": "1.8.4",
"version": "1.9.0",
"description": "Vercel routing utilities",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",

View File

@@ -36,6 +36,36 @@ export const routesSchema = {
},
},
},
locale: {
type: 'object',
additionalProperties: false,
properties: {
redirect: {
type: 'object',
additionalProperties: false,
minProperties: 1,
maxProperties: 100,
patternProperties: {
'^.{1,256}$': {
type: 'string',
maxLength: 4096,
},
},
},
value: {
type: 'string',
maxLength: 4096,
},
path: {
type: 'string',
maxLength: 4096,
},
default: {
type: 'string',
maxLength: 4096,
},
},
},
handle: {
type: 'string',
maxLength: 32,

View File

@@ -36,6 +36,20 @@ describe('normalizeRoutes', () => {
test('accepts valid routes', () => {
const routes = [
{
src: '^(?:/(?<value>en|fr))?(?<path>/.*)$',
locale: {
value: '$value',
path: '$path',
default: 'en',
},
},
{
src: '^/(?:en/?|fr/?)$',
locale: {
redirect: { en: '/en', fr: '/fr' },
},
},
{ src: '^/about$' },
{
src: '^/blog$',