Compare commits

...

11 Commits

Author SHA1 Message Date
Nathan Rajlich
c80bb37e8d Publish Canary
- @vercel/frameworks@0.0.15-canary.4
 - @vercel/build-utils@2.3.2-canary.3
 - vercel@19.0.2-canary.11
 - @vercel/client@8.0.2-canary.2
 - @vercel/go@1.1.2-canary.1
 - @vercel/next@2.6.3-canary.5
 - @vercel/node-bridge@1.3.1-canary.2
 - @vercel/node@1.6.2-canary.5
 - @vercel/python@1.2.2-canary.2
 - @vercel/routing-utils@1.8.3-canary.5
 - @vercel/ruby@1.2.2-canary.1
 - @vercel/static-build@0.17.2-canary.1
2020-06-03 13:58:37 -07:00
Nathan Rajlich
a7acd92ffd [cli][client] Throw an error if both vercel.json and now.json exist (#4316)
* [client] Throw an error if both `vercel.json` and `now.json` exist

* Update packages/now-client/src/create-deployment.ts

Co-authored-by: Steven <steven@ceriously.com>

* Check in CLI as well

* Add integration test

* Add logic to `getLocalPathConfig()` as well

* Fix import path

Co-authored-by: Steven <steven@ceriously.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-06-03 13:51:50 -07:00
Max Leiter
035720ca82 [cli] Prioritize index.html over other files named index (#4564)
Mirrors production more closely. Initially reported [on spectrum](https://spectrum.chat/zeit/now/statically-served-default-document-is-the-first-index-file-not-index-html~0ad66f8a-a139-4a0e-94d9-7e5ceb0fa043)
2020-06-03 19:56:36 +00:00
Nathan Rajlich
a6ae923a7a [all] Update TypeScript to v3.9.3 and regenerate yarn.lock file (#4565)
To fix GitHub Dependabot security alerts. See: https://github.com/vercel/vercel/network/alerts

<img width="835" alt="Screen Shot 2020-06-03 at 1 36 50 AM" src="https://user-images.githubusercontent.com/71256/83614929-b7e2c600-a53a-11ea-80b6-190e350283ac.png">

Also updates "typescript" to `3.9.3` for all packages, which is necessary because a downstream dependency is using syntax that requires a newer version of TypeScript.
2020-06-03 09:57:16 -07:00
Nathan Rajlich
83c0711d6e [node] Pass in the tsconfig.json file to startDevServer() (#4514)
So that if a `tsconfig.json` exists closer to the entrypoint file,
then that config file will be correctly used (rather than say, the
root-level `tsconfig.json` file, which may be specific to the frontend
configuration in Next.js for example).
2020-06-03 00:56:44 +00:00
Nathan Rajlich
231f18d56b [cli] Remove unnecessary build outputs (#4547)
Upon investigation into the `dist` dir, it appears that `ncc` is bundling some assets that don't need to be there. This change is a quick band-aid fix to remove those assets, without addressing the underlying cause of _why_ they're being bundled, which requires further investigation.

Overall about 1mb of disk space is saved.
2020-06-02 13:43:34 +00:00
Steven
9d73091d8c Publish Canary
- vercel@19.0.2-canary.10
 - @vercel/routing-utils@1.8.3-canary.4
2020-06-01 18:07:23 -04:00
Steven
0ca3189f79 [routing-utils] Fix headers with content-security-policy URL (#4550)
Fixes a case when the header value contains a URL which was mistaken for a named segment.

https://sentry.io/organizations/zeithq/issues/1702692084/?project=1351065

The regression was introduced in PR #4484 where unnamed segments were implemented for `redirects` and `rewrites` but not handled properly in `headers`.
2020-06-01 22:06:37 +00:00
Nathan Rajlich
9ff5bb9cb3 [cli] Throw an error if both .vercel and .now dirs exist (#4543) 2020-06-01 16:33:19 +00:00
Steven
45d05a603b Publish Canary
- @vercel/routing-utils@1.8.3-canary.3
2020-06-01 10:59:25 -04:00
Steven
6ef3b12fde [build-utils] Revert type of routing errors (#4549)
In PR #4498, the type of the routing error was changed from first error and then the remaining errors. This PR changes the type back such that `error.errors` returns all errors. This will avoid any breaking change.
2020-06-01 14:58:27 +00:00
52 changed files with 7485 additions and 1273 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/frameworks",
"version": "0.0.15-canary.3",
"version": "0.0.15-canary.4",
"main": "frameworks.json",
"license": "UNLICENSED",
"scripts": {
@@ -12,6 +12,6 @@
"ajv": "6.10.2",
"jest": "24.9.0",
"ts-jest": "24.1.0",
"typescript": "3.5.2"
"typescript": "3.9.3"
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/build-utils",
"version": "2.3.2-canary.2",
"version": "2.3.2-canary.3",
"license": "MIT",
"main": "./dist/index.js",
"types": "./dist/index.d.js",
@@ -45,7 +45,7 @@
"node-fetch": "2.2.0",
"semver": "6.1.1",
"ts-jest": "24.1.0",
"typescript": "3.5.2",
"typescript": "3.9.3",
"yazl": "2.4.3"
}
}

View File

@@ -531,6 +531,7 @@ describe('Test `detectBuilders`', () => {
const files = ['api/user.php'];
// @ts-ignore
const { errors } = await detectBuilders(files, null, {
// @ts-ignore
functions,
});
@@ -1530,6 +1531,7 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
const files = ['api/user.php'];
// @ts-ignore
const { errors } = await detectBuilders(files, null, {
// @ts-ignore
functions,
featHandleMiss,
});
@@ -1630,6 +1632,7 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
// @ts-ignore
const { errors } = await detectBuilders(files, null, {
// @ts-ignore
functions,
featHandleMiss,
});
@@ -1646,6 +1649,7 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
// @ts-ignore: Since we test an invalid type
const { errors } = await detectBuilders(files, null, {
// @ts-ignore
functions,
featHandleMiss,
});

View File

@@ -1,6 +1,6 @@
{
"name": "vercel",
"version": "19.0.2-canary.9",
"version": "19.0.2-canary.11",
"preferGlobal": true,
"license": "Apache-2.0",
"description": "The command-line interface for Now",
@@ -62,13 +62,13 @@
"node": ">= 10"
},
"dependencies": {
"@vercel/build-utils": "2.3.2-canary.2",
"@vercel/go": "1.1.2-canary.0",
"@vercel/next": "2.6.3-canary.4",
"@vercel/node": "1.6.2-canary.4",
"@vercel/python": "1.2.2-canary.1",
"@vercel/ruby": "1.2.2-canary.0",
"@vercel/static-build": "0.17.2-canary.0"
"@vercel/build-utils": "2.3.2-canary.3",
"@vercel/go": "1.1.2-canary.1",
"@vercel/next": "2.6.3-canary.5",
"@vercel/node": "1.6.2-canary.5",
"@vercel/python": "1.2.2-canary.2",
"@vercel/ruby": "1.2.2-canary.1",
"@vercel/static-build": "0.17.2-canary.1"
},
"devDependencies": {
"@sentry/node": "5.5.0",
@@ -182,7 +182,7 @@
"tmp-promise": "1.0.3",
"tree-kill": "1.2.1",
"ts-node": "8.3.0",
"typescript": "3.6.4",
"typescript": "3.9.3",
"universal-analytics": "0.4.20",
"update-check": "1.5.3",
"utility-types": "2.1.0",

View File

@@ -75,6 +75,17 @@ async function main() {
const dest = join(dirRoot, 'dist/runtimes');
await cpy('**/*', dest, { parents: true, cwd: runtimes });
// Band-aid to delete stuff that `ncc` bundles, but it shouldn't:
// TypeScript definition files from `@vercel/build-utils`
await remove(join(dirRoot, 'dist', 'dist'));
// The Readme and `package.json` from "config-chain" module
await remove(join(dirRoot, 'dist', 'config-chain'));
// A bunch of source `.ts` files from CLI's `util` directory
await remove(join(dirRoot, 'dist', 'util'));
console.log('Finished building `now-cli`');
}

View File

@@ -1,6 +1,7 @@
import path from 'path';
import mri from 'mri';
import { InvalidLocalConfig } from '../errors';
import { ConflictingConfigFiles } from '../errors-ts';
import { existsSync } from 'fs';
export default function getLocalPathConfig(prefix: string) {
@@ -11,20 +12,30 @@ export default function getLocalPathConfig(prefix: string) {
},
});
// If `--local-config` flag was specified, then that takes priority
const customPath = args['local-config'];
if (customPath && typeof customPath !== 'string') {
throw new InvalidLocalConfig(customPath);
if (customPath) {
if (typeof customPath !== 'string') {
throw new InvalidLocalConfig(customPath);
}
return path.resolve(prefix, customPath);
}
const possibleConfigFiles = [
path.join(prefix, 'vercel.json'),
path.join(prefix, 'now.json'),
];
// Otherwise check for either `vercel.json` or `now.json`.
// Throw an error if both exist.
const vercelConfigPath = path.join(prefix, 'vercel.json');
const nowConfigPath = path.join(prefix, 'now.json');
return (
(customPath && path.resolve(prefix, customPath)) ||
possibleConfigFiles.find(configFile => existsSync(configFile)) ||
possibleConfigFiles[0]
);
const vercelConfigExists = existsSync(vercelConfigPath);
const nowConfigExists = existsSync(nowConfigPath);
if (nowConfigExists && vercelConfigExists) {
throw new ConflictingConfigFiles([vercelConfigPath, nowConfigPath]);
}
if (nowConfigExists) {
return nowConfigPath;
}
return vercelConfigPath;
}

View File

@@ -1603,7 +1603,6 @@ export default class DevServer {
debug(`Skipping \`startDevServer()\` for ${match.entrypoint}`);
}
}
let foundAsset = findAsset(match, requestPath, nowConfig);
if (!foundAsset && callLevel === 0) {
@@ -2014,12 +2013,24 @@ async function findBuildMatch(
isFilesystem?: boolean
): Promise<BuildMatch | null> {
requestPath = requestPath.replace(/^\//, '');
let bestIndexMatch: undefined | BuildMatch;
for (const match of matches.values()) {
if (await shouldServe(match, files, requestPath, devServer, isFilesystem)) {
return match;
if (!isIndex(match.src)) {
return match;
} else {
// if isIndex === true and ends in .html, we're done. Otherwise, keep searching
bestIndexMatch = match;
if (extname(match.src) === '.html') {
return bestIndexMatch;
}
}
}
}
return null;
// return a non-.html index file or none are found
return bestIndexMatch || null;
}
async function shouldServe(

View File

@@ -771,6 +771,20 @@ export class CantParseJSONFile extends NowError<
}
}
export class ConflictingConfigFiles extends NowError<
'CONFLICTING_CONFIG_FILES',
{ 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.',
});
}
}
export class CantFindConfig extends NowError<
'CANT_FIND_CONFIG',
{ paths: string[] }

View File

@@ -3,6 +3,7 @@ import { fileNameSymbol } from '@vercel/client';
import {
CantParseJSONFile,
CantFindConfig,
ConflictingConfigFiles,
WorkingDirectoryDoesNotExist,
} from './errors-ts';
import humanizePath from './humanize-path';
@@ -49,28 +50,31 @@ export default async function getConfig(
}
}
// Then try with vercel.json in the same directory
// Then try with `vercel.json` or `now.json` in the same directory
const vercelFilePath = path.resolve(localPath, 'vercel.json');
const vercelConfig = await readJSONFile(vercelFilePath);
const nowFilePath = path.resolve(localPath, 'now.json');
const [vercelConfig, nowConfig] = await Promise.all([
readJSONFile(vercelFilePath),
readJSONFile(nowFilePath),
]);
if (vercelConfig instanceof CantParseJSONFile) {
return vercelConfig;
}
if (nowConfig instanceof CantParseJSONFile) {
return nowConfig;
}
if (vercelConfig && nowConfig) {
return new ConflictingConfigFiles([vercelFilePath, nowFilePath]);
}
if (vercelConfig !== null) {
output.debug(`Found config in file ${vercelFilePath}`);
output.debug(`Found config in file "${vercelFilePath}"`);
config = vercelConfig as NowConfig;
config[fileNameSymbol] = 'vercel.json';
return config;
}
// Then try with now.json in the same directory
const nowFilePath = path.resolve(localPath, 'now.json');
const mainConfig = await readJSONFile(nowFilePath);
if (mainConfig instanceof CantParseJSONFile) {
return mainConfig;
}
if (mainConfig !== null) {
output.debug(`Found config in file ${nowFilePath}`);
config = mainConfig as NowConfig;
if (nowConfig !== null) {
output.debug(`Found config in file "${nowFilePath}"`);
config = nowConfig as NowConfig;
config[fileNameSymbol] = 'now.json';
return config;
}

View File

@@ -42,10 +42,18 @@ const linkSchema = {
/**
* Returns the `<cwd>/.vercel` directory for the current project
* with a fallback to <cwd>/.now` if it exists.
*
* Throws an error if *both* `.vercel` and `.now` directories exist.
*/
export function getVercelDirectory(cwd: string = process.cwd()) {
export function getVercelDirectory(cwd: string = process.cwd()): string {
const possibleDirs = [join(cwd, VERCEL_DIR), join(cwd, VERCEL_DIR_FALLBACK)];
return possibleDirs.find(d => isDirectory(d)) || possibleDirs[0];
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.'
);
}
return existingDirs[0] || possibleDirs[0];
}
async function getLink(path?: string): Promise<ProjectLink | null> {

View File

@@ -0,0 +1 @@
This is index.css

View File

@@ -0,0 +1,2 @@
This is index.html

View File

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

View File

@@ -0,0 +1,5 @@
import { IncomingMessage, ServerResponse } from 'http';
export default function(req: IncomingMessage, res: ServerResponse) {
res.end('Nested `tsconfig.json` API endpoint');
}

View File

@@ -0,0 +1,6 @@
{
"name": "api",
"devDependencies": {
"@types/node": "12"
}
}

View File

@@ -0,0 +1,11 @@
{
"compilerOptions": {
"target": "es2015",
"lib": ["dom", "dom.iterable", "esnext"],
"strict": true,
"module": "CommonJS",
"esModuleInterop": true
},
"exclude": ["node_modules"],
"include": ["**/*.ts"]
}

View File

@@ -0,0 +1,8 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@types/node@12":
version "12.12.43"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.43.tgz#b60ce047822e526e7a9252e50844eee79d5386ff"
integrity sha512-KUyZdkGCnVPuXfsKmDUu2XLui65LZIJ2s0M57noy5e+ixUT2oK33ep7zlvgzI8LElcWqbf8AR+o/3GqAPac2zA==

View File

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

View File

@@ -0,0 +1,19 @@
{
"name": "nested-tsconfig",
"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>Nested tsconfig.json 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

@@ -1347,3 +1347,20 @@ test(
await testPath(200, `/api/user.sh`, /Hello, from Bash!/m);
})
);
test(
'[vercel dev] Should work with nested `tsconfig.json` files',
testFixtureStdio('nested-tsconfig', async testPath => {
await testPath(200, `/`, /Nested tsconfig.json test page/);
await testPath(200, `/api`, 'Nested `tsconfig.json` API endpoint');
})
);
test(
'[vercel dev] should prioritize index.html over other file named index.*',
testFixtureStdio('index-html-priority', async testPath => {
await testPath(200, '/', 'This is index.html');
await testPath(200, '/index.css', 'This is index.css');
})
);

View File

@@ -0,0 +1,2 @@
!.vercel
!.now

View File

@@ -0,0 +1 @@
!.now

View File

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

View File

@@ -514,6 +514,11 @@ CMD ["node", "index.js"]`,
],
}),
},
'conflicting-now-json-vercel-json': {
'index.html': '<h1>I am a website.</h1>',
'vercel.json': getConfigFile(true),
'now.json': getConfigFile(true),
},
};
for (const typeName of Object.keys(spec)) {

View File

@@ -2895,3 +2895,24 @@ test('deploys with only vercel.json and README.md', async t => {
const text = await res.text();
t.regex(text, /readme contents/);
});
test('reject conflicting `vercel.json` and `now.json` files', async t => {
const directory = fixture('conflicting-now-json-vercel-json');
const { exitCode, stderr, stdout } = await execa(
binaryPath,
[...defaultArgs, '--confirm'],
{
cwd: directory,
reject: false,
}
);
t.is(exitCode, 1, formatOutput({ stderr, stdout }));
t.true(
stderr.includes(
'Cannot use both a `vercel.json` and `now.json` file. Please delete the `now.json` file.'
),
formatOutput({ stderr, stdout })
);
});

View File

@@ -1,4 +1,4 @@
import { join, sep } from 'path';
import { basename, join, sep } from 'path';
import { send } from 'micro';
import test from 'ava';
import sinon from 'sinon';
@@ -24,6 +24,7 @@ import { isValidName } from '../src/util/is-valid-name';
import preferV2Deployment from '../src/util/prefer-v2-deployment';
import getUpdateCommand from '../src/util/get-update-command';
import { isCanary } from '../src/util/is-canary';
import { getVercelDirectory } from '../src/util/projects/link';
const output = createOutput({ debug: false });
const prefix = `${join(__dirname, 'fixtures', 'unit')}${sep}`;
@@ -1091,3 +1092,29 @@ test('detect update command', async t => {
const updateCommand = await getUpdateCommand();
t.is(updateCommand, `yarn add vercel@${isCanary() ? 'canary' : 'latest'}`);
});
test('`getVercelDirectory()` returns ".vercel"', t => {
const cwd = fixture('get-vercel-directory');
const dir = getVercelDirectory(cwd);
t.is(basename(dir), '.vercel');
});
test('`getVercelDirectory()` returns ".now"', t => {
const cwd = fixture('get-vercel-directory-legacy');
const dir = getVercelDirectory(cwd);
t.is(basename(dir), '.now');
});
test('`getVercelDirectory()` throws an error if ".vercel" and ".now" exist', t => {
let err;
const cwd = fixture('get-vercel-directory-error');
try {
getVercelDirectory(cwd);
} catch (_err) {
err = _err;
}
t.is(
err.message,
'Both `.vercel` and `.now` directories exist. Please remove the `.now` directory.'
);
});

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/client",
"version": "8.0.2-canary.1",
"version": "8.0.2-canary.2",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"homepage": "https://vercel.com",
@@ -27,7 +27,7 @@
"@types/node-fetch": "2.5.4",
"@types/recursive-readdir": "2.2.0",
"@zeit/ncc": "0.18.5",
"typescript": "3.5.1"
"typescript": "3.9.3"
},
"jest": {
"preset": "ts-jest",

View File

@@ -3,7 +3,7 @@ import { readdir as readRootFolder, lstatSync } from 'fs-extra';
import { relative, isAbsolute, basename } from 'path';
import hashes, { mapToObject } from './utils/hashes';
import { upload } from './upload';
import { buildFileTree, createDebug, parseNowJSON } from './utils';
import { buildFileTree, createDebug, parseVercelConfig } from './utils';
import { DeploymentError } from './errors';
import {
NowConfig,
@@ -85,10 +85,24 @@ export default function buildCreateDeployment(version: number) {
let configPath: string | undefined;
if (!nowConfig) {
// If the user did not provide a config file, use the one in the root directory.
configPath = fileList
.map(f => relative(cwd, f))
.find(f => f === 'vercel.json' || f === 'now.json');
nowConfig = await parseNowJSON(configPath);
const relativePaths = fileList.map(f => relative(cwd, f));
const hasVercelConfig = relativePaths.includes('vercel.json');
const hasNowConfig = relativePaths.includes('now.json');
if (hasVercelConfig) {
if (hasNowConfig) {
throw new DeploymentError({
code: 'conflicting_config',
message:
'Cannot use both a `vercel.json` and `now.json` file. Please delete the `now.json` file.',
});
}
configPath = 'vercel.json';
} else if (hasNowConfig) {
configPath = 'now.json';
}
nowConfig = await parseVercelConfig(configPath);
}
if (

View File

@@ -51,7 +51,7 @@ export function getApiDeploymentsUrl(
return '/v12/now/deployments';
}
export async function parseNowJSON(filePath?: string): Promise<NowConfig> {
export async function parseVercelConfig(filePath?: string): Promise<NowConfig> {
if (!filePath) {
return {};
}

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/go",
"version": "1.1.2-canary.0",
"version": "1.1.2-canary.1",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/go",
@@ -28,6 +28,6 @@
"node-fetch": "^2.2.1",
"string-argv": "0.3.1",
"tar": "4.4.6",
"typescript": "3.5.2"
"typescript": "3.9.3"
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/next",
"version": "2.6.3-canary.4",
"version": "2.6.3-canary.5",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/next-js",
@@ -34,7 +34,7 @@
"get-port": "5.0.0",
"resolve-from": "5.0.0",
"semver": "6.1.1",
"typescript": "3.5.2",
"typescript": "3.9.3",
"yazl": "https://github.com/ijjk/yazl#70949c55b482647669ce37023017b1514c42b33c"
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/node-bridge",
"version": "1.3.1-canary.1",
"version": "1.3.1-canary.2",
"license": "MIT",
"main": "./index.js",
"repository": {
@@ -20,6 +20,6 @@
"devDependencies": {
"@types/aws-lambda": "8.10.19",
"@types/node": "10.x",
"typescript": "3.5.2"
"typescript": "3.9.3"
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/node",
"version": "1.6.2-canary.4",
"version": "1.6.2-canary.5",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/node-js",
@@ -21,7 +21,7 @@
"dependencies": {
"@types/node": "*",
"ts-node": "8.9.1",
"typescript": "3.8.3"
"typescript": "3.9.3"
},
"devDependencies": {
"@babel/core": "7.5.0",

View File

@@ -1,3 +1,13 @@
const entrypoint = process.env.NOW_DEV_ENTRYPOINT;
delete process.env.NOW_DEV_ENTRYPOINT;
const tsconfig = process.env.NOW_DEV_TSCONFIG;
delete process.env.NOW_DEV_TSCONFIG;
if (!entrypoint) {
throw new Error('`NOW_DEV_ENTRYPOINT` must be defined');
}
import { register } from 'ts-node';
// Use the project's version of TypeScript if available,
@@ -18,6 +28,7 @@ register({
esModuleInterop: true,
jsx: 'react',
},
project: tsconfig || undefined, // Resolve `tsconfig.json` from entrypoint dir
transpileOnly: true,
});
@@ -38,13 +49,6 @@ function listen(server: Server, port: number, host: string): Promise<void> {
let bridge: Bridge | undefined = undefined;
async function main() {
const entrypoint = process.env.NOW_DEV_ENTRYPOINT;
delete process.env.NOW_DEV_ENTRYPOINT;
if (!entrypoint) {
throw new Error('`NOW_DEV_ENTRYPOINT` must be defined');
}
const config = JSON.parse(process.env.NOW_DEV_CONFIG || '{}');
delete process.env.NOW_DEV_CONFIG;
@@ -53,7 +57,7 @@ async function main() {
);
bridge = getNowLauncher({
entrypointPath: join(process.cwd(), entrypoint),
entrypointPath: join(process.cwd(), entrypoint!),
helpersPath: './helpers',
shouldAddHelpers,
bridgePath: 'not used',

View File

@@ -430,6 +430,14 @@ export async function startDevServer(
opts: StartDevServerOptions
): Promise<StartDevServerResult> {
const { entrypoint, workPath, config, meta = {} } = opts;
// Find the `tsconfig.json` file closest to the entrypoint file
const projectTsConfig = await walkParentDirs({
base: workPath,
start: join(workPath, dirname(entrypoint)),
filename: 'tsconfig.json',
});
const devServerPath = join(__dirname, 'dev-server.js');
const child = fork(devServerPath, [], {
cwd: workPath,
@@ -438,6 +446,7 @@ export async function startDevServer(
...process.env,
...meta.env,
NOW_DEV_ENTRYPOINT: entrypoint,
NOW_DEV_TSCONFIG: projectTsConfig || '',
NOW_DEV_CONFIG: JSON.stringify(config),
},
});
@@ -456,7 +465,7 @@ export async function startDevServer(
if (ext === '.ts' || ext === '.tsx') {
// Invoke `tsc --noEmit` asynchronously in the background, so
// that the HTTP request is not blocked by the type checking.
doTypeCheck(opts).catch((err: Error) => {
doTypeCheck(opts, projectTsConfig).catch((err: Error) => {
console.error('Type check for %j failed:', entrypoint, err);
});
}
@@ -470,23 +479,17 @@ export async function startDevServer(
}
}
async function doTypeCheck({
entrypoint,
workPath,
meta = {},
}: StartDevServerOptions): Promise<void> {
async function doTypeCheck(
{ entrypoint, workPath, meta = {} }: StartDevServerOptions,
projectTsConfig: string | null
): Promise<void> {
const { devCacheDir = join(workPath, '.now', 'cache') } = meta;
const entrypointCacheDir = join(devCacheDir, 'node', entrypoint);
// In order to type-check a single file, a standalone tsconfig
// file needs to be created that inherits from the base one :(
// See: https://stackoverflow.com/a/44748041/376773
const projectTsConfig = await walkParentDirs({
base: workPath,
start: join(workPath, dirname(entrypoint)),
filename: 'tsconfig.json',
});
//
// A different filename needs to be used for different `extends` tsconfig.json
const tsconfigName = projectTsConfig
? `tsconfig-with-${relative(workPath, projectTsConfig).replace(

View File

@@ -138,7 +138,7 @@ export function getAwsLauncher({
const { query } = parse(path, true);
const queryStringParameters: { [i: string]: string } = {};
for (const [key, value] of Object.entries(query)) {
if (!Array.isArray(value)) {
if (typeof value === 'string') {
queryStringParameters[key] = value;
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/python",
"version": "1.2.2-canary.1",
"version": "1.2.2-canary.2",
"main": "./dist/index.js",
"license": "MIT",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/python",
@@ -21,6 +21,6 @@
"devDependencies": {
"@types/execa": "^0.9.0",
"execa": "^1.0.0",
"typescript": "3.5.2"
"typescript": "3.9.3"
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/routing-utils",
"version": "1.8.3-canary.2",
"version": "1.8.3-canary.5",
"description": "Vercel routing utilities",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
@@ -25,7 +25,7 @@
"devDependencies": {
"@types/node": "12.12.20",
"ajv": "^6.0.0",
"typescript": "3.5.2"
"typescript": "3.9.3"
},
"optionalDependencies": {
"ajv": "^6.0.0"

View File

@@ -223,23 +223,18 @@ function checkRedirect(r: NowRedirect, index: number) {
function createError(
code: string,
errors: string | string[],
allErrors: string | string[],
link: string,
action: string
): RouteApiError | null {
let message: string;
let otherErrors: string[] = [];
if (Array.isArray(errors)) {
[message, ...otherErrors] = errors;
} else {
message = errors;
}
const errors = Array.isArray(allErrors) ? allErrors : [allErrors];
const message = errors[0];
const error: RouteApiError = {
code,
message,
link,
action,
otherErrors,
errors,
};
return error;
}

View File

@@ -89,7 +89,7 @@ export function convertHeaders(headers: NowHeader[]): Route[] {
return headers.map(h => {
const obj: { [key: string]: string } = {};
const { src, segments } = sourceToRegex(h.source);
const hasSegments = segments.length > 0;
const namedSegments = segments.filter(name => name !== UN_NAMED_SEGMENT);
const indexes: { [k: string]: string } = {};
segments.forEach((name, index) => {
@@ -97,7 +97,7 @@ export function convertHeaders(headers: NowHeader[]): Route[] {
});
h.headers.forEach(({ key, value }) => {
if (hasSegments) {
if (namedSegments.length > 0) {
if (key.includes(':')) {
key = safelyCompile(key, indexes);
}

View File

@@ -5,7 +5,7 @@ export type RouteApiError = {
message: string;
link?: string; // link to error message details
action?: string; // label for error link
otherErrors?: string[];
errors?: string[]; // array of all error messages
};
export type Source = {

View File

@@ -915,4 +915,65 @@ describe('getTransformedRoutes', () => {
actual.error.message
);
});
test('should work with content-security-policy header containing URL', () => {
const nowConfig = {
headers: [
{
source: '/(.*)',
headers: [
{
key: 'content-security-policy',
value:
"default-src 'self'; script-src 'self'; img-src 'self' https://*.example.com; style-src 'self' 'unsafe-inline'; connect-src 'self' https://*.examplpe.com wss://gateway.example.com; form-action 'self'",
},
{
key: 'feature-policy',
value:
"accelerometer 'none'; camera 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; payment 'none'; usb 'none'",
},
{
key: 'referrer-policy',
value: 'strict-origin-when-cross-origin',
},
{
key: 'strict-transport-security',
value: 'max-age=31536000; includesubdomains; preload',
},
{
key: 'x-content-type-options',
value: 'nosniff',
},
{
key: 'x-frame-options',
value: 'sameorigin',
},
{
key: 'x-xss-protection',
value: '1; mode=block',
},
],
},
],
};
const actual = getTransformedRoutes({ nowConfig });
assert.deepEqual(actual.routes, [
{
continue: true,
headers: {
'content-security-policy':
"default-src 'self'; script-src 'self'; img-src 'self' https://*.example.com; style-src 'self' 'unsafe-inline'; connect-src 'self' https://*.examplpe.com wss://gateway.example.com; form-action 'self'",
'feature-policy':
"accelerometer 'none'; camera 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; payment 'none'; usb 'none'",
'referrer-policy': 'strict-origin-when-cross-origin',
'strict-transport-security':
'max-age=31536000; includesubdomains; preload',
'x-content-type-options': 'nosniff',
'x-frame-options': 'sameorigin',
'x-xss-protection': '1; mode=block',
},
src: '^(?:/(.*))$',
},
]);
});
});

View File

@@ -1,7 +1,7 @@
{
"name": "@vercel/ruby",
"author": "Nathan Cahill <nathan@nathancahill.com>",
"version": "1.2.2-canary.0",
"version": "1.2.2-canary.1",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/ruby",
@@ -25,6 +25,6 @@
"execa": "2.0.4",
"fs-extra": "^7.0.1",
"semver": "6.1.1",
"typescript": "3.5.2"
"typescript": "3.9.3"
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/static-build",
"version": "0.17.2-canary.0",
"version": "0.17.2-canary.1",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/static-builds",
@@ -27,6 +27,6 @@
"is-port-reachable": "2.0.1",
"ms": "2.1.2",
"node-fetch": "2.6.0",
"typescript": "3.5.2"
"typescript": "3.9.3"
}
}

2626
yarn.lock

File diff suppressed because it is too large Load Diff