clean routes
This commit is contained in:
97
apps/website/lib/auth/PathnameInterpreter.ts
Normal file
97
apps/website/lib/auth/PathnameInterpreter.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* PathnameInterpreter
|
||||
*
|
||||
* Server-only utility for interpreting URL pathnames and extracting locale information.
|
||||
* Strips locale prefix if present and returns the logical pathname.
|
||||
*
|
||||
* Examples:
|
||||
* - '/de/dashboard' → { locale: 'de', logicalPathname: '/dashboard' }
|
||||
* - '/dashboard' → { locale: null, logicalPathname: '/dashboard' }
|
||||
* - '/' → { locale: null, logicalPathname: '/' }
|
||||
* - '/999/dashboard' → { locale: null, logicalPathname: '/999/dashboard' }
|
||||
*/
|
||||
|
||||
export interface PathnameInterpretation {
|
||||
locale: string | null;
|
||||
logicalPathname: string;
|
||||
}
|
||||
|
||||
export class PathnameInterpreter {
|
||||
/**
|
||||
* Interprets a pathname and extracts locale information
|
||||
*
|
||||
* @param pathname - The URL pathname to interpret
|
||||
* @returns Object with locale (if valid 2-letter code) and logical pathname
|
||||
*/
|
||||
interpret(pathname: string): PathnameInterpretation {
|
||||
// Handle empty path
|
||||
if (pathname === '') {
|
||||
return {
|
||||
locale: null,
|
||||
logicalPathname: '',
|
||||
};
|
||||
}
|
||||
|
||||
// Handle root path
|
||||
if (pathname === '/') {
|
||||
return {
|
||||
locale: null,
|
||||
logicalPathname: '/',
|
||||
};
|
||||
}
|
||||
|
||||
// Normalize pathname (remove trailing slash for consistent processing)
|
||||
const normalizedPathname = pathname.endsWith('/') && pathname.length > 1
|
||||
? pathname.slice(0, -1)
|
||||
: pathname;
|
||||
|
||||
// Split into segments
|
||||
const segments = normalizedPathname.split('/').filter(Boolean);
|
||||
|
||||
// No segments to process
|
||||
if (segments.length === 0) {
|
||||
return {
|
||||
locale: null,
|
||||
logicalPathname: '/',
|
||||
};
|
||||
}
|
||||
|
||||
// Check if first segment is a valid 2-letter locale code
|
||||
const firstSegment = segments[0];
|
||||
if (this.isValidLocale(firstSegment)) {
|
||||
// Valid locale detected - strip it
|
||||
const remainingSegments = segments.slice(1);
|
||||
const logicalPathname = remainingSegments.length > 0
|
||||
? '/' + remainingSegments.join('/')
|
||||
: '/';
|
||||
|
||||
return {
|
||||
locale: firstSegment,
|
||||
logicalPathname,
|
||||
};
|
||||
}
|
||||
|
||||
// No valid locale prefix found
|
||||
return {
|
||||
locale: null,
|
||||
logicalPathname: pathname,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates if a string is a valid 2-letter locale code
|
||||
* Must be exactly 2 lowercase letters (a-z)
|
||||
*
|
||||
* @param segment - The segment to validate
|
||||
* @returns True if valid locale code
|
||||
*/
|
||||
private isValidLocale(segment: string): boolean {
|
||||
// Must be exactly 2 characters
|
||||
if (segment.length !== 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Must be lowercase letters only (a-z)
|
||||
return /^[a-z]{2}$/.test(segment);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user