From 41e4616530d795ba55705aef48842c15c692bfe3 Mon Sep 17 00:00:00 2001 From: RizeKishimaro Date: Thu, 21 Nov 2024 13:55:46 +0630 Subject: [PATCH] fix/main: set event max listener to 30 --- lib/AmiClient.js | 701 +++++++------- package-lock.json | 2116 +++++++++++++++++++++++++++++++++++++++++ test/amiClientTest.js | 1252 ++++++++++++------------ 3 files changed, 3093 insertions(+), 976 deletions(-) create mode 100644 package-lock.json diff --git a/lib/AmiClient.js b/lib/AmiClient.js index 17aab0d..9fc6057 100644 --- a/lib/AmiClient.js +++ b/lib/AmiClient.js @@ -14,375 +14,376 @@ const debugError = require('debug')('AmiClient:error'); /** * AmiClient class */ -class AmiClient extends EventEmitter{ - - /** - * Constructor - */ - constructor(options){ - super(); - - Object.assign(this, { - _specPrefix: '--spec_', - _connector: null, - _kaTimer: null, - _kaActionId: null, - _options: Object.assign({ - reconnect: false, - maxAttemptsCount: 30, - attemptsDelay: 1000, - keepAlive: false, - keepAliveDelay: 1000, - emitEventsByTypes: true, - eventTypeToLowerCase: false, - emitResponsesById: true, - dontDeleteSpecActionId: false, - addTime: false, - eventFilter: null - }, options || {}), - _connection: null, - _lastAction: null, - _credentials: {user: null, secret: null}, - _connectionOptions: {}, - _userDisconnect: false, - _prEmitter: new EventEmitter(), - _prPendingActions: {} - }); - - this._prepareOptions(); - this._connector = amiConnector({ - reconnect: this._options.reconnect, - maxAttemptsCount: this._options.maxAttemptsCount, - attemptsDelay: this._options.attemptsDelay - }); - - this.on('disconnect', () => { - Object.keys(this._prPendingActions).forEach(actionId => { - this._prEmitter.emit(`disconnect_${actionId}`); - debugLog(`disconnect_${actionId}`); - }, this); - }); - } - - /** - * - * @param user - * @param secret - * @param options - * @returns {Promise} - */ - connect(user, secret, options){ - this._credentials = {user, secret}; - this._connectionOptions = options || {}; - - return this._connector.connect(user, secret, options) - .then(amiConnection => { - this._connection = amiConnection; - this._userDisconnect = false; - this.emit('connect', this._connection); - - this._connection - .on('event', event => { - if(!this._eventIsAllow(event)){ return; } - if(this._options.addTime){ - event.$time = Date.now(); - } - this.emit('event', event); - if(this._options.emitEventsByTypes && event.Event){ - let eventName = this._options.eventTypeToLowerCase ? - event.Event.toLowerCase() : event.Event; - this.emit(eventName, event); - } - }) - .on('response', response => { - if(this._options.keepAlive && response.ActionID === this._kaActionId){ - debugLog('keep-alive heart bit'); - this._keepAliveBit(); - return; - } - - if(this._options.addTime){ - response.$time = Date.now(); - } - - if(response.ActionID){ - if(this._options.emitResponsesById){ - this.emit(`resp_${response.ActionID}`, response); - } - this._prEmitter.emit(`resp_${response.ActionID}`, response); - - if(!this._options.dontDeleteSpecActionId && response.ActionID.startsWith(this._specPrefix)){ - delete response.ActionID; - } - } - this.emit('response', response); - }) - .on('data', chunk => this.emit('data', chunk)) - .on('error', error => this.emit('internalError', error)) - .on('close', () => { - clearTimeout(this._kaTimer); - this.emit('disconnect'); - this._prEmitter.emit('disconnect'); - setTimeout(() => { - this._connection.removeAllListeners(); - if(!this._userDisconnect && this._options.reconnect){ - this.emit('reconnection'); - this.connect( - this._credentials.user, - this._credentials.secret, - this._connectionOptions - ) - .catch(error => this.emit('internalError', error)); - } - }, 1); - }); - - if(this._options.keepAlive){ - this._keepAliveBit(); - } - return this._connection; - }) - } - - /** - * Disconnect from Asterisk - */ - disconnect(){ - this._userDisconnect = true; - clearTimeout(this._kaTimer); - this.emit('disconnect'); - if(this._connection){ - this._connection.close(); - setTimeout(this._connection.removeAllListeners, 1); - } - return this; - } +class AmiClient extends EventEmitter { + + /** + * Constructor + */ + constructor(options) { + super(); + + Object.assign(this, { + _specPrefix: '--spec_', + _connector: null, + _kaTimer: null, + _kaActionId: null, + _options: Object.assign({ + reconnect: false, + maxAttemptsCount: 30, + attemptsDelay: 1000, + keepAlive: false, + keepAliveDelay: 1000, + emitEventsByTypes: true, + eventTypeToLowerCase: false, + emitResponsesById: true, + dontDeleteSpecActionId: false, + addTime: false, + eventFilter: null + }, options || {}), + _connection: null, + _lastAction: null, + _credentials: { user: null, secret: null }, + _connectionOptions: {}, + _userDisconnect: false, + _prEmitter: new EventEmitter(), + _prPendingActions: {} + }); + this._prEmitter.setMaxListeners(30); + + this._prepareOptions(); + this._connector = amiConnector({ + reconnect: this._options.reconnect, + maxAttemptsCount: this._options.maxAttemptsCount, + attemptsDelay: this._options.attemptsDelay + }); + + this.on('disconnect', () => { + Object.keys(this._prPendingActions).forEach(actionId => { + this._prEmitter.emit(`disconnect_${actionId}`); + debugLog(`disconnect_${actionId}`); + }, this); + }); + } + + /** + * + * @param user + * @param secret + * @param options + * @returns {Promise} + */ + connect(user, secret, options) { + this._credentials = { user, secret }; + this._connectionOptions = options || {}; + + return this._connector.connect(user, secret, options) + .then(amiConnection => { + this._connection = amiConnection; + this._userDisconnect = false; + this.emit('connect', this._connection); + + this._connection + .on('event', event => { + if (!this._eventIsAllow(event)) { return; } + if (this._options.addTime) { + event.$time = Date.now(); + } + this.emit('event', event); + if (this._options.emitEventsByTypes && event.Event) { + let eventName = this._options.eventTypeToLowerCase ? + event.Event.toLowerCase() : event.Event; + this.emit(eventName, event); + } + }) + .on('response', response => { + if (this._options.keepAlive && response.ActionID === this._kaActionId) { + debugLog('keep-alive heart bit'); + this._keepAliveBit(); + return; + } - /** - * - * @param message - * @param promisable - * @returns {AmiClient} - */ - action(message, promisable){ - if(!this._connection){ - throw new Error(`Call 'connect' method before.`); - } - this._lastAction = message; - this.emit('action', message); + if (this._options.addTime) { + response.$time = Date.now(); + } - if(!message.ActionID){ - message.ActionID = this._genActionId(this._specPrefix); - } + if (response.ActionID) { + if (this._options.emitResponsesById) { + this.emit(`resp_${response.ActionID}`, response); + } + this._prEmitter.emit(`resp_${response.ActionID}`, response); - if(promisable){ - return this._promisable(message); + if (!this._options.dontDeleteSpecActionId && response.ActionID.startsWith(this._specPrefix)) { + delete response.ActionID; + } + } + this.emit('response', response); + }) + .on('data', chunk => this.emit('data', chunk)) + .on('error', error => this.emit('internalError', error)) + .on('close', () => { + clearTimeout(this._kaTimer); + this.emit('disconnect'); + this._prEmitter.emit('disconnect'); + setTimeout(() => { + this._connection.removeAllListeners(); + if (!this._userDisconnect && this._options.reconnect) { + this.emit('reconnection'); + this.connect( + this._credentials.user, + this._credentials.secret, + this._connectionOptions + ) + .catch(error => this.emit('internalError', error)); + } + }, 1); + }); + + if (this._options.keepAlive) { + this._keepAliveBit(); } - - this._connection.write(message); - return this; + return this._connection; + }) + } + + /** + * Disconnect from Asterisk + */ + disconnect() { + this._userDisconnect = true; + clearTimeout(this._kaTimer); + this.emit('disconnect'); + if (this._connection) { + this._connection.close(); + setTimeout(this._connection.removeAllListeners, 1); } - - /** - * - * @param message - * @param promisable - * @returns {*} - */ - write(message, promisable){ - return this.action(message, promisable); + return this; + } + + /** + * + * @param message + * @param promisable + * @returns {AmiClient} + */ + action(message, promisable) { + if (!this._connection) { + throw new Error(`Call 'connect' method before.`); } + this._lastAction = message; + this.emit('action', message); - /** - * - * @param message - * @param promisable - * @returns {*} - */ - send(message, promisable){ - return this.action(message, promisable); + if (!message.ActionID) { + message.ActionID = this._genActionId(this._specPrefix); } - /** - * - * @param name - * @param value - * @returns {*} - */ - option(name, value){ - if(!Object.hasOwnProperty.call(this._options, name)){ - return value === undefined ? undefined : false; - } - if(value !== undefined){ - this._options[name] = value; - this._prepareOptions(); - return true; - } - return this._options[name]; + if (promisable) { + return this._promisable(message); } - /** - * - * @param newOptions - * @returns {*} - */ - options(newOptions){ - if(newOptions === undefined){ - return this._options; - } - - Object.keys(this._options).forEach(optionName => { - if(Object.hasOwnProperty.call(newOptions, optionName)){ - this._options[optionName] = newOptions[optionName]; - } - }, this); - return this._prepareOptions(); + this._connection.write(message); + return this; + } + + /** + * + * @param message + * @param promisable + * @returns {*} + */ + write(message, promisable) { + return this.action(message, promisable); + } + + /** + * + * @param message + * @param promisable + * @returns {*} + */ + send(message, promisable) { + return this.action(message, promisable); + } + + /** + * + * @param name + * @param value + * @returns {*} + */ + option(name, value) { + if (!Object.hasOwnProperty.call(this._options, name)) { + return value === undefined ? undefined : false; } - - /** - * Keep-alive heart bit handler - * @private - */ - _keepAliveBit(){ - this._kaTimer = setTimeout(() => { - if(this._options.keepAlive && this._connection && this.isConnected){ - this._kaActionId = this._genActionId(this._specPrefix); - this._connection.write({ - Action: 'Ping', - ActionID: this._kaActionId - }); - } - }, this._options.keepAliveDelay); - this._kaTimer.unref(); - return this; + if (value !== undefined) { + this._options[name] = value; + this._prepareOptions(); + return true; } - - /** - * - * @returns {AmiClient} - * @private - */ - _prepareOptions(){ - if(this._options.eventFilter && !(this._options.eventFilter instanceof Set)){ - let eventNames = this._options.eventFilter; - - if(!Array.isArray(eventNames)){ - eventNames = Object.keys(this._options.eventFilter); - } - eventNames = eventNames.reduce((result, eventName) => { - let name = eventName ? eventName.toString() : ''; - if(name){ - result.push(name.toLowerCase()); - } - return result; - }, []); - this._options.eventFilter = new Set(eventNames); - } - return this; + return this._options[name]; + } + + /** + * + * @param newOptions + * @returns {*} + */ + options(newOptions) { + if (newOptions === undefined) { + return this._options; } - /** - * - * @param event - * @private - */ - _eventIsAllow(event){ - let eventName = event.Event ? event.Event.toLowerCase() : null; - - if(eventName && this._options.eventFilter){ - return !this._options.eventFilter.has(eventName); + Object.keys(this._options).forEach(optionName => { + if (Object.hasOwnProperty.call(newOptions, optionName)) { + this._options[optionName] = newOptions[optionName]; + } + }, this); + return this._prepareOptions(); + } + + /** + * Keep-alive heart bit handler + * @private + */ + _keepAliveBit() { + this._kaTimer = setTimeout(() => { + if (this._options.keepAlive && this._connection && this.isConnected) { + this._kaActionId = this._genActionId(this._specPrefix); + this._connection.write({ + Action: 'Ping', + ActionID: this._kaActionId + }); + } + }, this._options.keepAliveDelay); + this._kaTimer.unref(); + return this; + } + + /** + * + * @returns {AmiClient} + * @private + */ + _prepareOptions() { + if (this._options.eventFilter && !(this._options.eventFilter instanceof Set)) { + let eventNames = this._options.eventFilter; + + if (!Array.isArray(eventNames)) { + eventNames = Object.keys(this._options.eventFilter); + } + eventNames = eventNames.reduce((result, eventName) => { + let name = eventName ? eventName.toString() : ''; + if (name) { + result.push(name.toLowerCase()); } - return true; + return result; + }, []); + this._options.eventFilter = new Set(eventNames); } - - /** - * - * @param prefix - * @returns {string} - * @private - */ - _genActionId(prefix){ - prefix = prefix || ''; - return `${prefix}${Date.now()}`; + return this; + } + + /** + * + * @param event + * @private + */ + _eventIsAllow(event) { + let eventName = event.Event ? event.Event.toLowerCase() : null; + + if (eventName && this._options.eventFilter) { + return !this._options.eventFilter.has(eventName); } - - /** - * - * @param message - * @private - */ - _promisable(message){ - return new Promise((resolve, reject) => { - let resolveTimer = setTimeout(() => { - reject(new Error('Timeout response came.')); - }, 10000).unref(); - - this._connection.write(message); - this._prPendingActions[message.ActionID] = message; - this._prEmitter - .on(`resp_${message.ActionID}`, response => { - clearTimeout(resolveTimer); - resolve(response); - }) - .on(`disconnect_${message.ActionID}`, () => { - clearTimeout(resolveTimer); - reject(new Error('Client disconnected.')); - }); + return true; + } + + /** + * + * @param prefix + * @returns {string} + * @private + */ + _genActionId(prefix) { + prefix = prefix || ''; + return `${prefix}${Date.now()}`; + } + + /** + * + * @param message + * @private + */ + _promisable(message) { + return new Promise((resolve, reject) => { + let resolveTimer = setTimeout(() => { + reject(new Error('Timeout response came.')); + }, 10000).unref(); + + this._connection.write(message); + this._prPendingActions[message.ActionID] = message; + this._prEmitter + .on(`resp_${message.ActionID}`, response => { + clearTimeout(resolveTimer); + resolve(response); }) - .catch(error => error) - .then(response => { - this._prEmitter.removeAllListeners(`disconnect_${message.ActionID}`); - this._prEmitter.removeAllListeners(`resp_${message.ActionID}`); - delete this._prPendingActions[message.ActionID]; - if(response instanceof Error){ throw response; } - return response; - }); - } - - /** - * - * @returns {null} - */ - get lastEvent(){ - return this._connection ? this._connection.lastEvent : null; - } - - /** - * - * @returns {null} - */ - get lastResponse(){ - let response = this._connection ? this._connection.lastResponse : null; - if(response && response.ActionID && !this._options.dontDeleteSpecActionId - && response.ActionID.startsWith(this._specPrefix)){ - delete response.ActionID; - } - return response - } - - /** - * - * @returns {boolean} - */ - get isConnected(){ - return this._connection ? this._connection.isConnected : null; - } - - /** - * - * @returns {null} - */ - get lastAction(){ - return this._lastAction; - } - - /** - * - * @returns {T|*} - */ - get connection(){ - return this._connection; + .on(`disconnect_${message.ActionID}`, () => { + clearTimeout(resolveTimer); + reject(new Error('Client disconnected.')); + }); + }) + .catch(error => error) + .then(response => { + this._prEmitter.removeAllListeners(`disconnect_${message.ActionID}`); + this._prEmitter.removeAllListeners(`resp_${message.ActionID}`); + delete this._prPendingActions[message.ActionID]; + if (response instanceof Error) { throw response; } + return response; + }); + } + + /** + * + * @returns {null} + */ + get lastEvent() { + return this._connection ? this._connection.lastEvent : null; + } + + /** + * + * @returns {null} + */ + get lastResponse() { + let response = this._connection ? this._connection.lastResponse : null; + if (response && response.ActionID && !this._options.dontDeleteSpecActionId + && response.ActionID.startsWith(this._specPrefix)) { + delete response.ActionID; } + return response + } + + /** + * + * @returns {boolean} + */ + get isConnected() { + return this._connection ? this._connection.isConnected : null; + } + + /** + * + * @returns {null} + */ + get lastAction() { + return this._lastAction; + } + + /** + * + * @returns {T|*} + */ + get connection() { + return this._connection; + } } -module.exports = AmiClient; \ No newline at end of file +module.exports = AmiClient; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..f88ded2 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2116 @@ +{ + "name": "asterisk-ami-client", + "version": "1.1.5", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "asterisk-ami-client", + "version": "1.1.5", + "license": "MIT", + "dependencies": { + "asterisk-ami-connector": "^1.0", + "co": "^4.6.0", + "debug": "^2.2.0" + }, + "devDependencies": { + "asterisk-ami-event-utils": "^2.0.2", + "asterisk-ami-test-server": "^0.1.4", + "coveralls": "^2.11.9", + "istanbul": "^0.4.3", + "mocha": "^2.4.5" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==", + "dev": true, + "license": "ISC" + }, + "node_modules/amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==", + "dev": true, + "license": "BSD-3-Clause OR MIT", + "optional": true, + "engines": { + "node": ">=0.4.2" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha512-u1L0ZLywRziOVjUhRxI0Qg9G+4RnFB9H/Rq40YWn0dieDgO7vAYeJz6jKAO6t/aruzlDFLAPkQTT87e+f8Imaw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/asterisk-ami-connector": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/asterisk-ami-connector/-/asterisk-ami-connector-1.1.6.tgz", + "integrity": "sha512-FiIhFKNUD65svQgHHsMRofA+BuBsSQqczz5+0uTYqP8l9/w7Wg0c0fgyudNc2VKoWoV8GssDeuaUp7J97T3fWg==", + "license": "MIT", + "dependencies": { + "asterisk-ami-event-utils": "^2.0", + "asterisk-ami-events-stream": "^1.0", + "co": "^4.6.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/asterisk-ami-event-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/asterisk-ami-event-utils/-/asterisk-ami-event-utils-2.0.2.tgz", + "integrity": "sha512-peq2TlC/60T2yXA7I77tbkK1nbP7jOUdc4f4KfiR4g/nLluaTZVBPD2FMqbdjpiZ1G3GucbQD23T2APN1RFa6w==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/asterisk-ami-events-stream": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/asterisk-ami-events-stream/-/asterisk-ami-events-stream-1.2.8.tgz", + "integrity": "sha512-HU8r32NtBlxloppDeqHrs1TOwIC8ZBebr6Mre4TU4kjuLstEYtrp8UOB5qhIvx73NNzYGG6pFwQ0k43Pbzr+LQ==", + "license": "MIT", + "dependencies": { + "asterisk-ami-event-utils": "^2.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/asterisk-ami-test-server": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/asterisk-ami-test-server/-/asterisk-ami-test-server-0.1.4.tgz", + "integrity": "sha512-OM8OFiuOH0fZtn+8yRYeJaq23NqCRFA5TeKxr7deyOviVrYyKfe8gdDzJ2VgpJK30TmakTg9EvAvJaopBnrtPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "asterisk-ami-event-utils": "^2.0", + "asterisk-ami-events-stream": "^1.0", + "co": "^4.6.0", + "debug": "^2.2.0", + "shortid": "^2.1.3", + "yargs": "^4.6.0" + }, + "bin": { + "amiserver": "bin/amiserver" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==", + "dev": true, + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha512-JnJpAS0p9RmixkOvW2XwDxxzs1bd4/VAGIl6Q0EC5YOo+p+hqIhtDhn/nmFnB/xUNXbLkpE2mOjgVIBRKD4xYw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", + "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", + "dev": true, + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha512-KbiZEa9/vofNcVJXGwdWWn25reQ3V3dHBWbS07FTF3/TOehLnm9GEhJV4T6ZvGPkShRpmUqYwnaCrkj0mRnP6Q==", + "deprecated": "This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "hoek": "2.x.x" + }, + "engines": { + "node": ">=0.10.40" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/caseless": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha512-ODLXH644w9C2fMPAm7bMDQ3GRvipZWZfKc+8As6hIadRIelE0n0xZuN38NS6kiK3KPEVrpymmQD8bvncAHWQkQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz", + "integrity": "sha512-CD452fnk0jQyk3NfnK+KkR/hUPoHt5pVaKHogtyyv3N0U4QfAal9W0/rXLOg/vVZgQKa7jdtXypKs1YAip11uQ==", + "dev": true, + "engines": { + "node": ">= 0.6.x" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/coveralls": { + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-2.13.3.tgz", + "integrity": "sha512-iiAmn+l1XqRwNLXhW8Rs5qHZRFMYp9ZIPjEOVRpC/c4so6Y/f4/lFi0FfR5B9cCqgyhkJ5cZmbvcVRfP8MHchw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "js-yaml": "3.6.1", + "lcov-parse": "0.0.10", + "log-driver": "1.2.5", + "minimist": "1.2.0", + "request": "2.79.0" + }, + "bin": { + "coveralls": "bin/coveralls.js" + }, + "engines": { + "node": ">=0.8.6" + } + }, + "node_modules/cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha512-FFN5KwpvvQTTS5hWPxrU8/QE4kQUc6uwZcrnlMBN82t1MgAtq8mnoDwINBly9Tdr02seeIIhtdF+UH1feBYGog==", + "deprecated": "This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "boom": "2.x.x" + }, + "engines": { + "node": ">=0.10.40" + } + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dev": true, + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/dashdash/node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/diff": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", + "integrity": "sha512-VzVc42hMZbYU9Sx/ltb7KYuQ6pqAw+cbFWVy4XKdkuEL2CFaRLGEnISPs7YdzaUGpi+CpIqvRmu7hPQ4T7EQ5w==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", + "integrity": "sha512-cQpUid7bdTUnFin8S7BnNdOk+/eDqQmKgCANSyd/jAhrKEvxUvr9VQ8XZzXiOtest8NLfk3FSBZzwvemZNQ6Vg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^2.7.1", + "estraverse": "^1.9.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=0.12.0" + }, + "optionalDependencies": { + "source-map": "~0.2.0" + } + }, + "node_modules/esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true, + "license": "MIT" + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha512-8HWGSLAPr+AG0hBpsqi5Ob8HrLStN/LWeqhpFl14d7FJgHK48TmgLoALPz69XSUR65YJzDfLUX/BM8+MLJLghQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.5", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-property": "^1.0.2" + } + }, + "node_modules/generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha512-TuOwZWgJ2VAMEGJvAyPWvpqxSANF0LDpmyHauMjFYzaACvn+QTT/AZomvPCzVBV7yDN3OmwHQ5OvHaeLKre3JQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-property": "^1.0.0" + } + }, + "node_modules/get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true, + "license": "ISC" + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dev": true, + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/getpass/node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/growl": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "integrity": "sha512-RTBwDHhNuOx4F0hqzItc/siXCasGfC4DeWcBamclWd+6jWtBaeB/SGbMkGf0eiQoW7ib8JpvOgnUsmgMHI3Mfw==", + "dev": true, + "license": "MIT" + }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/handlebars/node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/handlebars/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/har-validator": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "integrity": "sha512-P6tFV+wCcUL3nbyTDAvveDySfbhy0XkDtAIfZP6HITjM2WUsiPna/Eg1Yy93SFXvahqoX+kt0n+6xlXKDXYowA==", + "deprecated": "this library is no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "chalk": "^1.1.1", + "commander": "^2.9.0", + "is-my-json-valid": "^2.12.4", + "pinkie-promise": "^2.0.0" + }, + "bin": { + "har-validator": "bin/har-validator" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/har-validator/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha512-X8xbmTc1cbPXcQV4WkLcRMALuyoxhfpFATmyuCxJPOAvrDS4DNnsTAOmKUxMTOWU6TzrTOkxPKwIx5ZOpJVSrg==", + "deprecated": "This module moved to @hapi/hawk. Please make sure to switch over as this distribution is no longer supported and may contain bugs and critical security issues.", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "boom": "2.x.x", + "cryptiles": "2.x.x", + "hoek": "2.x.x", + "sntp": "1.x.x" + }, + "engines": { + "node": ">=0.10.32" + } + }, + "node_modules/hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha512-V6Yw1rIcYV/4JsnggjBU0l4Kr+EXhpwqXRusENU1Xx6ro00IHPHYNynCuBTOZAPlr3AAmLvchH9I7N/VUdvOwQ==", + "deprecated": "This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.40" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true, + "license": "ISC" + }, + "node_modules/http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha512-iUn0NcRULlDGtqNLN1Jxmzayk8ogm7NToldASyZBpM2qggbphjXzNOiw3piN8tgz+e/DRs6X5gAzFwTI6BCRcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "assert-plus": "^0.2.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-my-ip-valid": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.1.tgz", + "integrity": "sha512-jxc8cBcOWbNK2i2aTkCZP6i7wkHF1bqKFrwEHuN5Jtg5BSaZHUZQ/JTOJwoV41YvHnOaRyWWh72T/KvfNz9DJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-my-json-valid": { + "version": "2.20.6", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.20.6.tgz", + "integrity": "sha512-1JQwulVNjx8UqkPE/bqDaxtH4PXCe/2VRh/y3p99heOV87HG4Id5/VfDswd+YiAfHcRTfDlWgISycnHuhZq1aw==", + "dev": true, + "license": "MIT", + "dependencies": { + "generate-function": "^2.0.0", + "generate-object-property": "^1.1.0", + "is-my-ip-valid": "^1.0.0", + "jsonpointer": "^5.0.0", + "xtend": "^4.0.0" + } + }, + "node_modules/is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "dev": true, + "license": "MIT" + }, + "node_modules/istanbul": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", + "integrity": "sha512-nMtdn4hvK0HjUlzr1DrKSUY8ychprt8dzHOgY2KXsIhHu5PuQQEOTM27gV9Xblyon7aUH/TSFIjRHEODF/FRPg==", + "deprecated": "This module is no longer maintained, try this instead:\n npm i nyc\nVisit https://istanbul.js.org/integrations for other alternatives.", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "abbrev": "1.0.x", + "async": "1.x", + "escodegen": "1.8.x", + "esprima": "2.7.x", + "glob": "^5.0.15", + "handlebars": "^4.0.1", + "js-yaml": "3.x", + "mkdirp": "0.5.x", + "nopt": "3.x", + "once": "1.x", + "resolve": "1.1.x", + "supports-color": "^3.1.0", + "which": "^1.1.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "istanbul": "lib/cli.js" + } + }, + "node_modules/jade": { + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", + "integrity": "sha512-mkk3vzUHFjzKjpCXeu+IjXeZD+QOTjUUdubgmHtHTDwvAO2ZTkMTTVrapts5CWz3JvJryh/4KWZpjeZrCepZ3A==", + "deprecated": "Jade has been renamed to pug, please install the latest version of pug instead of jade", + "dev": true, + "dependencies": { + "commander": "0.6.1", + "mkdirp": "0.3.0" + }, + "bin": { + "jade": "bin/jade" + } + }, + "node_modules/jade/node_modules/commander": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", + "integrity": "sha512-0fLycpl1UMTGX257hRsu/arL/cUbcvQM4zMKwvLvzXtfdezIV4yotPS2dYtknF+NmEfWSoCEF6+hj9XLm/6hEw==", + "dev": true, + "engines": { + "node": ">= 0.4.x" + } + }, + "node_modules/jade/node_modules/mkdirp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "integrity": "sha512-OHsdUcVAQ6pOtg5JYWpCBo9W/GySVuwvP9hueRMW7UqshC0tbfzLv8wjySTPm3tfUZ/21CE9E1pJagOA91Pxew==", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "dev": true, + "license": "MIT/X11", + "engines": { + "node": "*" + } + }, + "node_modules/js-yaml": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz", + "integrity": "sha512-BLv3oxhfET+w5fjPwq3PsAsxzi9i3qzU//HMpWVz0A6KplF86HdR9x2TGnv9DXhSUrO7LO8czUiTd3yb3mLSvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^2.6.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true, + "license": "(AFL-2.1 OR BSD-3-Clause)" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "license": "ISC" + }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/jsprim/node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "invert-kv": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lcov-parse": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", + "integrity": "sha512-YsL0D4QF/vNlNcHPXM832si9d2ROryFQ4r4JvcfMIiUYr1f6WULuO75YCtxNu4P+XMRHz0SfUc524+c+U3G5kg==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha512-hFuH8TY+Yji7Eja3mGiuAxBqLagejScbG8GbG0j6o9vzn0YL14My+ktnqtZgFTosKymC9/44wP6s7xyuLfnClw==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-driver": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.5.tgz", + "integrity": "sha512-UwqFFU6yztduP6DXcjcIjrIyvWQMv/spvrK2vji37XiUykpCm1qTUUM3zO+ER7qjL3CtmbWKAoVC5+bO2HwiNA==", + "dev": true, + "engines": { + "node": ">=0.8.6" + } + }, + "node_modules/lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha512-WpibWJ60c3AgAz8a2iYErDrcT2C7OmKnsWhIcHOjkUHFjkXncJhtLxNSqUmxRxRunpb5I8Vprd7aNSd2NtksJQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha512-7Wl+Jz+IGWuSdgsQEJ4JunV0si/iMhg42MnQQG6h1R6TNeVenp4U9x5CC5v/gYqz/fENLQITAWXidNtVL0NNbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mkdirp/node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mocha": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-2.5.3.tgz", + "integrity": "sha512-jNt2iEk9FPmZLzL+sm4FNyOIDYXf2wUU6L4Cc8OIKK/kzgMHKPi4YhTZqG4bW4kQVdIv6wutDybRhXfdnujA1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "commander": "2.3.0", + "debug": "2.2.0", + "diff": "1.4.0", + "escape-string-regexp": "1.0.2", + "glob": "3.2.11", + "growl": "1.9.2", + "jade": "0.26.3", + "mkdirp": "0.5.1", + "supports-color": "1.2.0", + "to-iso-string": "0.0.2" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 0.8.x" + } + }, + "node_modules/mocha/node_modules/debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha512-X0rGvJcskG1c3TgSCPqHJ0XJgwlcvOC7elJ5Y0hYuKBZoVqWpAMfLOeIh2UI/DCQ5ruodIjvsugZtjUYUw2pUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "0.7.1" + } + }, + "node_modules/mocha/node_modules/glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "integrity": "sha512-hVb0zwEZwC1FXSKRPFTeOtN7AArJcJlI6ULGLtrstaswKNlrTJqAA+1lYlSUop4vjA423xlBzqfVS3iWGlqJ+g==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "BSD", + "dependencies": { + "inherits": "2", + "minimatch": "0.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mocha/node_modules/minimatch": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "integrity": "sha512-WFX1jI1AaxNTZVOHLBVazwTWKaQjoykSzCBNXB72vDTCzopQGtyP91tKdFK5cv1+qMwPyiTu1HqUriqplI8pcA==", + "deprecated": "Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue", + "dev": true, + "license": "MIT", + "dependencies": { + "lru-cache": "2", + "sigmund": "~1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mocha/node_modules/minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha512-miQKw5Hv4NS1Psg2517mV4e4dYNaO3++hjAvLOAzKqZ61rH8NS1SK+vbfBWZ5PY/Me/bEWhUwqMghEW5Fb9T7Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/mocha/node_modules/mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha512-SknJC52obPfGQPnjIkXbmA6+5H15E+fR+E4iR2oQ3zzCLbd7/ONua69R/Gw7AgkTLsRG+r5fzksYwWe1AgTyWA==", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "0.0.8" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mocha/node_modules/ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha512-lRLiIR9fSNpnP6TC4v8+4OU7oStC01esuNowdQ34L+Gk8e5Puoc88IqJ+XAY/B3Mn2ZKis8l8HX90oU8ivzUHg==", + "dev": true + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.0.tgz", + "integrity": "sha512-mS5xsnjTh5b7f2DM6bch6lR582UCOTphzINlZnDsfpIRrwI6r58rb6YSSGsdexkm8qw2bBVO2ID2fnJOTuLiPA==", + "dev": true, + "license": "MIT", + "bin": { + "supports-color": "cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", + "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "license": "MIT" + }, + "node_modules/nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==", + "dev": true, + "license": "ISC", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha512-VlF07iu3VV3+BTXj43Nmp6Irt/G7j/NgEctUS6IweH1RGhURjjCc2NWtzXFPXXWWfc7hgbXQdtiQu2LGp6MxUg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha512-PRT7ZORmwu2MEFt4/fv3Q+mEfN4zetKxufQrkShY2oGvUms9r8otu5HfdyIFHkYXjO7laNsoVGmM2MANfuTA8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "lcid": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "error-ex": "^1.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/qs": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.3.tgz", + "integrity": "sha512-f8CQ/sKJBr9vfNJBdGiPzTSPUufuWyvOFkCYJKN9voqPWuBuhdlSZM78dOHKigtZ0BwuktYGrRFW2DXXc/f2Fg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/request": { + "version": "2.79.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", + "integrity": "sha512-e7MIJshe1eZAmRqg4ryaO0N9G0fs+/gpDe5FlbnIFy6zZznRSwdRFrLp63if0Yt43vrI5wowOqHv1qJdVocdOQ==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "aws-sign2": "~0.6.0", + "aws4": "^1.2.1", + "caseless": "~0.11.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.0", + "forever-agent": "~0.6.1", + "form-data": "~2.1.1", + "har-validator": "~2.0.6", + "hawk": "~3.1.3", + "http-signature": "~1.1.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.7", + "oauth-sign": "~0.8.1", + "qs": "~6.3.0", + "stringstream": "~0.0.4", + "tough-cookie": "~2.3.0", + "tunnel-agent": "~0.4.1", + "uuid": "^3.0.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug==", + "dev": true, + "license": "ISC" + }, + "node_modules/resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==", + "dev": true, + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true, + "license": "ISC" + }, + "node_modules/shortid": { + "version": "2.2.16", + "resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.16.tgz", + "integrity": "sha512-Ugt+GIZqvGXCIItnsL+lvFJOiN7RYqlGy7QE41O3YC1xbNSeDGIRO7xg2JJXIAj1cAGnOeC1r7/T9pgrtQbv4g==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "license": "MIT", + "dependencies": { + "nanoid": "^2.1.0" + } + }, + "node_modules/sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha512-fCvEXfh6NWpm+YSuY2bpXb/VIihqWA6hLsgboC+0nl71Q7N7o2eaCW8mJa/NLvQhs6jpd3VZV4UiUQlV6+lc8g==", + "dev": true, + "license": "ISC" + }, + "node_modules/sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha512-7bgVOAnPj3XjrKY577S+puCKGCRlUrcrEdsMeRXlg9Ghf5df/xNi6sONUa43WrHUd3TjJBF7O04jYoiY0FVa0A==", + "deprecated": "This module moved to @hapi/sntp. Please make sure to switch over as this distribution is no longer supported and may contain bugs and critical security issues.", + "dev": true, + "dependencies": { + "hoek": "2.x.x" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA==", + "dev": true, + "optional": true, + "dependencies": { + "amdefine": ">=0.0.4" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.20", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", + "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/sshpk": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sshpk/node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stringstream": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", + "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==", + "dev": true, + "license": "MIT" + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-utf8": "^0.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^1.0.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/to-iso-string": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/to-iso-string/-/to-iso-string-0.0.2.tgz", + "integrity": "sha512-oeHLgfWA7d0CPQa6h0+i5DAJZISz5un0d5SHPkw+Untclcvzv9T+AC3CvGXlZJdOlIbxbTfyyzlqCXc5hjpXYg==", + "deprecated": "to-iso-string has been deprecated, use @segment/to-iso-string instead.", + "dev": true, + "license": "MIT" + }, + "node_modules/tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "punycode": "^1.4.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha512-e0IoVDWx8SDHc/hwFTqJDQ7CCDTEeGhmcT9jkWJjoGQSpgBz20nAMr80E3Tpk7PatJ1b37DQDgJR3CNSzcMOZQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "dev": true, + "license": "Unlicense" + }, + "node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true, + "license": "MIT", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/verror/node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha512-F6+WgncZi/mJDrammbTuHe1q0R5hOXv/mBaiNA2TCNT/LTHusX0V+CJnj9XT8ki5ln2UZyyddDgHfCzyrOH7MQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/window-size": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", + "integrity": "sha512-UD7d8HFA2+PZsbKyaOCEy8gMh1oDtHgJh1LfgjQ4zVXmYjAT/kvz3PueITKuqDiIXQe7yzpPnxX3lNc+AhQMyw==", + "dev": true, + "license": "MIT", + "bin": { + "window-size": "cli.js" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", + "integrity": "sha512-LqodLrnIDM3IFT+Hf/5sxBnEGECrfdC1uIbgZeJmESCSo4HoCAaKEus8MylXHAkdacGc0ye+Qa+dpkuom8uVYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "lodash.assign": "^4.0.3", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.1", + "which-module": "^1.0.0", + "window-size": "^0.2.0", + "y18n": "^3.2.1", + "yargs-parser": "^2.4.1" + } + }, + "node_modules/yargs-parser": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", + "integrity": "sha512-9pIKIJhnI5tonzG6OnCFlz/yln8xHYcGl+pn3xR0Vzff0vzN1PbNRaelgfgRUwZ3s4i3jvxT9WhmUGL4whnasA==", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^3.0.0", + "lodash.assign": "^4.0.6" + } + } + } +} diff --git a/test/amiClientTest.js b/test/amiClientTest.js index 71be1da..1b942ec 100644 --- a/test/amiClientTest.js +++ b/test/amiClientTest.js @@ -12,734 +12,734 @@ const AmiClient = require('../lib/AmiClient'); const AmiConnection = require('../node_modules/asterisk-ami-connector/lib/AmiConnection'); const assert = require('assert'); -const USERNAME = 'test'; -const SECRET = 'test'; +const USERNAME = 'SPT_ami_admin'; +const SECRET = 'root'; let serverOptions = { - silent: true, - credentials: { - username: USERNAME, - secret: SECRET - } - }, - socketOptions = { - host: '127.0.0.1', - port: 5038 - }; - -describe('Ami Client internal functionality', function(){ - this.timeout(3000); - - let server = null, - client = null; - - afterEach(done => { - if(server instanceof AmiTestServer){ - server.close(); - server.removeAllListeners(); - server = null; - } - if(client instanceof AmiClient){ - client.disconnect(); - client = null; - } - setTimeout(done, 100); - }); - - describe('Regular connection with default configuration', function(){ - - beforeEach(done => { - client = new AmiClient(); - server = new AmiTestServer(serverOptions); - server.listen(socketOptions).then(done); - }); + silent: true, + credentials: { + username: USERNAME, + secret: SECRET + } +}, + socketOptions = { + host: '172.250.230.160', + port: 5038 + }; + +describe('Ami Client internal functionality', function() { + this.timeout(3000); + + let server = null, + client = null; + + afterEach(done => { + if (server instanceof AmiTestServer) { + server.close(); + server.removeAllListeners(); + server = null; + } + if (client instanceof AmiClient) { + client.disconnect(); + client = null; + } + setTimeout(done, 100); + }); + + describe('Regular connection with default configuration', function() { + + beforeEach(done => { + client = new AmiClient(); + server = new AmiTestServer(serverOptions); + server.listen(socketOptions).then(done); + }); - it('Connect with correct credentials', done => { - client.connect(USERNAME, SECRET, socketOptions).then(() => done()); - }); + it('Connect with correct credentials', done => { + client.connect(USERNAME, SECRET, socketOptions).then(() => done()); + }); - it('Connector returns instance of AmiConnection', done => { - client.connect(USERNAME, SECRET, socketOptions).then(amiConnection => { - assert.ok(amiConnection instanceof AmiConnection); - done(); - }); - }); + it('Connector returns instance of AmiConnection', done => { + client.connect(USERNAME, SECRET, socketOptions).then(amiConnection => { + assert.ok(amiConnection instanceof AmiConnection); + done(); + }); + }); - it('Connect with invalid credentials', done => { - client.connect('username', 'secret', socketOptions) - .catch(error => { - assert.ok(error instanceof Error); - assert.equal('ami message: authentication failed', error.message.toLowerCase()); - done(); - }); + it('Connect with invalid credentials', done => { + client.connect('username', 'secret', socketOptions) + .catch(error => { + assert.ok(error instanceof Error); + assert.equal('ami message: authentication failed', error.message.toLowerCase()); + done(); }); }); + }); - describe('Reconnection functioanlity', function(){ - - beforeEach(() => { - server = new AmiTestServer(serverOptions); - }); + describe('Reconnection functioanlity', function() { - it('Reconnection with correct credentials', done => { - client = new AmiClient({ - reconnect: true - }); - client.connect(USERNAME, SECRET, socketOptions).then(() => done()); - setTimeout(() => { - server.listen(socketOptions); - }, 1500); - }); + beforeEach(() => { + server = new AmiTestServer(serverOptions); + }); - it('Reconnection with invalid credentials', done => { - client = new AmiClient({ - reconnect: true - }); - client.connect('username', 'secret', socketOptions).catch(error => { - assert.ok(error instanceof Error); - assert.equal('ami message: authentication failed', error.message.toLowerCase()); - done(); - }); - setTimeout(() => { - server.listen(socketOptions); - }, 1500); - }); + it('Reconnection with correct credentials', done => { + client = new AmiClient({ + reconnect: true + }); + client.connect(USERNAME, SECRET, socketOptions).then(() => done()); + setTimeout(() => { + server.listen(socketOptions); + }, 1500); + }); - it('Limit of attempts of reconnection', done => { - client = new AmiClient({ - reconnect: true, - maxAttemptsCount: 1 - }); - client.connect(USERNAME, SECRET, socketOptions).catch(error => { - assert.ok(error instanceof Error); - assert.equal('reconnection error after max count attempts.', error.message.toLowerCase()); - done(); - }); - setTimeout(() => { - server.listen(socketOptions); - }, 1500); - }); + it('Reconnection with invalid credentials', done => { + client = new AmiClient({ + reconnect: true + }); + client.connect('username', 'secret', socketOptions).catch(error => { + assert.ok(error instanceof Error); + assert.equal('ami message: authentication failed', error.message.toLowerCase()); + done(); + }); + setTimeout(() => { + server.listen(socketOptions); + }, 1500); + }); - it('Ban for reconnection', done => { - client = new AmiClient({ - reconnect: false - }); - client.connect(USERNAME, SECRET, socketOptions).catch(error => { - assert.ok(error instanceof Error); - assert.equal('connect ECONNREFUSED 127.0.0.1:5038', error.message); - done(); - }); - }); + it('Limit of attempts of reconnection', done => { + client = new AmiClient({ + reconnect: true, + maxAttemptsCount: 1 + }); + client.connect(USERNAME, SECRET, socketOptions).catch(error => { + assert.ok(error instanceof Error); + assert.equal('reconnection error after max count attempts.', error.message.toLowerCase()); + done(); + }); + setTimeout(() => { + server.listen(socketOptions); + }, 1500); + }); - it('Reconnection after disconnect from Asterisk', done => { - let wasDisconnect = false, - connectCounter = 0; - - client = new AmiClient({ - reconnect: true, - maxAttemptsCount: null, - attemptsDelay: 1000 - }); - client - .on('disconnect', () => { - wasDisconnect = true; - }) - .on('connect', () => { - if(++connectCounter == 2 && wasDisconnect){ - done(); - } - }); - - server.listen(socketOptions).then(() => { - client.connect(USERNAME, SECRET, socketOptions).then(() => { - server.close(); - setTimeout(() => { - server.listen(socketOptions); - }, 1000); - }); - }); - }); + it('Ban for reconnection', done => { + client = new AmiClient({ + reconnect: false + }); + client.connect(USERNAME, SECRET, socketOptions).catch(error => { + assert.ok(error instanceof Error); + assert.equal('connect ECONNREFUSED 127.0.0.1:5038', error.message); + done(); + }); }); - describe('Last event/response/action', function(){ + it('Reconnection after disconnect from Asterisk', done => { + let wasDisconnect = false, + connectCounter = 0; + + client = new AmiClient({ + reconnect: true, + maxAttemptsCount: null, + attemptsDelay: 1000 + }); + client + .on('disconnect', () => { + wasDisconnect = true; + }) + .on('connect', () => { + if (++connectCounter == 2 && wasDisconnect) { + done(); + } + }); + + server.listen(socketOptions).then(() => { + client.connect(USERNAME, SECRET, socketOptions).then(() => { + server.close(); + setTimeout(() => { + server.listen(socketOptions); + }, 1000); + }); + }); + }); + }); - beforeEach(done => { - client = new AmiClient(); - server = new AmiTestServer(serverOptions); - server.listen(socketOptions).then(done); - }); + describe('Last event/response/action', function() { - it('Get last Event after event', done => { - let testEvent = { - Event: 'TestEvent', - Value: 'TestValue' - }; - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - server.broadcast(amiUtils.fromObject(testEvent)); - client.once('event', event => { - assert.deepEqual(event, client.lastEvent); - done(); - }); - }); - }); + beforeEach(done => { + client = new AmiClient(); + server = new AmiTestServer(serverOptions); + server.listen(socketOptions).then(done); + }); - it('Get last Event before event', done => { - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - assert.equal(null, client.lastEvent); - done(); - }); - }); + it('Get last Event after event', done => { + let testEvent = { + Event: 'TestEvent', + Value: 'TestValue' + }; + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + server.broadcast(amiUtils.fromObject(testEvent)); + client.once('event', event => { + assert.deepEqual(event, client.lastEvent); + done(); + }); + }); + }); - it('Get last Response after action', done => { - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - client.action({Action: 'Ping'}); - client.once('response', response => { - assert.equal(response.Response, 'Success'); - assert.equal(response.Ping, 'Pong'); - done(); - }); - }); - }); + it('Get last Event before event', done => { + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + assert.equal(null, client.lastEvent); + done(); + }); + }); - it('Get last Response before action', done => { - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - assert.equal(null, client.lastResponse); - done(); - }); + it('Get last Response after action', done => { + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + client.action({ Action: 'Ping' }); + client.once('response', response => { + assert.equal(response.Response, 'Success'); + assert.equal(response.Ping, 'Pong'); + done(); }); + }); + }); - it('Get last Action after action (without ActionID)', done => { - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - let testAction = {Action: 'Ping'}; - client.action(testAction); - assert.deepEqual(testAction, client.lastAction); - done(); - }); - }); + it('Get last Response before action', done => { + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + assert.equal(null, client.lastResponse); + done(); + }); + }); - it('Get last Action after action (with ActionID)', done => { - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - let testAction = { - Action: 'Ping', - ActionID: '1234567' - }; - client.action(testAction); - assert.deepEqual(testAction, client.lastAction); - done(); - }); - }); + it('Get last Action after action (without ActionID)', done => { + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + let testAction = { Action: 'Ping' }; + client.action(testAction); + assert.deepEqual(testAction, client.lastAction); + done(); + }); + }); - it('Get last Action before action', done => { - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - assert.equal(null, client.lastAction); - done(); - }); - }); + it('Get last Action after action (with ActionID)', done => { + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + let testAction = { + Action: 'Ping', + ActionID: '1234567' + }; + client.action(testAction); + assert.deepEqual(testAction, client.lastAction); + done(); + }); + }); + it('Get last Action before action', done => { + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + assert.equal(null, client.lastAction); + done(); + }); }); - describe('Client\'s events', function(){ + }); - beforeEach(done => { - client = new AmiClient({}); - server = new AmiTestServer(serverOptions); - server.listen(socketOptions).then(done); - }); + describe('Client\'s events', function() { - it('Connect event', done => { - client.on('connect', () => done()); - client.connect(USERNAME, SECRET, {port: socketOptions.port}); - }); + beforeEach(done => { + client = new AmiClient({}); + server = new AmiTestServer(serverOptions); + server.listen(socketOptions).then(done); + }); - it('Disconnect event', done => { - client.once('disconnect', done); - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - setTimeout(server.close.bind(server), 100); - }); - }); + it('Connect event', done => { + client.on('connect', () => done()); + client.connect(USERNAME, SECRET, { port: socketOptions.port }); + }); - it('Reconnect event', done => { - client = new AmiClient({reconnect: true}); - client.once('reconnection', () => done()); - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - server.close(); - }); - }); + it('Disconnect event', done => { + client.once('disconnect', done); + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + setTimeout(server.close.bind(server), 100); + }); + }); - it('Event event', done => { - let testEvent = { - Event: 'TestEvent' - }; + it('Reconnect event', done => { + client = new AmiClient({ reconnect: true }); + client.once('reconnection', () => done()); + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + server.close(); + }); + }); - client.on('event', event => { - assert.deepEqual(event, testEvent); - done(); - }); + it('Event event', done => { + let testEvent = { + Event: 'TestEvent' + }; - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - server.broadcast(amiUtils.fromObject(testEvent)); - }); - }); + client.on('event', event => { + assert.deepEqual(event, testEvent); + done(); + }); - it('Event by event\'s type', done => { - let testEvent = { - Event: 'TestEvent' - }; + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + server.broadcast(amiUtils.fromObject(testEvent)); + }); + }); - client.on('TestEvent', event => { - assert.deepEqual(event, testEvent); - done(); - }); + it('Event by event\'s type', done => { + let testEvent = { + Event: 'TestEvent' + }; - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - server.broadcast(amiUtils.fromObject(testEvent)); - }); - }); + client.on('TestEvent', event => { + assert.deepEqual(event, testEvent); + done(); + }); - it('Response event', done => { - client.on('response', response => { - assert(response.Response, 'Success'); - assert(response.Ping, 'Pong'); - done(); - }); + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + server.broadcast(amiUtils.fromObject(testEvent)); + }); + }); - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - client.action({Action: 'Ping'}); - }); - }); + it('Response event', done => { + client.on('response', response => { + assert(response.Response, 'Success'); + assert(response.Ping, 'Pong'); + done(); + }); - it('Response event by ActionID', done => { - client.on('resp_1234567', response => { - assert(response.Response, 'Success'); - assert(response.Ping, 'Pong'); - done(); - }); - - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - client.action({ - Action: 'Ping', - ActionID: '1234567' - }); - }); - }); + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + client.action({ Action: 'Ping' }); + }); + }); - it('Data event', done => { - let testChunk = amiUtils.fromString('test chunk'); - client.once('data', chunk => { - assert.equal(chunk.toString(), testChunk); - done(); - }); + it('Response event by ActionID', done => { + client.on('resp_1234567', response => { + assert(response.Response, 'Success'); + assert(response.Ping, 'Pong'); + done(); + }); - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - server.broadcast(testChunk); - }); + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + client.action({ + Action: 'Ping', + ActionID: '1234567' }); - + }); }); - describe('Action-method and aliases', function(){ + it('Data event', done => { + let testChunk = amiUtils.fromString('test chunk'); + client.once('data', chunk => { + assert.equal(chunk.toString(), testChunk); + done(); + }); - beforeEach(done => { - client = new AmiClient({}); - server = new AmiTestServer(serverOptions); - server.listen(socketOptions).then(done); - }); + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + server.broadcast(testChunk); + }); + }); - it('Call action before connection => exception', () => { - assert.throws(() => { - client.action({Action: 'Ping'}); - }, error => { - assert.ok(error instanceof Error); - assert.equal(`Call 'connect' method before.`, error.message); - return true; - }); - }); + }); - it('Write is a alias of action', done => { - let action = client.action, - testAction = {Action: 'Ping'}; + describe('Action-method and aliases', function() { - client.action = function(message){ - assert.deepEqual(testAction, message); - done(); - }; - client.write(testAction); - }); + beforeEach(done => { + client = new AmiClient({}); + server = new AmiTestServer(serverOptions); + server.listen(socketOptions).then(done); + }); - it('Send is a alias of action', done => { - let action = client.action, - testAction = {Action: 'Ping'}; + it('Call action before connection => exception', () => { + assert.throws(() => { + client.action({ Action: 'Ping' }); + }, error => { + assert.ok(error instanceof Error); + assert.equal(`Call 'connect' method before.`, error.message); + return true; + }); + }); - client.action = function(message){ - assert.deepEqual(testAction, message); - done(); - }; - client.send(testAction); - }); + it('Write is a alias of action', done => { + let action = client.action, + testAction = { Action: 'Ping' }; - it('Action is promissable', done => { - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - assert.ok(client.action({Action: 'Ping'}, true) instanceof Promise); - done(); - }); - }); + client.action = function(message) { + assert.deepEqual(testAction, message); + done(); + }; + client.write(testAction); + }); - it('Resolving promissabled action with ActionID', done => { - let action = { - Action: 'Ping', - ActionID: '1234567' - }; - - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - client.action(action, true).then( response => { - delete response.Timestamp; - assert.deepEqual({ - Response: 'Success', - Ping: 'Pong', - ActionID: action.ActionID - }, response); - done(); - }); - }); - }); + it('Send is a alias of action', done => { + let action = client.action, + testAction = { Action: 'Ping' }; - it('Resolving promissabled action without ActionID', done => { - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - client.action({Action: 'Ping'}, true).then( response => { - delete response.Timestamp; - assert.deepEqual({ - Response: 'Success', - Ping: 'Pong' - }, response); - done(); - }); - }); - }); + client.action = function(message) { + assert.deepEqual(testAction, message); + done(); + }; + client.send(testAction); + }); - it('Last response not have $time field after resolving promissabled action without ActionID', done => { - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - client.action({Action: 'Ping'}, true).then(() => { - assert.ok(client.lastResponse.$time === undefined); - done(); - }); - }); - }); + it('Action is promissable', done => { + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + assert.ok(client.action({ Action: 'Ping' }, true) instanceof Promise); + done(); + }); + }); + it('Resolving promissabled action with ActionID', done => { + let action = { + Action: 'Ping', + ActionID: '1234567' + }; + + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + client.action(action, true).then(response => { + delete response.Timestamp; + assert.deepEqual({ + Response: 'Success', + Ping: 'Pong', + ActionID: action.ActionID + }, response); + done(); + }); + }); }); - describe('Client\'s configuration', function(){ + it('Resolving promissabled action without ActionID', done => { + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + client.action({ Action: 'Ping' }, true).then(response => { + delete response.Timestamp; + assert.deepEqual({ + Response: 'Success', + Ping: 'Pong' + }, response); + done(); + }); + }); + }); - beforeEach(done => { - client = new AmiClient({}); - server = new AmiTestServer(serverOptions); - server.listen(socketOptions).then(done); + it('Last response not have $time field after resolving promissabled action without ActionID', done => { + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + client.action({ Action: 'Ping' }, true).then(() => { + assert.ok(client.lastResponse.$time === undefined); + done(); }); + }); + }); - it('Get all options of client', () => { - assert.deepEqual(client.options(), { - reconnect: false, - maxAttemptsCount: 30, - attemptsDelay: 1000, - keepAlive: false, - keepAliveDelay: 1000, - emitEventsByTypes: true, - eventTypeToLowerCase: false, - emitResponsesById: true, - dontDeleteSpecActionId: false, - addTime: false, - eventFilter: null - }) - }); + }); - it('Set all options of client', () => { - let newOptions = { - reconnect: true, - maxAttemptsCount: 5, - attemptsDelay: 5000, - keepAlive: true, - keepAliveDelay: 5000, - emitEventsByTypes: false, - eventTypeToLowerCase: true, - emitResponsesById: false, - dontDeleteSpecActionId: true, - addTime: true, - eventFilter: new Set(['Dial']) - }; - - client.options(Object.assign({}, newOptions, {undefinedOption: 'testValue'})); - assert.deepEqual(client.options(), newOptions) - }); + describe('Client\'s configuration', function() { - it('Get value of exists option', () => { - assert.equal(client.option('maxAttemptsCount'), 30) - }); + beforeEach(done => { + client = new AmiClient({}); + server = new AmiTestServer(serverOptions); + server.listen(socketOptions).then(done); + }); - it('Get value of not exists option', () => { - assert.equal(client.option('notExistsOption'), undefined) - }); + it('Get all options of client', () => { + assert.deepEqual(client.options(), { + reconnect: false, + maxAttemptsCount: 30, + attemptsDelay: 1000, + keepAlive: false, + keepAliveDelay: 1000, + emitEventsByTypes: true, + eventTypeToLowerCase: false, + emitResponsesById: true, + dontDeleteSpecActionId: false, + addTime: false, + eventFilter: null + }) + }); - it('Set value for exists option', () => { - let optionName = 'maxAttemptsCount', - result = client.option(optionName, 1); - assert.equal(client.option(optionName), 1); - assert.equal(result, true); - }); + it('Set all options of client', () => { + let newOptions = { + reconnect: true, + maxAttemptsCount: 5, + attemptsDelay: 5000, + keepAlive: true, + keepAliveDelay: 5000, + emitEventsByTypes: false, + eventTypeToLowerCase: true, + emitResponsesById: false, + dontDeleteSpecActionId: true, + addTime: true, + eventFilter: new Set(['Dial']) + }; + + client.options(Object.assign({}, newOptions, { undefinedOption: 'testValue' })); + assert.deepEqual(client.options(), newOptions) + }); - it('Set value for not exists option', () => { - let result = client.option('notExistsOption', 1); - assert.equal(result, false); - }); + it('Get value of exists option', () => { + assert.equal(client.option('maxAttemptsCount'), 30) + }); - it('Set event filter from array', () => { - let eventNames = ['Dial', 'Hangup', 'Dial']; - client.option('eventFilter', eventNames); - assert.ok(client.option('eventFilter') instanceof Set); - assert.deepEqual( - Array.from(client.option('eventFilter')), - Array.from(new Set(eventNames)).map(name => name.toLowerCase()) - ); - }); + it('Get value of not exists option', () => { + assert.equal(client.option('notExistsOption'), undefined) + }); - it('Set event filter from object', () => { - let eventNames = { - Dial: 1, - Hangup: 1 - }; - client.option('eventFilter', eventNames); - assert.ok(client.option('eventFilter') instanceof Set); - assert.deepEqual( - Array.from(client.option('eventFilter')), - Object.keys(eventNames).map(name => name.toLowerCase()) - ); - }); + it('Set value for exists option', () => { + let optionName = 'maxAttemptsCount', + result = client.option(optionName, 1); + assert.equal(client.option(optionName), 1); + assert.equal(result, true); + }); - it('Set event filter from Set', () => { - let eventNames = new Set(['Dial', 'Hangup', 'Dial']); - client.option('eventFilter', eventNames); - assert.deepEqual(client.option('eventFilter'), eventNames); - }); + it('Set value for not exists option', () => { + let result = client.option('notExistsOption', 1); + assert.equal(result, false); + }); - it('Event not have $time field', done => { - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - client.on('event', event => { - assert.ok(event.$time === undefined); - done(); - }); - server.broadcast(amiUtils.fromObject({Event: 'TestEvent'})); - }); - }); + it('Set event filter from array', () => { + let eventNames = ['Dial', 'Hangup', 'Dial']; + client.option('eventFilter', eventNames); + assert.ok(client.option('eventFilter') instanceof Set); + assert.deepEqual( + Array.from(client.option('eventFilter')), + Array.from(new Set(eventNames)).map(name => name.toLowerCase()) + ); + }); - it('Response not have $time field', done => { - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - client - .on('response', response => { - assert.ok(response.$time === undefined); - done(); - }) - .action({Action: 'Ping'}); - }); - }); + it('Set event filter from object', () => { + let eventNames = { + Dial: 1, + Hangup: 1 + }; + client.option('eventFilter', eventNames); + assert.ok(client.option('eventFilter') instanceof Set); + assert.deepEqual( + Array.from(client.option('eventFilter')), + Object.keys(eventNames).map(name => name.toLowerCase()) + ); + }); - it('Event has $time field', done => { - client = new AmiClient({addTime: true}); - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - client.once('event', event => { - assert.ok(/^\d{13}$/.test(event.$time)); - done(); - }); - server.broadcast(amiUtils.fromObject({Event: 'TestEvent'})); - }); - }); + it('Set event filter from Set', () => { + let eventNames = new Set(['Dial', 'Hangup', 'Dial']); + client.option('eventFilter', eventNames); + assert.deepEqual(client.option('eventFilter'), eventNames); + }); - it('Response has $time field', done => { - client = new AmiClient({addTime: true}); - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - client.once('response', response => { - assert.ok(/^\d{13}$/.test(response.$time)); - done(); - }) - .action({Action: 'Ping'}); - }); + it('Event not have $time field', done => { + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + client.on('event', event => { + assert.ok(event.$time === undefined); + done(); }); + server.broadcast(amiUtils.fromObject({ Event: 'TestEvent' })); + }); + }); - it('Response have deleted generated ActionID field', done => { - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - client - .on('response', response => { - assert.ok(response.ActionID === undefined); - done(); - }) - .action({Action: 'Ping'}); - }); - }); + it('Response not have $time field', done => { + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + client + .on('response', response => { + assert.ok(response.$time === undefined); + done(); + }) + .action({ Action: 'Ping' }); + }); + }); - it('Response has generated ActionID field', done => { - client = new AmiClient({dontDeleteSpecActionId: true}); - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - client.once('response', response => { - assert.ok(/^--spec_\d{13}$/.test(response.ActionID)); - done(); - }) - .action({Action: 'Ping'}); - }); + it('Event has $time field', done => { + client = new AmiClient({ addTime: true }); + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + client.once('event', event => { + assert.ok(/^\d{13}$/.test(event.$time)); + done(); }); + server.broadcast(amiUtils.fromObject({ Event: 'TestEvent' })); + }); + }); + it('Response has $time field', done => { + client = new AmiClient({ addTime: true }); + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + client.once('response', response => { + assert.ok(/^\d{13}$/.test(response.$time)); + done(); + }) + .action({ Action: 'Ping' }); + }); + }); + it('Response have deleted generated ActionID field', done => { + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + client + .on('response', response => { + assert.ok(response.ActionID === undefined); + done(); + }) + .action({ Action: 'Ping' }); + }); }); - describe('Connection state', function(){ + it('Response has generated ActionID field', done => { + client = new AmiClient({ dontDeleteSpecActionId: true }); + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + client.once('response', response => { + assert.ok(/^--spec_\d{13}$/.test(response.ActionID)); + done(); + }) + .action({ Action: 'Ping' }); + }); + }); - beforeEach(done => { - client = new AmiClient({}); - server = new AmiTestServer(serverOptions); - server.listen(socketOptions).then(done); - }); - it('State of AmiConnection before connect is "disconnected"', () => { - assert.equal(client.connection, null); - }); + }); - it('State of AmiConnection after connect is "connected"', done => { - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - assert.ok(client.connection instanceof AmiConnection); - done(); - }); - }); + describe('Connection state', function() { - it('State of connection before connect is "disconnected"', () => { - assert.ok(!client.isConnected); - }); + beforeEach(done => { + client = new AmiClient({}); + server = new AmiTestServer(serverOptions); + server.listen(socketOptions).then(done); + }); - it('State of connection after connect is "connected"', done => { - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - assert.ok(client.isConnected); - done(); - }); - }); + it('State of AmiConnection before connect is "disconnected"', () => { + assert.equal(client.connection, null); + }); - it('State of connection after disconnect is "disconnected"', done => { - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - server.close(); - setTimeout(() => { - assert.ok(!client.isConnected); - done(); - }, 100); - }); - }); + it('State of AmiConnection after connect is "connected"', done => { + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + assert.ok(client.connection instanceof AmiConnection); + done(); + }); + }); + it('State of connection before connect is "disconnected"', () => { + assert.ok(!client.isConnected); }); - describe('Event filtering', function(){ + it('State of connection after connect is "connected"', done => { + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + assert.ok(client.isConnected); + done(); + }); + }); - beforeEach(done => { - client = new AmiClient({}); - server = new AmiTestServer(serverOptions); - server.listen(socketOptions).then(done); - }); + it('State of connection after disconnect is "disconnected"', done => { + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + server.close(); + setTimeout(() => { + assert.ok(!client.isConnected); + done(); + }, 100); + }); + }); - it('Filter is disabled', done => { - let srcEvents = [ - {Event: 'Test1', Value: 'TestValue1'}, - {Event: 'Test2', Value: 'TestValue2'} - ], - controlEvents = []; - - assert.equal(null, client.option('eventFilter')); - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - client - .on('event', event => { - controlEvents.push(event); - }) - .on('response', () => { - assert.deepEqual(controlEvents, [ - {Event: 'Test1', Value: 'TestValue1'}, - {Event: 'Test2', Value: 'TestValue2'} - ]); - done(); - }); - - srcEvents.forEach(event => { - server.broadcast(amiUtils.fromObject(event)); - }); - server.broadcast(amiUtils.fromObject({ - Response: 'Success' - })); - }); - }); + }); - it('Filter is enabled', done => { - let srcEvents = [ - {Event: 'Test1', Value: 'TestValue1'}, - {Event: 'Test2', Value: 'TestValue2'} - ], - controlEvents = []; - - client.option('eventFilter', ['Test1']); - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - client - .on('event', event => { - controlEvents.push(event); - }) - .on('response', () => { - assert.deepEqual(controlEvents, [ - {Event: 'Test2', Value: 'TestValue2'} - ]); - done(); - }); - - srcEvents.forEach(event => { - server.broadcast(amiUtils.fromObject(event)); - }); - server.broadcast(amiUtils.fromObject({ - Response: 'Success' - })); - }); - }); + describe('Event filtering', function() { + beforeEach(done => { + client = new AmiClient({}); + server = new AmiTestServer(serverOptions); + server.listen(socketOptions).then(done); }); - describe('Keep-alive', function(){ + it('Filter is disabled', done => { + let srcEvents = [ + { Event: 'Test1', Value: 'TestValue1' }, + { Event: 'Test2', Value: 'TestValue2' } + ], + controlEvents = []; + + assert.equal(null, client.option('eventFilter')); + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + client + .on('event', event => { + controlEvents.push(event); + }) + .on('response', () => { + assert.deepEqual(controlEvents, [ + { Event: 'Test1', Value: 'TestValue1' }, + { Event: 'Test2', Value: 'TestValue2' } + ]); + done(); + }); + + srcEvents.forEach(event => { + server.broadcast(amiUtils.fromObject(event)); + }); + server.broadcast(amiUtils.fromObject({ + Response: 'Success' + })); + }); + }); - beforeEach(done => { - client = new AmiClient({}); - server = new AmiTestServer(serverOptions); - server.listen(socketOptions).then(done); - }); + it('Filter is enabled', done => { + let srcEvents = [ + { Event: 'Test1', Value: 'TestValue1' }, + { Event: 'Test2', Value: 'TestValue2' } + ], + controlEvents = []; + + client.option('eventFilter', ['Test1']); + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + client + .on('event', event => { + controlEvents.push(event); + }) + .on('response', () => { + assert.deepEqual(controlEvents, [ + { Event: 'Test2', Value: 'TestValue2' } + ]); + done(); + }); + + srcEvents.forEach(event => { + server.broadcast(amiUtils.fromObject(event)); + }); + server.broadcast(amiUtils.fromObject({ + Response: 'Success' + })); + }); + }); - it('keep-alive is disabled', done => { - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - let clientEventsStream = server.getAuthClients()[0]._eventStream, - timeout = setTimeout(() => { - clientEventsStream.removeAllListeners('amiAction'); - done(); - }, 2000); - - clientEventsStream.on('amiAction', action => { - if(action.Action === 'Ping'){ - clearTimeout(timeout); - } - }); - }); - }); + }); + + describe('Keep-alive', function() { + + beforeEach(done => { + client = new AmiClient({}); + server = new AmiTestServer(serverOptions); + server.listen(socketOptions).then(done); + }); - it('keep-alive is enabled', done => { - client = new AmiClient({ - keepAlive: true, - keepAliveDelay: 100 - }); - client.connect(USERNAME, SECRET, {port: socketOptions.port}).then(() => { - let clientEventsStream = server.getAuthClients()[0]._eventStream; - clientEventsStream.on('amiAction', action => { - if(action.Action === 'Ping'){ - assert.ok(action.ActionID.startsWith(client._specPrefix)); - clientEventsStream.removeAllListeners('amiAction'); - done(); - } - }); - }); + it('keep-alive is disabled', done => { + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + let clientEventsStream = server.getAuthClients()[0]._eventStream, + timeout = setTimeout(() => { + clientEventsStream.removeAllListeners('amiAction'); + done(); + }, 2000); + + clientEventsStream.on('amiAction', action => { + if (action.Action === 'Ping') { + clearTimeout(timeout); + } }); + }); + }); + it('keep-alive is enabled', done => { + client = new AmiClient({ + keepAlive: true, + keepAliveDelay: 100 + }); + client.connect(USERNAME, SECRET, { port: socketOptions.port }).then(() => { + let clientEventsStream = server.getAuthClients()[0]._eventStream; + clientEventsStream.on('amiAction', action => { + if (action.Action === 'Ping') { + assert.ok(action.ActionID.startsWith(client._specPrefix)); + clientEventsStream.removeAllListeners('amiAction'); + done(); + } + }); + }); }); + }); + });