在Nest.js的文档中看到了有集成GraphQL的指导,所以在本地尝试下先用Koa写出一个DEMO,之后再去与Nest.js集成起来。

先写出数据库模型(这个文件是之前就存在的,没有做更改,将文件名改成了models.ts):

/** * Created by w on 2018/4/13. */const mongoose = require('mongoose');mongoose.Promise = global.Promise;mongoose.connect('mongodb://localhost/ticket', {  server: {    socketOptions: {      keepAlive: 1    }  }});const models = {  users: {    username: {      type: String,      required: true    },    password: {      type: String,      required: true    },    description: {      type: String    },    createTime: {      type: Date,      default: new Date()    }  },  tickets: {    name: {      type: String,      required: true    },    price: {      type: Number,      requred: true    },    holdTime: {   //举办时间      type: Date,      required: true    },    count: {    //剩余数量      type: String,      required: true    },    place:{      type: String,      required: true    },    img: {      type: String    },    description: {      type: String    },    publicTime: {      type: Date,      default: new Date()    },  }};for (let m in models) {  mongoose.model(m, mongoose.Schema(models[m]));}module.exports = {  getModules: (name) => {    return mongoose.model(name);  }};

之后编写各自模型的GraphQL查询文件(user.ts)):

// @ts-ignoreconst {  //@ts-ignore  graphql, GraphQLSchema, GraphQLObjectType,GraphQLString,GraphQLID,GraphQLList,GraphQLNonNull,GraphQLInt,isOutputType,} = require('graphql');// @ts-ignoreconst User = require('../db/model').getModules('users');const userType = new GraphQLObjectType({  name: 'User',  fields: {    username: {      type: GraphQLString,    },    password: {      type: GraphQLString,    },    description: {      type: GraphQLString,    },    createTime: {      type: GraphQLString,    }  }});module.exports = {  query: {    type: new GraphQLList(userType),    args: {      username: {        username: 'username',        type: GraphQLNonNull(GraphQLString)      }    },    resolve(root, params, options) {      if (params.username === '$all') {        return User.find().exec()      }      return User.find({ username: params.username }).exec();    }  },  create: {    type: new GraphQLList(userType),    args: {      username: {        username: 'username',        type: GraphQLNonNull(GraphQLString)      },      possword: {        name: 'price',        type: GraphQLNonNull(GraphQLString)      },      createTime: {        type: GraphQLString,      },      description: {        name: 'description',        type: GraphQLString      }    },    resolve: async (root, params, options) => {      let user = new User({        username: params.username,        password: params.password,        description: params.description,        createTime: params.createTime      });      try {        await user.save();        return user.find({ username: params.username }).exec()      }catch(e) {        console.error("Error while save data: ", e);      }    }  }}

ticket.ts:

// @ts-ignoreconst {  // @ts-ignore  graphql, GraphQLSchema, GraphQLObjectType, GraphQLString, GraphQLID, GraphQLList, GraphQLNonNull, GraphQLInt, isOutputType,} = require('graphql');// @ts-ignoreconst Ticket = require('../db/model').getModules('tickets');const ticketType = new GraphQLObjectType({  name: 'Ticket',  fields: {    name: {      type: GraphQLString    },    price: {      type: GraphQLInt    },    holdTime: {      type: GraphQLString    },    count: {      type: GraphQLInt    },    place: {      type: GraphQLString    },    img: {      type: GraphQLString    },    description: {      type: GraphQLString    },    publicTime: {      type: GraphQLString    }  }});module.exports = {  query: {    type: new GraphQLList(ticketType),    args: {      name: {        name: 'name',        type: GraphQLNonNull(GraphQLString)      }    },    resolve(root, params, options) {      if (params.name === '$all') {        return Ticket.find().exec()      }      return Ticket.find({ name: params.name }).exec();    }  },  create: {    type: new GraphQLList(ticketType),    args: {      name: {        name: 'name',        type: GraphQLNonNull(GraphQLString)      },      price: {        name: 'price',        type: GraphQLInt      },      holdTime: {        name: 'holdTime',        type: GraphQLNonNull(GraphQLString)      },      count: {        name: 'count',        type: GraphQLNonNull(GraphQLInt)      },      place: {        name: 'place',        type: GraphQLNonNull(GraphQLString)      },      img: {        name: 'img',        type: GraphQLString      },      description: {        name: 'description',        type: GraphQLString      },      publicTime: {        name: 'publicTime',        type: GraphQLString      }    },    resolve: async (root, params, options) => {      let ticket = new Ticket({        name: params.name,        price: params.price,        holdTime: params.holdTime,        count: params.count,        place: params.place,        img: params.img,        description: params.description,        publicTime: params.publicTime      });      try {        await ticket.save();        return Ticket.find({ name: params.name }).exec()      }catch(e) {        console.error("Error while save data: ", e);      }    }  }}

接下来编写用于查询或修改数据的Schema.ts:

const {  //@ts-ignore  GraphQLSchema, GraphQLObjectType,} = require('graphql');//@ts-ignoreconst Ticket = require('./ticket');//@ts-ignoreconst User = require('./user');module.exports = new GraphQLSchema({  query: new GraphQLObjectType({    name: 'Queries',    fields: {      Ticket: Ticket.query,      User: User.query,    }  }),  mutation: new GraphQLObjectType({    name: 'Mutations',    fields: {      Ticket: Ticket.create,      User: User.create,    }  })})

编写服务端(server.ts):

const Koa = require('koa');const app = new Koa();const koaBody = require('koa-body');const CombileRouter = require('./combineRouter');app  .use(koaBody({    multipart: true,    formidable: {      keepExtensions: true,    },  }))  .use(CombileRouter.routes())  .use(CombileRouter.routes());app.listen(5000, () => {  console.log('App running~');})

定义ticket路由的ticket.router.ts:

const KoaRouter = require('koa-router');const ticketRouter = new KoaRouter();// @ts-ignoreconst { graphqlKoa, graphiqlKoa } = require('graphql-server-koa');// @ts-ignoreconst Ticket = require('../db/model').getModules('tickets');const ticketSchema = require('../graphql/schema');ticketRouter.get('/ticket/all', async (ctx) => {  try {    let result = await Ticket.find({});    ctx.body = { data: Object.assign({}, result), code: '0' };  } catch (e) {    console.error("Getting all ticket error: ", e);  }});ticketRouter.post('/graphql', async (ctx, next) => {  console.log('graphql', ctx.request.body);  await graphqlKoa({schema: ticketSchema})(ctx, next)}).get('/graphql', async (ctx, next) => {  await graphqlKoa({schema: ticketSchema})(ctx, next)}).get('/graphiql', async (ctx, next) => {  await graphiqlKoa({endpointURL: '/graphql'})(ctx, next)})module.exports = ticketRouter;

还有之前定义的user.router.ts(测试这个user路由是否是reachable的):

const Router = require('koa-router');const userRouter = new Router();// @ts-ignoreconst { graphiqlKoa } = require('graphql-server-koa');userRouter.get('/user/all', async (ctx) => {  ctx.body = {    code: '0',    msg: 'OK',    info: {      data: [{        username: 'a',        id: 0,        desc: 'ok',      }, {        username: 'd',        id: 1,        desc: 'ok',      }, {        username: 'c',        id: 2,        desc: 'ok',      }, {        username: 'b',        id: 3,        desc: 'ok',      }]    }  }});module.exports = userRouter;

将两个路由文件融合起来(combineRouter.ts):

const UserRouter:object = require('./koa-router/user.router');const TicketRouter:object = require('./koa-router/ticket.router');const combiler = (routers: object[]): object => {  let arr = [];    routers.forEach(v => {    //@ts-ignore    arr.push(...v.stack)  });  return Object.assign(routers[0], { stack:arr });}const res = combiler([UserRouter, TicketRouter]);module.exports = res;

OK了,这部分就写好了基础的query和mutation功能,还有删除的功能之后再加上。
附上tsconfig.json文件:

{  "compilerOptions": {    "module": "commonjs",    "target": "es6",    "sourceMap": true,    "experimentalDecorators": true,  },  "exclude": [    "node_modules"  ]}