Computing Atman
Setting Up Nx Nestjs Mongodb Mongoose Integration - Part 3
🥭

Setting Up Nx Nestjs Mongodb Mongoose Integration - Part 3

Part 3 of Nx Nest.js GraphQL Integration - Install packages, update configs, generate GraphQL client for seamless integration. Enhance data management and scalability. Congrats on completing this guide to harmonious Nx, Nest.js, GraphQL integration! Stay tuned for more tutorials.

2023/11/19
2023/12/02

Introduction

Welcome to the third part of our Nx Nest.js GraphQL Integration series, where we enhance our project by incorporating GraphQL. Follow these steps to seamlessly install essential packages, update the app.module.ts file, generate the data-access-graphql project, and utilize GraphQL code generation. We'll guide you through creating a GraphQL client and demonstrate its usage in a Next.js web application.

Reference URL

Engilaboo Next.js GraphQL Tutorial

Install Packages

npm i @graphql-codegen/typed-document-node @graphql-codegen/cli @graphql-codegen/typescript-operations @apollo/client @graphql-codegen/client-preset

Update app.module.ts in Nest.js Project

Add the following code:

@Module({
  imports: [
    ServeStaticModule.forRoot({
      rootPath: join(__dirname, '..', 'web/.next'),
      exclude: ['/api/*', '/api/graphql']
    }),
    GraphQLModule.forRoot<ApolloDriverConfig>({
      driver: ApolloDriver,
      path: '/api/graphql',
      autoSchemaFile: path.join(__dirname, './autogenerated-schema.gql')
    }),

By doing so, the autogenerated-schema.gql is created in the dist/apps/api folder after building the API.

Generate data-access-graphql Project

npx nx generate @nx/js:library data-access-graphql --directory=libs/web/data-access-graphql --importPath=@libs/web/data-access-graphql --tags=scope:web --bundler=swc
 
✔ Which unit test runner would you like to use? · none

Create codegen.yml

tools/graphql-codegen/codegen.ts

import type { CodegenConfig } from '@graphql-codegen/cli';
 
const codegenConfig: CodegenConfig = {
  overwrite: true,
  schema: 'dist/apps/api/autogenerated-schema.gql',
  documents: ['apps/web/**/*.graphql', 'libs/**/*.graphql'],
  generates: {
    'libs/web/data-access-graphql/src/lib/__generated__/': {
      preset: 'client',
      plugins: [
        {
          // branded type for custom Scalar
          add: {
            content: `export type DateString = string & { readonly __brand: unique symbol }`
          }
        }
      ],
      config: {
        strictScalars: true,
        useTypeImports: true,
        skipTypename: true,
        arrayInputCoercion: true,
        avoidOptionals: {
          field: true,
          inputValue: false,
          object: true,
          defaultValue: false
        },
        scalars: {
          Date: 'DateString'
        },
        enumsAsTypes: true
      }
    }
  }
};
 
export default codegenConfig;

Run Codegen

Add script to package.json

   "scripts": {
    "start:gql:watch": "graphql-codegen --config tools/graphql-codegen/codegen.ts --watch",

Create Client for Web

  1. Create apollo-client.ts

apps/web/lib/apollo-client.ts

In this case, apps/web is a Next.js project.

import { NEXT_PUBLIC_API_GQL_URL } from '@/config/index';
import { ApolloClient, InMemoryCache } from '@apollo/client';
 
// If env.NEXT_PUBLIC_API_GQL_URL is undefined, throw exeption.
if (!NEXT_PUBLIC_API_GQL_URL) {
  throw new Error('NEXT_PUBLIC_API_GQL_URL is undefined');
}
 
export const apolloClient = new ApolloClient({
  uri: NEXT_PUBLIC_API_GQL_URL,
  cache: new InMemoryCache(),
  credentials: 'include'
});
  1. Create ApolloProvider

apps/web/lib/apollo-client.ts

'use client';
 
import { apolloClient } from '@/lib/apollo-client';
import { ApolloProvider as Apollo } from '@apollo/client';
 
const ApolloProvider = ({ children }: React.PropsWithChildren) => {
  return <Apollo client={apolloClient}>{children}</Apollo>;
};
 
export default ApolloProvider;
  1. Update tsconfig.base.json
    "paths": {
      "@/lib/*": [
        "apps/web/lib/*"
      ],
  1. Set ApolloProvider

apps/web/app/layout.tsx

import ApolloProvider from '@/components/providers/ApolloProvider';
...
 
export default async function RootLayout({ children }: { children: ReactNode }) {
  return (
    <html suppressHydrationWarning>
      <head>
        ...
      </head>
 
      <body className="overflow-x-hidden bg-white text-black antialiased dark:bg-gray-900 dark:text-white">
        <ApolloProvider>
          ...
        </ApolloProvider>
      </body>
    </html>
  );
}

Use graphql

Example:

  1. Create graphql file

todo.graphql

query getSampleTodos {
  sampleTodos {
    _id
    content
    editing
    completed
  }
}
  1. Use useQuery
import { useQuery } from '@apollo/client';
import { GetSampleTodosDocument } from '@libs/web/data-access-graphql';
 
export default async function page() {
  const { data, loading, error } = useQuery(GetSampleTodosDocument);
 
  return <div>{data.GetSampleTodosDocument.map((x) => x._id)}</div>;
}

Congratulations! You've successfully configured Nx, Nest.js, and GraphQL in a harmonious integration. This series has empowered you to efficiently manage and query data, making your application more robust and scalable. Stay tuned for more insightful tutorials and happy coding!

The first part is here.

Setting Up Nx Nestjs Mongodb Mongoose Integration - Part 1