Skip to content

Commit

Permalink
fix: update to next13 (#657)
Browse files Browse the repository at this point in the history
* update some stuff

* prettier

* apply some install flags

* properly apply flags

* formatting

* refactor

* fix flags

* Update cli/template/addons/next-auth/_npmrc

Co-authored-by: Julius Marminge <[email protected]>

* Create fluffy-masks-explain.md

Co-authored-by: Christopher Ehrlich <[email protected]>
  • Loading branch information
juliusmarminge and c-ehrlich authored Oct 29, 2022
1 parent 4bde030 commit f1673eb
Show file tree
Hide file tree
Showing 36 changed files with 165 additions and 128 deletions.
5 changes: 5 additions & 0 deletions .changeset/fluffy-masks-explain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"create-t3-app": minor
---

feat: update dependency Next.js to 13
45 changes: 32 additions & 13 deletions cli/src/helpers/installDependencies.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,51 @@
import chalk from "chalk";
import { execa } from "execa";
import ora from "ora";
import { PkgInstallerMap } from "~/installers/index.js";
import { getUserPkgManager } from "~/utils/getUserPkgManager.js";
import { logger } from "~/utils/logger.js";

export const installDependencies = async (projectDir: string) => {
type Options = {
projectDir: string;
packages: PkgInstallerMap;
};

export const installDependencies = async ({
projectDir,
packages,
}: Options) => {
logger.info("Installing dependencies...");
const pkgManager = getUserPkgManager();
const spinner = ora(`Running ${pkgManager} install...\n`).start();
let flags: string[] = [];

// FIXME: temp fix for next-auth with node 18
// FIXME: temp fix for NextAuth.js with node 18/19
// see: https://github.com/nextauthjs/next-auth/issues/4575
if (
process.versions.node.startsWith("18") ||
process.versions.node.startsWith("19")
) {
if (pkgManager === "yarn") {
await execa(pkgManager, ["add", "--ignore-engines", "true"], {
cwd: projectDir,
});
} else {
await execa(pkgManager, ["install", "--engine-strict", "false"], {
cwd: projectDir,
});
}
} else {
await execa(pkgManager, ["install"], { cwd: projectDir });
flags = [
...flags,
...(pkgManager === "yarn"
? ["--ignore-engines", "true"]
: ["--engine-strict", "false"]),
];
}

// FIXME: temp fix for NextAuth.js with Next.js 13
if (packages.nextAuth.inUse) {
flags = [
...flags,
...(pkgManager === "pnpm"
? ["--strict-peer-dependencies", "false"]
: pkgManager === "npm"
? ["--legacy-peer-deps", "true"]
: []),
];
}

await execa(pkgManager, ["install", ...flags], { cwd: projectDir });

spinner.succeed(chalk.green("Successfully installed dependencies!\n"));
};
2 changes: 1 addition & 1 deletion cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const main = async () => {
});

if (!noInstall) {
await installDependencies(projectDir);
await installDependencies({ projectDir, packages: usePackages });
}

if (!noGit) {
Expand Down
7 changes: 6 additions & 1 deletion cli/template/addons/next-auth/_npmrc
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
engine-strict=false
# next-auth not officially Node 18 compatible
engine-strict=false

# next-auth currently on Next.js 12
strict-peer-dependencies=false
legacy-peer-deps=true
4 changes: 2 additions & 2 deletions cli/template/addons/next-auth/api-handler-prisma.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import NextAuth, { type NextAuthOptions } from "next-auth";
import DiscordProvider from "next-auth/providers/discord";

// Prisma adapter for NextAuth, optional and can be removed
import { PrismaAdapter } from "@next-auth/prisma-adapter";
import { prisma } from "../../../server/db/client";

import { env } from "../../../env/server.mjs";
import { prisma } from "../../../server/db/client";

export const authOptions: NextAuthOptions = {
// Include user.id on session
Expand Down
1 change: 1 addition & 0 deletions cli/template/addons/next-auth/api-handler.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import NextAuth, { type NextAuthOptions } from "next-auth";
import DiscordProvider from "next-auth/providers/discord";

import { env } from "../../../env/server.mjs";

export const authOptions: NextAuthOptions = {
Expand Down
13 changes: 7 additions & 6 deletions cli/template/addons/next-auth/get-server-auth-session.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
// Wrapper for unstable_getServerSession https://next-auth.js.org/configuration/nextjs

import type { GetServerSidePropsContext } from "next";
import { type GetServerSidePropsContext } from "next";
import { unstable_getServerSession } from "next-auth";
import { authOptions as nextAuthOptions } from "../../pages/api/auth/[...nextauth]";
import { authOptions } from "../../pages/api/auth/[...nextauth]";

// Next API route example - /pages/api/restricted.ts
/**
* Wrapper for unstable_getServerSession https://next-auth.js.org/configuration/nextjs
* See example usage in trpc createContext or the restricted API route
*/
export const getServerAuthSession = async (ctx: {
req: GetServerSidePropsContext["req"];
res: GetServerSidePropsContext["res"];
}) => {
return await unstable_getServerSession(ctx.req, ctx.res, nextAuthOptions);
return await unstable_getServerSession(ctx.req, ctx.res, authOptions);
};
2 changes: 1 addition & 1 deletion cli/template/addons/next-auth/next-auth.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DefaultSession } from "next-auth";
import { type DefaultSession } from "next-auth";

declare module "next-auth" {
/**
Expand Down
3 changes: 1 addition & 2 deletions cli/template/addons/next-auth/restricted.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Example of a restricted endpoint that only authenticated users can access from https://next-auth.js.org/getting-started/example
import { type NextApiRequest, type NextApiResponse } from "next";

import { NextApiRequest, NextApiResponse } from "next";
import { getServerAuthSession } from "../../server/common/get-server-auth-session";

const restricted = async (req: NextApiRequest, res: NextApiResponse) => {
Expand Down
2 changes: 1 addition & 1 deletion cli/template/addons/prisma/client.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// src/server/db/client.ts
import { PrismaClient } from "@prisma/client";

import { env } from "../../env/server.mjs";

declare global {
Expand Down
4 changes: 2 additions & 2 deletions cli/template/addons/prisma/sample-api.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// src/pages/api/examples.ts
import type { NextApiRequest, NextApiResponse } from "next";
import { type NextApiRequest, type NextApiResponse } from "next";

import { prisma } from "../../server/db/client";

const examples = async (req: NextApiRequest, res: NextApiResponse) => {
Expand Down
6 changes: 3 additions & 3 deletions cli/template/addons/trpc/api-handler.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// src/pages/api/trpc/[trpc].ts
import { createNextApiHandler } from "@trpc/server/adapters/next";
import { appRouter } from "../../../server/trpc/router/_app";
import { createContext } from "../../../server/trpc/context";

import { env } from "../../../env/server.mjs";
import { createContext } from "../../../server/trpc/context";
import { appRouter } from "../../../server/trpc/router/_app";

// export API handler
export default createNextApiHandler({
Expand Down
2 changes: 0 additions & 2 deletions cli/template/addons/trpc/app-router.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
// src/server/router/_app.ts
import { router } from "../trpc";

import { exampleRouter } from "./example";

export const appRouter = router({
Expand Down
3 changes: 1 addition & 2 deletions cli/template/addons/trpc/auth-app-router.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// src/server/trpc/router/_app.ts
import { router } from "../trpc";
import { exampleRouter } from "./example";
import { authRouter } from "./auth";
import { exampleRouter } from "./example";

export const appRouter = router({
example: exampleRouter,
Expand Down
13 changes: 7 additions & 6 deletions cli/template/addons/trpc/auth-context.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
// src/server/router/context.ts
import type { inferAsyncReturnType } from "@trpc/server";
import type { CreateNextContextOptions } from "@trpc/server/adapters/next";
import type { Session } from "next-auth";
import { type inferAsyncReturnType } from "@trpc/server";
import { type CreateNextContextOptions } from "@trpc/server/adapters/next";
import { type Session } from "next-auth";

import { getServerAuthSession } from "../common/get-server-auth-session";

type CreateContextOptions = {
session: Session | null;
};

/** Use this helper for:
* - testing, where we dont have to Mock Next.js' req/res
* - trpc's `createSSGHelpers` where we don't have req/res
* - testing, so we dont have to mock Next.js' req/res
* - trpc's `createSSGHelpers` where we don't have req/res
* @see https://beta.create.t3.gg/en/usage/trpc#-servertrpccontextts
**/
export const createContextInner = async (opts: CreateContextOptions) => {
return {
Expand Down
9 changes: 5 additions & 4 deletions cli/template/addons/trpc/auth-prisma-context.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// src/server/router/context.ts
import type { inferAsyncReturnType } from "@trpc/server";
import type { CreateNextContextOptions } from "@trpc/server/adapters/next";
import type { Session } from "next-auth";
import { type inferAsyncReturnType } from "@trpc/server";
import { type CreateNextContextOptions } from "@trpc/server/adapters/next";
import { type Session } from "next-auth";

import { getServerAuthSession } from "../common/get-server-auth-session";
import { prisma } from "../db/client";

Expand All @@ -12,6 +12,7 @@ type CreateContextOptions = {
/** Use this helper for:
* - testing, so we dont have to mock Next.js' req/res
* - trpc's `createSSGHelpers` where we don't have req/res
* @see https://beta.create.t3.gg/en/usage/trpc#-servertrpccontextts
**/
export const createContextInner = async (opts: CreateContextOptions) => {
return {
Expand Down
3 changes: 2 additions & 1 deletion cli/template/addons/trpc/auth-server-utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { initTRPC, TRPCError } from "@trpc/server";
import type { Context } from "./context";
import superjson from "superjson";

import { type Context } from "./context";

const t = initTRPC.context<Context>().create({
transformer: superjson,
errorFormatter({ shape }) {
Expand Down
14 changes: 6 additions & 8 deletions cli/template/addons/trpc/base-context.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
// src/server/router/context.ts
import * as trpc from "@trpc/server";
import * as trpcNext from "@trpc/server/adapters/next";
import { type inferAsyncReturnType } from "@trpc/server";
import { type CreateNextContextOptions } from "@trpc/server/adapters/next";

/**
* Replace this with an object if you want to pass things to createContextInner
*/
type CreateContextOptions = Record<string, never>;

/** Use this helper for:
* - testing, where we dont have to Mock Next.js' req/res
* - testing, so we dont have to mock Next.js' req/res
* - trpc's `createSSGHelpers` where we don't have req/res
* @see https://beta.create.t3.gg/en/usage/trpc#-servertrpccontextts
**/
export const createContextInner = async (opts: CreateContextOptions) => {
return {};
Expand All @@ -19,10 +19,8 @@ export const createContextInner = async (opts: CreateContextOptions) => {
* This is the actual context you'll use in your router
* @link https://trpc.io/docs/context
**/
export const createContext = async (
opts: trpcNext.CreateNextContextOptions,
) => {
export const createContext = async (opts: CreateNextContextOptions) => {
return await createContextInner({});
};

export type Context = trpc.inferAsyncReturnType<typeof createContext>;
export type Context = inferAsyncReturnType<typeof createContext>;
3 changes: 2 additions & 1 deletion cli/template/addons/trpc/example-prisma-router.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { router, publicProcedure } from "../trpc";
import { z } from "zod";

import { router, publicProcedure } from "../trpc";

export const exampleRouter = router({
hello: publicProcedure
.input(z.object({ text: z.string().nullish() }).nullish())
Expand Down
3 changes: 2 additions & 1 deletion cli/template/addons/trpc/example-router.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { router, publicProcedure } from "../trpc";
import { z } from "zod";

import { router, publicProcedure } from "../trpc";

export const exampleRouter = router({
hello: publicProcedure
.input(z.object({ text: z.string().nullish() }).nullish())
Expand Down
13 changes: 7 additions & 6 deletions cli/template/addons/trpc/prisma-context.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// src/server/router/context.ts
import type { inferAsyncReturnType } from "@trpc/server";
import type { CreateNextContextOptions } from "@trpc/server/adapters/next";
import { type inferAsyncReturnType } from "@trpc/server";
import { type CreateNextContextOptions } from "@trpc/server/adapters/next";

import { prisma } from "../db/client";

/**
Expand All @@ -9,9 +9,10 @@ import { prisma } from "../db/client";
type CreateContextOptions = Record<string, never>;

/** Use this helper for:
* - testing, where we dont have to Mock Next.js' req/res
* - trpc's `createSSGHelpers` where we don't have req/res
*/
* - testing, so we dont have to mock Next.js' req/res
* - trpc's `createSSGHelpers` where we don't have req/res
* @see https://beta.create.t3.gg/en/usage/trpc#-servertrpccontextts
**/
export const createContextInner = async (opts: CreateContextOptions) => {
return {
prisma,
Expand Down
3 changes: 2 additions & 1 deletion cli/template/addons/trpc/server-utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { initTRPC } from "@trpc/server";
import type { Context } from "./context";
import superjson from "superjson";

import { type Context } from "./context";

const t = initTRPC.context<Context>().create({
transformer: superjson,
errorFormatter({ shape }) {
Expand Down
12 changes: 5 additions & 7 deletions cli/template/addons/trpc/utils.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
// src/utils/trpc.ts
import superjson from "superjson";

import { httpBatchLink, loggerLink } from "@trpc/client";
import { createTRPCNext } from "@trpc/next";
import type { GetInferenceHelpers } from "@trpc/server";
import { type GetInferenceHelpers } from "@trpc/server";
import superjson from "superjson";

import type { AppRouter } from "../server/trpc/router/_app";
import { type AppRouter } from "../server/trpc/router/_app";

const getBaseUrl = () => {
if (typeof window !== "undefined") return ""; // browser should use relative url
Expand Down Expand Up @@ -34,6 +32,6 @@ export const trpc = createTRPCNext<AppRouter>({

/**
* Inference helpers
* @example type HelloOutput = AppRouterTypes['example']['hello']['output']
* @example type HelloOutput = RouterTypes['example']['hello']['output']
**/
export type AppRouterTypes = GetInferenceHelpers<AppRouter>;
export type RouterTypes = GetInferenceHelpers<AppRouter>;
5 changes: 4 additions & 1 deletion cli/template/base/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,8 @@
"project": "./tsconfig.json"
},
"plugins": ["@typescript-eslint"],
"extends": ["next/core-web-vitals", "plugin:@typescript-eslint/recommended"]
"extends": ["next/core-web-vitals", "plugin:@typescript-eslint/recommended"],
"rules": {
"@typescript-eslint/consistent-type-imports": "warn"
}
}
26 changes: 7 additions & 19 deletions cli/template/base/next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,29 +1,17 @@
// @ts-check
/* run the build with this set to skip validation */
!process.env.SKIP_ENV_VALIDATION && (await import("./src/env/server.mjs"));

/**
* Don't be scared of the generics here.
* All they do is to give us autocompletion when using this.
*
* @template {import('next').NextConfig} T
* @param {T} config - A generic parameter that flows through to the return type
* @constraint {{import('next').NextConfig}}
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation.
* This is especially useful for Docker builds.
*/
function defineNextConfig(config) {
return config;
}
!process.env.SKIP_ENV_VALIDATION && (await import("./src/env/server.mjs"));

export default defineNextConfig({
/** @type {import("next").NextConfig} */
const config = {
reactStrictMode: true,
swcMinify: true,
/** Next.js i18n docs:
* @see https://nextjs.org/docs/advanced-features/i18n-routing
* Reference repo for i18n:
* @see https://github.com/juliusmarminge/t3-i18n
**/
i18n: {
locales: ["en"],
defaultLocale: "en",
},
});
};
export default config;
Loading

1 comment on commit f1673eb

@vercel
Copy link

@vercel vercel bot commented on f1673eb Oct 29, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.