import { createLocalizedRoute, createLocalizedSegmentRoute, createRoute, createSegmentRoute, } from "../routes/create.ts"; import type { LocalizedEndRoute, LocalizedSegmentRoute, } from "../routes/index.ts"; import type { EndRoute, SegmentRoute } from "../routes/interfaces.ts"; import type { LocaleType, LocalizedPathsRecord } from "../types.ts"; import { getKeys } from "../utils/getKeys.ts"; export interface SegmentRouterBuilder { add: (path: string, ref: RouteRef, key?: string) => void; addLocalized: ( localizedPaths: LocalizedPathsRecord, ref: RouteRef, key?: string, ) => void; addLocalizedSegment: ( localizedPaths: LocalizedPathsRecord, buildSegment: (builder: SegmentRouterBuilder) => void, ) => void; addSegment: ( path: string, buildSegment: (builder: SegmentRouterBuilder) => void, ) => void; defaultRoute: (ref: RouteRef, key?: string) => void; } export function createSegmentRouterBuilderCreator< Locales extends LocaleType, RouteRef, >( defaultLocale: Locales | undefined, addToRouteMap: (key: string, route: EndRoute) => void, ): ( segmentRoute: SegmentRoute, ) => SegmentRouterBuilder { const createSegmentRouterBuilder = ( segmentRoute: SegmentRoute, ): SegmentRouterBuilder => { const getCompletePath = (path: string, locale?: Locales): string => `${segmentRoute.getPath(locale).completePath}${path}`; const getCompleteLocalizedPaths = ( localizedPaths: LocalizedPathsRecord, ): LocalizedPathsRecord => { // eslint-disable-next-line @typescript-eslint/consistent-type-assertions const completeLocalizedPaths: Record = {} as Record< Locales, string >; getKeys(localizedPaths).forEach((locale: Locales) => { completeLocalizedPaths[locale] = getCompletePath( localizedPaths[locale], locale, ); }); return completeLocalizedPaths; }; const createLocalizedPathFromSegment = ( segmentRoute: LocalizedSegmentRoute, path: string, ): Record => { // eslint-disable-next-line @typescript-eslint/consistent-type-assertions const localizedPaths: Record = {} as Record< Locales, string >; [...segmentRoute.localizedPaths.keys()].forEach((locale) => { localizedPaths[locale] = path; }); return localizedPaths; }; const _createLocalizedEndRoute = ( localizedPaths: LocalizedPathsRecord, ref: RouteRef, key?: string, ): LocalizedEndRoute => { const completeLocalizedPaths = getCompleteLocalizedPaths(localizedPaths); const finalKey: string = key || completeLocalizedPaths[defaultLocale!]; const route = createLocalizedRoute( localizedPaths, completeLocalizedPaths, ref, ); addToRouteMap(finalKey, route); return route; }; const _createEndRoute = ( path: string, ref: RouteRef, key?: string, ): EndRoute => { if (segmentRoute.isLocalized()) { return _createLocalizedEndRoute( createLocalizedPathFromSegment( segmentRoute as LocalizedSegmentRoute, path, ), ref, key, ); } const completePath = getCompletePath(path); const route = createRoute(path, completePath, ref); const finalKey: string = key || completePath; addToRouteMap(finalKey, route); return route; }; const _createLocalizedSegmentRoute = ( localizedPaths: LocalizedPathsRecord, buildSegment: (builder: SegmentRouterBuilder) => void, ): LocalizedSegmentRoute => { const completeLocalizedPaths = getCompleteLocalizedPaths(localizedPaths); const route = createLocalizedSegmentRoute( localizedPaths, completeLocalizedPaths, ); buildSegment(createSegmentRouterBuilder(route)); route.freeze(); return route; }; const _createSegmentRoute = ( path: string, buildSegment: (builder: SegmentRouterBuilder) => void, ): SegmentRoute => { if (segmentRoute.isLocalized()) { return _createLocalizedSegmentRoute( createLocalizedPathFromSegment( segmentRoute as LocalizedSegmentRoute, path, ), buildSegment, ); } const completePath = getCompletePath(path); const route = createSegmentRoute(path, completePath); buildSegment(createSegmentRouterBuilder(route)); route.freeze(); return route; }; return { defaultRoute: (ref: RouteRef, key?: string): void => { segmentRoute.defaultRoute = _createEndRoute("", ref, key); }, add: (path: string, ref: RouteRef, key?: string): void => { segmentRoute.nestedRoutes.push(_createEndRoute(path, ref, key)); }, addLocalized: ( localizedPaths: LocalizedPathsRecord, ref: RouteRef, key?: string, ): void => { if (!defaultLocale) throw new Error("Invalid locales"); segmentRoute.nestedRoutes.push( _createLocalizedEndRoute(localizedPaths, ref, key), ); }, addSegment: ( path: string, buildSegment: ( builder: SegmentRouterBuilder, ) => void, ): void => { segmentRoute.nestedRoutes.push(_createSegmentRoute(path, buildSegment)); }, addLocalizedSegment: ( localizedPaths: LocalizedPathsRecord, buildSegment: ( builder: SegmentRouterBuilder, ) => void, ): void => { if (!defaultLocale) throw new Error("Invalid locales"); segmentRoute.nestedRoutes.push( _createLocalizedSegmentRoute(localizedPaths, buildSegment), ); }, }; }; return createSegmentRouterBuilder; }