Skip to content

Commit

Permalink
version 0.3.0; seneca 0.6.1; better tests
Browse files Browse the repository at this point in the history
  • Loading branch information
rjrodger committed Feb 1, 2015
1 parent 6e87594 commit 61bbef0
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 64 deletions.
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,3 @@ language: node_js
node_js:
- "0.11"
- "0.10"
- "0.8"
72 changes: 66 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,79 @@
# seneca-jsonrest-api
# seneca-jsonrest-api - a [Seneca](http://senecajs.org) plugin

## A HTTP JSON REST API for data entities for the [Seneca](http://senecajs.org) toolkit
## Seneca HTTP JSON REST API Plugin

Exposes your data entities as a [REST
API](http://en.wikipedia.org/wiki/Representational_state_transfer). For
example, if you have a data entity called _foo_, then the following
end points will become available:

Documentation pending...
* GET _/api/rest/foo_: return a list of all foo entities
* GET _/api/rest/foo/:id_: return a single foo entity by identifier
* POST _/api/rest/foo_: create a new foo entity
* PUT _/api/rest/foo/:id_: update a foo entity

You can use the plugin options to change the URL prefix, and to add
additional behaviours.

Note that it is not necessary for the underlying entity to be
persistent. You can define a virtual entity _foo_ by providing actions for
the patterns:

* _role:entity,name:foo,cmd:save_
* _role:entity,name:foo,cmd:load_
* _role:entity,name:foo,cmd:list_
* _role:entity,name:foo,cmd:remove_


## Options

You can _seneca.use_ this plugin multiple times to create multiple
independent API end points, so long as you specify different
prefixes. The _prefix_ option is used to create separate action
patterns so that they do not conflict.

* _prefix_: a custom prefix
* _pins_: an array of entity pins, with properties _name,base,zone_. These define the data entities that will be exposed.

## Examples

See the
[tests](https://github.com/rjrodger/seneca-jsonrest-api/tree/master/test)
in this repository, and
[seneca-data-editor](https://github.com/rjrodger/seneca-data-editor).


## Support

If you're using this module, feel free to contact me on twitter if you
Current Version: 0.3.0

Tested on: Node 0.10.36, [Seneca](/rjrodger/seneca) 0.6.1

[![Build Status](https://travis-ci.org/rjrodger/seneca-jsonrest-api.png?branch=master)](https://travis-ci.org/rjrodger/seneca-jsonrest-api)

[Annotated Source Code](http://rjrodger.github.io/seneca-jsonrest-api/doc/jsonrest-api.html).

If you're using this module, feel free to contact me on Twitter if you
have any questions! :) [@rjrodger](http://twitter.com/rjrodger)

Current Version: 0.2.1
[![Gitter chat](https://badges.gitter.im/rjrodger/seneca-jsonrest-api.png)](https://gitter.im/rjrodger/seneca-jsonrest-api)


## Install

To install and add to the dependencies list in the package.json file
for your project:

```sh
npm install seneca-jsonrest-api --save
```

And in your code:

Tested on: Node 0.10.24, Seneca 0.5.15
```js
var seneca = require('seneca')()
.use( 'jsonrest-api' )
```



Expand Down
53 changes: 18 additions & 35 deletions jsonrest-api.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/* Copyright (c) 2013-2014 Richard Rodger, MIT License */
/* Copyright (c) 2013-2015 Richard Rodger, MIT License */
"use strict";


var _ = require('underscore')
var _ = require('lodash')


function noware(req,res,next) {
Expand All @@ -23,8 +23,6 @@ module.exports = function( options ) {
var seneca = this
var plugin = "jsonrest-api"

//console.dir(options)

options = seneca.util.deepextend({
prefix:'/api/rest',
aspect:false,
Expand All @@ -45,11 +43,8 @@ module.exports = function( options ) {
var validprops = {zone:1,base:1,name:1}

var pins = options.pin
//console.dir(pins)

pins = pins ? _.isArray(pins) ? pins : [pins] : []
//console.log('canon')
//console.dir(pins)

_.map(pins,function(pin){
pin = _.isString(pin) ? seneca.util.parsecanon(pin) : pin
Expand All @@ -64,18 +59,12 @@ module.exports = function( options ) {
})

})
//console.dir(pin)

})
if( 0 == pins.length ) {
pins.push({})
}


//console.dir(pins)



function parse_ent(args) {
var out = {
name: mark==args.name ? void 0 : args.name,
Expand Down Expand Up @@ -119,32 +108,34 @@ module.exports = function( options ) {
var remove_aspect = make_aspect('remove')


//console.log('ADD')
_.each(pins,function(pin){
//console.log(pin)

seneca.add(_.extend({},pin,{role:plugin,prefix:options.prefix,method:'get'}),action_get)
seneca.add(
_.extend({},pin,{role:plugin,prefix:options.prefix,method:'get'}),
action_get)

seneca.add(_.extend({},pin,{role:plugin,prefix:options.prefix,method:'put'}),function(args,done){
putpost(this,args,done)
})
seneca.add(
_.extend({},pin,{role:plugin,prefix:options.prefix,method:'put'}),
function(args,done){
action_putpost(this,args,done)
})

seneca.add(_.extend({},pin,{role:plugin,prefix:options.prefix,method:'post'}),function(args,done){
putpost(this,args,done)
})
seneca.add(
_.extend({},pin,{role:plugin,prefix:options.prefix,method:'post'}),
function(args,done){
action_putpost(this,args,done)
})

seneca.add(_.extend({},pin,{role:plugin,prefix:options.prefix,method:'delete'}),action_delete)
seneca.add(
_.extend({},pin,{role:plugin,prefix:options.prefix,method:'delete'}),
action_delete)
})





function action_get(args,done){
//console.log('ACTION GET')
//console.log(seneca.util.clean(args))
//console.trace()

var ent_type = parse_ent(args)

var qent = this.make(ent_type.zone,ent_type.base,ent_type.name)
Expand Down Expand Up @@ -289,21 +280,13 @@ module.exports = function( options ) {
}
}


//console.log('RESOLVE')
//console.log(seneca.util.clean(args))

act(args,respond)
}


_.each(pins, function(pin){
pin = _.extend({},pin,{role:plugin,prefix:options.prefix,method:'*'})


//console.log(pin)


seneca.act({role:'web',use:{
prefix:options.prefix,
pin:pin,
Expand Down
19 changes: 9 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"name": "seneca-jsonrest-api",
"version": "0.2.1",
"version": "0.3.0",
"description": "A HTTP JSON REST API for Seneca entities",
"main": "jsonrest-api.js",
"scripts": {
"test": "./node_modules/mocha/bin/mocha test/jsonrest-api.test.js"
"test": "./test.sh"
},
"repository": {
"type": "git",
Expand All @@ -19,16 +19,15 @@
"author": "Richard Rodger (@rjrodger)",
"license": "MIT",
"devDependencies": {
"seneca": "0.5.x",
"connect": "2.12.x",
"mocha": "1.17.x",
"gex": "0.1.x"
"body-parser": "^1.11.0",
"connect": "~3.3.4",
"gex": "~0.2.0",
"mocha": "~2.1.0",
"seneca": "plugin",
"serve-static": "^1.8.1"
},
"dependencies": {
"underscore": "1.5.x"
},
"peerDependencies": {
"seneca": "*"
"lodash": "~2.4.1"
},
"files": [
"README.md",
Expand Down
40 changes: 40 additions & 0 deletions test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
./node_modules/.bin/mocha test/*.test.js

cd test
node basic.app.js --seneca.log=level:warn &
NODE_PID=$!
sleep 1
GET_FOO_a0=`curl -m 1 -s http://localhost:3000/api/rest/foo/a`
GET_FOO_b0=`curl -m 1 -s http://localhost:3000/api/rest/foo/b`
POST_FOO_a0=`curl -m 1 -s -d '{"tag":"AA","zed":1}' -H "Content-Type: application/json" http://localhost:3000/api/rest/foo/a`
GET_FOO_a1=`curl -m 1 -s http://localhost:3000/api/rest/foo/a`
kill -9 $NODE_PID

if [ $GET_FOO_a0 != '{"entity$":"-/-/foo","tag":"A","id":"a"}' ]; then
echo "FAIL: $GET_FOO_a0"
exit 1
else
echo "PASS: $GET_FOO_a0"
fi

if [ $GET_FOO_b0 != '{"entity$":"-/-/foo","tag":"B","id":"b"}' ]; then
echo "FAIL: $GET_FOO_b0"
exit 1
else
echo "PASS: $GET_FOO_b0"
fi

if [ $POST_FOO_a0 != '{"entity$":"-/-/foo","tag":"AA","zed":1,"id":"a"}' ]; then
echo "FAIL: $POST_FOO_a0"
exit 1
else
echo "PASS: $POST_FOO_a0"
fi

if [ $GET_FOO_a1 != '{"entity$":"-/-/foo","tag":"AA","id":"a","zed":1}' ]; then
echo "FAIL: $GET_FOO_a1"
exit 1
else
echo "PASS: $GET_FOO_a1"
fi

18 changes: 9 additions & 9 deletions test/basic.app.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
/* Copyright (c) 2013-2014 Richard Rodger */
/* Copyright (c) 2013-2015 Richard Rodger */
"use strict";


// node basic.app.js
// must be run inside test folder so static works

var connect = require('connect')
var connect = require('connect')
var serveStatic = require('serve-static')
var bodyParser = require('body-parser')

var seneca = require('seneca')()

seneca.use( require('..') )



var app = connect()

app.use( connect.static('./public') )
app.use( connect.bodyParser() )
app.use( connect.cookieParser() )
app.use( connect.json() )
app.use( serveStatic('./public') )
app.use( bodyParser.json() )
app.use( seneca.export('web') )

app.listen(3000)


var foo_ent = seneca.make('foo')
foo_ent.make$({tag:'a'}).save$()
foo_ent.make$({tag:'b'}).save$()
foo_ent.make$({id$:'a',tag:'A'}).save$()
foo_ent.make$({id$:'b',tag:'B'}).save$()


4 changes: 2 additions & 2 deletions test/jsonrest-api.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (c) 2013-2014 Richard Rodger */
/* Copyright (c) 2013-2015 Richard Rodger */
"use strict";


Expand All @@ -10,7 +10,7 @@ var assert = require('assert')
var util = require('util')


var _ = require('underscore')
var _ = require('lodash')
var gex = require('gex')


Expand Down
1 change: 0 additions & 1 deletion test/public/backbone.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.10/backbone-min.js"></script>
<script src="/js/util/browser.js"></script>
<script>
var Foo = Backbone.Model.extend({})
var FooList = Backbone.Collection.extend({url:'/api/rest/foo',model:Foo})
Expand Down

0 comments on commit 61bbef0

Please sign in to comment.