1.0.14 • Published 11 months ago

generate-router v1.0.14

Weekly downloads
-
License
ISC
Repository
github
Last release
11 months ago

Generate Router

npm version downloads license

A utility to generate TypeScript route definitions for Next.js projects. This tool supports both pages (Page Router) and app (App Router) structures, allowing you to create type-safe route definitions.

Installation

You can install the library using pnpm, npm, or yarn:

pnpm add generate-router

Usage

CLI Usage

The library provides a CLI tool to generate TypeScript route definitions. After installation, you can use the generate-router command:

npx generate-router ./pages ./types/routes.d.ts

Using Type Overrides

This library overrides the types for Next.js's useRouter (from next/router and next/navigation) and the href prop of the Link component. This ensures type safety and will result in TypeScript compilation errors if you try to use undefined routes.

// Correct usage
router.push('/about'); // Works fine
router.push('/user/123'); // Works fine

// Incorrect usage
router.push('/invalid-path'); // Compilation error
<Link href="/undefined-route">Invalid</Link> // Compilation error

To enable type overriding, add the --override or -o option when running the CLI:

npx generate-router ./pages ./types/routes.d.ts --override
# or
npx generate-router ./pages ./types/routes.d.ts -o

Arguments

  1. <pagesDir>: Path to the pages or app directory in your Next.js project. (Required)
  2. <outputFile>: Path to the output TypeScript definition file. (Required)

Options

  • -o, --override: Override Next.js router types to provide type-safe routing. When enabled, it adds type definitions for next/router and next/navigation modules. (Optional, defaults to false)

Example

If your pages directory contains the following structure:

pages/
├── about.tsx
├── index.tsx
└── user/
    └── [id].tsx

Running the following command:

npx generate-router ./pages ./types/routes.d.ts --override

Will generate a file at ./types/routes.d.ts with the following content:

// This file is auto-generated. Do not edit manually.
type StaticPaths =
    | '/'
    | '/about';

type DynamicPaths =
    | `/user/${string}`;

type RoutePath = StaticPaths | DynamicPaths | `${StaticPaths}?${string}`;

// Next.js Router Type Overrides (when --override option is used)
declare module 'next/router' {
  interface UrlObject {
    pathname: RoutePath;
    query?: { [key: string]: string | number | boolean | readonly string[] | undefined };
    hash?: string;
  }

  interface NextRouter extends Omit<import('next/dist/shared/lib/router/router').NextRouter, 'push' | 'replace'> {
    push(
      url: RoutePath | UrlObject,
      as?: string | UrlObject,
      options?: TransitionOptions
    ): Promise<boolean>;
    replace(
      url: RoutePath | UrlObject,
      as?: string | UrlObject,
      options?: TransitionOptions
    ): Promise<boolean>;
  }

  export function useRouter(): NextRouter;
}

declare module 'next/navigation' {
  interface NavigationUrlObject {
    pathname: RoutePath;
    query?: { [key: string]: string | number | boolean | readonly string[] | undefined };
    hash?: string;
  }

  interface NavigationRouter extends Omit<import('next/dist/shared/lib/app-router-context.shared-runtime').AppRouterInstance, 'push' | 'replace'> {
    push(href: RoutePath | NavigationUrlObject, options?: { scroll?: boolean }): void;
    replace(href: RoutePath | NavigationUrlObject, options?: { scroll?: boolean }): void;
    query: { [key: string]: string | string[] | undefined };
  }

  export { NavigationRouter };
  export function useRouter(): NavigationRouter;
  export function usePathname(): RoutePath;
  export function useSearchParams(): URLSearchParams & {
    get(key: string): string | null;
    getAll(): { [key: string]: string | string[] };
  };
}

declare module 'next/link' {
  export interface LinkProps
    extends Omit<import('next/dist/client/link').LinkProps, 'href'> {
    href:
      | RoutePath
      | {
          pathname: RoutePath;
          query?: {
            [key: string]:
              | string
              | number
              | boolean
              | readonly string[]
              | undefined;
          };
          hash?: string;
        };
  }

  export default function Link(props: LinkProps): JSX.Element;
}

Using npm scripts

You can also define a script in your package.json for easier usage:

"scripts": {
  "generate:routes": "generate-router ./pages ./src/routes.d.ts --override"
}

Now you can run:

yarn generate:routes

Development

Scripts

  • Build: Run the Rollup bundler to create the production build:
    pnpm run build
  • Test: Run Jest tests:
    pnpm run test

File Structure

project-root/
├── src/
│   ├── index.ts             # Entry point
│   ├── generator.ts         # Core logic
│   ├── utils/
│       ├── fileUtils.ts     # File utilities
│       ├── routeUtils.ts    # Route generation utilities
├── test/
│   ├── generator.test.ts    # Tests for generator.ts
│   ├── utils/
│       ├── fileUtils.test.ts # Tests for fileUtils.ts
│       ├── routeUtils.test.ts # Tests for routeUtils.ts
├── dist/                    # Build output
├── package.json             # Project configuration
├── jest.config.js           # Jest configuration
├── rollup.config.js         # Rollup configuration
├── tsconfig.json            # TypeScript configuration

License

This project is licensed under the ISC License.

1.0.9

11 months ago

1.0.8

11 months ago

1.0.11

11 months ago

1.0.10

11 months ago

1.0.14

11 months ago

1.0.13

11 months ago

1.0.12

11 months ago

1.0.5

11 months ago

1.0.4

11 months ago

1.0.3

11 months ago

1.0.2

11 months ago

1.0.1

11 months ago

1.0.0

11 months ago