0.0.14 • Published 1 year ago

@mclfy82/nextjs-subzero v0.0.14

Weekly downloads
-
License
-
Repository
-
Last release
1 year ago

NextJs Subzero (Nextjs App Router ^13)

Cat

1 Install


  yarn add @mclfy82/nextjs-subzero 

2 Setup


Route setup

Add to src/app/api/graphql/route.ts

import { graphqlRoute } from "@mclfy82/nextjs-subzero";

const GET = grap^qlRoute.GET
const POST = graphqlRoute.POST
export { GET, POST };

Add to src/app/api/auth/[...nextauth]/route.ts

import { authRoute } from "@mclfy82/nextjs-subzero";

const GET = authRoute.GET
const POST = authRoute.POST
export { GET, POST };

NextJs .env setup

Add to .env

NODE_ENV=development
NEXT_PUBLIC_APP_URL=http://localhost:3000
ALLOW_ORIGIN=http://localhost:3000
#db
DATABASE_URL=           
#auth
NEXTAUTH_URL=${NEXT_PUBLIC_APP_URL}
NEXTAUTH_SECRET=pS9TmIUY0lyQyjK4XzcnMVXyqLDm8dhoYKoJiyF1Jqs=
#graphql
NEXT_PUBLIC_GRAPHQL_URL=http://localhost:3000/api/graphql
#mail
MAIL_PORT=
MAIL_HOST=
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_FROM_EMAIL=
MAIL_ENCRYPTION=

NextJs config setup

Add to next.config.js

const { withSubzero } = require("./subzero/lib/webpackConfig");

/**
 * @type {import('next').NextConfig}
 * */
module.exports = {
  webpack: (config, { isServer }) => {
    return withSubzero(config, isServer);
  }
};

Backend API Workflow


Step 1 - create a model using prisma

Under: projectRoot > prisma > schema.prisma

Modify the documente has follow:

 // existing model
model User {
  // existing fields
  ...
  // new one-to-one relation
  Profile Profile?
}

  // new model
model Profile {
  id     String  @id @default(cuid())
  image  String? // optional
  // one-to-one relation
  userId String  @unique
  User   User    @relation(fields: [userId], references: [id], onDelete: Cascade)
}

After the modification migrate the database by running:

yarn run seed

Step 2 - declare the model in graphql

Under: projectRoot > graphql > schemas

Create a file Profile.graphql

type Profile {
  id:    String!  
  image: String # optional
}
input ProfileInput {
  image: String  # optional
}
type ProfileResponse {
  profile: Profile
}
type Mutation {
  updateProfile(input: ProfileInput): ProfileResponse
}
type Query {
  getProfile: ProfileResponse
}

run: yarn run codegen

Step 3 - define the model API on the server

Under: projectRoot > graphql > resolvers

create a operation file name Profiles.ts

import { MutationUpdateProfileImageArgs, ProfileResponse } from '@/graphql/__generated__/apollo';
import prisma from "@backend/client/prismaClient";
import { GraphqlContext } from "@backend/globalTypes/graphql";

export default {
    Mutation: {
        async updateProfileImage(_parent: any, args: MutationUpdateProfileImageArgs, context: GraphqlContext) {
            const { user: authUser } = context
            const profile = await prisma.profile.findUnique({
                where: {
                    userId: authUser?.id
                }
            })
            const updatedProfile = await prisma.profile.update({
                where: {
                    id: profile?.id
                },
                data: {
                    image: args.input?.image
                }
            })
            return updatedProfile

        },
    },
    Query: {
        async getProfile(_parent: any, args: unknown, context: GraphqlContext): Promise<ProfileResponse> {
            const { user: authUser } = context
            return {
                profile: await prisma.profile.findUniqueOrThrow({
                    where: {
                        userId: authUser?.id
                    }
                })
            }
        }
    }
}

Step 4 - declare your API in the client

export const GetProfile = gql`
  query getProfile {
    getProfile {
      profile {
          image
      }
    }
  }
`;

Step 5 - consume your API in the client

In a page.ts file use the useGetProfileQuery and useUpdateProfileMutation

"use client";
import { 
  useGetProfileQuery, 
  useUpdateProfileMutation 
} from "@/graphql/__generated__/reactQuery";

export default function Home() {
  const session = useSession()
  const { isLoading, data } = useGetProfileQuery();

  if (session.status === authenticated) return <p>Please authenticate...</p>;  
  if (isLoading) return <p>loading...</p>;
  return <div>data: {JSON.stringify(data?.profile)}</div>;
}

3 Backend API Workflow


Step 1 - create a model using prisma

Under: projectRoot > prisma > schema.prisma

Modify the documente has follow:

 // existing model
model User {
  // existing fields
  ...
  // new one-to-one relation
  Profile Profile?
}

  // new model
model Profile {
  id     String  @id @default(cuid())
  image  String? // optional
  // one-to-one relation
  userId String  @unique
  User   User    @relation(fields: [userId], references: [id], onDelete: Cascade)
}

After the modification migrate the database by running:

yarn run seed

Step 2 - declare the model in graphql

Under: projectRoot > graphql > schemas

Create a file Profile.graphql

type Profile {
  id:    String!  
  image: String # optional
}
input ProfileInput {
  image: String  # optional
}
type ProfileResponse {
  profile: Profile
}
type Mutation {
  updateProfile(input: ProfileInput): ProfileResponse
}
type Query {
  getProfile: ProfileResponse
}

run: yarn run codegen

Step 3 - define the model API on the server

Under: projectRoot > graphql > resolvers

create a operation file name Profiles.ts

import { MutationUpdateProfileImageArgs, ProfileResponse } from '@/graphql/__generated__/apollo';
import prisma from "@backend/client/prismaClient";
import { GraphqlContext } from "@backend/globalTypes/graphql";

export default {
    Mutation: {
        async updateProfileImage(_parent: any, args: MutationUpdateProfileImageArgs, context: GraphqlContext) {
            const { user: authUser } = context
            const profile = await prisma.profile.findUnique({
                where: {
                    userId: authUser?.id
                }
            })
            const updatedProfile = await prisma.profile.update({
                where: {
                    id: profile?.id
                },
                data: {
                    image: args.input?.image
                }
            })
            return updatedProfile

        },
    },
    Query: {
        async getProfile(_parent: any, args: unknown, context: GraphqlContext): Promise<ProfileResponse> {
            const { user: authUser } = context
            return {
                profile: await prisma.profile.findUniqueOrThrow({
                    where: {
                        userId: authUser?.id
                    }
                })
            }
        }
    }
}

Step 4 - declare your API in the client

export const GetProfile = gql`
  query getProfile {
    getProfile {
      profile {
          image
      }
    }
  }
`;

Step 5 - consume your API in the client

In a page.ts file use the useGetProfileQuery and useUpdateProfileMutation

"use client";
import { 
  useGetProfileQuery, 
  useUpdateProfileMutation 
} from "@/graphql/__generated__/reactQuery";

export default function Home() {
  const session = useSession()
  const { isLoading, data } = useGetProfileQuery();

  if (session.status === authenticated) return <p>Please authenticate...</p>;  
  if (isLoading) return <p>loading...</p>;
  return <div>data: {JSON.stringify(data?.profile)}</div>;
}