-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 67515e0
Showing
13 changed files
with
6,899 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"parserOptions": { | ||
"ecmaVersion": 6 | ||
}, | ||
"rules": { | ||
"eol-last": "error", | ||
"indent": ["error", 2, { "SwitchCase": 1 }], | ||
"no-trailing-spaces": "error", | ||
"no-unused-vars": ["error", { "vars": "all", "args": "none", "ignoreRestSiblings": true }] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
# OS | ||
# =========== | ||
.DS_Store | ||
ehthumbs.db | ||
Icon? | ||
Thumbs.db | ||
|
||
# Node and related ecosystem | ||
# ========================== | ||
.nodemonignore | ||
.sass-cache/ | ||
node_modules/ | ||
help/ | ||
a | ||
public/lib/ | ||
app/tests/coverage/ | ||
.bower-*/ | ||
.idea/ | ||
coverage/ | ||
|
||
# MEAN.js app and assets | ||
# ====================== | ||
public/dist/ | ||
uploads | ||
modules/users/client/img/profile/uploads | ||
config/env/local.js | ||
*.pem | ||
|
||
# Ignoring MEAN.JS's gh-pages branch for documenation | ||
_site/ | ||
|
||
# General | ||
# ======= | ||
*.log | ||
*.csv | ||
*.dat | ||
*.out | ||
*.pid | ||
*.gz | ||
*.tmp | ||
*.bak | ||
*.swp | ||
logs/ | ||
build/ | ||
uploads/ | ||
|
||
# Sublime editor | ||
# ============== | ||
.sublime-project | ||
*.sublime-project | ||
*.sublime-workspace | ||
|
||
# Eclipse project files | ||
# ===================== | ||
.project | ||
.settings/ | ||
.*.md.html | ||
.metadata | ||
*~.nib | ||
local.properties | ||
|
||
# IntelliJ | ||
# ======== | ||
*.iml | ||
|
||
# Cloud9 IDE | ||
# ========= | ||
.c9/ | ||
data/ | ||
mongod | ||
|
||
# Visual Studio | ||
# ========= | ||
*.suo | ||
*.ntvs* | ||
*.njsproj | ||
*.sln |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
# xmysql: one command to generate REST APIs for **any** MySql database | ||
|
||
> Requires node >= 7.6.0 | ||
## Why this ? | ||
Deriving REST APIs for a database which do not follow conventions of frameworks such as rails, django etc | ||
is like a small adventure .. | ||
|
||
<p align="center"> | ||
<img src="https://media.giphy.com/media/8gWrk3QZrjF1C/giphy.gif" alt="Rick & Morty"/> | ||
</p> | ||
|
||
Hence this. | ||
|
||
Powered by node packages : (express, mysql) => { xmysql } | ||
|
||
## FEATURES | ||
* Generates API for **ANY** MySql database | ||
* Serves APIs irrespective of naming conventions of primary keys, foreign keys, tables etc | ||
* CRUD : Usual suspects | ||
* Support for composite primary keys | ||
* Pagination | ||
* Sorting | ||
* Fields | ||
* Relations | ||
* Run dynamic queries | ||
|
||
## Sample usage | ||
* npm install -g xmysql | ||
* xmysql -h localhost -u mysqlUsername -p mysqlPassword -d databaseName | ||
* [http://localhost:3000](#http://localhost:3000) | ||
|
||
|
||
Run HTTP client [Postman](https://www.getpostman.com/) or [similar tools](https://chrome.google.com/webstore/search/http%20client?_category=apps) to invoke REST API calls | ||
|
||
## CRUD APIs Usual Suspects | ||
* GET /api/:tableName | ||
* POST /api/:tableName | ||
* GET /api/:tableName/:id | ||
* PUT /api/:tableName/:id | ||
* GET /api/:tableName/count | ||
* GET /api/:tableName/exists | ||
* GET /api/:parentTable/:id/:childTable | ||
* DELETE /api/:tableName/:id | ||
* POST /dynamic | ||
|
||
## Other APIS | ||
* GET /api/:tableName/describe | ||
* GET /api/tables | ||
|
||
## Support for composite primary keys | ||
|
||
#### ___ (three underscores) | ||
|
||
``` | ||
/api/payments/103___JM555205 | ||
``` | ||
*___* : If there are multiple primary keys - seperate them by three underscores as shown | ||
|
||
## Pagination | ||
|
||
#### _p & _size | ||
|
||
_p indicates page and _size indicates size of response rows | ||
|
||
By default 20 records and max of 100 are returned per GET request on a table. | ||
|
||
``` | ||
/api/payments?_size=50 | ||
``` | ||
``` | ||
/api/payments?_p=2 | ||
``` | ||
``` | ||
/api/payments?_p=2&_size=50 | ||
``` | ||
|
||
|
||
## Sorting | ||
|
||
#### _sort | ||
|
||
``` | ||
/api/payments?_sort=column1 | ||
``` | ||
eg: sorts ascending by column1 | ||
|
||
``` | ||
/api/payments?_sort=-column1 | ||
``` | ||
eg: sorts descending by column1 | ||
|
||
``` | ||
/api/payments?_sort=column1,-column2 | ||
``` | ||
eg: sorts ascending by column1 and descending by column2 | ||
|
||
|
||
## Fields | ||
``` | ||
/api/payments?_fields=customerNumber,checkNumber | ||
``` | ||
eg: gets only customerNumber and checkNumber in response of each record | ||
``` | ||
/api/payments?_fields=-checkNumber | ||
``` | ||
eg: gets all fields in table row but not checkNumber | ||
|
||
|
||
## Run dynamic queries | ||
Dynamic queries on a database can be run by POST method to URL localhost:3000/dynamic | ||
|
||
This is enabled only in local i.e -h localhost or -h 127.0.0.1 option. | ||
|
||
Post body takes two fields : query and params. | ||
|
||
>query: SQL query or SQL prepared query (ones with ?? and ?) | ||
>params : parameters for SQL prepared query | ||
``` | ||
POST /dynamic | ||
{ | ||
"query": "select * from ?? limit 1,20", | ||
"params": ["customers"] | ||
} | ||
``` | ||
## Relational Tables | ||
xmysql identifies foreign key relations automatically and provides GET api. | ||
``` | ||
/api/customers/103/payments | ||
``` | ||
eg: Customers is parent table and payments is child table. API invocation will result in all payments with customer 103. | ||
|
||
|
||
## When to use ? | ||
* You need REST APIs without much hassle for (ANY) MySql database | ||
* You are learning new frontend frameworks and need REST APIs for your MySql database. | ||
* You are working on a demo, hacks etc | ||
|
||
## When NOT to use ? | ||
* Other times not mentioned in when to use section | ||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
#! /usr/bin/env node | ||
|
||
const morgan = require('morgan'); | ||
const bodyParser = require('body-parser'); | ||
const express = require('express'); | ||
const sqlConfig = require('commander'); | ||
const mysql = require('mysql'); | ||
|
||
const Xapi = require('../lib/xapi.js'); | ||
const cmdargs = require('../lib/util/cmd.helper.js'); | ||
|
||
cmdargs.handle(sqlConfig) | ||
|
||
|
||
|
||
/**************** START : setup express ****************/ | ||
let app = express(); | ||
app.use(morgan('tiny')) | ||
app.use(bodyParser.json()) | ||
app.use(bodyParser.urlencoded({ | ||
extended: true | ||
})) | ||
/**************** END : setup express ****************/ | ||
|
||
|
||
/**************** START : setup mysql ****************/ | ||
let mysqlPool = mysql.createPool(sqlConfig); | ||
/**************** END : setup mysql ****************/ | ||
|
||
|
||
/**************** START : setup Xapi ****************/ | ||
let moreApis = new Xapi(sqlConfig,mysqlPool,app); | ||
|
||
moreApis.init((err, results) => { | ||
|
||
app.listen(sqlConfig.portNumber) | ||
|
||
}) | ||
/**************** END : setup Xapi ****************/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
#! /usr/bin/env node | ||
|
||
const morgan = require('morgan'); | ||
const bodyParser = require('body-parser'); | ||
const express = require('express'); | ||
const sqlConfig = require('commander'); | ||
const mysql = require('mysql'); | ||
|
||
const Xapi = require('./lib/xapi.js'); | ||
const cmdargs = require('./lib/util/cmd.helper.js'); | ||
|
||
cmdargs.handle(sqlConfig) | ||
|
||
|
||
|
||
/**************** START : setup express ****************/ | ||
let app = express(); | ||
app.use(morgan('tiny')) | ||
app.use(bodyParser.json()) | ||
app.use(bodyParser.urlencoded({ | ||
extended: true | ||
})) | ||
/**************** END : setup express ****************/ | ||
|
||
|
||
/**************** START : setup mysql ****************/ | ||
let mysqlPool = mysql.createPool(sqlConfig); | ||
/**************** END : setup mysql ****************/ | ||
|
||
|
||
/**************** START : setup Xapi ****************/ | ||
let moreApis = new Xapi(sqlConfig,mysqlPool,app); | ||
|
||
moreApis.init((err, results) => { | ||
|
||
app.listen(sqlConfig.portNumber) | ||
|
||
}) | ||
/**************** END : setup Xapi ****************/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
'use strict'; | ||
const program = require('commander'); | ||
const colors = require('colors'); | ||
|
||
program.on('--help', () => { | ||
console.log('') | ||
console.log(' Examples:'.blue) | ||
console.log('') | ||
console.log(' $ xmysql -u username -p password -d databaseSchema'.blue) | ||
console.log('') | ||
}) | ||
|
||
program | ||
.version('0.0.2') | ||
.option('-h, --host <n>', 'hostname') | ||
.option('-d, --database <n>', 'database schema name') | ||
.option('-u, --user <n>', 'username of database / root by default') | ||
.option('-p, --password <n>', 'password of database / empty by default') | ||
.option('-n, --portNumber <n>', 'port number : 3000 by default') | ||
.parse(process.argv) | ||
|
||
|
||
function paintHelp(txt) { | ||
return colors.magenta(txt) //display the help text in a color | ||
} | ||
|
||
function processInvalidArguments(program) { | ||
|
||
let err = ''; | ||
|
||
if (!program.password) { | ||
err += 'Error: password for database is missing\n'; | ||
} | ||
|
||
if (!program.database) { | ||
err += 'Error: database name is missing\n'; | ||
} | ||
|
||
if (err !== '') { | ||
program.outputHelp(paintHelp) | ||
console.log(err.red) | ||
} | ||
} | ||
|
||
exports.handle = program => { | ||
|
||
/**************** START : default values ****************/ | ||
program.portNumber = program.portNumber || 3000; | ||
program.user = program.user || 'root'; | ||
program.password = program.password || ''; | ||
program.host = program.host || 'localhost'; | ||
|
||
|
||
program.connectionLimit = 10; | ||
|
||
if (program.host === 'localhost' || program.host === '127.0.0.1') { | ||
program.dynamic = 1 | ||
} | ||
//console.log(program.rawArgs); | ||
/**************** END : default values ****************/ | ||
|
||
|
||
if (program.database && program.host && program.user) { | ||
console.log('Starting server at:', 'http://'+program.host + ':' + program.portNumber) | ||
} else { | ||
processInvalidArguments(program) | ||
process.exit(1) | ||
} | ||
|
||
}; |
Oops, something went wrong.