{"_id":"@ama-team/voxengine-sdk","_rev":"10-681f7c67235958f01ac37914f5d95fe2","name":"@ama-team/voxengine-sdk","description":"Bundle of helper functions and classes for VoxEngine scenario scripts","dist-tags":{"latest":"0.4.0"},"versions":{"0.1.0":{"name":"@ama-team/voxengine-sdk","version":"0.1.0","description":"Bundle of helpers for VoxEngine scenario scripts","main":"index.js","scripts":{"test":"mocha","test:coverage:report":"istanbul cover _mocha","test:coverage":"npm run test:coverage:report && npm run coveralls","coveralls":"cat report/coverage/lcov.info | node_modules/.bin/coveralls","test:ignore":"npm run test || true","test:report":"npm run allure:clean && npm run test:ignore && npm run allure:report","allure:clean":"rm -rf report/allure-results report/allure","allure:report":"allure generate -o report/allure -- report/allure-results","allure:open":"allure report open -o report/allure"},"repository":{"type":"git","url":"git+https://github.com/ama-team/voxengine-sdk.git"},"keywords":["voximplant"],"author":{"name":"AMA Team"},"license":"MIT","bugs":{"url":"https://github.com/ama-team/voxengine-sdk/issues"},"homepage":"https://github.com/ama-team/voxengine-sdk#readme","dependencies":{"@ama-team/voxengine-definitions":"^0.1.0","promise":"^7.1.1"},"devDependencies":{"chai":"^3.5.0","chai-as-promised":"^6.0.0","chai-string":"^1.3.0","coveralls":"^2.11.15","istanbul":"^0.4.5","mocha":"^3.1.2","mocha-allure-reporter":"^1.2.4","mocha-multi":"^0.9.1","mocha-multi-reporters":"^1.1.1","sinon":"^1.17.6","sinon-as-promised":"^4.0.2"},"gitHead":"c92c7bb5f055efb71096bda5236f89c933af0b78","_id":"@ama-team/voxengine-sdk@0.1.0","_shasum":"cb16fcdce208bbd6bcc4f07ac2cd3add54e0aee9","_from":".","_npmVersion":"3.10.10","_nodeVersion":"6.9.5","_npmUser":{"name":"ama-team","email":"dev@amagroup.ru"},"dist":{"shasum":"cb16fcdce208bbd6bcc4f07ac2cd3add54e0aee9","tarball":"https://registry.npmjs.org/@ama-team/voxengine-sdk/-/voxengine-sdk-0.1.0.tgz","integrity":"sha512-YzXESKGo97QRUOYy1MmVZAPqNOqAhTHrW+qaI5SUG8QJlnnGiUPulqmeXm9XnW38ADxZfjOvB+qPwJwHdqWYsg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHHUM3KntYJS28PsxgdiKYBcoOY2vdC1BNBvekjrs66sAiEAw9+qL4aJ+ygXTj4xEwtqTDkr7tP1Du+5F726CbyvNCs="}]},"maintainers":[{"name":"ama-team","email":"dev@amagroup.ru"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/voxengine-sdk-0.1.0.tgz_1487080523023_0.4602713657077402"},"directories":{}},"0.1.1":{"name":"@ama-team/voxengine-sdk","version":"0.1.1","description":"Bundle of helpers for VoxEngine scenario scripts","main":"index.js","scripts":{"clean":"rm -rf build","test":"istanbul cover _mocha","test:report:allure":"allure generate -o build/report/allure -- build/data/allure","test:report:allure:open":"allure report open -o build/report/allure","test:report":"npm run test:report:allure","test:report:publish:coverage":"cat build/report/coverage/lcov.info | node_modules/.bin/coveralls","test:report:publish":"npm run test:report:publish:coverage","npm:login":"npm-cli-login"},"repository":{"type":"git","url":"git+https://github.com/ama-team/voxengine-sdk.git"},"keywords":["voximplant","voxengine"],"author":{"name":"AMA Team","email":"dev@amagroup.ru","url":"http://amagroup.ru"},"license":"MIT","bugs":{"url":"https://github.com/ama-team/voxengine-sdk/issues"},"homepage":"https://github.com/ama-team/voxengine-sdk#readme","dependencies":{},"devDependencies":{"@ama-team/voxengine-definitions":"^0.1.0","promise":"^7.1.1","chai":"^3.5.0","chai-as-promised":"^6.0.0","chai-string":"^1.3.0","coveralls":"^2.11.15","istanbul":"^0.4.5","mocha":"^3.1.2","mocha-allure-reporter":"^1.2.4","mocha-multi":"^0.9.1","mocha-multi-reporters":"^1.1.1","npm-cli-login":"0.0.10","npm-utils":"^1.11.0","sinon":"^1.17.6","sinon-as-promised":"^4.0.2"},"gitHead":"745f3ee4bdc95cad93ece8571a9b199fd0e4f7a5","_id":"@ama-team/voxengine-sdk@0.1.1","_shasum":"b32cd86f0b01880d396957413cd9077abbcb66e2","_from":".","_npmVersion":"2.14.12","_nodeVersion":"4.2.6","_npmUser":{"name":"ama-bot","email":"ops@amagroup.ru"},"dist":{"shasum":"b32cd86f0b01880d396957413cd9077abbcb66e2","tarball":"https://registry.npmjs.org/@ama-team/voxengine-sdk/-/voxengine-sdk-0.1.1.tgz","integrity":"sha512-7Xvlr70n9/521+DH+ad4aAVk+9gSrSBogAV19M+ezgfZj7lTrgfCShmpNOl82PAieFP1OiNSwAcxRzwRV6WGRA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCbMB7biIf02Al7iTqyMCUcOQAY1PEVgZN+6LRg1SltWAIhAKL7LWLNFB/xhfGJ/Ld2d6PvU6VvwwJ5OCq2DSjY421k"}]},"maintainers":[{"name":"ama-bot","email":"ops@amagroup.ru"},{"name":"ama-team","email":"dev@amagroup.ru"},{"name":"etki","email":"etki@etki.me"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/voxengine-sdk-0.1.1.tgz_1487898247606_0.54499387787655"},"directories":{}},"0.2.0":{"name":"@ama-team/voxengine-sdk","version":"0.2.0","description":"Bundle of helpers for VoxEngine scenario scripts","main":"lib/index.js","scripts":{"clean":"rm -rf build","test":"istanbul cover node_modules/.bin/_mocha","test:report:allure":"allure generate -o build/report/allure -- build/data/allure","test:report:allure:open":"allure report open -o build/report/allure","test:report":"npm run test:report:allure","test:report:publish:coverage":"cat build/report/coverage/lcov.info | node_modules/.bin/coveralls","test:report:publish":"npm run test:report:publish:coverage","doc":"jsdoc -d build/doc lib"},"repository":{"type":"git","url":"git+https://github.com/ama-team/voxengine-sdk.git"},"keywords":["voximplant","voxengine"],"author":{"name":"AMA Team","email":"dev@amagroup.ru","url":"http://amagroup.ru"},"license":"MIT","bugs":{"url":"https://github.com/ama-team/voxengine-sdk/issues"},"homepage":"https://github.com/ama-team/voxengine-sdk#readme","dependencies":{},"devDependencies":{"@ama-team/allure-polyfill":"^0.1.0","@ama-team/voxengine-definitions":"^0.1.0","chai":"^3.5.0","chai-as-promised":"^6.0.0","chai-string":"^1.3.0","coveralls":"^2.11.15","istanbul":"^0.4.5","jsdoc":"^3.4.3","mocha":"^3.1.2","mocha-allure-reporter":"^1.2.4","mocha-junit-reporter":"^1.13.0","mocha-multi":"^0.9.1","mocha-multi-reporters":"^1.1.1","npm-cli-login":"0.0.10","npm-utils":"^1.11.0","promise":"^7.1.1","sinon":"^1.17.6","sinon-as-promised":"^4.0.2"},"_id":"@ama-team/voxengine-sdk@0.2.0","_shasum":"fa5df925e00ff40bb54d15e8e4004d02ece4ff90","_from":".","_npmVersion":"2.14.12","_nodeVersion":"4.2.6","_npmUser":{"name":"ama-bot","email":"ops@amagroup.ru"},"dist":{"shasum":"fa5df925e00ff40bb54d15e8e4004d02ece4ff90","tarball":"https://registry.npmjs.org/@ama-team/voxengine-sdk/-/voxengine-sdk-0.2.0.tgz","integrity":"sha512-hgHZgtLmvw8adLRBumPajUT3t2mUFLZYRIqtm1oCGNLtlTBfTyr23O1jhp7yJP86nC4yprEN9v9rG1RS0/KrVA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCeJF5I8h1dUcuMT6/EUnmaMTpd9EZtklPFebKJWyku6gIhAK8JlqUH2PJL/d6JZOJByFUw2qPw3xlS/FTFb1tLT3Oa"}]},"maintainers":[{"name":"ama-bot","email":"ops@amagroup.ru"},{"name":"ama-team","email":"dev@amagroup.ru"},{"name":"etki","email":"etki@etki.me"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/voxengine-sdk-0.2.0.tgz_1488100267656_0.3133519454859197"},"directories":{}},"0.3.0":{"name":"@ama-team/voxengine-sdk","version":"0.3.0","description":"Bundle of helper functions and classes for VoxEngine scenario scripts","main":"lib/index.js","scripts":{"clean":"rm -rf build","lint":"standard","minify":"jake minify","test":"jake test","test:coverage":"jake test:coverage","test:report":"jake test:report","test:with-report":"jake test:with-report","test:report:publish":"jake test:report:publish","doc":"jsdoc -d tmp/doc -r lib -R README.md"},"repository":{"type":"git","url":"git+https://github.com/ama-team/voxengine-sdk.git"},"keywords":["voximplant","voxengine"],"author":{"name":"AMA Team","email":"dev@amagroup.ru","url":"http://amagroup.ru"},"license":"MIT","bugs":{"url":"https://github.com/ama-team/voxengine-sdk/issues"},"homepage":"https://github.com/ama-team/voxengine-sdk#readme","dependencies":{},"devDependencies":{"@ama-team/allure-polyfill":"^0.1.0","@ama-team/voxengine-definitions":"^0.1.0","chai":"^3.5.0","chai-as-promised":"^6.0.0","chai-string":"^1.3.0","coveralls":"^2.11.15","fs-extra":"^4.0.1","glob":"^7.1.2","istanbul":"^0.4.5","jake":"^8.0.15","js-yaml":"^3.9.1","jsdoc":"^3.4.3","mocha":"^3.1.2","mocha-allure-reporter":"^1.2.4","mocha-junit-reporter":"^1.13.0","mocha-multi":"^0.9.1","mocha-multi-reporters":"^1.1.1","npm-cli-login":"0.0.10","npm-utils":"^1.11.0","promise":"^7.1.1","promises-aplus-tests":"*","sinon":"^3.2.0","standard":"^9.0.0","uglify-js":"^3.0.27"},"standard":{"globals":["Logger","Net"],"ignore":["examples/*/node_modules","examples/*/dist"]},"gitHead":"598926c00c2905f35167cb47088fe50ae8445850","_id":"@ama-team/voxengine-sdk@0.3.0","_shasum":"73adef8c36c291918ac3eaed576fd9127dbab35a","_from":".","_npmVersion":"2.15.11","_nodeVersion":"4.8.4","_npmUser":{"name":"ama-bot","email":"ops@amagroup.ru"},"dist":{"shasum":"73adef8c36c291918ac3eaed576fd9127dbab35a","tarball":"https://registry.npmjs.org/@ama-team/voxengine-sdk/-/voxengine-sdk-0.3.0.tgz","integrity":"sha512-ywM04NoajmfHyRswfFzHWVZhFKj1i3EsiqYeF0edo3mBzcF76W//iINqK8D4O/zBmkY3KHgRw2h2NfEMsu7ytg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCE9pvImiQRKnEuJEZC++w/44cITBeFjt/pCvGcUy6dkQIgOgstlVPWfpq83tqFE/OJF/c+mG48hpAfmauj7VkARDc="}]},"maintainers":[{"name":"ama-bot","email":"ops@amagroup.ru"},{"name":"ama-team","email":"dev@amagroup.ru"},{"name":"etki","email":"etki@etki.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/voxengine-sdk-0.3.0.tgz_1503304538546_0.2510296239051968"},"directories":{}},"0.4.0":{"name":"@ama-team/voxengine-sdk","version":"0.4.0","description":"Bundle of helper functions and classes for VoxEngine scenario scripts","main":"lib/index.js","scripts":{"clean":"rm -rf build","lint":"standard","minify":"jake minify","test":"jake test","test:coverage":"jake test:coverage","test:report":"jake test:report","test:with-report":"jake test:with-report","test:report:publish":"jake test:report:publish","doc":"jsdoc -d tmp/doc -r lib -R README.md"},"repository":{"type":"git","url":"git+https://github.com/ama-team/voxengine-sdk.git"},"keywords":["voximplant","voxengine"],"author":{"name":"AMA Team","email":"dev@amagroup.ru","url":"http://amagroup.ru"},"license":"MIT","bugs":{"url":"https://github.com/ama-team/voxengine-sdk/issues"},"homepage":"https://github.com/ama-team/voxengine-sdk#readme","dependencies":{},"devDependencies":{"@ama-team/allure-polyfill":"^0.1.0","@ama-team/voxengine-definitions":"^0.1.0","chai":"^3.5.0","chai-as-promised":"^6.0.0","chai-string":"^1.3.0","coveralls":"^2.11.15","fs-extra":"^4.0.1","glob":"^7.1.2","istanbul":"^0.4.5","jake":"^8.0.15","js-yaml":"^3.9.1","jsdoc":"^3.4.3","mocha":"^3.1.2","mocha-allure-reporter":"^1.2.4","mocha-junit-reporter":"^1.13.0","mocha-multi":"^0.9.1","mocha-multi-reporters":"^1.1.1","npm-cli-login":"0.0.10","npm-utils":"^1.11.0","promise":"^7.1.1","promises-aplus-tests":"*","sinon":"^3.2.0","standard":"^9.0.0","uglify-js":"^3.0.27"},"standard":{"globals":["Logger","Net"],"ignore":["examples/*/node_modules","examples/*/dist"]},"gitHead":"1a164b13630984602417b18e42e043509bf54aa4","_id":"@ama-team/voxengine-sdk@0.4.0","_shasum":"252fc4cf43e5ccc3b54914f6f36ffe67a0e4ac0d","_from":".","_npmVersion":"2.15.11","_nodeVersion":"4.8.4","_npmUser":{"name":"ama-bot","email":"ops@amagroup.ru"},"dist":{"shasum":"252fc4cf43e5ccc3b54914f6f36ffe67a0e4ac0d","tarball":"https://registry.npmjs.org/@ama-team/voxengine-sdk/-/voxengine-sdk-0.4.0.tgz","integrity":"sha512-C4xa4W3GLSG+WGVlivuUoeGmqSE/sWs5mtonBxkalfzzVy1bMEJrds7Mu7xGuA/BF3dx4DxnKSN39N+lCRYjGA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCiSBedy6NDjusxly2XduP7kKVutXlpSHzPbap1l+NXIwIgSJw0U+2L+E7eh1tsbxVvmbou/mXiQMii3LOQpN9szB4="}]},"maintainers":[{"email":"etki@etki.me","name":"etki"},{"email":"ops@amagroup.ru","name":"ama-bot"},{"email":"dev@amagroup.ru","name":"ama-team"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/voxengine-sdk-0.4.0.tgz_1504490881530_0.0808012681081891"},"directories":{}}},"readme":"# (Unofficial) VoxEngine SDK\n\n[![npm version](https://img.shields.io/npm/v/@ama-team/voxengine-sdk.svg?style=flat-square)](https://www.npmjs.com/package/@ama-team/voxengine-sdk) \n[![CircleCI](https://img.shields.io/circleci/project/github/ama-team/voxengine-sdk/master.svg?style=flat-square)](https://circleci.com/gh/ama-team/voxengine-sdk)\n[![Coveralls](https://img.shields.io/coveralls/ama-team/voxengine-sdk/master.svg?style=flat-square)](https://coveralls.io/github/ama-team/voxengine-sdk?branch=master)\n[![Code Climate](https://img.shields.io/codeclimate/github/ama-team/voxengine-sdk.svg?style=flat-square)](https://codeclimate.com/github/ama-team/voxengine-sdk)\n[![Scrutinizer](https://img.shields.io/scrutinizer/g/ama-team/voxengine-sdk/master.svg?style=flat-square)](https://scrutinizer-ci.com/g/ama-team/voxengine-sdk/issues/master)\n\nThis repository contains simple SDK to ease development of VoxImplant \nscenarios. It has:\n\n- Promise-based HTTP client\n- Promise-based REST client\n- [SLF4J][]-alike logger\n- Some concurrent primitives that may be required during development\n(timeout, delay, task queue, completable promise)\n\nIt may be installed via classic npm call\n\n```bash\nnpm i @ama-team/voxengine-sdk --save\n```\n\nAnd required as any other package:\n\n```js\nvar SDK = require('@ama-team/voxengine-sdk')\n```\n\n## SLF4J-alike Logger\n\nThis library wraps standard `Logger` and adds support for logger names,\nlog levels and log message parameters (substitutions):\n\n```js\nvar Slf4j = SDK.Logger.Slf4j\nvar logger = Slf4j.create('logger.name')\n\n// ...\n\nvar user = 'Pavel'\nvar elapsed = 12.345\nvar metadata = {roles: ['lead'], extras: []}\n    \ncall.addEventListener(CallEvents.Connected, function () {\n  logger.info('{} has responded in {} seconds (meta: {})', user, elapsed, metadata)\n  // [INFO] logger.name: Pavel has responded in 12.345 seconds (meta: {\"roles\": [\"lead\"], \"extras\": []})\n});\n```\n\nThis logger provides `.trace()`, `.debug()`, `.info()`, `.notice()`, \n`.warn()`, `.error()` and `.log(Logger.Level.*, pattern, substitutions...)` \nmethods to print things. \n\n### Substitutions\n\nThis logger uses following algorithm for injecting provided arguments:\n\n- While another placeholder is available, replace it with short \nrepresentation of an argument\n- When there are no more placeholders, jump to new line and print\nlong argument representation\n\nMost of the types, there is no difference between two representations.\nHowever,\n\n- Custom `.toString()` implementation will be used in short \nrepresentations\n- If not provided with custom `.toString()`, errors will be\nrepresented as `<$.name: $.message>` in short mode\n- Objects are represented using JSON in long representations\n- Long error representations are basically concatenation of\nshort representation with stack\n\n```js\nlogger.error('{} was caused by:', new Error('alpha'), new Error('beta'))\n// ERROR logger.name: <Error: alpha> was caused by:\n// <Error: beta>\n// Stack:\n//   ...\n````\n\nSo in order to see stack traces you need to have at most as many\nplaceholders as there are arguments before error.\n\n### MDC \nThere are `.attach(key, value)`, `.detach(key)`, `.attachAll(object)` \nand `.detachAll()` methods for functionality known as Mapped Diagnostic\nContext in Logback:\n\n```js\nlogger.attach('id', '123')\nlogger.info('Sending custom event')\n// [INFO] logger.name [id=123]: Sending custom event \n```\n\nThis may help you if you have similar logging output but need to \ndistinguish components one from another.\n\n### Configuring\n\nEvery logger may be created with particular level and writer, as\nwell as swap them in runtime:\n\n```js\n// please note that Logger symbol (last parameter) comes from VoxEngine, not from SDK\nvar logger = Slf4j.create('logger.name', Slf4j.Level.Info, Logger)\nlogger.setLevel(Slf4j.Level.Notice)\nlogger.setLevel('warn')\nlogger.setWriter(Logger)\n```\n\nThis functionality is also exported via `Slf4j` static methods:\n\n```js\nSlf4j.setLevel('logger.name', 'info')\nSlf4j.setWriter('logger.name', Logger)\n```\n\nso you can control loggers buried deep in other components.\n\nLogger level and writer are looked up hierarchically: if no \nlevel / writer is found for current name, search continues for parent \none. Names are separated using dots, so `logger.name` will use \n`logger.name`, `logger`, `(root)` lookup chain.\n\n## Basic HTTP Client\n\nThis client is a simple wrapper around `Net.httpRequestAsync` primitive\n\n```js\nvar SDK = require('@ama-team/voxengine-sdk')\nvar options = {\n  url: 'http://my.backend.com',\n  retries: 9,\n  throwOnServerError: true\n}\nvar client = new SDK.Http.Basic(options);\n\nvar call = client\n  .get('/magic-phone-number.txt')\n  .then(function(response) {\n    return VoxEngine.callPSTN(response.payload);\n  });\n```\n\nBasic client provides you with following methods:\n\n- `get(url, [query, headers, timeout])`\n- `head(url, [query, headers, timeout])`\n- `post(url, [payload, headers, timeout])`\n- `put(url, [payload, headers, timeout])`\n- `patch(url, [payload, headers, timeout])`\n- `delete(url, [payload, headers, timeout])`\n- `request(method, url, [query, payload, headers, timeout])`\n\nwith following rules:\n\n- Query is an object where every key is associated with a\nstring value or array of string values:\n`{page: '1', filters: ['active', 'fresh']}`.\n- The same applies to headers object.\n- Payload may be either a string or falsey value.\n- URL is built by simple concatenation of `options.url` and `url` \nmethod argument, so it would be \n`http://my.backend.com/magic-phone-number.txt` in the example. In case \nyou need to use same client to talk to different hosts, just don't \nspecify url in options - it would be set to empty string.\n- Method is a string and can be set using `SDK.Http.Method` enum.\n\nEvery method returns a promise that either resolves with response or\nrejects with `SDK.Http.NetworkException`, `SDK.Http.HttpException`, one \nof their children or `SDK.Http.InvalidConfigurationException`. \nIn case of reject, received exception should have `.name`, `.message`, \n`.code`, `.request` and sometimes `.response` fields (except for \n`InvalidConfigurationException`). \n\nWhether an error will be thrown and how many retries will be made is \ndefined in client settings passed as first constructor argument:\n\n```js\nvar settings = {\n    retryOnNetworkError: true,\n    throwOnServerError: false,\n    retryOnServerError: true,\n    throwOnClientError: false,\n    retryOnClientError: false,\n    // NotFound is a special case for 404 response code\n    throwOnNotFound: false,\n    retryOnNotFound: false,\n    // VoxImplant is capable only of emitting GET and POST requests,\n    // but this may be overcome by providing real method in\n    // additional header\n    methodOverrideHeader: 'X-HTTP-Method-Override',\n    // those will be used on every request unless headers \n    // specified with request override these \n    headers: {},\n    // maximum amount of request retries\n    retries: 4,\n    // default timeout in milliseconds\n    timeout: 1000,\n    // alternative logger options\n    logger: {\n      level: SDK.Logger.Level.Info,\n      name: 'custom-name',\n      // mapping diagnostic context as described above\n      mdc: {\n        entity: 'call#123'\n      },\n      instance: new MyCustomLogger()\n    }\n};\n```\n\nYou can tune client as you want to throw exceptions or return responses\non certain outcomes. Network errors always result in exception, \nhowever, you may enforce several retries to be made.\n\n## REST client\n\nREST client is a wrapper around basic HTTP client that operates over\nentities rather than HTTP requests/responses. It adds automatic \nserialization/deserialization support, provides `exists`, `get`, \n`create`, `set`, `modify` and `delete` methods and adds following rules:\n\n- Any client error results in corresponding exception\n- Any server error also results in exception, but retries for specified \namount of times\n- `.exists()` method is a wrapper around HEAD-request and returns boolean \nin promise, treating 404 as false and any 2xx as true\n- `.get()` method is a wrapper around GET-request and returns null on 404\n- Non-safe data-changing methods (all others) treat 404 as an error and \ntrigger `http.NotFoundException`\n- There are fallback methods `.request()` and `.execute()` in case you have \nsome logic depending on response codes.\n\nThe signatures are:\n\n- `get(resource, [query, headers, timeout])`\n- `exists(resource, [query, headers, timeout])`\n- `create(resource, [payload, headers, query, timeout])`\n- `set(resource, [payload, headers, query, timeout]) : PUT`\n- `modify(resource, [payload, headers, query, timeout]) : PATCH`\n- `delete(resource, [payload, headers, query, timeout])`\n \nSo you may talk to your backend like that:\n \n```js\nvar rest = new SDK.Http.Rest()\nvar user = rest\n  .get('/user', {phone: number, size: 1})\n  .then(function (response) {\n    return response ? response.content[0] : rest.create('/user', {phone: number});\n  });\n```\n\nREST client is configured very similarly to HTTP client:\n\n```js\nvar options = {\n  // this will be prepended to all routes you pass into client\n  url: 'http://backend/api/v1',\n  // you will certainly need to set this if you're going to use anything but .get/.create\n  methodOverrideHeader: 'X-HTTP-Method-Override',\n  // that's pretty much the default\n  retries: 4,\n  // this is set by default as well\n  serializer: {\n    serialize: JSON.stringify,\n    deserialize: JSON.parse\n  },\n  // again, a set of headers that will always be present in \n  // requests (unless overriden in particular request)\n  headers: {\n    'Content-Type': 'application/json'\n  },\n  // default timeout\n  timeout: 1000,\n  // same logger options\n  logger: {}\n}\nvar client = new SDK.Http.Rest(options);\n```\n\n## Future\n\nThis SDK also provides an externally-completable promise called Future\nfor brevity. It has the same interface as standard promise, but also\nexposes `#resolve()` and `#reject()` instance methods:\n\n```js\nvar Future = SDK.Concurrent.Future\n\nvar race = Future.race([new Future(), new Future()])\nrace.resolve('hijack')\nrace.reject('will be ignored')\nvar future = new Future(function (resolve, reject) {\n  Math.random() > 0.5 ? resolve() : reject()\n})\n```\n\nFuture passes all Promises/A+ \n[compliance tests](https://github.com/promises-aplus/promises-tests).\n\n## timeout\n\n`timeout` function allows you to wrap promise with another one which \nwill auto-reject after specified time. Most of the time you won't need \nthis, because VoxEngine automatically times out long dials and \nrequests, but sometimes you will need more strict time bounds or set\na timeout on non-standard resource:\n\n```js\nvar perfectMatch = api.getPerfectMatch(call)\nSDK.Concurrent.timeout(perfectMatch, 10000)\n  .then(null, function (error) {\n    logger.info('It looks like api can\\'t find match quickly: ', error)\n    logger.info('Falling back to standard match')\n    return api.getStandardMatch(call)\n  })\n```\n\nThe `TimeoutException` used to reject such promise can be located as\n`SDK.Concurrent.TimeoutException`. Resulting promise also has \n`#cancel(silent)` method that allows to clear internal timeout id.\nSilent parameter defines whether it it will be cancelled silently \n(pretending that there never was a timeout) or with \nCancellationException.\n\n## delay\n\n`delay` function will wrap your callback and invoke it in future, or\njust create a timer promise if callback is omitted:\n\n```js\nSDK.Concurrent.delay(10000, function () {\n  call.say('Your answering time has expired')\n})\n```\n\n```js\nSDK.Concurrent.delay(10000).then(function () {\n  call.say('Your answering time has expired')\n})\n```\n\nYou can use it with `Promise.race()` to create some basic time-bounded\nscenarios without explicit rejection:\n\n```js\nvar toneDetection = new Promise(function (resolve) {\n  call.addEventListener(CallEvents.ToneDetected, resolve)\n})\nvar timeBound = SDK.Concurrent.delay(10000)\nPromise.race(toneDetection, timeBound).then(function() {\n  call.say('I\\'m sorry, Dave. I\\'m afraid i can\\'t do that.')\n})\n```\n\nDelay function result has `#cancel(silent)` method as well that will\neither instantly resolve delay or reject promise with \nCancellationException depending on `silent` parameter.\n\n## throttle\n\nThe last helper function prevents promise from resolving too fast. It\nwraps promise as well and ensures that it will resolve not earlier than\nspecified timeout allows:\n\n```js\nlogger.info('Emulating hard work so our clients would think we\\'re smart')\nvar balance = rest.get('/users/' + id + '/balance')\nvar throttled = SDK.Concurrent.throttle(balance, 10000)\n```\n\nThrottle function result provides similar `#cancel(silent)` method.\n\n## TaskQueue\n\nWhen you're using tons of async code, quite often you need to enforce\nsome ordering on processing. TaskQueue is created to run tasks \nsequentially - for example, it is often necessary for HTTP requests\nto come in order:\n\n```js\nvar queue = SDK.Concurrent.TaskQueue.started({name: 'Call ' + id + ' event stream'})\nqueue.push(function () {\n  return rest.create('/calls/' + id, {number: number})\n})\nqueue.push(function() {\n  return rest.modify('/users/' + userId + '/balance', {amount: -33.3})\n}, {name: 'User balance withdrawal', timeout: 1000})\nqueue\n  .close()\n  .then(function() {\n    logger.info('Everything has been finished!')\n  })\n```\n\nQueue exposes `#start()` and `#pause()` methods to start and pause\nprocessing, `#push()` for adding new tasks, `#close()` and\n`#terminate()` for normal (wait for all tasks) and emergency (discard\nwaiting tasks) queue finalization. `#push` will return a promise that\nwill be resolved once task has been run, while closing methods will \nreturn promise which will resolve once queue will become empty.\n\n## How do i require this stuff in VoxEngine?\n\nIf you don't already know, VoxImplant scripts are basically just a \nsingle file which is executed on external trigger. This limits your \nability to `require` anything, including this particular library, but \nyou can always bundle things down with a build tool of your choice.\nI personally use Webpack, but was recommended of Browserify as well,\nand, of course good old Grunt and Gulp should work too.\n\nDon't forget that VoxImplant has scenario size limit of \n[256 kb][voxengine-ref], so don't require anything at sight, don't \nforget to minify things you require and don't forget to strip \ncomments off.\n\n## ES5 & standards\n\nThis repository is developed as ES5 module because it is implied that \nbuilt code would be injected directly in VoxImplant scenarios, which, in \nturn, do not support ES6 yet, and transpiling would dramatically harden\nbug hunt.\n\nThis repository is developed using [standardjs][], sorry if you have\nfeelings for semicolons.\n\n## Testing\n\nThis package is using Mocha with Chai for test running, Istanbul for \nrecording coverage metrics and Allure framework for reporting. To run\ntests, simply invoke jake:\n\n```bash\nnpx jake test\n```\nIf you  want full-blown feedback, use `npx jake test:with-report` to \ngenerate Allure report (don't forget to install \n[allure-commandline][allure-commandline] before) and coverage report,\nwhich will be placed in `tmp/report` directory.\n\n## Anything else?\n\nWe have [@ama-team/voxengine-definitions][@definitions] package that \nhelps with autocompletion and [scenario framework][@scenario-framework]\nwhich aims at more sophisticated approach for VoxImplant scenario\ndevelopment. Also there is a chance that \n[script publishing tool][@publisher] will be finally developed at the \nmoment you're reading this, so it worth to check it.\n\nThere is no particular roadmap for this project, so you may use GitHub \nissues to propose any ideas you got. However, there is not much time\nthat could be devoted to this project.\n\n### Dev branch state / incubating\n\n[![CircleCI](https://img.shields.io/circleci/project/github/ama-team/voxengine-sdk/dev.svg?style=flat-square)](https://circleci.com/gh/ama-team/voxengine-sdk)\n[![Coveralls](https://img.shields.io/coveralls/ama-team/voxengine-sdk/dev.svg?style=flat-square)](https://coveralls.io/github/ama-team/voxengine-sdk?branch=dev)\n[![Scrutinizer](https://img.shields.io/scrutinizer/g/ama-team/voxengine-sdk/dev.svg?style=flat-square)](https://scrutinizer-ci.com/g/ama-team/voxengine-sdk/issues/dev)\n\n  [allure-commandline]: https://github.com/allure-framework/allure2\n  [@definitions]: https://github.com/ama-team/voxengine-definitions\n  [@scenario-framework]: https://github.com/ama-team/voxengine-scenario-framework\n  [@publisher]: https://github.com/ama-team/voximplant-publisher\n  [slf4j]: https://www.slf4j.org/\n  [standardjs]: https://standardjs.com\n  [voxengine-ref]: https://voximplant.com/docs/references/appengine/\n","maintainers":[{"email":"dev@amagroup.ru","name":"ama-master"},{"email":"ops@amagroup.ru","name":"ama-bot"},{"email":"etki@etki.me","name":"etki"}],"time":{"modified":"2022-06-12T14:36:16.981Z","created":"2017-02-14T13:55:24.902Z","0.1.0":"2017-02-14T13:55:24.902Z","0.1.1":"2017-02-24T01:04:08.381Z","0.2.0":"2017-02-26T09:11:09.687Z","0.3.0":"2017-08-21T08:35:39.652Z","0.4.0":"2017-09-04T02:08:02.831Z"},"homepage":"https://github.com/ama-team/voxengine-sdk#readme","keywords":["voximplant","voxengine"],"repository":{"type":"git","url":"git+https://github.com/ama-team/voxengine-sdk.git"},"author":{"name":"AMA Team","email":"dev@amagroup.ru","url":"http://amagroup.ru"},"bugs":{"url":"https://github.com/ama-team/voxengine-sdk/issues"},"license":"MIT","readmeFilename":"README.md"}