release: WRNexusJS 0.3.0
This commit is contained in:
@@ -23,12 +23,19 @@ import {
|
||||
compileRoutePattern,
|
||||
matchRoute,
|
||||
sortRoutes,
|
||||
findRouteConflicts,
|
||||
type Route,
|
||||
type RouteMatch,
|
||||
} from "./match.ts";
|
||||
|
||||
export type { Route, RouteMatch } from "./match.ts";
|
||||
export { compileRoutePattern, matchRoute, sortRoutes } from "./match.ts";
|
||||
export {
|
||||
compileRoutePattern,
|
||||
getRouteParams,
|
||||
matchRoute,
|
||||
sortRoutes,
|
||||
findRouteConflicts,
|
||||
} from "./match.ts";
|
||||
export { generateRoutesFile } from "./routes-gen.ts";
|
||||
|
||||
export interface ComponentRef {
|
||||
@@ -69,10 +76,13 @@ export interface RouterOptions {
|
||||
* - drops a trailing `index` segment
|
||||
* - prefixes with `prefix` (e.g. "/api")
|
||||
*/
|
||||
function fileToRoute(rel: string, prefix: string): string {
|
||||
export function fileToRoute(rel: string, prefix = ""): string {
|
||||
const withoutExt = rel.replace(/\.(tsx|ts|wrn)$/, "");
|
||||
const segments = withoutExt.split("/").filter(Boolean);
|
||||
if (segments[segments.length - 1] === "index") segments.pop();
|
||||
const segments = withoutExt
|
||||
.split("/")
|
||||
.filter(Boolean)
|
||||
.filter((segment) => !(segment.startsWith("(") && segment.endsWith(")")));
|
||||
if (["index", "page"].includes(segments[segments.length - 1] ?? "")) segments.pop();
|
||||
const tail = segments.join("/");
|
||||
const route = prefix + (tail ? "/" + tail : "");
|
||||
return route === "" ? "/" : route;
|
||||
@@ -81,8 +91,8 @@ function fileToRoute(rel: string, prefix: string): string {
|
||||
function buildRoutes(files: ScannedFile[], prefix: string): Route[] {
|
||||
const routes = files.map((f): Route => {
|
||||
const raw = fileToRoute(f.rel, prefix);
|
||||
const { regex, paramNames } = compileRoutePattern(raw);
|
||||
return { raw, file: f.file, regex, paramNames };
|
||||
const { regex, paramNames, paramMeta } = compileRoutePattern(raw);
|
||||
return { raw, file: f.file, regex, paramNames, paramMeta };
|
||||
});
|
||||
return sortRoutes(routes);
|
||||
}
|
||||
@@ -93,8 +103,8 @@ function normalizeEmbeddedApiPath(path: string): string {
|
||||
}
|
||||
|
||||
function routeFromRaw(raw: string, file: string): Route {
|
||||
const { regex, paramNames } = compileRoutePattern(raw);
|
||||
return { raw, file, regex, paramNames };
|
||||
const { regex, paramNames, paramMeta } = compileRoutePattern(raw);
|
||||
return { raw, file, regex, paramNames, paramMeta };
|
||||
}
|
||||
|
||||
function embeddedWireRoutes(pageFiles: ScannedFile[]): Pick<Router, "api" | "realtime"> {
|
||||
@@ -121,6 +131,14 @@ function embeddedWireRoutes(pageFiles: ScannedFile[]): Pick<Router, "api" | "rea
|
||||
return { api, realtime };
|
||||
}
|
||||
|
||||
function warnRouteConflicts(kind: string, routes: Route[]): void {
|
||||
for (const conflict of findRouteConflicts(routes)) {
|
||||
console.warn(
|
||||
`[wrnexus] WRN-ROUTE-CONFLICT: duplicate ${kind} route '${conflict.raw}' in ${conflict.files.join(", ")}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/** Scan an app directory and build all route tables. */
|
||||
export function buildRouter(appDir: string, opts: RouterOptions = {}): Router {
|
||||
const pageFiles = scanDir(join(appDir, "pages"));
|
||||
@@ -132,6 +150,10 @@ export function buildRouter(appDir: string, opts: RouterOptions = {}): Router {
|
||||
...embedded.realtime,
|
||||
]);
|
||||
|
||||
warnRouteConflicts("page", pages);
|
||||
warnRouteConflicts("API", api);
|
||||
warnRouteConflicts("realtime", realtime);
|
||||
|
||||
// Middleware runs in deterministic (alphabetical) order.
|
||||
const middlewareFiles = scanDir(join(appDir, "middleware"))
|
||||
.map((f) => f.file)
|
||||
|
||||
Reference in New Issue
Block a user