release: WRNexusJS 0.3.0

This commit is contained in:
2026-07-22 17:29:08 +05:30
parent 13dfa31d19
commit 07d8fb59d6
145 changed files with 9664 additions and 3881 deletions
+30 -8
View File
@@ -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)