@vercel/next 3.0.1-canary.0 → 3.0.2-canary.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,23 +1,9 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.
|
3
|
+
exports.EDGE_FUNCTION_SIZE_LIMIT = void 0;
|
4
4
|
const KIB = 1024;
|
5
5
|
const MIB = 1024 * KIB;
|
6
6
|
/**
|
7
|
-
* The
|
8
|
-
* See https://github.com/cloudflare/wrangler/blob/8907b12add3d70ee21ac597b69cd66f6807571f4/src/wranglerjs/output.rs#L44
|
7
|
+
* The maximum size of a *compressed* edge function.
|
9
8
|
*/
|
10
|
-
|
11
|
-
/**
|
12
|
-
* This safety buffer must cover the size of our whole runtime layer compressed
|
13
|
-
* plus some extra space to allow it to grow in the future. At the time of
|
14
|
-
* writing this comment the compressed size size is ~7KiB so 20KiB should
|
15
|
-
* be more than enough.
|
16
|
-
*/
|
17
|
-
const EDGE_FUNCTION_SCRIPT_SIZE_BUFFER = 20 * KIB;
|
18
|
-
/**
|
19
|
-
* The max size we allow for compressed user code is the compressed script
|
20
|
-
* limit minus the compressed safety buffer. We must check this limit after
|
21
|
-
* compressing the user code.
|
22
|
-
*/
|
23
|
-
exports.EDGE_FUNCTION_USER_SCRIPT_SIZE_LIMIT = EDGE_FUNCTION_SCRIPT_SIZE_LIMIT - EDGE_FUNCTION_SCRIPT_SIZE_BUFFER;
|
9
|
+
exports.EDGE_FUNCTION_SIZE_LIMIT = MIB;
|
@@ -66,7 +66,7 @@ function getWasmImportStatements(wasm = []) {
|
|
66
66
|
}
|
67
67
|
async function validateScript(content) {
|
68
68
|
const gzipped = await gzip(content);
|
69
|
-
if (gzipped.length > constants_1.
|
70
|
-
throw new Error(`Exceeds maximum edge function script size: ${(0, pretty_bytes_1.default)(gzipped.length)} / ${(0, pretty_bytes_1.default)(constants_1.
|
69
|
+
if (gzipped.length > constants_1.EDGE_FUNCTION_SIZE_LIMIT) {
|
70
|
+
throw new Error(`Exceeds maximum edge function script size: ${(0, pretty_bytes_1.default)(gzipped.length)} / ${(0, pretty_bytes_1.default)(constants_1.EDGE_FUNCTION_SIZE_LIMIT)}`);
|
71
71
|
}
|
72
72
|
}
|
package/dist/index.js
CHANGED
@@ -44725,27 +44725,13 @@ exports.default = createServerlessConfig;
|
|
44725
44725
|
"use strict";
|
44726
44726
|
|
44727
44727
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
44728
|
-
exports.
|
44728
|
+
exports.EDGE_FUNCTION_SIZE_LIMIT = void 0;
|
44729
44729
|
const KIB = 1024;
|
44730
44730
|
const MIB = 1024 * KIB;
|
44731
44731
|
/**
|
44732
|
-
* The
|
44733
|
-
* See https://github.com/cloudflare/wrangler/blob/8907b12add3d70ee21ac597b69cd66f6807571f4/src/wranglerjs/output.rs#L44
|
44732
|
+
* The maximum size of a *compressed* edge function.
|
44734
44733
|
*/
|
44735
|
-
|
44736
|
-
/**
|
44737
|
-
* This safety buffer must cover the size of our whole runtime layer compressed
|
44738
|
-
* plus some extra space to allow it to grow in the future. At the time of
|
44739
|
-
* writing this comment the compressed size size is ~7KiB so 20KiB should
|
44740
|
-
* be more than enough.
|
44741
|
-
*/
|
44742
|
-
const EDGE_FUNCTION_SCRIPT_SIZE_BUFFER = 20 * KIB;
|
44743
|
-
/**
|
44744
|
-
* The max size we allow for compressed user code is the compressed script
|
44745
|
-
* limit minus the compressed safety buffer. We must check this limit after
|
44746
|
-
* compressing the user code.
|
44747
|
-
*/
|
44748
|
-
exports.EDGE_FUNCTION_USER_SCRIPT_SIZE_LIMIT = EDGE_FUNCTION_SCRIPT_SIZE_LIMIT - EDGE_FUNCTION_SCRIPT_SIZE_BUFFER;
|
44734
|
+
exports.EDGE_FUNCTION_SIZE_LIMIT = MIB;
|
44749
44735
|
|
44750
44736
|
|
44751
44737
|
/***/ }),
|
@@ -44822,8 +44808,8 @@ function getWasmImportStatements(wasm = []) {
|
|
44822
44808
|
}
|
44823
44809
|
async function validateScript(content) {
|
44824
44810
|
const gzipped = await gzip(content);
|
44825
|
-
if (gzipped.length > constants_1.
|
44826
|
-
throw new Error(`Exceeds maximum edge function script size: ${(0, pretty_bytes_1.default)(gzipped.length)} / ${(0, pretty_bytes_1.default)(constants_1.
|
44811
|
+
if (gzipped.length > constants_1.EDGE_FUNCTION_SIZE_LIMIT) {
|
44812
|
+
throw new Error(`Exceeds maximum edge function script size: ${(0, pretty_bytes_1.default)(gzipped.length)} / ${(0, pretty_bytes_1.default)(constants_1.EDGE_FUNCTION_SIZE_LIMIT)}`);
|
44827
44813
|
}
|
44828
44814
|
}
|
44829
44815
|
|
@@ -44857,6 +44843,7 @@ const create_serverless_config_1 = __importDefault(__webpack_require__(9892));
|
|
44857
44843
|
const legacy_versions_1 = __importDefault(__webpack_require__(1207));
|
44858
44844
|
const server_build_1 = __webpack_require__(5840);
|
44859
44845
|
const utils_1 = __webpack_require__(4411);
|
44846
|
+
const assert_1 = __importDefault(__webpack_require__(2357));
|
44860
44847
|
exports.version = 2;
|
44861
44848
|
exports.htmlContentType = 'text/html; charset=utf-8';
|
44862
44849
|
const SERVER_BUILD_MINIMUM_NEXT_VERSION = 'v10.0.9-canary.4';
|
@@ -45532,7 +45519,11 @@ const build = async ({ files, workPath, repoRootPath, entrypoint, config = {}, m
|
|
45532
45519
|
nextFiles['next.config.js'] = filesAfterBuild['next.config.js'];
|
45533
45520
|
}
|
45534
45521
|
const pagesDir = path_1.default.join(entryPath, outputDirectory, 'server', 'static', buildId, 'pages');
|
45535
|
-
const pages = await (
|
45522
|
+
const pages = await getServerlessPages({
|
45523
|
+
pagesDir,
|
45524
|
+
entryPath,
|
45525
|
+
outputDirectory,
|
45526
|
+
});
|
45536
45527
|
const launcherPath = path_1.default.join(__dirname, 'legacy-launcher.js');
|
45537
45528
|
const launcherData = await (0, fs_extra_1.readFile)(launcherPath, 'utf8');
|
45538
45529
|
await Promise.all(Object.keys(pages).map(async (page) => {
|
@@ -45578,7 +45569,11 @@ const build = async ({ files, workPath, repoRootPath, entrypoint, config = {}, m
|
|
45578
45569
|
else {
|
45579
45570
|
(0, build_utils_1.debug)('Preparing serverless function files...');
|
45580
45571
|
const pagesDir = path_1.default.join(entryPath, outputDirectory, isServerMode ? 'server' : 'serverless', 'pages');
|
45581
|
-
const pages = await (
|
45572
|
+
const pages = await getServerlessPages({
|
45573
|
+
pagesDir,
|
45574
|
+
entryPath,
|
45575
|
+
outputDirectory,
|
45576
|
+
});
|
45582
45577
|
const isApiPage = (page) => page
|
45583
45578
|
.replace(/\\/g, '/')
|
45584
45579
|
.match(/(serverless|server)\/pages\/api(\/|\.js$)/);
|
@@ -45729,6 +45724,7 @@ const build = async ({ files, workPath, repoRootPath, entrypoint, config = {}, m
|
|
45729
45724
|
entryPath,
|
45730
45725
|
baseDir,
|
45731
45726
|
dataRoutes,
|
45727
|
+
buildId,
|
45732
45728
|
escapedBuildId,
|
45733
45729
|
outputDirectory,
|
45734
45730
|
trailingSlashRedirects,
|
@@ -46637,6 +46633,23 @@ const prepareCache = async ({ workPath, repoRootPath, entrypoint, config = {}, }
|
|
46637
46633
|
return cache;
|
46638
46634
|
};
|
46639
46635
|
exports.prepareCache = prepareCache;
|
46636
|
+
async function getServerlessPages(params) {
|
46637
|
+
const [pages, middlewareManifest] = await Promise.all([
|
46638
|
+
(0, build_utils_1.glob)('**/!(_middleware).js', params.pagesDir),
|
46639
|
+
(0, utils_1.getMiddlewareManifest)(params.entryPath, params.outputDirectory),
|
46640
|
+
]);
|
46641
|
+
// Edge Functions do not consider as Serverless Functions
|
46642
|
+
for (const edgeFunctionFile of Object.keys(middlewareManifest?.functions ?? {})) {
|
46643
|
+
// `getStaticProps` are expecting `Prerender` output which is a Serverless function
|
46644
|
+
// and not an Edge Function. Therefore we only remove API endpoints for now, as they
|
46645
|
+
// don't have `getStaticProps`.
|
46646
|
+
//
|
46647
|
+
// Context: https://github.com/vercel/vercel/pull/7905#discussion_r890213165
|
46648
|
+
(0, assert_1.default)(edgeFunctionFile.startsWith('/api/'), `Only API endpoints are currently supported for Edge endpoints.`);
|
46649
|
+
delete pages[edgeFunctionFile.slice(1) + '.js'];
|
46650
|
+
}
|
46651
|
+
return pages;
|
46652
|
+
}
|
46640
46653
|
|
46641
46654
|
|
46642
46655
|
/***/ }),
|
@@ -47011,7 +47024,8 @@ const pretty_bytes_1 = __importDefault(__webpack_require__(539));
|
|
47011
47024
|
// related PR: https://github.com/vercel/next.js/pull/30046
|
47012
47025
|
const CORRECT_NOT_FOUND_ROUTES_VERSION = 'v12.0.1';
|
47013
47026
|
const CORRECT_MIDDLEWARE_ORDER_VERSION = 'v12.1.7-canary.29';
|
47014
|
-
|
47027
|
+
const NEXT_DATA_MIDDLEWARE_RESOLVING_VERSION = 'v12.1.7-canary.33';
|
47028
|
+
async function serverBuild({ dynamicPages, pagesDir, config = {}, privateOutputs, baseDir, workPath, entryPath, nodeVersion, buildId, escapedBuildId, dynamicPrefix, entryDirectory, outputDirectory, redirects, beforeFilesRewrites, afterFilesRewrites, fallbackRewrites, headers, dataRoutes, hasIsr404Page, imagesManifest, wildcardConfig, routesManifest, staticPages, lambdaPages, nextVersion, canUsePreviewMode, prerenderManifest, omittedPrerenderRoutes, trailingSlashRedirects, isCorrectLocaleAPIRoutes, lambdaCompressedByteLimit, requiredServerFilesManifest, }) {
|
47015
47029
|
const lambdas = {};
|
47016
47030
|
const prerenders = {};
|
47017
47031
|
const lambdaPageKeys = Object.keys(lambdaPages);
|
@@ -47410,6 +47424,8 @@ async function serverBuild({ dynamicPages, pagesDir, config = {}, privateOutputs
|
|
47410
47424
|
routesManifest,
|
47411
47425
|
isCorrectMiddlewareOrder,
|
47412
47426
|
});
|
47427
|
+
const isNextDataServerResolving = middleware.staticRoutes.length > 0 &&
|
47428
|
+
semver_1.default.gte(nextVersion, NEXT_DATA_MIDDLEWARE_RESOLVING_VERSION);
|
47413
47429
|
const dynamicRoutes = await (0, utils_1.getDynamicRoutes)(entryPath, entryDirectory, dynamicPages, false, routesManifest, omittedPrerenderRoutes, canUsePreviewMode, prerenderManifest.bypassToken || '', true, middleware.dynamicRouteMap).then(arr => (0, utils_1.localizeDynamicRoutes)(arr, dynamicPrefix, entryDirectory, staticPages, prerenderManifest, routesManifest, true, isCorrectLocaleAPIRoutes));
|
47414
47430
|
const { staticFiles, publicDirectoryFiles, staticDirectoryFiles } = await (0, utils_1.getStaticFiles)(entryPath, entryDirectory, outputDirectory);
|
47415
47431
|
const notFoundPreviewRoutes = [];
|
@@ -47452,6 +47468,39 @@ async function serverBuild({ dynamicPages, pagesDir, config = {}, privateOutputs
|
|
47452
47468
|
}
|
47453
47469
|
}
|
47454
47470
|
}
|
47471
|
+
const normalizeNextDataRoute = isNextDataServerResolving
|
47472
|
+
? [
|
47473
|
+
// strip _next/data prefix for resolving
|
47474
|
+
{
|
47475
|
+
src: `^${path_1.default.join('/', entryDirectory, '/_next/data/', escapedBuildId, '/(.*).json')}`,
|
47476
|
+
dest: `${path_1.default.join('/', entryDirectory, '/$1')}`,
|
47477
|
+
continue: true,
|
47478
|
+
override: true,
|
47479
|
+
has: [
|
47480
|
+
{
|
47481
|
+
type: 'header',
|
47482
|
+
key: 'x-nextjs-data',
|
47483
|
+
},
|
47484
|
+
],
|
47485
|
+
},
|
47486
|
+
]
|
47487
|
+
: [];
|
47488
|
+
const denormalizeNextDataRoute = isNextDataServerResolving
|
47489
|
+
? [
|
47490
|
+
{
|
47491
|
+
src: '/(.*)',
|
47492
|
+
has: [
|
47493
|
+
{
|
47494
|
+
type: 'header',
|
47495
|
+
key: 'x-nextjs-data',
|
47496
|
+
},
|
47497
|
+
],
|
47498
|
+
dest: `${path_1.default.join('/', entryDirectory, '/_next/data/', buildId, '/$1.json')}`,
|
47499
|
+
continue: true,
|
47500
|
+
override: true,
|
47501
|
+
},
|
47502
|
+
]
|
47503
|
+
: [];
|
47455
47504
|
return {
|
47456
47505
|
wildcard: wildcardConfig,
|
47457
47506
|
images: imagesManifest?.images?.loader === 'default'
|
@@ -47475,6 +47524,15 @@ async function serverBuild({ dynamicPages, pagesDir, config = {}, privateOutputs
|
|
47475
47524
|
...staticDirectoryFiles,
|
47476
47525
|
...privateOutputs.files,
|
47477
47526
|
...middleware.edgeFunctions,
|
47527
|
+
...(isNextDataServerResolving
|
47528
|
+
? {
|
47529
|
+
__next_data_catchall: new build_utils_1.FileBlob({
|
47530
|
+
contentType: 'application/json',
|
47531
|
+
mode: 0o644,
|
47532
|
+
data: '{}',
|
47533
|
+
}),
|
47534
|
+
}
|
47535
|
+
: {}),
|
47478
47536
|
},
|
47479
47537
|
routes: [
|
47480
47538
|
/*
|
@@ -47492,6 +47550,8 @@ async function serverBuild({ dynamicPages, pagesDir, config = {}, privateOutputs
|
|
47492
47550
|
// trailing slash
|
47493
47551
|
...trailingSlashRedirects,
|
47494
47552
|
...privateOutputs.routes,
|
47553
|
+
// normalize _next/data URL before processing redirects
|
47554
|
+
...normalizeNextDataRoute,
|
47495
47555
|
...(i18n
|
47496
47556
|
? [
|
47497
47557
|
// Handle auto-adding current default locale to path based on
|
@@ -47617,6 +47677,8 @@ async function serverBuild({ dynamicPages, pagesDir, config = {}, privateOutputs
|
|
47617
47677
|
continue: true,
|
47618
47678
|
},
|
47619
47679
|
]),
|
47680
|
+
// we need to undo _next/data normalize before checking filesystem
|
47681
|
+
...denormalizeNextDataRoute,
|
47620
47682
|
// while middleware was in beta the order came right before
|
47621
47683
|
// handle: 'filesystem' we maintain this for older versions
|
47622
47684
|
// to prevent a local/deploy mismatch
|
@@ -47635,13 +47697,19 @@ async function serverBuild({ dynamicPages, pagesDir, config = {}, privateOutputs
|
|
47635
47697
|
},
|
47636
47698
|
]
|
47637
47699
|
: []),
|
47638
|
-
//
|
47639
|
-
|
47640
|
-
|
47641
|
-
|
47642
|
-
|
47643
|
-
|
47644
|
-
|
47700
|
+
// normalize _next/data URL before processing rewrites
|
47701
|
+
...normalizeNextDataRoute,
|
47702
|
+
...(!isNextDataServerResolving
|
47703
|
+
? [
|
47704
|
+
// No-op _next/data rewrite to trigger handle: 'rewrites' and then 404
|
47705
|
+
// if no match to prevent rewriting _next/data unexpectedly
|
47706
|
+
{
|
47707
|
+
src: path_1.default.join('/', entryDirectory, '_next/data/(.*)'),
|
47708
|
+
dest: path_1.default.join('/', entryDirectory, '_next/data/$1'),
|
47709
|
+
check: true,
|
47710
|
+
},
|
47711
|
+
]
|
47712
|
+
: []),
|
47645
47713
|
// These need to come before handle: miss or else they are grouped
|
47646
47714
|
// with that routing section
|
47647
47715
|
...afterFilesRewrites,
|
@@ -47687,18 +47755,34 @@ async function serverBuild({ dynamicPages, pagesDir, config = {}, privateOutputs
|
|
47687
47755
|
// routes that are called after each rewrite or after routes
|
47688
47756
|
// if there no rewrites
|
47689
47757
|
{ handle: 'rewrite' },
|
47758
|
+
// re-build /_next/data URL after resolving
|
47759
|
+
...denormalizeNextDataRoute,
|
47690
47760
|
// /_next/data routes for getServerProps/getStaticProps pages
|
47691
47761
|
...dataRoutes,
|
47692
|
-
|
47693
|
-
|
47694
|
-
|
47695
|
-
|
47696
|
-
|
47697
|
-
|
47698
|
-
|
47762
|
+
...(!isNextDataServerResolving
|
47763
|
+
? [
|
47764
|
+
// ensure we 404 for non-existent _next/data routes before
|
47765
|
+
// trying page dynamic routes
|
47766
|
+
{
|
47767
|
+
src: path_1.default.join('/', entryDirectory, '_next/data/(.*)'),
|
47768
|
+
dest: path_1.default.join('/', entryDirectory, '404'),
|
47769
|
+
status: 404,
|
47770
|
+
},
|
47771
|
+
]
|
47772
|
+
: []),
|
47699
47773
|
// Dynamic routes (must come after dataRoutes as dataRoutes are more
|
47700
47774
|
// specific)
|
47701
47775
|
...dynamicRoutes,
|
47776
|
+
...(isNextDataServerResolving
|
47777
|
+
? [
|
47778
|
+
// add a catch-all data route so we don't 404 when getting
|
47779
|
+
// middleware effects
|
47780
|
+
{
|
47781
|
+
src: `^${path_1.default.join('/', entryDirectory, '/_next/data/', escapedBuildId, '/(.*).json')}`,
|
47782
|
+
dest: '__next_data_catchall',
|
47783
|
+
},
|
47784
|
+
]
|
47785
|
+
: []),
|
47702
47786
|
// routes to call after a file has been matched
|
47703
47787
|
{ handle: 'hit' },
|
47704
47788
|
// Before we handle static files we need to set proper caching headers
|
@@ -47920,7 +48004,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
47920
48004
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
47921
48005
|
};
|
47922
48006
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
47923
|
-
exports.getMiddlewareBundle = exports.getSourceFilePathFromPage = exports.isDynamicRoute = exports.normalizePage = exports.getNextConfig = exports.normalizePackageJson = exports.validateEntrypoint = exports.excludeFiles = exports.getPrivateOutputs = exports.updateRouteSrc = exports.getNextServerPath = exports.normalizeIndexOutput = exports.getStaticFiles = exports.onPrerenderRoute = exports.onPrerenderRouteInitial = exports.detectLambdaLimitExceeding = exports.outputFunctionFileSizeInfo = exports.getPageLambdaGroups = exports.MAX_UNCOMPRESSED_LAMBDA_SIZE = exports.addLocaleOrDefault = exports.normalizeLocalePath = exports.getPrerenderManifest = exports.getRequiredServerFilesManifest = exports.getExportStatus = exports.getExportIntent = exports.createLambdaFromPseudoLayers = exports.createPseudoLayer = exports.ExperimentalTraceVersion = exports.collectTracedFiles = exports.getFilesMapFromReasons = exports.filterStaticPages = exports.getImagesManifest = exports.localizeDynamicRoutes = exports.getDynamicRoutes = exports.getRoutesManifest = void 0;
|
48007
|
+
exports.getMiddlewareManifest = exports.getMiddlewareBundle = exports.getSourceFilePathFromPage = exports.isDynamicRoute = exports.normalizePage = exports.getNextConfig = exports.normalizePackageJson = exports.validateEntrypoint = exports.excludeFiles = exports.getPrivateOutputs = exports.updateRouteSrc = exports.getNextServerPath = exports.normalizeIndexOutput = exports.getStaticFiles = exports.onPrerenderRoute = exports.onPrerenderRouteInitial = exports.detectLambdaLimitExceeding = exports.outputFunctionFileSizeInfo = exports.getPageLambdaGroups = exports.MAX_UNCOMPRESSED_LAMBDA_SIZE = exports.addLocaleOrDefault = exports.normalizeLocalePath = exports.getPrerenderManifest = exports.getRequiredServerFilesManifest = exports.getExportStatus = exports.getExportIntent = exports.createLambdaFromPseudoLayers = exports.createPseudoLayer = exports.ExperimentalTraceVersion = exports.collectTracedFiles = exports.getFilesMapFromReasons = exports.filterStaticPages = exports.getImagesManifest = exports.localizeDynamicRoutes = exports.getDynamicRoutes = exports.getRoutesManifest = void 0;
|
47924
48008
|
const build_utils_1 = __webpack_require__(3445);
|
47925
48009
|
const async_sema_1 = __webpack_require__(7916);
|
47926
48010
|
const buffer_crc32_1 = __importDefault(__webpack_require__(360));
|
@@ -49234,25 +49318,41 @@ async function getPrivateOutputs(dir, entries) {
|
|
49234
49318
|
exports.getPrivateOutputs = getPrivateOutputs;
|
49235
49319
|
async function getMiddlewareBundle({ entryPath, outputDirectory, routesManifest, isCorrectMiddlewareOrder, }) {
|
49236
49320
|
const middlewareManifest = await getMiddlewareManifest(entryPath, outputDirectory);
|
49237
|
-
|
49238
|
-
|
49239
|
-
|
49321
|
+
const sortedFunctions = [
|
49322
|
+
...(!middlewareManifest
|
49323
|
+
? []
|
49324
|
+
: middlewareManifest.sortedMiddleware.map(key => ({
|
49325
|
+
key,
|
49326
|
+
edgeFunction: middlewareManifest?.middleware[key],
|
49327
|
+
type: 'middleware',
|
49328
|
+
}))),
|
49329
|
+
...Object.entries(middlewareManifest?.functions ?? {}).map(([key, edgeFunction]) => {
|
49330
|
+
return {
|
49331
|
+
key,
|
49332
|
+
edgeFunction,
|
49333
|
+
type: 'function',
|
49334
|
+
};
|
49335
|
+
}),
|
49336
|
+
];
|
49337
|
+
if (middlewareManifest && sortedFunctions.length > 0) {
|
49338
|
+
const workerConfigs = await Promise.all(sortedFunctions.map(async ({ key, edgeFunction, type }) => {
|
49240
49339
|
try {
|
49241
|
-
const wrappedModuleSource = await (0, get_edge_function_source_1.getNextjsEdgeFunctionSource)(
|
49242
|
-
name:
|
49340
|
+
const wrappedModuleSource = await (0, get_edge_function_source_1.getNextjsEdgeFunctionSource)(edgeFunction.files, {
|
49341
|
+
name: edgeFunction.name,
|
49243
49342
|
staticRoutes: routesManifest.staticRoutes,
|
49244
49343
|
dynamicRoutes: routesManifest.dynamicRoutes.filter(r => !('isMiddleware' in r)),
|
49245
49344
|
nextConfig: {
|
49246
49345
|
basePath: routesManifest.basePath,
|
49247
49346
|
i18n: routesManifest.i18n,
|
49248
49347
|
},
|
49249
|
-
}, path_1.default.resolve(entryPath, outputDirectory),
|
49348
|
+
}, path_1.default.resolve(entryPath, outputDirectory), edgeFunction.wasm);
|
49250
49349
|
return {
|
49251
|
-
|
49350
|
+
type,
|
49351
|
+
page: edgeFunction.page,
|
49252
49352
|
edgeFunction: (() => {
|
49253
49353
|
const { source, map } = wrappedModuleSource.sourceAndMap();
|
49254
49354
|
const transformedMap = (0, sourcemapped_1.stringifySourceMap)(transformSourceMap(map));
|
49255
|
-
const wasmFiles = (
|
49355
|
+
const wasmFiles = (edgeFunction.wasm ?? []).reduce((acc, { filePath, name }) => {
|
49256
49356
|
const fullFilePath = path_1.default.join(entryPath, outputDirectory, filePath);
|
49257
49357
|
acc[`wasm/${name}.wasm`] = new build_utils_1.FileFsRef({
|
49258
49358
|
mode: 0o644,
|
@@ -49263,7 +49363,7 @@ async function getMiddlewareBundle({ entryPath, outputDirectory, routesManifest,
|
|
49263
49363
|
}, {});
|
49264
49364
|
return new build_utils_1.EdgeFunction({
|
49265
49365
|
deploymentTarget: 'v8-worker',
|
49266
|
-
name:
|
49366
|
+
name: edgeFunction.name,
|
49267
49367
|
files: {
|
49268
49368
|
'index.js': new build_utils_1.FileBlob({
|
49269
49369
|
data: source,
|
@@ -49280,10 +49380,10 @@ async function getMiddlewareBundle({ entryPath, outputDirectory, routesManifest,
|
|
49280
49380
|
...wasmFiles,
|
49281
49381
|
},
|
49282
49382
|
entrypoint: 'index.js',
|
49283
|
-
envVarsInUse:
|
49383
|
+
envVarsInUse: edgeFunction.env,
|
49284
49384
|
});
|
49285
49385
|
})(),
|
49286
|
-
routeSrc: getRouteSrc(
|
49386
|
+
routeSrc: getRouteSrc(edgeFunction, routesManifest),
|
49287
49387
|
};
|
49288
49388
|
}
|
49289
49389
|
catch (e) {
|
@@ -49298,15 +49398,21 @@ async function getMiddlewareBundle({ entryPath, outputDirectory, routesManifest,
|
|
49298
49398
|
};
|
49299
49399
|
for (const worker of workerConfigs.values()) {
|
49300
49400
|
const edgeFile = worker.edgeFunction.name;
|
49301
|
-
|
49302
|
-
|
49401
|
+
const shortPath = edgeFile.replace(/^pages\//, '');
|
49402
|
+
worker.edgeFunction.name = shortPath;
|
49403
|
+
source.edgeFunctions[shortPath] = worker.edgeFunction;
|
49303
49404
|
const route = {
|
49304
49405
|
continue: true,
|
49305
|
-
middlewarePath: edgeFile,
|
49306
49406
|
src: worker.routeSrc,
|
49307
49407
|
};
|
49308
|
-
if (
|
49309
|
-
route.
|
49408
|
+
if (worker.type === 'function') {
|
49409
|
+
route.dest = shortPath;
|
49410
|
+
}
|
49411
|
+
else {
|
49412
|
+
route.middlewarePath = shortPath;
|
49413
|
+
if (isCorrectMiddlewareOrder) {
|
49414
|
+
route.override = true;
|
49415
|
+
}
|
49310
49416
|
}
|
49311
49417
|
if (routesManifest.version > 3 && isDynamicRoute(worker.page)) {
|
49312
49418
|
source.dynamicRouteMap.set(worker.page, route);
|
@@ -49340,6 +49446,7 @@ async function getMiddlewareManifest(entryPath, outputDirectory) {
|
|
49340
49446
|
}
|
49341
49447
|
return fs_extra_1.default.readJSON(middlewareManifestPath);
|
49342
49448
|
}
|
49449
|
+
exports.getMiddlewareManifest = getMiddlewareManifest;
|
49343
49450
|
/**
|
49344
49451
|
* For an object containing middleware info and a routes manifest this will
|
49345
49452
|
* generate a string with the route that will activate the middleware on
|
package/dist/server-build.js
CHANGED
@@ -18,7 +18,8 @@ const pretty_bytes_1 = __importDefault(require("pretty-bytes"));
|
|
18
18
|
// related PR: https://github.com/vercel/next.js/pull/30046
|
19
19
|
const CORRECT_NOT_FOUND_ROUTES_VERSION = 'v12.0.1';
|
20
20
|
const CORRECT_MIDDLEWARE_ORDER_VERSION = 'v12.1.7-canary.29';
|
21
|
-
|
21
|
+
const NEXT_DATA_MIDDLEWARE_RESOLVING_VERSION = 'v12.1.7-canary.33';
|
22
|
+
async function serverBuild({ dynamicPages, pagesDir, config = {}, privateOutputs, baseDir, workPath, entryPath, nodeVersion, buildId, escapedBuildId, dynamicPrefix, entryDirectory, outputDirectory, redirects, beforeFilesRewrites, afterFilesRewrites, fallbackRewrites, headers, dataRoutes, hasIsr404Page, imagesManifest, wildcardConfig, routesManifest, staticPages, lambdaPages, nextVersion, canUsePreviewMode, prerenderManifest, omittedPrerenderRoutes, trailingSlashRedirects, isCorrectLocaleAPIRoutes, lambdaCompressedByteLimit, requiredServerFilesManifest, }) {
|
22
23
|
const lambdas = {};
|
23
24
|
const prerenders = {};
|
24
25
|
const lambdaPageKeys = Object.keys(lambdaPages);
|
@@ -417,6 +418,8 @@ async function serverBuild({ dynamicPages, pagesDir, config = {}, privateOutputs
|
|
417
418
|
routesManifest,
|
418
419
|
isCorrectMiddlewareOrder,
|
419
420
|
});
|
421
|
+
const isNextDataServerResolving = middleware.staticRoutes.length > 0 &&
|
422
|
+
semver_1.default.gte(nextVersion, NEXT_DATA_MIDDLEWARE_RESOLVING_VERSION);
|
420
423
|
const dynamicRoutes = await (0, utils_1.getDynamicRoutes)(entryPath, entryDirectory, dynamicPages, false, routesManifest, omittedPrerenderRoutes, canUsePreviewMode, prerenderManifest.bypassToken || '', true, middleware.dynamicRouteMap).then(arr => (0, utils_1.localizeDynamicRoutes)(arr, dynamicPrefix, entryDirectory, staticPages, prerenderManifest, routesManifest, true, isCorrectLocaleAPIRoutes));
|
421
424
|
const { staticFiles, publicDirectoryFiles, staticDirectoryFiles } = await (0, utils_1.getStaticFiles)(entryPath, entryDirectory, outputDirectory);
|
422
425
|
const notFoundPreviewRoutes = [];
|
@@ -459,6 +462,39 @@ async function serverBuild({ dynamicPages, pagesDir, config = {}, privateOutputs
|
|
459
462
|
}
|
460
463
|
}
|
461
464
|
}
|
465
|
+
const normalizeNextDataRoute = isNextDataServerResolving
|
466
|
+
? [
|
467
|
+
// strip _next/data prefix for resolving
|
468
|
+
{
|
469
|
+
src: `^${path_1.default.join('/', entryDirectory, '/_next/data/', escapedBuildId, '/(.*).json')}`,
|
470
|
+
dest: `${path_1.default.join('/', entryDirectory, '/$1')}`,
|
471
|
+
continue: true,
|
472
|
+
override: true,
|
473
|
+
has: [
|
474
|
+
{
|
475
|
+
type: 'header',
|
476
|
+
key: 'x-nextjs-data',
|
477
|
+
},
|
478
|
+
],
|
479
|
+
},
|
480
|
+
]
|
481
|
+
: [];
|
482
|
+
const denormalizeNextDataRoute = isNextDataServerResolving
|
483
|
+
? [
|
484
|
+
{
|
485
|
+
src: '/(.*)',
|
486
|
+
has: [
|
487
|
+
{
|
488
|
+
type: 'header',
|
489
|
+
key: 'x-nextjs-data',
|
490
|
+
},
|
491
|
+
],
|
492
|
+
dest: `${path_1.default.join('/', entryDirectory, '/_next/data/', buildId, '/$1.json')}`,
|
493
|
+
continue: true,
|
494
|
+
override: true,
|
495
|
+
},
|
496
|
+
]
|
497
|
+
: [];
|
462
498
|
return {
|
463
499
|
wildcard: wildcardConfig,
|
464
500
|
images: imagesManifest?.images?.loader === 'default'
|
@@ -482,6 +518,15 @@ async function serverBuild({ dynamicPages, pagesDir, config = {}, privateOutputs
|
|
482
518
|
...staticDirectoryFiles,
|
483
519
|
...privateOutputs.files,
|
484
520
|
...middleware.edgeFunctions,
|
521
|
+
...(isNextDataServerResolving
|
522
|
+
? {
|
523
|
+
__next_data_catchall: new build_utils_1.FileBlob({
|
524
|
+
contentType: 'application/json',
|
525
|
+
mode: 0o644,
|
526
|
+
data: '{}',
|
527
|
+
}),
|
528
|
+
}
|
529
|
+
: {}),
|
485
530
|
},
|
486
531
|
routes: [
|
487
532
|
/*
|
@@ -499,6 +544,8 @@ async function serverBuild({ dynamicPages, pagesDir, config = {}, privateOutputs
|
|
499
544
|
// trailing slash
|
500
545
|
...trailingSlashRedirects,
|
501
546
|
...privateOutputs.routes,
|
547
|
+
// normalize _next/data URL before processing redirects
|
548
|
+
...normalizeNextDataRoute,
|
502
549
|
...(i18n
|
503
550
|
? [
|
504
551
|
// Handle auto-adding current default locale to path based on
|
@@ -624,6 +671,8 @@ async function serverBuild({ dynamicPages, pagesDir, config = {}, privateOutputs
|
|
624
671
|
continue: true,
|
625
672
|
},
|
626
673
|
]),
|
674
|
+
// we need to undo _next/data normalize before checking filesystem
|
675
|
+
...denormalizeNextDataRoute,
|
627
676
|
// while middleware was in beta the order came right before
|
628
677
|
// handle: 'filesystem' we maintain this for older versions
|
629
678
|
// to prevent a local/deploy mismatch
|
@@ -642,13 +691,19 @@ async function serverBuild({ dynamicPages, pagesDir, config = {}, privateOutputs
|
|
642
691
|
},
|
643
692
|
]
|
644
693
|
: []),
|
645
|
-
//
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
694
|
+
// normalize _next/data URL before processing rewrites
|
695
|
+
...normalizeNextDataRoute,
|
696
|
+
...(!isNextDataServerResolving
|
697
|
+
? [
|
698
|
+
// No-op _next/data rewrite to trigger handle: 'rewrites' and then 404
|
699
|
+
// if no match to prevent rewriting _next/data unexpectedly
|
700
|
+
{
|
701
|
+
src: path_1.default.join('/', entryDirectory, '_next/data/(.*)'),
|
702
|
+
dest: path_1.default.join('/', entryDirectory, '_next/data/$1'),
|
703
|
+
check: true,
|
704
|
+
},
|
705
|
+
]
|
706
|
+
: []),
|
652
707
|
// These need to come before handle: miss or else they are grouped
|
653
708
|
// with that routing section
|
654
709
|
...afterFilesRewrites,
|
@@ -694,18 +749,34 @@ async function serverBuild({ dynamicPages, pagesDir, config = {}, privateOutputs
|
|
694
749
|
// routes that are called after each rewrite or after routes
|
695
750
|
// if there no rewrites
|
696
751
|
{ handle: 'rewrite' },
|
752
|
+
// re-build /_next/data URL after resolving
|
753
|
+
...denormalizeNextDataRoute,
|
697
754
|
// /_next/data routes for getServerProps/getStaticProps pages
|
698
755
|
...dataRoutes,
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
756
|
+
...(!isNextDataServerResolving
|
757
|
+
? [
|
758
|
+
// ensure we 404 for non-existent _next/data routes before
|
759
|
+
// trying page dynamic routes
|
760
|
+
{
|
761
|
+
src: path_1.default.join('/', entryDirectory, '_next/data/(.*)'),
|
762
|
+
dest: path_1.default.join('/', entryDirectory, '404'),
|
763
|
+
status: 404,
|
764
|
+
},
|
765
|
+
]
|
766
|
+
: []),
|
706
767
|
// Dynamic routes (must come after dataRoutes as dataRoutes are more
|
707
768
|
// specific)
|
708
769
|
...dynamicRoutes,
|
770
|
+
...(isNextDataServerResolving
|
771
|
+
? [
|
772
|
+
// add a catch-all data route so we don't 404 when getting
|
773
|
+
// middleware effects
|
774
|
+
{
|
775
|
+
src: `^${path_1.default.join('/', entryDirectory, '/_next/data/', escapedBuildId, '/(.*).json')}`,
|
776
|
+
dest: '__next_data_catchall',
|
777
|
+
},
|
778
|
+
]
|
779
|
+
: []),
|
709
780
|
// routes to call after a file has been matched
|
710
781
|
{ handle: 'hit' },
|
711
782
|
// Before we handle static files we need to set proper caching headers
|
package/dist/utils.js
CHANGED
@@ -22,7 +22,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
22
22
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
23
23
|
};
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
25
|
-
exports.getMiddlewareBundle = exports.getSourceFilePathFromPage = exports.isDynamicRoute = exports.normalizePage = exports.getNextConfig = exports.normalizePackageJson = exports.validateEntrypoint = exports.excludeFiles = exports.getPrivateOutputs = exports.updateRouteSrc = exports.getNextServerPath = exports.normalizeIndexOutput = exports.getStaticFiles = exports.onPrerenderRoute = exports.onPrerenderRouteInitial = exports.detectLambdaLimitExceeding = exports.outputFunctionFileSizeInfo = exports.getPageLambdaGroups = exports.MAX_UNCOMPRESSED_LAMBDA_SIZE = exports.addLocaleOrDefault = exports.normalizeLocalePath = exports.getPrerenderManifest = exports.getRequiredServerFilesManifest = exports.getExportStatus = exports.getExportIntent = exports.createLambdaFromPseudoLayers = exports.createPseudoLayer = exports.ExperimentalTraceVersion = exports.collectTracedFiles = exports.getFilesMapFromReasons = exports.filterStaticPages = exports.getImagesManifest = exports.localizeDynamicRoutes = exports.getDynamicRoutes = exports.getRoutesManifest = void 0;
|
25
|
+
exports.getMiddlewareManifest = exports.getMiddlewareBundle = exports.getSourceFilePathFromPage = exports.isDynamicRoute = exports.normalizePage = exports.getNextConfig = exports.normalizePackageJson = exports.validateEntrypoint = exports.excludeFiles = exports.getPrivateOutputs = exports.updateRouteSrc = exports.getNextServerPath = exports.normalizeIndexOutput = exports.getStaticFiles = exports.onPrerenderRoute = exports.onPrerenderRouteInitial = exports.detectLambdaLimitExceeding = exports.outputFunctionFileSizeInfo = exports.getPageLambdaGroups = exports.MAX_UNCOMPRESSED_LAMBDA_SIZE = exports.addLocaleOrDefault = exports.normalizeLocalePath = exports.getPrerenderManifest = exports.getRequiredServerFilesManifest = exports.getExportStatus = exports.getExportIntent = exports.createLambdaFromPseudoLayers = exports.createPseudoLayer = exports.ExperimentalTraceVersion = exports.collectTracedFiles = exports.getFilesMapFromReasons = exports.filterStaticPages = exports.getImagesManifest = exports.localizeDynamicRoutes = exports.getDynamicRoutes = exports.getRoutesManifest = void 0;
|
26
26
|
const build_utils_1 = require("@vercel/build-utils");
|
27
27
|
const async_sema_1 = require("async-sema");
|
28
28
|
const buffer_crc32_1 = __importDefault(require("buffer-crc32"));
|
@@ -1336,25 +1336,41 @@ async function getPrivateOutputs(dir, entries) {
|
|
1336
1336
|
exports.getPrivateOutputs = getPrivateOutputs;
|
1337
1337
|
async function getMiddlewareBundle({ entryPath, outputDirectory, routesManifest, isCorrectMiddlewareOrder, }) {
|
1338
1338
|
const middlewareManifest = await getMiddlewareManifest(entryPath, outputDirectory);
|
1339
|
-
|
1340
|
-
|
1341
|
-
|
1339
|
+
const sortedFunctions = [
|
1340
|
+
...(!middlewareManifest
|
1341
|
+
? []
|
1342
|
+
: middlewareManifest.sortedMiddleware.map(key => ({
|
1343
|
+
key,
|
1344
|
+
edgeFunction: middlewareManifest?.middleware[key],
|
1345
|
+
type: 'middleware',
|
1346
|
+
}))),
|
1347
|
+
...Object.entries(middlewareManifest?.functions ?? {}).map(([key, edgeFunction]) => {
|
1348
|
+
return {
|
1349
|
+
key,
|
1350
|
+
edgeFunction,
|
1351
|
+
type: 'function',
|
1352
|
+
};
|
1353
|
+
}),
|
1354
|
+
];
|
1355
|
+
if (middlewareManifest && sortedFunctions.length > 0) {
|
1356
|
+
const workerConfigs = await Promise.all(sortedFunctions.map(async ({ key, edgeFunction, type }) => {
|
1342
1357
|
try {
|
1343
|
-
const wrappedModuleSource = await (0, get_edge_function_source_1.getNextjsEdgeFunctionSource)(
|
1344
|
-
name:
|
1358
|
+
const wrappedModuleSource = await (0, get_edge_function_source_1.getNextjsEdgeFunctionSource)(edgeFunction.files, {
|
1359
|
+
name: edgeFunction.name,
|
1345
1360
|
staticRoutes: routesManifest.staticRoutes,
|
1346
1361
|
dynamicRoutes: routesManifest.dynamicRoutes.filter(r => !('isMiddleware' in r)),
|
1347
1362
|
nextConfig: {
|
1348
1363
|
basePath: routesManifest.basePath,
|
1349
1364
|
i18n: routesManifest.i18n,
|
1350
1365
|
},
|
1351
|
-
}, path_1.default.resolve(entryPath, outputDirectory),
|
1366
|
+
}, path_1.default.resolve(entryPath, outputDirectory), edgeFunction.wasm);
|
1352
1367
|
return {
|
1353
|
-
|
1368
|
+
type,
|
1369
|
+
page: edgeFunction.page,
|
1354
1370
|
edgeFunction: (() => {
|
1355
1371
|
const { source, map } = wrappedModuleSource.sourceAndMap();
|
1356
1372
|
const transformedMap = (0, sourcemapped_1.stringifySourceMap)(transformSourceMap(map));
|
1357
|
-
const wasmFiles = (
|
1373
|
+
const wasmFiles = (edgeFunction.wasm ?? []).reduce((acc, { filePath, name }) => {
|
1358
1374
|
const fullFilePath = path_1.default.join(entryPath, outputDirectory, filePath);
|
1359
1375
|
acc[`wasm/${name}.wasm`] = new build_utils_1.FileFsRef({
|
1360
1376
|
mode: 0o644,
|
@@ -1365,7 +1381,7 @@ async function getMiddlewareBundle({ entryPath, outputDirectory, routesManifest,
|
|
1365
1381
|
}, {});
|
1366
1382
|
return new build_utils_1.EdgeFunction({
|
1367
1383
|
deploymentTarget: 'v8-worker',
|
1368
|
-
name:
|
1384
|
+
name: edgeFunction.name,
|
1369
1385
|
files: {
|
1370
1386
|
'index.js': new build_utils_1.FileBlob({
|
1371
1387
|
data: source,
|
@@ -1382,10 +1398,10 @@ async function getMiddlewareBundle({ entryPath, outputDirectory, routesManifest,
|
|
1382
1398
|
...wasmFiles,
|
1383
1399
|
},
|
1384
1400
|
entrypoint: 'index.js',
|
1385
|
-
envVarsInUse:
|
1401
|
+
envVarsInUse: edgeFunction.env,
|
1386
1402
|
});
|
1387
1403
|
})(),
|
1388
|
-
routeSrc: getRouteSrc(
|
1404
|
+
routeSrc: getRouteSrc(edgeFunction, routesManifest),
|
1389
1405
|
};
|
1390
1406
|
}
|
1391
1407
|
catch (e) {
|
@@ -1400,15 +1416,21 @@ async function getMiddlewareBundle({ entryPath, outputDirectory, routesManifest,
|
|
1400
1416
|
};
|
1401
1417
|
for (const worker of workerConfigs.values()) {
|
1402
1418
|
const edgeFile = worker.edgeFunction.name;
|
1403
|
-
|
1404
|
-
|
1419
|
+
const shortPath = edgeFile.replace(/^pages\//, '');
|
1420
|
+
worker.edgeFunction.name = shortPath;
|
1421
|
+
source.edgeFunctions[shortPath] = worker.edgeFunction;
|
1405
1422
|
const route = {
|
1406
1423
|
continue: true,
|
1407
|
-
middlewarePath: edgeFile,
|
1408
1424
|
src: worker.routeSrc,
|
1409
1425
|
};
|
1410
|
-
if (
|
1411
|
-
route.
|
1426
|
+
if (worker.type === 'function') {
|
1427
|
+
route.dest = shortPath;
|
1428
|
+
}
|
1429
|
+
else {
|
1430
|
+
route.middlewarePath = shortPath;
|
1431
|
+
if (isCorrectMiddlewareOrder) {
|
1432
|
+
route.override = true;
|
1433
|
+
}
|
1412
1434
|
}
|
1413
1435
|
if (routesManifest.version > 3 && isDynamicRoute(worker.page)) {
|
1414
1436
|
source.dynamicRouteMap.set(worker.page, route);
|
@@ -1442,6 +1464,7 @@ async function getMiddlewareManifest(entryPath, outputDirectory) {
|
|
1442
1464
|
}
|
1443
1465
|
return fs_extra_1.default.readJSON(middlewareManifestPath);
|
1444
1466
|
}
|
1467
|
+
exports.getMiddlewareManifest = getMiddlewareManifest;
|
1445
1468
|
/**
|
1446
1469
|
* For an object containing middleware info and a routes manifest this will
|
1447
1470
|
* generate a string with the route that will activate the middleware on
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@vercel/next",
|
3
|
-
"version": "3.0.
|
3
|
+
"version": "3.0.2-canary.0",
|
4
4
|
"license": "MIT",
|
5
5
|
"main": "./dist/index",
|
6
6
|
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/next-js",
|
@@ -45,7 +45,7 @@
|
|
45
45
|
"@types/semver": "6.0.0",
|
46
46
|
"@types/text-table": "0.2.1",
|
47
47
|
"@types/webpack-sources": "3.2.0",
|
48
|
-
"@vercel/build-utils": "4.
|
48
|
+
"@vercel/build-utils": "4.1.1-canary.0",
|
49
49
|
"@vercel/nft": "0.19.1",
|
50
50
|
"@vercel/routing-utils": "1.13.4",
|
51
51
|
"async-sema": "3.0.1",
|
@@ -70,5 +70,5 @@
|
|
70
70
|
"typescript": "4.5.2",
|
71
71
|
"webpack-sources": "3.2.3"
|
72
72
|
},
|
73
|
-
"gitHead": "
|
73
|
+
"gitHead": "4bf6295d7a1d6544f195d76a2a4aedb476fa7dc1"
|
74
74
|
}
|