import type { Redirect, Rewrite } from 'next/dist/lib/load-custom-routes' import type { NextConfig } from 'next/dist/server/config-shared' import type { Configuration as WebpackConfiguration, FileCacheOptions } from 'webpack' import { ntrMessagePrefix } from '../shared/withNtrPrefix' import { NextConfigWithNTR } from '../types' import { createNtrData } from './createNtrData' import { getPagesPath } from './getPagesPath' import { getRouteBranchReRoutes } from './getRouteBranchReRoutes' import { getAllRoutesFiles } from './routesFiles' /** * Sort redirects and rewrites by descending specificity: * - first by descending number of regexp in source * - then by descending number of path segments */ const sortBySpecificity = (rArray: R[]): R[] => rArray.sort((a, b) => { if (a.source.includes(':') && !b.source.includes(':')) { return 1 } if (!a.source.includes(':') && b.source.includes(':')) { return -1 } return b.source.split('/').length - a.source.split('/').length }) /** * Inject translated routes */ export const withTranslateRoutes = (userNextConfig: NextConfigWithNTR): NextConfig => { const { translateRoutes: { debug, pagesDirectory } = {}, ...nextConfig } = userNextConfig if (!nextConfig.i18n) { throw new Error( ntrMessagePrefix + 'No i18n config found in next.config.js. i18n config is mandatory to use next-translate-routes-multi-domain.\nSeehttps://nextjs.org/docs/advanced-features/i18n-routing', ) } const pagesPath = getPagesPath(pagesDirectory) const ntrData = createNtrData(userNextConfig, pagesPath) const { routesTree, locales, defaultLocale } = ntrData const { redirects, rewrites } = getRouteBranchReRoutes({ locales, routeBranch: routesTree, defaultLocale }) const sortedRedirects = sortBySpecificity(redirects) const sortedRewrites = sortBySpecificity(rewrites) if (debug) { console.log(ntrMessagePrefix + 'Redirects:', sortedRedirects) console.log(ntrMessagePrefix + 'Rewrites:', sortedRewrites) } return { ...nextConfig, webpack(conf: WebpackConfiguration, context) { const config = typeof nextConfig.webpack === 'function' ? (nextConfig.webpack(conf, context) as WebpackConfiguration) : conf config.cache = typeof config.cache === 'object' ? (config.cache as FileCacheOptions) : { type: 'filesystem' } config.cache.buildDependencies = config.cache.buildDependencies || {} config.cache.buildDependencies.ntrRoutes = getAllRoutesFiles() if (!config.module) { config.module = {} } if (!config.module.rules) { config.module.rules = [] } config.module.rules.push({ test: new RegExp( `${pagesPath.replace(/\\|\//g, '(\\\\|\\/)')}_app\\.(${context.config.pageExtensions.join('|')})$`, ), use: { loader: 'next-translate-routes-multi-domain/loader', options: { data: ntrData, }, }, }) return config }, async redirects() { const existingRedirects = (nextConfig.redirects && (await nextConfig.redirects())) || [] return [...sortedRedirects, ...existingRedirects] }, async rewrites() { const existingRewrites = (nextConfig.rewrites && (await nextConfig.rewrites())) || [] if (Array.isArray(existingRewrites)) { return [...existingRewrites, ...sortedRewrites] } return { ...existingRewrites, afterFiles: [...(existingRewrites.afterFiles || []), ...sortedRewrites], } }, } as NextConfig }