@mclfy82/nextjs-subzero v0.0.14
NextJs Subzero (Nextjs App Router ^13)
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>;
}