1.0.23 • Published 8 years ago

restglue v1.0.23

Weekly downloads
4
License
ISC
Repository
github
Last release
8 years ago

Usage

<script type="text/javascript" src="https://cdn.jsdelivr.net/es6-promise/3.1.2/es6-promise.min.js"></script> <!-- older browsers -->
<script type="text/javascript" src="dist/restglue.min.js"></script>

or in nodejs just do npm install restglue superagent and then:

var restglue = require('restglue')

Example: single api

var myapi = new restglue()
myapi.headers['Content-Type'] = 'application/json'
myapi.addEndpoint("pizza")

Not really exciting yet, but now you can do calls like so:

myapi.pizza.getAll()
.then( function(json){  // json-result of GET /pizza
                        // call json.getResponse() for raw response (headers etc)
})
.catch( function(err){
  console.log("could not get pizza")
})

NOTE: use new restglue("http://api.foo.com/v1") to automatically prepend an external apiurl to all endpoints, and make sure you got CORS setup on your server when doing requests from the browser.

Restful endpoint function reference

getAll(query, headers)                - will do GET     /pizza
post(payload, query, headers)         - will do POST    /pizza      {..}
get(id, query, headers)               - will do GET     /pizza/{id}
put(id, payload, query, headers)      - will do PUT     /pizza/{id} {..}
delete(id, payload, query, headers)   - will do DELETE  /pizza/{id} {..}
patch(id, payload, query, headers)    - will do PATCH   /pizza/{id} {..}
options(id, payload, querym headers)  - will do OPTIONS /pizza/{id} {..}

NOTE: query and headers are optional and are used only for that request.

Custom endpoints + monkeypatch

myapi.pizza.customPost = restglue.prototype.request.bind( this, "post",  '/foo/bar',  {payload:true}, {queryfoo:1, querybar:2}, {X-HEADER-FOO:12} )
myapi.pizza.customGet  = restglue.prototype.request.bind( this, "get",  '/foo/bar' )

Also, you can monkeypatch these function to alter restglue's behaviour:

restglue.prototype.addEndpointg( resourcename  )
restglue.prototype.afterRequestg(cb)
restglue.prototype.beforeRequestg(cb)
restglue.prototype.composeg(chain)
restglue.prototype.constructorg(apiurl)
restglue.prototype.getSandboxedUrlg(method,url)
restglue.prototype.requestg(method, url, payload, query, headers)
restglue.prototype.sandboxUrlg(url,destination)
restglue.prototype.toQueryStringg(data)

Offline sandbox

You can fake responses (for offline development etc) in 2 ways, like so:

myapi.addEndpoint("foobar")
myapi.addEndpoint("foo")

myapi.sandboxUrl('/foobar',       {'data':{"foo":true}}  ) 
myapi.sandboxUrl('/myapi',        {'path':"/js/sandbox"} )
myapi.sandboxUrl( /some.*regex/,  "/js/foo" )

myapi.foobar.getAll().then(function(data){    
  // data = {"foo":true}
})

myapi.foo.getAll().then(function(data){    
  // data = /js/sandbox/foo/get.json instead of GET {apiurl}/myapi/foo 
})

NOTE: {apiurl} is passed using new restglue({apiurl:"http://foo.com/v1"})

Chained endpoints, multiple api's

Byebye async spaghetti, welcome clean code.

Combine multiple endpoints into one call:

myapi.pizza.getCookPageRanking = myapi.compose([
  function(i)  { return myapi.pizza.getAll({"sort":"-date_create"})    },
  function(res){ return otherapi.getRanking(res.cook.profile_url)      },
  function(res){ return res.score                                      }
])("foo")

myapi.pizza.getCookPageRanking().then( function(res){
  // res is '4'
}).catch( function(err){ ..  })

Example: query args

myapi.pizza.getAll( {"sort":"-date_create"} )
.then( function(res){
  // result of GET /pizza?sort=-date_create
}
var password = "bar"
myapi.headers['Authorization'] = 'Basic '+btoa( login+":"+password )

// do calls

Example: response headers

myapi.pizza.getAll()
.then( function(res){
  var headers = res.getResponse().headers
})

NOTE: Make sure you have CORS configured properly on your server, otherwise certain headers won't be accessible in javascript.

Example: hooks

beforeRequest and afterRequest allow you to massage the request or response

myapi.beforeRequest( function(config){
  // format the input for an exotic api, before doing the actual request
  config.payload = { type: "payload", payload:config.payload } 
})

Here's how to simply prevent unnecessary calls

var cache = {get:{}}

myapi.beforeRequest( function(config){
  if( config.method == "get" && cache.get[config.url] ) return cache.get[config.url]
})

myapi.afterRequest( function(config, res, err){
  if( config.method == "get" && !err ) cache.get[ config.url ] = res
})

NOTE: optionally you can store a new Date().getTime() timestamp, and bypass the cache when expired

Example: Multi-api and mult-versioned wrappers

This easifies iterative, backwardscompatible development:

function getApi(){
  var v1       = new restglue("http://api.foo.com/v1"),
  var v2       = new restglue("http://api.foo.com/v2"),
  var api      = {
    ga: new restglue("https://www.googleapis.com/analytics/v3") 
  }

  // *TODO* call addEndpoint(...) on v1,v2 and googleanalytics

  // ok, we're assuming the v1 and v2 endpoints are setup 
  // so now we set v1 endpoints as default 
  for( i in v1 ) api[i] = v1[i]

  // but upgrade the pizza endpoint to v2 
  api.pizza = v2.pizza 

  return api 
}

var myapi = getApi()

Example: HTTP auth

var login          = "foo"
var password       = "bar"

myapi.addEndpoint("user/current")
myapi.headers['Authorization'] = 'Basic '+btoa( login+":"+password 

myapi.pizza.getAll()
.then( function(res){

  // authenticated response

})
.catch( function(err){
  console.log(err)
})

Example: HTTP auth + bearer token

var login          = "foo"
var password       = "bar"

myapi.addEndpoint("user/current")

myapi['user/current'].getAll(false, { 'Authorization': 'Basic '+btoa( login+":"+password ) })
.then( function(res){

  if( ! res.bearer_hash ) throw new Exception("AUTH_FAILED")
  myapi.headers['Authentication'] = "bearer "+res.bearer_hash 

})
.catch( function(err){
  console.log(err)
})

Why superagent and not fetch?

Eventhough I prefer fetch, this module relies on superagent and not on fetch because:

  • I had some weird experiences with fetch-polyfill vs native fetch (I guess it needs a bit of time)
  • XHR request seems a more robust choice before fetch really takes over
  • superagent seems battletested and has a lot of extensions and plugins

Also i noticed projects like restful.js, frisbee, superagent-defaults, superagent-jsonapify,superagent-ls,superapi, superagent-pool, super-res

but I needed a little bit more and less, in short I need:

  • a drop-in solution (not all js devs have ES6/ES7 transpilertoolchain-experience)
  • easy chaining of endpoints, from multiple api's (hence async helpers included)
  • promises
  • requestpool cache but with TTL (hence the hooks, so the beforeRequest-hook can return a cached response)
  • compose a superapi (swap around endpoint versions)
1.0.23

8 years ago

1.0.22

9 years ago

1.0.21

9 years ago

1.0.20

9 years ago

1.0.19

9 years ago

1.0.18

9 years ago

1.0.17

9 years ago

1.0.16

9 years ago

1.0.15

9 years ago

1.0.14

9 years ago

1.0.13

9 years ago

1.0.12

9 years ago

1.0.11

9 years ago

1.0.10

9 years ago

1.0.9

9 years ago

1.0.8

10 years ago

1.0.6

10 years ago

1.0.5

10 years ago

1.0.4

10 years ago

1.0.3

10 years ago

1.0.2

10 years ago

1.0.1

10 years ago

1.0.0

10 years ago