Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion docs/runtime/file-system-router.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,18 @@ router.match("/settings?foo=bar");
}
```

A name that appears more than once in the query string maps to an array of its values.

```ts
router.match("/settings?foo=bar&foo=baz&page=2").query;

// =>
{
foo: ["bar", "baz"],
page: "2"
}
```

The router parses URL parameters and returns them in the `params` property:

```ts
Expand All @@ -77,6 +89,18 @@ router.match("/blog/my-cool-post");
}
```

`query` also contains the route parameters. A route parameter wins over a query string entry with the same name.

```ts
router.match("/blog/my-cool-post?slug=other&page=2").query;

// =>
{
slug: "my-cool-post",
page: "2"
}
```

The `.match()` method also accepts `Request` and `Response` objects; the router uses their `url` property to resolve the route.

```ts
Expand Down Expand Up @@ -111,7 +135,7 @@ interface Bun {
pathname: string;
src: string;
params?: Record<string, string>;
query?: Record<string, string>;
query?: Record<string, string | string[]>;
} | null
}
}
Expand Down
25 changes: 23 additions & 2 deletions packages/bun-types/bun.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8390,7 +8390,11 @@ declare module "bun" {
match(input: string | Request | Response): MatchedRoute | null;

readonly assetPrefix: string;
readonly origin: string;
/**
* The `origin` passed to the constructor. `null` when the router was
* created without one (or with `""`).
*/
readonly origin: string | null;
readonly style: string;
readonly routes: Record<string, string>;

Expand All @@ -8417,7 +8421,24 @@ declare module "bun" {
readonly params: Record<string, string>;
readonly filePath: string;
readonly pathname: string;
readonly query: Record<string, string>;
/**
* The parsed query string, merged with {@link MatchedRoute.params}. A
* route parameter wins over a query string entry of the same name. A
* name that appears more than once in the query string maps to an array
* of its values.
*
* @example
* ```ts
* // with a pages/blog/[slug].tsx route:
* const router = new FileSystemRouter({
* dir: "/path/to/pages",
* style: "nextjs",
* });
* router.match("/blog/hello?tag=a&tag=b&page=2")?.query;
* // { slug: "hello", tag: ["a", "b"], page: "2" }
* ```
*/
readonly query: Record<string, string | string[]>;
readonly name: string;
readonly kind: "exact" | "catch-all" | "optional-catch-all" | "dynamic";
readonly src: string;
Expand Down
10 changes: 9 additions & 1 deletion test/integration/bun-types/fixture/fsrouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,16 @@ const router = new FileSystemRouter({
style: "nextjs",
});

// null when the router was constructed without an origin.
expectType(router.origin).is<string | null>();

const match = router.match("/");
expectType<string>(match?.name!);
expectType<string>(match?.pathname!);
expectType<Record<string, string>>(match?.query!);
// A query string name given more than once maps to an array of its values.
expectType(match?.query!).is<Record<string, string | string[]>>();
for (const value of Object.values(match!.query)) {
if (Array.isArray(value)) expectType(value).is<string[]>();
else expectType(value).is<string>();
}
expectType<Record<string, string>>(match?.params!);