mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-24 19:00:03 +00:00
Compare commits
7 Commits
@now/next@
...
@now/next@
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f128e69e6 | ||
|
|
f1487c92cb | ||
|
|
45066cdf44 | ||
|
|
7dde9c8207 | ||
|
|
fd964f825d | ||
|
|
1656c9874e | ||
|
|
d999a3b2ad |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@now/build-utils",
|
||||
"version": "2.0.0",
|
||||
"version": "2.0.1-canary.0",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.js",
|
||||
|
||||
@@ -80,6 +80,7 @@ export async function detectBuilders(
|
||||
warnings: ErrorResponse[];
|
||||
defaultRoutes: Route[] | null;
|
||||
redirectRoutes: Route[] | null;
|
||||
rewriteRoutes: Route[] | null;
|
||||
}> {
|
||||
const errors: ErrorResponse[] = [];
|
||||
const warnings: ErrorResponse[] = [];
|
||||
@@ -87,9 +88,6 @@ export async function detectBuilders(
|
||||
const apiBuilders: Builder[] = [];
|
||||
let frontendBuilder: Builder | null = null;
|
||||
|
||||
const defaultRoutes: Route[] = [];
|
||||
const redirectRoutes: Route[] = [];
|
||||
|
||||
const functionError = validateFunctions(options);
|
||||
|
||||
if (functionError) {
|
||||
@@ -99,6 +97,7 @@ export async function detectBuilders(
|
||||
warnings,
|
||||
defaultRoutes: null,
|
||||
redirectRoutes: null,
|
||||
rewriteRoutes: null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -153,6 +152,7 @@ export async function detectBuilders(
|
||||
warnings,
|
||||
defaultRoutes: null,
|
||||
redirectRoutes: null,
|
||||
rewriteRoutes: null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -224,6 +224,7 @@ export async function detectBuilders(
|
||||
builders: null,
|
||||
redirectRoutes: null,
|
||||
defaultRoutes: null,
|
||||
rewriteRoutes: null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -264,6 +265,7 @@ export async function detectBuilders(
|
||||
warnings,
|
||||
redirectRoutes: null,
|
||||
defaultRoutes: null,
|
||||
rewriteRoutes: null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -294,15 +296,13 @@ export async function detectBuilders(
|
||||
options
|
||||
);
|
||||
|
||||
defaultRoutes.push(...routesResult.defaultRoutes);
|
||||
redirectRoutes.push(...routesResult.redirectRoutes);
|
||||
|
||||
return {
|
||||
warnings,
|
||||
builders: builders.length ? builders : null,
|
||||
errors: errors.length ? errors : null,
|
||||
redirectRoutes,
|
||||
defaultRoutes,
|
||||
redirectRoutes: routesResult.redirectRoutes,
|
||||
defaultRoutes: routesResult.defaultRoutes,
|
||||
rewriteRoutes: routesResult.rewriteRoutes,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -835,10 +835,10 @@ function createRouteFromPath(
|
||||
} else if (isLast) {
|
||||
const { name: fileName, ext } = parsePath(segment);
|
||||
const isIndex = fileName === 'index';
|
||||
const prefix = isIndex ? '\\/' : '';
|
||||
const prefix = isIndex ? '/' : '';
|
||||
|
||||
const names = [
|
||||
isIndex ? prefix : `${fileName}\\/`,
|
||||
isIndex ? prefix : `${fileName}/`,
|
||||
prefix + escapeName(fileName),
|
||||
featHandleMiss && cleanUrls
|
||||
? ''
|
||||
@@ -891,14 +891,14 @@ function mergeRoutes(
|
||||
): {
|
||||
defaultRoutes: Route[];
|
||||
redirectRoutes: Route[];
|
||||
rewriteRoutes: Route[];
|
||||
} {
|
||||
const defaultRoutes: Route[] = [];
|
||||
const redirectRoutes: Route[] = [];
|
||||
const rewriteRoutes: Route[] = [];
|
||||
|
||||
if (preDefaultRoutes && preDefaultRoutes.length > 0) {
|
||||
if (options.featHandleMiss) {
|
||||
defaultRoutes.push({ handle: 'miss' });
|
||||
|
||||
const extSet = detectApiExtensions(apiBuilders);
|
||||
|
||||
if (extSet.size > 0) {
|
||||
@@ -923,6 +923,7 @@ function mergeRoutes(
|
||||
status: 308,
|
||||
});
|
||||
} else {
|
||||
defaultRoutes.push({ handle: 'miss' });
|
||||
defaultRoutes.push({
|
||||
src: `^/api/(.+)${extGroup}$`,
|
||||
dest: '/api/$1',
|
||||
@@ -932,11 +933,11 @@ function mergeRoutes(
|
||||
}
|
||||
|
||||
if (preDynamicRoutes) {
|
||||
defaultRoutes.push(...preDynamicRoutes);
|
||||
rewriteRoutes.push(...preDynamicRoutes);
|
||||
}
|
||||
|
||||
if (preDefaultRoutes.length) {
|
||||
defaultRoutes.push({
|
||||
rewriteRoutes.push({
|
||||
src: '^/api(/.*)?$',
|
||||
status: 404,
|
||||
continue: true,
|
||||
@@ -969,6 +970,7 @@ function mergeRoutes(
|
||||
return {
|
||||
defaultRoutes,
|
||||
redirectRoutes,
|
||||
rewriteRoutes,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -906,11 +906,11 @@ it('Test `detectRoutes`', async () => {
|
||||
|
||||
expect(defaultRoutes!.length).toBe(3);
|
||||
expect((defaultRoutes![0] as any).src).toBe(
|
||||
'^/api/date(\\/|\\/index|\\/index\\.js)?$'
|
||||
'^/api/date(/|/index|/index\\.js)?$'
|
||||
);
|
||||
expect((defaultRoutes![0] as any).dest).toBe('/api/date/index.js');
|
||||
expect((defaultRoutes![1] as any).src).toBe(
|
||||
'^/api/(date\\/|date|date\\.js)$'
|
||||
'^/api/(date/|date|date\\.js)$'
|
||||
);
|
||||
expect((defaultRoutes![1] as any).dest).toBe('/api/date.js');
|
||||
}
|
||||
@@ -922,13 +922,13 @@ it('Test `detectRoutes`', async () => {
|
||||
|
||||
expect(defaultRoutes!.length).toBe(3);
|
||||
expect((defaultRoutes![0] as any).src).toBe(
|
||||
'^/api/([^/]+)(\\/|\\/index|\\/index\\.js)?$'
|
||||
'^/api/([^/]+)(/|/index|/index\\.js)?$'
|
||||
);
|
||||
expect((defaultRoutes![0] as any).dest).toBe(
|
||||
'/api/[date]/index.js?date=$1'
|
||||
);
|
||||
expect((defaultRoutes![1] as any).src).toBe(
|
||||
'^/api/(date\\/|date|date\\.js)$'
|
||||
'^/api/(date/|date|date\\.js)$'
|
||||
);
|
||||
expect((defaultRoutes![1] as any).dest).toBe('/api/date.js');
|
||||
}
|
||||
@@ -970,7 +970,7 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
|
||||
{
|
||||
const files = ['api/user.go', 'api/team.js', 'api/package.json'];
|
||||
|
||||
const { defaultRoutes } = await detectBuilders(files, null, {
|
||||
const { defaultRoutes, rewriteRoutes } = await detectBuilders(files, null, {
|
||||
featHandleMiss,
|
||||
});
|
||||
expect(defaultRoutes).toStrictEqual([
|
||||
@@ -980,6 +980,8 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
|
||||
dest: '/api/$1',
|
||||
check: true,
|
||||
},
|
||||
]);
|
||||
expect(rewriteRoutes).toStrictEqual([
|
||||
{
|
||||
status: 404,
|
||||
src: '^/api(/.*)?$',
|
||||
@@ -1022,7 +1024,7 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
|
||||
{
|
||||
const files = ['api/[endpoint].js', 'api/[endpoint]/[id].js'];
|
||||
|
||||
const { defaultRoutes } = await detectBuilders(files, null, {
|
||||
const { defaultRoutes, rewriteRoutes } = await detectBuilders(files, null, {
|
||||
featHandleMiss,
|
||||
});
|
||||
expect(defaultRoutes).toStrictEqual([
|
||||
@@ -1032,6 +1034,8 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
|
||||
dest: '/api/$1',
|
||||
check: true,
|
||||
},
|
||||
]);
|
||||
expect(rewriteRoutes).toStrictEqual([
|
||||
{
|
||||
src: '^/api/([^/]+)/([^/]+)$',
|
||||
dest: '/api/[endpoint]/[id]?endpoint=$1&id=$2',
|
||||
@@ -1057,7 +1061,7 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
|
||||
'api/[endpoint]/[id].js',
|
||||
];
|
||||
|
||||
const { defaultRoutes } = await detectBuilders(files, null, {
|
||||
const { defaultRoutes, rewriteRoutes } = await detectBuilders(files, null, {
|
||||
featHandleMiss,
|
||||
});
|
||||
expect(defaultRoutes).toStrictEqual([
|
||||
@@ -1067,6 +1071,9 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
|
||||
dest: '/api/$1',
|
||||
check: true,
|
||||
},
|
||||
]);
|
||||
|
||||
expect(rewriteRoutes).toStrictEqual([
|
||||
{
|
||||
src: '^/api/([^/]+)/([^/]+)$',
|
||||
dest: '/api/[endpoint]/[id]?endpoint=$1&id=$2',
|
||||
@@ -1098,7 +1105,7 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
|
||||
|
||||
const files = ['public/index.html', 'api/[endpoint].js'];
|
||||
|
||||
const { defaultRoutes } = await detectBuilders(files, pkg, {
|
||||
const { defaultRoutes, rewriteRoutes } = await detectBuilders(files, pkg, {
|
||||
featHandleMiss,
|
||||
});
|
||||
expect(defaultRoutes).toStrictEqual([
|
||||
@@ -1108,6 +1115,8 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
|
||||
dest: '/api/$1',
|
||||
check: true,
|
||||
},
|
||||
]);
|
||||
expect(rewriteRoutes).toStrictEqual([
|
||||
{
|
||||
src: '^/api/([^/]+)$',
|
||||
dest: '/api/[endpoint]?endpoint=$1',
|
||||
@@ -1133,7 +1142,7 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
|
||||
{
|
||||
const files = ['api/date/index.js', 'api/date.js'];
|
||||
|
||||
const { defaultRoutes } = await detectBuilders(files, null, {
|
||||
const { defaultRoutes, rewriteRoutes } = await detectBuilders(files, null, {
|
||||
featHandleMiss,
|
||||
});
|
||||
expect(defaultRoutes).toStrictEqual([
|
||||
@@ -1143,6 +1152,9 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
|
||||
dest: '/api/$1',
|
||||
check: true,
|
||||
},
|
||||
]);
|
||||
|
||||
expect(rewriteRoutes).toStrictEqual([
|
||||
{
|
||||
status: 404,
|
||||
src: '^/api(/.*)?$',
|
||||
@@ -1154,7 +1166,7 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
|
||||
{
|
||||
const files = ['api/date.js', 'api/[date]/index.js'];
|
||||
|
||||
const { defaultRoutes } = await detectBuilders(files, null, {
|
||||
const { defaultRoutes, rewriteRoutes } = await detectBuilders(files, null, {
|
||||
featHandleMiss,
|
||||
});
|
||||
expect(defaultRoutes).toStrictEqual([
|
||||
@@ -1164,8 +1176,10 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
|
||||
dest: '/api/$1',
|
||||
check: true,
|
||||
},
|
||||
]);
|
||||
expect(rewriteRoutes).toStrictEqual([
|
||||
{
|
||||
src: '^/api/([^/]+)(\\/|\\/index|\\/index\\.js)?$',
|
||||
src: '^/api/([^/]+)(/|/index|/index\\.js)?$',
|
||||
dest: '/api/[date]/index?date=$1',
|
||||
check: true,
|
||||
},
|
||||
@@ -1186,7 +1200,7 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
|
||||
'api/food.ts',
|
||||
'api/ts/gold.ts',
|
||||
];
|
||||
const { defaultRoutes } = await detectBuilders(files, null, {
|
||||
const { defaultRoutes, rewriteRoutes } = await detectBuilders(files, null, {
|
||||
featHandleMiss,
|
||||
});
|
||||
|
||||
@@ -1197,7 +1211,14 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
|
||||
dest: '/api/$1',
|
||||
check: true,
|
||||
},
|
||||
{ status: 404, src: '^/api(/.*)?$', continue: true },
|
||||
]);
|
||||
|
||||
expect(rewriteRoutes).toStrictEqual([
|
||||
{
|
||||
status: 404,
|
||||
src: '^/api(/.*)?$',
|
||||
continue: true,
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -1206,7 +1227,7 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
|
||||
const functions = { 'api/user.php': { runtime: 'now-php@0.0.8' } };
|
||||
const files = ['api/user.php'];
|
||||
|
||||
const { defaultRoutes } = await detectBuilders(files, null, {
|
||||
const { defaultRoutes, rewriteRoutes } = await detectBuilders(files, null, {
|
||||
functions,
|
||||
featHandleMiss,
|
||||
});
|
||||
@@ -1217,7 +1238,14 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
|
||||
dest: '/api/$1',
|
||||
check: true,
|
||||
},
|
||||
{ status: 404, src: '^/api(/.*)?$', continue: true },
|
||||
]);
|
||||
|
||||
expect(rewriteRoutes).toStrictEqual([
|
||||
{
|
||||
status: 404,
|
||||
src: '^/api(/.*)?$',
|
||||
continue: true,
|
||||
},
|
||||
]);
|
||||
}
|
||||
});
|
||||
@@ -1239,14 +1267,14 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
|
||||
{
|
||||
const files = ['api/user.go', 'api/team.js', 'api/package.json'];
|
||||
|
||||
const { defaultRoutes, redirectRoutes } = await detectBuilders(
|
||||
files,
|
||||
null,
|
||||
options
|
||||
);
|
||||
const {
|
||||
defaultRoutes,
|
||||
redirectRoutes,
|
||||
rewriteRoutes,
|
||||
} = await detectBuilders(files, null, options);
|
||||
testHeaders(redirectRoutes);
|
||||
expect(defaultRoutes).toStrictEqual([
|
||||
{ handle: 'miss' },
|
||||
expect(defaultRoutes).toStrictEqual([]);
|
||||
expect(rewriteRoutes).toStrictEqual([
|
||||
{
|
||||
status: 404,
|
||||
src: '^/api(/.*)?$',
|
||||
@@ -1317,14 +1345,14 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
|
||||
{
|
||||
const files = ['api/[endpoint].js', 'api/[endpoint]/[id].js'];
|
||||
|
||||
const { defaultRoutes, redirectRoutes } = await detectBuilders(
|
||||
files,
|
||||
null,
|
||||
options
|
||||
);
|
||||
const {
|
||||
defaultRoutes,
|
||||
redirectRoutes,
|
||||
rewriteRoutes,
|
||||
} = await detectBuilders(files, null, options);
|
||||
testHeaders(redirectRoutes);
|
||||
expect(defaultRoutes).toStrictEqual([
|
||||
{ handle: 'miss' },
|
||||
expect(defaultRoutes).toStrictEqual([]);
|
||||
expect(rewriteRoutes).toStrictEqual([
|
||||
{
|
||||
src: '^/api/([^/]+)/([^/]+)$',
|
||||
dest: '/api/[endpoint]/[id]?endpoint=$1&id=$2',
|
||||
@@ -1350,14 +1378,14 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
|
||||
'api/[endpoint]/[id].js',
|
||||
];
|
||||
|
||||
const { defaultRoutes, redirectRoutes } = await detectBuilders(
|
||||
files,
|
||||
null,
|
||||
options
|
||||
);
|
||||
const {
|
||||
defaultRoutes,
|
||||
redirectRoutes,
|
||||
rewriteRoutes,
|
||||
} = await detectBuilders(files, null, options);
|
||||
testHeaders(redirectRoutes);
|
||||
expect(defaultRoutes).toStrictEqual([
|
||||
{ handle: 'miss' },
|
||||
expect(defaultRoutes).toStrictEqual([]);
|
||||
expect(rewriteRoutes).toStrictEqual([
|
||||
{
|
||||
src: '^/api/([^/]+)/([^/]+)$',
|
||||
dest: '/api/[endpoint]/[id]?endpoint=$1&id=$2',
|
||||
@@ -1389,14 +1417,14 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
|
||||
|
||||
const files = ['public/index.html', 'api/[endpoint].js'];
|
||||
|
||||
const { defaultRoutes, redirectRoutes } = await detectBuilders(
|
||||
files,
|
||||
pkg,
|
||||
options
|
||||
);
|
||||
const {
|
||||
defaultRoutes,
|
||||
redirectRoutes,
|
||||
rewriteRoutes,
|
||||
} = await detectBuilders(files, pkg, options);
|
||||
testHeaders(redirectRoutes);
|
||||
expect(defaultRoutes).toStrictEqual([
|
||||
{ handle: 'miss' },
|
||||
expect(defaultRoutes).toStrictEqual([]);
|
||||
expect(rewriteRoutes).toStrictEqual([
|
||||
{
|
||||
src: '^/api/([^/]+)$',
|
||||
dest: '/api/[endpoint]?endpoint=$1',
|
||||
@@ -1420,14 +1448,14 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
|
||||
{
|
||||
const files = ['api/date/index.js', 'api/date.js'];
|
||||
|
||||
const { defaultRoutes, redirectRoutes } = await detectBuilders(
|
||||
files,
|
||||
null,
|
||||
options
|
||||
);
|
||||
const {
|
||||
defaultRoutes,
|
||||
redirectRoutes,
|
||||
rewriteRoutes,
|
||||
} = await detectBuilders(files, null, options);
|
||||
testHeaders(redirectRoutes);
|
||||
expect(defaultRoutes).toStrictEqual([
|
||||
{ handle: 'miss' },
|
||||
expect(defaultRoutes).toStrictEqual([]);
|
||||
expect(rewriteRoutes).toStrictEqual([
|
||||
{
|
||||
status: 404,
|
||||
src: '^/api(/.*)?$',
|
||||
@@ -1439,16 +1467,16 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
|
||||
{
|
||||
const files = ['api/date.js', 'api/[date]/index.js'];
|
||||
|
||||
const { defaultRoutes, redirectRoutes } = await detectBuilders(
|
||||
files,
|
||||
null,
|
||||
options
|
||||
);
|
||||
const {
|
||||
defaultRoutes,
|
||||
redirectRoutes,
|
||||
rewriteRoutes,
|
||||
} = await detectBuilders(files, null, options);
|
||||
testHeaders(redirectRoutes);
|
||||
expect(defaultRoutes).toStrictEqual([
|
||||
{ handle: 'miss' },
|
||||
expect(defaultRoutes).toStrictEqual([]);
|
||||
expect(rewriteRoutes).toStrictEqual([
|
||||
{
|
||||
src: '^/api/([^/]+)(\\/|\\/index)?$',
|
||||
src: '^/api/([^/]+)(/|/index)?$',
|
||||
dest: '/api/[date]/index?date=$1',
|
||||
check: true,
|
||||
},
|
||||
@@ -1469,15 +1497,19 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
|
||||
'api/food.ts',
|
||||
'api/ts/gold.ts',
|
||||
];
|
||||
const { defaultRoutes, redirectRoutes } = await detectBuilders(
|
||||
files,
|
||||
null,
|
||||
options
|
||||
);
|
||||
const {
|
||||
defaultRoutes,
|
||||
redirectRoutes,
|
||||
rewriteRoutes,
|
||||
} = await detectBuilders(files, null, options);
|
||||
testHeaders(redirectRoutes);
|
||||
expect(defaultRoutes).toStrictEqual([
|
||||
{ handle: 'miss' },
|
||||
{ status: 404, src: '^/api(/.*)?$', continue: true },
|
||||
expect(defaultRoutes).toStrictEqual([]);
|
||||
expect(rewriteRoutes).toStrictEqual([
|
||||
{
|
||||
status: 404,
|
||||
src: '^/api(/.*)?$',
|
||||
continue: true,
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -1486,15 +1518,19 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
|
||||
const functions = { 'api/user.php': { runtime: 'now-php@0.0.8' } };
|
||||
const files = ['api/user.php'];
|
||||
|
||||
const { defaultRoutes, redirectRoutes } = await detectBuilders(
|
||||
files,
|
||||
null,
|
||||
{ functions, ...options }
|
||||
);
|
||||
const {
|
||||
defaultRoutes,
|
||||
redirectRoutes,
|
||||
rewriteRoutes,
|
||||
} = await detectBuilders(files, null, { functions, ...options });
|
||||
testHeaders(redirectRoutes);
|
||||
expect(defaultRoutes).toStrictEqual([
|
||||
{ handle: 'miss' },
|
||||
{ status: 404, src: '^/api(/.*)?$', continue: true },
|
||||
expect(defaultRoutes).toStrictEqual([]);
|
||||
expect(rewriteRoutes).toStrictEqual([
|
||||
{
|
||||
status: 404,
|
||||
src: '^/api(/.*)?$',
|
||||
continue: true,
|
||||
},
|
||||
]);
|
||||
}
|
||||
});
|
||||
@@ -1517,14 +1553,14 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
|
||||
{
|
||||
const files = ['api/user.go', 'api/team.js', 'api/package.json'];
|
||||
|
||||
const { defaultRoutes, redirectRoutes } = await detectBuilders(
|
||||
files,
|
||||
null,
|
||||
options
|
||||
);
|
||||
const {
|
||||
defaultRoutes,
|
||||
redirectRoutes,
|
||||
rewriteRoutes,
|
||||
} = await detectBuilders(files, null, options);
|
||||
testHeaders(redirectRoutes);
|
||||
expect(defaultRoutes).toStrictEqual([
|
||||
{ handle: 'miss' },
|
||||
expect(defaultRoutes).toStrictEqual([]);
|
||||
expect(rewriteRoutes).toStrictEqual([
|
||||
{
|
||||
status: 404,
|
||||
src: '^/api(/.*)?$',
|
||||
@@ -1565,14 +1601,14 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
|
||||
{
|
||||
const files = ['api/[endpoint].js', 'api/[endpoint]/[id].js'];
|
||||
|
||||
const { defaultRoutes, redirectRoutes } = await detectBuilders(
|
||||
files,
|
||||
null,
|
||||
options
|
||||
);
|
||||
const {
|
||||
defaultRoutes,
|
||||
redirectRoutes,
|
||||
rewriteRoutes,
|
||||
} = await detectBuilders(files, null, options);
|
||||
testHeaders(redirectRoutes);
|
||||
expect(defaultRoutes).toStrictEqual([
|
||||
{ handle: 'miss' },
|
||||
expect(defaultRoutes).toStrictEqual([]);
|
||||
expect(rewriteRoutes).toStrictEqual([
|
||||
{
|
||||
src: '^/api/([^/]+)/([^/]+)$',
|
||||
dest: '/api/[endpoint]/[id]?endpoint=$1&id=$2',
|
||||
@@ -1598,14 +1634,14 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
|
||||
'api/[endpoint]/[id].js',
|
||||
];
|
||||
|
||||
const { defaultRoutes, redirectRoutes } = await detectBuilders(
|
||||
files,
|
||||
null,
|
||||
options
|
||||
);
|
||||
const {
|
||||
defaultRoutes,
|
||||
redirectRoutes,
|
||||
rewriteRoutes,
|
||||
} = await detectBuilders(files, null, options);
|
||||
testHeaders(redirectRoutes);
|
||||
expect(defaultRoutes).toStrictEqual([
|
||||
{ handle: 'miss' },
|
||||
expect(defaultRoutes).toStrictEqual([]);
|
||||
expect(rewriteRoutes).toStrictEqual([
|
||||
{
|
||||
src: '^/api/([^/]+)/([^/]+)$',
|
||||
dest: '/api/[endpoint]/[id]?endpoint=$1&id=$2',
|
||||
@@ -1637,14 +1673,14 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
|
||||
|
||||
const files = ['public/index.html', 'api/[endpoint].js'];
|
||||
|
||||
const { defaultRoutes, redirectRoutes } = await detectBuilders(
|
||||
files,
|
||||
pkg,
|
||||
options
|
||||
);
|
||||
const {
|
||||
defaultRoutes,
|
||||
redirectRoutes,
|
||||
rewriteRoutes,
|
||||
} = await detectBuilders(files, pkg, options);
|
||||
testHeaders(redirectRoutes);
|
||||
expect(defaultRoutes).toStrictEqual([
|
||||
{ handle: 'miss' },
|
||||
expect(defaultRoutes).toStrictEqual([]);
|
||||
expect(rewriteRoutes).toStrictEqual([
|
||||
{
|
||||
src: '^/api/([^/]+)$',
|
||||
dest: '/api/[endpoint]?endpoint=$1',
|
||||
@@ -1661,14 +1697,14 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
|
||||
{
|
||||
const files = ['api/date/index.js', 'api/date.js'];
|
||||
|
||||
const { defaultRoutes, redirectRoutes } = await detectBuilders(
|
||||
files,
|
||||
null,
|
||||
options
|
||||
);
|
||||
const {
|
||||
defaultRoutes,
|
||||
redirectRoutes,
|
||||
rewriteRoutes,
|
||||
} = await detectBuilders(files, null, options);
|
||||
testHeaders(redirectRoutes);
|
||||
expect(defaultRoutes).toStrictEqual([
|
||||
{ handle: 'miss' },
|
||||
expect(defaultRoutes).toStrictEqual([]);
|
||||
expect(rewriteRoutes).toStrictEqual([
|
||||
{
|
||||
status: 404,
|
||||
src: '^/api(/.*)?$',
|
||||
@@ -1680,16 +1716,16 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
|
||||
{
|
||||
const files = ['api/date.js', 'api/[date]/index.js'];
|
||||
|
||||
const { defaultRoutes, redirectRoutes } = await detectBuilders(
|
||||
files,
|
||||
null,
|
||||
options
|
||||
);
|
||||
const {
|
||||
defaultRoutes,
|
||||
redirectRoutes,
|
||||
rewriteRoutes,
|
||||
} = await detectBuilders(files, null, options);
|
||||
testHeaders(redirectRoutes);
|
||||
expect(defaultRoutes).toStrictEqual([
|
||||
{ handle: 'miss' },
|
||||
expect(defaultRoutes).toStrictEqual([]);
|
||||
expect(rewriteRoutes).toStrictEqual([
|
||||
{
|
||||
src: '^/api/([^/]+)(\\/|\\/index)?$',
|
||||
src: '^/api/([^/]+)(/|/index)?$',
|
||||
dest: '/api/[date]/index?date=$1',
|
||||
check: true,
|
||||
},
|
||||
@@ -1710,15 +1746,19 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
|
||||
'api/food.ts',
|
||||
'api/ts/gold.ts',
|
||||
];
|
||||
const { defaultRoutes, redirectRoutes } = await detectBuilders(
|
||||
files,
|
||||
null,
|
||||
options
|
||||
);
|
||||
const {
|
||||
defaultRoutes,
|
||||
redirectRoutes,
|
||||
rewriteRoutes,
|
||||
} = await detectBuilders(files, null, options);
|
||||
testHeaders(redirectRoutes);
|
||||
expect(defaultRoutes).toStrictEqual([
|
||||
{ handle: 'miss' },
|
||||
{ status: 404, src: '^/api(/.*)?$', continue: true },
|
||||
expect(defaultRoutes).toStrictEqual([]);
|
||||
expect(rewriteRoutes).toStrictEqual([
|
||||
{
|
||||
status: 404,
|
||||
src: '^/api(/.*)?$',
|
||||
continue: true,
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -1727,15 +1767,19 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
|
||||
const functions = { 'api/user.php': { runtime: 'now-php@0.0.8' } };
|
||||
const files = ['api/user.php'];
|
||||
|
||||
const { defaultRoutes, redirectRoutes } = await detectBuilders(
|
||||
files,
|
||||
null,
|
||||
{ functions, ...options }
|
||||
);
|
||||
const {
|
||||
defaultRoutes,
|
||||
redirectRoutes,
|
||||
rewriteRoutes,
|
||||
} = await detectBuilders(files, null, { functions, ...options });
|
||||
testHeaders(redirectRoutes);
|
||||
expect(defaultRoutes).toStrictEqual([
|
||||
{ handle: 'miss' },
|
||||
{ status: 404, src: '^/api(/.*)?$', continue: true },
|
||||
expect(defaultRoutes).toStrictEqual([]);
|
||||
expect(rewriteRoutes).toStrictEqual([
|
||||
{
|
||||
status: 404,
|
||||
src: '^/api(/.*)?$',
|
||||
continue: true,
|
||||
},
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "now",
|
||||
"version": "17.0.5-canary.1",
|
||||
"version": "17.0.5-canary.4",
|
||||
"preferGlobal": true,
|
||||
"license": "Apache-2.0",
|
||||
"description": "The command-line interface for Now",
|
||||
|
||||
@@ -566,6 +566,11 @@ export default async function main(
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (deployment.readyState === 'CANCELED') {
|
||||
output.log('The deployment has been canceled');
|
||||
return 1;
|
||||
}
|
||||
|
||||
const deploymentResponse = await getDeploymentByIdOrHost(
|
||||
now,
|
||||
contextName,
|
||||
|
||||
@@ -202,6 +202,13 @@ export default async function processDeployment({
|
||||
}
|
||||
}
|
||||
|
||||
if (event.type === 'canceled') {
|
||||
if (buildSpinner) {
|
||||
buildSpinner();
|
||||
}
|
||||
return event.payload;
|
||||
}
|
||||
|
||||
if (event.type === 'ready') {
|
||||
if (queuedSpinner) {
|
||||
queuedSpinner();
|
||||
|
||||
@@ -133,6 +133,9 @@ export async function devRouter(
|
||||
);
|
||||
if (missResult.found) {
|
||||
return missResult;
|
||||
} else {
|
||||
reqPathname = destPath;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (routeConfig.status && phase === 'miss') {
|
||||
|
||||
@@ -12,7 +12,11 @@ import serveHandler from 'serve-handler';
|
||||
import { watch, FSWatcher } from 'chokidar';
|
||||
import { parse as parseDotenv } from 'dotenv';
|
||||
import { basename, dirname, extname, join } from 'path';
|
||||
import { getTransformedRoutes, HandleValue } from '@now/routing-utils';
|
||||
import {
|
||||
getTransformedRoutes,
|
||||
appendRoutesToPhase,
|
||||
HandleValue,
|
||||
} from '@now/routing-utils';
|
||||
import directoryTemplate from 'serve-handler/src/directory';
|
||||
import getPort from 'get-port';
|
||||
import { ChildProcess } from 'child_process';
|
||||
@@ -553,6 +557,7 @@ export default class DevServer {
|
||||
errors,
|
||||
defaultRoutes,
|
||||
redirectRoutes,
|
||||
rewriteRoutes,
|
||||
} = await detectBuilders(files, pkg, {
|
||||
tag: getDistTag(cliVersion) === 'canary' ? 'canary' : 'latest',
|
||||
functions: config.functions,
|
||||
@@ -582,7 +587,13 @@ export default class DevServer {
|
||||
const routes: RouteConfig[] = [];
|
||||
const { routes: nowConfigRoutes } = config;
|
||||
routes.push(...(redirectRoutes || []));
|
||||
routes.push(...(nowConfigRoutes || []));
|
||||
routes.push(
|
||||
...appendRoutesToPhase({
|
||||
routes: nowConfigRoutes,
|
||||
newRoutes: rewriteRoutes,
|
||||
phase: 'filesystem',
|
||||
})
|
||||
);
|
||||
routes.push(...(defaultRoutes || []));
|
||||
config.routes = routes;
|
||||
}
|
||||
@@ -1176,6 +1187,35 @@ export default class DevServer {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This is the equivalent to now-proxy exit_with_status() function.
|
||||
*/
|
||||
exitWithStatus = async (
|
||||
match: BuildMatch | null,
|
||||
routeResult: RouteResult,
|
||||
phase: HandleValue | null,
|
||||
req: http.IncomingMessage,
|
||||
res: http.ServerResponse,
|
||||
nowRequestId: string
|
||||
): Promise<boolean> => {
|
||||
const { status, headers, dest } = routeResult;
|
||||
const location = headers['location'] || dest;
|
||||
|
||||
if (status && location && (300 <= status && status <= 399)) {
|
||||
this.output.debug(`Route found with redirect status code ${status}`);
|
||||
await this.sendRedirect(req, res, nowRequestId, location, status);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!match && status && phase !== 'miss') {
|
||||
this.output.debug(`Route found with with status code ${status}`);
|
||||
await this.sendError(req, res, nowRequestId, '', status);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Serve project directory as a Now v2 deployment.
|
||||
*/
|
||||
@@ -1259,6 +1299,19 @@ export default class DevServer {
|
||||
this
|
||||
);
|
||||
|
||||
if (
|
||||
await this.exitWithStatus(
|
||||
match,
|
||||
routeResult,
|
||||
phase,
|
||||
req,
|
||||
res,
|
||||
nowRequestId
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!match && missRoutes.length > 0) {
|
||||
// Since there was no build match, enter the miss phase
|
||||
routeResult = await devRouter(
|
||||
@@ -1277,6 +1330,18 @@ export default class DevServer {
|
||||
routeResult.dest,
|
||||
this
|
||||
);
|
||||
if (
|
||||
await this.exitWithStatus(
|
||||
match,
|
||||
routeResult,
|
||||
phase,
|
||||
req,
|
||||
res,
|
||||
nowRequestId
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
} else if (match && hitRoutes.length > 0) {
|
||||
// Since there was a build match, enter the hit phase.
|
||||
// The hit phase must not set status code.
|
||||
@@ -1295,28 +1360,6 @@ export default class DevServer {
|
||||
|
||||
statusCode = routeResult.status;
|
||||
|
||||
if (match && statusCode === 404 && routeResult.phase === 'miss') {
|
||||
statusCode = undefined;
|
||||
}
|
||||
|
||||
const location = routeResult.headers['location'] || routeResult.dest;
|
||||
|
||||
if (statusCode && location && (300 <= statusCode && statusCode <= 399)) {
|
||||
// Equivalent to now-proxy exit_with_status() function
|
||||
this.output.debug(
|
||||
`Route found with redirect status code ${statusCode}`
|
||||
);
|
||||
await this.sendRedirect(req, res, nowRequestId, location, statusCode);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!match && statusCode && routeResult.phase !== 'miss') {
|
||||
// Equivalent to now-proxy exit_with_status() function
|
||||
this.output.debug(`Route found with with status code ${statusCode}`);
|
||||
await this.sendError(req, res, nowRequestId, '', statusCode);
|
||||
return;
|
||||
}
|
||||
|
||||
if (match) {
|
||||
// end the phase
|
||||
break;
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Index Page
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"version": 2,
|
||||
"routes": [
|
||||
{ "handle": "filesystem" },
|
||||
{ "src": "/([^/]+/dir/.+)", "dest": "/$1.html", "check": true },
|
||||
{ "handle": "miss" },
|
||||
{ "src": "/pathA(?:/.+)?", "status": 404, "continue": true },
|
||||
{ "src": "/pathB(?:/.+)?", "status": 404, "continue": true }
|
||||
]
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
Path A
|
||||
@@ -1 +0,0 @@
|
||||
Path B
|
||||
@@ -1 +0,0 @@
|
||||
Path C
|
||||
@@ -10,14 +10,14 @@
|
||||
"dest": "/blog/$1",
|
||||
"check": true
|
||||
},
|
||||
{
|
||||
"handle": "miss"
|
||||
},
|
||||
{
|
||||
"src": "/.*",
|
||||
"status": 404,
|
||||
"continue": true
|
||||
},
|
||||
{
|
||||
"handle": "miss"
|
||||
},
|
||||
{
|
||||
"src": "/(.*)",
|
||||
"dest": "/src/$1",
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Index Page
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"version": 2,
|
||||
"routes": [
|
||||
{ "handle": "miss" },
|
||||
{ "src": "/pathA(?:/.+)?", "status": 404, "continue": true },
|
||||
{ "src": "/pathB(?:/.+)?", "status": 404, "continue": true }
|
||||
]
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
Path A
|
||||
@@ -1 +0,0 @@
|
||||
Path B
|
||||
@@ -1 +0,0 @@
|
||||
Path C
|
||||
@@ -1 +0,0 @@
|
||||
!public
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"functions": {
|
||||
"server/**/*.js": {
|
||||
"runtime": "@now/node@1.2.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
This is content.
|
||||
@@ -1,3 +0,0 @@
|
||||
export default (req, res) => {
|
||||
res.end(`current hour: ${Math.floor(Date.now() / 10000)}`);
|
||||
};
|
||||
@@ -0,0 +1,2 @@
|
||||
module.exports = (req, res) =>
|
||||
res.send(req.query.username);
|
||||
@@ -0,0 +1 @@
|
||||
module.exports = (req, res) => res.end('42');
|
||||
@@ -0,0 +1,2 @@
|
||||
module.exports = (req, res) =>
|
||||
res.send(req.query.id);
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"rewrites": [{ "source": "/rand", "destination": "/api/fourty-two" }]
|
||||
}
|
||||
@@ -411,28 +411,6 @@ test(
|
||||
})
|
||||
);
|
||||
|
||||
test(
|
||||
'[now dev] does not display directory listing after multiple 404',
|
||||
testFixtureStdio('handle-miss-multiple-404', async (t, port) => {
|
||||
t.is((await fetch(`http://localhost:${port}/pathA/dir`)).status, 404);
|
||||
t.is((await fetch(`http://localhost:${port}/pathB/dir`)).status, 404);
|
||||
t.is((await fetch(`http://localhost:${port}/pathC/dir`)).status, 200);
|
||||
})
|
||||
);
|
||||
|
||||
test(
|
||||
'[now dev] does not display directory listing after `handle: miss` and 404',
|
||||
testFixtureStdio('handle-miss-handle-filesystem-404', async (t, port) => {
|
||||
t.is((await fetch(`http://localhost:${port}/pathA/dir`)).status, 404);
|
||||
t.is((await fetch(`http://localhost:${port}/pathB/dir`)).status, 404);
|
||||
t.is((await fetch(`http://localhost:${port}/pathC/dir`)).status, 200);
|
||||
|
||||
t.is((await fetch(`http://localhost:${port}/pathA/dir/one`)).status, 200);
|
||||
t.is((await fetch(`http://localhost:${port}/pathB/dir/two`)).status, 200);
|
||||
t.is((await fetch(`http://localhost:${port}/pathC/dir/three`)).status, 200);
|
||||
})
|
||||
);
|
||||
|
||||
test(
|
||||
'[now dev] handles hit after handle: filesystem',
|
||||
testFixtureStdio('handle-hit-after-fs', async (t, port) => {
|
||||
@@ -606,6 +584,31 @@ test('[now dev] validate env var names', async t => {
|
||||
t.pass();
|
||||
});
|
||||
|
||||
test(
|
||||
'[now dev] test rewrites with segments serve correct content',
|
||||
testFixtureStdio('test-rewrites-with-segments', async (t, port) => {
|
||||
const users = await fetchWithRetry(
|
||||
`http://localhost:${port}/api/users/first`,
|
||||
3
|
||||
);
|
||||
t.regex(await users.text(), /first/gm);
|
||||
const fourtytwo = await fetchWithRetry(
|
||||
`http://localhost:${port}/api/fourty-two`,
|
||||
3
|
||||
);
|
||||
t.regex(await fourtytwo.text(), /42/gm);
|
||||
const rand = await fetchWithRetry(`http://localhost:${port}/rand`, 3);
|
||||
t.regex(await rand.text(), /42/gm);
|
||||
const dynamic = await fetchWithRetry(
|
||||
`http://localhost:${port}/api/dynamic`,
|
||||
3
|
||||
);
|
||||
t.regex(await dynamic.text(), /dynamic/gm);
|
||||
const notfound = await fetch(`http://localhost:${port}/api`);
|
||||
t.is(notfound.status, 404);
|
||||
})
|
||||
);
|
||||
|
||||
test(
|
||||
'[now dev] test rewrites serve correct content',
|
||||
testFixtureStdio('test-rewrites', async (t, port) => {
|
||||
|
||||
4
packages/now-cli/test/unit.js
vendored
4
packages/now-cli/test/unit.js
vendored
@@ -69,9 +69,7 @@ const getStaticFiles = async (dir, isBuilds = false) => {
|
||||
const normalizeWindowsPaths = files => {
|
||||
if (process.platform === 'win32') {
|
||||
const prefix = 'D:/a/now/now/packages/now-cli/test/fixtures/unit/';
|
||||
return files.map(f =>
|
||||
f.replace(/\\/g, '/').slice(prefix.length)
|
||||
);
|
||||
return files.map(f => f.replace(/\\/g, '/').slice(prefix.length));
|
||||
}
|
||||
return files;
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "now-client",
|
||||
"version": "7.0.1-canary.0",
|
||||
"version": "7.0.1-canary.1",
|
||||
"main": "dist/index.js",
|
||||
"typings": "dist/index.d.ts",
|
||||
"homepage": "https://zeit.co",
|
||||
|
||||
@@ -77,6 +77,15 @@ export async function* checkDeploymentStatus(
|
||||
yield { type: 'building', payload: deploymentUpdate };
|
||||
}
|
||||
|
||||
if (
|
||||
deploymentUpdate.readyState === 'CANCELED' &&
|
||||
!finishedEvents.has('canceled')
|
||||
) {
|
||||
debug('Deployment state changed to CANCELED');
|
||||
finishedEvents.add('canceled');
|
||||
yield { type: 'canceled', payload: deploymentUpdate };
|
||||
}
|
||||
|
||||
if (isReady(deploymentUpdate) && !finishedEvents.has('ready')) {
|
||||
debug('Deployment state changed to READY');
|
||||
finishedEvents.add('ready');
|
||||
|
||||
@@ -29,6 +29,7 @@ const EVENTS_ARRAY = [
|
||||
'error',
|
||||
'notice',
|
||||
'tip',
|
||||
'canceled',
|
||||
] as const;
|
||||
|
||||
export type DeploymentEventType = (typeof EVENTS_ARRAY)[number];
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@now/next",
|
||||
"version": "2.3.17",
|
||||
"version": "2.3.18",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://zeit.co/docs/runtimes#official-runtimes/next-js",
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
runNpmInstall,
|
||||
runPackageJsonScript,
|
||||
} from '@now/build-utils';
|
||||
import { Route, Source } from '@now/routing-utils';
|
||||
import { Route } from '@now/routing-utils';
|
||||
import {
|
||||
convertHeaders,
|
||||
convertRedirects,
|
||||
@@ -336,11 +336,17 @@ export const build = async ({
|
||||
env.NODE_OPTIONS = `--max_old_space_size=${memoryToConsume}`;
|
||||
await runPackageJsonScript(entryPath, shouldRunScript, { ...spawnOpts, env });
|
||||
|
||||
const appMountPrefixNoTrailingSlash = path.posix
|
||||
.join('/', entryDirectory)
|
||||
.replace(/\/+$/, '');
|
||||
|
||||
const routesManifest = await getRoutesManifest(entryPath, realNextVersion);
|
||||
const prerenderManifest = await getPrerenderManifest(entryPath);
|
||||
const headers: Route[] = [];
|
||||
const rewrites: Route[] = [];
|
||||
const redirects: Route[] = [];
|
||||
const nextBasePathRoute: Route[] = [];
|
||||
const dataRoutes: Route[] = [];
|
||||
let nextBasePath: string | undefined;
|
||||
// whether they have enabled pages/404.js as the custom 404 page
|
||||
let hasPages404 = false;
|
||||
@@ -356,6 +362,35 @@ export const build = async ({
|
||||
headers.push(...convertHeaders(routesManifest.headers));
|
||||
}
|
||||
|
||||
if (routesManifest.dataRoutes) {
|
||||
// Load the /_next/data routes for both dynamic SSG and SSP pages.
|
||||
// These must be combined and sorted to prevent conflicts
|
||||
for (const dataRoute of routesManifest.dataRoutes) {
|
||||
const ssgDataRoute = prerenderManifest.lazyRoutes[dataRoute.page];
|
||||
|
||||
// we don't need to add routes for non-lazy SSG routes since
|
||||
// they have outputs which would override the routes anyways
|
||||
if (prerenderManifest.routes[dataRoute.page]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dataRoutes.push({
|
||||
src: dataRoute.dataRouteRegex.replace(
|
||||
/^\^/,
|
||||
`^${appMountPrefixNoTrailingSlash}`
|
||||
),
|
||||
dest: path.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
// make sure to route SSG data route to the data prerender
|
||||
// output, we don't do this for SSP routes since they don't
|
||||
// have a separate data output
|
||||
(ssgDataRoute && ssgDataRoute.dataRoute) || dataRoute.page
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (routesManifest.pages404) {
|
||||
hasPages404 = true;
|
||||
}
|
||||
@@ -521,13 +556,8 @@ export const build = async ({
|
||||
const prerenders: { [key: string]: Prerender | FileFsRef } = {};
|
||||
const staticPages: { [key: string]: FileFsRef } = {};
|
||||
const dynamicPages: string[] = [];
|
||||
const dynamicDataRoutes: Array<Source> = [];
|
||||
let static404Page: string | undefined;
|
||||
|
||||
const appMountPrefixNoTrailingSlash = path.posix
|
||||
.join('/', entryDirectory)
|
||||
.replace(/\/+$/, '');
|
||||
|
||||
if (isLegacy) {
|
||||
const filesAfterBuild = await glob('**', entryPath);
|
||||
|
||||
@@ -629,7 +659,6 @@ export const build = async ({
|
||||
|
||||
const pages = await glob('**/*.js', pagesDir);
|
||||
const staticPageFiles = await glob('**/*.html', pagesDir);
|
||||
const prerenderManifest = await getPrerenderManifest(entryPath);
|
||||
|
||||
Object.keys(staticPageFiles).forEach((page: string) => {
|
||||
const pathname = page.replace(/\.html$/, '');
|
||||
@@ -976,18 +1005,25 @@ export const build = async ({
|
||||
onPrerenderRoute(route, true)
|
||||
);
|
||||
|
||||
// Dynamic pages for lazy routes should be handled by the lambda flow.
|
||||
Object.keys(prerenderManifest.lazyRoutes).forEach(lazyRoute => {
|
||||
const { dataRouteRegex, dataRoute } = prerenderManifest.lazyRoutes[
|
||||
lazyRoute
|
||||
];
|
||||
dynamicDataRoutes.push({
|
||||
// Next.js provided data route regex
|
||||
src: dataRouteRegex.replace(/^\^/, `^${appMountPrefixNoTrailingSlash}`),
|
||||
// Location of lambda in builder output
|
||||
dest: path.posix.join(entryDirectory, dataRoute),
|
||||
// We still need to use lazyRoutes if the dataRoutes field
|
||||
// isn't available for backwards compatibility
|
||||
if (!(routesManifest && routesManifest.dataRoutes)) {
|
||||
// Dynamic pages for lazy routes should be handled by the lambda flow.
|
||||
Object.keys(prerenderManifest.lazyRoutes).forEach(lazyRoute => {
|
||||
const { dataRouteRegex, dataRoute } = prerenderManifest.lazyRoutes[
|
||||
lazyRoute
|
||||
];
|
||||
dataRoutes.push({
|
||||
// Next.js provided data route regex
|
||||
src: dataRouteRegex.replace(
|
||||
/^\^/,
|
||||
`^${appMountPrefixNoTrailingSlash}`
|
||||
),
|
||||
// Location of lambda in builder output
|
||||
dest: path.posix.join(entryDirectory, dataRoute),
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const nextStaticFiles = await glob(
|
||||
@@ -1086,6 +1122,7 @@ export const build = async ({
|
||||
continue: true,
|
||||
},
|
||||
{ src: path.join('/', entryDirectory, '_next(?!/data(?:/|$))(?:/.*)?') },
|
||||
|
||||
// Next.js page lambdas, `static/` folder, reserved assets, and `public/`
|
||||
// folder
|
||||
{ handle: 'filesystem' },
|
||||
@@ -1107,7 +1144,10 @@ export const build = async ({
|
||||
...rewrites,
|
||||
// Dynamic routes
|
||||
...dynamicRoutes,
|
||||
...dynamicDataRoutes,
|
||||
|
||||
// /_next/data routes for getServerProps/getStaticProps pages
|
||||
...dataRoutes,
|
||||
|
||||
// Custom Next.js 404 page (TODO: do we want to remove this?)
|
||||
...(isLegacy
|
||||
? []
|
||||
|
||||
@@ -316,6 +316,7 @@ export type RoutesManifest = {
|
||||
regex: string;
|
||||
}[];
|
||||
version: number;
|
||||
dataRoutes?: Array<{ page: string; dataRouteRegex: string }>;
|
||||
};
|
||||
|
||||
export async function getRoutesManifest(
|
||||
|
||||
@@ -84,6 +84,21 @@
|
||||
"x-now-cache": "/HIT|STALE/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/blog/post-4.json",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{ "delay": 2000 },
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/blog/post-4.json",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "/HIT|STALE/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/blog/post-1/comment-1",
|
||||
"status": 200,
|
||||
|
||||
@@ -82,6 +82,21 @@
|
||||
"x-now-cache": "/HIT|STALE/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/blog/post-4.json",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{ "delay": 2000 },
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/blog/post-4.json",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "/HIT|STALE/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/blog/post-3",
|
||||
"status": 200,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "9.2.2-canary.16",
|
||||
"next": "9.2.3-canary.13",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6"
|
||||
}
|
||||
|
||||
5
packages/now-next/test/fixtures/21-server-props/next.config.js
vendored
Normal file
5
packages/now-next/test/fixtures/21-server-props/next.config.js
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
generateBuildId() {
|
||||
return 'testing-build-id';
|
||||
},
|
||||
};
|
||||
164
packages/now-next/test/fixtures/21-server-props/now.json
vendored
Normal file
164
packages/now-next/test/fixtures/21-server-props/now.json
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
{
|
||||
"version": 2,
|
||||
"builds": [{ "src": "package.json", "use": "@now/next" }],
|
||||
"probes": [
|
||||
{
|
||||
"path": "/lambda",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/forever",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{ "delay": 2000 },
|
||||
{
|
||||
"path": "/forever",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/another",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{ "delay": 2000 },
|
||||
{
|
||||
"path": "/another",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/blog/post-1",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{ "delay": 2000 },
|
||||
{
|
||||
"path": "/blog/post-1",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/blog/post-2",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{ "delay": 2000 },
|
||||
{
|
||||
"path": "/blog/post-2",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/blog/post-3",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{ "delay": 2000 },
|
||||
{
|
||||
"path": "/blog/post-3",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "/MISS/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/blog/post-1/comment-1",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/blog/post-2/comment-2",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/blog/post-3/comment-3",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/lambda.json",
|
||||
"status": 404
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/another.json",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "/MISS/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/another2.json",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{ "delay": 2000 },
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/another2.json",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/blog/post-1.json",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "/MISS/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/blog/post-1.json",
|
||||
"status": 200,
|
||||
"mustContain": "post-1"
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/blog/post-1337/comment-1337.json",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/blog/post-1337/comment-1337.json",
|
||||
"status": 200,
|
||||
"mustContain": "comment-1337"
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/blog/post-1337/comment-1337.json",
|
||||
"status": 200,
|
||||
"mustContain": "post-1337"
|
||||
}
|
||||
]
|
||||
}
|
||||
7
packages/now-next/test/fixtures/21-server-props/package.json
vendored
Normal file
7
packages/now-next/test/fixtures/21-server-props/package.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "9.2.3-canary.13",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6"
|
||||
}
|
||||
}
|
||||
20
packages/now-next/test/fixtures/21-server-props/pages/another.js
vendored
Normal file
20
packages/now-next/test/fixtures/21-server-props/pages/another.js
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
import React from 'react';
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
export async function unstable_getServerProps() {
|
||||
return {
|
||||
props: {
|
||||
world: 'world',
|
||||
time: new Date().getTime(),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default ({ world, time }) => {
|
||||
return (
|
||||
<>
|
||||
<p>hello: {world}</p>
|
||||
<span>time: {time}</span>
|
||||
</>
|
||||
);
|
||||
};
|
||||
20
packages/now-next/test/fixtures/21-server-props/pages/another2.js
vendored
Normal file
20
packages/now-next/test/fixtures/21-server-props/pages/another2.js
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
import React from 'react';
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
export async function unstable_getServerProps() {
|
||||
return {
|
||||
props: {
|
||||
world: 'world',
|
||||
time: new Date().getTime(),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default ({ world, time }) => {
|
||||
return (
|
||||
<>
|
||||
<p>hello: {world}</p>
|
||||
<span>time: {time}</span>
|
||||
</>
|
||||
);
|
||||
};
|
||||
22
packages/now-next/test/fixtures/21-server-props/pages/blog/[post]/[comment].js
vendored
Normal file
22
packages/now-next/test/fixtures/21-server-props/pages/blog/[post]/[comment].js
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
import React from 'react';
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
export async function unstable_getServerProps ({ params }) {
|
||||
return {
|
||||
props: {
|
||||
post: params.post,
|
||||
comment: params.comment,
|
||||
time: new Date().getTime(),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default ({ post, comment, time }) => {
|
||||
return (
|
||||
<>
|
||||
<p>Post: {post}</p>
|
||||
<p>Comment: {comment}</p>
|
||||
<span>time: {time}</span>
|
||||
</>
|
||||
);
|
||||
};
|
||||
26
packages/now-next/test/fixtures/21-server-props/pages/blog/[post]/index.js
vendored
Normal file
26
packages/now-next/test/fixtures/21-server-props/pages/blog/[post]/index.js
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
import React from 'react'
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
export async function unstable_getServerProps ({ params }) {
|
||||
if (params.post === 'post-10') {
|
||||
await new Promise(resolve => {
|
||||
setTimeout(() => resolve(), 1000)
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
props: {
|
||||
post: params.post,
|
||||
time: (await import('perf_hooks')).performance.now()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export default ({ post, time }) => {
|
||||
return (
|
||||
<>
|
||||
<p>Post: {post}</p>
|
||||
<span>time: {time}</span>
|
||||
</>
|
||||
)
|
||||
}
|
||||
20
packages/now-next/test/fixtures/21-server-props/pages/forever.js
vendored
Normal file
20
packages/now-next/test/fixtures/21-server-props/pages/forever.js
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
import React from 'react';
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
export async function unstable_getServerProps() {
|
||||
return {
|
||||
props: {
|
||||
world: 'world',
|
||||
time: new Date().getTime(),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default ({ world, time }) => {
|
||||
return (
|
||||
<>
|
||||
<p>hello: {world}</p>
|
||||
<span>time: {time}</span>
|
||||
</>
|
||||
);
|
||||
};
|
||||
1
packages/now-next/test/fixtures/21-server-props/pages/index.js
vendored
Normal file
1
packages/now-next/test/fixtures/21-server-props/pages/index.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export default () => 'Hi';
|
||||
5
packages/now-next/test/fixtures/21-server-props/pages/lambda.js
vendored
Normal file
5
packages/now-next/test/fixtures/21-server-props/pages/lambda.js
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
const Page = ({ data }) => <p>{data} world</p>;
|
||||
|
||||
Page.getInitialProps = () => ({ data: 'hello' });
|
||||
|
||||
export default Page;
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@now/routing-utils",
|
||||
"version": "1.6.0",
|
||||
"version": "1.6.1-canary.0",
|
||||
"description": "ZEIT Now routing utilities",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
|
||||
39
packages/now-routing-utils/src/append.ts
Normal file
39
packages/now-routing-utils/src/append.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { AppendRoutesToPhaseProps } from './types';
|
||||
import { isHandler } from './index';
|
||||
|
||||
export function appendRoutesToPhase({
|
||||
routes: prevRoutes,
|
||||
newRoutes,
|
||||
phase,
|
||||
}: AppendRoutesToPhaseProps) {
|
||||
if (prevRoutes === null) {
|
||||
return [];
|
||||
}
|
||||
if (newRoutes === null || newRoutes.length === 0) {
|
||||
return prevRoutes;
|
||||
}
|
||||
let isInPhase = false;
|
||||
let insertIndex = -1;
|
||||
const routes = [...prevRoutes];
|
||||
|
||||
routes.forEach((r, i) => {
|
||||
if (isHandler(r)) {
|
||||
if (r.handle === phase) {
|
||||
isInPhase = true;
|
||||
} else if (isInPhase) {
|
||||
insertIndex = i;
|
||||
isInPhase = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (isInPhase) {
|
||||
routes.push(...newRoutes);
|
||||
} else if (insertIndex > -1) {
|
||||
routes.splice(insertIndex, 0, ...newRoutes);
|
||||
} else {
|
||||
routes.push({ handle: phase });
|
||||
routes.push(...newRoutes);
|
||||
}
|
||||
return routes;
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
|
||||
export { getCleanUrls } from './superstatic';
|
||||
export { mergeRoutes } from './merge';
|
||||
export { appendRoutesToPhase } from './append';
|
||||
|
||||
const VALID_HANDLE_VALUES = ['filesystem', 'hit', 'miss'] as const;
|
||||
const validHandleValues = new Set<string>(VALID_HANDLE_VALUES);
|
||||
|
||||
@@ -80,3 +80,18 @@ export interface NowHeaderKeyValue {
|
||||
key: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export interface AppendRoutesToPhaseProps {
|
||||
/**
|
||||
* All input routes including `handle` phases.
|
||||
*/
|
||||
routes: Route[] | null;
|
||||
/**
|
||||
* The routes to append to a specific phase.
|
||||
*/
|
||||
newRoutes: Route[] | null;
|
||||
/**
|
||||
* The phase to append the routes such as `filesystem`.
|
||||
*/
|
||||
phase: HandleValue;
|
||||
}
|
||||
|
||||
114
packages/now-routing-utils/test/append.spec.js
vendored
Normal file
114
packages/now-routing-utils/test/append.spec.js
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
const { deepEqual } = require('assert');
|
||||
const { appendRoutesToPhase } = require('../dist/append');
|
||||
|
||||
test('appendRoutesToPhase `routes=null`', () => {
|
||||
const routes = null;
|
||||
const newRoutes = [];
|
||||
const phase = 'filesystem';
|
||||
const actual = appendRoutesToPhase({ routes, newRoutes, phase });
|
||||
const expected = [];
|
||||
deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
test('appendRoutesToPhase `newRoutes=null`', () => {
|
||||
const routes = [];
|
||||
const newRoutes = null;
|
||||
const phase = 'filesystem';
|
||||
const actual = appendRoutesToPhase({ routes, newRoutes, phase });
|
||||
const expected = [];
|
||||
deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
test('appendRoutesToPhase `routes=[]` and `newRoutes=[]`', () => {
|
||||
const routes = [];
|
||||
const newRoutes = [];
|
||||
const phase = 'filesystem';
|
||||
const actual = appendRoutesToPhase({ routes, newRoutes, phase });
|
||||
const expected = [];
|
||||
deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
test('appendRoutesToPhase one routes, zero newRoutes', () => {
|
||||
const routes = [{ src: '/foo', dest: '/bar' }];
|
||||
const newRoutes = [];
|
||||
const phase = 'filesystem';
|
||||
const actual = appendRoutesToPhase({ routes, newRoutes, phase });
|
||||
const expected = routes;
|
||||
deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
test('appendRoutesToPhase zero routes, one newRoutes', () => {
|
||||
const routes = [];
|
||||
const newRoutes = [{ src: '/foo', dest: '/bar' }];
|
||||
const phase = 'filesystem';
|
||||
const actual = appendRoutesToPhase({ routes, newRoutes, phase });
|
||||
const expected = [{ handle: 'filesystem' }, ...newRoutes];
|
||||
deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
test('appendRoutesToPhase two routes in phase', () => {
|
||||
const routes = [{ handle: 'filesystem' }, { src: '/first', dest: '/one' }];
|
||||
const newRoutes = [{ src: '/new', dest: '/to' }];
|
||||
const phase = 'filesystem';
|
||||
const actual = appendRoutesToPhase({ routes, newRoutes, phase });
|
||||
const expected = [
|
||||
{ handle: 'filesystem' },
|
||||
{ src: '/first', dest: '/one' },
|
||||
{ src: '/new', dest: '/to' },
|
||||
];
|
||||
deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
test('appendRoutesToPhase two routes out of phase', () => {
|
||||
const routes = [{ handle: 'resource' }, { src: '/first', dest: '/one' }];
|
||||
const newRoutes = [{ src: '/new', dest: '/to' }];
|
||||
const phase = 'filesystem';
|
||||
const actual = appendRoutesToPhase({ routes, newRoutes, phase });
|
||||
const expected = [
|
||||
{ handle: 'resource' },
|
||||
{ src: '/first', dest: '/one' },
|
||||
{ handle: 'filesystem' },
|
||||
{ src: '/new', dest: '/to' },
|
||||
];
|
||||
deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
test('appendRoutesToPhase one routes before, two routes in phase', () => {
|
||||
const routes = [
|
||||
{ src: '/first', dest: '/one' },
|
||||
{ handle: 'filesystem' },
|
||||
{ src: '/second', dest: '/two' },
|
||||
];
|
||||
const newRoutes = [{ src: '/new', dest: '/to' }];
|
||||
const phase = 'filesystem';
|
||||
const actual = appendRoutesToPhase({ routes, newRoutes, phase });
|
||||
const expected = [
|
||||
{ src: '/first', dest: '/one' },
|
||||
{ handle: 'filesystem' },
|
||||
{ src: '/second', dest: '/two' },
|
||||
{ src: '/new', dest: '/to' },
|
||||
];
|
||||
deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
test('appendRoutesToPhase one routes before, two routes in phase, two routes in different phase', () => {
|
||||
const routes = [
|
||||
{ src: '/first', dest: '/one' },
|
||||
{ handle: 'filesystem' },
|
||||
{ src: '/second', dest: '/two' },
|
||||
{ handle: 'miss' },
|
||||
{ src: '/third', dest: '/three' },
|
||||
];
|
||||
const newRoutes = [{ src: '/new', dest: '/to' }];
|
||||
const phase = 'filesystem';
|
||||
const actual = appendRoutesToPhase({ routes, newRoutes, phase });
|
||||
const expected = [
|
||||
{ src: '/first', dest: '/one' },
|
||||
{ handle: 'filesystem' },
|
||||
{ src: '/second', dest: '/two' },
|
||||
{ src: '/new', dest: '/to' },
|
||||
{ handle: 'miss' },
|
||||
{ src: '/third', dest: '/three' },
|
||||
];
|
||||
deepEqual(actual, expected);
|
||||
});
|
||||
Reference in New Issue
Block a user