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

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

内容简介:在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的案例》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

最优化理论与方法

最优化理论与方法

袁亚湘 / 科学出版社 / 1997-1 / 38.00元

《最优化理论与方法》全面、系统地介绍了无约束最优化、约束最优化和非光滑最优化的理论和计算方法,它包括了近年来国际上关于优化研究的最新成果。《最优化理论与方法》在经济计划、工程设计、生产管理、交通运输等方面得到了广泛应用。一起来看看 《最优化理论与方法》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具