【问题标题】:How to integrate graphql-compose-mongoose with next.js apollo server如何将 graphql-compose-mongoose 与 next.js apollo 服务器集成
【发布时间】:2021-03-29 11:34:01
【问题描述】:

我正在尝试在我的项目中使用 mongoose、graphql 和 next.js,但不断收到此错误:

Error: You try to generate GraphQL Type with name Customer from mongoose model but this type already exists in SchemaComposer. Please choose another type name "composeWithMongoose(model, { name: 'NewTypeName' })", or reuse existed type "schemaComposer.getOTC('TypeName')", or remove type from SchemaComposer before calling composeWithMongoose method "schemaComposer.delete('TypeName')".

我拥有的是简单的猫鼬模式:

const mongoose = require('mongoose');

const CustomerSchema = new mongoose.Schema({
    name: {
        type: String
    }
}, {
    toJSON: {
        transform: function (doc, ret, options) {
            ret.id = ret._id.toString();
            delete ret.__v;
            delete ret._id;
        }
    }
});

以及组成 gql 架构的单独模块:

import {composeMongoose} from "graphql-compose-mongoose";

import { schemaComposer } from 'graphql-compose';

import {Customer} from '../db/models/Customer';

const customizationOptions = {}
const CustomerTC = composeMongoose(Customer, customizationOptions);

schemaComposer.Query.addFields({
    customerById: CustomerTC.mongooseResolvers.findById()
})

console.log("Schema:", schemaComposer.getOTC('Customer'))

const customerSchema = schemaComposer.buildSchema();
export default customerSchema;

和服务器 api 模块:

import {ApolloServer} from 'apollo-server-micro'
import customerSchema from '../../apollo/customer-type-defs';

const apolloServer = new ApolloServer({
    schema: customerSchema,
    context: () => ({})
});

export const config = {
    api: {
        bodyParser: false,
    },
}

export default apolloServer.createHandler({path: '/api/graphql'})

有人可以告诉我如何修复错误吗?

【问题讨论】:

    标签: mongoose graphql next.js apollo-server


    【解决方案1】:

    我遇到了同样的问题,我发现解决方案只是检查ObjectTC 是否已经存在,如果不存在则创建。

    function createObjectTC({ model, customizationOptions = {} }}) {
     let ModelTC = null;
    
     try {
      ModelTC = schemaComposer.getOTC(model.modelName);
     } catch {
      ModelTC = composeWithMongoose(model, customizationOptions);
     }
    
     return ModelTC;
    }
    
    
    const UserTC =  createObjectTC({ model: User, customizationOptions: {} });
    

    【讨论】:

      【解决方案2】:

      我的解决方案是使用 graphql 和 express 创建一个单独的后端服务器。以及一个前端服务器,以保留下一个服务器引擎提供的所有内置优势。 hack 是设置一个 api/graphql 端点,将 graphql 调用转发到后端服务器。

      这是我的 api 端点:

      /api/graphql.js

      import logger from '../../lib/logger'
      import {getSession} from "next-auth/client";
      
      
      export default async (_req, _res) => {
          // logger.debug("api/graphql: Request body:\n", _req.body)
          const session = await getSession({req: _req})
          logger.debug( "current session: ", session )
          const accessToken = session?.accessToken ?? "";
          const query = {
              method: 'POST', // *GET, POST, PUT, DELETE, etc.
              mode: 'cors', // no-cors, *cors, same-origin
              cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
              credentials: 'same-origin', // include, *same-origin, omit
              headers: {
                  'Content-Type': 'application/json',
                  'infraToken': session.infraToken
                  // 'Content-Type': 'application/x-www-form-urlencoded',
              },
              redirect: 'follow', // manual, *follow, error
              referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
              body: JSON.stringify({
                  operationName: _req.body.operationName,
                  variables: _req.body.variables,
                  query: _req.body.query
              }) // body data type must match "Content-Type" header
          };
          const res = await fetch('http://localhost:4000/api/graphql', query)
          const json = await res.json()
          _res.statusCode = 200;
          _res.setHeader('Content-Type', 'application/json');
          _res.setHeader('Cache-Control', 'max-age=180000');
          _res.json(json)
          _res.end()
      };
      

      我还有其他端点来处理其他操作,例如图像上传 和获取。并分别认证下 /api/rest/[...rest].js 和 /api/auth/[...nextauth].js

      【讨论】:

        猜你喜欢
        • 2023-01-30
        • 1970-01-01
        • 2019-02-22
        • 2021-12-01
        • 2020-03-27
        • 2018-02-23
        • 1970-01-01
        • 2018-12-08
        • 2020-06-21
        相关资源
        最近更新 更多