Skip to content

Commit

Permalink
- updated the options section of the docs site to include --filename
Browse files Browse the repository at this point in the history
- updated the examples folder with an example project that uses a custom filename for the routeType.ts files
- updated the cli to allow for a custom filename to be set under the --filename flag to replace the default of 'routeType.ts'
  • Loading branch information
JasonPaff committed Dec 7, 2024
1 parent c1d364e commit aa809d6
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 82 deletions.
12 changes: 6 additions & 6 deletions examples/appdir-custom-filename/_next-typesafe-url_.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ declare module "@@@next-typesafe-url" {
import type { InferRoute, StaticRoute } from "next-typesafe-url";

interface DynamicRouter {
"/foo/[id]/nest": InferRoute<import("./src/app/(test)/foo/[id]/nest/routeType").RouteType>;
"/foo/[id]": InferRoute<import("./src/app/(test)/foo/[id]/routeType").RouteType>;
"/client/[...client]": InferRoute<import("./src/app/client/[...client]/routeType").RouteType>;
"/jsonRoute/[foo]": InferRoute<import("./src/app/jsonRoute/[foo]/routeType").RouteType>;
"/transform": InferRoute<import("./src/app/transform/routeType").RouteType>;
"/[slug]/[...foo]": InferRoute<import("./src/app/[slug]/[...foo]/routeType").RouteType>;
"/foo/[id]/nest": InferRoute<import("./src/app/(test)/foo/[id]/nest/route-type").RouteType>;
"/foo/[id]": InferRoute<import("./src/app/(test)/foo/[id]/route-type").RouteType>;
"/client/[...client]": InferRoute<import("./src/app/client/[...client]/route-type").RouteType>;
"/jsonRoute/[foo]": InferRoute<import("./src/app/jsonRoute/[foo]/route-type").RouteType>;
"/transform": InferRoute<import("./src/app/transform/route-type").RouteType>;
"/[slug]/[...foo]": InferRoute<import("./src/app/[slug]/[...foo]/route-type").RouteType>;
"/dynamic": InferRoute<import("./src/pages/dynamic").RouteType>;
}

Expand Down
45 changes: 23 additions & 22 deletions packages/next-typesafe-url/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,46 +60,47 @@ export type RouteInformation = {
};

function build({
paths,
pageExtensions,
filename
}: {
paths,
pageExtensions,
filename
}: {
paths: Paths;
pageExtensions: string[];
filename: string;
}) {
const { absoluteAppPath, absolutePagesPath } = paths;

const appRoutesInfo = absoluteAppPath
? getAPPRoutesWithExportedRoute({
? getAPPRoutesWithExportedRoute({
basePath: absoluteAppPath,
dir: absoluteAppPath,
pageExtensions,
filename,
})
: null;
: null;
const pagesRoutesInfo = absolutePagesPath
? getPAGESRoutesWithExportedRoute({
? getPAGESRoutesWithExportedRoute({
basePath: absolutePagesPath,
dir: absolutePagesPath,
pageExtensions,
filename,
})
: null;
: null;

generateTypesFile({
appRoutesInfo,
pagesRoutesInfo,
paths,
filename
});
console.log(`Generated route types`);
}

function watch({
paths,
pageExtensions,
filename
}: {
paths,
pageExtensions,
filename
}: {
paths: Paths;
pageExtensions: string[];
filename: string;
Expand All @@ -108,17 +109,17 @@ function watch({

if (absoluteAppPath) {
chokidar
.watch([`${absoluteAppPath}/**/*.{${pageExtensions.join(",")}}`])
.on("change", () => {
build({filename, paths, pageExtensions });
});
.watch([`${absoluteAppPath}/**/*.{${pageExtensions.join(",")}}`])
.on("change", () => {
build({filename, paths, pageExtensions });
});
}
if (absolutePagesPath) {
chokidar
.watch([`${absolutePagesPath}/**/*.{${pageExtensions.join(",")}}`])
.on("change", () => {
build({ filename, paths, pageExtensions });
});
.watch([`${absolutePagesPath}/**/*.{${pageExtensions.join(",")}}`])
.on("change", () => {
build({ filename, paths, pageExtensions });
});
}

console.log(`Watching for route changes`);
Expand All @@ -137,8 +138,8 @@ if (require.main === module) {

const absoluteOutputPath = path.join(process.cwd(), outputPath);
const relativePathFromOutputToSrc = path.relative(
path.dirname(absoluteOutputPath),
absoluteSrcPath
path.dirname(absoluteOutputPath),
absoluteSrcPath
);

const appPath = path.join(absoluteSrcPath, "app");
Expand Down
110 changes: 56 additions & 54 deletions packages/next-typesafe-url/src/generateTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import path from "path";
import type { Paths, RouteInformation } from "./cli";

export function getPAGESRoutesWithExportedRoute({
basePath,
dir,
hasRoute = [],
doesntHaveRoute = [],
pageExtensions,
filename,
}: {
basePath,
dir,
hasRoute = [],
doesntHaveRoute = [],
pageExtensions,
filename,
}: {
basePath: string;
dir: string;
hasRoute?: string[];
Expand All @@ -31,24 +31,24 @@ export function getPAGESRoutesWithExportedRoute({
} else {
const fileName = path.basename(fullPath);
if (
fileName === "_app.tsx" ||
fileName === "_document.tsx" ||
fileName.startsWith("_") ||
![".tsx", ".js"].includes(path.extname(fullPath))
fileName === "_app.tsx" ||
fileName === "_document.tsx" ||
fileName.startsWith("_") ||
![".tsx", ".js"].includes(path.extname(fullPath))
) {
return;
}

const fileContent = fs.readFileSync(fullPath, "utf8");
const hasExportedRouteType = /export\s+type\s+RouteType\b/.test(
fileContent
fileContent
);

let routePath = fullPath
.replace(basePath, "")
.replace(/\\/g, "/")
.replace(/\/index\.(tsx|js)$/, "")
.replace(/\.(tsx|js)$/, "");
.replace(basePath, "")
.replace(/\\/g, "/")
.replace(/\/index\.(tsx|js)$/, "")
.replace(/\.(tsx|js)$/, "");

// Matches all the index files with extensions from the pageExtensions
if (pageExtensions.map((ext) => `index.${ext}`).includes(fileName)) {
Expand All @@ -74,13 +74,13 @@ export function getPAGESRoutesWithExportedRoute({
}

export function getAPPRoutesWithExportedRoute({
basePath,
dir = basePath,
hasRoute = [],
doesntHaveRoute = [],
pageExtensions,
filename
}: {
basePath,
dir = basePath,
hasRoute = [],
doesntHaveRoute = [],
pageExtensions,
filename
}: {
basePath: string;
dir: string;
hasRoute?: string[];
Expand All @@ -99,9 +99,9 @@ export function getAPPRoutesWithExportedRoute({

//intercepted routes- "(.)" "(..)" "(...)"
if (
/^\(\.\)(.+)$/.test(file) ||
/^\(\.\.\)(.+)$/.test(file) ||
/^\(\.\.\.\)(.+)$/.test(file)
/^\(\.\)(.+)$/.test(file) ||
/^\(\.\.\)(.+)$/.test(file) ||
/^\(\.\.\.\)(.+)$/.test(file)
) {
return;
}
Expand All @@ -115,21 +115,21 @@ export function getAPPRoutesWithExportedRoute({
filename
});
} else if (
// Matches page files with the extensions from pageExtensions
pageExtensions.map((p) => `page.${p}`).includes(file)
// Matches page files with the extensions from pageExtensions
pageExtensions.map((p) => `page.${p}`).includes(file)
) {
// With custom pageExtension
let routePath = fullPath
.replace(basePath, "")
.replace(/\\/g, "/")
.replace(new RegExp(`/page\\.(${pageExtensions.join("|")})$`), "");
.replace(basePath, "")
.replace(/\\/g, "/")
.replace(new RegExp(`/page\\.(${pageExtensions.join("|")})$`), "");

if (dir === basePath) {
routePath = "/";
}

const routeTypePaths = ["ts", "tsx"].map((ext) =>
path.join(dir, `${filename}.${ext}`)
path.join(dir, `${filename}.${ext}`)
);
const didAddRoute = routeTypePaths.reduce((didAdd, routeTypePath) => {
// Avoid adding the same route twice
Expand All @@ -153,13 +153,15 @@ export function getAPPRoutesWithExportedRoute({
}

export function generateTypesFile({
appRoutesInfo,
pagesRoutesInfo,
paths,
}: {
appRoutesInfo,
pagesRoutesInfo,
paths,
filename,
}: {
appRoutesInfo: RouteInformation | null;
pagesRoutesInfo: RouteInformation | null;
paths: Paths;
filename: string;
}): void {
let routeCounter = 0;

Expand All @@ -174,27 +176,27 @@ export function generateTypesFile({
const allDoesntHaveRoute_pages = pagesRoutesInfo?.doesntHaveRoute ?? [];

const routeTypeDeclarations = allHasRoute
.map(({ route, type }) => {
const pathAfterSrc = path.join(
type,
route === "/" ? "" : route,
type === "app" ? "routeType" : ""
);
const finalRelativePath = path
.join(paths.relativePathFromOutputToSrc, pathAfterSrc)
// replace backslashes with forward slashes
.replace(/\\/g, "/")
// ensure relative paths start with "./"
.replace(/^(?!\.\.\/)/, "./");
return ` "${
type === "app" ? route.replace(/\/\([^()]+\)/g, "") : route
}": InferRoute<import("${finalRelativePath}").RouteType>;`;
})
.join("\n ");
.map(({ route, type }) => {
const pathAfterSrc = path.join(
type,
route === "/" ? "" : route,
type === "app" ? filename : ""
);
const finalRelativePath = path
.join(paths.relativePathFromOutputToSrc, pathAfterSrc)
// replace backslashes with forward slashes
.replace(/\\/g, "/")
// ensure relative paths start with "./"
.replace(/^(?!\.\.\/)/, "./");
return ` "${
type === "app" ? route.replace(/\/\([^()]+\)/g, "") : route
}": InferRoute<import("${finalRelativePath}").RouteType>;`;
})
.join("\n ");

const staticRoutesDeclarations = [
...allDoesntHaveRoute_app.map(
(route) => ` "${route.replace(/\/\([^()]+\)/g, "")}": StaticRoute;`
(route) => ` "${route.replace(/\/\([^()]+\)/g, "")}": StaticRoute;`
),
...allDoesntHaveRoute_pages.map((route) => ` "${route}": StaticRoute;`),
].join("\n ");
Expand Down

0 comments on commit aa809d6

Please sign in to comment.