{"id":18084814,"url":"https://github.com/coderofsalvation/restglue","last_synced_at":"2025-04-12T20:09:42.902Z","repository":{"id":57355049,"uuid":"63780553","full_name":"coderofsalvation/restglue","owner":"coderofsalvation","description":"multi-api restful client (javascript) with endpoint-glue \u0026 promises (lightweight, no buildchain needed)","archived":false,"fork":false,"pushed_at":"2020-05-28T19:25:02.000Z","size":66,"stargazers_count":3,"open_issues_count":1,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-12T20:09:35.320Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/coderofsalvation.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"custom":"https://gumroad.com/l/hGYGh"}},"created_at":"2016-07-20T12:43:25.000Z","updated_at":"2023-08-18T10:49:59.000Z","dependencies_parsed_at":"2022-08-28T13:20:58.648Z","dependency_job_id":null,"html_url":"https://github.com/coderofsalvation/restglue","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coderofsalvation%2Frestglue","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coderofsalvation%2Frestglue/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coderofsalvation%2Frestglue/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coderofsalvation%2Frestglue/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/coderofsalvation","download_url":"https://codeload.github.com/coderofsalvation/restglue/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248625493,"owners_count":21135513,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-31T15:08:18.080Z","updated_at":"2025-04-12T20:09:42.871Z","avatar_url":"https://github.com/coderofsalvation.png","language":"JavaScript","funding_links":["https://gumroad.com/l/hGYGh"],"categories":[],"sub_categories":[],"readme":"\u003cimg src=\"logo.png\" style=\"width:80px; max-width:80px\" width=\"80\"/\u003e\n![Build Status](https://travis-ci.org/coderofsalvation/restglue.svg?branch=master)\nRESTGLUE: multi-api restful client using superagent \u0026 promises \n\n## Usage \n\n    \u003cscript type=\"text/javascript\" src=\"https://cdn.jsdelivr.net/es6-promise/3.1.2/es6-promise.min.js\"\u003e\u003c/script\u003e \u003c!-- older browsers --\u003e\n    \u003cscript type=\"text/javascript\" src=\"dist/restglue.min.js\"\u003e\u003c/script\u003e\n\n\u003e or in nodejs just do `npm install restglue superagent` and then:\n\n    var restglue = require('restglue')\n\n## Example: single api \n\n    var myapi = new restglue()\n    myapi.headers['Content-Type'] = 'application/json'\n    myapi.addEndpoint(\"pizza\")\n\nNot really exciting yet, but now you can do calls like so:\n\n    myapi.pizza.getAll()\n    .then( function(json){  // json-result of GET /pizza\n                            // call json.getResponse() for raw response (headers etc)\n    })\n    .catch( function(err){\n      console.log(\"could not get pizza\")\n    })\n\n\u003e NOTE: use `new restglue(\"http://api.foo.com/v1\")` to automatically prepend an external apiurl to all endpoints,  and make \nsure you got CORS setup on your server when doing requests from the browser.\n\n## Restful endpoint function reference\n\n    getAll(query, headers)                - will do GET     /pizza\n    post(payload, query, headers)         - will do POST    /pizza      {..}\n    get(id, query, headers)               - will do GET     /pizza/{id}\n    put(id, payload, query, headers)      - will do PUT     /pizza/{id} {..}\n    delete(id, payload, query, headers)   - will do DELETE  /pizza/{id} {..}\n    patch(id, payload, query, headers)    - will do PATCH   /pizza/{id} {..}\n    options(id, payload, querym headers)  - will do OPTIONS /pizza/{id} {..}\n\n\u003e NOTE: `query` and `headers` are optional and are used only for that request.\n\n## Custom endpoints + monkeypatch\n\n    myapi.pizza.customPost = restglue.prototype.request.bind( this, \"post\",  '/foo/bar',  {payload:true}, {queryfoo:1, querybar:2}, {X-HEADER-FOO:12} )\n    myapi.pizza.customGet  = restglue.prototype.request.bind( this, \"get\",  '/foo/bar' )\n\nAlso, you can monkeypatch these function to alter restglue's behaviour:\n\n    restglue.prototype.addEndpointg( resourcename  )\n    restglue.prototype.afterRequestg(cb)\n    restglue.prototype.beforeRequestg(cb)\n    restglue.prototype.composeg(chain)\n    restglue.prototype.constructorg(apiurl)\n    restglue.prototype.getSandboxedUrlg(method,url)\n    restglue.prototype.requestg(method, url, payload, query, headers)\n    restglue.prototype.sandboxUrlg(url,destination)\n    restglue.prototype.toQueryStringg(data)\n\n## Offline sandbox \n\nYou can fake responses (for offline development etc) in 2 ways, like so:\n\n    myapi.addEndpoint(\"foobar\")\n    myapi.addEndpoint(\"foo\")\n\n    myapi.sandboxUrl('/foobar',       {'data':{\"foo\":true}}  ) \n    myapi.sandboxUrl('/myapi',        {'path':\"/js/sandbox\"} )\n    myapi.sandboxUrl( /some.*regex/,  \"/js/foo\" )\n\n    myapi.foobar.getAll().then(function(data){    \n      // data = {\"foo\":true}\n    })\n\n    myapi.foo.getAll().then(function(data){    \n      // data = /js/sandbox/foo/get.json instead of GET {apiurl}/myapi/foo \n    })\n\n\u003e NOTE: {apiurl} is passed using `new restglue({apiurl:\"http://foo.com/v1\"})`    \n\n\n## Chained endpoints, multiple api's\n\n\u003e Byebye async spaghetti, welcome clean code.\n\nCombine multiple endpoints into one call:\n\n    myapi.pizza.getCookPageRanking = myapi.compose([\n      function(i)  { return myapi.pizza.getAll({\"sort\":\"-date_create\"})    },\n      function(res){ return otherapi.getRanking(res.cook.profile_url)      },\n      function(res){ return res.score                                      }\n    ])(\"foo\")\n\n    myapi.pizza.getCookPageRanking().then( function(res){\n      // res is '4'\n    }).catch( function(err){ ..  })\n\n## Example: query args \n\n    myapi.pizza.getAll( {\"sort\":\"-date_create\"} )\n    .then( function(res){\n      // result of GET /pizza?sort=-date_create\n    }\n    var password = \"bar\"\n    myapi.headers['Authorization'] = 'Basic '+btoa( login+\":\"+password )\n\n    // do calls\n\n## Example: response headers\n\n    myapi.pizza.getAll()\n    .then( function(res){\n      var headers = res.getResponse().headers\n    })\n\n\u003e NOTE: Make sure you have CORS configured properly on your server, otherwise certain headers won't be accessible in javascript.\n\n## Example: hooks\n\n`beforeRequest` and `afterRequest` allow you to massage the request or response\n\n    myapi.beforeRequest( function(config){\n      // format the input for an exotic api, before doing the actual request\n      config.payload = { type: \"payload\", payload:config.payload } \n    })\n\nHere's how to simply prevent unnecessary calls\n\n    var cache = {get:{}}\n\n    myapi.beforeRequest( function(config){\n      if( config.method == \"get\" \u0026\u0026 cache.get[config.url] ) return cache.get[config.url]\n    })\n\n    myapi.afterRequest( function(config, res, err){\n      if( config.method == \"get\" \u0026\u0026 !err ) cache.get[ config.url ] = res\n    })\n\n\u003e NOTE: optionally you can store a `new Date().getTime()` timestamp, and bypass the cache when expired \n\n## Example: Multi-api and mult-versioned wrappers \n\nThis easifies iterative, backwardscompatible development:\n\n    function getApi(){\n      var v1       = new restglue(\"http://api.foo.com/v1\"),\n      var v2       = new restglue(\"http://api.foo.com/v2\"),\n      var api      = {\n        ga: new restglue(\"https://www.googleapis.com/analytics/v3\") \n      }\n\n      // *TODO* call addEndpoint(...) on v1,v2 and googleanalytics\n\n      // ok, we're assuming the v1 and v2 endpoints are setup \n      // so now we set v1 endpoints as default \n      for( i in v1 ) api[i] = v1[i]\n\n      // but upgrade the pizza endpoint to v2 \n      api.pizza = v2.pizza \n    \n      return api \n    }\n\n    var myapi = getApi()\n\n## Example: HTTP auth \n\n    var login          = \"foo\"\n    var password       = \"bar\"\n\n    myapi.addEndpoint(\"user/current\")\n    myapi.headers['Authorization'] = 'Basic '+btoa( login+\":\"+password \n\n    myapi.pizza.getAll()\n    .then( function(res){\n\n      // authenticated response\n\n    })\n    .catch( function(err){\n      console.log(err)\n    })\n\n## Example: HTTP auth + bearer token\n\n    var login          = \"foo\"\n    var password       = \"bar\"\n\n    myapi.addEndpoint(\"user/current\")\n\n    myapi['user/current'].getAll(false, { 'Authorization': 'Basic '+btoa( login+\":\"+password ) })\n    .then( function(res){\n\n      if( ! res.bearer_hash ) throw new Exception(\"AUTH_FAILED\")\n      myapi.headers['Authentication'] = \"bearer \"+res.bearer_hash \n\n    })\n    .catch( function(err){\n      console.log(err)\n    })\n\n## Why superagent and not fetch?\n\nEventhough I prefer fetch, this module relies on superagent and not on fetch because:\n\n* I had some weird experiences with fetch-polyfill vs native fetch (I guess it needs a bit of time)\n* XHR request seems a more robust choice before fetch really takes over\n* superagent seems battletested and has a __lot__ of extensions and plugins\n\nAlso i noticed projects like [restful.js](https://github.com/marmelab/restful.js/tree/master), [frisbee](https://www.npmjs.com/package/frisbee), [superagent-defaults](https://www.npmjs.com/package/superagent-defaults), [superagent-jsonapify](https://www.npmjs.com/package/superagent-jsonapify),[superagent-ls](https://www.npmjs.com/package/superagent-ls),[superapi](https://www.npmjs.com/package/superagent-ls), [superagent-pool](https://github.com/lapwinglabs/superagent-pool), [super-res](https://www.npmjs.com/package/super-res)\n\nbut I needed a little bit more and less, in short I need:\n\n* a drop-in solution (not all js devs have  ES6/ES7 transpilertoolchain-experience)\n* easy chaining of endpoints, from multiple api's (hence async helpers included)\n* promises\n* requestpool cache but with TTL (hence the hooks, so the beforeRequest-hook can return a cached response)\n* compose a superapi (swap around endpoint versions)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoderofsalvation%2Frestglue","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcoderofsalvation%2Frestglue","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoderofsalvation%2Frestglue/lists"}