@epicabdou/linkr 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -215,6 +215,7 @@ function makeLazyRoute(loader, filePath, defaultRedirectTo) {
215
215
  const result = { Component: mod.default };
216
216
  if (mod.ErrorBoundary) result.ErrorBoundary = mod.ErrorBoundary;
217
217
  if (mod.handle !== void 0) result.handle = mod.handle;
218
+ result.HydrateFallback = () => null;
218
219
  if (mod.protect) {
219
220
  const check = typeof mod.protect === "function" ? mod.protect : mod.protect.check;
220
221
  const redirectTo = (typeof mod.protect === "object" && mod.protect.redirectTo != null ? mod.protect.redirectTo : defaultRedirectTo) ?? "/";
@@ -223,7 +224,6 @@ function makeLazyRoute(loader, filePath, defaultRedirectTo) {
223
224
  if (!ok) throw redirect(redirectTo);
224
225
  return null;
225
226
  };
226
- result.HydrateFallback = () => null;
227
227
  }
228
228
  return result;
229
229
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/createRoutes.ts","../src/pathUtils.ts","../src/Protect.tsx","../src/LinkrApp.tsx"],"sourcesContent":["import type { RouteObject } from \"react-router\";\r\nimport { redirect } from \"react-router\";\r\nimport type { CreateRoutesOptions, LayoutMap, LayoutsGlob, PagesGlob, RouteProtect } from \"./types\";\r\nimport {\r\n normalizePath,\r\n getRouteExtension,\r\n parseSegment,\r\n compareSegments,\r\n type ParsedSegment,\r\n} from \"./pathUtils\";\r\n\r\nconst DEFAULT_PAGES_DIR = \"src/pages\";\r\nconst DEFAULT_LAYOUTS_DIR = \"src/layouts\";\r\nconst DEFAULT_LAYOUT_FILE = \"_layout\";\r\nconst DEFAULT_NOT_FOUND_FILE = \"404\";\r\nconst DEFAULT_EXTENSIONS = [\".tsx\", \".ts\", \".jsx\", \".js\"];\r\n\r\n/** Build layout name -> loader from layoutsGlob. Layout name = filename without ext (one level). */\r\nfunction parseLayoutsGlob(\r\n layoutsGlob: LayoutsGlob,\r\n layoutsDir: string,\r\n extensions: string[]\r\n): Map<string, () => Promise<unknown>> {\r\n const map = new Map<string, () => Promise<unknown>>();\r\n const dir = normalizePath(layoutsDir).replace(/\\/$/, \"\");\r\n for (const key of Object.keys(layoutsGlob)) {\r\n const normalized = normalizePath(key).replace(/^\\.\\//, \"\");\r\n let relative = normalized;\r\n if (relative.startsWith(dir + \"/\")) relative = relative.slice(dir.length + 1);\r\n else if (relative.startsWith(dir)) relative = relative.slice(dir.length).replace(/^\\//, \"\");\r\n const ext = getRouteExtension(relative, extensions);\r\n if (!ext) continue;\r\n const withoutExt = relative.slice(0, -ext.length);\r\n const parts = withoutExt.split(\"/\").filter(Boolean);\r\n if (parts.length === 0) continue;\r\n const name = parts[parts.length - 1];\r\n map.set(name, layoutsGlob[key]);\r\n }\r\n return map;\r\n}\r\n\r\ntype LazyModule = {\r\n default?: React.ComponentType;\r\n ErrorBoundary?: React.ComponentType;\r\n handle?: unknown;\r\n protect?: RouteProtect;\r\n};\r\n\r\n/**\r\n * Strip extension from filename.\r\n */\r\nfunction stripExtension(filename: string, extensions: string[]): string {\r\n const lower = filename.toLowerCase();\r\n for (const ext of extensions) {\r\n if (lower.endsWith(ext)) return filename.slice(0, -ext.length);\r\n }\r\n return filename;\r\n}\r\n\r\n/**\r\n * Check if segment is a valid splat (exactly \"[...name]\").\r\n */\r\nfunction isValidSplatSegment(segment: string): boolean {\r\n return /^\\[\\.\\.\\.[^\\]]*\\]$/.test(segment);\r\n}\r\n\r\n/**\r\n * Warn in dev when a module has no default export (called from lazy).\r\n */\r\nfunction warnNoDefault(path: string): void {\r\n if (typeof process !== \"undefined\" && process.env?.NODE_ENV !== \"production\") {\r\n console.warn(`[linkr] Module has no default export, skipping route: ${path}`);\r\n }\r\n}\r\n\r\n/**\r\n * Warn when [...slug] is used with other segments in the same filename.\r\n */\r\nfunction warnInvalidSplat(path: string): void {\r\n if (typeof process !== \"undefined\" && process.env?.NODE_ENV !== \"production\") {\r\n console.warn(\r\n `[linkr] Invalid splat usage (e.g. foo[...slug].tsx); use only [...slug].tsx in filename. Skipping: ${path}`\r\n );\r\n }\r\n}\r\n\r\ninterface FileEntry {\r\n path: string;\r\n segments: string[];\r\n isLayout: boolean;\r\n is404: boolean;\r\n isIndex: boolean;\r\n segmentKinds: ReturnType<typeof parseSegment>[];\r\n}\r\n\r\nfunction parseGlobKey(\r\n key: string,\r\n opts: Required<Pick<CreateRoutesOptions, \"pagesDir\" | \"layoutFileName\" | \"notFoundFileName\" | \"routeExtensions\">>\r\n): FileEntry | null {\r\n const normalized = normalizePath(key);\r\n const withoutLeadingSlash = normalized.replace(/^\\.\\//, \"\");\r\n const dir = normalizePath(opts.pagesDir).replace(/\\/$/, \"\");\r\n let relative = withoutLeadingSlash;\r\n if (relative.startsWith(dir + \"/\")) {\r\n relative = relative.slice(dir.length + 1);\r\n } else if (relative.startsWith(dir)) {\r\n relative = relative.slice(dir.length).replace(/^\\//, \"\");\r\n } else if (dir.includes(\"/\")) {\r\n const lastDirSegment = dir.split(\"/\").pop()!;\r\n if (relative.startsWith(lastDirSegment + \"/\")) {\r\n relative = relative.slice(lastDirSegment.length + 1);\r\n }\r\n }\r\n\r\n const ext = getRouteExtension(relative, opts.routeExtensions);\r\n if (!ext) return null;\r\n\r\n const withoutExt = relative.slice(0, -ext.length);\r\n const parts = withoutExt.split(\"/\").filter(Boolean);\r\n if (parts.length === 0) return null;\r\n\r\n const lastPart = parts[parts.length - 1];\r\n const isLayout = stripExtension(lastPart, opts.routeExtensions) === opts.layoutFileName;\r\n const is404 = stripExtension(lastPart, opts.routeExtensions) === opts.notFoundFileName;\r\n const isIndex = lastPart.toLowerCase().replace(new RegExp(\"\\\\\" + ext + \"$\", \"i\"), \"\") === \"index\";\r\n const segmentParts = isIndex ? parts.slice(0, -1) : parts;\r\n const segmentStrings = segmentParts.map((p, i) => {\r\n const isLast = i === segmentParts.length - 1;\r\n return isLast ? stripExtension(p, opts.routeExtensions) : p;\r\n });\r\n\r\n const segmentKinds = segmentStrings.map(parseSegment);\r\n for (const s of segmentStrings) {\r\n if (s.includes(\"[...\") && !isValidSplatSegment(s)) {\r\n warnInvalidSplat(key);\r\n return null;\r\n }\r\n }\r\n\r\n return {\r\n path: key,\r\n segments: segmentStrings,\r\n isLayout,\r\n is404,\r\n isIndex,\r\n segmentKinds,\r\n };\r\n}\r\n\r\ninterface RouteNode {\r\n path: string;\r\n layout: FileEntry | null;\r\n indexRoute: FileEntry | null;\r\n children: Map<string, { entry: FileEntry }>;\r\n childLayouts: Map<string, RouteNode>;\r\n}\r\n\r\nfunction buildTree(entries: FileEntry[]): RouteNode {\r\n const root: RouteNode = {\r\n path: \"\",\r\n layout: null,\r\n indexRoute: null,\r\n children: new Map(),\r\n childLayouts: new Map(),\r\n };\r\n\r\n for (const entry of entries) {\r\n if (entry.is404) continue;\r\n if (entry.isLayout) {\r\n const layoutSegments = entry.segments.slice(0, -1);\r\n let node = root;\r\n for (let i = 0; i < layoutSegments.length; i++) {\r\n const key = layoutSegments.slice(0, i + 1).join(\"/\");\r\n if (!node.childLayouts.has(key)) {\r\n node.childLayouts.set(key, {\r\n path: key,\r\n layout: null,\r\n indexRoute: null,\r\n children: new Map(),\r\n childLayouts: new Map(),\r\n });\r\n }\r\n node = node.childLayouts.get(key)!;\r\n }\r\n node.layout = entry;\r\n continue;\r\n }\r\n\r\n if (entry.isIndex && entry.segments.length === 0) {\r\n root.indexRoute = entry;\r\n continue;\r\n }\r\n\r\n if (entry.isIndex) {\r\n let node = root;\r\n const segs = entry.segments;\r\n for (let i = 0; i < segs.length; i++) {\r\n const key = segs.slice(0, i + 1).join(\"/\");\r\n if (node.childLayouts.has(key)) {\r\n node = node.childLayouts.get(key)!;\r\n } else {\r\n const next: RouteNode = {\r\n path: key,\r\n layout: null,\r\n indexRoute: null,\r\n children: new Map(),\r\n childLayouts: new Map(),\r\n };\r\n node.childLayouts.set(key, next);\r\n node = next;\r\n }\r\n }\r\n node.indexRoute = entry;\r\n continue;\r\n }\r\n\r\n const segs = entry.segments;\r\n let node = root;\r\n for (let i = 0; i < segs.length - 1; i++) {\r\n const key = segs.slice(0, i + 1).join(\"/\");\r\n if (node.childLayouts.has(key)) {\r\n node = node.childLayouts.get(key)!;\r\n } else {\r\n const next: RouteNode = {\r\n path: key,\r\n layout: null,\r\n indexRoute: null,\r\n children: new Map(),\r\n childLayouts: new Map(),\r\n };\r\n node.childLayouts.set(key, next);\r\n node = next;\r\n }\r\n }\r\n const lastSeg = segs[segs.length - 1];\r\n node.children.set(lastSeg, { entry });\r\n }\r\n\r\n return root;\r\n}\r\n\r\nfunction segmentToPath(segment: ParsedSegment): string {\r\n if (segment.kind === \"static\") return segment.raw;\r\n if (segment.kind === \"dynamic\") return \":\" + (segment.paramName ?? \"param\");\r\n if (segment.kind === \"splat\") return \"*\";\r\n return segment.raw;\r\n}\r\n\r\nfunction makeLazyRoute(\r\n loader: () => Promise<unknown>,\r\n filePath: string,\r\n defaultRedirectTo?: string\r\n): RouteObject[\"lazy\"] {\r\n return async () => {\r\n const mod = (await loader()) as LazyModule;\r\n if (!mod.default) {\r\n warnNoDefault(filePath);\r\n return { Component: () => null };\r\n }\r\n const result: Record<string, unknown> = { Component: mod.default };\r\n if (mod.ErrorBoundary) result.ErrorBoundary = mod.ErrorBoundary;\r\n if (mod.handle !== undefined) result.handle = mod.handle;\r\n\r\n if (mod.protect) {\r\n const check = typeof mod.protect === \"function\" ? mod.protect : mod.protect.check;\r\n const redirectTo =\r\n (typeof mod.protect === \"object\" && mod.protect.redirectTo != null\r\n ? mod.protect.redirectTo\r\n : defaultRedirectTo) ?? \"/\";\r\n result.loader = async () => {\r\n const ok = await Promise.resolve(check());\r\n if (!ok) throw redirect(redirectTo);\r\n return null;\r\n };\r\n // React Router v7 requires HydrateFallback when a route has a loader and no hydration data.\r\n result.HydrateFallback = () => null;\r\n }\r\n\r\n return result as {\r\n Component: React.ComponentType;\r\n ErrorBoundary?: React.ComponentType;\r\n handle?: unknown;\r\n loader?: RouteObject[\"loader\"];\r\n HydrateFallback?: React.ComponentType;\r\n };\r\n };\r\n}\r\n\r\nfunction nodeToRoutes(\r\n node: RouteNode,\r\n pathPrefix: string,\r\n pagesGlob: PagesGlob,\r\n defaultRedirectTo?: string,\r\n layoutMap?: LayoutMap,\r\n layoutLoaders?: Map<string, () => Promise<unknown>>\r\n): RouteObject[] {\r\n const childRouteObjects: RouteObject[] = [];\r\n\r\n if (node.indexRoute) {\r\n const loader = pagesGlob[node.indexRoute.path];\r\n if (loader) {\r\n childRouteObjects.push({\r\n index: true,\r\n lazy: makeLazyRoute(loader, node.indexRoute.path, defaultRedirectTo),\r\n });\r\n }\r\n }\r\n\r\n const childSegments = Array.from(node.children.entries());\r\n childSegments.sort(([a], [b]) => compareSegments(parseSegment(a), parseSegment(b)));\r\n\r\n for (const [segStr, { entry }] of childSegments) {\r\n const seg = parseSegment(segStr);\r\n const pathSeg = segmentToPath(seg);\r\n const loader = pagesGlob[entry.path];\r\n if (!loader) continue;\r\n childRouteObjects.push({\r\n path: pathSeg,\r\n lazy: makeLazyRoute(loader, entry.path, defaultRedirectTo),\r\n });\r\n }\r\n\r\n const sortedLayoutKeys = Array.from(node.childLayouts.keys()).sort((a, b) => {\r\n const segsA = a.split(\"/\").map(parseSegment);\r\n const segsB = b.split(\"/\").map(parseSegment);\r\n const len = Math.min(segsA.length, segsB.length);\r\n for (let i = 0; i < len; i++) {\r\n const c = compareSegments(segsA[i], segsB[i]);\r\n if (c !== 0) return c;\r\n }\r\n return segsA.length - segsB.length;\r\n });\r\n\r\n for (const key of sortedLayoutKeys) {\r\n const childNode = node.childLayouts.get(key)!;\r\n const firstSeg = key.split(\"/\")[0];\r\n const seg = parseSegment(firstSeg);\r\n const pathSeg = segmentToPath(seg);\r\n const nested = nodeToRoutes(\r\n childNode,\r\n pathPrefix ? pathPrefix + \"/\" + pathSeg : pathSeg,\r\n pagesGlob,\r\n defaultRedirectTo,\r\n layoutMap,\r\n layoutLoaders\r\n );\r\n const layoutName = layoutMap && layoutLoaders ? layoutMap[key] ?? layoutMap[\"/\" + key] : undefined;\r\n const layoutLoader = layoutName ? layoutLoaders!.get(layoutName) : undefined;\r\n if (layoutLoader) {\r\n childRouteObjects.push({\r\n path: pathSeg,\r\n lazy: makeLazyRoute(layoutLoader, \"layout:\" + layoutName, defaultRedirectTo),\r\n children: nested,\r\n });\r\n } else if (childNode.layout && childNode.layout.path in pagesGlob) {\r\n childRouteObjects.push(...nested);\r\n } else if (childNode.layout) {\r\n childRouteObjects.push({ path: pathSeg, children: nested });\r\n } else if (nested.length > 0) {\r\n childRouteObjects.push({ path: pathSeg, children: nested });\r\n }\r\n }\r\n\r\n if (node.layout && node.layout.path in pagesGlob) {\r\n const layoutLoader = pagesGlob[node.layout.path];\r\n return [{\r\n path: pathPrefix === \"\" ? \"/\" : pathPrefix,\r\n lazy: makeLazyRoute(layoutLoader, node.layout.path, defaultRedirectTo),\r\n children: childRouteObjects.length ? childRouteObjects : undefined,\r\n }];\r\n }\r\n\r\n return childRouteObjects;\r\n}\r\n\r\nfunction flattenRootChildren(\r\n root: RouteNode,\r\n pagesGlob: PagesGlob,\r\n defaultRedirectTo?: string,\r\n layoutMap?: LayoutMap,\r\n layoutLoaders?: Map<string, () => Promise<unknown>>\r\n): RouteObject[] {\r\n const result: RouteObject[] = [];\r\n\r\n if (root.indexRoute) {\r\n const loader = pagesGlob[root.indexRoute.path];\r\n if (loader) {\r\n result.push({\r\n index: true,\r\n lazy: makeLazyRoute(loader, root.indexRoute.path, defaultRedirectTo),\r\n });\r\n }\r\n }\r\n\r\n const childSegments = Array.from(root.children.entries());\r\n childSegments.sort(([a], [b]) => compareSegments(parseSegment(a), parseSegment(b)));\r\n\r\n for (const [segStr, { entry }] of childSegments) {\r\n const seg = parseSegment(segStr);\r\n const pathSeg = segmentToPath(seg);\r\n const loader = pagesGlob[entry.path];\r\n if (!loader) continue;\r\n result.push({\r\n path: pathSeg,\r\n lazy: makeLazyRoute(loader, entry.path, defaultRedirectTo),\r\n });\r\n }\r\n\r\n const layoutKeys = Array.from(root.childLayouts.keys()).sort((a, b) => {\r\n const segsA = a.split(\"/\").map(parseSegment);\r\n const segsB = b.split(\"/\").map(parseSegment);\r\n const len = Math.min(segsA.length, segsB.length);\r\n for (let i = 0; i < len; i++) {\r\n const c = compareSegments(segsA[i], segsB[i]);\r\n if (c !== 0) return c;\r\n }\r\n return segsA.length - segsB.length;\r\n });\r\n\r\n for (const key of layoutKeys) {\r\n const childNode = root.childLayouts.get(key)!;\r\n const firstSeg = key.split(\"/\")[0];\r\n const seg = parseSegment(firstSeg);\r\n const pathSeg = segmentToPath(seg);\r\n const nested = nodeToRoutes(\r\n childNode,\r\n pathSeg,\r\n pagesGlob,\r\n defaultRedirectTo,\r\n layoutMap,\r\n layoutLoaders\r\n );\r\n const layoutName = layoutMap && layoutLoaders ? layoutMap[key] ?? layoutMap[\"/\" + key] : undefined;\r\n const layoutLoader = layoutName ? layoutLoaders!.get(layoutName) : undefined;\r\n if (layoutLoader) {\r\n result.push({\r\n path: pathSeg,\r\n lazy: makeLazyRoute(layoutLoader, \"layout:\" + layoutName, defaultRedirectTo),\r\n children: nested,\r\n });\r\n } else if (childNode.layout && childNode.layout.path in pagesGlob) {\r\n result.push(...nested);\r\n } else if (childNode.layout) {\r\n result.push({ path: pathSeg, children: nested });\r\n } else if (nested.length > 0) {\r\n result.push({ path: pathSeg, children: nested });\r\n }\r\n }\r\n\r\n const rootLayoutName = layoutMap && layoutLoaders ? layoutMap[\"\"] ?? layoutMap[\"/\"] : undefined;\r\n const rootLayoutLoader = rootLayoutName ? layoutLoaders!.get(rootLayoutName) : undefined;\r\n if (rootLayoutLoader && result.length > 0) {\r\n return [{\r\n path: \"/\",\r\n lazy: makeLazyRoute(rootLayoutLoader, \"layout:\" + rootLayoutName, defaultRedirectTo),\r\n children: result,\r\n }];\r\n }\r\n return result;\r\n}\r\n\r\nexport function createRoutes(options: CreateRoutesOptions): RouteObject[] {\r\n const pagesDir = normalizePath(options.pagesDir ?? DEFAULT_PAGES_DIR).replace(/\\/$/, \"\");\r\n const opts = {\r\n pagesDir,\r\n layoutFileName: options.layoutFileName ?? DEFAULT_LAYOUT_FILE,\r\n notFoundFileName: options.notFoundFileName ?? DEFAULT_NOT_FOUND_FILE,\r\n routeExtensions: options.routeExtensions ?? DEFAULT_EXTENSIONS,\r\n };\r\n\r\n const entries: FileEntry[] = [];\r\n for (const key of Object.keys(options.pagesGlob)) {\r\n const entry = parseGlobKey(key, opts);\r\n if (entry) entries.push(entry);\r\n }\r\n\r\n const notFoundEntry = entries.find((e) => e.is404);\r\n const useLayoutsFolder = options.layoutsGlob != null && options.layoutMap != null;\r\n const rest = useLayoutsFolder\r\n ? entries.filter((e) => !e.is404 && !e.isLayout)\r\n : entries.filter((e) => !e.is404);\r\n const root = buildTree(rest);\r\n\r\n const layoutLoaders =\r\n options.layoutsGlob && options.layoutMap\r\n ? parseLayoutsGlob(\r\n options.layoutsGlob,\r\n options.layoutsDir ?? DEFAULT_LAYOUTS_DIR,\r\n opts.routeExtensions\r\n )\r\n : undefined;\r\n\r\n let topLevelRoutes: RouteObject[];\r\n\r\n if (layoutLoaders && options.layoutMap) {\r\n topLevelRoutes = flattenRootChildren(\r\n root,\r\n options.pagesGlob,\r\n options.defaultRedirectTo,\r\n options.layoutMap,\r\n layoutLoaders\r\n );\r\n } else if (root.layout && root.layout.path in options.pagesGlob) {\r\n const layoutLoader = options.pagesGlob[root.layout.path];\r\n topLevelRoutes = [{\r\n path: \"/\",\r\n lazy: makeLazyRoute(layoutLoader, root.layout.path, options.defaultRedirectTo),\r\n children: flattenRootChildren(root, options.pagesGlob, options.defaultRedirectTo),\r\n }];\r\n } else {\r\n topLevelRoutes = flattenRootChildren(root, options.pagesGlob, options.defaultRedirectTo);\r\n }\r\n\r\n if (notFoundEntry && notFoundEntry.path in options.pagesGlob) {\r\n const loader = options.pagesGlob[notFoundEntry.path];\r\n topLevelRoutes.push({\r\n path: \"*\",\r\n lazy: makeLazyRoute(loader, notFoundEntry.path, options.defaultRedirectTo),\r\n });\r\n }\r\n\r\n return topLevelRoutes;\r\n}\r\n","/**\r\n * Normalize path to use forward slashes (Windows-safe).\r\n */\r\nexport function normalizePath(p: string): string {\r\n return p.replace(/\\\\/g, \"/\");\r\n}\r\n\r\n/**\r\n * Get route extension from filename (e.g. \".tsx\") or null if not a route file.\r\n */\r\nexport function getRouteExtension(\r\n filename: string,\r\n extensions: string[]\r\n): string | null {\r\n const lower = filename.toLowerCase();\r\n for (const ext of extensions) {\r\n if (lower.endsWith(ext)) return ext;\r\n }\r\n return null;\r\n}\r\n\r\nexport type SegmentKind = \"static\" | \"dynamic\" | \"splat\";\r\n\r\nexport interface ParsedSegment {\r\n /** Original segment string, e.g. \"blog\", \"[id]\", \"[...slug]\" */\r\n raw: string;\r\n kind: SegmentKind;\r\n /** For dynamic: \"id\"; for splat: \"slug\"; for static: same as raw */\r\n paramName?: string;\r\n}\r\n\r\n/**\r\n * Parse a single path segment into kind and param name.\r\n */\r\nexport function parseSegment(segment: string): ParsedSegment {\r\n if (segment.startsWith(\"[...\") && segment.endsWith(\"]\")) {\r\n const param = segment.slice(4, -1);\r\n return { raw: segment, kind: \"splat\", paramName: param || \"splat\" };\r\n }\r\n if (segment.startsWith(\"[\") && segment.endsWith(\"]\")) {\r\n const param = segment.slice(1, -1);\r\n return { raw: segment, kind: \"dynamic\", paramName: param || \"param\" };\r\n }\r\n return { raw: segment, kind: \"static\" };\r\n}\r\n\r\n/**\r\n * Compare two segments for sort order: static < dynamic < splat.\r\n */\r\nexport function compareSegments(a: ParsedSegment, b: ParsedSegment): number {\r\n const order = { static: 0, dynamic: 1, splat: 2 };\r\n const diff = order[a.kind] - order[b.kind];\r\n if (diff !== 0) return diff;\r\n return a.raw.localeCompare(b.raw);\r\n}\r\n","import { useEffect, useState, type ReactNode } from \"react\";\r\nimport { useNavigate } from \"react-router\";\r\n\r\nexport interface ProtectProps {\r\n /** Sync or async function that returns true to allow access, false to redirect. */\r\n condition: () => boolean | Promise<boolean>;\r\n /** Where to redirect when condition returns false. */\r\n redirectTo: string;\r\n /** Optional content to show while an async condition is pending (e.g. a spinner). */\r\n fallback?: ReactNode;\r\n /** Content to render when condition is true. */\r\n children: ReactNode;\r\n}\r\n\r\n/**\r\n * Reusable protection config: condition, redirectTo, and optional fallback.\r\n * Define once in a config file and spread into <Protect {...config}>.\r\n */\r\nexport type ProtectConfig = Pick<ProtectProps, \"condition\" | \"redirectTo\" | \"fallback\">;\r\n\r\n/**\r\n * Protects content by checking a condition before rendering. If the condition\r\n * returns false (sync or async), redirects to redirectTo. Use this to guard\r\n * a single route's content or an entire layout's <Outlet />.\r\n */\r\nexport function Protect({ condition, redirectTo, fallback = null, children }: ProtectProps) {\r\n const navigate = useNavigate();\r\n const [allowed, setAllowed] = useState<boolean | null>(null);\r\n\r\n useEffect(() => {\r\n let cancelled = false;\r\n const result = condition();\r\n if (typeof result === \"boolean\") {\r\n if (!cancelled) setAllowed(result);\r\n if (!result) navigate(redirectTo, { replace: true });\r\n return;\r\n }\r\n result.then((ok) => {\r\n if (!cancelled) setAllowed(ok);\r\n if (!ok) navigate(redirectTo, { replace: true });\r\n });\r\n return () => {\r\n cancelled = true;\r\n };\r\n }, [condition, redirectTo, navigate]);\r\n\r\n if (allowed === null) return <>{fallback}</>;\r\n if (!allowed) return null;\r\n return <>{children}</>;\r\n}\r\n","import { StrictMode, useMemo, useRef } from \"react\";\r\nimport { createRoot } from \"react-dom/client\";\r\nimport { createBrowserRouter, RouterProvider } from \"react-router\";\r\nimport { createRoutes } from \"./createRoutes\";\r\nimport type { CreateRoutesOptions, PagesGlob } from \"./types\";\r\n\r\n/**\r\n * Options for LinkrApp and createRootWithLinkr.\r\n * Same as CreateRoutesOptions (pagesGlob required; rest optional).\r\n */\r\nexport type LinkrAppOptions = { pagesGlob: PagesGlob } & Omit<CreateRoutesOptions, \"pagesGlob\">;\r\n\r\n/**\r\n * Renders the file-based router. Options are read once on mount.\r\n * Use this when you need to wrap the app with your own providers.\r\n */\r\nexport function LinkrApp(options: LinkrAppOptions) {\r\n const optionsRef = useRef(options);\r\n optionsRef.current = options;\r\n const router = useMemo(\r\n () => createBrowserRouter(createRoutes(optionsRef.current)),\r\n []\r\n );\r\n return <RouterProvider router={router} />;\r\n}\r\n\r\n/**\r\n * One-shot setup: creates the root, builds routes from pagesGlob, and renders\r\n * with StrictMode + RouterProvider. Minimizes app entry to a single call.\r\n *\r\n * @example\r\n * ```tsx\r\n * import { createRootWithLinkr } from \"@epicabdou/linkr\";\r\n * createRootWithLinkr(document.getElementById(\"root\")!, {\r\n * pagesGlob: import.meta.glob(\"./pages/**\\/*.tsx\"),\r\n * pagesDir: \"pages\",\r\n * });\r\n * ```\r\n */\r\nexport function createRootWithLinkr(\r\n rootElement: HTMLElement,\r\n options: LinkrAppOptions\r\n): ReturnType<typeof createRoot> {\r\n const router = createBrowserRouter(createRoutes(options));\r\n const root = createRoot(rootElement);\r\n root.render(\r\n <StrictMode>\r\n <RouterProvider router={router} />\r\n </StrictMode>\r\n );\r\n return root;\r\n}\r\n"],"mappings":"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","names":["node","segs","jsx"]}
1
+ {"version":3,"sources":["../src/createRoutes.ts","../src/pathUtils.ts","../src/Protect.tsx","../src/LinkrApp.tsx"],"sourcesContent":["import type { RouteObject } from \"react-router\";\r\nimport { redirect } from \"react-router\";\r\nimport type { CreateRoutesOptions, LayoutMap, LayoutsGlob, PagesGlob, RouteProtect } from \"./types\";\r\nimport {\r\n normalizePath,\r\n getRouteExtension,\r\n parseSegment,\r\n compareSegments,\r\n type ParsedSegment,\r\n} from \"./pathUtils\";\r\n\r\nconst DEFAULT_PAGES_DIR = \"src/pages\";\r\nconst DEFAULT_LAYOUTS_DIR = \"src/layouts\";\r\nconst DEFAULT_LAYOUT_FILE = \"_layout\";\r\nconst DEFAULT_NOT_FOUND_FILE = \"404\";\r\nconst DEFAULT_EXTENSIONS = [\".tsx\", \".ts\", \".jsx\", \".js\"];\r\n\r\n/** Build layout name -> loader from layoutsGlob. Layout name = filename without ext (one level). */\r\nfunction parseLayoutsGlob(\r\n layoutsGlob: LayoutsGlob,\r\n layoutsDir: string,\r\n extensions: string[]\r\n): Map<string, () => Promise<unknown>> {\r\n const map = new Map<string, () => Promise<unknown>>();\r\n const dir = normalizePath(layoutsDir).replace(/\\/$/, \"\");\r\n for (const key of Object.keys(layoutsGlob)) {\r\n const normalized = normalizePath(key).replace(/^\\.\\//, \"\");\r\n let relative = normalized;\r\n if (relative.startsWith(dir + \"/\")) relative = relative.slice(dir.length + 1);\r\n else if (relative.startsWith(dir)) relative = relative.slice(dir.length).replace(/^\\//, \"\");\r\n const ext = getRouteExtension(relative, extensions);\r\n if (!ext) continue;\r\n const withoutExt = relative.slice(0, -ext.length);\r\n const parts = withoutExt.split(\"/\").filter(Boolean);\r\n if (parts.length === 0) continue;\r\n const name = parts[parts.length - 1];\r\n map.set(name, layoutsGlob[key]);\r\n }\r\n return map;\r\n}\r\n\r\ntype LazyModule = {\r\n default?: React.ComponentType;\r\n ErrorBoundary?: React.ComponentType;\r\n handle?: unknown;\r\n protect?: RouteProtect;\r\n};\r\n\r\n/**\r\n * Strip extension from filename.\r\n */\r\nfunction stripExtension(filename: string, extensions: string[]): string {\r\n const lower = filename.toLowerCase();\r\n for (const ext of extensions) {\r\n if (lower.endsWith(ext)) return filename.slice(0, -ext.length);\r\n }\r\n return filename;\r\n}\r\n\r\n/**\r\n * Check if segment is a valid splat (exactly \"[...name]\").\r\n */\r\nfunction isValidSplatSegment(segment: string): boolean {\r\n return /^\\[\\.\\.\\.[^\\]]*\\]$/.test(segment);\r\n}\r\n\r\n/**\r\n * Warn in dev when a module has no default export (called from lazy).\r\n */\r\nfunction warnNoDefault(path: string): void {\r\n if (typeof process !== \"undefined\" && process.env?.NODE_ENV !== \"production\") {\r\n console.warn(`[linkr] Module has no default export, skipping route: ${path}`);\r\n }\r\n}\r\n\r\n/**\r\n * Warn when [...slug] is used with other segments in the same filename.\r\n */\r\nfunction warnInvalidSplat(path: string): void {\r\n if (typeof process !== \"undefined\" && process.env?.NODE_ENV !== \"production\") {\r\n console.warn(\r\n `[linkr] Invalid splat usage (e.g. foo[...slug].tsx); use only [...slug].tsx in filename. Skipping: ${path}`\r\n );\r\n }\r\n}\r\n\r\ninterface FileEntry {\r\n path: string;\r\n segments: string[];\r\n isLayout: boolean;\r\n is404: boolean;\r\n isIndex: boolean;\r\n segmentKinds: ReturnType<typeof parseSegment>[];\r\n}\r\n\r\nfunction parseGlobKey(\r\n key: string,\r\n opts: Required<Pick<CreateRoutesOptions, \"pagesDir\" | \"layoutFileName\" | \"notFoundFileName\" | \"routeExtensions\">>\r\n): FileEntry | null {\r\n const normalized = normalizePath(key);\r\n const withoutLeadingSlash = normalized.replace(/^\\.\\//, \"\");\r\n const dir = normalizePath(opts.pagesDir).replace(/\\/$/, \"\");\r\n let relative = withoutLeadingSlash;\r\n if (relative.startsWith(dir + \"/\")) {\r\n relative = relative.slice(dir.length + 1);\r\n } else if (relative.startsWith(dir)) {\r\n relative = relative.slice(dir.length).replace(/^\\//, \"\");\r\n } else if (dir.includes(\"/\")) {\r\n const lastDirSegment = dir.split(\"/\").pop()!;\r\n if (relative.startsWith(lastDirSegment + \"/\")) {\r\n relative = relative.slice(lastDirSegment.length + 1);\r\n }\r\n }\r\n\r\n const ext = getRouteExtension(relative, opts.routeExtensions);\r\n if (!ext) return null;\r\n\r\n const withoutExt = relative.slice(0, -ext.length);\r\n const parts = withoutExt.split(\"/\").filter(Boolean);\r\n if (parts.length === 0) return null;\r\n\r\n const lastPart = parts[parts.length - 1];\r\n const isLayout = stripExtension(lastPart, opts.routeExtensions) === opts.layoutFileName;\r\n const is404 = stripExtension(lastPart, opts.routeExtensions) === opts.notFoundFileName;\r\n const isIndex = lastPart.toLowerCase().replace(new RegExp(\"\\\\\" + ext + \"$\", \"i\"), \"\") === \"index\";\r\n const segmentParts = isIndex ? parts.slice(0, -1) : parts;\r\n const segmentStrings = segmentParts.map((p, i) => {\r\n const isLast = i === segmentParts.length - 1;\r\n return isLast ? stripExtension(p, opts.routeExtensions) : p;\r\n });\r\n\r\n const segmentKinds = segmentStrings.map(parseSegment);\r\n for (const s of segmentStrings) {\r\n if (s.includes(\"[...\") && !isValidSplatSegment(s)) {\r\n warnInvalidSplat(key);\r\n return null;\r\n }\r\n }\r\n\r\n return {\r\n path: key,\r\n segments: segmentStrings,\r\n isLayout,\r\n is404,\r\n isIndex,\r\n segmentKinds,\r\n };\r\n}\r\n\r\ninterface RouteNode {\r\n path: string;\r\n layout: FileEntry | null;\r\n indexRoute: FileEntry | null;\r\n children: Map<string, { entry: FileEntry }>;\r\n childLayouts: Map<string, RouteNode>;\r\n}\r\n\r\nfunction buildTree(entries: FileEntry[]): RouteNode {\r\n const root: RouteNode = {\r\n path: \"\",\r\n layout: null,\r\n indexRoute: null,\r\n children: new Map(),\r\n childLayouts: new Map(),\r\n };\r\n\r\n for (const entry of entries) {\r\n if (entry.is404) continue;\r\n if (entry.isLayout) {\r\n const layoutSegments = entry.segments.slice(0, -1);\r\n let node = root;\r\n for (let i = 0; i < layoutSegments.length; i++) {\r\n const key = layoutSegments.slice(0, i + 1).join(\"/\");\r\n if (!node.childLayouts.has(key)) {\r\n node.childLayouts.set(key, {\r\n path: key,\r\n layout: null,\r\n indexRoute: null,\r\n children: new Map(),\r\n childLayouts: new Map(),\r\n });\r\n }\r\n node = node.childLayouts.get(key)!;\r\n }\r\n node.layout = entry;\r\n continue;\r\n }\r\n\r\n if (entry.isIndex && entry.segments.length === 0) {\r\n root.indexRoute = entry;\r\n continue;\r\n }\r\n\r\n if (entry.isIndex) {\r\n let node = root;\r\n const segs = entry.segments;\r\n for (let i = 0; i < segs.length; i++) {\r\n const key = segs.slice(0, i + 1).join(\"/\");\r\n if (node.childLayouts.has(key)) {\r\n node = node.childLayouts.get(key)!;\r\n } else {\r\n const next: RouteNode = {\r\n path: key,\r\n layout: null,\r\n indexRoute: null,\r\n children: new Map(),\r\n childLayouts: new Map(),\r\n };\r\n node.childLayouts.set(key, next);\r\n node = next;\r\n }\r\n }\r\n node.indexRoute = entry;\r\n continue;\r\n }\r\n\r\n const segs = entry.segments;\r\n let node = root;\r\n for (let i = 0; i < segs.length - 1; i++) {\r\n const key = segs.slice(0, i + 1).join(\"/\");\r\n if (node.childLayouts.has(key)) {\r\n node = node.childLayouts.get(key)!;\r\n } else {\r\n const next: RouteNode = {\r\n path: key,\r\n layout: null,\r\n indexRoute: null,\r\n children: new Map(),\r\n childLayouts: new Map(),\r\n };\r\n node.childLayouts.set(key, next);\r\n node = next;\r\n }\r\n }\r\n const lastSeg = segs[segs.length - 1];\r\n node.children.set(lastSeg, { entry });\r\n }\r\n\r\n return root;\r\n}\r\n\r\nfunction segmentToPath(segment: ParsedSegment): string {\r\n if (segment.kind === \"static\") return segment.raw;\r\n if (segment.kind === \"dynamic\") return \":\" + (segment.paramName ?? \"param\");\r\n if (segment.kind === \"splat\") return \"*\";\r\n return segment.raw;\r\n}\r\n\r\nfunction makeLazyRoute(\r\n loader: () => Promise<unknown>,\r\n filePath: string,\r\n defaultRedirectTo?: string\r\n): RouteObject[\"lazy\"] {\r\n return async () => {\r\n const mod = (await loader()) as LazyModule;\r\n if (!mod.default) {\r\n warnNoDefault(filePath);\r\n return { Component: () => null };\r\n }\r\n const result: Record<string, unknown> = { Component: mod.default };\r\n if (mod.ErrorBoundary) result.ErrorBoundary = mod.ErrorBoundary;\r\n if (mod.handle !== undefined) result.handle = mod.handle;\r\n\r\n // React Router v7 requires HydrateFallback when a route can suspend (lazy or loader) during initial hydration.\r\n result.HydrateFallback = () => null;\r\n\r\n if (mod.protect) {\r\n const check = typeof mod.protect === \"function\" ? mod.protect : mod.protect.check;\r\n const redirectTo =\r\n (typeof mod.protect === \"object\" && mod.protect.redirectTo != null\r\n ? mod.protect.redirectTo\r\n : defaultRedirectTo) ?? \"/\";\r\n result.loader = async () => {\r\n const ok = await Promise.resolve(check());\r\n if (!ok) throw redirect(redirectTo);\r\n return null;\r\n };\r\n }\r\n\r\n return result as {\r\n Component: React.ComponentType;\r\n ErrorBoundary?: React.ComponentType;\r\n handle?: unknown;\r\n loader?: RouteObject[\"loader\"];\r\n HydrateFallback?: React.ComponentType;\r\n };\r\n };\r\n}\r\n\r\nfunction nodeToRoutes(\r\n node: RouteNode,\r\n pathPrefix: string,\r\n pagesGlob: PagesGlob,\r\n defaultRedirectTo?: string,\r\n layoutMap?: LayoutMap,\r\n layoutLoaders?: Map<string, () => Promise<unknown>>\r\n): RouteObject[] {\r\n const childRouteObjects: RouteObject[] = [];\r\n\r\n if (node.indexRoute) {\r\n const loader = pagesGlob[node.indexRoute.path];\r\n if (loader) {\r\n childRouteObjects.push({\r\n index: true,\r\n lazy: makeLazyRoute(loader, node.indexRoute.path, defaultRedirectTo),\r\n });\r\n }\r\n }\r\n\r\n const childSegments = Array.from(node.children.entries());\r\n childSegments.sort(([a], [b]) => compareSegments(parseSegment(a), parseSegment(b)));\r\n\r\n for (const [segStr, { entry }] of childSegments) {\r\n const seg = parseSegment(segStr);\r\n const pathSeg = segmentToPath(seg);\r\n const loader = pagesGlob[entry.path];\r\n if (!loader) continue;\r\n childRouteObjects.push({\r\n path: pathSeg,\r\n lazy: makeLazyRoute(loader, entry.path, defaultRedirectTo),\r\n });\r\n }\r\n\r\n const sortedLayoutKeys = Array.from(node.childLayouts.keys()).sort((a, b) => {\r\n const segsA = a.split(\"/\").map(parseSegment);\r\n const segsB = b.split(\"/\").map(parseSegment);\r\n const len = Math.min(segsA.length, segsB.length);\r\n for (let i = 0; i < len; i++) {\r\n const c = compareSegments(segsA[i], segsB[i]);\r\n if (c !== 0) return c;\r\n }\r\n return segsA.length - segsB.length;\r\n });\r\n\r\n for (const key of sortedLayoutKeys) {\r\n const childNode = node.childLayouts.get(key)!;\r\n const firstSeg = key.split(\"/\")[0];\r\n const seg = parseSegment(firstSeg);\r\n const pathSeg = segmentToPath(seg);\r\n const nested = nodeToRoutes(\r\n childNode,\r\n pathPrefix ? pathPrefix + \"/\" + pathSeg : pathSeg,\r\n pagesGlob,\r\n defaultRedirectTo,\r\n layoutMap,\r\n layoutLoaders\r\n );\r\n const layoutName = layoutMap && layoutLoaders ? layoutMap[key] ?? layoutMap[\"/\" + key] : undefined;\r\n const layoutLoader = layoutName ? layoutLoaders!.get(layoutName) : undefined;\r\n if (layoutLoader) {\r\n childRouteObjects.push({\r\n path: pathSeg,\r\n lazy: makeLazyRoute(layoutLoader, \"layout:\" + layoutName, defaultRedirectTo),\r\n children: nested,\r\n });\r\n } else if (childNode.layout && childNode.layout.path in pagesGlob) {\r\n childRouteObjects.push(...nested);\r\n } else if (childNode.layout) {\r\n childRouteObjects.push({ path: pathSeg, children: nested });\r\n } else if (nested.length > 0) {\r\n childRouteObjects.push({ path: pathSeg, children: nested });\r\n }\r\n }\r\n\r\n if (node.layout && node.layout.path in pagesGlob) {\r\n const layoutLoader = pagesGlob[node.layout.path];\r\n return [{\r\n path: pathPrefix === \"\" ? \"/\" : pathPrefix,\r\n lazy: makeLazyRoute(layoutLoader, node.layout.path, defaultRedirectTo),\r\n children: childRouteObjects.length ? childRouteObjects : undefined,\r\n }];\r\n }\r\n\r\n return childRouteObjects;\r\n}\r\n\r\nfunction flattenRootChildren(\r\n root: RouteNode,\r\n pagesGlob: PagesGlob,\r\n defaultRedirectTo?: string,\r\n layoutMap?: LayoutMap,\r\n layoutLoaders?: Map<string, () => Promise<unknown>>\r\n): RouteObject[] {\r\n const result: RouteObject[] = [];\r\n\r\n if (root.indexRoute) {\r\n const loader = pagesGlob[root.indexRoute.path];\r\n if (loader) {\r\n result.push({\r\n index: true,\r\n lazy: makeLazyRoute(loader, root.indexRoute.path, defaultRedirectTo),\r\n });\r\n }\r\n }\r\n\r\n const childSegments = Array.from(root.children.entries());\r\n childSegments.sort(([a], [b]) => compareSegments(parseSegment(a), parseSegment(b)));\r\n\r\n for (const [segStr, { entry }] of childSegments) {\r\n const seg = parseSegment(segStr);\r\n const pathSeg = segmentToPath(seg);\r\n const loader = pagesGlob[entry.path];\r\n if (!loader) continue;\r\n result.push({\r\n path: pathSeg,\r\n lazy: makeLazyRoute(loader, entry.path, defaultRedirectTo),\r\n });\r\n }\r\n\r\n const layoutKeys = Array.from(root.childLayouts.keys()).sort((a, b) => {\r\n const segsA = a.split(\"/\").map(parseSegment);\r\n const segsB = b.split(\"/\").map(parseSegment);\r\n const len = Math.min(segsA.length, segsB.length);\r\n for (let i = 0; i < len; i++) {\r\n const c = compareSegments(segsA[i], segsB[i]);\r\n if (c !== 0) return c;\r\n }\r\n return segsA.length - segsB.length;\r\n });\r\n\r\n for (const key of layoutKeys) {\r\n const childNode = root.childLayouts.get(key)!;\r\n const firstSeg = key.split(\"/\")[0];\r\n const seg = parseSegment(firstSeg);\r\n const pathSeg = segmentToPath(seg);\r\n const nested = nodeToRoutes(\r\n childNode,\r\n pathSeg,\r\n pagesGlob,\r\n defaultRedirectTo,\r\n layoutMap,\r\n layoutLoaders\r\n );\r\n const layoutName = layoutMap && layoutLoaders ? layoutMap[key] ?? layoutMap[\"/\" + key] : undefined;\r\n const layoutLoader = layoutName ? layoutLoaders!.get(layoutName) : undefined;\r\n if (layoutLoader) {\r\n result.push({\r\n path: pathSeg,\r\n lazy: makeLazyRoute(layoutLoader, \"layout:\" + layoutName, defaultRedirectTo),\r\n children: nested,\r\n });\r\n } else if (childNode.layout && childNode.layout.path in pagesGlob) {\r\n result.push(...nested);\r\n } else if (childNode.layout) {\r\n result.push({ path: pathSeg, children: nested });\r\n } else if (nested.length > 0) {\r\n result.push({ path: pathSeg, children: nested });\r\n }\r\n }\r\n\r\n const rootLayoutName = layoutMap && layoutLoaders ? layoutMap[\"\"] ?? layoutMap[\"/\"] : undefined;\r\n const rootLayoutLoader = rootLayoutName ? layoutLoaders!.get(rootLayoutName) : undefined;\r\n if (rootLayoutLoader && result.length > 0) {\r\n return [{\r\n path: \"/\",\r\n lazy: makeLazyRoute(rootLayoutLoader, \"layout:\" + rootLayoutName, defaultRedirectTo),\r\n children: result,\r\n }];\r\n }\r\n return result;\r\n}\r\n\r\nexport function createRoutes(options: CreateRoutesOptions): RouteObject[] {\r\n const pagesDir = normalizePath(options.pagesDir ?? DEFAULT_PAGES_DIR).replace(/\\/$/, \"\");\r\n const opts = {\r\n pagesDir,\r\n layoutFileName: options.layoutFileName ?? DEFAULT_LAYOUT_FILE,\r\n notFoundFileName: options.notFoundFileName ?? DEFAULT_NOT_FOUND_FILE,\r\n routeExtensions: options.routeExtensions ?? DEFAULT_EXTENSIONS,\r\n };\r\n\r\n const entries: FileEntry[] = [];\r\n for (const key of Object.keys(options.pagesGlob)) {\r\n const entry = parseGlobKey(key, opts);\r\n if (entry) entries.push(entry);\r\n }\r\n\r\n const notFoundEntry = entries.find((e) => e.is404);\r\n const useLayoutsFolder = options.layoutsGlob != null && options.layoutMap != null;\r\n const rest = useLayoutsFolder\r\n ? entries.filter((e) => !e.is404 && !e.isLayout)\r\n : entries.filter((e) => !e.is404);\r\n const root = buildTree(rest);\r\n\r\n const layoutLoaders =\r\n options.layoutsGlob && options.layoutMap\r\n ? parseLayoutsGlob(\r\n options.layoutsGlob,\r\n options.layoutsDir ?? DEFAULT_LAYOUTS_DIR,\r\n opts.routeExtensions\r\n )\r\n : undefined;\r\n\r\n let topLevelRoutes: RouteObject[];\r\n\r\n if (layoutLoaders && options.layoutMap) {\r\n topLevelRoutes = flattenRootChildren(\r\n root,\r\n options.pagesGlob,\r\n options.defaultRedirectTo,\r\n options.layoutMap,\r\n layoutLoaders\r\n );\r\n } else if (root.layout && root.layout.path in options.pagesGlob) {\r\n const layoutLoader = options.pagesGlob[root.layout.path];\r\n topLevelRoutes = [{\r\n path: \"/\",\r\n lazy: makeLazyRoute(layoutLoader, root.layout.path, options.defaultRedirectTo),\r\n children: flattenRootChildren(root, options.pagesGlob, options.defaultRedirectTo),\r\n }];\r\n } else {\r\n topLevelRoutes = flattenRootChildren(root, options.pagesGlob, options.defaultRedirectTo);\r\n }\r\n\r\n if (notFoundEntry && notFoundEntry.path in options.pagesGlob) {\r\n const loader = options.pagesGlob[notFoundEntry.path];\r\n topLevelRoutes.push({\r\n path: \"*\",\r\n lazy: makeLazyRoute(loader, notFoundEntry.path, options.defaultRedirectTo),\r\n });\r\n }\r\n\r\n return topLevelRoutes;\r\n}\r\n","/**\r\n * Normalize path to use forward slashes (Windows-safe).\r\n */\r\nexport function normalizePath(p: string): string {\r\n return p.replace(/\\\\/g, \"/\");\r\n}\r\n\r\n/**\r\n * Get route extension from filename (e.g. \".tsx\") or null if not a route file.\r\n */\r\nexport function getRouteExtension(\r\n filename: string,\r\n extensions: string[]\r\n): string | null {\r\n const lower = filename.toLowerCase();\r\n for (const ext of extensions) {\r\n if (lower.endsWith(ext)) return ext;\r\n }\r\n return null;\r\n}\r\n\r\nexport type SegmentKind = \"static\" | \"dynamic\" | \"splat\";\r\n\r\nexport interface ParsedSegment {\r\n /** Original segment string, e.g. \"blog\", \"[id]\", \"[...slug]\" */\r\n raw: string;\r\n kind: SegmentKind;\r\n /** For dynamic: \"id\"; for splat: \"slug\"; for static: same as raw */\r\n paramName?: string;\r\n}\r\n\r\n/**\r\n * Parse a single path segment into kind and param name.\r\n */\r\nexport function parseSegment(segment: string): ParsedSegment {\r\n if (segment.startsWith(\"[...\") && segment.endsWith(\"]\")) {\r\n const param = segment.slice(4, -1);\r\n return { raw: segment, kind: \"splat\", paramName: param || \"splat\" };\r\n }\r\n if (segment.startsWith(\"[\") && segment.endsWith(\"]\")) {\r\n const param = segment.slice(1, -1);\r\n return { raw: segment, kind: \"dynamic\", paramName: param || \"param\" };\r\n }\r\n return { raw: segment, kind: \"static\" };\r\n}\r\n\r\n/**\r\n * Compare two segments for sort order: static < dynamic < splat.\r\n */\r\nexport function compareSegments(a: ParsedSegment, b: ParsedSegment): number {\r\n const order = { static: 0, dynamic: 1, splat: 2 };\r\n const diff = order[a.kind] - order[b.kind];\r\n if (diff !== 0) return diff;\r\n return a.raw.localeCompare(b.raw);\r\n}\r\n","import { useEffect, useState, type ReactNode } from \"react\";\r\nimport { useNavigate } from \"react-router\";\r\n\r\nexport interface ProtectProps {\r\n /** Sync or async function that returns true to allow access, false to redirect. */\r\n condition: () => boolean | Promise<boolean>;\r\n /** Where to redirect when condition returns false. */\r\n redirectTo: string;\r\n /** Optional content to show while an async condition is pending (e.g. a spinner). */\r\n fallback?: ReactNode;\r\n /** Content to render when condition is true. */\r\n children: ReactNode;\r\n}\r\n\r\n/**\r\n * Reusable protection config: condition, redirectTo, and optional fallback.\r\n * Define once in a config file and spread into <Protect {...config}>.\r\n */\r\nexport type ProtectConfig = Pick<ProtectProps, \"condition\" | \"redirectTo\" | \"fallback\">;\r\n\r\n/**\r\n * Protects content by checking a condition before rendering. If the condition\r\n * returns false (sync or async), redirects to redirectTo. Use this to guard\r\n * a single route's content or an entire layout's <Outlet />.\r\n */\r\nexport function Protect({ condition, redirectTo, fallback = null, children }: ProtectProps) {\r\n const navigate = useNavigate();\r\n const [allowed, setAllowed] = useState<boolean | null>(null);\r\n\r\n useEffect(() => {\r\n let cancelled = false;\r\n const result = condition();\r\n if (typeof result === \"boolean\") {\r\n if (!cancelled) setAllowed(result);\r\n if (!result) navigate(redirectTo, { replace: true });\r\n return;\r\n }\r\n result.then((ok) => {\r\n if (!cancelled) setAllowed(ok);\r\n if (!ok) navigate(redirectTo, { replace: true });\r\n });\r\n return () => {\r\n cancelled = true;\r\n };\r\n }, [condition, redirectTo, navigate]);\r\n\r\n if (allowed === null) return <>{fallback}</>;\r\n if (!allowed) return null;\r\n return <>{children}</>;\r\n}\r\n","import { StrictMode, useMemo, useRef } from \"react\";\r\nimport { createRoot } from \"react-dom/client\";\r\nimport { createBrowserRouter, RouterProvider } from \"react-router\";\r\nimport { createRoutes } from \"./createRoutes\";\r\nimport type { CreateRoutesOptions, PagesGlob } from \"./types\";\r\n\r\n/**\r\n * Options for LinkrApp and createRootWithLinkr.\r\n * Same as CreateRoutesOptions (pagesGlob required; rest optional).\r\n */\r\nexport type LinkrAppOptions = { pagesGlob: PagesGlob } & Omit<CreateRoutesOptions, \"pagesGlob\">;\r\n\r\n/**\r\n * Renders the file-based router. Options are read once on mount.\r\n * Use this when you need to wrap the app with your own providers.\r\n */\r\nexport function LinkrApp(options: LinkrAppOptions) {\r\n const optionsRef = useRef(options);\r\n optionsRef.current = options;\r\n const router = useMemo(\r\n () => createBrowserRouter(createRoutes(optionsRef.current)),\r\n []\r\n );\r\n return <RouterProvider router={router} />;\r\n}\r\n\r\n/**\r\n * One-shot setup: creates the root, builds routes from pagesGlob, and renders\r\n * with StrictMode + RouterProvider. Minimizes app entry to a single call.\r\n *\r\n * @example\r\n * ```tsx\r\n * import { createRootWithLinkr } from \"@epicabdou/linkr\";\r\n * createRootWithLinkr(document.getElementById(\"root\")!, {\r\n * pagesGlob: import.meta.glob(\"./pages/**\\/*.tsx\"),\r\n * pagesDir: \"pages\",\r\n * });\r\n * ```\r\n */\r\nexport function createRootWithLinkr(\r\n rootElement: HTMLElement,\r\n options: LinkrAppOptions\r\n): ReturnType<typeof createRoot> {\r\n const router = createBrowserRouter(createRoutes(options));\r\n const root = createRoot(rootElement);\r\n root.render(\r\n <StrictMode>\r\n <RouterProvider router={router} />\r\n </StrictMode>\r\n );\r\n return root;\r\n}\r\n"],"mappings":"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","names":["node","segs","jsx"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@epicabdou/linkr",
3
- "version": "0.0.5",
3
+ "version": "0.0.6",
4
4
  "description": "linkr.js — File-based routing for React Router (v7) with Vite",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",