mongoose - 기존의 리졸버를 활용해 커스텀 리졸버 생성하기

ToastEggsToast·2021년 3월 30일
0

TIL

목록 보기
10/15

Mongoose

What is Mongoose?

Mongoose is an Object Data Modeling (ODM) library for MongoDB and Node.js. It manages relationships between data, provides schema validation, and is used to translate between objects in code and the representation of those objects in MongoDB.

mongoose는 몽고디비, 노드 js를 위한 ODM 라이브러리로 데이터 간의 관계나 스키마 밸리데이션을 관리합니다.

기존의 리졸버를 활용해 커스텀 리졸버 제작하기

기존 api 코드

import { DocumentType } from '@typegoose/typegoose';
import { pick } from 'lodash';

import { CouponModel, User, UserModel } from '../../../../models';
import { CouponModelTC } from '../../..';

const name = 'userCouponCreateOne';

export const resolver = UserCouponModelTC.mongooseResolvers
  .createOne()
  .wrapResolve((next) => async (rp) => {
    const user: DocumentType<User> = rp.context.user;
    const args: typeof rp.args & { userUid?: string } = rp.args;
    const record = args.record;
    const coupon: string = record.coupon;

    if (!(await CouponModel.findById(coupon, []))) {
      throw new Error('쿠폰 정보가 올바르지 않습니다.');
    }

    rp.args.record = {
      ...pick(rp.args.record, [
        'coupon',
        'expiredAt',
        'issuedAt',
        'metaData',
        'owner',
        'status',
      ]),
      issuedBy: user._id,
    };

    return next(rp);
  });

export const init = () => {
  return {
    [name]: resolver,
  };
};

위의 코드는 몽구스에서 제공하는 createOne 리졸버를 이용해 만든 api 입니다.
그리고 새로 제작하는 api는 createOne을 기반으로 한 api로 여러 장의 쿠폰을 여러 명의 회원에게 생성해주려고 하는 목적을 가지고 있습니다.

새로 생성한 코드

import { DocumentType } from '@typegoose/typegoose';
import Bluebird from 'bluebird';
import { UserCouponStatus, UserType } from 'swingby-shared';

import { CouponModel, User, UserCoupon, UserModel } from '../../../../models';
import { UserCouponModelTC } from '../../..';
import { resolver as userCouponCreateOneResolver } from '../create';

const name = 'userCouponCreateMany';

export const init = () => {
  UserCouponModelTC.addResolver({
    args: {
      couponUid: 'MongoID!',
      issuedAt: 'Date!',
    },
    name,
    resolve: async ({ args, context }) => {
      const { couponUid, issuedAt } = args;
      const admin: DocumentType<User> = context.user;

      const coupon = await CouponModel.findOne({
        uid: couponUid,
      });

      if (!coupon) {
        throw new Error('쿠폰 정보가 올바르지 않습니다.');
      }

      const createUserCoupon = async (usr: DocumentType<User>) => {
        try {
          const result = await userCouponCreateOneResolver.resolve({
            context,
            args: {
              record: {
                uid: '-',
                owner: usr._id,
                coupon: coupon._id,
                issuedBy: admin._id,
                issuedAt,
                expiredAt: new Date(),
                status: UserCouponStatus.Paid,
              },
            },
          });

          return result.record;
        } catch (e) {
          console.error(e);
        }
      };

      const users = await UserModel.find({ type: UserType.Root });

      const userCoupons: DocumentType<UserCoupon>[] = await Bluebird.map(
        users,
        async (user: DocumentType<User>) => {
          return createUserCoupon(user);
        }
      );

      if (!userCoupons) {
        throw new Error('올바른 쿠폰 정보가 아닙니다.');
      }

      return userCoupons;
    },
    type: [UserCouponModelTC],
  });

  return {
    [name]: UserCouponModelTC.getResolver(name),
  };
};

위에서 import 해온 userCouponCreateOneResolver가 기존에 있던 코드입니다.
userCouponCreateMany resolver는 몽구스에서 제공하고있는 resolver를 사용하지 않고 커스텀으로 리졸버 추가합니다.

import 해온 resolver를 커스텀 한 리졸버 안으로 끌어들어와 각각에 대한 validation, create은 기존의 userCouponCreateOne에서 진행하고, 결과적으로 만들어진 userCoupons를 리턴하는 방식으로 api가 구성됩니다.

주의해야 할 부분은 type 부분인데, 꼭! 배열로 정의를 해주어야합니다.

처음 스스로 제작 할 때에는 따로 배열로 정의하지 않아 제대로 된 결과값을 받지 못했었습니다.
type은 리턴되는 타입에 대한 정의로, 배열로 정의 할 경우 여러개의 값을 배열로 리턴하게 되고 그렇지 않으면 일반 TC의 형태로 리턴됩니다.

profile
개발하는 반숙계란 / 하고싶은 공부를 합니다. 목적은 흥미입니다.

0개의 댓글