React를 사용한 Slack 클론 | 시맨틱 UI | 그래프QL | PostgresSQL(5부)

이전에는 GraphQL의 작동 방식에 대해 살펴보았습니다. 당신은 그것을 찾을 수 있습니다.

오늘 우리는 Graphql 쿼리와 변형을 만들기 시작할 것입니다.
typesDefs.js 파일을 엽니다. 가장 먼저 해야 할 일은 데이터가 어떻게 될지 계획하는 것입니다. 우리는 프로젝트에서 사용자를 나타내기 위해 User 객체가 필요하다는 것을 알고 있으므로 거기서부터 시작하겠습니다.

유형


typeDefs.js 파일에서 이전 코드를 제거하고 다음으로 바꿉니다 =>

const { gql } = require("apollo-server");
module.exports = gql`
  type User {
    username: String!
    email: String!
    password: String!
  }
`

다음으로 사용자가 팀을 생성해야 할 때를 위해 Team 객체를 생성해야 합니다.

const { gql } = require("apollo-server");
module.exports = gql`
  type Team {
    owner: User!
    members: [User!]!
    channels: [Channel!]!
  }
`

가입하려면 Channels가 필요합니다 =>

const { gql } = require("apollo-server");
module.exports = gql`
  type Channel {
    id: Int!
    name: String!
    public: Boolean!
    messages: [Message!]!
    users: [User!]!
  }
`

마지막으로 보내고 받을 수 있어야 합니다Messages =>

const { gql } = require("apollo-server");
module.exports = gql`
  type Message {
    id: Int!
    text: String!
    user: User!
    channel: Channel!
  }
`

이러한 유형을 자세히 살펴보겠습니다.
  • 만든 팀? (소유자 소품), 팀에 누가 있습니까? (멤버 소품), 이 팀과 연결된 채널은 무엇입니까? (채널 소품).
  • 팀과 채널(이메일, 사용자 이름, 암호 소품)을 만드는 사용자를 알아야 하는 사용자입니다.
  • 어떤 채널인지(id prop) 채널 이름이 무엇입니까? (name prop), 공개 또는 비공개입니까? (public prop), 메시지는 무엇입니까(message prop), 이 채널의 사용자 목록(users prop).
  • 메시지 어떤 메시지입니까? (id prop), 메시지는 무엇을 말합니까? (text prop), 이 메시지를 보낸 사용자(user prop), 마지막으로 이 메시지가 속한 채널(channel prop)

  • 결국 귀하의 typeDefs.js는 다음과 같아야 합니다 =>



    이제 쿼리(GET 끝점) 및 변형(POST, PUT, DELETE 끝점)을 정의하겠습니다.

    그래도 typeDefs.js 파일 내부에 쿼리를 추가해 보겠습니다.

    type Query {
        getUsers: [User!]!
        getMessages: [Message!]
        getUser(id: Int!): User!
      }
    

    이것이 내가 지금까지 가지고 있는 것입니다. 돌연변이는 다음과 같습니다 =>

    type Mutation {
        createUser(username: String!, email: String!, password: String!): User
        createMessage(channel_id: Int!, text: String!): Boolean
        createTeam(name: String!): Boolean
        createChannel(teamId: Int!, name: String!, public: Boolean = false): Boolean
      }
    

    참고로 사용에 필요한 매개변수만 전달하면 됩니다. 보시다시피 우리의 모든 변이는 현재 무엇인가(POST)를 생성하는 것과 관련이 있습니다.

    우리는 지금 그것을 정의하고 있습니다. 실제로 createUser 변이를 사용하여 사용자를 생성하는 것부터 시작하여 리졸버로 일부 실제 데이터를 반환해 보겠습니다.

    리졸버


    resolvers.js 파일로 이동하여 createUser 변형을 생성합니다. 이름을 지정하는 것이 중요합니다. 정의한 유형 쿼리와 동일한 이름이어야 합니다.

    const bcrypt = require("bcrypt");
    const { User } = require("../models");
    module.exports = {
      Mutation: {
          createUser: async (_, args) => {
            let { username, email, password } = args;
            try {
            // 1. Check if user exist in DB
            const getUser = await User.findOne({ where: { email: email } });
            if (!getUser) {
              // 2. Hash user password
              password = await bcrypt.hash(password, 12);
              // 3. store user in DB
              const user = await User.create({
                username,
                email,
                password
              });
              return user;
            } else {
              throw Error("User already exist");
            }
          } catch (err) {
            return err;
          }
        }
    };
    

    우리가 하는 일은 args(destructuring data)를 통해 우리에게 전달된 데이터로 사용자를 만드는 것입니다. Sequelize의 User 모델을 사용하여 DB에 사용자를 생성했습니다. 나머지 의견이 무슨 일이 일어나고 있는지 요점을 파악하는 데 도움이 되기를 바랍니다.

    플레이그라운드에서 이 끝점을 테스트해 보겠습니다. 서버를 실행하고 localhost:4000으로 이동합니다.
    createUser 돌연변이 호출은 다음과 같아야 합니다 =>



    유형(쿼리 또는 변형)을 지정합니다. 그런 다음 끝점을 선택합니다. 성공하면 사용자를 반환하고 DB에 사용자를 생성해야 합니다 =>



    이제 DB를 확인합니다.


    참고로 첫 번째 사용자는 무시합니다. 이전에 수행한 테스트였습니다. 하지만 보시다시피 JamesB는 해시된 비밀번호로 생성되었습니다.

    나머지 돌연변이를 만들어 봅시다. 팀, 채널 및 메시지 생성.

    const bcrypt = require("bcrypt");
    const { Channel, Message, Team } = require("../models");
    module.exports = {
      Mutation: {
        createChannel: async (_, args) => {
          try {
            await Channel.create(args);
            return true;
          } catch (err) {
            console.log(err);
            return false;
          }
        },
        createMessage: async (_, args) => {
          // const channel = Channel.findOne({where: {id: args.channel_ids}})
          try {
            await Message.create({
              ...args,
              userId: 1
            });
            return true;
          } catch (error) {
            console.log(error);
            return false;
          }
        },
        createTeam: async (_, args) => {
          try {
            await Team.create({
              ...args,
              owner: 1
            });
            return true;
          } catch (error) {
            console.log(error);
            return false;
          }
        }
      }
    };
    

    이제 우리의 쿼리 =>

    const bcrypt = require("bcrypt");
    const { User } = require("../models");
    module.exports = {
      Query: {
        getUsers: async () => {
          try {
            const users = await User.findAll();
            return users;
          } catch (err) {
            console.log(err);
          }
        },
        getUser: async (_, { id }) => {
          try {
            const user = await User.findOne({ where: { id } });
            return user;
          } catch (error) {
            console.log(error);
          }
        }
      },
    }
    

    이제 작업할 사용자가 있으므로 getUsers 쿼리를 사용하여 사용자를 가져옵니다.



    그것은 우리가 필요하다고 말한 것을 정확하게 반환합니다. 간단히 말해서 이들은 프런트엔드에서 호출할 엔드포인트입니다.

    전반적으로 typeDefs.js 파일은 이제 다음과 같아야 합니다 =>



    그리고 resolvers.js 파일





    그게 전부입니다. 너무 마음에 들지 않기를 바랍니다. 이 시리즈가 이 프로젝트에서 현재 있는 위치에 도달하기 전에 몇 가지 더 많은 기사가 있습니다. 그럼 그때까지 질문이 있거나 놓친 것이 있으면 알려주세요 :)

    좋은 웹페이지 즐겨찾기