I tried creating a Fullstack Web Application with TypeScript & GraphQL【 TodoList 】

## Technologies used
#### Backend：
- Typescript
- Node.js
- Express
- Apollo Server v4
- sqlite
- Prisma

#### Frontend:
- Typescript
- React
- Apollo Client
- Tailwindcss
- vite

## 1 - Project setup
① Create a project
```
mkdir <Project Name>
cd <Project Name>
npm init -y
```
② Use the workspace function
※　A function that manages multiple functions.
```
mkdir packages
```
③ Add code to package.json

```package.json
//省略
"license": "ISC",
  "workspaces": [
    "packages/*"
   ],
```
④ Create frontend and backend folders in packages folder

⑤ Open three terminals and rename them root, frontend, and backend.

⑥ Go to backend terminal
```
cd packages/backend/
npm init -y
```
⑦ Go to frontend terminal
```
cd packages/frontend/
npm create vite@latest . -- --template react-ts
```
⑧ Go to root terminal
```
npm i
```
⑨　Allow root to control forontend and backend

```root/package.json
//省略
"scripts": {
    "dev:front": "npm run dev -w frontend"
  },
```
```
npm run dev:front
```
⑩　Prepare typescript in backend

Create src folder and index.ts
```
npm i -DE typescript @types/node nodemon
touch backend
```
```backend/tsconfig.json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "outDir": "./dist",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "skipLibCheck": true,
    "moduleResolution": "NodeNext"
  }
}
```
```backend/package.json
//省略
"main": "index.js",
  "type": "module",
  "scripts": {
    "dev": "nodemon dist/index.js",
    "watch":"tsc --watch",
    "build":"tsc",
    "start": "node dist/index.js",
    "lint":"eslint --fix \"./src/**/*.{js,jsx,ts,tsx,json}\""
```
```
npm run lint
```
⑪　Allow root to control forontend and backend

```root/package.json
//省略
"scripts": {
    "build": "npm run build:back && npm run build:front",
    "build:back": "npm run build -w backend",
    "build:front": "npm run build -w frontend",
    "dev:back": "npm run dev -w backend",
    "watch:back": "npm run watch -w backend",
    "dev:front": "npm run dev -w frontend"
  },
```
```
npm run build
```

⑫ Add eslint to backend

```
npm i -ED eslint
npx eslint --init
```
※ shift + option + f (Run Prettier)
```backend/src/.eslintrc.cjs
//省略
extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:@typescript-eslint/recommended-requiring-type-checking',
  ],
//省略
 parserOptions: {
        sourceType: 'script',
        tsconfigRootDir: __dirname,//Add code
        project: ['tsconfig.eslint.json'],//Add code
      },
```
⑬　Add tsconfig.eslint.json to backend/src

```backend/src/tsconfig.eslint.json
{
  "extends": "./tsconfig.json",
  "include": ["src/**/*.ts", ".eslintrc.cjs"],
  "exclude": ["node_modules"]
}
```
※ shift + command + p (open command palette:Developer:Reload Window) 

⑭　Add eslint to frontend

```
npm i -ED eslint
npx eslint --init
npm i -ED eslint-plugin-react-hooks
```
```frontend/eslintrc.cjs
extends: [
    'eslint:recommended',
    'plugin:react/recommended',
    'plugin:react-hooks/recommended',//Add code
    'plugin:@typescript-eslint/recommended',
  ],

  //省略
 parserOptions: {
        sourceType: 'script',
        tsconfigRootDir: __dirname,//Add code
        project: ['tsconfig.eslint.json'],//Add code
      },
```

⑮　Add tsconfig.eslint.json to frontend/src

```frontend/src/tsconfig.eslint.json
{
  "extends": "./tsconfig.json",
  "include": ["src/**/*.ts", ".eslintrc.cjs"],
  "exclude": ["node_modules"]
}
```
## 2 - Launching a minimal Apollo server

① Enter the backend terminal and install the necessary libraries

```
npm i express graphql @apollo/server
npm i -ED @types/express
```

② Start up apollo server

```backend / src / index.ts
import http from 'http';

import { ApolloServer } from '@apollo/server';
import { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHttpServer';
import { expressMiddleware } from '@apollo/server/express4';
import express from 'express';
import { mergeResolvers, mergeTypeDefs } from '@graphql-tools/merge';

const typeDefs = `#graphql
    type Query {
    health: Boolean
}
`;

const resolvers = {
  Query: {
    health: async (_: any, args: any, context: MyContext, info: any) => {
      return true;
    },
  },
};

type MyContext = {
  req: express.Request;
  res: express.Response;
};

async function main() {
  const PORT = process.env.PORT || 5555;
  const app = express();

  const httpSever = http.createServer(app);
  const server = new ApolloServer<MyContext>({
    typeDefs: mergeTypeDefs([typeDefs]),
    resolvers: mergeResolvers([resolvers]),
    plugins: [ApolloServerPluginDrainHttpServer({ httpServer: httpSever })],
  });
  await server.start();
  app.use(express.json());
  app.use(
    '/graphql',
    expressMiddleware(server, {
      context: async ({ req, res }) => ({ req, res }),
    })
  );
  await new Promise<void>((resolve) => {
    httpSever.listen({ port: PORT }, resolve);
  });
  console.log(`server is up and running at http://localhost:{PORT}`);
}

main().catch((error) => {
  console.error(error);
  process.exit(1);
});
```

## 3 - Adding a Graphql code generator
① Create modules/root/greet/greet.typeDefs.ts for refactoring

```modules/root/greet/greetTypeDefs.ts
const typeDefs = `#graphql
    type Query {
    greet: String
}
`;
export default typeDefs;
```
② Create modules/root/greet/greet.resolversts.ts for refactoring
```modules/root/greet/greet.resolversts.ts 
import { MyContext } from '../../../types/graphql.js';

const resolvers = {
  Query: {
    health: async (_: any, args: any, context: MyContext, info: any) => {
      return true;
    },
  },
};

export default resolvers;
```

③ Create/types/graphql.ts
```types/graphql.ts
import express from 'express';

export type MyContext = {
  req: express.Request;
  res: express.Response;
};
```


④　Refactor backend/src/index.ts
```backend / src / index.ts
import http from 'http';

import { ApolloServer } from '@apollo/server';
import { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHttpServer';
import { expressMiddleware } from '@apollo/server/express4';
import express from 'express';
import { mergeResolvers, mergeTypeDefs } from '@graphql-tools/merge';
import { MyContext } from './types/graphql.js';
import greetTypeDefs from './modules/root/greet/greet.typeDefs.js';
import greetResolvers from './modules/root/greet/greet.resolversts.js';
import makeTodoTypeDefs from './modules/todos/make-todo/make-todo.typeDefs.js';
import makeTodoResolvers from './modules/todos/make-todo/make-todo.resolvers.js';
import TodoTypeDefs from './modules/root/models/todo.typeDefs.js';

async function main() {
  const PORT = process.env.PORT || 5555;
  const app = express();

  const httpSever = http.createServer(app);
  const server = new ApolloServer<MyContext>({
    typeDefs: mergeTypeDefs([greetTypeDefs, makeTodoTypeDefs, TodoTypeDefs]),
    resolvers: mergeResolvers([greetResolvers, makeTodoResolvers]),
    plugins: [ApolloServerPluginDrainHttpServer({ httpServer: httpSever })],
  });
  await server.start();
  app.use(express.json());
  app.use(
    '/graphql',
    expressMiddleware(server, {
      context: async ({ req, res }) => ({ req, res }),
    })
  );
  await new Promise<void>((resolve) => {
    httpSever.listen({ port: PORT }, resolve);
  });
  console.log(`server is up and running at http://localhost:{PORT}`);
}

main().catch((error) => {
  console.error(error);
  process.exit(1);
});

```
⑤ Create todos folder get-todo, get-todos, make-todo, 
remove-todo, update-todo folder in modules folder

⑥ Create make-todo.typeDefs.ts  and make-todo.resolvers.ts in make-todo
```make-todo/make-todo.typeDefs.ts
const typeDefs = `#graphql

    input MakeTodoInput {
        title: String!
}

type MakeTodoRespose {
   todo:Todo!
}

type Mutation {
   makeTodo(MakeTodoInput:MakeTodoInput!):MakeTodoRespose!
}
`;
export default typeDefs;
```
```make-todo/make-todo.resolvers.ts 
import { title } from 'process';
import { Resolvers } from '../../../_generated_/graphql.js';
import { MyContext } from '../../../types/graphql.js';
import crypto from 'crypto';

const resolvers: Resolvers<MyContext> = {
  Mutation: {
    makeTodo: async (
      _: any,
      args: { makeTodoInput },
      context: MyContext,
      info: any
    ) => {
      const todoItem = {
        id: crypto.randomUUID(),
        title: makeTodoInput.title,
        updatedAt: new Date().toISOString(),
        createdAt: new Date().toISOString(),
      };

      return 'todo has been created !';
    },
  },
};

export default resolvers;
```

⑦ Automate type specification
```
npm i -ED @graphql-codegen/cli
npx graphql-code-generator init
```
```make-todo/make-todo.resolvers.ts
import { Resolvers } from '../../../_generated_/graphql.js';
import { MyContext } from '../../../types/graphql.js';
import crypto from 'crypto';

const resolvers: Resolvers<MyContext> = {
  Mutation: {
    makeTodo: async (
      _: any,
      args: { makeTodoInput },
      context: MyContext,
      info: any
    ) => {
      const todoItem = {
        id: crypto.randomUUID(),
        title: makeTodoInput.title,
        updatedAt: new Date().toISOString(),
        createdAt: new Date().toISOString(),
      };

      return 'todo has been created !';
    },
  },
};

export default resolvers;
```

⑧ Create a files generated by codegen.yml

```backend/src/codegen.yml
overwrite: true
schema: 'http://localhost:5555/graphql'
generates:
  src/_generated_/graphql.ts:
    plugins:
      - 'typescript'
      - 'typescript-resolvers'
```

⑨ Remove ^ in package.json and run npm i
```
npm i
```

⑩ backend/src/_generated_/graphql.ts

⑪ type Todo {
    id: String!
    title: String!
    updatedAt: String!
    createdAt: String!
    } will be used elsewhere, so create a file to share.

create root/models/todo.typeDefs.ts

```root/models/todo.typeDefs.ts
const typeDefs = `#graphql
type Todo {
    id: String!
    title: String!
    updatedAt: String!
    createdAt: String!
    }
`;

export default typeDefs;
```
## 4 - Automatic import of TypeDefs and Resolvers

① Install the library

```
//backend
npm i -E glob
npm i -ED @types/glob copyfiles
```

② Create buildSchema.ts in the utils folder

```utils/buildSchema.ts

```
③ Create make-todo.graphql in make-todo folder
```make-todo/make-todo.graphql

```
④ Create greet.graphql in greet folder
```greet/greet.graphql

```
⑤ Delete make-todo.typeDefs.ts in make-todo folder

⑥ Delete greet.typeDefs.ts in greet folder

⑦ Create todo.graphql in modeles folder

```modeles/todo.graphql

```
⑧ Delete todo.typeDefs.ts in greet folder

⑨　Refactor backend/src/index.ts
```backend / src / index.ts

```
⑩ Add code to backend/src/package.json

```backend/src/package.json
//省略
"scripts": {
    //省略
    "gen": "graphql-codegen --config codegen.yml",
    "cpgql": "copyfiles -u 1 src/**/*.graphql ./dist "
  },
```
## 5 - Prisma preparation & TodoCRUD implementation
公式サイト：[prisma](https://www.prisma.io/typescript)

① Install prisma in your backend project
```
npm i -E prisma@prisma/client
npx prisma init
```
②　Edit .env in backend

```backend/.env

DATABASE_URL="file:./dev.db"
```
③ Add code to prisma/schema.prisma
```prisma/schema.prisma
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "sqlite"
  url      = env("DATABASE_URL")
}

model Todo{
  id String @id @default(uuid())
  title String
  isCompleted Boolean @default(false)
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}
```
④　Create migration file in backend
```
npx prisma migrate dev --name init
npx prisma studio //server starts up
```
④　Edit backend/src/index.ts to use Prisma
```backend / src / index.ts
import http from 'http';

import { ApolloServer } from '@apollo/server';
import { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHttpServer';
import { expressMiddleware } from '@apollo/server/express4';
import express from 'express';
import { PrismaClient } from '@prisma/client';
import { MyContext } from './types/graphql.js';
import { buildSchema } from './utils/buildSchema.js';

const prismaClient = new PrismaClient();

async function main() {
  await prismaClient.$connect();

  const PORT = process.env.PORT || 5555;
  const app = express();

  const httpSever = http.createServer(app);
  const server = new ApolloServer<MyContext>({
    schema: await buildSchema(),
    plugins: [ApolloServerPluginDrainHttpServer({ httpServer: httpSever })],
  });
  await server.start();
  app.use(express.json());
  app.use(
    '/graphql',
    expressMiddleware(server, {
      context: async ({ req, res }) => ({ req, res }),
    })
  );
  await new Promise<void>((resolve) => {
    httpSever.listen({ port: PORT }, resolve);
  });
  console.log(`server is up and running at http://localhost:{PORT}`);
}

main().catch(async (error) => {
  console.error(error);
  await prismaClient.$disconnect();
  process.exit(1);
});
```
⑤ Create/types/graphql.ts
```types/graphql.ts

```
⑥ Edit make-todo/make-todo.resolvers.ts

```make-todo/make-todo.resolvers.ts
import crypto from 'crypto';
import { Resolvers } from '../../../_generated_/graphql.js';
import { MyContext } from '../../../types/graphql.js';

export const resolvers: Resolvers<MyContext> = {
  Mutation: {
    makeTodo: async (_, { makeTodoInput }, { prismaClient }, info) => {
      const newTodo = await prismaClient.todo.create({
        date: {
          title: makeTodoInput.title,
        },
      });
      return {
        todo: {
          ...newTodo,
          updatedAt: newTodo.updatedAt.toISOString(),
          createdAt: newTodo.createdAt.toISOString(),
        },
      };
    },
  },
};
```
⑦ Add code to backend/src/package.json

```backend/src/package.json
//省略
"scripts": {
    //省略
    "gen": "graphql-codegen --config codegen.yml",
    "gen:db": "prisma migrate dev --name",
    "gui:db": "prisma studio",
    "cpgql": "copyfiles -u 1 src/**/*.graphql ./dist "
  },
```
⑧　Create migration file in backend
```
npm run gen:db -- fix-type-todo-table
npm run gui:db
```
⑨ Create get-todos.graphql, get-todos.resolvers.ts in get-todos folder
```get-todos/get-todos.graphql
type GetTodosResponse {
  getTodos: [Todo]
}

type Query {
  getTodos: GetTodosResponse
}
```
```
npm run cpgql
npm run gen:gql
```
⑩ Create remove-todo.graphql,remove-todo.resolvers.ts in remove-todo folder
```remove-todo/remove-todo.graphql
input UpdateTodoInput {
  todoId: String!
  title: String
  isCompleted: Boolean
}

type UpdateTodoResponse {
  todo: Todo!
}

type Mutation {
  updateTodo(updateTodoInput: UpdateTodoInput!): UpdateTodoResponse!
}

```
```
npm run cpgql
npm run gen:gql
```
```remove-todo/remove-todo.resolvers.ts
import { GraphQLError } from 'graphql';
import { Resolvers } from '../../../_generated_/graphql.js';
import { MyContext } from '../../../types/graphql.js';

export const resolvers: Resolvers<MyContext> = {
  Mutation: {
    removeTodo: async (_, { removeTodoInput }, { prismaClient }, info) => {
      const existingTodo = await prismaClient.todo.findUnique({
        where: {
          id: removeTodoInput.todoId,
        },
      });
      if (!existingTodo) {
        throw new GraphQLError('Not found');
      }
      await prismaClient.todo.delete({
        where: {
          id: existingTodo.id,
        },
      });
      return {
        todo: {
          ...existingTodo,
          updatedAt: existingTodo.updatedAt.toISOString(),
          createdAt: existingTodo.createdAt.toISOString(),
        },
      };
    },
  },
};

```
⑩ Create update-todo.graphql,update-todo.resolvers.ts in update-todo folder

```update-todo/update-todo.graphql
input UpdateTodoInput {
  todoId: String!
  title: String
  isCompleted: Boolean
}

type UpdateTodoResponse {
  todo: Todo!
}

type Mutation {
  updateTodo(updateTodoInput: UpdateTodoInput!): UpdateTodoResponse!
}
```
```update-todo/update-todo.resolvers.ts
import { GraphQLError } from 'graphql';
import { Resolvers } from '../../../_generated_/graphql.js';
import { MyContext } from '../../../types/graphql.js';
import { title } from 'process';

export const resolvers: Resolvers<MyContext> = {
  Mutation: {
    updateTodo: async (_, { updateTodoInput }, { prismaClient }, info) => {
      const existingTodo = await prismaClient.todo.findUnique({
        where: {
          id: updateTodoInput.todoId,
        },
      });
      if (!existingTodo) {
        throw new GraphQLError('Not found');
      }

      if (typeof updateTodoInput.title === 'string') {
        existingTodo.title = updateTodoInput.title;
      }

      if (typeof updateTodoInput.isCompleted === 'boolean') {
        existingTodo.isCompleted = updateTodoInput.isCompleted;
      }

      await prismaClient.todo.update({
        where: {
          id: existingTodo.id,
        },
        date: {
          title: existingTodo.title,
          isCompleted: existingTodo.isCompleted,
        },
      });

      return {
        todo: {
          ...existingTodo,
          updatedAt: existingTodo.updatedAt.toISOString(),
          createdAt: existingTodo.createdAt.toISOString(),
        },
      };
    },
  },
};


```
⑪ Create get-todo.graphql,get-todo.resolvers.ts in get-todo folder

```get-todo/get-todo.graphql
input GetTodoInput {
  todoId: String!
}

type GetTodoRespose {
  todo: Todo!
}

type Query {
  getTodo(GetTodo: GetTodoInput!): GetTodoRespose!
}
```
```get-todo/get-todo.resolvers.ts
import { Resolvers } from '../../../_generated_/graphql.js';
import { MyContext } from '../../../types/graphql.js';

export const resolvers: Resolvers<MyContext> = {
  Query: {
    getTodo: async (_, { getTodoInput }, { prismaClient }, info) => {
      const existingTodo = await prismaClient.todo.findUnique({
        where: {
          id: getTodoInput.todoId,
        },
      });
      if (!existingTodo) {
        throw new GraphQLError('Not found');
      }
      return {
        todos: {
          ...existingTodo,
          updatedAt: existingTodo.updatedAt.toISOString(),
          createdAt: existingTodo.createdAt.toISOString(),
        },
      };
    },
  },
};
```
## 6 - Adding DateTime Scalar

① Create scalars/datetime folder and datetime.graphql, datetime.resolvers.ts in root folder
```root/scalars/datetime/datetime.graphql


```
② Adding DateTime Scalar

```codegen.yml
overwrite: true
schema: 'http://localhost:5555/graphql'
generates:
  src/__generated__/graphql.ts:
  config:
  scalars:
  DateTime: 'Date'
plugins:
  - 'typescript'
  - 'typescript-resolvers'
```
```
npm i -E graphql-scalars
```

## 7- Implementation of Tailwind CSS and Apollo Client
① Install Tailwind CSS on the frontend
```
npm i -DE tailwindcss postcss autoprefixer
npx tailwindcss init -p
```
② Edit tailwind.config.js
```tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ['index.html', 'src/**/:/{js,ts,jsx,tsx}'],
  theme: {
    extend: {},
  },
  plugins: [],
};
```
③　Edit frontend/src/index.css

```frontend/src/index.css
@tailwind base;
@tailwind components;
@tailwind utilities;
```
④ Edit frontend/src/App.tsx
```frontend/src/App.tsx

```
⑤ Share resources across origins in backend
```
npm i -E cors
npm i -ED @types/cors
```
⑥ Edit backend/src/index.ts
```backend/src/index.ts
//omission
import cors from 'cors';
//omission

app.use(
    cors({
      origin: 'http://localhost:5173',
    })
  );
```
⑦ Install to frontend
```
npm i --save-dev @types/react
npm i react-dom
npm i vite
npm i @types/vite 
npm i @vitejs/plugin-react
npm i -E graphql @apollo/client
npm i -DE @graphql-codegen/cli

```
⑧ Set up apollo/client
```frontend/src/main.tsx
declare module 'react-dom/client';
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App.tsx';
import './index.css';
import { ApolloClient, ApolloProvider, InMemoryCache } from '@apollo/client';

const apolloClient = new ApolloClient({
  uri: 'http://localhost:5555/graphql', // Adjust the GraphQL endpoint URL as needed
  cache: new InMemoryCache(),
});

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <ApolloProvider client={apolloClient}>
      <App />
    </ApolloProvider>
  </React.StrictMode>
);
```
⑨ Edit frontend/src/App.tsx
```frontend/src/App.tsx


```
⑩ Automate type specification in frontend
```
npm i -ED @graphql-codegen/cli
mkdir src/_generated_
mkdir src/graphql
npx graphql-code-generator init
npm i -DE @graphql-codegen/typescript-react-apollo @graphql-codegen/typescript @graphql-codegen/typescript-operations
```
⑪ Edit frontend/codegen.yml
```frontend/codegen.yml
overwrite: true
schema: 'http://localhost:5555/graphql'
documents: 'src/graphql/**/*.graphql'
generates:
  src/__generated__/graphql.ts:
    config:
      scalars:
        DateTime: 'Date'
plugins: ['typescript-react-apollo', 'typescript', 'typescript-operations']
```

⑫ Create todos/queries/get-todo.graphql in graphql file

```Create todos/queries/get-todo.graphql in graphql file
const getTodoQuery = gql`
  query Todos {
    getTodos {
      todos {
        id
        title
        isCompleted
        createAt
        updateAt
      }
    }
  }
`;
```

```
npm run gen
```

⑬ Create graphql.tsx in _generated_ file
```_generated_/graphql.tsx
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
export type Maybe<T> = T | null;
export type InputMaybe<T> = Maybe<T>;
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
export type MakeOptional<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]?: Maybe<T[SubKey]> };
export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]: Maybe<T[SubKey]> };
const defaultOptions = {} as const;
/** All built-in and custom scalars, mapped to their actual values */
export type Scalars = {
  ID: string;
  String: string;
  Boolean: boolean;
  Int: number;
  Float: number;
  Void: void;
};

export type CheckAuthResponse = {
  __typename?: 'CheckAuthResponse';
  user?: Maybe<User>;
};

export type ConfirmEmailInput = {
  token: Scalars['String'];
};

export type ConfirmEmailResponse = {
  __typename?: 'ConfirmEmailResponse';
  user?: Maybe<User>;
};

export type LoginInput = {
  email: Scalars['String'];
  password: Scalars['String'];
};

export type LoginResponse = {
  __typename?: 'LoginResponse';
  user?: Maybe<User>;
};

export type Mutation = {
  __typename?: 'Mutation';
  confirmEmail?: Maybe<ConfirmEmailResponse>;
  login?: Maybe<LoginResponse>;
  logout?: Maybe<Scalars['Void']>;
  register?: Maybe<RegisterResponse>;
};


export type MutationConfirmEmailArgs = {
  confirmEmailInput: ConfirmEmailInput;
};


export type MutationLoginArgs = {
  loginInput: LoginInput;
};


export type MutationRegisterArgs = {
  registerInput: RegisterInput;
};

export type Query = {
  __typename?: 'Query';
  checkAuth?: Maybe<CheckAuthResponse>;
  health?: Maybe<Scalars['Boolean']>;
};

export type RegisterInput = {
  email: Scalars['String'];
  password: Scalars['String'];
};

export type RegisterResponse = {
  __typename?: 'RegisterResponse';
  user?: Maybe<User>;
};

export type User = {
  __typename?: 'User';
  createdAt?: Maybe<Scalars['String']>;
  email?: Maybe<Scalars['String']>;
  id?: Maybe<Scalars['String']>;
  updatedAt?: Maybe<Scalars['String']>;
};

export type ConfirmEmailMutationVariables = Exact<{
  confirmEmailInput: ConfirmEmailInput;
}>;


export type ConfirmEmailMutation = { __typename?: 'Mutation', confirmEmail?: { __typename?: 'ConfirmEmailResponse', user?: { __typename?: 'User', id?: string | null, email?: string | null, createdAt?: string | null, updatedAt?: string | null } | null } | null };

export type LoginMutationVariables = Exact<{
  loginInput: LoginInput;
}>;


export type LoginMutation = { __typename?: 'Mutation', login?: { __typename?: 'LoginResponse', user?: { __typename?: 'User', id?: string | null, email?: string | null, createdAt?: string | null, updatedAt?: string | null } | null } | null };

export type LogoutMutationVariables = Exact<{ [key: string]: never; }>;


export type LogoutMutation = { __typename?: 'Mutation', logout?: void | null };

export type RegisterMutationVariables = Exact<{
  registerInput: RegisterInput;
}>;


export type RegisterMutation = { __typename?: 'Mutation', register?: { __typename?: 'RegisterResponse', user?: { __typename?: 'User', id?: string | null, email?: string | null, createdAt?: string | null, updatedAt?: string | null } | null } | null };

export type CheckAuthQueryVariables = Exact<{ [key: string]: never; }>;


export type CheckAuthQuery = { __typename?: 'Query', checkAuth?: { __typename?: 'CheckAuthResponse', user?: { __typename?: 'User', id?: string | null, email?: string | null, updatedAt?: string | null, createdAt?: string | null } | null } | null };


export const ConfirmEmailDocument = gql`
    mutation ConfirmEmail($confirmEmailInput: ConfirmEmailInput!) {
  confirmEmail(confirmEmailInput: $confirmEmailInput) {
    user {
      id
      email
      createdAt
      updatedAt
    }
  }
}
    `;
export type ConfirmEmailMutationFn = Apollo.MutationFunction<ConfirmEmailMutation, ConfirmEmailMutationVariables>;

/**
 * __useConfirmEmailMutation__
 *
 * To run a mutation, you first call `useConfirmEmailMutation` within a React component and pass it any options that fit your needs.
 * When your component renders, `useConfirmEmailMutation` returns a tuple that includes:
 * - A mutate function that you can call at any time to execute the mutation
 * - An object with fields that represent the current status of the mutation's execution
 *
 * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
 *
 * @example
 * const [confirmEmailMutation, { data, loading, error }] = useConfirmEmailMutation({
 *   variables: {
 *      confirmEmailInput: // value for 'confirmEmailInput'
 *   },
 * });
 */
export function useConfirmEmailMutation(baseOptions?: Apollo.MutationHookOptions<ConfirmEmailMutation, ConfirmEmailMutationVariables>) {
        const options = {...defaultOptions, ...baseOptions}
        return Apollo.useMutation<ConfirmEmailMutation, ConfirmEmailMutationVariables>(ConfirmEmailDocument, options);
      }
export type ConfirmEmailMutationHookResult = ReturnType<typeof useConfirmEmailMutation>;
export type ConfirmEmailMutationResult = Apollo.MutationResult<ConfirmEmailMutation>;
export type ConfirmEmailMutationOptions = Apollo.BaseMutationOptions<ConfirmEmailMutation, ConfirmEmailMutationVariables>;
export const LoginDocument = gql`
    mutation Login($loginInput: LoginInput!) {
  login(loginInput: $loginInput) {
    user {
      id
      email
      createdAt
      updatedAt
    }
  }
}
    `;
export type LoginMutationFn = Apollo.MutationFunction<LoginMutation, LoginMutationVariables>;

/**
 * __useLoginMutation__
 *
 * To run a mutation, you first call `useLoginMutation` within a React component and pass it any options that fit your needs.
 * When your component renders, `useLoginMutation` returns a tuple that includes:
 * - A mutate function that you can call at any time to execute the mutation
 * - An object with fields that represent the current status of the mutation's execution
 *
 * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
 *
 * @example
 * const [loginMutation, { data, loading, error }] = useLoginMutation({
 *   variables: {
 *      loginInput: // value for 'loginInput'
 *   },
 * });
 */
export function useLoginMutation(baseOptions?: Apollo.MutationHookOptions<LoginMutation, LoginMutationVariables>) {
        const options = {...defaultOptions, ...baseOptions}
        return Apollo.useMutation<LoginMutation, LoginMutationVariables>(LoginDocument, options);
      }
export type LoginMutationHookResult = ReturnType<typeof useLoginMutation>;
export type LoginMutationResult = Apollo.MutationResult<LoginMutation>;
export type LoginMutationOptions = Apollo.BaseMutationOptions<LoginMutation, LoginMutationVariables>;
export const LogoutDocument = gql`
    mutation Logout {
  logout
}
    `;
export type LogoutMutationFn = Apollo.MutationFunction<LogoutMutation, LogoutMutationVariables>;

/**
 * __useLogoutMutation__
 *
 * To run a mutation, you first call `useLogoutMutation` within a React component and pass it any options that fit your needs.
 * When your component renders, `useLogoutMutation` returns a tuple that includes:
 * - A mutate function that you can call at any time to execute the mutation
 * - An object with fields that represent the current status of the mutation's execution
 *
 * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
 *
 * @example
 * const [logoutMutation, { data, loading, error }] = useLogoutMutation({
 *   variables: {
 *   },
 * });
 */
export function useLogoutMutation(baseOptions?: Apollo.MutationHookOptions<LogoutMutation, LogoutMutationVariables>) {
        const options = {...defaultOptions, ...baseOptions}
        return Apollo.useMutation<LogoutMutation, LogoutMutationVariables>(LogoutDocument, options);
      }
export type LogoutMutationHookResult = ReturnType<typeof useLogoutMutation>;
export type LogoutMutationResult = Apollo.MutationResult<LogoutMutation>;
export type LogoutMutationOptions = Apollo.BaseMutationOptions<LogoutMutation, LogoutMutationVariables>;
export const RegisterDocument = gql`
    mutation Register($registerInput: RegisterInput!) {
  register(registerInput: $registerInput) {
    user {
      id
      email
      createdAt
      updatedAt
    }
  }
}
    `;
export type RegisterMutationFn = Apollo.MutationFunction<RegisterMutation, RegisterMutationVariables>;

/**
 * __useRegisterMutation__
 *
 * To run a mutation, you first call `useRegisterMutation` within a React component and pass it any options that fit your needs.
 * When your component renders, `useRegisterMutation` returns a tuple that includes:
 * - A mutate function that you can call at any time to execute the mutation
 * - An object with fields that represent the current status of the mutation's execution
 *
 * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
 *
 * @example
 * const [registerMutation, { data, loading, error }] = useRegisterMutation({
 *   variables: {
 *      registerInput: // value for 'registerInput'
 *   },
 * });
 */
export function useRegisterMutation(baseOptions?: Apollo.MutationHookOptions<RegisterMutation, RegisterMutationVariables>) {
        const options = {...defaultOptions, ...baseOptions}
        return Apollo.useMutation<RegisterMutation, RegisterMutationVariables>(RegisterDocument, options);
      }
export type RegisterMutationHookResult = ReturnType<typeof useRegisterMutation>;
export type RegisterMutationResult = Apollo.MutationResult<RegisterMutation>;
export type RegisterMutationOptions = Apollo.BaseMutationOptions<RegisterMutation, RegisterMutationVariables>;
export const CheckAuthDocument = gql`
    query CheckAuth {
  checkAuth {
    user {
      id
      email
      updatedAt
      createdAt
    }
  }
}
    `;

/**
 * __useCheckAuthQuery__
 *
 * To run a query within a React component, call `useCheckAuthQuery` and pass it any options that fit your needs.
 * When your component renders, `useCheckAuthQuery` returns an object from Apollo Client that contains loading, error, and data properties
 * you can use to render your UI.
 *
 * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
 *
 * @example
 * const { data, loading, error } = useCheckAuthQuery({
 *   variables: {
 *   },
 * });
 */
export function useCheckAuthQuery(baseOptions?: Apollo.QueryHookOptions<CheckAuthQuery, CheckAuthQueryVariables>) {
        const options = {...defaultOptions, ...baseOptions}
        return Apollo.useQuery<CheckAuthQuery, CheckAuthQueryVariables>(CheckAuthDocument, options);
      }
export function useCheckAuthLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<CheckAuthQuery, CheckAuthQueryVariables>) {
          const options = {...defaultOptions, ...baseOptions}
          return Apollo.useLazyQuery<CheckAuthQuery, CheckAuthQueryVariables>(CheckAuthDocument, options);
        }
export type CheckAuthQueryHookResult = ReturnType<typeof useCheckAuthQuery>;
export type CheckAuthLazyQueryHookResult = ReturnType<typeof useCheckAuthLazyQuery>;
export type CheckAuthQueryResult = Apollo.QueryResult<CheckAuthQuery, CheckAuthQueryVariables>;
```





## Reference site
[【TypeScript & GraphQL】で Fullstack Web Application開発 #1 - プロジェクトセットアップ](https://www.youtube.com/watch?v=er4-IgfZk68&t=74s)
[【TypeScript & GraphQL】で Fullstack Web Application開発 #2 - ミニマムなApollo serverの立ち上げ](https://www.youtube.com/watch?v=ljf1d24sh-Q)
[【TypeScript & GraphQL】で Fullstack Web Application開発 #3 - Graphql コードジェネレーターの追加](https://www.youtube.com/watch?v=pU0_0xbKFDg)
[【TypeScript & GraphQL】で Fullstack Web Application開発 #4 - TypeDefsとResolversの自動インポート](https://www.youtube.com/watch?v=45bvkwn4CqU)
[【TypeScript & GraphQL】で Fullstack Web Application開発 #5 - Prismaの準備&TodoCRUDの実装](https://www.youtube.com/watch?v=bc19UYOWvwQ)
[【TypeScript & GraphQL】で Fullstack Web Application開発 #6 - DateTime Scalarの追加](https://www.youtube.com/watch?v=vYV_4_d-N-w)
[【TypeScript & GraphQL】で Fullstack Web Application開発 #7- Tailwind CSSとApollo Clientの実装](https://www.youtube.com/watch?v=oYTlpjmmZRU)