从零编写一个Koa + graphQL的案例

栏目: Node.js · 发布时间: 4年前

内容简介:在Nest.js的文档中看到了有集成GraphQL的指导,所以在本地尝试下先用Koa写出一个DEMO,之后再去与Nest.js集成起来。先写出数据库模型(这个文件是之前就存在的,没有做更改,将文件名改成了models.ts):之后编写各自模型的GraphQL查询文件(user.ts)):

在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-ignore
const {
  //@ts-ignore
  graphql, GraphQLSchema, GraphQLObjectType,GraphQLString,GraphQLID,GraphQLList,GraphQLNonNull,GraphQLInt,isOutputType,
} = require('graphql');
// @ts-ignore
const 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-ignore
const {
  // @ts-ignore
  graphql, GraphQLSchema, GraphQLObjectType, GraphQLString, GraphQLID, GraphQLList, GraphQLNonNull, GraphQLInt, isOutputType,
} = require('graphql');
// @ts-ignore
const 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-ignore
const Ticket = require('./ticket');
//@ts-ignore
const 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-ignore
const { graphqlKoa, graphiqlKoa } = require('graphql-server-koa');
// @ts-ignore
const 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-ignore
const { 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"
  ]
}

以上所述就是小编给大家介绍的《从零编写一个Koa + graphQL的案例》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Shallows

The Shallows

Nicholas Carr / W. W. Norton & Company / 2010-6-15 / USD 26.95

"Is Google making us stupid?" When Nicholas Carr posed that question, in a celebrated Atlantic Monthly cover story, he tapped into a well of anxiety about how the Internet is changing us. He also crys......一起来看看 《The Shallows》 这本书的介绍吧!

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具