Skip to content

Commit

Permalink
feat!: support multiple entries with same route (#118)
Browse files Browse the repository at this point in the history
pi0 authored Jul 9, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent a293f3b commit 8dd80ed
Showing 8 changed files with 50 additions and 37 deletions.
8 changes: 5 additions & 3 deletions src/operations/add.ts
Original file line number Diff line number Diff line change
@@ -65,11 +65,13 @@ export function addRoute<T>(
if (!node.methods) {
node.methods = Object.create(null);
}
node.methods![method] = {
if (!node.methods![method]) {
node.methods![method] = [];
}
node.methods![method].push({
data: data || (null as T),
paramsMap: hasParams ? paramsMap : undefined,
};
node.index = segments.length - 1;
});

// Static
if (!hasParams) {
28 changes: 14 additions & 14 deletions src/operations/find-all.ts
Original file line number Diff line number Diff line change
@@ -14,18 +14,18 @@ export function findAllRoutes<T>(
path = path.slice(0, -1);
}
const segments = splitPath(path);
const _matches = _findAll(ctx, ctx.root, method, segments, 0);
const matches: MatchedRoute<T>[] = [];
for (const match of _matches) {
matches.push({
data: match.data,
params:
match.paramsMap && opts?.params !== false
? getMatchParams(segments, match.paramsMap)
: undefined,
});
const matches = _findAll(ctx, ctx.root, method, segments, 0);

if (opts?.params === false) {
return matches;
}
return matches;

return matches.map((m) => {
return {
data: m.data,
params: m.paramsMap ? getMatchParams(segments, m.paramsMap) : undefined,
};
});
}

function _findAll<T>(
@@ -42,7 +42,7 @@ function _findAll<T>(
if (node.wildcard && node.wildcard.methods) {
const match = node.wildcard.methods[method] || node.wildcard.methods[""];
if (match) {
matches.push(match);
matches.push(...match);
}
}

@@ -52,7 +52,7 @@ function _findAll<T>(
if (index === segments.length && node.param.methods) {
const match = node.param.methods[method] || node.param.methods[""];
if (match) {
matches.push(match);
matches.push(...match);
}
}
}
@@ -67,7 +67,7 @@ function _findAll<T>(
if (index === segments.length && node.methods) {
const match = node.methods[method] || node.methods[""];
if (match) {
matches.push(match);
matches.push(...match);
}
}

26 changes: 15 additions & 11 deletions src/operations/find.ts
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@ export function findRoute<T = unknown>(
method: string = "",
path: string,
opts?: { params?: boolean },
): MatchedRoute<T> | undefined {
): MatchedRoute<T>[] | undefined {
if (path[path.length - 1] === "/") {
path = path.slice(0, -1);
}
@@ -26,18 +26,22 @@ export function findRoute<T = unknown>(
// Lookup tree
const segments = splitPath(path);

const match = _lookupTree<T>(ctx, ctx.root, method, segments, 0);
if (match === undefined) {
const matches = _lookupTree<T>(ctx, ctx.root, method, segments, 0);

if (matches === undefined) {
return;
}

return {
data: match.data,
params:
match.paramsMap && opts?.params !== false
? getMatchParams(segments, match.paramsMap)
: undefined,
};
if (opts?.params === false) {
return matches;
}

return matches.map((m) => {
return {
data: m.data,
params: m.paramsMap ? getMatchParams(segments, m.paramsMap) : undefined,
};
});
}

function _lookupTree<T>(
@@ -46,7 +50,7 @@ function _lookupTree<T>(
method: string,
segments: string[],
index: number,
): MethodData<T> | undefined {
): MethodData<T>[] | undefined {
// 0. End of path
if (index === segments.length) {
if (node.methods) {
3 changes: 1 addition & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -13,8 +13,7 @@ export interface Node<T = unknown> {
param?: Node<T>;
wildcard?: Node<T>;

index?: number;
methods?: Record<string, MethodData<T> | undefined>;
methods?: Record<string, MethodData<T>[] | undefined>;
}

export type MatchedRoute<T = unknown> = {
6 changes: 4 additions & 2 deletions test/_utils.ts
Original file line number Diff line number Diff line change
@@ -52,8 +52,10 @@ function _formatMethods(node: Node<{ path?: string }>) {
return "";
}
return ` β”ˆ> ${Object.entries(node.methods)
.map(([method, d]) => {
const val = d?.data?.path || JSON.stringify(d?.data);
.map(([method, arr]) => {
const val =
arr?.map((d) => d?.data?.path || JSON.stringify(d?.data)).join(" + ") ||
"";
return `[${method || "*"}] ${val}`;
})
.join(", ")}`;
5 changes: 4 additions & 1 deletion test/basic.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { describe, it, expect } from "vitest";
import { createRouter, formatTree } from "./_utils";
import { findRoute, removeRoute } from "../src";
import { findRoute as _findRoute, removeRoute } from "../src";

const findRoute = (router: any, method: string, path: string) =>
_findRoute(router, method, path)?.[0];

describe("Basic router", () => {
const router = createRouter([
3 changes: 2 additions & 1 deletion test/bench/impl.ts
Original file line number Diff line number Diff line change
@@ -33,7 +33,8 @@ export function createRouter(rou3: typeof rou3Src, withAll: boolean = false) {
};
}
return (method: string, path: string) => {
return rou3.findRoute(router, method, path);
const r = rou3.findRoute(router, method, path);
return r?.[0] || r;
};
}

8 changes: 5 additions & 3 deletions test/router.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import type { RouterContext } from "../src/types";
import { describe, it, expect } from "vitest";
import { createRouter, formatTree } from "./_utils";
import { addRoute, findRoute, removeRoute } from "../src";
import { addRoute, findRoute as _findRoute, removeRoute } from "../src";

const findRoute = (router: any, method: string, path: string) =>
_findRoute(router, method, path)?.[0];

type TestRoute = {
data: { path: string };
@@ -374,7 +377,6 @@ describe("Router insert", () => {
"hi",
"helium",
"/choo",
"//choo",
"coooool",
"chrome",
"choot",
@@ -396,7 +398,7 @@ describe("Router insert", () => {
β”œβ”€β”€ /cool β”ˆ> [GET] cool
β”œβ”€β”€ /hi β”ˆ> [GET] hi
β”œβ”€β”€ /helium β”ˆ> [GET] helium
β”œβ”€β”€ /choo β”ˆ> [GET] //choo
β”œβ”€β”€ /choo β”ˆ> [GET] /choo
β”œβ”€β”€ /coooool β”ˆ> [GET] coooool
β”œβ”€β”€ /chrome β”ˆ> [GET] chrome
β”œβ”€β”€ /choot β”ˆ> [GET] choot

0 comments on commit 8dd80ed

Please sign in to comment.