next-generate-path 0.0.1
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 +138 -0
- package/dist/index.d.mts +11 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +56 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +30 -0
- package/dist/index.mjs.map +1 -0
- package/dist/next.d.mts +5 -0
- package/dist/next.d.ts +5 -0
- package/dist/next.js +49 -0
- package/dist/next.js.map +1 -0
- package/dist/next.mjs +24 -0
- package/dist/next.mjs.map +1 -0
- package/package.json +70 -0
package/README.md
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# next-generate-path
|
|
2
|
+
|
|
3
|
+
Type-safe `generatePath()` for Next.js. Autocomplete for every route, params enforced at compile time.
|
|
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.
|
|
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.
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { generatePath } from "next-generate-path";
|
|
11
|
+
|
|
12
|
+
generatePath("/blog/[slug]", { slug: "hello-world" });
|
|
13
|
+
// => "/blog/hello-world" — full autocomplete, params required
|
|
14
|
+
|
|
15
|
+
generatePath("/about");
|
|
16
|
+
// => "/about" — no params needed
|
|
17
|
+
|
|
18
|
+
generatePath("/blog/[slug]");
|
|
19
|
+
// TS error: missing required params
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The return type is compatible with Next.js's `RouteImpl`, so it works directly with `<Link>`, `redirect()`, and `router.push()` — no casts needed.
|
|
23
|
+
|
|
24
|
+
## Setup
|
|
25
|
+
|
|
26
|
+
### 1. Install
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install next-generate-path
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### 2. Wrap your Next.js config
|
|
33
|
+
|
|
34
|
+
```js
|
|
35
|
+
// next.config.js
|
|
36
|
+
import { withTypedRoutes } from "next-generate-path/next";
|
|
37
|
+
|
|
38
|
+
const nextConfig = {};
|
|
39
|
+
|
|
40
|
+
export default withTypedRoutes(nextConfig);
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
That's it. `withTypedRoutes` enables `typedRoutes` and generates a declaration file that wires your app's routes into `generatePath` automatically.
|
|
44
|
+
|
|
45
|
+
### 3. Use it
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
import Link from "next/link";
|
|
49
|
+
import { generatePath } from "next-generate-path";
|
|
50
|
+
|
|
51
|
+
export default function Page() {
|
|
52
|
+
return (
|
|
53
|
+
<Link href={generatePath("/blog/[slug]", { slug: "hello-world" })}>
|
|
54
|
+
Read post
|
|
55
|
+
</Link>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Supported route types
|
|
61
|
+
|
|
62
|
+
### Static routes
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
generatePath("/about");
|
|
66
|
+
// => "/about"
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Dynamic routes
|
|
70
|
+
|
|
71
|
+
```tsx
|
|
72
|
+
generatePath("/blog/[slug]", { slug: "hello-world" });
|
|
73
|
+
// => "/blog/hello-world"
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Nested dynamic routes
|
|
77
|
+
|
|
78
|
+
```tsx
|
|
79
|
+
generatePath("/products/[id]/reviews", { id: "42" });
|
|
80
|
+
// => "/products/42/reviews"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Catch-all routes
|
|
84
|
+
|
|
85
|
+
Catch-all params accept `string[]` — segments are joined with `/`.
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
generatePath("/docs/[...segments]", { segments: ["guides", "routing"] });
|
|
89
|
+
// => "/docs/guides/routing"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Route groups
|
|
93
|
+
|
|
94
|
+
Route groups like `(marketing)` don't affect URLs. A page at `app/(marketing)/pricing/page.tsx` is just `/pricing`:
|
|
95
|
+
|
|
96
|
+
```tsx
|
|
97
|
+
generatePath("/pricing");
|
|
98
|
+
// => "/pricing"
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## How it works
|
|
102
|
+
|
|
103
|
+
Next.js with `typedRoutes: true` generates a `ParamMap` interface in `.next/types/routes.d.ts` that maps every route pattern to its params:
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
interface ParamMap {
|
|
107
|
+
"/": {}
|
|
108
|
+
"/about": {}
|
|
109
|
+
"/blog/[slug]": { slug: string }
|
|
110
|
+
"/docs/[...segments]": { segments: string[] }
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
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.
|
|
115
|
+
|
|
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.
|
|
117
|
+
|
|
118
|
+
## `createGeneratePath` factory
|
|
119
|
+
|
|
120
|
+
If you're not using Next.js, or want to provide your own param map, use the factory:
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
import { createGeneratePath } from "next-generate-path";
|
|
124
|
+
|
|
125
|
+
type MyRoutes = {
|
|
126
|
+
"/": {};
|
|
127
|
+
"/users/[id]": { id: string };
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const generatePath = createGeneratePath<MyRoutes>();
|
|
131
|
+
|
|
132
|
+
generatePath("/users/[id]", { id: "123" });
|
|
133
|
+
// => "/users/123"
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## License
|
|
137
|
+
|
|
138
|
+
MIT
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
type HasParams<T> = keyof T extends never ? false : true;
|
|
2
|
+
type ResolveRoute<R extends string> = R extends `${infer Before}[${string}]${infer After}` ? `${Before}${string}${ResolveRoute<After>}` : R;
|
|
3
|
+
type ParamValue = string | string[];
|
|
4
|
+
interface TypedRoutesParamMap {
|
|
5
|
+
}
|
|
6
|
+
declare function generatePath<R extends keyof TypedRoutesParamMap & string>(...args: HasParams<TypedRoutesParamMap[R]> extends true ? [route: R, params: TypedRoutesParamMap[R]] : [route: R]): ResolveRoute<R>;
|
|
7
|
+
declare function createGeneratePath<PM extends {
|
|
8
|
+
[K in keyof PM]: Record<string, ParamValue>;
|
|
9
|
+
}>(): <R extends keyof PM & string>(...args: HasParams<PM[R]> extends true ? [route: R, params: PM[R]] : [route: R]) => ResolveRoute<R>;
|
|
10
|
+
|
|
11
|
+
export { type TypedRoutesParamMap, createGeneratePath, generatePath };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
type HasParams<T> = keyof T extends never ? false : true;
|
|
2
|
+
type ResolveRoute<R extends string> = R extends `${infer Before}[${string}]${infer After}` ? `${Before}${string}${ResolveRoute<After>}` : R;
|
|
3
|
+
type ParamValue = string | string[];
|
|
4
|
+
interface TypedRoutesParamMap {
|
|
5
|
+
}
|
|
6
|
+
declare function generatePath<R extends keyof TypedRoutesParamMap & string>(...args: HasParams<TypedRoutesParamMap[R]> extends true ? [route: R, params: TypedRoutesParamMap[R]] : [route: R]): ResolveRoute<R>;
|
|
7
|
+
declare function createGeneratePath<PM extends {
|
|
8
|
+
[K in keyof PM]: Record<string, ParamValue>;
|
|
9
|
+
}>(): <R extends keyof PM & string>(...args: HasParams<PM[R]> extends true ? [route: R, params: PM[R]] : [route: R]) => ResolveRoute<R>;
|
|
10
|
+
|
|
11
|
+
export { type TypedRoutesParamMap, createGeneratePath, generatePath };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
createGeneratePath: () => createGeneratePath,
|
|
24
|
+
generatePath: () => generatePath
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(index_exports);
|
|
27
|
+
function replaceParams(route, params) {
|
|
28
|
+
return route.replace(/\[(?:\.\.\.)?([^\]]+)\]/g, (_, key) => {
|
|
29
|
+
const value = params[key];
|
|
30
|
+
if (value === void 0) {
|
|
31
|
+
throw new Error(`Missing param "${key}" for route "${route}"`);
|
|
32
|
+
}
|
|
33
|
+
if (Array.isArray(value)) {
|
|
34
|
+
return value.map(encodeURIComponent).join("/");
|
|
35
|
+
}
|
|
36
|
+
return encodeURIComponent(value);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
function generatePath(...args) {
|
|
40
|
+
const [route, params] = args;
|
|
41
|
+
if (!params) return route;
|
|
42
|
+
return replaceParams(route, params);
|
|
43
|
+
}
|
|
44
|
+
function createGeneratePath() {
|
|
45
|
+
return function generatePath2(...args) {
|
|
46
|
+
const [route, params] = args;
|
|
47
|
+
if (!params) return route;
|
|
48
|
+
return replaceParams(route, params);
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
52
|
+
0 && (module.exports = {
|
|
53
|
+
createGeneratePath,
|
|
54
|
+
generatePath
|
|
55
|
+
});
|
|
56
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Checks whether a type has any keys at all.\n// Used to distinguish \"/blog/[slug]\" (has params) from \"/\" (no params).\n// HasParams<{ slug: string }> → true\n// HasParams<{}> → false\ntype HasParams<T> = keyof T extends never ? false : true;\n\n// Recursively turns a route pattern into the shape of its resolved URL,\n// so Next.js's Link/redirect/router.push accept it as a valid route.\n// ResolveRoute<\"/blog/[slug]\"> → `/blog/${string}`\n// ResolveRoute<\"/blog/[slug]/comments/[commentId]\"> → `/blog/${string}/comments/${string}`\n// ResolveRoute<\"/docs/[...segments]\"> → `/docs/${string}`\n// ResolveRoute<\"/\"> → \"/\"\ntype ResolveRoute<R extends string> =\n R extends `${infer Before}[${string}]${infer After}`\n ? `${Before}${string}${ResolveRoute<After>}`\n : R;\n\n// Param values can be strings (regular params) or string arrays (catch-all params like [...slug]).\ntype ParamValue = string | string[];\n\n// Replaces [param] and [...param] segments with their values.\n// Catch-all params (string[]) are joined with \"/\".\nfunction replaceParams(route: string, params: Record<string, ParamValue>): string {\n return route.replace(/\\[(?:\\.\\.\\.)?([^\\]]+)\\]/g, (_, key: string) => {\n const value = params[key];\n if (value === undefined) {\n throw new Error(`Missing param \"${key}\" for route \"${route}\"`);\n }\n if (Array.isArray(value)) {\n return value.map(encodeURIComponent).join(\"/\");\n }\n return encodeURIComponent(value);\n });\n}\n\n// Augmentable interface — `withTypedRoutes()` in next.config.js auto-generates\n// a declaration file that merges Next.js's `ParamMap` into this interface.\n// This is what makes `generatePath` know about your app's routes without\n// any manual wiring.\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface TypedRoutesParamMap {}\n\n// Ready-to-use generatePath, typed against TypedRoutesParamMap.\n// When used with `withTypedRoutes()` in next.config.js, this automatically\n// knows all your app's routes. No factory or manual setup needed.\nexport function generatePath<\n R extends keyof TypedRoutesParamMap & string,\n>(\n ...args: HasParams<TypedRoutesParamMap[R]> extends true\n ? [route: R, params: TypedRoutesParamMap[R]]\n : [route: R]\n): ResolveRoute<R> {\n const [route, params] = args as [string, Record<string, ParamValue>?];\n\n if (!params) return route as ResolveRoute<R>;\n\n return replaceParams(route, params) as ResolveRoute<R>;\n}\n\n// Factory for non-Next.js consumers or custom ParamMap types.\n// Produces the same generatePath function but with an explicit type parameter.\nexport function createGeneratePath<\n // Self-referential constraint: each value must be a Record<string, string | string[]>.\n // Written this way (instead of Record<string, ...>) because TS interfaces\n // (like Next.js's ParamMap) don't satisfy index-signature constraints.\n PM extends { [K in keyof PM]: Record<string, ParamValue> },\n>() {\n return function generatePath<R extends keyof PM & string>(\n // Conditional args tuple:\n // - routes WITH params → two args required: (route, params)\n // - routes WITHOUT params → single arg: (route)\n // This makes `generatePath(\"/\")` valid but `generatePath(\"/blog/[slug]\")` a TS error.\n ...args: HasParams<PM[R]> extends true\n ? [route: R, params: PM[R]]\n : [route: R]\n ): ResolveRoute<R> {\n const [route, params] = args as [string, Record<string, ParamValue>?];\n\n if (!params) return route as ResolveRoute<R>;\n\n return replaceParams(route, params) as ResolveRoute<R>;\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsBA,SAAS,cAAc,OAAe,QAA4C;AAChF,SAAO,MAAM,QAAQ,4BAA4B,CAAC,GAAG,QAAgB;AACnE,UAAM,QAAQ,OAAO,GAAG;AACxB,QAAI,UAAU,QAAW;AACvB,YAAM,IAAI,MAAM,kBAAkB,GAAG,gBAAgB,KAAK,GAAG;AAAA,IAC/D;AACA,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,aAAO,MAAM,IAAI,kBAAkB,EAAE,KAAK,GAAG;AAAA,IAC/C;AACA,WAAO,mBAAmB,KAAK;AAAA,EACjC,CAAC;AACH;AAYO,SAAS,gBAGX,MAGc;AACjB,QAAM,CAAC,OAAO,MAAM,IAAI;AAExB,MAAI,CAAC,OAAQ,QAAO;AAEpB,SAAO,cAAc,OAAO,MAAM;AACpC;AAIO,SAAS,qBAKZ;AACF,SAAO,SAASA,iBAKX,MAGc;AACjB,UAAM,CAAC,OAAO,MAAM,IAAI;AAExB,QAAI,CAAC,OAAQ,QAAO;AAEpB,WAAO,cAAc,OAAO,MAAM;AAAA,EACpC;AACF;","names":["generatePath"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
function replaceParams(route, params) {
|
|
3
|
+
return route.replace(/\[(?:\.\.\.)?([^\]]+)\]/g, (_, key) => {
|
|
4
|
+
const value = params[key];
|
|
5
|
+
if (value === void 0) {
|
|
6
|
+
throw new Error(`Missing param "${key}" for route "${route}"`);
|
|
7
|
+
}
|
|
8
|
+
if (Array.isArray(value)) {
|
|
9
|
+
return value.map(encodeURIComponent).join("/");
|
|
10
|
+
}
|
|
11
|
+
return encodeURIComponent(value);
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
function generatePath(...args) {
|
|
15
|
+
const [route, params] = args;
|
|
16
|
+
if (!params) return route;
|
|
17
|
+
return replaceParams(route, params);
|
|
18
|
+
}
|
|
19
|
+
function createGeneratePath() {
|
|
20
|
+
return function generatePath2(...args) {
|
|
21
|
+
const [route, params] = args;
|
|
22
|
+
if (!params) return route;
|
|
23
|
+
return replaceParams(route, params);
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export {
|
|
27
|
+
createGeneratePath,
|
|
28
|
+
generatePath
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Checks whether a type has any keys at all.\n// Used to distinguish \"/blog/[slug]\" (has params) from \"/\" (no params).\n// HasParams<{ slug: string }> → true\n// HasParams<{}> → false\ntype HasParams<T> = keyof T extends never ? false : true;\n\n// Recursively turns a route pattern into the shape of its resolved URL,\n// so Next.js's Link/redirect/router.push accept it as a valid route.\n// ResolveRoute<\"/blog/[slug]\"> → `/blog/${string}`\n// ResolveRoute<\"/blog/[slug]/comments/[commentId]\"> → `/blog/${string}/comments/${string}`\n// ResolveRoute<\"/docs/[...segments]\"> → `/docs/${string}`\n// ResolveRoute<\"/\"> → \"/\"\ntype ResolveRoute<R extends string> =\n R extends `${infer Before}[${string}]${infer After}`\n ? `${Before}${string}${ResolveRoute<After>}`\n : R;\n\n// Param values can be strings (regular params) or string arrays (catch-all params like [...slug]).\ntype ParamValue = string | string[];\n\n// Replaces [param] and [...param] segments with their values.\n// Catch-all params (string[]) are joined with \"/\".\nfunction replaceParams(route: string, params: Record<string, ParamValue>): string {\n return route.replace(/\\[(?:\\.\\.\\.)?([^\\]]+)\\]/g, (_, key: string) => {\n const value = params[key];\n if (value === undefined) {\n throw new Error(`Missing param \"${key}\" for route \"${route}\"`);\n }\n if (Array.isArray(value)) {\n return value.map(encodeURIComponent).join(\"/\");\n }\n return encodeURIComponent(value);\n });\n}\n\n// Augmentable interface — `withTypedRoutes()` in next.config.js auto-generates\n// a declaration file that merges Next.js's `ParamMap` into this interface.\n// This is what makes `generatePath` know about your app's routes without\n// any manual wiring.\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface TypedRoutesParamMap {}\n\n// Ready-to-use generatePath, typed against TypedRoutesParamMap.\n// When used with `withTypedRoutes()` in next.config.js, this automatically\n// knows all your app's routes. No factory or manual setup needed.\nexport function generatePath<\n R extends keyof TypedRoutesParamMap & string,\n>(\n ...args: HasParams<TypedRoutesParamMap[R]> extends true\n ? [route: R, params: TypedRoutesParamMap[R]]\n : [route: R]\n): ResolveRoute<R> {\n const [route, params] = args as [string, Record<string, ParamValue>?];\n\n if (!params) return route as ResolveRoute<R>;\n\n return replaceParams(route, params) as ResolveRoute<R>;\n}\n\n// Factory for non-Next.js consumers or custom ParamMap types.\n// Produces the same generatePath function but with an explicit type parameter.\nexport function createGeneratePath<\n // Self-referential constraint: each value must be a Record<string, string | string[]>.\n // Written this way (instead of Record<string, ...>) because TS interfaces\n // (like Next.js's ParamMap) don't satisfy index-signature constraints.\n PM extends { [K in keyof PM]: Record<string, ParamValue> },\n>() {\n return function generatePath<R extends keyof PM & string>(\n // Conditional args tuple:\n // - routes WITH params → two args required: (route, params)\n // - routes WITHOUT params → single arg: (route)\n // This makes `generatePath(\"/\")` valid but `generatePath(\"/blog/[slug]\")` a TS error.\n ...args: HasParams<PM[R]> extends true\n ? [route: R, params: PM[R]]\n : [route: R]\n ): ResolveRoute<R> {\n const [route, params] = args as [string, Record<string, ParamValue>?];\n\n if (!params) return route as ResolveRoute<R>;\n\n return replaceParams(route, params) as ResolveRoute<R>;\n };\n}\n"],"mappings":";AAsBA,SAAS,cAAc,OAAe,QAA4C;AAChF,SAAO,MAAM,QAAQ,4BAA4B,CAAC,GAAG,QAAgB;AACnE,UAAM,QAAQ,OAAO,GAAG;AACxB,QAAI,UAAU,QAAW;AACvB,YAAM,IAAI,MAAM,kBAAkB,GAAG,gBAAgB,KAAK,GAAG;AAAA,IAC/D;AACA,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,aAAO,MAAM,IAAI,kBAAkB,EAAE,KAAK,GAAG;AAAA,IAC/C;AACA,WAAO,mBAAmB,KAAK;AAAA,EACjC,CAAC;AACH;AAYO,SAAS,gBAGX,MAGc;AACjB,QAAM,CAAC,OAAO,MAAM,IAAI;AAExB,MAAI,CAAC,OAAQ,QAAO;AAEpB,SAAO,cAAc,OAAO,MAAM;AACpC;AAIO,SAAS,qBAKZ;AACF,SAAO,SAASA,iBAKX,MAGc;AACjB,UAAM,CAAC,OAAO,MAAM,IAAI;AAExB,QAAI,CAAC,OAAQ,QAAO;AAEpB,WAAO,cAAc,OAAO,MAAM;AAAA,EACpC;AACF;","names":["generatePath"]}
|
package/dist/next.d.mts
ADDED
package/dist/next.d.ts
ADDED
package/dist/next.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/next.ts
|
|
21
|
+
var next_exports = {};
|
|
22
|
+
__export(next_exports, {
|
|
23
|
+
withTypedRoutes: () => withTypedRoutes
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(next_exports);
|
|
26
|
+
var import_node_fs = require("fs");
|
|
27
|
+
var import_node_path = require("path");
|
|
28
|
+
var GENERATED_DTS = `// Auto-generated by next-generate-path \u2014 do not edit
|
|
29
|
+
import type { ParamMap } from "./routes";
|
|
30
|
+
import "next-generate-path";
|
|
31
|
+
|
|
32
|
+
declare module "next-generate-path" {
|
|
33
|
+
interface TypedRoutesParamMap extends ParamMap {}
|
|
34
|
+
}
|
|
35
|
+
`;
|
|
36
|
+
function withTypedRoutes(config) {
|
|
37
|
+
const typesDir = (0, import_node_path.join)(process.cwd(), ".next", "types");
|
|
38
|
+
(0, import_node_fs.mkdirSync)(typesDir, { recursive: true });
|
|
39
|
+
(0, import_node_fs.writeFileSync)((0, import_node_path.join)(typesDir, "typed-routes.d.ts"), GENERATED_DTS);
|
|
40
|
+
return {
|
|
41
|
+
...config,
|
|
42
|
+
typedRoutes: true
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
46
|
+
0 && (module.exports = {
|
|
47
|
+
withTypedRoutes
|
|
48
|
+
});
|
|
49
|
+
//# sourceMappingURL=next.js.map
|
package/dist/next.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/next.ts"],"sourcesContent":["import type { NextConfig } from \"next\";\nimport { writeFileSync, mkdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nconst GENERATED_DTS = `// Auto-generated by next-generate-path — do not edit\nimport type { ParamMap } from \"./routes\";\nimport \"next-generate-path\";\n\ndeclare module \"next-generate-path\" {\n interface TypedRoutesParamMap extends ParamMap {}\n}\n`;\n\n// Wraps your Next.js config to enable direct `generatePath` imports.\n// Generates a .d.ts file in .next/types/ that bridges Next.js's ParamMap\n// into the package's TypedRoutesParamMap via module augmentation.\nexport function withTypedRoutes(config: NextConfig): NextConfig {\n const typesDir = join(process.cwd(), \".next\", \"types\");\n mkdirSync(typesDir, { recursive: true });\n writeFileSync(join(typesDir, \"typed-routes.d.ts\"), GENERATED_DTS);\n\n return {\n ...config,\n typedRoutes: true,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,qBAAyC;AACzC,uBAAqB;AAErB,IAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYf,SAAS,gBAAgB,QAAgC;AAC9D,QAAM,eAAW,uBAAK,QAAQ,IAAI,GAAG,SAAS,OAAO;AACrD,gCAAU,UAAU,EAAE,WAAW,KAAK,CAAC;AACvC,wCAAc,uBAAK,UAAU,mBAAmB,GAAG,aAAa;AAEhE,SAAO;AAAA,IACL,GAAG;AAAA,IACH,aAAa;AAAA,EACf;AACF;","names":[]}
|
package/dist/next.mjs
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// src/next.ts
|
|
2
|
+
import { writeFileSync, mkdirSync } from "fs";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
var GENERATED_DTS = `// Auto-generated by next-generate-path \u2014 do not edit
|
|
5
|
+
import type { ParamMap } from "./routes";
|
|
6
|
+
import "next-generate-path";
|
|
7
|
+
|
|
8
|
+
declare module "next-generate-path" {
|
|
9
|
+
interface TypedRoutesParamMap extends ParamMap {}
|
|
10
|
+
}
|
|
11
|
+
`;
|
|
12
|
+
function withTypedRoutes(config) {
|
|
13
|
+
const typesDir = join(process.cwd(), ".next", "types");
|
|
14
|
+
mkdirSync(typesDir, { recursive: true });
|
|
15
|
+
writeFileSync(join(typesDir, "typed-routes.d.ts"), GENERATED_DTS);
|
|
16
|
+
return {
|
|
17
|
+
...config,
|
|
18
|
+
typedRoutes: true
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
withTypedRoutes
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=next.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/next.ts"],"sourcesContent":["import type { NextConfig } from \"next\";\nimport { writeFileSync, mkdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nconst GENERATED_DTS = `// Auto-generated by next-generate-path — do not edit\nimport type { ParamMap } from \"./routes\";\nimport \"next-generate-path\";\n\ndeclare module \"next-generate-path\" {\n interface TypedRoutesParamMap extends ParamMap {}\n}\n`;\n\n// Wraps your Next.js config to enable direct `generatePath` imports.\n// Generates a .d.ts file in .next/types/ that bridges Next.js's ParamMap\n// into the package's TypedRoutesParamMap via module augmentation.\nexport function withTypedRoutes(config: NextConfig): NextConfig {\n const typesDir = join(process.cwd(), \".next\", \"types\");\n mkdirSync(typesDir, { recursive: true });\n writeFileSync(join(typesDir, \"typed-routes.d.ts\"), GENERATED_DTS);\n\n return {\n ...config,\n typedRoutes: true,\n };\n}\n"],"mappings":";AACA,SAAS,eAAe,iBAAiB;AACzC,SAAS,YAAY;AAErB,IAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYf,SAAS,gBAAgB,QAAgC;AAC9D,QAAM,WAAW,KAAK,QAAQ,IAAI,GAAG,SAAS,OAAO;AACrD,YAAU,UAAU,EAAE,WAAW,KAAK,CAAC;AACvC,gBAAc,KAAK,UAAU,mBAAmB,GAAG,aAAa;AAEhE,SAAO;AAAA,IACL,GAAG;AAAA,IACH,aAAa;AAAA,EACf;AACF;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "next-generate-path",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Type-safe route path generation for Next.js typed routes",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/index.d.mts",
|
|
13
|
+
"default": "./dist/index.mjs"
|
|
14
|
+
},
|
|
15
|
+
"require": "./dist/index.js"
|
|
16
|
+
},
|
|
17
|
+
"./next": {
|
|
18
|
+
"types": "./dist/next.d.ts",
|
|
19
|
+
"import": {
|
|
20
|
+
"types": "./dist/next.d.mts",
|
|
21
|
+
"default": "./dist/next.mjs"
|
|
22
|
+
},
|
|
23
|
+
"require": "./dist/next.js"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"dist"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsup",
|
|
31
|
+
"dev": "tsup --watch",
|
|
32
|
+
"lint": "eslint . --max-warnings 0",
|
|
33
|
+
"check-types": "tsc --noEmit",
|
|
34
|
+
"test": "vitest run"
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"nextjs",
|
|
38
|
+
"typed-routes",
|
|
39
|
+
"generate-path",
|
|
40
|
+
"type-safe",
|
|
41
|
+
"routing"
|
|
42
|
+
],
|
|
43
|
+
"license": "MIT",
|
|
44
|
+
"repository": {
|
|
45
|
+
"type": "git",
|
|
46
|
+
"url": "git+https://github.com/twenty9-labs/next-generate-path.git"
|
|
47
|
+
},
|
|
48
|
+
"bugs": {
|
|
49
|
+
"url": "https://github.com/twenty9-labs/next-generate-path/issues"
|
|
50
|
+
},
|
|
51
|
+
"homepage": "https://github.com/twenty9-labs/next-generate-path#readme",
|
|
52
|
+
"peerDependencies": {
|
|
53
|
+
"next": ">=14"
|
|
54
|
+
},
|
|
55
|
+
"peerDependenciesMeta": {
|
|
56
|
+
"next": {
|
|
57
|
+
"optional": true
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"@repo/eslint-config": "workspace:*",
|
|
62
|
+
"@repo/typescript-config": "workspace:*",
|
|
63
|
+
"@types/node": "^22.15.3",
|
|
64
|
+
"eslint": "^9.39.1",
|
|
65
|
+
"next": "16.1.5",
|
|
66
|
+
"tsup": "^8.5.1",
|
|
67
|
+
"typescript": "5.9.2",
|
|
68
|
+
"vitest": "^4.0.18"
|
|
69
|
+
}
|
|
70
|
+
}
|