GithubHelp home page GithubHelp logo

resquel's Introduction

Easily convert your SQL database into a REST API.

This is a lightweight Express.js middleware library that is able to convert SQL databases into a REST API. This library also works seamlessly with the Form.io platform where you can build Angular.js and React.js applications on top of your SQL database. Please go to https://form.io to learn more.

This library has been validated with Microsoft SQL Server, MySQL, and PostgreSQL.

How it works

This module works by assigning routes to specific queries, which you define, that are executed when the routes are triggered. For example, lets say you have the following customer table.

customer

  • firstName
  • lastName
  • email

This library is able to convert this into the following REST API.

  • GET: /customer - Returns a list of all customers.
  • GET: /customer/:id - Returns a single customer
  • POST: /customer - Creates a new customer
  • PUT: /customer/:id - Updates a customer
  • DELETE: /customer/:id - Deletes a customer.

Please refer to the FULL CRUD Example below to see how example configurations to achieve the following.

How to use

This library is pretty simple. You include it in your Express.js application like the following.

const { Resquel } = require('resquel');
const express = require('express');
const app = express();

(async function () {
    const resquel = new Resquel({
      db: {
        client: 'mysql',
        connection: {
          host: 'localhost',
          database: 'formio',
          user: 'root',
          password: 'CHANGEME'
        }
      },
      routes: [
        {
          method: 'get',
          endpoint: '/customer',
          query: 'SELECT * FROM customers'
        },
        ...
      ]
    });
    await resquel.init();
    app.use(resquel.router);

    // Listen to port 3010.
    app.listen(3010);
})();

DB Configuration

Please review Knex documentation for specific details on configuring the database connection. The paramaters are passed through to Knex, so all options that are valid there for your database server will work.

Routes

The routes definition is where you will define all of your SQL routes for this library. It is an array of routes that are each defined as follows.

{
  method: 'get|post|put|delete',
  endpoint: '/your/endpoint/:withParams',
  query: 'SELECT * FROM customer'
}

Advanced Queries

The query property in routes can be provided in 3 forms:

  1. Simple query
query: 'SELECT * FROM customer'

This is very limited in use, and mostly provided as shorthand

  1. Multiple queries
query: [
  'TRUNCATE customer',
  'SELECT * FROM customer'
]

When multiple queries are provided, only the return response from the last query appears in the reply

  1. Prepared queries
query: [
  [
    'UPDATE customer SET firstName=?, lastName=?, email=? WHERE id=?',
    'body.firstName',
    'body.lastName',
    'body.email',
    'params.id'
  ],
  [
    'SELECT * FROM customer id=?',
    'params.id'
  ]
]

This is the true intended way to use the library. In the inner arrays, the first item MUST be the query. All subsequent items are substitution values for the ? in the query in the format of object paths on the req object. All properties are accessible, including (but not limited to): headers, params, query, body.

If not all values required by the prepared query are available, then an error will be emitted and execution of queries on that route will be halted (if there are followup queries present).

Note: When using prepared queries, mixing in shorthand style queries will result in an error. Invalid example:

query: [
  [
    'DELETE FROM customer WHERE id=?',
    'params.customerId'
  ],
  'SELECT COUNT(*) AS num FROM customer'
]

Full CRUD example

Let's suppose that you have a SQL table called "customers" that have the following fields.

  • First Name (firstName)
  • Last Name (lastName)
  • Email (email)

The following configuration would generate a full CRUD REST API for this SQL Table.

const { Resquel } = require('resquel');
const express = require('express');
const app = express();
(async function () {
    const resquel = new Resquel({
        db: {
            client: process.env.DB_TYPE,
            connection: {
                host: process.env.DB_HOST,
                database: process.env.DB_NAME,
                user: process.env.DB_USER,
                password: process.env.DB_PASS
            },
        },
        routes: [
            {
              method: 'get',
              endpoint: '/customer',
              query: 'SELECT * FROM customers'
            },
            {
              method: 'post',
              endpoint: '/customer',
              query: [
                [
                  'INSERT INTO customers (firstname, lastName, email) VALUES (?, ?, ?, ?)',
                  'body.data.firstName',
                  'body.data.lastName',
                  'body.data.email'
                ],
                [
                  'SELECT * FROM customers WHERE id=LAST_INSERT_ID();'
                ]
              ]
            },
            {
              method: 'get',
              endpoint: '/customer/:id',
              query: [
                'SELECT * FROM customers WHERE id=?',
                'params.id'
              ]
            },
            {
              method: 'put',
              endpoint: '/customer/:id',
              query: [
                [
                  'UPDATE customers SET firstName=?, lastName=?, email=? WHERE id=?',
                  'body.data.firstName',
                  'body.data.lastName',
                  'body.data.email',
                  'params.id'
                ],
                [
                  'SELECT * FROM customers WHERE id=?',
                  'params.id'
                ]
              ]
            },
            {
              method: 'delete',
              endpoint: '/customer/:id',
              query: [
                'DELETE FROM customers WHERE id=?',
                'params.id'
              ]
            }
        ]
    });
    await resquel.init();
    app.use(resquel.router);
    app.listen(3010);
})();

Troubleshooting

Using with MySQL 8

With the latest version of MySQL 8, you will need to ensure that the "root" user is able to login with the password provider. Otherwise you will get an error. If you are using this library with MySQL 8, please make sure you run the following query within your database to ensure that you are able to authenticate properly.

ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'YourRootPassword';
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'YourRootPassword';

Enjoy!

  • The Form.io Team

resquel's People

Contributors

travist avatar zackurben avatar zoe-codez avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

resquel's Issues

[BUG] ERR_BUFFER_OUT_OF_BOUNDS

Environment

Please provide as many details as you can:

  • Hosting type
    • Local deployment
      • Version: Latest

Steps to Reproduce

require('envkey')
const express = require('express')
const resquel = require('resquel')
const Console = require('consola')

const app = express()
const port = process.env.PORT || 3031

app.use(
  resquel({
    db: {
      user: process.env.DBUSER,
      password: process.env.DBPASS,
      server: process.env.DBHOST,
      database: process.env.DBNAME,
      port: process.env.DBPORT
    },
    routes: [
      {
        method: 'get',
        endpoint: '/users',
        query: 'SELECT * FROM core_members;'
      }
    ]
  })
)

app.listen(port)
Console.log(`Listening on port ${port}`)

Expected behavior

To start successfully

Observed behavior

$ node index.js
Listening on port 3031                                                                                                                                                                                    17:45:24
internal/buffer.js:47
    throw new ERR_BUFFER_OUT_OF_BOUNDS();
    ^

RangeError [ERR_BUFFER_OUT_OF_BOUNDS]: Attempt to write outside buffer bounds
    at boundsError (internal/buffer.js:47:11)
    at Buffer.readUInt8 (internal/buffer.js:137:5)
    at Packet.isLast (/Users/daniel/code/ironmarch/api/node_modules/tedious/lib/packet.js:112:29)
    at ReadablePacketStream.<anonymous> (/Users/daniel/code/ironmarch/api/node_modules/tedious/lib/message-io.js:91:18)
    at ReadablePacketStream.emit (events.js:198:13)
    at addChunk (/Users/daniel/code/ironmarch/api/node_modules/readable-stream/lib/_stream_readable.js:291:12)
    at readableAddChunk (/Users/daniel/code/ironmarch/api/node_modules/readable-stream/lib/_stream_readable.js:278:11)
    at ReadablePacketStream.Readable.push (/Users/daniel/code/ironmarch/api/node_modules/readable-stream/lib/_stream_readable.js:245:10)
    at ReadablePacketStream.Transform.push (/Users/daniel/code/ironmarch/api/node_modules/readable-stream/lib/_stream_transform.js:148:32)
    at ReadablePacketStream._transform (/Users/daniel/code/ironmarch/api/node_modules/tedious/lib/message-io.js:57:16)
error Command failed with exit code 1.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.