npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

restglue

v1.0.23

Published

multi-api restful client (javascript) with glue, using superagent & promises (lightweight, no buildchain needed)

Downloads

31

Readme

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)