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 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
@@ -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 };
@@ -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"]}
@@ -0,0 +1,5 @@
1
+ import { NextConfig } from 'next';
2
+
3
+ declare function withTypedRoutes(config: NextConfig): NextConfig;
4
+
5
+ export { withTypedRoutes };
package/dist/next.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ import { NextConfig } from 'next';
2
+
3
+ declare function withTypedRoutes(config: NextConfig): NextConfig;
4
+
5
+ export { withTypedRoutes };
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
@@ -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
+ }