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.
Files changed (2) hide show
  1. package/README.md +101 -15
  2. 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
- 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.
5
+ ## The problem
6
6
 
7
- `next-generate-path` fixes this. It gives you a single `generatePath` function with full autocomplete for **all** your routes and compile-time enforcement of the correct params.
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
- // => "/blog/hello-world" full autocomplete, params required
17
+ // ^ autocomplete shows all routes ^ params are required and type-checked
14
18
 
15
19
  generatePath("/about");
16
- // => "/about" — no params needed
20
+ // => "/about" — static routes need no params
17
21
 
18
22
  generatePath("/blog/[slug]");
19
- // TS error: missing required params
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
- ### Route groups
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 like `(marketing)` don't affect URLs. A page at `app/(marketing)/pricing/page.tsx` is just `/pricing`:
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 declaration 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). Since `.next/types/**/*.ts` is already in your tsconfig's `include`, TypeScript picks it up automatically — no manual wiring needed.
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
- 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.
162
+ declare module "next-generate-path" {
163
+ interface TypedRoutesParamMap extends ParamMap {}
164
+ }
165
+ ```
117
166
 
118
- ## `createGeneratePath` factory
167
+ Since `.next/types/**/*.ts` is already in your tsconfig's `include`, TypeScript picks it up automatically — no manual wiring needed.
119
168
 
120
- If you're not using Next.js, or want to provide your own param map, use the factory:
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "next-generate-path",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "Type-safe route path generation for Next.js typed routes",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",