Spaces:
Running
Running
| ; | |
| Object.defineProperty(exports, "__esModule", { | |
| value: true | |
| }); | |
| 0 && (module.exports = { | |
| compileNonPath: null, | |
| matchHas: null, | |
| parseDestination: null, | |
| prepareDestination: null | |
| }); | |
| function _export(target, all) { | |
| for(var name in all)Object.defineProperty(target, name, { | |
| enumerable: true, | |
| get: all[name] | |
| }); | |
| } | |
| _export(exports, { | |
| compileNonPath: function() { | |
| return compileNonPath; | |
| }, | |
| matchHas: function() { | |
| return matchHas; | |
| }, | |
| parseDestination: function() { | |
| return parseDestination; | |
| }, | |
| prepareDestination: function() { | |
| return prepareDestination; | |
| } | |
| }); | |
| const _escaperegexp = require("../../escape-regexp"); | |
| const _parseurl = require("./parse-url"); | |
| const _interceptionroutes = require("./interception-routes"); | |
| const _getcookieparser = require("../../../../server/api-utils/get-cookie-parser"); | |
| const _routematchutils = require("./route-match-utils"); | |
| /** | |
| * Ensure only a-zA-Z are used for param names for proper interpolating | |
| * with path-to-regexp | |
| */ function getSafeParamName(paramName) { | |
| let newParamName = ''; | |
| for(let i = 0; i < paramName.length; i++){ | |
| const charCode = paramName.charCodeAt(i); | |
| if (charCode > 64 && charCode < 91 || // A-Z | |
| charCode > 96 && charCode < 123 // a-z | |
| ) { | |
| newParamName += paramName[i]; | |
| } | |
| } | |
| return newParamName; | |
| } | |
| function escapeSegment(str, segmentName) { | |
| return str.replace(new RegExp(`:${(0, _escaperegexp.escapeStringRegexp)(segmentName)}`, 'g'), `__ESC_COLON_${segmentName}`); | |
| } | |
| function unescapeSegments(str) { | |
| return str.replace(/__ESC_COLON_/gi, ':'); | |
| } | |
| function matchHas(req, query, has = [], missing = []) { | |
| const params = {}; | |
| const hasMatch = (hasItem)=>{ | |
| let value; | |
| let key = hasItem.key; | |
| switch(hasItem.type){ | |
| case 'header': | |
| { | |
| key = key.toLowerCase(); | |
| value = req.headers[key]; | |
| break; | |
| } | |
| case 'cookie': | |
| { | |
| if ('cookies' in req) { | |
| value = req.cookies[hasItem.key]; | |
| } else { | |
| const cookies = (0, _getcookieparser.getCookieParser)(req.headers)(); | |
| value = cookies[hasItem.key]; | |
| } | |
| break; | |
| } | |
| case 'query': | |
| { | |
| value = query[key]; | |
| break; | |
| } | |
| case 'host': | |
| { | |
| const { host } = req?.headers || {}; | |
| // remove port from host if present | |
| const hostname = host?.split(':', 1)[0].toLowerCase(); | |
| value = hostname; | |
| break; | |
| } | |
| default: | |
| { | |
| break; | |
| } | |
| } | |
| if (!hasItem.value && value) { | |
| params[getSafeParamName(key)] = value; | |
| return true; | |
| } else if (value) { | |
| const matcher = new RegExp(`^${hasItem.value}$`); | |
| const matches = Array.isArray(value) ? value.slice(-1)[0].match(matcher) : value.match(matcher); | |
| if (matches) { | |
| if (Array.isArray(matches)) { | |
| if (matches.groups) { | |
| Object.keys(matches.groups).forEach((groupKey)=>{ | |
| params[groupKey] = matches.groups[groupKey]; | |
| }); | |
| } else if (hasItem.type === 'host' && matches[0]) { | |
| params.host = matches[0]; | |
| } | |
| } | |
| return true; | |
| } | |
| } | |
| return false; | |
| }; | |
| const allMatch = has.every((item)=>hasMatch(item)) && !missing.some((item)=>hasMatch(item)); | |
| if (allMatch) { | |
| return params; | |
| } | |
| return false; | |
| } | |
| function compileNonPath(value, params) { | |
| if (!value.includes(':')) { | |
| return value; | |
| } | |
| for (const key of Object.keys(params)){ | |
| if (value.includes(`:${key}`)) { | |
| value = value.replace(new RegExp(`:${key}\\*`, 'g'), `:${key}--ESCAPED_PARAM_ASTERISKS`).replace(new RegExp(`:${key}\\?`, 'g'), `:${key}--ESCAPED_PARAM_QUESTION`).replace(new RegExp(`:${key}\\+`, 'g'), `:${key}--ESCAPED_PARAM_PLUS`).replace(new RegExp(`:${key}(?!\\w)`, 'g'), `--ESCAPED_PARAM_COLON${key}`); | |
| } | |
| } | |
| value = value.replace(/(:|\*|\?|\+|\(|\)|\{|\})/g, '\\$1').replace(/--ESCAPED_PARAM_PLUS/g, '+').replace(/--ESCAPED_PARAM_COLON/g, ':').replace(/--ESCAPED_PARAM_QUESTION/g, '?').replace(/--ESCAPED_PARAM_ASTERISKS/g, '*'); | |
| // the value needs to start with a forward-slash to be compiled | |
| // correctly | |
| return (0, _routematchutils.safeCompile)(`/${value}`, { | |
| validate: false | |
| })(params).slice(1); | |
| } | |
| function parseDestination(args) { | |
| let escaped = args.destination; | |
| for (const param of Object.keys({ | |
| ...args.params, | |
| ...args.query | |
| })){ | |
| if (!param) continue; | |
| escaped = escapeSegment(escaped, param); | |
| } | |
| const parsed = (0, _parseurl.parseUrl)(escaped); | |
| let pathname = parsed.pathname; | |
| if (pathname) { | |
| pathname = unescapeSegments(pathname); | |
| } | |
| let href = parsed.href; | |
| if (href) { | |
| href = unescapeSegments(href); | |
| } | |
| let hostname = parsed.hostname; | |
| if (hostname) { | |
| hostname = unescapeSegments(hostname); | |
| } | |
| let hash = parsed.hash; | |
| if (hash) { | |
| hash = unescapeSegments(hash); | |
| } | |
| let search = parsed.search; | |
| if (search) { | |
| search = unescapeSegments(search); | |
| } | |
| let origin = parsed.origin; | |
| if (origin) { | |
| origin = unescapeSegments(origin); | |
| } | |
| return { | |
| ...parsed, | |
| pathname, | |
| hostname, | |
| href, | |
| hash, | |
| search, | |
| origin | |
| }; | |
| } | |
| function prepareDestination(args) { | |
| const parsedDestination = parseDestination(args); | |
| const { hostname: destHostname, query: destQuery, search: destSearch } = parsedDestination; | |
| // The following code assumes that the pathname here includes the hash if it's | |
| // present. | |
| let destPath = parsedDestination.pathname; | |
| if (parsedDestination.hash) { | |
| destPath = `${destPath}${parsedDestination.hash}`; | |
| } | |
| const destParams = []; | |
| const destPathParamKeys = []; | |
| (0, _routematchutils.safePathToRegexp)(destPath, destPathParamKeys); | |
| for (const key of destPathParamKeys){ | |
| destParams.push(key.name); | |
| } | |
| if (destHostname) { | |
| const destHostnameParamKeys = []; | |
| (0, _routematchutils.safePathToRegexp)(destHostname, destHostnameParamKeys); | |
| for (const key of destHostnameParamKeys){ | |
| destParams.push(key.name); | |
| } | |
| } | |
| const destPathCompiler = (0, _routematchutils.safeCompile)(destPath, // we don't validate while compiling the destination since we should | |
| // have already validated before we got to this point and validating | |
| // breaks compiling destinations with named pattern params from the source | |
| // e.g. /something:hello(.*) -> /another/:hello is broken with validation | |
| // since compile validation is meant for reversing and not for inserting | |
| // params from a separate path-regex into another | |
| { | |
| validate: false | |
| }); | |
| let destHostnameCompiler; | |
| if (destHostname) { | |
| destHostnameCompiler = (0, _routematchutils.safeCompile)(destHostname, { | |
| validate: false | |
| }); | |
| } | |
| // update any params in query values | |
| for (const [key, strOrArray] of Object.entries(destQuery)){ | |
| // the value needs to start with a forward-slash to be compiled | |
| // correctly | |
| if (Array.isArray(strOrArray)) { | |
| destQuery[key] = strOrArray.map((value)=>compileNonPath(unescapeSegments(value), args.params)); | |
| } else if (typeof strOrArray === 'string') { | |
| destQuery[key] = compileNonPath(unescapeSegments(strOrArray), args.params); | |
| } | |
| } | |
| // add path params to query if it's not a redirect and not | |
| // already defined in destination query or path | |
| let paramKeys = Object.keys(args.params).filter((name)=>name !== 'nextInternalLocale'); | |
| if (args.appendParamsToQuery && !paramKeys.some((key)=>destParams.includes(key))) { | |
| for (const key of paramKeys){ | |
| if (!(key in destQuery)) { | |
| destQuery[key] = args.params[key]; | |
| } | |
| } | |
| } | |
| let newUrl; | |
| // The compiler also that the interception route marker is an unnamed param, hence '0', | |
| // so we need to add it to the params object. | |
| if ((0, _interceptionroutes.isInterceptionRouteAppPath)(destPath)) { | |
| for (const segment of destPath.split('/')){ | |
| const marker = _interceptionroutes.INTERCEPTION_ROUTE_MARKERS.find((m)=>segment.startsWith(m)); | |
| if (marker) { | |
| if (marker === '(..)(..)') { | |
| args.params['0'] = '(..)'; | |
| args.params['1'] = '(..)'; | |
| } else { | |
| args.params['0'] = marker; | |
| } | |
| break; | |
| } | |
| } | |
| } | |
| try { | |
| newUrl = destPathCompiler(args.params); | |
| const [pathname, hash] = newUrl.split('#', 2); | |
| if (destHostnameCompiler) { | |
| parsedDestination.hostname = destHostnameCompiler(args.params); | |
| } | |
| parsedDestination.pathname = pathname; | |
| parsedDestination.hash = `${hash ? '#' : ''}${hash || ''}`; | |
| parsedDestination.search = destSearch ? compileNonPath(destSearch, args.params) : ''; | |
| } catch (err) { | |
| if (err.message.match(/Expected .*? to not repeat, but got an array/)) { | |
| throw Object.defineProperty(new Error(`To use a multi-match in the destination you must add \`*\` at the end of the param name to signify it should repeat. https://nextjs.org/docs/messages/invalid-multi-match`), "__NEXT_ERROR_CODE", { | |
| value: "E329", | |
| enumerable: false, | |
| configurable: true | |
| }); | |
| } | |
| throw err; | |
| } | |
| // Query merge order lowest priority to highest | |
| // 1. initial URL query values | |
| // 2. path segment values | |
| // 3. destination specified query values | |
| parsedDestination.query = { | |
| ...args.query, | |
| ...parsedDestination.query | |
| }; | |
| return { | |
| newUrl, | |
| destQuery, | |
| parsedDestination | |
| }; | |
| } | |
| //# sourceMappingURL=prepare-destination.js.map |