Skip to content

Commit aabb9a4

Browse files
baic-ehrlich
andauthored
feat: Use ~/* import alias (#1191)
* feat: Use @/* import alias * Allow users override import alias * Change default import alias to ~/ * Run setImportAliases at a later stage --------- Co-authored-by: Christopher Ehrlich <[email protected]>
1 parent d5d3590 commit aabb9a4

28 files changed

+113
-31
lines changed

Diff for: .changeset/purple-carpets-cough.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"create-t3-app": patch
3+
---
4+
5+
Use ~/\* import alias

Diff for: cli/src/cli/index.ts

+24
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ interface CliFlags {
1313
noGit: boolean;
1414
noInstall: boolean;
1515
default: boolean;
16+
importAlias: string;
1617

1718
/** @internal Used in CI. */
1819
CI: boolean;
@@ -44,6 +45,7 @@ const defaultOptions: CliResults = {
4445
trpc: false,
4546
prisma: false,
4647
nextAuth: false,
48+
importAlias: "~/",
4749
},
4850
};
4951

@@ -105,6 +107,12 @@ export const runCli = async () => {
105107
"Experimental: Boolean value if we should install tRPC. Must be used in conjunction with `--CI`.",
106108
(value) => !!value && value !== "false",
107109
)
110+
/** @experimental - Used for CI E2E tests. Used in conjunction with `--CI` to skip prompting. */
111+
.option(
112+
"-i, --import-alias",
113+
"Explicitly tell the CLI to use a custom import alias",
114+
defaultOptions.flags.importAlias,
115+
)
108116
/** END CI-FLAGS */
109117
.version(getVersion(), "-v, --version", "Display the version number")
110118
.addHelpText(
@@ -164,6 +172,8 @@ export const runCli = async () => {
164172
if (!cliResults.flags.noInstall) {
165173
cliResults.flags.noInstall = !(await promptInstall());
166174
}
175+
176+
cliResults.flags.importAlias = await promptImportAlias();
167177
}
168178
} catch (err) {
169179
// If the user is not calling create-t3-app from an interactive terminal, inquirer will throw an error with isTTYError = true
@@ -277,3 +287,17 @@ const promptInstall = async (): Promise<boolean> => {
277287

278288
return install;
279289
};
290+
291+
const promptImportAlias = async (): Promise<string> => {
292+
const { importAlias } = await inquirer.prompt<Pick<CliFlags, "importAlias">>({
293+
name: "importAlias",
294+
type: "input",
295+
message: "What import alias would you like configured?",
296+
default: defaultOptions.flags.importAlias,
297+
transformer: (input: string) => {
298+
return input.trim();
299+
},
300+
});
301+
302+
return importAlias;
303+
};

Diff for: cli/src/helpers/createProject.ts

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ interface CreateProjectOptions {
99
projectName: string;
1010
packages: PkgInstallerMap;
1111
noInstall: boolean;
12+
importAlias: string;
1213
}
1314

1415
export const createProject = async ({

Diff for: cli/src/helpers/setImportAlias.ts

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import fs from "fs";
2+
import path from "path";
3+
4+
function replaceTextInFiles(
5+
directoryPath: string,
6+
search: string,
7+
replacement: string,
8+
): void {
9+
const files = fs.readdirSync(directoryPath);
10+
11+
files.forEach((file) => {
12+
const filePath = path.join(directoryPath, file);
13+
if (fs.statSync(filePath).isDirectory()) {
14+
replaceTextInFiles(filePath, search, replacement);
15+
} else {
16+
const data = fs.readFileSync(filePath, "utf8");
17+
const updatedData = data.replace(new RegExp(search, "g"), replacement);
18+
fs.writeFileSync(filePath, updatedData, "utf8");
19+
}
20+
});
21+
}
22+
23+
export const setImportAlias = async (
24+
projectDir: string,
25+
importAlias: string,
26+
) => {
27+
const normalizedImportAlias = importAlias
28+
.replace(/\*/g, "") // remove any wildcards (~/* -> ~/)
29+
.replace(/[^\/]$/, "$&/"); // ensure trailing slash (@ -> ~/)
30+
31+
// update import alias in any files if not using the default
32+
replaceTextInFiles(projectDir, `~/`, normalizedImportAlias);
33+
};

Diff for: cli/src/index.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import fs from "fs-extra";
66
import { runCli } from "~/cli/index.js";
77
import { createProject } from "~/helpers/createProject.js";
88
import { initializeGit } from "~/helpers/git.js";
9+
import { setImportAlias } from "~/helpers/setImportAlias.js";
910
import { logNextSteps } from "~/helpers/logNextSteps.js";
1011
import { buildPkgInstallerMap } from "~/installers/index.js";
1112
import { logger } from "~/utils/logger.js";
@@ -32,7 +33,7 @@ const main = async () => {
3233
const {
3334
appName,
3435
packages,
35-
flags: { noGit, noInstall },
36+
flags: { noGit, noInstall, importAlias },
3637
} = await runCli();
3738

3839
const usePackages = buildPkgInstallerMap(packages);
@@ -43,6 +44,7 @@ const main = async () => {
4344
const projectDir = await createProject({
4445
projectName: appDir,
4546
packages: usePackages,
47+
importAlias: importAlias,
4648
noInstall,
4749
});
4850

@@ -56,6 +58,11 @@ const main = async () => {
5658
spaces: 2,
5759
});
5860

61+
// update import alias in any generated files if not using the default
62+
if (importAlias !== "~/") {
63+
await setImportAlias(projectDir, importAlias);
64+
}
65+
5966
if (!noInstall) {
6067
await installDependencies({ projectDir });
6168
}

Diff for: cli/template/base/src/pages/_app.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { type AppType } from "next/dist/shared/lib/utils";
22

3-
import "../styles/globals.css";
3+
import "~/styles/globals.css";
44

55
const MyApp: AppType = ({ Component, pageProps }) => {
66
return <Component {...pageProps} />;

Diff for: cli/template/base/tsconfig.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@
1515
"isolatedModules": true,
1616
"jsx": "preserve",
1717
"incremental": true,
18-
"noUncheckedIndexedAccess": true
18+
"noUncheckedIndexedAccess": true,
19+
"baseUrl": ".",
20+
"paths": {
21+
"~/*": ["./src/*"]
22+
}
1923
},
2024
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.cjs", "**/*.mjs"],
2125
"exclude": ["node_modules"]

Diff for: cli/template/extras/src/pages/_app/with-auth-trpc.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import { type AppType } from "next/app";
22
import { type Session } from "next-auth";
33
import { SessionProvider } from "next-auth/react";
44

5-
import { api } from "../utils/api";
5+
import { api } from "~/utils/api";
66

7-
import "../styles/globals.css";
7+
import "~/styles/globals.css";
88

99
const MyApp: AppType<{ session: Session | null }> = ({
1010
Component,

Diff for: cli/template/extras/src/pages/_app/with-auth.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { type AppType } from "next/app";
22
import { type Session } from "next-auth";
33
import { SessionProvider } from "next-auth/react";
44

5-
import "../styles/globals.css";
5+
import "~/styles/globals.css";
66

77
const MyApp: AppType<{ session: Session | null }> = ({
88
Component,

Diff for: cli/template/extras/src/pages/_app/with-trpc.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { type AppType } from "next/app";
22

3-
import { api } from "../utils/api";
3+
import { api } from "~/utils/api";
44

5-
import "../styles/globals.css";
5+
import "~/styles/globals.css";
66

77
const MyApp: AppType = ({ Component, pageProps }) => {
88
return <Component {...pageProps} />;
+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
import NextAuth from "next-auth";
2-
import { authOptions } from "../../../server/auth";
2+
import { authOptions } from "~/server/auth";
33

44
export default NextAuth(authOptions);

Diff for: cli/template/extras/src/pages/api/trpc/[trpc].ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { createNextApiHandler } from "@trpc/server/adapters/next";
22

3-
import { env } from "../../../env.mjs";
4-
import { createTRPCContext } from "../../../server/api/trpc";
5-
import { appRouter } from "../../../server/api/root";
3+
import { env } from "~/env.mjs";
4+
import { createTRPCContext } from "~/server/api/trpc";
5+
import { appRouter } from "~/server/api/root";
66

77
// export API handler
88
export default createNextApiHandler({

Diff for: cli/template/extras/src/pages/index/with-auth-trpc-tw.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import Head from "next/head";
33
import Link from "next/link";
44
import { signIn, signOut, useSession } from "next-auth/react";
55

6-
import { api } from "../utils/api";
6+
import { api } from "~/utils/api";
77

88
const Home: NextPage = () => {
99
const hello = api.example.hello.useQuery({ text: "from tRPC" });

Diff for: cli/template/extras/src/pages/index/with-auth-trpc.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import Head from "next/head";
44
import Link from "next/link";
55
import { signIn, signOut, useSession } from "next-auth/react";
66

7-
import { api } from "../utils/api";
7+
import { api } from "~/utils/api";
88

99
const Home: NextPage = () => {
1010
const hello = api.example.hello.useQuery({ text: "from tRPC" });

Diff for: cli/template/extras/src/pages/index/with-trpc-tw.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { type NextPage } from "next";
22
import Head from "next/head";
33
import Link from "next/link";
44

5-
import { api } from "../utils/api";
5+
import { api } from "~/utils/api";
66

77
const Home: NextPage = () => {
88
const hello = api.example.hello.useQuery({ text: "from tRPC" });

Diff for: cli/template/extras/src/pages/index/with-trpc.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { type NextPage } from "next";
33
import Head from "next/head";
44
import Link from "next/link";
55

6-
import { api } from "../utils/api";
6+
import { api } from "~/utils/api";
77

88
const Home: NextPage = () => {
99
const hello = api.example.hello.useQuery({ text: "from tRPC" });

Diff for: cli/template/extras/src/server/api/root.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { createTRPCRouter } from "./trpc";
2-
import { exampleRouter } from "./routers/example";
1+
import { createTRPCRouter } from "~/server/api/trpc";
2+
import { exampleRouter } from "~/server/api/routers/example";
33

44
/**
55
* This is the primary router for your server.

Diff for: cli/template/extras/src/server/api/routers/example/base.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { z } from "zod";
22

3-
import { createTRPCRouter, publicProcedure } from "../trpc";
3+
import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";
44

55
export const exampleRouter = createTRPCRouter({
66
hello: publicProcedure

Diff for: cli/template/extras/src/server/api/routers/example/with-auth-prisma.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import { z } from "zod";
22

3-
import { createTRPCRouter, publicProcedure, protectedProcedure } from "../trpc";
3+
import {
4+
createTRPCRouter,
5+
publicProcedure,
6+
protectedProcedure,
7+
} from "~/server/api/trpc";
48

59
export const exampleRouter = createTRPCRouter({
610
hello: publicProcedure

Diff for: cli/template/extras/src/server/api/routers/example/with-auth.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import { z } from "zod";
22

3-
import { createTRPCRouter, publicProcedure, protectedProcedure } from "../trpc";
3+
import {
4+
createTRPCRouter,
5+
publicProcedure,
6+
protectedProcedure,
7+
} from "~/server/api/trpc";
48

59
export const exampleRouter = createTRPCRouter({
610
hello: publicProcedure

Diff for: cli/template/extras/src/server/api/routers/example/with-prisma.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { z } from "zod";
22

3-
import { createTRPCRouter, publicProcedure } from "../trpc";
3+
import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";
44

55
export const exampleRouter = createTRPCRouter({
66
hello: publicProcedure

Diff for: cli/template/extras/src/server/api/trpc/with-auth-prisma.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
import { type CreateNextContextOptions } from "@trpc/server/adapters/next";
1919
import { type Session } from "next-auth";
2020

21-
import { getServerAuthSession } from "../auth";
22-
import { prisma } from "../db";
21+
import { getServerAuthSession } from "~/server/auth";
22+
import { prisma } from "~/server/db";
2323

2424
type CreateContextOptions = {
2525
session: Session | null;

Diff for: cli/template/extras/src/server/api/trpc/with-auth.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import { type CreateNextContextOptions } from "@trpc/server/adapters/next";
1919
import { type Session } from "next-auth";
2020

21-
import { getServerAuthSession } from "../auth";
21+
import { getServerAuthSession } from "~/server/auth";
2222

2323
type CreateContextOptions = {
2424
session: Session | null;

Diff for: cli/template/extras/src/server/api/trpc/with-prisma.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
*/
1818
import { type CreateNextContextOptions } from "@trpc/server/adapters/next";
1919

20-
import { prisma } from "../db";
20+
import { prisma } from "~/server/db";
2121

2222
type CreateContextOptions = Record<string, never>;
2323

Diff for: cli/template/extras/src/server/auth/base.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
type DefaultSession,
66
} from "next-auth";
77
import DiscordProvider from "next-auth/providers/discord";
8-
import { env } from "../env.mjs";
8+
import { env } from "~/env.mjs";
99

1010
/**
1111
* Module augmentation for `next-auth` types.

Diff for: cli/template/extras/src/server/auth/with-prisma.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import {
66
} from "next-auth";
77
import DiscordProvider from "next-auth/providers/discord";
88
import { PrismaAdapter } from "@next-auth/prisma-adapter";
9-
import { env } from "../env.mjs";
10-
import { prisma } from "./db";
9+
import { env } from "~/env.mjs";
10+
import { prisma } from "~/server/db";
1111

1212
/**
1313
* Module augmentation for `next-auth` types.

Diff for: cli/template/extras/src/server/db.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { PrismaClient } from "@prisma/client";
22

3-
import { env } from "../env.mjs";
3+
import { env } from "~/env.mjs";
44

55
const globalForPrisma = globalThis as unknown as { prisma: PrismaClient };
66

Diff for: cli/template/extras/src/utils/api.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { createTRPCNext } from "@trpc/next";
1010
import { type inferRouterInputs, type inferRouterOutputs } from "@trpc/server";
1111
import superjson from "superjson";
1212

13-
import { type AppRouter } from "../server/api/root";
13+
import { type AppRouter } from "~/server/api/root";
1414

1515
const getBaseUrl = () => {
1616
if (typeof window !== "undefined") return ""; // browser should use relative url

0 commit comments

Comments
 (0)