Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
"commit": false,
"access": "public",
"baseBranch": "main",
"ignore": ["pagesdir", "appdir", "custom-filename"]
"ignore": ["pagesdir", "appdir", "custom-filename", "with-config"]
}
5 changes: 5 additions & 0 deletions .changeset/witty-experts-juggle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"next-typesafe-url": minor
---

Adds TypeScript configuration file support
2 changes: 1 addition & 1 deletion examples/custom-filename/_next-typesafe-url_.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

declare module "@@@next-typesafe-url" {
import type { InferRoute, StaticRoute } from "next-typesafe-url";

interface DynamicRouter {
"/[slug]/[...foo]": InferRoute<import("./src/app/[slug]/[...foo]/route-type").RouteType>;
}
Expand Down
39 changes: 39 additions & 0 deletions examples/with-config/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js
.yarn/install-state.gz

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts

# generated types
_next-typesafe-url_.d.ts
14 changes: 14 additions & 0 deletions examples/with-config/next-typesafe-url.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { Config } from "next-typesafe-url";

const config: Config = {
// Optional: customize the output path
outputPath: "./next_safe_routes.d.ts",
// Optional: customize the src directory
srcPath: "./src",
// Optional: customize page extensions
pageExtensions: ["tsx", "ts", "jsx", "js"],
// Optional: customize the routeType filename
filename: "route-type",
};

export default config;
4 changes: 4 additions & 0 deletions examples/with-config/next.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/** @type {import('next').NextConfig} */
const nextConfig = {};

export default nextConfig;
19 changes: 19 additions & 0 deletions examples/with-config/next_safe_routes.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// This file is generated by next-typesafe-url
// Do not edit this file directly.

// @generated
// prettier-ignore
/* eslint-disable */

declare module "@@@next-typesafe-url" {
import type { InferRoute, StaticRoute } from "next-typesafe-url";

interface DynamicRouter {
"/blog/[slug]": InferRoute<import("./src/app/blog/[slug]/route-type").RouteType>;
}

interface StaticRouter {
"/about": StaticRoute;
"/": StaticRoute;
}
}
22 changes: 22 additions & 0 deletions examples/with-config/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "with-config",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "concurrently \"next-typesafe-url -w\" \"next dev\"",
"build": "next-typesafe-url && next build",
"start": "next start"
},
"dependencies": {
"@types/node": "22.0.0",
"@types/react": "18.3.12",
"@types/react-dom": "18.3.1",
"concurrently": "^8.0.1",
"next": "15.0.0",
"next-typesafe-url": "workspace:*",
"react": "19.0.0",
"react-dom": "19.0.0",
"typescript": "^5",
"zod": "^4.1.12"
}
}
14 changes: 14 additions & 0 deletions examples/with-config/src/app/about/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export default function About() {
return (
<div>
<h1>About</h1>
<p>
This is a simple static route that doesn't require route parameters.
</p>
<p>
Static routes are automatically typed and available in the router
autocomplete.
</p>
</div>
);
}
22 changes: 22 additions & 0 deletions examples/with-config/src/app/blog/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { PageProps, Route } from "./route-type";
import { withParamValidation } from "next-typesafe-url/app/hoc";

async function BlogPost({ routeParams }: PageProps) {
const { slug } = await routeParams;

return (
<div>
<h1>Blog Post: {slug}</h1>
<p>
This route demonstrates type-safe dynamic route parameters using
next-typesafe-url.
</p>
<p>
The <code>slug</code> parameter is validated at runtime and fully typed
at compile time.
</p>
</div>
);
}

export default withParamValidation(BlogPost, Route);
12 changes: 12 additions & 0 deletions examples/with-config/src/app/blog/[slug]/route-type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { DynamicRoute, InferPagePropsType } from "next-typesafe-url";

import { z } from "zod";

export const Route = {
routeParams: z.object({
slug: z.string(),
}),
} satisfies DynamicRoute;

export type RouteType = typeof Route;
export type PageProps = InferPagePropsType<RouteType>;
26 changes: 26 additions & 0 deletions examples/with-config/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import type { Metadata } from "next";
import type { ReactNode } from "react";

export const metadata: Metadata = {
title: "Next.js Typesafe URL - Config Example",
description: "Demonstrating config file usage with next-typesafe-url",
};

export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en">
<body>
<nav style={{ padding: "1rem", borderBottom: "1px solid #ccc" }}>
<a href="/" style={{ marginRight: "1rem" }}>
Home
</a>
<a href="/about" style={{ marginRight: "1rem" }}>
About
</a>
<a href="/blog/example-post">Blog Post</a>
</nav>
<main style={{ padding: "2rem" }}>{children}</main>
</body>
</html>
);
}
48 changes: 48 additions & 0 deletions examples/with-config/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
"use client";

import { $path } from "next-typesafe-url";
import { useRouter } from "next/navigation";

export default function Home() {
const router = useRouter();

const handleNavigate = () => {
// Type-safe navigation with route params
const url = $path({
route: "/blog/[slug]",
routeParams: {
slug: "my-first-post",
},
});
router.push(url);
};

return (
<div>
<h1>Welcome to Next.js Typesafe URL</h1>
<p>
This example demonstrates using a config file (
<code>next-typesafe-url.config.ts</code>) instead of CLI arguments.
</p>

<h2>Features:</h2>
<ul>
<li>✅ Type-safe routing</li>
<li>✅ Configuration file support</li>
<li>✅ Next.js 15 and React 19</li>
<li>✅ Automatic type generation</li>
</ul>

<button
onClick={handleNavigate}
style={{
marginTop: "1rem",
padding: "0.5rem 1rem",
cursor: "pointer",
}}
>
Navigate to Blog Post (Type-safe!)
</button>
</div>
);
}
27 changes: 27 additions & 0 deletions examples/with-config/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"compilerOptions": {
"target": "ES2017",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}
1 change: 0 additions & 1 deletion packages/next-typesafe-url/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,6 @@
### Major Changes

- 88cdd83: - major changes

- significant refactor to internal encoding + decoding logic- now simpler and easier to follow
- complete documentation rewrite
- code generation overhaul
Expand Down
2 changes: 2 additions & 0 deletions packages/next-typesafe-url/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@
},
"dependencies": {
"chokidar": "^3.5.3",
"cosmiconfig": "^9.0.0",
"jiti": "^1.21.0",
"meow": "9.0.0"
},
"devDependencies": {
Expand Down
Loading
Loading