diff --git a/frontends/nextjs/src/lib/routing/index.ts b/frontends/nextjs/src/lib/routing/index.ts index f0549bf25..9bdbef3a9 100644 --- a/frontends/nextjs/src/lib/routing/index.ts +++ b/frontends/nextjs/src/lib/routing/index.ts @@ -4,14 +4,44 @@ import { NextResponse } from 'next/server' * Routing utilities (stub) */ -export function parseRoute(_b_path: string): Record { - // TODO: Implement route parsing - return {} +export function parseRoute(path: string): Record { + const params: Record = {} + + // Extract query parameters from path + const [pathname = '', queryString] = path.split('?') + + if (queryString !== undefined && queryString.length > 0) { + const searchParams = new URLSearchParams(queryString) + searchParams.forEach((value, key) => { + params[key] = value + }) + } + + // Extract path segments + const segments = pathname.split('/').filter(s => s.length > 0) + segments.forEach((segment, index) => { + params[`segment${index}`] = segment + }) + + return params } -export function buildRoute(template: string, _b_params: Record): string { - // TODO: Implement route building - return template +export function buildRoute(template: string, params: Record): string { + let route = template + + // Replace named parameters in the template + Object.entries(params).forEach(([key, value]) => { + const placeholder = `{${key}}` + const colonPlaceholder = `:${key}` + + if (route.includes(placeholder)) { + route = route.replace(placeholder, value) + } else if (route.includes(colonPlaceholder)) { + route = route.replace(colonPlaceholder, value) + } + }) + + return route } export const STATUS = { diff --git a/frontends/nextjs/src/lib/routing/route-parser.ts b/frontends/nextjs/src/lib/routing/route-parser.ts index 524d2cc2f..f965cf6a2 100644 --- a/frontends/nextjs/src/lib/routing/route-parser.ts +++ b/frontends/nextjs/src/lib/routing/route-parser.ts @@ -11,9 +11,41 @@ export interface ParsedRoute { export const RESERVED_PATHS = ['api', 'admin', 'auth', '_next', 'static'] -export function parseRoute(_b_url: string): ParsedRoute { - // TODO: Implement route parsing - return { b_params: {} } +export function parseRoute(url: string): ParsedRoute { + const result: ParsedRoute = { b_params: {} } + + // Split URL into path and query + const [pathname = '', queryString] = url.split('?') + + // Parse query parameters + if (queryString !== undefined && queryString.length > 0) { + const searchParams = new URLSearchParams(queryString) + searchParams.forEach((value, key) => { + result.b_params[key] = value + }) + } + + // Parse path segments + const segments = pathname.split('/').filter(s => s.length > 0) + + // Try to extract tenant/package/path from segments + // Pattern: /{tenant}/{package}/...rest + if (segments.length >= 1) { + const firstSegment = segments[0] + if (firstSegment !== undefined && !isReservedPath(firstSegment)) { + result.tenant = firstSegment + } + } + + if (segments.length >= 2) { + result.package = segments[1] + } + + if (segments.length >= 3) { + result.path = '/' + segments.slice(2).join('/') + } + + return result } export function getPrefixedEntity(entity: string, prefix?: string): string { @@ -21,13 +53,22 @@ export function getPrefixedEntity(entity: string, prefix?: string): string { return prefix !== undefined && prefix.length > 0 ? `${prefix}_${entity}` : entity } -export function getTableName(entity: string, _tenantId?: string): string { - // TODO: Implement table name resolution - return entity.toLowerCase() +export function getTableName(entity: string, tenantId?: string): string { + // Convert entity name to lowercase and optionally prefix with tenant + const tableName = entity.toLowerCase() + + // If tenant ID is provided, prefix the table name + if (tenantId !== undefined && tenantId.length > 0) { + return `${tenantId}_${tableName}` + } + + return tableName } -export function isReservedPath(b_path: string): boolean { - // TODO: Implement reserved path checking - const segment = b_path.split('/')[1] - return RESERVED_PATHS.includes(segment ?? b_path) +export function isReservedPath(path: string): boolean { + // Get the first segment of the path + const segment = path.startsWith('/') ? path.split('/')[1] : path.split('/')[0] + + // Check if the segment matches any reserved paths + return segment !== undefined && RESERVED_PATHS.includes(segment) }