{"id":27890183,"url":"https://github.com/tibcosoftware/justapis-javascript-sdk","last_synced_at":"2025-12-12T04:23:20.286Z","repository":{"id":57287469,"uuid":"47996611","full_name":"TIBCOSoftware/justapis-javascript-sdk","owner":"TIBCOSoftware","description":"JustAPIs JavaScript SDK","archived":false,"fork":false,"pushed_at":"2016-09-07T19:54:22.000Z","size":964,"stargazers_count":1,"open_issues_count":11,"forks_count":2,"subscribers_count":6,"default_branch":"develop","last_synced_at":"2025-04-26T14:19:36.528Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://justapis.com","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/TIBCOSoftware.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-12-14T19:29:39.000Z","updated_at":"2023-03-16T21:37:10.000Z","dependencies_parsed_at":"2022-08-24T23:42:48.711Z","dependency_job_id":null,"html_url":"https://github.com/TIBCOSoftware/justapis-javascript-sdk","commit_stats":null,"previous_names":["anypresence/justapis-javascript-sdk"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TIBCOSoftware%2Fjustapis-javascript-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TIBCOSoftware%2Fjustapis-javascript-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TIBCOSoftware%2Fjustapis-javascript-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TIBCOSoftware%2Fjustapis-javascript-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TIBCOSoftware","download_url":"https://codeload.github.com/TIBCOSoftware/justapis-javascript-sdk/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252485557,"owners_count":21755817,"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":"2025-05-05T10:44:55.445Z","updated_at":"2025-12-12T04:23:20.239Z","avatar_url":"https://github.com/TIBCOSoftware.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\njustapis-javascript-sdk\n================================================================================\n\n[![Latest NPM release][npm-badge]][npm-badge-url]\n[![TravisCI Build Status][travis-badge]][travis-badge-url]\n\n[npm-badge]: https://img.shields.io/npm/v/justapis-javascript-sdk.svg\n[npm-badge-url]: https://www.npmjs.com/package/justapis-javascript-sdk\n[travis-badge]: https://img.shields.io/travis/AnyPresence/justapis-javascript-sdk.svg\n[travis-badge-url]: https://travis-ci.org/AnyPresence/justapis-javascript-sdk\n\nA lightweight JavaScript SDK to connect to a JustAPIs gateway in Node or\nthe browser.\n\n\nDependencies\n--------------------------------------------------------------------------------\n\n* [Native Promise Only](https://github.com/getify/native-promise-only)\n* [Tiny Emitter](https://github.com/scottcorgan/tiny-emitter)\n* [xml2js](https://www.npmjs.com/package/xml2js) (Node-only)\n* [xmlserializer](https://www.npmjs.com/package/xmlserializer) (Node-only)\n\n\nFeatures\n--------------------------------------------------------------------------------\n\n* Browser \u0026 Node.js support\n* HTTP request/response connection\n* HTTP Public Key Pinning\n* Per-request caching\n* Pausable/Resumable asynchronous request queue\n\n\nInstall via NPM\n--------------------------------------------------------------------------------\n\n```bash\n$ npm install justapis-javascript-sdk\n```\n\n\nSetup\n--------------------------------------------------------------------------------\n\nThe SDK is built with browserify. If you would like to add a single bundled file\nyou can find it in the `dist` folder.\n\n```html\n\u003cscript src=\"justapis-javascript-sdk/dist/justapis-javascript-sdk.min.js\"\u003e\u003c/script\u003e\n```\n\nElse, if you are using browserify in your project you probably prefer to use\n`require` to load the dependency.\n\n```javascript\nvar APGateway = require(\"justapis-javascript-sdk\");\n```\n\n\n### Creating a Gateway\n\nThe main object in the SDK is APGateway, you can think of it as an http client.\nTo make a request to an endpoint you just need to do\n\n```javascript\nvar APGateway = require(\"justapis-javascript-sdk\");\n\nvar options = {\n\turl: \"http://my.gateway.domain.org/users\",\n\tmethod: \"GET\",\n\theaders: {\n\t\t\"Foo\": \"Bar\"\n\t},\n\tdata: {\n\t\t\"name\": \"john\"\n\t}\n};\n\n// If you prefer objects you can do:\nvar gw = new APGateway(options);\n\n// Or you can create it like this\nvar gw = APGateway.create(options);\n\n// Now executing a request is as easy as\ngw.execute().then(function(response) {\n\t// Response came back ok...\n\tconsole.log(response.data);\n}).catch(function(error) {\n\t// An error occured :(\n\tconsole.log(error.message);\n});\n\n// Also you can reuse your gateway as many times as you like.\n// It will send the same request as before...\ngw.execute();\n\n// Or you can change only the pieces that you want and keep using it...\ngw.method(\"POST\").execute();\n```\n\n\n### Copying a Gateway\n\nA nice feature of gateways is that they can be copied. By copying a gateway you\nget all the configuration from the original, so you don't have to\nrepeat yourself.\n\n```javascript\nvar gw = new APGateway({\n\theaders: {\n\t\t\"Foo\": \"Bar\"\n\t}\n});\n\n// just call the copy method\nvar gwCopy = gw.copy();\n\ngwCopy.headers({\n\t\"Foo\": \"Hello World!\"\n});\n\ngw.headers(); // will return { \"Foo\": \"Bar\" }\ngwCopy.headers(); // will return { \"Foo\": \"Hello World!\" }\n```\n\n\nCaching Requests\n--------------------------------------------------------------------------------\n\n**Note: The Caching service behaves differently in Node than in the browser**\n\n`APGateway` allow for request caching per request. Only responses to GET\nrequests are cached, and this is enabled by default.\n\n```javascript\nvar gateway = new APGateway();\ngateway.cache(false);   // Disable caching from now on...\ngateway.execute();      // Send request without caching the response\ngateway.cache(true)     // Enable caching from now on...\n```\n\nWhen using it in Node, responses will be cached in-memory only by default.\nIn the browser however, cached responses will be saved to `localStorage`\nif available.\n\nSince `localStorage` is persistent, you might want to flush it at some point.\n\n```javascript\n// This will only remove localStorage entries set by\n// APGateway's request cache\nAPGateway.RequestCache.flush();\n```\n\nCached responses have a TTL (time to live) of 1 week (604800000 milliseconds).\nAny response older than that will be ignored and removed from the cache.\nIf you would like to use a different TTL you can set it like so:\n\n```javascript\n// ttl is in milliseconds\nAPGateway.RequestCache.ttl = 60000; // set ttl to 1 minute\n```\n\n\n### Custom Persistence\n\nIn some cases you may want to persist the cache in a different way. In the case\nof Node, for example, you may want to persist cached instances through a\ndatabase or external service. In order to do that you can replace `APGateway.RequestCache.storage` with your own implementation. Here is a small\nexample of how to do just that:\n\n```javascript\n// The storage object MUST have the following methods\nAPGateway.RequestCache.storage = {\n    /**\n     * Set key/value pair in storage\n     *\n     * key -\u003e string key identifying the value\n     * record -\u003e an Object containing two attributes:\n     *      'value' -\u003e the Object being cached\n     *      'timestamp' -\u003e already serialized Date string\n     *\n     * returns -\u003e a Promise to be resolved when set is finished (no resolve value needed)\n     */\n    set: function(key, record) {...},\n\n    /**\n     * Get a value from storage\n     *\n     * key -\u003e string identifying the value to retrieve\n     *\n     * returns -\u003e a Promise that resolves with the retrieved Object\n     */\n    get: function(key) {...},\n\n    /**\n     * Get all values in the storage. A prefix is passed that identifies the entire cache.\n     * This prefix is prepended to every key and used to differentiate one cache instance from another.\n     * It is only passed as a convenience, it is not required to use it internally.\n     *\n     * prefix -\u003e string prefix identifying the cache\n     *\n     * returns -\u003e a Promise that resolves with an Array of the retrieved objects (or empty Array if none)  \n     */\n    getAll: function(prefix) {...},\n\n    /**\n     * Removes a single record from the storage\n     *\n     * key -\u003e string key identifying the record\n     *\n     * returns -\u003e a Promise that resolves when the record has been removed (no resolve value needed)\n     */\n    remove: function(key) {...},\n\n    /**\n     * Removes all records from storage\n     *\n     * prefix -\u003e Same as with 'getAll()'\n     *\n     * returns -\u003e a Promise that resolves when flushing is complete (no resolve value needed)\n     */\n    flush: function(prefix) {...}\n\n};\n```\n\nYou may have noticed that all the required methods to override return a Promise,\nthis is meant as a convenience so you can easily work with async operations when\npersisting records. Any Promises/A+ compliant implementation can be used\n(or even native Promises if available), but in case you do not want to add a\npromise package just for this, **APGateway** uses an implementation internally\nthat you can find in `APGateway.Promise`.\n\n\nAsync request queue\n--------------------------------------------------------------------------------\n\n**APGateway** instances use an async queue internally to send requests.\nThis queue is shared across instances and can be paused/resumed to avoid sending\nfurther requests at any time. If your application goes offline you can pause the\nqueue, wait for reconnection, and resume it without loosing requests.\n\n```javascript\nAPGateway.Queue.pause();\nvar gateway = new APGateway();\ngateway\n    .url('http://localhost:1337/resource')\n    .execute() // This adds the request to the queue\n    .then(function(response) { /* Got response back */ })\n    .catch(function(error) { /* Got an error */ });\n\n// The queue will continue to build up until resumed\nAPGateway.Queue.resume();\n```\n\nWhenever the queue is resumed it will start sending pending requests\nasynchronously. Because the queue can get pretty big while paused, the queue\nwill throttle the flow of requests being sent to avoid flooding the server.\nThe default throttle time is 300 milliseconds, but you can adjust this by doing `APGateway.Queue.throttleBy(amountInMilliseconds)`.\n\n\n### Persisting the Queue\n\nIn some cases you might want to save the state of the queue either to\n`localStorage` or a database. For that purpose there's an export method on the\nqueue you can use.\n\n**Note: The queue must be paused before calling export,\notherwise an Error will be thrown**\n\n```javascript\n// Pause the queue\nAPGateway.Queue.pause();\n// requests will be an Array of requests\nvar requests = APGateway.Queue.export();\n\n// persists requests...\n```\n\nNow when get your persisted requests you can just resend them.\n\n```javascript\n// Get the saved requests from your storage of choice\n\nvar gateway = new APGateway();\npersistedRequests.forEach(function(requestData) {\n   // First we need to recreate the APRequest object\n   var request = Object.create(APGateway.APRequest, requestData);\n   gateway\n    .sendRequest(request)\n    .then(function(res) {\n        // Do something else\n    })\n    .catch(function(error) {\n        // There was an error\n    });\n});\n```\n\n\nAPGateway Instance Methods\n--------------------------------------------------------------------------------\n\n### Default Properties\n\n```javascript\nurl: {\n    href: \"http://localhost:5000\",\n    protocol: \"http:\",\t\t\t\n    hostname: \"localhost\",\n    port: \"5000\",\n    pathname: \"/\",\n    search: null,\n    hash: null\n},\nmethod: \"GET\",\nsilentFail: true,\ncache: true,\ndataType: \"json\",\ndata: {},\nheaders: {\n\t'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'\n},\nparsers: {\n    json: JSONParser,\n    form: FormDataParser,\n    xml: XMLParser\n},\ntransformations: {\n    request: [ EncodeTransformation ],\n\tresponse: [ DecodeTransformation, CacheResponse ]\n}\n```\n\n\n### Methods\n\n\n#### `url( url )`\nReturns the current url or the APGateway instance for quick chaining\n\n* `url`: `string`\n\t* If `url` is undefined the method will act as a getter, else it will set the\n\tvalue and return `this`.\n\n\n#### `method( method )`\nReturns the current http method or the APGateway instance for quick chaining\n\n* `method`: `string`\n\t* Accepted values `GET`, `POST`, `PUT`, `PATCH`, `DELETE`\n\t* If `method` is undefined the method will act as a getter, else it will set\n\tthe value and return `this`.\n\n\n#### `data( data )`\nReturns the current request data or the APGateway instance for quick chaining\n\n* `data`: `object`\n\t* If `data` is undefined the method will act as a getter, else it will set the\n\tvalue and return `this`.\n\n\n#### `dataType( dataType )`\nReturns the current response data type or the APGateway instance for\nquick chaining\n\n* `dataType`: `string`\n\t* If `dataType` is undefined the method will act as a getter, else it will set\n\tthe value and return `this`.  `json` and `xml` dataTypes are parsed\n\tautomatically, any other dataType will be returned as a string.\n\n\n#### `contentType( contentType )`\nReturns the current content type or the APGateway instance for quick chaining\n\n* `contentType`: `string`\n\t* If `contentType` is undefined the method will act as a getter, else it will\n\tset the value and return `this`.\n\n\n#### `headers( headers )`\nReturns the current headers or the APGateway instance for quick chaining\n\n* `headers`: `object`\n\t* The key-value pairs in `headers` will be appended to the current ones.\n\t* If `headers` is undefined the method will act as a getter, else it will set\n\tthe value and return `this`.\n\n\n#### `withCredentials( withCredentials )`\n\nReturns the current value of withCredentials or the APGateway instance for\nquick chaining\n\nEnabling `withCredentials` will cause any cookies to be included in the request\nto the server. The server needs to be configured to enable credentials as well\nby adding `Access-Control-Allow-Credentials: true` as a response header.\n\n* `withCredentials`: `boolean`\n\t* Default value: `false`\n\t* If `withCredentials` is undefined the method will act as a getter, else it\n\twill set the value and return `this`.\n\n\n#### `silentFail( silent )`\n\nReturns the current value of silentFail or the APGateway instance for\nquick chaining\n\nWhen a request is not successful `APGateway` will throw an error.\nSetting `silentFail` to `true` will cause the gateway to ignore those errors.\n\n* `silent`: `boolean`\n\t* Default value: `true`.  If `silent` is undefined the method will act as a\n\tgetter, else it will set the value and return `this`.\n\n\n#### `cache( active )`\n\nReturns the current value of cache or the APGateway instance for quick chaining\n\n* `active`: `boolean`\n\t* Default value: `true`.  If `active` is undefined the method will act as a\n\tgetter, else it will set the value and return `this`.\n\n\n#### `copy()`\n\nReturns a shallow copy of the APGateway instance.\n\n\n#### `requestTransformations( transformations )`\n\nReturns the current request transformations or the APGateway instance for\nquick chaining\n\n* `transformations`: `[function]`\n\t* Array of functions to transform the request configuration **before** it is\n\tsent to the server\n\t```javascript\n\t\tgw.requestTransformations([\n\t\t\t// transformations must ALWAYS return \"request\"\n\t\t\t// in order for the entire chain to work properly\n\t\t\tfunction(request) {...},\n\t\t\tfunction(request) {...}\t\t\n\t\t]);\n\t```\n\tIf undefined the method will act as a getter, else it will set the value and\n\treturn `this`.\n\n\n#### `responseTransformations( transformations )`\n\nReturns the current response transformations or the APGateway instance for\nquick chaining\n\n* `transformations`: `[function]`\n\t* Array of functions to transform the response object **after** it returns\n\tfrom the server\n\t```javascript\n\t\tgw.responseTransformations([\n\t\t\t// transformations must ALWAYS return \"response\"\n\t\t\t// in order for the entire chain to work properly\n\t\t\tfunction(response) {...},\n\t\t\tfunction(response) {...}\t\t\n\t\t]);\n\t```\n\tIf undefined the method will act as a getter, else it will set the value and\n\treturn `this`.\n\n\n#### `addRequestTransformation( transformation )`\n\nReturns the APGateway instance for quick chaining\n\n* `transformation`: `function`\n\t* Adds the transformation at the end of the request transformation chain\n\n\n#### `addResponseTransformation( transformation )`\n\nReturns the APGateway instance for quick chaining\n\n* `transformation`: `function`\n\t* Adds the transformation at the end of the response transformation chain\n\n\n#### `hpkp( options )`\n\nSets up [HTTP Public Key Pinning](https://developer.mozilla.org/en/docs/Web/Security/Public_Key_Pinning)\nfor the **APGateway** instance.\n\n* `options`: `object`\n  * `sha256s`: `[string]` (required)\n      * Array of **two** encoded public key information hashes. One is actually\n\t\t\tused, the other is kept as backup.\n  * `maxAge`: `number` (required)\n      * The time in seconds that the pinned key will be remembered for.\n  * `includeSubdomains`: `boolean` (optional)\n      * Applies the pinned key to subdomains also.\n  * `reportOnly`: `boolean` (optional)\n      * Specifies if pin validation failures should be reported to the given\n\t\t\tURL (if true `reportUri` must be present as well).\n  * `reportUri`: `string` (optional)\n      * URL to send pin validation failure reports to.\n\n\n#### `execute()`\n\nReturns a Promise\n\n* Executes a request with the current configuration\n\n\nFramework Integration\n--------------------------------------------------------------------------------\n\n### React\n\nThe SDK will work with React.js out of the box since its plain JavaScript.\n\n\n### Angular\n\nIntegrating with Angular.js is not a problem, here is an example of how you would use it.\n\n```javascript\nangular.module('MyModule')\n\t.controller('MyModuleController', ['$scope', function($scope) {\n\t\t// Declare a default message to show\n\t\t$scope.message = \"Default message\";\n\t\t// Create the gateway as usual...\n\t\tvar gateway = new APGateway();\n\n\t\tgateway\n\t\t.url('http://my.service/message')\n\t\t.execute()\n\t\t.then(function(response) {\n\t\t\t// Keep in mind, when updating the $scope, to use $apply\n\t\t\t//   so angular is made aware of the change\n\t\t\t$scope.$apply(function() {\n\t\t\t\t$scope.message = response.data;\n\t\t\t});\n\t\t});\n\n\n\t});\n```\n\n\n### Ember\n\nLike React or Angular, there is no restriction to use APGateway in an Ember application. If you're using Ember Data however you might want to integrate APGateway so you can load Models from it.\n\n\n#### Ember Data\n\nIn order to integrate with Ember Data you will want to create an [Adapter](http://emberjs.com/api/data/classes/DS.Adapter.html).\n\nThis example code shows the basic principle of how to integrate the two.\n\n**NOTE**: For simplicity's sake the example only shows implementations of `findRecord` and `createRecord` but when extending `DS.Adapter` you **must** implement the other methods too.\n\n```javascript\n// url of your endpoint\nvar URL = \"http://localhost:5000/todos\";\nvar gateway = new APGateway();\n\n// This helper will make sure that the response of the gateway runs\n// inside Ember's run loop.\nfunction runRequestToGateway(gateway) {\n\treturn Ember.RSVP.Promise(function(resolve, reject) {\n\t\tgateway\n\t\t.execute()\n\t\t.then(function(response) {\n\t\t\tEmber.run(null, resolve, response.data);\n\t\t})\n\t\t.catch(function(error) {\n\t\t\tEmber.run(null, reject, error);\n\t\t});\n\t});\n}\n\n// Register an ApplicationAdapter that uses APGateway internally...\nTodos.ApplicationAdapter = DS.Adapter.extend({\n\n\tfindRecord: function(store, type, id, snapshot) {\n\t\tgateway\n\t\t.method(\"GET\")\n\t\t.url(URL + \"/\" + id)\n\t\t.silentFail(false);\n\n\t\treturn runRequestToGateway(gateway);\n\t},\n\n\tcreateRecord: function(store, type, snapshot) {\n\t\tvar data = this.serialize(snapshot, { includeId: true });\n\n\t\tgateway\n\t\t.url(URL)\n\t\t.method(\"POST\")\n\t\t.data(data)\n\t\t.silentFail(false);\n\n\t\treturn runRequestToGateway(gateway);\n\t},\n\n\tupdateRecord: function(store, type, snapshot) {...},\n\n\tdeleteRecord: function(store, type, snapshot) {...},\n\n\tfindAll: function(store, type, sinceToken, snapshotRecordArray) {...},\n\n\tquery: function(store, type, query, recordArray) {...}\n});\n```\n\n\nDevelopment\n--------------------------------------------------------------------------------\n\nIf you would like to develop in the SDK you can just download the repository\nand do\n\n```bash\nnpm install\n```\n\nOnce that finishes, just use grunt to start the `watch` process\n\n```bash\ngrunt\n```\n\n\nContribution Guidelines\n--------------------------------------------------------------------------------\n\nThis repository relies on [semantic-release-cli][semantic-release-cli] for automated\nreleases and [commitizen][commitizen] and\n[cz-conventional-changelog][cz-conventional-changelog] for standardized commit\nmessages and automated changelogs.\n\n\n### Committing\n\nAll work should be committed to a new branch off `develop`, never to a mainline\nbranch directly.  When ready to commit changes, stage them as usual with:\n\n\t\tgit add .\n\nCommitting changes is a little different.  In order to ensure standardized\ncommit messages across time and contributors, always use the npm script:\n\n\t\tnpm run commit\n\nand follow the instructions on screen.\n\n**Note**:  for an overview of commitizen and the conventional changelog tool,\n[watch the video][commitizen-video].\n\n[semantic-release-cli]: https://www.npmjs.com/package/semantic-release-cli\n[commitizen]: https://www.npmjs.com/package/commitizen\n[cz-conventional-changelog]: https://www.npmjs.com/package/cz-conventional-changelog\n[commitizen-video]: https://egghead.io/lessons/javascript-how-to-write-a-javascript-library-committing-a-new-feature-with-commitizen\n\n\n### Pull Requests\n\nWhen a branch is ready to merge, submit a pull request to `develop` via GitHub.\nPull requests are automatically tested on Travis CI and may not be merged until\nall tests pass.  At that time, a team member may safely merge the PR\ninto `develop`.\n\n\n### Releasing\n\nReleases are made from the `master` branch automatically.  To initiate a\nrelease, create a PR from `develop` to `master`.  Since releasing is automated,\nthe timing and extent of these PR's is at the discretion of team members.\n\nReleasing is automated with `semantic-release`.  An automatic release is tagged\nand published to npm upon a successful merge into the `master` branch only after\nall tests successfully pass.  No human intervention is required to create\nreleases other than merging a PR.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftibcosoftware%2Fjustapis-javascript-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftibcosoftware%2Fjustapis-javascript-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftibcosoftware%2Fjustapis-javascript-sdk/lists"}