main repo

This commit is contained in:
Basilosaurusrex
2025-11-24 18:09:40 +01:00
parent b636ee5e70
commit f027651f9b
34146 changed files with 4436636 additions and 0 deletions

View File

@@ -0,0 +1,65 @@
import type { DomainLocale, I18NConfig } from '../../config-shared';
import type { NextParsedUrlQuery } from '../../request-meta';
/**
* The result of matching a locale aware route.
*/
export interface LocaleAnalysisResult {
/**
* The pathname without the locale prefix (if any).
*/
pathname: string;
/**
* The detected locale. If no locale was detected, this will be `undefined`.
*/
detectedLocale?: string;
/**
* True if the locale was inferred from the default locale.
*/
inferredFromDefault: boolean;
}
type LocaleAnalysisOptions = {
/**
* When provided, it will be used as the default locale if the locale
* cannot be inferred from the pathname.
*/
defaultLocale?: string;
};
/**
* The I18NProvider is used to match locale aware routes, detect the locale from
* the pathname and hostname and normalize the pathname by removing the locale
* prefix.
*/
export declare class I18NProvider {
readonly config: Readonly<I18NConfig>;
private readonly lowerCaseLocales;
private readonly lowerCaseDomains?;
constructor(config: Readonly<I18NConfig>);
/**
* Detects the domain locale from the hostname and the detected locale if
* provided.
*
* @param hostname The hostname to detect the domain locale from, this must be lowercased.
* @param detectedLocale The detected locale to use if the hostname does not match.
* @returns The domain locale if found, `undefined` otherwise.
*/
detectDomainLocale(hostname?: string, detectedLocale?: string): DomainLocale | undefined;
/**
* Pulls the pre-computed locale and inference results from the query
* object.
*
* @param pathname the pathname that could contain a locale prefix
* @param query the query object
* @returns the locale analysis result
*/
fromQuery(pathname: string, query: NextParsedUrlQuery): LocaleAnalysisResult;
/**
* Analyzes the pathname for a locale and returns the pathname without it.
*
* @param pathname The pathname that could contain a locale prefix.
* @param options The options to use when matching the locale.
* @returns The matched locale and the pathname without the locale prefix
* (if any).
*/
analyze(pathname: string, options?: LocaleAnalysisOptions): LocaleAnalysisResult;
}
export {};

View File

@@ -0,0 +1,124 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "I18NProvider", {
enumerable: true,
get: function() {
return I18NProvider;
}
});
class I18NProvider {
constructor(config){
var _config_domains;
this.config = config;
if (!config.locales.length) {
throw new Error("Invariant: No locales provided");
}
this.lowerCaseLocales = config.locales.map((locale)=>locale.toLowerCase());
this.lowerCaseDomains = (_config_domains = config.domains) == null ? void 0 : _config_domains.map((domainLocale)=>{
var _domainLocale_locales;
const domain = domainLocale.domain.toLowerCase();
return {
defaultLocale: domainLocale.defaultLocale.toLowerCase(),
hostname: domain.split(":")[0],
domain,
locales: (_domainLocale_locales = domainLocale.locales) == null ? void 0 : _domainLocale_locales.map((locale)=>locale.toLowerCase()),
http: domainLocale.http
};
});
}
/**
* Detects the domain locale from the hostname and the detected locale if
* provided.
*
* @param hostname The hostname to detect the domain locale from, this must be lowercased.
* @param detectedLocale The detected locale to use if the hostname does not match.
* @returns The domain locale if found, `undefined` otherwise.
*/ detectDomainLocale(hostname, detectedLocale) {
if (!hostname || !this.lowerCaseDomains || !this.config.domains) return;
if (detectedLocale) detectedLocale = detectedLocale.toLowerCase();
for(let i = 0; i < this.lowerCaseDomains.length; i++){
var // Configuration validation ensures that the locale is not repeated in
// other domains locales.
_domainLocale_locales;
const domainLocale = this.lowerCaseDomains[i];
if (// We assume that the hostname is already lowercased.
domainLocale.hostname === hostname || ((_domainLocale_locales = domainLocale.locales) == null ? void 0 : _domainLocale_locales.some((locale)=>locale === detectedLocale))) {
return this.config.domains[i];
}
}
return;
}
/**
* Pulls the pre-computed locale and inference results from the query
* object.
*
* @param pathname the pathname that could contain a locale prefix
* @param query the query object
* @returns the locale analysis result
*/ fromQuery(pathname, query) {
const detectedLocale = query.__nextLocale;
// If a locale was detected on the query, analyze the pathname to ensure
// that the locale matches.
if (detectedLocale) {
const analysis = this.analyze(pathname);
// If the analysis contained a locale we should validate it against the
// query and strip it from the pathname.
if (analysis.detectedLocale) {
if (analysis.detectedLocale !== detectedLocale) {
throw new Error(`Invariant: The detected locale does not match the locale in the query. Expected to find '${detectedLocale}' in '${pathname}' but found '${analysis.detectedLocale}'}`);
}
pathname = analysis.pathname;
}
}
return {
pathname,
detectedLocale,
inferredFromDefault: query.__nextInferredLocaleFromDefault === "1"
};
}
/**
* Analyzes the pathname for a locale and returns the pathname without it.
*
* @param pathname The pathname that could contain a locale prefix.
* @param options The options to use when matching the locale.
* @returns The matched locale and the pathname without the locale prefix
* (if any).
*/ analyze(pathname, options = {}) {
let detectedLocale = options.defaultLocale;
// By default, we assume that the default locale was inferred if there was
// no detected locale.
let inferredFromDefault = typeof detectedLocale === "string";
// The first segment will be empty, because it has a leading `/`. If
// there is no further segment, there is no locale (or it's the default).
const segments = pathname.split("/");
if (!segments[1]) return {
detectedLocale,
pathname,
inferredFromDefault
};
// The second segment will contain the locale part if any.
const segment = segments[1].toLowerCase();
// See if the segment matches one of the locales. If it doesn't, there is
// no locale (or it's the default).
const index = this.lowerCaseLocales.indexOf(segment);
if (index < 0) return {
detectedLocale,
pathname,
inferredFromDefault
};
// Return the case-sensitive locale.
detectedLocale = this.config.locales[index];
inferredFromDefault = false;
// Remove the `/${locale}` part of the pathname.
pathname = pathname.slice(detectedLocale.length + 1) || "/";
return {
detectedLocale,
pathname,
inferredFromDefault
};
}
}
//# sourceMappingURL=i18n-provider.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/server/future/helpers/i18n-provider.ts"],"names":["I18NProvider","constructor","config","locales","length","Error","lowerCaseLocales","map","locale","toLowerCase","lowerCaseDomains","domains","domainLocale","domain","defaultLocale","hostname","split","http","detectDomainLocale","detectedLocale","i","some","fromQuery","pathname","query","__nextLocale","analysis","analyze","inferredFromDefault","__nextInferredLocaleFromDefault","options","segments","segment","index","indexOf","slice"],"mappings":"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"}

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,6 @@
export declare const INTERCEPTION_ROUTE_MARKERS: readonly ["(..)(..)", "(.)", "(..)", "(...)"];
export declare function isInterceptionRouteAppPath(path: string): boolean;
export declare function extractInterceptionRouteInformation(path: string): {
interceptingRoute: string;
interceptedRoute: string;
};

View File

@@ -0,0 +1,89 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
INTERCEPTION_ROUTE_MARKERS: null,
isInterceptionRouteAppPath: null,
extractInterceptionRouteInformation: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
INTERCEPTION_ROUTE_MARKERS: function() {
return INTERCEPTION_ROUTE_MARKERS;
},
isInterceptionRouteAppPath: function() {
return isInterceptionRouteAppPath;
},
extractInterceptionRouteInformation: function() {
return extractInterceptionRouteInformation;
}
});
const _apppaths = require("../../../shared/lib/router/utils/app-paths");
const INTERCEPTION_ROUTE_MARKERS = [
"(..)(..)",
"(.)",
"(..)",
"(...)"
];
function isInterceptionRouteAppPath(path) {
// TODO-APP: add more serious validation
return path.split("/").find((segment)=>INTERCEPTION_ROUTE_MARKERS.find((m)=>segment.startsWith(m))) !== undefined;
}
function extractInterceptionRouteInformation(path) {
let interceptingRoute, marker, interceptedRoute;
for (const segment of path.split("/")){
marker = INTERCEPTION_ROUTE_MARKERS.find((m)=>segment.startsWith(m));
if (marker) {
[interceptingRoute, interceptedRoute] = path.split(marker, 2);
break;
}
}
if (!interceptingRoute || !marker || !interceptedRoute) {
throw new Error(`Invalid interception route: ${path}. Must be in the format /<intercepting route>/(..|...|..)(..)/<intercepted route>`);
}
interceptingRoute = (0, _apppaths.normalizeAppPath)(interceptingRoute) // normalize the path, e.g. /(blog)/feed -> /feed
;
switch(marker){
case "(.)":
// (.) indicates that we should match with sibling routes, so we just need to append the intercepted route to the intercepting route
if (interceptingRoute === "/") {
interceptedRoute = `/${interceptedRoute}`;
} else {
interceptedRoute = interceptingRoute + "/" + interceptedRoute;
}
break;
case "(..)":
// (..) indicates that we should match at one level up, so we need to remove the last segment of the intercepting route
if (interceptingRoute === "/") {
throw new Error(`Invalid interception route: ${path}. Cannot use (..) marker at the root level, use (.) instead.`);
}
interceptedRoute = interceptingRoute.split("/").slice(0, -1).concat(interceptedRoute).join("/");
break;
case "(...)":
// (...) will match the route segment in the root directory, so we need to use the root directory to prepend the intercepted route
interceptedRoute = "/" + interceptedRoute;
break;
case "(..)(..)":
// (..)(..) indicates that we should match at two levels up, so we need to remove the last two segments of the intercepting route
const splitInterceptingRoute = interceptingRoute.split("/");
if (splitInterceptingRoute.length <= 2) {
throw new Error(`Invalid interception route: ${path}. Cannot use (..)(..) marker at the root level or one level up.`);
}
interceptedRoute = splitInterceptingRoute.slice(0, -2).concat(interceptedRoute).join("/");
break;
default:
throw new Error("Invariant: unexpected marker");
}
return {
interceptingRoute,
interceptedRoute
};
}
//# sourceMappingURL=interception-routes.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/server/future/helpers/interception-routes.ts"],"names":["INTERCEPTION_ROUTE_MARKERS","isInterceptionRouteAppPath","extractInterceptionRouteInformation","path","split","find","segment","m","startsWith","undefined","interceptingRoute","marker","interceptedRoute","Error","normalizeAppPath","slice","concat","join","splitInterceptingRoute","length"],"mappings":";;;;;;;;;;;;;;;;IAGaA,0BAA0B;eAA1BA;;IAOGC,0BAA0B;eAA1BA;;IAWAC,mCAAmC;eAAnCA;;;0BArBiB;AAG1B,MAAMF,6BAA6B;IACxC;IACA;IACA;IACA;CACD;AAEM,SAASC,2BAA2BE,IAAY;IACrD,wCAAwC;IACxC,OACEA,KACGC,KAAK,CAAC,KACNC,IAAI,CAAC,CAACC,UACLN,2BAA2BK,IAAI,CAAC,CAACE,IAAMD,QAAQE,UAAU,CAACD,SACtDE;AAEZ;AAEO,SAASP,oCAAoCC,IAAY;IAC9D,IAAIO,mBACFC,QACAC;IAEF,KAAK,MAAMN,WAAWH,KAAKC,KAAK,CAAC,KAAM;QACrCO,SAASX,2BAA2BK,IAAI,CAAC,CAACE,IAAMD,QAAQE,UAAU,CAACD;QACnE,IAAII,QAAQ;YACT,CAACD,mBAAmBE,iBAAiB,GAAGT,KAAKC,KAAK,CAACO,QAAQ;YAC5D;QACF;IACF;IAEA,IAAI,CAACD,qBAAqB,CAACC,UAAU,CAACC,kBAAkB;QACtD,MAAM,IAAIC,MACR,CAAC,4BAA4B,EAAEV,KAAK,iFAAiF,CAAC;IAE1H;IAEAO,oBAAoBI,IAAAA,0BAAgB,EAACJ,mBAAmB,iDAAiD;;IAEzG,OAAQC;QACN,KAAK;YACH,oIAAoI;YACpI,IAAID,sBAAsB,KAAK;gBAC7BE,mBAAmB,CAAC,CAAC,EAAEA,iBAAiB,CAAC;YAC3C,OAAO;gBACLA,mBAAmBF,oBAAoB,MAAME;YAC/C;YACA;QACF,KAAK;YACH,uHAAuH;YACvH,IAAIF,sBAAsB,KAAK;gBAC7B,MAAM,IAAIG,MACR,CAAC,4BAA4B,EAAEV,KAAK,4DAA4D,CAAC;YAErG;YACAS,mBAAmBF,kBAChBN,KAAK,CAAC,KACNW,KAAK,CAAC,GAAG,CAAC,GACVC,MAAM,CAACJ,kBACPK,IAAI,CAAC;YACR;QACF,KAAK;YACH,kIAAkI;YAClIL,mBAAmB,MAAMA;YACzB;QACF,KAAK;YACH,iIAAiI;YAEjI,MAAMM,yBAAyBR,kBAAkBN,KAAK,CAAC;YACvD,IAAIc,uBAAuBC,MAAM,IAAI,GAAG;gBACtC,MAAM,IAAIN,MACR,CAAC,4BAA4B,EAAEV,KAAK,+DAA+D,CAAC;YAExG;YAEAS,mBAAmBM,uBAChBH,KAAK,CAAC,GAAG,CAAC,GACVC,MAAM,CAACJ,kBACPK,IAAI,CAAC;YACR;QACF;YACE,MAAM,IAAIJ,MAAM;IACpB;IAEA,OAAO;QAAEH;QAAmBE;IAAiB;AAC/C"}

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,6 @@
/**
* Loads a given module for a given ID.
*/
export interface ModuleLoader {
load<M = any>(id: string): Promise<M>;
}

View File

@@ -0,0 +1,8 @@
/**
* Loads a given module for a given ID.
*/ "use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
//# sourceMappingURL=module-loader.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/server/future/helpers/module-loader/module-loader.ts"],"names":[],"mappings":"AAAA;;CAEC"}

View File

@@ -0,0 +1,7 @@
import { ModuleLoader } from './module-loader';
/**
* Loads a module using `await require(id)`.
*/
export declare class NodeModuleLoader implements ModuleLoader {
load<M>(id: string): Promise<M>;
}

View File

@@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "NodeModuleLoader", {
enumerable: true,
get: function() {
return NodeModuleLoader;
}
});
class NodeModuleLoader {
async load(id) {
if (process.env.NEXT_RUNTIME !== "edge") {
// Need to `await` to cover the case that route is marked ESM modules by ESM escalation.
return await (process.env.NEXT_MINIMAL ? __non_webpack_require__(id) : require(id));
}
throw new Error("NodeModuleLoader is not supported in edge runtime.");
}
}
//# sourceMappingURL=node-module-loader.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/server/future/helpers/module-loader/node-module-loader.ts"],"names":["NodeModuleLoader","load","id","process","env","NEXT_RUNTIME","NEXT_MINIMAL","__non_webpack_require__","require","Error"],"mappings":";;;;+BAKaA;;;eAAAA;;;AAAN,MAAMA;IACX,MAAaC,KAAQC,EAAU,EAAc;QAC3C,IAAIC,QAAQC,GAAG,CAACC,YAAY,KAAK,QAAQ;YACvC,wFAAwF;YACxF,OAAO,MAAOF,CAAAA,QAAQC,GAAG,CAACE,YAAY,GAElCC,wBAAwBL,MACxBM,QAAQN,GAAE;QAChB;QAEA,MAAM,IAAIO,MAAM;IAClB;AACF"}

View File

@@ -0,0 +1,8 @@
import type { RouteModule } from '../../route-modules/route-module';
import type { ModuleLoader } from './module-loader';
export interface AppLoaderModule<M extends RouteModule = RouteModule> {
routeModule: M;
}
export declare class RouteModuleLoader {
static load<M extends RouteModule>(id: string, loader?: ModuleLoader): Promise<M>;
}

View File

@@ -0,0 +1,22 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "RouteModuleLoader", {
enumerable: true,
get: function() {
return RouteModuleLoader;
}
});
const _nodemoduleloader = require("./node-module-loader");
class RouteModuleLoader {
static async load(id, loader = new _nodemoduleloader.NodeModuleLoader()) {
const module = await loader.load(id);
if ("routeModule" in module) {
return module.routeModule;
}
throw new Error(`Module "${id}" does not export a routeModule.`);
}
}
//# sourceMappingURL=route-module-loader.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/server/future/helpers/module-loader/route-module-loader.ts"],"names":["RouteModuleLoader","load","id","loader","NodeModuleLoader","module","routeModule","Error"],"mappings":";;;;+BASaA;;;eAAAA;;;kCANoB;AAM1B,MAAMA;IACX,aAAaC,KACXC,EAAU,EACVC,SAAuB,IAAIC,kCAAgB,EAAE,EACjC;QACZ,MAAMC,SAA6B,MAAMF,OAAOF,IAAI,CAACC;QACrD,IAAI,iBAAiBG,QAAQ;YAC3B,OAAOA,OAAOC,WAAW;QAC3B;QAEA,MAAM,IAAIC,MAAM,CAAC,QAAQ,EAAEL,GAAG,gCAAgC,CAAC;IACjE;AACF"}