You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
	
	
		
			304 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			JavaScript
		
	
		
		
			
		
	
	
			304 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			JavaScript
		
	
| 
											9 months ago
										 | "use strict"; | ||
|  | Object.defineProperty(exports, "__esModule", { | ||
|  |     value: true | ||
|  | }); | ||
|  | 0 && (module.exports = { | ||
|  |     normalizeVercelUrl: null, | ||
|  |     interpolateDynamicPath: null, | ||
|  |     normalizeDynamicRouteParams: null, | ||
|  |     getUtils: null | ||
|  | }); | ||
|  | function _export(target, all) { | ||
|  |     for(var name in all)Object.defineProperty(target, name, { | ||
|  |         enumerable: true, | ||
|  |         get: all[name] | ||
|  |     }); | ||
|  | } | ||
|  | _export(exports, { | ||
|  |     normalizeVercelUrl: function() { | ||
|  |         return normalizeVercelUrl; | ||
|  |     }, | ||
|  |     interpolateDynamicPath: function() { | ||
|  |         return interpolateDynamicPath; | ||
|  |     }, | ||
|  |     normalizeDynamicRouteParams: function() { | ||
|  |         return normalizeDynamicRouteParams; | ||
|  |     }, | ||
|  |     getUtils: function() { | ||
|  |         return getUtils; | ||
|  |     } | ||
|  | }); | ||
|  | const _url = require("url"); | ||
|  | const _normalizelocalepath = require("../shared/lib/i18n/normalize-locale-path"); | ||
|  | const _pathmatch = require("../shared/lib/router/utils/path-match"); | ||
|  | const _routeregex = require("../shared/lib/router/utils/route-regex"); | ||
|  | const _routematcher = require("../shared/lib/router/utils/route-matcher"); | ||
|  | const _preparedestination = require("../shared/lib/router/utils/prepare-destination"); | ||
|  | const _removetrailingslash = require("../shared/lib/router/utils/remove-trailing-slash"); | ||
|  | const _apppaths = require("../shared/lib/router/utils/app-paths"); | ||
|  | const _constants = require("../lib/constants"); | ||
|  | function normalizeVercelUrl(req, trustQuery, paramKeys, pageIsDynamic, defaultRouteRegex) { | ||
|  |     // make sure to normalize req.url on Vercel to strip dynamic params
 | ||
|  |     // from the query which are added during routing
 | ||
|  |     if (pageIsDynamic && trustQuery && defaultRouteRegex) { | ||
|  |         const _parsedUrl = (0, _url.parse)(req.url, true); | ||
|  |         delete _parsedUrl.search; | ||
|  |         for (const key of Object.keys(_parsedUrl.query)){ | ||
|  |             if (key !== _constants.NEXT_QUERY_PARAM_PREFIX && key.startsWith(_constants.NEXT_QUERY_PARAM_PREFIX) || (paramKeys || Object.keys(defaultRouteRegex.groups)).includes(key)) { | ||
|  |                 delete _parsedUrl.query[key]; | ||
|  |             } | ||
|  |         } | ||
|  |         req.url = (0, _url.format)(_parsedUrl); | ||
|  |     } | ||
|  | } | ||
|  | function interpolateDynamicPath(pathname, params, defaultRouteRegex) { | ||
|  |     if (!defaultRouteRegex) return pathname; | ||
|  |     for (const param of Object.keys(defaultRouteRegex.groups)){ | ||
|  |         const { optional, repeat } = defaultRouteRegex.groups[param]; | ||
|  |         let builtParam = `[${repeat ? "..." : ""}${param}]`; | ||
|  |         if (optional) { | ||
|  |             builtParam = `[${builtParam}]`; | ||
|  |         } | ||
|  |         const paramIdx = pathname.indexOf(builtParam); | ||
|  |         if (paramIdx > -1) { | ||
|  |             let paramValue; | ||
|  |             const value = params[param]; | ||
|  |             if (Array.isArray(value)) { | ||
|  |                 paramValue = value.map((v)=>v && encodeURIComponent(v)).join("/"); | ||
|  |             } else if (value) { | ||
|  |                 paramValue = encodeURIComponent(value); | ||
|  |             } else { | ||
|  |                 paramValue = ""; | ||
|  |             } | ||
|  |             pathname = pathname.slice(0, paramIdx) + paramValue + pathname.slice(paramIdx + builtParam.length); | ||
|  |         } | ||
|  |     } | ||
|  |     return pathname; | ||
|  | } | ||
|  | function normalizeDynamicRouteParams(params, ignoreOptional, defaultRouteRegex, defaultRouteMatches) { | ||
|  |     let hasValidParams = true; | ||
|  |     if (!defaultRouteRegex) return { | ||
|  |         params, | ||
|  |         hasValidParams: false | ||
|  |     }; | ||
|  |     params = Object.keys(defaultRouteRegex.groups).reduce((prev, key)=>{ | ||
|  |         let value = params[key]; | ||
|  |         if (typeof value === "string") { | ||
|  |             value = (0, _apppaths.normalizeRscURL)(value); | ||
|  |         } | ||
|  |         if (Array.isArray(value)) { | ||
|  |             value = value.map((val)=>{ | ||
|  |                 if (typeof val === "string") { | ||
|  |                     val = (0, _apppaths.normalizeRscURL)(val); | ||
|  |                 } | ||
|  |                 return val; | ||
|  |             }); | ||
|  |         } | ||
|  |         // if the value matches the default value we can't rely
 | ||
|  |         // on the parsed params, this is used to signal if we need
 | ||
|  |         // to parse x-now-route-matches or not
 | ||
|  |         const defaultValue = defaultRouteMatches[key]; | ||
|  |         const isOptional = defaultRouteRegex.groups[key].optional; | ||
|  |         const isDefaultValue = Array.isArray(defaultValue) ? defaultValue.some((defaultVal)=>{ | ||
|  |             return Array.isArray(value) ? value.some((val)=>val.includes(defaultVal)) : value == null ? void 0 : value.includes(defaultVal); | ||
|  |         }) : value == null ? void 0 : value.includes(defaultValue); | ||
|  |         if (isDefaultValue || typeof value === "undefined" && !(isOptional && ignoreOptional)) { | ||
|  |             hasValidParams = false; | ||
|  |         } | ||
|  |         // non-provided optional values should be undefined so normalize
 | ||
|  |         // them to undefined
 | ||
|  |         if (isOptional && (!value || Array.isArray(value) && value.length === 1 && // fallback optional catch-all SSG pages have
 | ||
|  |         // [[...paramName]] for the root path on Vercel
 | ||
|  |         (value[0] === "index" || value[0] === `[[...${key}]]`))) { | ||
|  |             value = undefined; | ||
|  |             delete params[key]; | ||
|  |         } | ||
|  |         // query values from the proxy aren't already split into arrays
 | ||
|  |         // so make sure to normalize catch-all values
 | ||
|  |         if (value && typeof value === "string" && defaultRouteRegex.groups[key].repeat) { | ||
|  |             value = value.split("/"); | ||
|  |         } | ||
|  |         if (value) { | ||
|  |             prev[key] = value; | ||
|  |         } | ||
|  |         return prev; | ||
|  |     }, {}); | ||
|  |     return { | ||
|  |         params, | ||
|  |         hasValidParams | ||
|  |     }; | ||
|  | } | ||
|  | function getUtils({ page, i18n, basePath, rewrites, pageIsDynamic, trailingSlash, caseSensitive }) { | ||
|  |     let defaultRouteRegex; | ||
|  |     let dynamicRouteMatcher; | ||
|  |     let defaultRouteMatches; | ||
|  |     if (pageIsDynamic) { | ||
|  |         defaultRouteRegex = (0, _routeregex.getNamedRouteRegex)(page, false); | ||
|  |         dynamicRouteMatcher = (0, _routematcher.getRouteMatcher)(defaultRouteRegex); | ||
|  |         defaultRouteMatches = dynamicRouteMatcher(page); | ||
|  |     } | ||
|  |     function handleRewrites(req, parsedUrl) { | ||
|  |         const rewriteParams = {}; | ||
|  |         let fsPathname = parsedUrl.pathname; | ||
|  |         const matchesPage = ()=>{ | ||
|  |             const fsPathnameNoSlash = (0, _removetrailingslash.removeTrailingSlash)(fsPathname || ""); | ||
|  |             return fsPathnameNoSlash === (0, _removetrailingslash.removeTrailingSlash)(page) || (dynamicRouteMatcher == null ? void 0 : dynamicRouteMatcher(fsPathnameNoSlash)); | ||
|  |         }; | ||
|  |         const checkRewrite = (rewrite)=>{ | ||
|  |             const matcher = (0, _pathmatch.getPathMatch)(rewrite.source + (trailingSlash ? "(/)?" : ""), { | ||
|  |                 removeUnnamedParams: true, | ||
|  |                 strict: true, | ||
|  |                 sensitive: !!caseSensitive | ||
|  |             }); | ||
|  |             let params = matcher(parsedUrl.pathname); | ||
|  |             if ((rewrite.has || rewrite.missing) && params) { | ||
|  |                 const hasParams = (0, _preparedestination.matchHas)(req, parsedUrl.query, rewrite.has, rewrite.missing); | ||
|  |                 if (hasParams) { | ||
|  |                     Object.assign(params, hasParams); | ||
|  |                 } else { | ||
|  |                     params = false; | ||
|  |                 } | ||
|  |             } | ||
|  |             if (params) { | ||
|  |                 const { parsedDestination, destQuery } = (0, _preparedestination.prepareDestination)({ | ||
|  |                     appendParamsToQuery: true, | ||
|  |                     destination: rewrite.destination, | ||
|  |                     params: params, | ||
|  |                     query: parsedUrl.query | ||
|  |                 }); | ||
|  |                 // if the rewrite destination is external break rewrite chain
 | ||
|  |                 if (parsedDestination.protocol) { | ||
|  |                     return true; | ||
|  |                 } | ||
|  |                 Object.assign(rewriteParams, destQuery, params); | ||
|  |                 Object.assign(parsedUrl.query, parsedDestination.query); | ||
|  |                 delete parsedDestination.query; | ||
|  |                 Object.assign(parsedUrl, parsedDestination); | ||
|  |                 fsPathname = parsedUrl.pathname; | ||
|  |                 if (basePath) { | ||
|  |                     fsPathname = fsPathname.replace(new RegExp(`^${basePath}`), "") || "/"; | ||
|  |                 } | ||
|  |                 if (i18n) { | ||
|  |                     const destLocalePathResult = (0, _normalizelocalepath.normalizeLocalePath)(fsPathname, i18n.locales); | ||
|  |                     fsPathname = destLocalePathResult.pathname; | ||
|  |                     parsedUrl.query.nextInternalLocale = destLocalePathResult.detectedLocale || params.nextInternalLocale; | ||
|  |                 } | ||
|  |                 if (fsPathname === page) { | ||
|  |                     return true; | ||
|  |                 } | ||
|  |                 if (pageIsDynamic && dynamicRouteMatcher) { | ||
|  |                     const dynamicParams = dynamicRouteMatcher(fsPathname); | ||
|  |                     if (dynamicParams) { | ||
|  |                         parsedUrl.query = { | ||
|  |                             ...parsedUrl.query, | ||
|  |                             ...dynamicParams | ||
|  |                         }; | ||
|  |                         return true; | ||
|  |                     } | ||
|  |                 } | ||
|  |             } | ||
|  |             return false; | ||
|  |         }; | ||
|  |         for (const rewrite of rewrites.beforeFiles || []){ | ||
|  |             checkRewrite(rewrite); | ||
|  |         } | ||
|  |         if (fsPathname !== page) { | ||
|  |             let finished = false; | ||
|  |             for (const rewrite of rewrites.afterFiles || []){ | ||
|  |                 finished = checkRewrite(rewrite); | ||
|  |                 if (finished) break; | ||
|  |             } | ||
|  |             if (!finished && !matchesPage()) { | ||
|  |                 for (const rewrite of rewrites.fallback || []){ | ||
|  |                     finished = checkRewrite(rewrite); | ||
|  |                     if (finished) break; | ||
|  |                 } | ||
|  |             } | ||
|  |         } | ||
|  |         return rewriteParams; | ||
|  |     } | ||
|  |     function getParamsFromRouteMatches(req, renderOpts, detectedLocale) { | ||
|  |         return (0, _routematcher.getRouteMatcher)(function() { | ||
|  |             const { groups, routeKeys } = defaultRouteRegex; | ||
|  |             return { | ||
|  |                 re: { | ||
|  |                     // Simulate a RegExp match from the \`req.url\` input
 | ||
|  |                     exec: (str)=>{ | ||
|  |                         const obj = Object.fromEntries(new URLSearchParams(str)); | ||
|  |                         const matchesHasLocale = i18n && detectedLocale && obj["1"] === detectedLocale; | ||
|  |                         for (const key of Object.keys(obj)){ | ||
|  |                             const value = obj[key]; | ||
|  |                             if (key !== _constants.NEXT_QUERY_PARAM_PREFIX && key.startsWith(_constants.NEXT_QUERY_PARAM_PREFIX)) { | ||
|  |                                 const normalizedKey = key.substring(_constants.NEXT_QUERY_PARAM_PREFIX.length); | ||
|  |                                 obj[normalizedKey] = value; | ||
|  |                                 delete obj[key]; | ||
|  |                             } | ||
|  |                         } | ||
|  |                         // favor named matches if available
 | ||
|  |                         const routeKeyNames = Object.keys(routeKeys || {}); | ||
|  |                         const filterLocaleItem = (val)=>{ | ||
|  |                             if (i18n) { | ||
|  |                                 // locale items can be included in route-matches
 | ||
|  |                                 // for fallback SSG pages so ensure they are
 | ||
|  |                                 // filtered
 | ||
|  |                                 const isCatchAll = Array.isArray(val); | ||
|  |                                 const _val = isCatchAll ? val[0] : val; | ||
|  |                                 if (typeof _val === "string" && i18n.locales.some((item)=>{ | ||
|  |                                     if (item.toLowerCase() === _val.toLowerCase()) { | ||
|  |                                         detectedLocale = item; | ||
|  |                                         renderOpts.locale = detectedLocale; | ||
|  |                                         return true; | ||
|  |                                     } | ||
|  |                                     return false; | ||
|  |                                 })) { | ||
|  |                                     // remove the locale item from the match
 | ||
|  |                                     if (isCatchAll) { | ||
|  |                                         val.splice(0, 1); | ||
|  |                                     } | ||
|  |                                     // the value is only a locale item and
 | ||
|  |                                     // shouldn't be added
 | ||
|  |                                     return isCatchAll ? val.length === 0 : true; | ||
|  |                                 } | ||
|  |                             } | ||
|  |                             return false; | ||
|  |                         }; | ||
|  |                         if (routeKeyNames.every((name)=>obj[name])) { | ||
|  |                             return routeKeyNames.reduce((prev, keyName)=>{ | ||
|  |                                 const paramName = routeKeys == null ? void 0 : routeKeys[keyName]; | ||
|  |                                 if (paramName && !filterLocaleItem(obj[keyName])) { | ||
|  |                                     prev[groups[paramName].pos] = obj[keyName]; | ||
|  |                                 } | ||
|  |                                 return prev; | ||
|  |                             }, {}); | ||
|  |                         } | ||
|  |                         return Object.keys(obj).reduce((prev, key)=>{ | ||
|  |                             if (!filterLocaleItem(obj[key])) { | ||
|  |                                 let normalizedKey = key; | ||
|  |                                 if (matchesHasLocale) { | ||
|  |                                     normalizedKey = parseInt(key, 10) - 1 + ""; | ||
|  |                                 } | ||
|  |                                 return Object.assign(prev, { | ||
|  |                                     [normalizedKey]: obj[key] | ||
|  |                                 }); | ||
|  |                             } | ||
|  |                             return prev; | ||
|  |                         }, {}); | ||
|  |                     } | ||
|  |                 }, | ||
|  |                 groups | ||
|  |             }; | ||
|  |         }())(req.headers["x-now-route-matches"]); | ||
|  |     } | ||
|  |     return { | ||
|  |         handleRewrites, | ||
|  |         defaultRouteRegex, | ||
|  |         dynamicRouteMatcher, | ||
|  |         defaultRouteMatches, | ||
|  |         getParamsFromRouteMatches, | ||
|  |         normalizeDynamicRouteParams: (params, ignoreOptional)=>normalizeDynamicRouteParams(params, ignoreOptional, defaultRouteRegex, defaultRouteMatches), | ||
|  |         normalizeVercelUrl: (req, trustQuery, paramKeys)=>normalizeVercelUrl(req, trustQuery, paramKeys, pageIsDynamic, defaultRouteRegex), | ||
|  |         interpolateDynamicPath: (pathname, params)=>interpolateDynamicPath(pathname, params, defaultRouteRegex) | ||
|  |     }; | ||
|  | } | ||
|  | 
 | ||
|  | //# sourceMappingURL=server-utils.js.map
 |