Skip to content

Commit

Permalink
override nextjs types
Browse files Browse the repository at this point in the history
  • Loading branch information
tatethurston committed Mar 25, 2022
1 parent 80de2ae commit d5c0396
Show file tree
Hide file tree
Showing 7 changed files with 165 additions and 243 deletions.
15 changes: 15 additions & 0 deletions examples/typescript-example/@types/nextjs-routes.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.'
// Run `yarn nextjs-routes` to regenerate this file.

//import type { NextUrl } from "nextjs-routes";
// , Router, LinkProps, NextLink
type Routes = NextUrl<"/api/hello"> | NextUrl<"/index">;

declare module "next/link" {
function Link(props: string): number;
export default Link;
}

declare module "next/router" {
export function useRouter(): Router<Routes>;
}
66 changes: 7 additions & 59 deletions examples/typescript-example/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,78 +1,26 @@
import type { NextPage } from "next";
import Head from "next/head";
import Image from "next/image";
import styles from "../styles/Home.module.css";
import { Link, useRouter } from "../routes";
import { useEffect } from "react";
import { useRouter } from "next/router";
import Link from "next/link";

const Home: NextPage = () => {
const router = useRouter();
useEffect(() => {
router.push({ pathname: "/api/hello" });
router.push({ pathname: "/index" });
}, []);

return (
<div className={styles.container}>
<>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<Link href={{ pathname: "/index" }}>Hello</Link>
<main className={styles.main}>
<h1 className={styles.title}>
Welcome to <a href="https://nextjs.org">Next.js!</a>
</h1>

<p className={styles.description}>
Get started by editing{" "}
<code className={styles.code}>pages/index.tsx</code>
</p>

<div className={styles.grid}>
<a href="https://nextjs.org/docs" className={styles.card}>
<h2>Documentation &rarr;</h2>
<p>Find in-depth information about Next.js features and API.</p>
</a>

<a href="https://nextjs.org/learn" className={styles.card}>
<h2>Learn &rarr;</h2>
<p>Learn about Next.js in an interactive course with quizzes!</p>
</a>

<a
href="https://github.com/vercel/next.js/tree/canary/examples"
className={styles.card}
>
<h2>Examples &rarr;</h2>
<p>Discover and deploy boilerplate example Next.js projects.</p>
</a>

<a
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
className={styles.card}
>
<h2>Deploy &rarr;</h2>
<p>
Instantly deploy your Next.js site to a public URL with Vercel.
</p>
</a>
</div>
<main>
<Link href={{ pathname: "/i" }}>Home</Link>
</main>

<footer className={styles.footer}>
<a
href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Powered by{" "}
<span className={styles.logo}>
<Image src="/vercel.svg" alt="Vercel Logo" width={72} height={16} />
</span>
</a>
</footer>
</div>
</>
);
};

Expand Down
25 changes: 0 additions & 25 deletions examples/typescript-example/routes.ts

This file was deleted.

7 changes: 3 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nextjs-routes",
"version": "0.0.2",
"version": "0.0.3",
"description": "Type safe routing for Next.js",
"license": "MIT",
"author": "Tate <[email protected]>",
Expand All @@ -22,9 +22,7 @@
"lint:fix": "prettier --write . && prettier-package-json --write '{,example/}package.json' && eslint --fix .",
"package:prune": "find dist -name test.* | xargs rm",
"test": "yarn jest",
"typecheck": "yarn tsc --noEmit",
"version": "yarn run build && git add -A package.json",
"postversion": "git push && git push --tags"
"typecheck": "yarn tsc --noEmit"
},
"sideEffects": false,
"types": "dist/index.d.ts",
Expand All @@ -50,6 +48,7 @@
"next": "^12.1.0",
"prettier": "^2.1.1",
"prettier-package-json": "^2.1.3",
"react": "^17.0.2",
"typescript": "^4.1.3",
"webpack": "^5.37.0",
"webpack-cli": "^4.7.0"
Expand Down
5 changes: 3 additions & 2 deletions src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env node

import { writeFileSync } from "fs";
import { mkdirSync, writeFileSync } from "fs";
import { join } from "path";
import {
NEXTJS_PAGES_DIRECTORY_NAME,
Expand All @@ -24,7 +24,8 @@ async function main(): Promise<void> {
console.warn(e);
}

writeFileSync("./routes.ts", generated);
mkdirSync("./@types", { recursive: true });
writeFileSync("./@types/nextjs-routes.d.ts", generated);
}

void main();
59 changes: 11 additions & 48 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,6 @@ export function findFiles(entry: string): string[] {
});
}

function humanize(input: string): string {
return input
.replace(/\[.*?]/g, "")
.replace(/\]/g, "")
.replace("...", "")
.split(/\/|-|_/)
.filter(Boolean)
.map((x) => x[0].toUpperCase() + x.slice(1))
.join("");
}

type QueryType = "dynamic" | "catch-all" | "optional-catch-all";

interface Route {
Expand Down Expand Up @@ -98,35 +87,12 @@ function getQueryInterface(query: Route["query"]): string {
return res;
}

function getRouteHelperInterface(route: Route): string {
const query = getQueryInterface(route.query);
let generic = "";
if (query) {
generic = `NextUrl<'${route.pathname}', ${query}>`;
} else {
generic = `NextUrl<'${route.pathname}'>`;
}

const optionalArgs = !query;

return `${humanize(route.pathname)}: function<Url extends ${generic}>(opts${
optionalArgs ? "?" : ""
}: Omit<Url, 'pathname'>): Url`;
}

export function generate(routes: Route[]): string {
let res = "";
res += `\
return `\
// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.'
// Run \`yarn nextjs-routes\` to regenerate this file.
import { useRouter as useNextRouter } from "next/router";
import NextLink from "next/link";
import type { NextUrl, Router, RouteLink } from "nextjs-routes";
export const useRouter: () => Router<Routes> = useNextRouter;
export const Link: RouteLink<Routes> = NextLink
import type { NextUrl, Router, LinkProps, NextLink } from "nextjs-routes";
export type Routes =
| ${routes
Expand All @@ -140,17 +106,14 @@ export type Routes =
})
.join("\n | ")}
export const Route = {
${routes
.map(
(route) =>
`${getRouteHelperInterface(route)} {
return { pathname: '${route.pathname}', ...opts } as Url;
}`
)
.join(",\n ")}
} as const;
`;
declare module "next/link" {
declare function Link(props: LinkProps<Routes>): NextLink
export default Link;
}
return res;
declare module "next/router" {
export function useRouter(): Router<Routes>;
}
`;
}
Loading

0 comments on commit d5c0396

Please sign in to comment.