将上传类型添加到 GraphQL

Add Upload type to GraphQL

我正在尝试创建一个自定义解析器来为使用 composeWithMongoose.

的 Express + Apollo Server + Mongoose 项目上传用户头像图像

正在使用 SchemaComposer 创建用户解析器,它从 Mongoose 模式生成它们,例如:

用户模型

import mongoose, { Schema } from 'mongoose';
import timestamps from 'mongoose-timestamp';
import bcrypt from 'mongoose-bcrypt';
import { composeWithMongoose } from 'graphql-compose-mongoose';

export const UserSchema = new Schema(
    {
        name: {
            type: String,
            trim: true,
            required: true,
        },
        email: {
            type: String,
            lowercase: true,
            trim: true,
            unique: true,
        },
        phone: {
            type: Number,
            trim: true,
            unique: true,
        },
        password: {
            type: String,
            bcrypt: true,
        },
        type: {
            type: String,
        },
        image: {
            type: String,
            trim: true,
            lowercase: true,
        },
    },
    {
        collection: 'users',
    }
);

UserSchema.plugin(timestamps);
UserSchema.plugin(bcrypt);

UserSchema.index({ createdAt: 1, updatedAt: 1 });

export const User = mongoose.model('User', UserSchema);
export const UserTC = composeWithMongoose(User);

用户架构

import { User, UserTC } from '../models/user';

const UserQuery = {
    userById: UserTC.getResolver('findById'),
    userByIds: UserTC.getResolver('findByIds'),
    userOne: UserTC.getResolver('findOne'),
    userMany: UserTC.getResolver('findMany'),
    userCount: UserTC.getResolver('count'),
    userConnection: UserTC.getResolver('connection'),
    userPagination: UserTC.getResolver('pagination'),
};

const UserMutation = {
    userCreateOne: UserTC.getResolver('createOne'),
    userCreateMany: UserTC.getResolver('createMany'),
    userUpdateById: UserTC.getResolver('updateById'),
    userUpdateOne: UserTC.getResolver('updateOne'),
    userUpdateMany: UserTC.getResolver('updateMany'),
    userRemoveById: UserTC.getResolver('removeById'),
    userRemoveOne: UserTC.getResolver('removeOne'),
    userRemoveMany: UserTC.getResolver('removeMany'),
};

export { UserQuery, UserMutation };

根据 graphql-compose-mongoose documentation 和我的理解,我必须使用方法 addResolver() 将解析器添加到 ObjectTypeComposer (UserTC),例如:

用户架构

import { User, UserTC } from '../models/user';
import { GraphQLUpload } from 'graphql-upload';

UserTC.addResolver({
    name: 'uploadImage',
    type: 'String',
    args: { userId: 'MongoID!', image: 'Upload!' },
    resolve: async ({ source, args, context, info }) => {
        const user = await User.findById({ _id: args.userId }).exec();
        console.log(user);
    }
});

const UserQuery = {
    ...
};

const UserMutation = {
    ...
    uploadImage: UserTC.getResolver('uploadImage'),
};

export { UserQuery, UserMutation };

这一直有效,直到我将 image 参数类型从 String 更改为 Upload。其中,根据Apollo documentation默认启用。

我在控制台中收到此错误:Error: Type with name "Upload" does not exists

但我不确定在这种情况下如何使用 composeWithMongoose() 添加到我自己的类型定义中。

我有兴趣听听其他方法 - 也许使用完全不同的方法是完全有效的。

编辑 1:回应@Daniel Rearden

我仍然收到 Upload 类型不存在:

  throw new Error(`Type with name ${(0, _misc.inspect)(typeName)} does not exists`);

 ^

Error: Type with name "Upload" does not exists

  1. 我已经安装了:express-graphqlapollo-upload-server
  2. 我将中间件添加到服务器配置中:
import dotenv from 'dotenv';
import express from 'express';
import { ApolloServer } from 'apollo-server-express';
import mongoose from 'mongoose';
import bodyParser from 'body-parser';
import { apolloUploadExpress } from 'apollo-upload-server'; 
import './utils/db';
import schema from './schema';

dotenv.config();

const app = express();

app.use(
    bodyParser.json(),
    apolloUploadExpress()
);

const server = new ApolloServer({
    schema,
    cors: true,
    playground: process.env.NODE_ENV === 'development' ? true : false,
    introspection: true,
    tracing: true,
    path: '/',
});
...
  1. 我在架构索引中提供了以下代码:
import { SchemaComposer } from 'graphql-compose';
import { GraphQLUpload } from 'apollo-upload-server';

import db from '../utils/db'; //eslint-disable-line no-unused-vars

const schemaComposer = new SchemaComposer();

schemaComposer.add(GraphQLUpload);
...

我仍然收到错误:Error: Type with name "Upload" does not exists

编辑 2:另外,回应@Daniel Rearden

好吧,我刚刚将自定义解析器添加到 UserMutation 模式并且它起作用了:

const UserMutation = {
    userCreateOne: UserTC.getResolver('createOne'),
    userCreateMany: UserTC.getResolver('createMany'),
    userUpdateById: UserTC.getResolver('updateById'),
    userUpdateOne: UserTC.getResolver('updateOne'),
    userUpdateMany: UserTC.getResolver('updateMany'),
    userRemoveById: UserTC.getResolver('removeById'),
    userRemoveOne: UserTC.getResolver('removeOne'),
    userRemoveMany: UserTC.getResolver('removeMany'),
    uploadImage: {
        type: 'String',
        args: {
            userId: 'String!',
            image: 'Upload'
        },
        resolve: async (_, { userId, image }) => {
            const user = await User.findById({ _id: userId}).exec();
            console.log(user);
        },
    }
};

如文档所述:

Note: When using typeDefs, Apollo Server adds scalar Upload to your schema, so any existing declaration of scalar Upload in the type definitions should be removed. If you create your schema with makeExecutableSchema and pass it to ApolloServer constructor using the schema param, make sure to include scalar Upload.

如果您不使用 typeDefsresolvers 选项而是将 schema 直接传递给 ApolloServer 的构造函数,则必须添加标量你自己。 graphql-compose 的文档显示 how to do this 但它应该像这样简单:

import { schemaComposer } from 'graphql-compose'
import { GraphQLUpload } from 'apollo-server'

schemaComposer.add(GraphQLUpload)