63 lines
2.1 KiB
TypeScript
63 lines
2.1 KiB
TypeScript
import { FreshContext } from "$fresh/server.ts";
|
|
import { Route, State } from "$root/defaults/interfaces.ts";
|
|
import { ComponentChildren } from "preact";
|
|
|
|
/**
|
|
* Generates a catch-all [slug] route that dynamically loads partials.
|
|
* This enables direct URL navigation to sub-pages (e.g. /admin/modules).
|
|
* @param basePath The base path of the module, should be `import.meta.dirname!`.
|
|
* @returns A route handler that loads the partial matching the slug.
|
|
*/
|
|
export default function makeSlug(basePath: string): Route {
|
|
return async function SlugRoute(
|
|
request: Request,
|
|
context: FreshContext<State>,
|
|
): Promise<ComponentChildren | Response> {
|
|
const slug = context.params.slug;
|
|
|
|
// Try partials/<slug>.tsx, then partials/(admin)/<slug>.tsx
|
|
let page: Route | undefined;
|
|
try {
|
|
page = (await import(`${basePath}/partials/${slug}.tsx`)).Page;
|
|
} catch {
|
|
try {
|
|
page = (await import(`${basePath}/partials/(admin)/${slug}.tsx`)).Page;
|
|
} catch {
|
|
// No partial found for this slug
|
|
}
|
|
}
|
|
|
|
// For multi-segment slugs (e.g. "overview/12345"), try
|
|
// partials/<dir>/[param].tsx and inject the param into context.params
|
|
if (!page && slug.includes("/")) {
|
|
const idx = slug.indexOf("/");
|
|
const dir = slug.slice(0, idx);
|
|
const param = slug.slice(idx + 1);
|
|
|
|
// Discover the dynamic segment name from the file system
|
|
try {
|
|
const entries: string[] = [];
|
|
for await (const entry of Deno.readDir(`${basePath}/partials/${dir}`)) {
|
|
if (entry.isFile) entries.push(entry.name);
|
|
}
|
|
const dynFile = entries.find((n) =>
|
|
n.startsWith("[") && n.endsWith("].tsx")
|
|
);
|
|
if (dynFile) {
|
|
const paramName = dynFile.slice(1, -5); // "[numEtud].tsx" → "numEtud"
|
|
context.params[paramName] = param;
|
|
page = (await import(`${basePath}/partials/${dir}/${dynFile}`)).Page;
|
|
}
|
|
} catch {
|
|
// directory doesn't exist or no dynamic file
|
|
}
|
|
}
|
|
|
|
if (!page) {
|
|
return context.renderNotFound();
|
|
}
|
|
|
|
return page(request, context);
|
|
};
|
|
}
|