next-generate-path 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +101 -15
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,25 +2,36 @@
|
|
|
2
2
|
|
|
3
3
|
Type-safe `generatePath()` for Next.js. Autocomplete for every route, params enforced at compile time.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## The problem
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Next.js [typed routes](https://nextjs.org/docs/app/api-reference/config/next-config-js/typedRoutes) give you type safety on `<Link href>`, `redirect()`, etc. — but dynamic routes like `/blog/[slug]` don't appear in autocomplete. You have to know the pattern and manually write template literals. There's no way to discover what routes exist or what params they need.
|
|
8
|
+
|
|
9
|
+
## The solution
|
|
10
|
+
|
|
11
|
+
`next-generate-path` gives you a single `generatePath` function with full autocomplete for **all** your routes and compile-time enforcement of the correct params.
|
|
8
12
|
|
|
9
13
|
```tsx
|
|
10
14
|
import { generatePath } from "next-generate-path";
|
|
11
15
|
|
|
12
16
|
generatePath("/blog/[slug]", { slug: "hello-world" });
|
|
13
|
-
//
|
|
17
|
+
// ^ autocomplete shows all routes ^ params are required and type-checked
|
|
14
18
|
|
|
15
19
|
generatePath("/about");
|
|
16
|
-
// => "/about" — no params
|
|
20
|
+
// => "/about" — static routes need no params
|
|
17
21
|
|
|
18
22
|
generatePath("/blog/[slug]");
|
|
19
|
-
// TS error:
|
|
23
|
+
// TS error: expected 2 arguments, got 1
|
|
20
24
|
```
|
|
21
25
|
|
|
22
26
|
The return type is compatible with Next.js's `RouteImpl`, so it works directly with `<Link>`, `redirect()`, and `router.push()` — no casts needed.
|
|
23
27
|
|
|
28
|
+
```tsx
|
|
29
|
+
// All of these are fully type-safe
|
|
30
|
+
<Link href={generatePath("/blog/[slug]", { slug: "hello" })}>Read post</Link>
|
|
31
|
+
redirect(generatePath("/products/[id]", { id: "42" }));
|
|
32
|
+
router.push(generatePath("/about"));
|
|
33
|
+
```
|
|
34
|
+
|
|
24
35
|
## Setup
|
|
25
36
|
|
|
26
37
|
### 1. Install
|
|
@@ -40,7 +51,7 @@ const nextConfig = {};
|
|
|
40
51
|
export default withTypedRoutes(nextConfig);
|
|
41
52
|
```
|
|
42
53
|
|
|
43
|
-
That's it. `withTypedRoutes` enables `typedRoutes` and generates a declaration file that wires your app's routes into `generatePath` automatically.
|
|
54
|
+
That's it. `withTypedRoutes` enables Next.js's `typedRoutes` option and generates a declaration file that wires your app's routes into `generatePath` automatically.
|
|
44
55
|
|
|
45
56
|
### 3. Use it
|
|
46
57
|
|
|
@@ -57,6 +68,8 @@ export default function Page() {
|
|
|
57
68
|
}
|
|
58
69
|
```
|
|
59
70
|
|
|
71
|
+
> **Note:** After first setup, run `next build` or `next dev` once to generate the route types. Autocomplete will work after that.
|
|
72
|
+
|
|
60
73
|
## Supported route types
|
|
61
74
|
|
|
62
75
|
### Static routes
|
|
@@ -66,7 +79,7 @@ generatePath("/about");
|
|
|
66
79
|
// => "/about"
|
|
67
80
|
```
|
|
68
81
|
|
|
69
|
-
### Dynamic routes
|
|
82
|
+
### Dynamic routes — `[param]`
|
|
70
83
|
|
|
71
84
|
```tsx
|
|
72
85
|
generatePath("/blog/[slug]", { slug: "hello-world" });
|
|
@@ -75,23 +88,46 @@ generatePath("/blog/[slug]", { slug: "hello-world" });
|
|
|
75
88
|
|
|
76
89
|
### Nested dynamic routes
|
|
77
90
|
|
|
91
|
+
Params from parent segments are included:
|
|
92
|
+
|
|
78
93
|
```tsx
|
|
79
94
|
generatePath("/products/[id]/reviews", { id: "42" });
|
|
80
95
|
// => "/products/42/reviews"
|
|
81
96
|
```
|
|
82
97
|
|
|
83
|
-
### Catch-all routes
|
|
98
|
+
### Catch-all routes — `[...param]`
|
|
84
99
|
|
|
85
|
-
Catch-all params accept `string[]` — segments are joined with
|
|
100
|
+
Catch-all params accept `string[]` — segments are joined with `/`:
|
|
86
101
|
|
|
87
102
|
```tsx
|
|
88
103
|
generatePath("/docs/[...segments]", { segments: ["guides", "routing"] });
|
|
89
104
|
// => "/docs/guides/routing"
|
|
105
|
+
|
|
106
|
+
generatePath("/docs/[...segments]", { segments: ["getting-started"] });
|
|
107
|
+
// => "/docs/getting-started"
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### API routes — `route.ts`
|
|
111
|
+
|
|
112
|
+
API route handlers are included in the `ParamMap` too, so `generatePath` works for building API URLs:
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
generatePath("/api/health");
|
|
116
|
+
// => "/api/health"
|
|
117
|
+
|
|
118
|
+
generatePath("/api/products/[id]", { id: "42" });
|
|
119
|
+
// => "/api/products/42"
|
|
90
120
|
```
|
|
91
121
|
|
|
92
|
-
|
|
122
|
+
This is useful for `fetch` calls where you want type-safe API paths:
|
|
123
|
+
|
|
124
|
+
```tsx
|
|
125
|
+
const res = await fetch(generatePath("/api/products/[id]", { id: productId }));
|
|
126
|
+
```
|
|
93
127
|
|
|
94
|
-
Route groups
|
|
128
|
+
### Route groups — `(folder)`
|
|
129
|
+
|
|
130
|
+
Route groups don't affect URLs. A page at `app/(marketing)/pricing/page.tsx` is just `/pricing`:
|
|
95
131
|
|
|
96
132
|
```tsx
|
|
97
133
|
generatePath("/pricing");
|
|
@@ -103,28 +139,72 @@ generatePath("/pricing");
|
|
|
103
139
|
Next.js with `typedRoutes: true` generates a `ParamMap` interface in `.next/types/routes.d.ts` that maps every route pattern to its params:
|
|
104
140
|
|
|
105
141
|
```ts
|
|
142
|
+
// Generated by Next.js
|
|
106
143
|
interface ParamMap {
|
|
107
144
|
"/": {}
|
|
108
145
|
"/about": {}
|
|
146
|
+
"/api/health": {}
|
|
147
|
+
"/api/products/[id]": { id: string }
|
|
109
148
|
"/blog/[slug]": { slug: string }
|
|
149
|
+
"/products/[id]": { id: string }
|
|
150
|
+
"/products/[id]/reviews": { id: string }
|
|
110
151
|
"/docs/[...segments]": { segments: string[] }
|
|
152
|
+
"/pricing": {}
|
|
111
153
|
}
|
|
112
154
|
```
|
|
113
155
|
|
|
114
|
-
`withTypedRoutes()` generates a small
|
|
156
|
+
`withTypedRoutes()` generates a small `.d.ts` file in `.next/types/` that merges this `ParamMap` into the package via [module augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation):
|
|
157
|
+
|
|
158
|
+
```ts
|
|
159
|
+
// Auto-generated in .next/types/typed-routes.d.ts
|
|
160
|
+
import type { ParamMap } from "./routes";
|
|
115
161
|
|
|
116
|
-
|
|
162
|
+
declare module "next-generate-path" {
|
|
163
|
+
interface TypedRoutesParamMap extends ParamMap {}
|
|
164
|
+
}
|
|
165
|
+
```
|
|
117
166
|
|
|
118
|
-
|
|
167
|
+
Since `.next/types/**/*.ts` is already in your tsconfig's `include`, TypeScript picks it up automatically — no manual wiring needed.
|
|
119
168
|
|
|
120
|
-
|
|
169
|
+
The `generatePath` function uses **conditional tuple types** to require params only when the route has them, and returns a **template literal type** (e.g. `` `/blog/${string}` ``) that Next.js's `RouteImpl` accepts — so the result works directly with `<Link>`, `redirect()`, and `router.push()`.
|
|
170
|
+
|
|
171
|
+
## API
|
|
172
|
+
|
|
173
|
+
### `generatePath(route, params?)`
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
import { generatePath } from "next-generate-path";
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Returns the resolved URL string. Params are required for dynamic routes and omitted for static routes.
|
|
180
|
+
|
|
181
|
+
- **`route`** — A route pattern string (autocompleted from your app's routes)
|
|
182
|
+
- **`params`** — An object of param values (required when the route has dynamic segments)
|
|
183
|
+
- **Returns** — The resolved URL, typed as a template literal compatible with Next.js's `RouteImpl`
|
|
184
|
+
|
|
185
|
+
Param values are URI-encoded. Catch-all params (`string[]`) are joined with `/`.
|
|
186
|
+
|
|
187
|
+
### `withTypedRoutes(config)`
|
|
188
|
+
|
|
189
|
+
```ts
|
|
190
|
+
import { withTypedRoutes } from "next-generate-path/next";
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Wraps your Next.js config. Enables `typedRoutes: true` and generates the type bridge file.
|
|
194
|
+
|
|
195
|
+
### `createGeneratePath<ParamMap>()`
|
|
121
196
|
|
|
122
197
|
```ts
|
|
123
198
|
import { createGeneratePath } from "next-generate-path";
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Factory for creating a `generatePath` function with a custom param map. Useful outside of Next.js or for testing:
|
|
124
202
|
|
|
203
|
+
```ts
|
|
125
204
|
type MyRoutes = {
|
|
126
205
|
"/": {};
|
|
127
206
|
"/users/[id]": { id: string };
|
|
207
|
+
"/docs/[...path]": { path: string[] };
|
|
128
208
|
};
|
|
129
209
|
|
|
130
210
|
const generatePath = createGeneratePath<MyRoutes>();
|
|
@@ -133,6 +213,12 @@ generatePath("/users/[id]", { id: "123" });
|
|
|
133
213
|
// => "/users/123"
|
|
134
214
|
```
|
|
135
215
|
|
|
216
|
+
## Requirements
|
|
217
|
+
|
|
218
|
+
- Next.js 14+ with App Router
|
|
219
|
+
- TypeScript
|
|
220
|
+
- `typedRoutes` enabled (handled automatically by `withTypedRoutes`)
|
|
221
|
+
|
|
136
222
|
## License
|
|
137
223
|
|
|
138
224
|
MIT
|