Compare commits

...

10 Commits

Author SHA1 Message Date
Steven
4e52f8532b Publish Canary
- @vercel/build-utils@2.12.3-canary.7
 - vercel@23.1.3-canary.9
 - @vercel/client@10.2.3-canary.7
 - @vercel/go@1.2.4-canary.3
 - @vercel/node@1.12.2-canary.4
 - @vercel/python@2.0.6-canary.4
 - @vercel/ruby@1.2.8-canary.3
2021-09-21 22:20:00 -04:00
Steven
702cb9e29c [all] Revert to @vercel/ncc@0.24.0 (#6749) 2021-09-21 22:17:06 -04:00
jj@jjsweb.site
d3d5555d79 Publish Canary
- @vercel/build-utils@2.12.3-canary.6
 - vercel@23.1.3-canary.8
 - @vercel/client@10.2.3-canary.6
 - @vercel/frameworks@0.5.1-canary.5
 - @vercel/routing-utils@1.11.4-canary.2
2021-09-20 19:35:05 -05:00
JJ Kasper
2fd3fc73e5 [routing-utils] Allow passing internal params to convertRewrites (#6742)
This adds an argument to allow passing internal param names that should be ignored when considering whether params should be auto-added to a rewrite's destination query. After adding this we should be able to resolve https://github.com/vercel/next.js/issues/27563 in the runtime where `convertRewrites` is called. 

This matches Next.js' handling for internal params which can be seen [here](e90825ad88/packages/next/shared/lib/router/utils/prepare-destination.ts (L203))

### Related Issues

x-ref: https://github.com/vercel/next.js/issues/27563

### 📋 Checklist

<!--
  Please keep your PR as a Draft until the checklist is complete
-->

#### Tests

- [x] The code changed/added as part of this PR has been covered with tests
- [x] All tests pass locally with `yarn test-unit`

#### Code Review

- [ ] This PR has a concise title and thorough description useful to a reviewer
- [ ] Issue from task tracker has a link to this PR
2021-09-21 00:15:29 +00:00
Steven
de0b13a46e Publish Canary
- vercel@23.1.3-canary.7
 - @vercel/node@1.12.2-canary.3
2021-09-16 12:54:47 -04:00
Steven
d0fe85db92 [node] Bump nft to 0.14.0 (#6727) 2021-09-16 12:49:04 -04:00
jj@jjsweb.site
bfbd927320 Publish Canary
- @vercel/build-utils@2.12.3-canary.5
 - vercel@23.1.3-canary.6
 - @vercel/client@10.2.3-canary.5
 - @vercel/frameworks@0.5.1-canary.4
 - @vercel/routing-utils@1.11.4-canary.1
2021-09-14 15:02:32 -05:00
JJ Kasper
90bacf88b8 [routing-utils] Fix host segment replacing (#6713)
* Fix host segment replacing

* Add additional check
2021-09-14 13:20:35 -05:00
Steven
07c369c542 Publish Canary
- @vercel/build-utils@2.12.3-canary.4
 - vercel@23.1.3-canary.5
 - @vercel/client@10.2.3-canary.4
 - @vercel/go@1.2.4-canary.2
 - @vercel/node@1.12.2-canary.2
 - @vercel/python@2.0.6-canary.3
 - @vercel/ruby@1.2.8-canary.2
2021-09-13 16:32:45 -04:00
Steven
a2e4186ccb [all] Bump ncc to 0.31.1 (#6700)
https://github.com/vercel/ncc/releases/tag/0.31.0

https://github.com/vercel/ncc/releases/tag/0.31.1
2021-09-13 20:20:48 +00:00
15 changed files with 378 additions and 234 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/build-utils",
"version": "2.12.3-canary.3",
"version": "2.12.3-canary.7",
"license": "MIT",
"main": "./dist/index.js",
"types": "./dist/index.d.js",
@@ -30,8 +30,8 @@
"@types/node-fetch": "^2.1.6",
"@types/semver": "6.0.0",
"@types/yazl": "^2.4.1",
"@vercel/frameworks": "0.5.1-canary.3",
"@vercel/ncc": "0.29.2",
"@vercel/frameworks": "0.5.1-canary.5",
"@vercel/ncc": "0.24.0",
"aggregate-error": "3.0.1",
"async-retry": "1.2.3",
"async-sema": "2.1.4",

View File

@@ -1,6 +1,6 @@
{
"name": "vercel",
"version": "23.1.3-canary.4",
"version": "23.1.3-canary.9",
"preferGlobal": true,
"license": "Apache-2.0",
"description": "The command-line interface for Vercel",
@@ -43,11 +43,11 @@
"node": ">= 12"
},
"dependencies": {
"@vercel/build-utils": "2.12.3-canary.3",
"@vercel/go": "1.2.4-canary.1",
"@vercel/node": "1.12.2-canary.1",
"@vercel/python": "2.0.6-canary.2",
"@vercel/ruby": "1.2.8-canary.1",
"@vercel/build-utils": "2.12.3-canary.7",
"@vercel/go": "1.2.4-canary.3",
"@vercel/node": "1.12.2-canary.4",
"@vercel/python": "2.0.6-canary.4",
"@vercel/ruby": "1.2.8-canary.3",
"update-notifier": "4.1.0"
},
"devDependencies": {
@@ -87,8 +87,8 @@
"@types/update-notifier": "5.1.0",
"@types/which": "1.3.2",
"@types/write-json-file": "2.2.1",
"@vercel/frameworks": "0.5.1-canary.3",
"@vercel/ncc": "0.29.2",
"@vercel/frameworks": "0.5.1-canary.5",
"@vercel/ncc": "0.24.0",
"@zeit/fun": "0.11.2",
"@zeit/source-map-support": "0.6.2",
"ajv": "6.12.2",

View File

@@ -49,19 +49,12 @@ async function main() {
// Do the initial `ncc` build
console.log();
const src = join(dirRoot, 'src/index.ts');
const args = [
'ncc',
'build',
'--no-asset-builds',
'--external',
'update-notifier',
];
const args = ['ncc', 'build', '--external', 'update-notifier'];
if (isDev) {
args.push('--source-map');
}
args.push(src);
await execa('yarn', args, { stdio: 'inherit' });
args.push('src/index.ts');
await execa('yarn', args, { stdio: 'inherit', cwd: dirRoot });
// `ncc` has some issues with `@zeit/fun`'s runtime files:
// - Executable bits on the `bootstrap` files appear to be lost:

View File

@@ -587,20 +587,93 @@ const main = async () => {
}
}
if (!targetCommand) {
const sub = param(subcommand);
console.error(error(`The ${sub} subcommand does not exist`));
return 1;
}
const metric = metrics();
let exitCode;
const eventCategory = 'Exit Code';
try {
const start = Date.now();
const full = require(`./commands/${targetCommand}`).default;
exitCode = await full(client);
let func: any;
switch (targetCommand) {
case 'alias':
func = await import('./commands/alias');
break;
case 'billing':
func = await import('./commands/billing');
break;
case 'certs':
func = await import('./commands/certs');
break;
case 'deploy':
func = await import('./commands/deploy');
break;
case 'dev':
func = await import('./commands/dev');
break;
case 'dns':
func = await import('./commands/dns');
break;
case 'domains':
func = await import('./commands/domains');
break;
case 'env':
func = await import('./commands/env');
break;
case 'init':
func = await import('./commands/init');
break;
case 'inspect':
func = await import('./commands/inspect');
break;
case 'link':
func = await import('./commands/link');
break;
case 'list':
func = await import('./commands/list');
break;
case 'logs':
func = await import('./commands/logs');
break;
case 'login':
func = await import('./commands/login');
break;
case 'logout':
func = await import('./commands/logout');
break;
case 'projects':
func = await import('./commands/projects');
break;
case 'remove':
func = await import('./commands/remove');
break;
case 'secrets':
func = await import('./commands/secrets');
break;
case 'teams':
func = await import('./commands/teams');
break;
case 'update':
func = await import('./commands/update');
break;
case 'whoami':
func = await import('./commands/whoami');
break;
default:
func = null;
break;
}
if (!func || !targetCommand) {
const sub = param(subcommand);
output.error(`The ${sub} subcommand does not exist`);
return 1;
}
if (func.default) {
func = func.default;
}
exitCode = await func(client);
const end = Date.now() - start;
if (shouldCollectMetrics) {

View File

@@ -1,6 +1,5 @@
{
"compilerOptions": {
"baseUrl": ".",
"strict": true,
"noEmitOnError": true,
"noFallthroughCasesInSwitch": true,

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/client",
"version": "10.2.3-canary.3",
"version": "10.2.3-canary.7",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"homepage": "https://vercel.com",
@@ -40,7 +40,7 @@
]
},
"dependencies": {
"@vercel/build-utils": "2.12.3-canary.3",
"@vercel/build-utils": "2.12.3-canary.7",
"@zeit/fetch": "5.2.0",
"async-retry": "1.2.3",
"async-sema": "3.0.0",

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/frameworks",
"version": "0.5.1-canary.3",
"version": "0.5.1-canary.5",
"main": "./dist/frameworks.js",
"types": "./dist/frameworks.d.ts",
"files": [
@@ -20,7 +20,7 @@
"@types/js-yaml": "3.12.1",
"@types/node": "12.0.4",
"@types/node-fetch": "2.5.8",
"@vercel/routing-utils": "1.11.4-canary.0",
"@vercel/routing-utils": "1.11.4-canary.2",
"ajv": "6.12.2",
"typescript": "4.3.4"
}

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/go",
"version": "1.2.4-canary.1",
"version": "1.2.4-canary.3",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/go",
@@ -24,7 +24,7 @@
"@types/fs-extra": "^5.0.5",
"@types/node-fetch": "^2.3.0",
"@types/tar": "^4.0.0",
"@vercel/ncc": "0.29.2",
"@vercel/ncc": "0.24.0",
"async-retry": "1.3.1",
"execa": "^1.0.0",
"fs-extra": "^7.0.0",

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/node",
"version": "1.12.2-canary.1",
"version": "1.12.2-canary.4",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/node-js",
@@ -32,8 +32,8 @@
"@types/cookie": "0.3.3",
"@types/etag": "1.8.0",
"@types/test-listen": "1.1.0",
"@vercel/ncc": "0.29.2",
"@vercel/nft": "0.13.1",
"@vercel/ncc": "0.24.0",
"@vercel/nft": "0.14.0",
"@vercel/node-bridge": "2.1.1-canary.1",
"content-type": "1.0.4",
"cookie": "0.4.0",

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/python",
"version": "2.0.6-canary.2",
"version": "2.0.6-canary.4",
"main": "./dist/index.js",
"license": "MIT",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/python",
@@ -20,7 +20,7 @@
},
"devDependencies": {
"@types/execa": "^0.9.0",
"@vercel/ncc": "0.29.2",
"@vercel/ncc": "0.24.0",
"execa": "^1.0.0",
"typescript": "4.3.4"
}

View File

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

View File

@@ -77,12 +77,21 @@ export function convertRedirects(
});
}
export function convertRewrites(rewrites: Rewrite[]): Route[] {
export function convertRewrites(
rewrites: Rewrite[],
internalParamNames?: string[]
): Route[] {
return rewrites.map(r => {
const { src, segments } = sourceToRegex(r.source);
const hasSegments = collectHasSegments(r.has);
try {
const dest = replaceSegments(segments, hasSegments, r.destination);
const dest = replaceSegments(
segments,
hasSegments,
r.destination,
false,
internalParamNames
);
const route: Route = { src, dest, check: true };
if (r.has) {
@@ -211,91 +220,118 @@ export function collectHasSegments(has?: HasField) {
return [...hasSegments];
}
const escapeSegment = (str: string, segmentName: string) =>
str.replace(new RegExp(`:${segmentName}`, 'g'), `__ESC_COLON_${segmentName}`);
const unescapeSegments = (str: string) => str.replace(/__ESC_COLON_/gi, ':');
function replaceSegments(
segments: string[],
hasItemSegments: string[],
destination: string,
isRedirect?: boolean
isRedirect?: boolean,
internalParamNames?: string[]
): string {
const parsedDestination = parseUrl(destination, true);
const namedSegments = segments.filter(name => name !== UN_NAMED_SEGMENT);
const canNeedReplacing =
(destination.includes(':') && namedSegments.length > 0) ||
hasItemSegments.length > 0 ||
!isRedirect;
if (!canNeedReplacing) {
return destination;
}
let escapedDestination = destination;
const indexes: { [k: string]: string } = {};
segments.forEach((name, index) => {
indexes[name] = toSegmentDest(index);
escapedDestination = escapeSegment(escapedDestination, name);
});
// 'has' matches override 'source' matches
hasItemSegments.forEach(name => {
indexes[name] = '$' + name;
escapedDestination = escapeSegment(escapedDestination, name);
});
const parsedDestination = parseUrl(escapedDestination, true);
delete (parsedDestination as any).href;
delete (parsedDestination as any).path;
delete (parsedDestination as any).search;
delete (parsedDestination as any).host;
// eslint-disable-next-line prefer-const
let { pathname, hash, query, ...rest } = parsedDestination;
pathname = pathname || '';
hash = hash || '';
let { pathname, hash, query, hostname, ...rest } = parsedDestination;
pathname = unescapeSegments(pathname || '');
hash = unescapeSegments(hash || '');
hostname = unescapeSegments(hostname || '');
const namedSegments = segments.filter(name => name !== UN_NAMED_SEGMENT);
let destParams = new Set<string>();
if (namedSegments.length > 0 || hasItemSegments.length > 0) {
const indexes: { [k: string]: string } = {};
segments.forEach((name, index) => {
indexes[name] = toSegmentDest(index);
});
const pathnameKeys: Key[] = [];
const hashKeys: Key[] = [];
const hostnameKeys: Key[] = [];
// 'has' matches override 'source' matches
hasItemSegments.forEach(name => {
indexes[name] = '$' + name;
});
let destParams = new Set<string>();
if (destination.includes(':')) {
const pathnameKeys: Key[] = [];
const hashKeys: Key[] = [];
try {
pathToRegexp(pathname, pathnameKeys);
pathToRegexp(hash || '', hashKeys);
} catch (_) {
// this is not fatal so don't error when failing to parse the
// params from the destination
}
destParams = new Set(
[...pathnameKeys, ...hashKeys]
.map(key => key.name)
.filter(val => typeof val === 'string') as string[]
);
pathname = safelyCompile(pathname, indexes, true);
hash = hash ? safelyCompile(hash, indexes, true) : null;
for (const [key, strOrArray] of Object.entries(query)) {
if (Array.isArray(strOrArray)) {
query[key] = strOrArray.map(str => safelyCompile(str, indexes, true));
} else {
query[key] = safelyCompile(strOrArray, indexes, true);
}
}
}
// We only add path segments to redirect queries if manually
// specified and only automatically add them for rewrites if one
// or more params aren't already used in the destination's path
const paramKeys = Object.keys(indexes);
if (!isRedirect && !paramKeys.some(param => destParams.has(param))) {
for (const param of paramKeys) {
if (!(param in query) && param !== UN_NAMED_SEGMENT) {
query[param] = indexes[param];
}
}
}
destination = formatUrl({
...rest,
pathname,
query,
hash,
});
// url.format() escapes the dollar sign but it must be preserved for now-proxy
destination = destination.replace(/%24/g, '$');
try {
pathToRegexp(pathname, pathnameKeys);
pathToRegexp(hash || '', hashKeys);
pathToRegexp(hostname || '', hostnameKeys);
} catch (_) {
// this is not fatal so don't error when failing to parse the
// params from the destination
}
return destination;
destParams = new Set(
[...pathnameKeys, ...hashKeys, ...hostnameKeys]
.map(key => key.name)
.filter(val => typeof val === 'string') as string[]
);
pathname = safelyCompile(pathname, indexes, true);
hash = hash ? safelyCompile(hash, indexes, true) : null;
hostname = hostname ? safelyCompile(hostname, indexes, true) : null;
for (const [key, strOrArray] of Object.entries(query)) {
if (Array.isArray(strOrArray)) {
query[key] = strOrArray.map(str =>
safelyCompile(unescapeSegments(str), indexes, true)
);
} else {
query[key] = safelyCompile(unescapeSegments(strOrArray), indexes, true);
}
}
// We only add path segments to redirect queries if manually
// specified and only automatically add them for rewrites if one
// or more params aren't already used in the destination's path
const paramKeys = Object.keys(indexes);
const needsQueryUpdating =
// we do not consider an internal param since it is added automatically
!isRedirect &&
!paramKeys.some(
param =>
!(internalParamNames && internalParamNames.includes(param)) &&
destParams.has(param)
);
if (needsQueryUpdating) {
for (const param of paramKeys) {
if (!(param in query) && param !== UN_NAMED_SEGMENT) {
query[param] = indexes[param];
}
}
}
destination = formatUrl({
...rest,
hostname,
pathname,
query,
hash,
});
// url.format() escapes the dollar sign but it must be preserved for now-proxy
return destination.replace(/%24/g, '$');
}
function safelyCompile(

View File

@@ -147,6 +147,11 @@ test('convertCleanUrls false', () => {
test('convertRedirects', () => {
const actual = convertRedirects([
{
source: '/(.*)',
has: [{ type: 'host', value: '(?<subdomain>.*)-test.vercel.app' }],
destination: 'https://:subdomain.example.com/some-path/end?a=b',
},
{ source: '/some/old/path', destination: '/some/new/path' },
{ source: '/next(\\.js)?', destination: 'https://nextjs.org' },
{
@@ -256,6 +261,19 @@ test('convertRedirects', () => {
]);
const expected = [
{
has: [
{
type: 'host',
value: '(?<subdomain>.*)-test.vercel.app',
},
],
headers: {
Location: 'https://$subdomain.example.com/some-path/end?a=b',
},
src: '^(?:\\/(.*))$',
status: 308,
},
{
src: '^\\/some\\/old\\/path$',
headers: { Location: '/some/new/path' },
@@ -406,6 +424,7 @@ test('convertRedirects', () => {
deepEqual(actual, expected);
const mustMatch = [
['/hello'],
['/some/old/path'],
['/next', '/next.js'],
['/proxy/one', '/proxy/2', '/proxy/-', '/proxy/dir/sub'],
@@ -427,6 +446,7 @@ test('convertRedirects', () => {
];
const mustNotMatch = [
[],
['/nope'],
['/nextAjs', '/nextjs'],
['/prox', '/proxyed/two'],
@@ -451,120 +471,133 @@ test('convertRedirects', () => {
});
test('convertRewrites', () => {
const actual = convertRewrites([
{ source: '/some/old/path', destination: '/some/new/path' },
{ source: '/proxy/(.*)', destination: 'https://www.firebase.com' },
{
source: '/proxy-regex/([a-zA-Z]{1,})',
destination: 'https://firebase.com/$1',
},
{
source: '/proxy-port/([a-zA-Z]{1,})',
destination: 'https://firebase.com:8080/$1',
},
{ source: '/projects/:id/edit', destination: '/projects.html' },
{
source: '/users/:id',
destination: '/api/user?identifier=:id&version=v2',
},
{
source: '/:file/:id',
destination: '/:file/get?identifier=:id',
},
{
source: '/qs-and-hash/:id/:hash',
destination: '/api/get?identifier=:id#:hash',
},
{
source: '/fullurl',
destination:
'https://user:pass@sub.example.com:8080/path/goes/here?v=1&id=2#hash',
},
{
source: '/dont-override-qs/:name/:age',
destination: '/final?name=bob&age=',
},
{ source: '/catchall/:hello*/', destination: '/catchall/:hello*' },
{
source: '/another-catch/:hello+/',
destination: '/another-catch/:hello+',
},
{ source: '/catchme/:id*', destination: '/api/user' },
{ source: '/:path', destination: '/test?path=:path' },
{ source: '/:path/:two', destination: '/test?path=:path' },
{ source: '/(.*)-:id(\\d+).html', destination: '/blog/:id' },
{
source: '/feature-{:slug}',
destination: '/blog-{:slug}',
},
{
source: '/hello/:world',
destination: '/somewhere?else={:world}',
},
{
source: '/hello/:first',
destination: '/another/:a/:b',
has: [
{
type: 'host',
value: '(?<a>.*)\\.(?<b>.*)',
},
],
},
{
source: '/hello/:first',
destination:
'/another/:first/:username/:pathname/:another/:host/:a/:b/:c/:d',
has: [
{
type: 'header',
key: 'x-rewrite',
},
{
type: 'cookie',
key: 'loggedIn',
value: '1',
},
{
type: 'host',
value: 'vercel.com',
},
{
type: 'host',
value: '(?<a>.*)\\.(?<b>.*)',
},
{
type: 'header',
key: 'host',
value: '(?<c>.*)\\.(?<d>.*)',
},
{
type: 'query',
key: 'username',
},
{
type: 'header',
key: 'x-pathname',
value: '(?<pathname>.*)',
},
{
type: 'header',
key: 'X-Pathname',
value: '(?<another>hello|world)',
},
],
},
{
source: '/array-query-string/:id/:name',
destination: 'https://example.com/?tag=1&tag=2',
},
]);
const actual = convertRewrites(
[
{ source: '/some/old/path', destination: '/some/new/path' },
{ source: '/proxy/(.*)', destination: 'https://www.firebase.com' },
{ source: '/proxy/(.*)', destination: 'https://www.firebase.com/' },
{
source: '/proxy-regex/([a-zA-Z]{1,})',
destination: 'https://firebase.com/$1',
},
{
source: '/proxy-port/([a-zA-Z]{1,})',
destination: 'https://firebase.com:8080/$1',
},
{ source: '/projects/:id/edit', destination: '/projects.html' },
{
source: '/users/:id',
destination: '/api/user?identifier=:id&version=v2',
},
{
source: '/:file/:id',
destination: '/:file/get?identifier=:id',
},
{
source: '/qs-and-hash/:id/:hash',
destination: '/api/get?identifier=:id#:hash',
},
{
source: '/fullurl',
destination:
'https://user:pass@sub.example.com:8080/path/goes/here?v=1&id=2#hash',
},
{
source: '/dont-override-qs/:name/:age',
destination: '/final?name=bob&age=',
},
{ source: '/catchall/:hello*/', destination: '/catchall/:hello*' },
{
source: '/another-catch/:hello+/',
destination: '/another-catch/:hello+',
},
{ source: '/catchme/:id*', destination: '/api/user' },
{ source: '/:path', destination: '/test?path=:path' },
{ source: '/:path/:two', destination: '/test?path=:path' },
{ source: '/(.*)-:id(\\d+).html', destination: '/blog/:id' },
{
source: '/feature-{:slug}',
destination: '/blog-{:slug}',
},
{
source: '/hello/:world',
destination: '/somewhere?else={:world}',
},
{
source: '/hello/:first',
destination: '/another/:a/:b',
has: [
{
type: 'host',
value: '(?<a>.*)\\.(?<b>.*)',
},
],
},
{
source: '/hello/:first',
destination:
'/another/:first/:username/:pathname/:another/:host/:a/:b/:c/:d',
has: [
{
type: 'header',
key: 'x-rewrite',
},
{
type: 'cookie',
key: 'loggedIn',
value: '1',
},
{
type: 'host',
value: 'vercel.com',
},
{
type: 'host',
value: '(?<a>.*)\\.(?<b>.*)',
},
{
type: 'header',
key: 'host',
value: '(?<c>.*)\\.(?<d>.*)',
},
{
type: 'query',
key: 'username',
},
{
type: 'header',
key: 'x-pathname',
value: '(?<pathname>.*)',
},
{
type: 'header',
key: 'X-Pathname',
value: '(?<another>hello|world)',
},
],
},
{
source: '/array-query-string/:id/:name',
destination: 'https://example.com/?tag=1&tag=2',
},
{
source: '/:nextInternalLocale/:path',
destination: '/api/hello',
},
],
['nextInternalLocale']
);
const expected = [
{ src: '^\\/some\\/old\\/path$', dest: '/some/new/path', check: true },
{
src: '^\\/proxy(?:\\/(.*))$',
dest: 'https://www.firebase.com',
dest: 'https://www.firebase.com/',
check: true,
},
{
src: '^\\/proxy(?:\\/(.*))$',
dest: 'https://www.firebase.com/',
check: true,
},
{
@@ -702,6 +735,11 @@ test('convertRewrites', () => {
dest: 'https://example.com/?tag=1&tag=2&id=$1&name=$2',
check: true,
},
{
check: true,
dest: '/api/hello?nextInternalLocale=$1&path=$2',
src: '^(?:\\/([^\\/]+?))(?:\\/([^\\/]+?))$',
},
];
deepEqual(actual, expected);
@@ -709,6 +747,7 @@ test('convertRewrites', () => {
const mustMatch = [
['/some/old/path'],
['/proxy/one', '/proxy/two'],
['/proxy/one', '/proxy/two'],
['/proxy-regex/admin', '/proxy-regex/anotherAdmin'],
['/proxy-port/admin', '/proxy-port/anotherAdmin'],
['/projects/one/edit', '/projects/two/edit'],
@@ -728,11 +767,13 @@ test('convertRewrites', () => {
['/hello/world'],
['/hello/world'],
['/array-query-string/10/email'],
['/en/hello'],
];
const mustNotMatch = [
['/nope'],
['/prox', '/proxyed/two'],
['/prox', '/proxyed/two'],
['/proxy-regex/user/1', '/proxy-regex/another/1'],
['/proxy-port/user/1', '/proxy-port/another/1'],
['/projects/edit', '/projects/two/delete', '/projects'],
@@ -752,6 +793,7 @@ test('convertRewrites', () => {
['/hllooo'],
['/hllooo'],
['/array-query-string/10'],
['/en/hello/world', '/en/hello/'],
];
assertRegexMatches(actual, mustMatch, mustNotMatch);

View File

@@ -1,7 +1,7 @@
{
"name": "@vercel/ruby",
"author": "Nathan Cahill <nathan@nathancahill.com>",
"version": "1.2.8-canary.1",
"version": "1.2.8-canary.3",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/ruby",
@@ -22,7 +22,7 @@
"devDependencies": {
"@types/fs-extra": "8.0.0",
"@types/semver": "6.0.0",
"@vercel/ncc": "0.29.2",
"@vercel/ncc": "0.24.0",
"execa": "2.0.4",
"fs-extra": "^7.0.1",
"semver": "6.1.1",

View File

@@ -2493,19 +2493,20 @@
"@typescript-eslint/types" "4.28.0"
eslint-visitor-keys "^2.0.0"
"@vercel/ncc@0.29.2":
version "0.29.2"
resolved "https://registry.yarnpkg.com/@vercel/ncc/-/ncc-0.29.2.tgz#29a35d21b03267a538b536168af766f4270ae8f4"
integrity sha512-eUxibZD92k+rY0oZJFZooGqdVpGkDrrHlUhj9UAWrtoyXCGmNOWC1Kcr2KPrZoHRSlWwHOcRnkn2nGT+aHY2KA==
"@vercel/ncc@0.24.0":
version "0.24.0"
resolved "https://registry.yarnpkg.com/@vercel/ncc/-/ncc-0.24.0.tgz#a2e8783a185caa99b5d8961a57dfc9665de16296"
integrity sha512-crqItMcIwCkvdXY/V3/TzrHJQx6nbIaRqE1cOopJhgGX6izvNov40SmD//nS5flfEvdK54YGjwVVq+zG6crjOg==
"@vercel/nft@0.13.1":
version "0.13.1"
resolved "https://registry.yarnpkg.com/@vercel/nft/-/nft-0.13.1.tgz#98df07e04620069ba63fff92af490c5842a2f31f"
integrity sha512-7pBTfSkwhhcPAeGVsFml5YX7LCZgtocP+zTAknnRK2u/RsV3GGqOD5yw7CtbgTpfjY8NfXWzwoxF1zOUEVsbww==
"@vercel/nft@0.14.0":
version "0.14.0"
resolved "https://registry.yarnpkg.com/@vercel/nft/-/nft-0.14.0.tgz#e9a6c33508881837ede68d59763fa1dc9fab7cbb"
integrity sha512-E3fVM+/ZygEs4AS9Wyx/ZyzpvjGMs20E0IfuqGgixUIj0Xnebl0260WqVvKLVuw/Z9oK4ZwoC+n/6JIMWivpfw==
dependencies:
"@mapbox/node-pre-gyp" "^1.0.5"
acorn "^8.3.0"
acorn-class-fields "^1.0.0"
acorn-private-class-elements "^1.0.0"
acorn-static-class-features "^1.0.0"
bindings "^1.4.0"
estree-walker "^0.6.1"