From 7f783a7347eb17678eb41ed0fe9346d5f5e58d13 Mon Sep 17 00:00:00 2001 From: oof1lab Date: Sun, 12 Nov 2017 19:40:05 +0530 Subject: [PATCH] API : Replace (PUT) in plural route and replace put with replace in singular route. npm v0.2.4 --- README.md | 3 ++- assets/log.gif | Bin 7532 -> 7162 bytes lib/util/cmd.helper.js | 2 +- lib/xapi.js | 59 ++++++++++++++++++++++++++++++++++++++++- lib/xsql.js | 3 ++- package.json | 2 +- tests/tests.js | 35 +++++++++++++++++++++--- 7 files changed, 96 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index cd1ef3fafa..5b86bce697 100644 --- a/README.md +++ b/README.md @@ -96,8 +96,9 @@ Root URL (localhost:3000/) returns all REST API urls for each table in schema. ## CRUD APIs Usual Suspects * GET       /api/tableName * POST      /api/tableName +* PUT       /api/tableName ( acts as REPLACE ) * GET       /api/tableName/:id -* PUT       /api/tableName/:id +* PATCH       /api/tableName/:id ( acts as UPDATE ) * GET       /api/tableName/findOne * GET       /api/tableName/count * GET       /api/tableName/:id/exists diff --git a/assets/log.gif b/assets/log.gif index 210d361cef03fe7de68eadddc2300d44eb7e7c37..e3be0cc0b5a2c1c95212e1f6cb325f0b19de8d18 100644 GIT binary patch delta 855 zcmV-d1E~D$I{G)T3dLlmGsfTRfV5Xy`L}mA z(z^tOH_32j_`yKRqR6>9A}7+!u4=?VNiSIdy8>?+;zc>By85(Zau*GZGnvo&cP_%) zb#d5Tsh312I9M?U))V-bqxh9@2voQj(@0f+nWvZ;xXCGbN#xjv=H&$!#3;(Qr_cmv zntJw_>IUl?D!Yn$8+sI5OIzBfJN&!ndr0Z|%4-{JJWB?-D|ISdTqCVpgS*U{$<18X z8-d*H7d~k|t!}$+5)8Pky?Jd2eNX(1p?$7jt?y4%BVPbn$+IRdTRnapN|8Fas+&81 zQ0>44ENCyH!O&m-*r{XaF=It>65);Hr$(cyhfi37L^n~@NR9bIQg~^xCQODpJMI$s z6QN0WK6%~~La$}FY?=y5GW2O?(?qSv9mVv>lUAoq=5c-c2Ps&Rx1^;bRDvgbARl`}*C-wgoa;$^D@ct_U$?ia_qNyHR=d-Nh zs_e9j3Ja~Mm^RStq1!fUX{eA&`faDAI?BPa=~`=QwZM8BEw+ww+A6p5Qd_UO^?%|k zZm#nFn(e*&u6shc1AE&mymWrMthVeXfN8?$LL02P!}hDGwCtAau)p{o(ebqw>$~Q> z54ZcV$QhqZEWHY7Tqw+f`YPNdbAl4 delta 915 zcmV;E18n^IH|#pF3&?2WtTwlMM%Xlko?7lh6h{vug-70+X)_z>{+d9+Phi zU=08O000310RR930!#su%?n^9NC8Fw5C9GU00JD0Z=kD)%-n%XCJJo8*>e4P7&wX) zd72Qqs*_O)B!5N#SOFXW00RDukEzS;52Kv4+KaQ^ykh_y;WK*XiKgnxwr(}XQ28!k z?a?rGqrKSCWrR2eaVR<_LCROND0w=h393bBCFP(qE-)bTg2f*sPlXL`$u@HMYX~u! z@Ns;;{Mj$GrksAKhZm?fF-IjdNQj^qSJenPc=*xy7=J0Kn5hZ4$nxe06!!U9*JlQ5 zl*ov>*Sb?@RJGblWI79KtCXc++h$kGIvRXC95e|AiK|S@T1wn-C=BhpTugG@J55ZQ zm(BdG8xd{ITa7)NyDbZg7F;4~ovB{N{#=~ByWUKF&+nZMr&7LozTkbyb4htXtcN>^in=)TC$IzOA`7?%li@>+TIaxZdBw ziyMbR{J8SvDq%B!4!uK@VG1L&We&UpvoI3I0)I(Rny96cW-0)lmOct<0-t^wY6GKo zdMW~>PLQe#t3vSV5Rj^hYNv*ls%NUN#(Jv*y4s2>uMf1^g0Ku2>;8kIxBl8Ev!Vj4 z0J6>o3vH&RLVLibl0FJ4rrjQDZKJ0uy8*Huc>8Rxpqd-!ud{NyswnH$tFXk{TWhx1mOHQrnqqsf!0_I?X1MawI;^$fDqOFx{RX@&zW{R^?Y5*&%didq ze!MNkb~^g7$;WE!Z?)t?oH3*B7P_m(^>Vr~5jd+1bI*0^TeHe3?|bdaMQ7Zx!a=8- zugghST*SXj`%GuT_~s1t)cQWnHP>4=eJ}OWSch%%xdoRXHN|PmIrF#gUad989UuHM pt+Q&YHn;^(46nHS){Q~P97v5a;FBX3NdaE7Z5E6LlMoTo0Xt&9x)=Ze diff --git a/lib/util/cmd.helper.js b/lib/util/cmd.helper.js index cee0b42a16..ece6868de9 100644 --- a/lib/util/cmd.helper.js +++ b/lib/util/cmd.helper.js @@ -11,7 +11,7 @@ program.on('--help', () => { }) program - .version('0.2.3') + .version('0.2.4') .option('-h, --host ', 'hostname') .option('-d, --database ', 'database schema name') .option('-u, --user ', 'username of database / root by default') diff --git a/lib/xapi.js b/lib/xapi.js index 9e22448136..0e2b8bd03d 100644 --- a/lib/xapi.js +++ b/lib/xapi.js @@ -112,7 +112,6 @@ class Xapi { /**************** START : setup routes for each table ****************/ - let resources = []; resources = this.mysql.getSchemaRoutes(true, '/api/'); @@ -150,6 +149,11 @@ class Xapi { .get(this.asyncMiddleware(this.read.bind(this))); break; + case 'patch': + this.app.route(routes[i]['routeUrl']) + .patch(this.asyncMiddleware(this.patch.bind(this))); + break; + case 'update': this.app.route(routes[i]['routeUrl']) .put(this.asyncMiddleware(this.update.bind(this))); @@ -246,6 +250,7 @@ class Xapi { } + /** * * @param req @@ -412,8 +417,22 @@ class Xapi { } + async update(req, res) { + let query = 'REPLACE INTO ?? SET ?'; + let params = []; + + params.push(req.app.locals._tableName); + params.push(req.body); + + var results = await this.mysql.exec(query, params); + res.status(200).json(results); + + } + + async patch(req, res) { + let query = 'UPDATE ?? SET '; let keys = Object.keys(req.body); @@ -449,6 +468,44 @@ class Xapi { } + + // async update(req, res) { + // + // let query = 'UPDATE ?? SET '; + // let keys = Object.keys(req.body); + // + // // SET clause + // let updateKeys = ''; + // for (let i = 0; i < keys.length; ++i) { + // updateKeys += keys[i] + ' = ? ' + // if (i !== keys.length - 1) + // updateKeys += ', ' + // } + // + // // where clause + // query += updateKeys + ' where ' + // let clause = this.mysql.getPrimaryKeyWhereClause(req.app.locals._tableName, + // req.params.id.split('___')); + // + // if (!clause) { + // return res.status(400).send({ + // error: "Table is made of composite primary keys - all keys were not in input" + // }) + // } + // + // query += clause; + // + // // params + // let params = []; + // params.push(req.app.locals._tableName); + // params = params.concat(Object.values(req.body)); + // + // let results = await this.mysql.exec(query, params); + // res.status(200).json(results); + // + // + // } + async delete(req, res) { let query = 'DELETE FROM ?? WHERE '; diff --git a/lib/xsql.js b/lib/xsql.js index f19e37f973..f9d3b0a5ca 100644 --- a/lib/xsql.js +++ b/lib/xsql.js @@ -462,8 +462,9 @@ class Xsql { routes.push(this.prepareRoute(internal, 'get', apiPrefix, tableName + '/findOne', 'findOne')) routes.push(this.prepareRoute(internal, 'post', apiPrefix, tableName, 'create')) routes.push(this.prepareRoute(internal, 'get', apiPrefix, tableName, 'list')) + routes.push(this.prepareRoute(internal, 'put', apiPrefix, tableName, 'update')) routes.push(this.prepareRoute(internal, 'get', apiPrefix, tableName + '/:id', 'read')) - routes.push(this.prepareRoute(internal, 'put', apiPrefix, tableName + '/:id', 'update')) + routes.push(this.prepareRoute(internal, 'patch', apiPrefix, tableName + '/:id', 'patch')) routes.push(this.prepareRoute(internal, 'delete', apiPrefix, tableName + '/:id', 'delete')) routes.push(this.prepareRoute(internal, 'get', apiPrefix, tableName + '/:id/exists', 'exists')) diff --git a/package.json b/package.json index 223681a601..8a4146ef28 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "xmysql", - "version": "0.2.3", + "version": "0.2.4", "description": "One command to generate REST APIs for any MySql database", "main": "index.js", "scripts": { diff --git a/tests/tests.js b/tests/tests.js index f5bcc78126..7ba690b52f 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -455,8 +455,36 @@ describe('xmysql : tests', function () { return done(); }); + }); + + it('PUT /api/productlines should PASS', function (done) { + + var obj = {}; + obj['productLine'] = 'Hyperloop' + obj['textDescription'] = 'Hyperloop is essentially a train system that ElonMusk calls \"a cross between ' + + 'a Concorde, a railgun, and an air hockey table\". ' + + 'It\'s based on the very high-speed transit (VHST) system proposed in 1972,' + + 'which combines a magnetic levitation train and a low pressure transit tube.' + + 'It evolves some of the original ideas of VHST, but it still uses tunnels' + + 'and pods or capsules to move from place to place.' + //post to an url with data + agent.put('/api/productlines') //enter url + .send(obj) //postdata + .expect(200)//200 for success 4xx for failure + .end(function (err, res) { + // Handle /api/v error + if (err) { + return done(err); + } + + //validate response + res.body['affectedRows'].should.be.equals(2) + + return done(); + + }); }); it('POST /dynamic should PASS', function (done) { @@ -477,7 +505,6 @@ describe('xmysql : tests', function () { } //validate response - res.body.length.should.be.equals(5) return done(); @@ -537,7 +564,9 @@ describe('xmysql : tests', function () { }); }); - it('PUT /api/customers/:id should PASS', function (done) { + + + it('PATCH /api/productlines/Hyperloop should PASS', function (done) { var obj = {}; @@ -549,7 +578,7 @@ describe('xmysql : tests', function () { 'and pods or capsules to move from place to place.' //post to an url with data - agent.put('/api/productlines/Hyperloop') //enter url + agent.patch('/api/productlines/Hyperloop') //enter url .send(obj) //postdata .expect(200)//200 for success 4xx for failure .end(function (err, res) {