npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

koa-restql

v15.0.0-beta

Published

Koa RESTful API middleware based on Sequlizejs

Downloads

38

Readme

koa-restql

Travis branch NPM version

Build real RESTful APIs without writing one line of code. Cool, right?

Now it works perfectly with MySQL.

[toc]

Installation

koa-restql requires node v6.0.0 or higher for (partial) ES2015 support.

npm install --save koa-restql

Usage

const koa     = require('koa')
const RestQL  = require('koa-restql')

let app = koa()
let restql = new RestQL(sequelize.models) // Build APIs from `sequelize.models`
app.use(restql.routes())

How to request real RESTful APIs

Basic

GET /user

If you just have one database table and sequelize model both named user, just choose the right HTTP method to visit path as exactly same name as it.

Using querystring in your url can add condition or limit for the request. For more details, read about querystring.

List

  • Request

    GET /user
  • Response

    HTTP/1.1 206 Partial Content
    X-Range: items 0-2/10
    [
      {
        "id": 1,
        "name": "Li Xin"
      },
      {
        "id": 2,
        "name": "Zhang Chi"
      }
    ]

    Note:

    • Request for a list will always respond an array.
    • This response example include necessary HTTP headers to explain how Partial Content works. If the response was just part of the list, the API would like to response HTTP status code 206.

Single

  • Request

    GET /user/1
  • Response

    {
      "id": 1,
      "name": "Li Xin"
    }

    Note: Request path with id will always respond an object.

Association

1:1

To define an 1:1 association with sequelize, use model.hasOne() or model.belongsTo().

  • Request

    GET /user/1/profile
  • Response

    {
      "id": 1,
      "user_id": 1,
      "site": "https://github.com/crzidea"
    }

    Note: This example is for hasOne(). If the profile was an association defined with belongTo(), there should not be user_id field.

1:N

To define an 1:N association with sequelize, use model.belongsTo().

List
  • Request

    GET /user/1/messages
  • Response

    [
      {
        "id": 1,
        "content": "hello"
      },
      {
        "id": 2,
        "content": "world"
      }
    ]
Single
  • Request

    GET /user/1/messages/2
  • Response

    {
      "id": 2,
      "content": "world"
    }

N:M

To define an N:M association with sequelize, use model.belongsToMany().

Basicly, you can use the same way to request n:n association as 1:N association. The difference is response.

  • Request

    GET /user/1/friends/2
  • Response

    {
      "id": 2,
      "name": "Zhang Chi",
      "friendship": {
        "id": 1,
        "user_id": 1,
        "friend_id": 2
      }
    }

    Note: RestQL will respond the target model with another model referred through option.

Another noticeable problem is, you can not do the following query with association path although it is supported by sequelize:

models.user.findAll(
  {
    include: models.user.association.friends
  }
)

But, fortunately, you can implement the query with querystring like this:

GET /user?_include%5B0%5D=friends

Read more.

CRUD

RestQL could do all CRUD operations for you. Just choose the right HTTP method to access either the resource or the association path.

Supported HTTP verbs:

HTTP verb | CRUD | --------- | ------------- | GET | Read | POST | Create | PUT | Create/Update | DELETE | Delete |

Supported HTTP method with body:

HTTP verb | List | Single | --------- | ------------ | ------ | POST | Array/Object | × | PUT | Array/Object | Object |

  • List path examples:
    • /resource
    • /resource/:id/association, association is 1:n relationship
    • /resource/:id/association, association is n:m relationship
  • Single path examples:
    • /resource/:id
    • /resource/:id/association, association is 1:1 relationship
    • /resource/:id/association/:id, association is 1:n relationship
    • /resource/:id/association/:id, association is n:m relationship

Note: PUT method must be used with unique key(s), which means you can not use PUT method with a request body without an unique key.

To use POST or PUT method, you should put data into request body. Example:

POST /user

{
  "name": "Li Xin"
}

querystring

It's strongly recommended that use qs to stringify nesting querystrings. And this document will assume you will use qs to stringify querystring from JavaScript object.

Example:

qs.stringify({a: 1, b:2}) // => a=1&b=2

To understand RestQL querystring, there are only 3 rules:

  • Every keys in querystring not start with _, will be directly used as where option for sequelize#query(). Example:

    // query
    {
      name: "Li Xin"
    }
    // option for sequelize
    {
      where: {
        name: "Li Xin"
      }
    }
  • Every keys in querystring start with _, will be directly used as sequelize#query().

    // query
    {
      _limit: 10
    }
    // option for sequelize
    {
      limit: 10
    }
  • include option for sequelize#query() should be passed as String of association name.

    // query
    {
      _include: ['friends']
    }
    // option for sequelize
    {
      include: [
        models.user.association.friends
      ]
    }

Sometimes, you want modify query in your own middleware. To do so, you should modify this.restql.query instead of this.request.query or this.query, because the query MUST be parsed with the package qs, not querystring (which is default package of koa).

Access Control

There are at least 2 ways to implement the Access Control:

  1. Add another middleware before request be handled by RestQL.
  2. Add options on sequelize#model#associations, RestQL will handle the options.

This document will only talk about the 2nd way. And the option was only support with associations, not with models.

  1. To specify which association should not be accessed by RestQL, add ignore option. Example:

    models.user.hasOne(
      models.privacy,
      {
        restql: {
          ignore: true
        }
      }
    )
  2. To specify an association should not be accessed by specific HTTP method, add the method to ignore as an array element. Example:

    models.user.hasOne(
      models.privacy,
      {
        restql: {
          ignore: ['get']
        }
      }
    )

Running tests

npm test

License

MIT