Tech

Objectionを使用したAPIの実装

TL;DR

Knex.jsを使用したMigrationとSeedの作成の続きです。
Objection.jsを使用してAPIを実装してみたいと思います。

実装後はこちら

Objection.jsとは

前回少し触ったKnex.jsを内包したNode.jsのORMです。
クエリはKnexを使用するため、DBサポートはKnexと同様にSQLite3、PostgreSQL、MySQLをサポートしています。

Objectionを使うことによりObjectionでモデルを定義すると、そのモデルクラスを元に、DB操作を行う事ができるようになります。
また、そのモデル自体にJsonSchemaによるバリデーションを定義できます。

Modelファイルの作成

model/User.js を作成します。
公式ではjsonSchemaを記載していたりしますが、Joi を元に joi-to-json-schema を使ってjsonSchemaを作りました。

'use strict'

const Model = require('objection').Model
const Joi = require('joi')
const convert = require('joi-to-json-schema')


class User extends Model {

  // table name
  static get tableName() {
    return 'user'
  }

  // validate
  static get jsonSchema() {
    const joiSchema = Joi.object({
      name: Joi.string().min(4).max(50).required(),
      email: Joi.string().email().max(100).required(),
      password: Joi.string().min(6).max(200).required(),
    })
    return convert(joiSchema)
  }
}

module.exports = User

Routeの実装

前回でも行っているuserモデルのAPIを作ります。
ObjectionのModelを作っていると Model.query() で Modelで定義しているテーブルの一覧、の結果を簡単に得ることができます。

const User = require('../model/User')
const md5 = require('md5')

module.exports = [
  {
    method: 'GET',
    path: '/user',
    handler: async (request, h) => {

      try {
        const user = await User.query()
        return user.map((elem) => {
          delete elem.password
          return elem
        })
      } catch (err) {
        return h.response({ ...err }).code(err.statusCode || 500)
      }
    }
  },
  {
    method: 'POST',
    path: '/user',
    handler: async (request, h) => {
      const data = request.payload
      data.password = md5(data.password)

      try {
        const user = await User.query().insert(data)
        return { message: 'created' }
      } catch (err) {
        return h.response({ ...err }).code(err.statusCode || 500)
      }
    }
  },
  {
    method: 'GET',
    path: '/user/{id}',
    handler: async (request, h) => {


      try {
        const user = await User.query().where({ id: request.params.id })
        console.log(user);
        if (!user[0]) return h.response({ statusCode: 404 }).code(404)
        delete user.password
        return user
      } catch (err) {
        return h.response({ ...err }).code(err.statusCode || 500)
      }
    }
  },
  {
    method: 'PUT',
    path: '/user/{id}',
    handler: async (request, h) => {
      try {
        const user = await User.query().patchAndFetchById(request.params.id, request.payload)
        if (!user) return h.response({ statusCode: 404 }).code(404)
        return { message: 'updated' }
      } catch (err) {
        return h.response({ ...err }).code(err.statusCode || 500)
      }
    }
  },
  {
    method: 'DELETE',
    path: '/user/{id}',
    handler: async (request, h) => {
      try {
        const user = await User.query().deleteById(request.params.id)
        console.log(user);
        if (!user) return h.response({ statusCode: 404 }).code(404)
        return { message: 'deleted' }
      } catch (err) {
        return h.response({ ...err }).code(err.statusCode || 500)
      }
    }
  },
]

以上で、 /user//user/{id} のAPIが動作するようになるかと思います。

参考

share