UNPKG

@sentry/remix

Version:
148 lines (145 loc) • 4.64 kB
import * as fs from 'fs'; import * as path from 'path'; let manifestCache = null; let lastAppDirPath = null; function isRouteFile(filename) { return filename.endsWith(".tsx") || filename.endsWith(".ts") || filename.endsWith(".jsx") || filename.endsWith(".js"); } function convertRemixRouteToPath(filename) { const basename = filename.replace(/\.(tsx?|jsx?)$/, ""); if (basename === "_index") { return { path: "/", isDynamic: false }; } const normalizedBasename = basename.replace(/[/\\]/g, "."); const segments = normalizedBasename.split("."); const pathSegments = []; let isDynamic = false; let isIndexRoute = false; for (let i = 0; i < segments.length; i++) { const segment = segments[i]; if (!segment) { continue; } if (segment.startsWith("_") && segment !== "_index") { continue; } if (segment === "_index" && i === segments.length - 1) { isIndexRoute = true; continue; } const pathSegment = segment.endsWith("_") ? segment.slice(0, -1) : segment; if (pathSegment === "$") { pathSegments.push(":*"); isDynamic = true; continue; } if (pathSegment.startsWith("$")) { const paramName = pathSegment.substring(1); pathSegments.push(`:${paramName}`); isDynamic = true; } else { pathSegments.push(pathSegment); } } if (pathSegments.length === 0 && !isIndexRoute) { return null; } const path2 = pathSegments.length > 0 ? `/${pathSegments.join("/")}` : "/"; return { path: path2, isDynamic }; } function buildRegexForDynamicRoute(routePath) { const segments = routePath.split("/").filter(Boolean); const regexSegments = []; const paramNames = []; for (const segment of segments) { if (segment.startsWith(":")) { const paramName = segment.substring(1); if (paramName.endsWith("*")) { const cleanParamName = paramName.slice(0, -1); paramNames.push(cleanParamName); regexSegments.push("(.+)"); } else { paramNames.push(paramName); regexSegments.push("([^/]+)"); } } else { regexSegments.push(segment.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")); } } const pattern = `^/${regexSegments.join("/")}$`; return { regex: pattern, paramNames }; } function scanRoutesDirectory(routesDir, prefix = "") { const dynamicRoutes = []; const staticRoutes = []; try { if (!fs.existsSync(routesDir)) { return { dynamicRoutes, staticRoutes }; } const entries = fs.readdirSync(routesDir); for (const entry of entries) { const fullPath = path.join(routesDir, entry); const stat = fs.lstatSync(fullPath); if (stat.isDirectory()) { const nestedPrefix = prefix ? `${prefix}/${entry}` : entry; const nested = scanRoutesDirectory(fullPath, nestedPrefix); dynamicRoutes.push(...nested.dynamicRoutes); staticRoutes.push(...nested.staticRoutes); } else if (stat.isFile() && isRouteFile(entry)) { const routeName = prefix ? `${prefix}/${entry}` : entry; const result = convertRemixRouteToPath(routeName); if (result === null) { continue; } const { path: routePath, isDynamic } = result; if (isDynamic) { const { regex, paramNames } = buildRegexForDynamicRoute(routePath); dynamicRoutes.push({ path: routePath, regex, paramNames }); } else { staticRoutes.push({ path: routePath }); } } } } catch (error) { console.warn("Error building Remix route manifest:", error); } return { dynamicRoutes, staticRoutes }; } function createRemixRouteManifest(options) { const rootDir = options?.rootDir || process.cwd(); let appDirPath; if (options?.appDirPath) { appDirPath = options.appDirPath; } else { const maybeAppDirPath = path.join(rootDir, "app"); if (fs.existsSync(maybeAppDirPath) && fs.lstatSync(maybeAppDirPath).isDirectory()) { appDirPath = maybeAppDirPath; } } if (!appDirPath) { return { dynamicRoutes: [], staticRoutes: [] }; } if (manifestCache && lastAppDirPath === appDirPath) { return manifestCache; } const routesDir = path.join(appDirPath, "routes"); const { dynamicRoutes, staticRoutes } = scanRoutesDirectory(routesDir); const manifest = { dynamicRoutes, staticRoutes }; manifestCache = manifest; lastAppDirPath = appDirPath; return manifest; } export { convertRemixRouteToPath, createRemixRouteManifest }; //# sourceMappingURL=createRemixRouteManifest.js.map