Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

web-speech-cognitive-services

Package Overview
Dependencies
Maintainers
1
Versions
153
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

web-speech-cognitive-services - npm Package Compare versions

Comparing version 0.0.1-master.869e22a to 0.0.1-master.9c30f69

334

lib/CognitiveServicesSpeechRecognition.js

@@ -7,2 +7,4 @@ 'use strict';

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

@@ -14,2 +16,6 @@

var _eventAsPromise = require('event-as-promise');
var _eventAsPromise2 = _interopRequireDefault(_eventAsPromise);
var _memoizeOne = require('memoize-one');

@@ -23,2 +29,4 @@

function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }

@@ -77,6 +85,6 @@

var name = 'Browser';
var osVersion = "0.0.1-master.869e22a";
var osVersion = "0.0.1-master.9c30f69";
var manufacturer = 'web-speech-cognitive-services';
var model = 'web-speech-cognitive-services';
var deviceVersion = "0.0.1-master.869e22a";
var deviceVersion = "0.0.1-master.9c30f69";

@@ -144,139 +152,202 @@ var config = new CognitiveSpeech.RecognizerConfig(new CognitiveSpeech.SpeechConfig(new CognitiveSpeech.Context(new CognitiveSpeech.OS(platform, name, osVersion), new CognitiveSpeech.Device(manufacturer, model, deviceVersion))), mode, lang, CognitiveSpeech.SpeechResultFormat.Detailed);

_createClass(CognitiveServicesSpeechRecognition, [{
key: '_transitTo',
value: function _transitTo(nextReadyState) {
// console.log(`_transitTo: readyState = ${ this.readyState }, nextReadyState = ${ nextReadyState }`);
key: 'abort',
value: function abort() {
// TODO: Should redesign how to stop a recognition session
// After abort is called, we should not saw it is a "success", "silent", or "no match"
var _ref3 = this.recognizer || {},
AudioSource = _ref3.AudioSource;
if (nextReadyState > this.readyState) {
var lifecycleEvents = [null, null, this.onstart, this.onaudiostart, this.onsoundstart, this.onspeechstart, this.onspeechend, this.onsoundend, this.onaudioend, this.onend];
AudioSource && AudioSource.TurnOff();
if (this.readyState === AUDIO_START && nextReadyState >= AUDIO_END) {
// If soundstart, speechstart, speechend, and soundend are not fired after audiostart,
// we can skip them and just fire audioend directly
this.readyState = SOUND_END;
}
this._aborted = true;
}
}, {
key: 'emit',
value: function emit(name, event) {
var listener = this['on' + name];
for (var transition = this.readyState + 1; transition <= nextReadyState; transition++) {
var eventListener = lifecycleEvents[transition];
// eventListener && console.log(`Firing "${ EVENT_TYPES[transition] }"`);
eventListener && eventListener({ type: EVENT_TYPES[transition] });
}
if (nextReadyState === END) {
this.readyState = IDLE;
} else {
this.readyState = nextReadyState;
}
}
listener && listener.call(this, _extends({}, event, { type: name }));
}
}, {
key: '_handleDetailedPhrase',
value: function _handleDetailedPhrase(event) {
console.log(event);
key: 'stop',
value: function stop() {
throw new Error('not supported');
}
}, {
key: 'start',
value: function () {
var _ref4 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee3() {
var recognizer, _toPromise, eventListener, promises, error, listeningStarted, recognitionStarted, gotFirstHypothesis, speechHypothesis, speechDetailedPhrase, recognitionResult;
this._transitTo(AUDIO_END);
return regeneratorRuntime.wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
recognizer = this.recognizer = this.createRecognizer(window.localStorage.getItem('SPEECH_KEY'), this.lang);
_toPromise = toPromise(), eventListener = _toPromise.eventListener, promises = _objectWithoutProperties(_toPromise, ['eventListener']);
if (CognitiveSpeech.RecognitionStatus[event.Result.RecognitionStatus] === CognitiveSpeech.RecognitionStatus.Success) {
var nBest = event.Result.NBest;
recognizer.Recognize(eventListener);
this._aborted = false;
this.onresult && this.onresult(buildSpeechResult(event.Result.NBest[0].Display, event.Result.NBest[0].Confidence, true));
} else {
this.onerror && this.onerror({ error: event.Result.RecognitionStatus, type: 'error' });
}
}
}, {
key: '_handleHypothesis',
value: function _handleHypothesis(event) {
console.log(event);
_context3.next = 6;
return promises.recognitionTriggered;
this.onresult && this.onresult(buildSpeechResult(event.Result.Text, .5, false));
}
}, {
key: 'abort',
value: function abort() {
var _ref3 = this.recognizer || {},
AudioSource = _ref3.AudioSource;
case 6:
error = void 0;
_context3.next = 9;
return Promise.race([promises.listeningStarted, promises.recognitionEnded]);
console.log('ABORT: ' + AudioSource);
case 9:
listeningStarted = _context3.sent;
AudioSource && AudioSource.TurnOff();
}
}, {
key: 'handleRecognize',
value: function handleRecognize(event) {
try {
var name = event.Name;
if (!(listeningStarted.Name === 'RecognitionEndedEvent')) {
_context3.next = 14;
break;
}
// Possibly not authorized to use microphone
if (listeningStarted.Status === CognitiveSpeech.RecognitionCompletionStatus.AudioSourceError) {
error = 'not-allowed';
} else {
error = CognitiveSpeech.RecognitionCompletionStatus[listeningStarted.Status];
}
_context3.next = 51;
break;
console.log('handleRecognize: ' + name);
case 14:
this.emit('start');
switch (name) {
case 'ListeningStartedEvent':
this._transitTo(AUDIO_START);
break;
_context3.next = 17;
return promises.connectingToService;
case 'RecognitionEndedEvent':
if (event.Status !== CognitiveSpeech.RecognitionCompletionStatus.Success) {
this._transitTo(AUDIO_END);
this.onerror && this.onerror({ error: CognitiveSpeech.RecognitionCompletionStatus[event.Status], type: 'error' });
}
case 17:
_context3.next = 19;
return Promise.race([promises.recognitionStarted, promises.recognitionEnded]);
this._transitTo(END);
case 19:
recognitionStarted = _context3.sent;
break;
case 'RecognitionStartedEvent':
this._transitTo(SPEECH_START);
break;
this.emit('audiostart');
case 'RecognitionTriggeredEvent':
this._transitTo(START);
break;
if (!(recognitionStarted.Name === 'RecognitionEndedEvent')) {
_context3.next = 25;
break;
}
case 'SpeechEndDetectedEvent':
this._transitTo(SPEECH_END);
break;
// Possibly network error
if (recognitionStarted.Status === CognitiveSpeech.RecognitionCompletionStatus.ConnectError) {
error = 'network';
} else {
error = CognitiveSpeech.RecognitionCompletionStatus[recognitionStarted.Status];
}
_context3.next = 36;
break;
case 'SpeechStartDetectedEvent':
this._transitTo(SPEECH_START);
break;
case 25:
gotFirstHypothesis = void 0;
case 'SpeechHypothesisEvent':
this._handleHypothesis(event);
break;
case 26:
_context3.next = 28;
return Promise.race([promises.getSpeechHypothesisPromise(), promises.speechEndDetected]);
case 'SpeechDetailedPhraseEvent':
this._handleDetailedPhrase(event);
break;
case 28:
speechHypothesis = _context3.sent;
case 'ConnectingToServiceEvent':
case 'SpeechSimplePhraseEvent':
break;
if (!(speechHypothesis.Name === 'SpeechEndDetectedEvent')) {
_context3.next = 31;
break;
}
default:
console.warn('Unexpected event "' + name + '" from Cognitive Services, please file a bug to https://github.com/compulim/web-speech-cognitive-services');
break;
}
} catch (err) {
// Cognitive Services will hide all exceptions thrown in the event listener
// We need to show it otherwise when exception happen, we will not know what's going on
console.error(err);
throw err;
return _context3.abrupt('break', 35);
case 31:
if (!gotFirstHypothesis) {
gotFirstHypothesis = true;
this.emit('soundstart');
this.emit('speechstart');
}
this.emit('result', buildSpeechResult(speechHypothesis.Result.Text, .5, false));
case 33:
_context3.next = 26;
break;
case 35:
if (gotFirstHypothesis) {
this.emit('speechend');
this.emit('soundend');
}
case 36:
this.emit('audioend');
if (!this._aborted) {
_context3.next = 43;
break;
}
error = 'aborted';
_context3.next = 41;
return promises.recognitionEnded;
case 41:
_context3.next = 51;
break;
case 43:
_context3.next = 45;
return Promise.race([promises.speechDetailedPhrase, promises.recognitionEnded]);
case 45:
speechDetailedPhrase = _context3.sent;
if (!(speechDetailedPhrase.Name !== 'RecognitionEndedEvent')) {
_context3.next = 51;
break;
}
recognitionResult = CognitiveSpeech.RecognitionStatus[speechDetailedPhrase.Result.RecognitionStatus];
if (recognitionResult === CognitiveSpeech.RecognitionStatus.Success) {
this.emit('result', buildSpeechResult(speechDetailedPhrase.Result.NBest[0].Display, speechDetailedPhrase.Result.NBest[0].Confidence, true));
} else if (recognitionResult !== CognitiveSpeech.RecognitionStatus.NoMatch) {
// Possibly silent or muted
if (recognitionResult === CognitiveSpeech.RecognitionStatus.InitialSilenceTimeout) {
error = 'no-speech';
} else {
error = speechDetailedPhrase.Result.RecognitionStatus;
}
}
_context3.next = 51;
return promises.recognitionEnded;
case 51:
error && this.emit('error', { error: error });
this.emit('end');
case 53:
case 'end':
return _context3.stop();
}
}
}, _callee3, this);
}));
function start() {
return _ref4.apply(this, arguments);
}
}
}, {
key: 'start',
value: function start() {
this.recognizer = this.createRecognizer(window.localStorage.getItem('SPEECH_KEY'), this.lang);
this.recognizer.Recognize(this.handleRecognize.bind(this));
this._transitTo(START);
}
return start;
}()
}, {
key: 'stop',
value: function stop() {
throw new Error('not supported');
}
}, {
key: 'grammars',

@@ -336,3 +407,44 @@ get: function get() {

function toPromise() {
var events = {
ConnectingToServiceEvent: new _eventAsPromise2.default(),
ListeningStartedEvent: new _eventAsPromise2.default(),
RecognitionEndedEvent: new _eventAsPromise2.default(),
RecognitionStartedEvent: new _eventAsPromise2.default(),
RecognitionTriggeredEvent: new _eventAsPromise2.default(),
SpeechDetailedPhraseEvent: new _eventAsPromise2.default(),
SpeechEndDetectedEvent: new _eventAsPromise2.default(),
SpeechHypothesisEvent: new _eventAsPromise2.default(),
SpeechSimplePhraseEvent: new _eventAsPromise2.default(),
SpeechStartDetectedEvent: new _eventAsPromise2.default()
};
return {
connectingToService: events.ConnectingToServiceEvent.upcoming(),
listeningStarted: events.ListeningStartedEvent.upcoming(),
recognitionEnded: events.RecognitionEndedEvent.upcoming(),
recognitionStarted: events.RecognitionStartedEvent.upcoming(),
recognitionTriggered: events.RecognitionTriggeredEvent.upcoming(),
speechDetailedPhrase: events.SpeechDetailedPhraseEvent.upcoming(),
speechEndDetected: events.SpeechEndDetectedEvent.upcoming(),
getSpeechHypothesisPromise: function getSpeechHypothesisPromise() {
return events.SpeechHypothesisEvent.upcoming();
},
speechSimplePhrase: events.SpeechSimplePhraseEvent.upcoming(),
speechStartDetected: events.SpeechStartDetectedEvent.upcoming(),
eventListener: function eventListener(event) {
var name = event.Name;
var eventAsPromise = events[name];
if (eventAsPromise) {
eventAsPromise.eventListener.call(null, event);
} else {
console.warn('Unexpected event "' + name + '" from Cognitive Services, please file a bug to https://github.com/compulim/web-speech-cognitive-services');
}
}
};
}
exports.default = CognitiveServicesSpeechRecognition;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9Db2duaXRpdmVTZXJ2aWNlc1NwZWVjaFJlY29nbml0aW9uLmpzIl0sIm5hbWVzIjpbIkNvZ25pdGl2ZVNwZWVjaCIsIlVOSU5JVCIsIklETEUiLCJTVEFSVCIsIkFVRElPX1NUQVJUIiwiU09VTkRfU1RBUlQiLCJTUEVFQ0hfU1RBUlQiLCJTUEVFQ0hfRU5EIiwiU09VTkRfRU5EIiwiQVVESU9fRU5EIiwiRU5EIiwiRVZFTlRfVFlQRVMiLCJidWlsZFNwZWVjaFJlc3VsdCIsInRyYW5zY3JpcHQiLCJjb25maWRlbmNlIiwiaXNGaW5hbCIsInJlc3VsdCIsInJlc3VsdHMiLCJ0eXBlIiwiQ29nbml0aXZlU2VydmljZXNTcGVlY2hSZWNvZ25pdGlvbiIsIl9sYW5nIiwicmVhZHlTdGF0ZSIsIm9uYXVkaW9zdGFydCIsIm9uYXVkaW9lbmQiLCJvbmVuZCIsIm9uZXJyb3IiLCJvbm5vbWF0Y2giLCJvbnJlc3VsdCIsIm9uc291bmRzdGFydCIsIm9uc291bmRlbmQiLCJvbnNwZWVjaHN0YXJ0Iiwib25zcGVlY2hlbmQiLCJvbnN0YXJ0IiwiY3JlYXRlUmVjb2duaXplciIsInN1YnNjcmlwdGlvbktleU9yVG9rZW5GZXRjaCIsImxhbmciLCJuYXZpZ2F0b3IiLCJsYW5ndWFnZSIsIm1vZGUiLCJSZWNvZ25pdGlvbk1vZGUiLCJJbnRlcmFjdGl2ZSIsInBsYXRmb3JtIiwid2luZG93IiwidXNlckFnZW50IiwibmFtZSIsIm9zVmVyc2lvbiIsIm1hbnVmYWN0dXJlciIsIm1vZGVsIiwiZGV2aWNlVmVyc2lvbiIsImNvbmZpZyIsIlJlY29nbml6ZXJDb25maWciLCJTcGVlY2hDb25maWciLCJDb250ZXh0IiwiT1MiLCJEZXZpY2UiLCJTcGVlY2hSZXN1bHRGb3JtYXQiLCJEZXRhaWxlZCIsImF1dGgiLCJDb2duaXRpdmVUb2tlbkF1dGhlbnRpY2F0aW9uIiwiYXV0aEZldGNoRXZlbnRJRCIsIkNvZ25pdGl2ZVN1YnNjcmlwdGlvbktleUF1dGhlbnRpY2F0aW9uIiwiQ3JlYXRlUmVjb2duaXplciIsIm5leHRSZWFkeVN0YXRlIiwibGlmZWN5Y2xlRXZlbnRzIiwidHJhbnNpdGlvbiIsImV2ZW50TGlzdGVuZXIiLCJldmVudCIsImNvbnNvbGUiLCJsb2ciLCJfdHJhbnNpdFRvIiwiUmVjb2duaXRpb25TdGF0dXMiLCJSZXN1bHQiLCJTdWNjZXNzIiwibkJlc3QiLCJOQmVzdCIsIkRpc3BsYXkiLCJDb25maWRlbmNlIiwiZXJyb3IiLCJUZXh0IiwicmVjb2duaXplciIsIkF1ZGlvU291cmNlIiwiVHVybk9mZiIsIk5hbWUiLCJTdGF0dXMiLCJSZWNvZ25pdGlvbkNvbXBsZXRpb25TdGF0dXMiLCJfaGFuZGxlSHlwb3RoZXNpcyIsIl9oYW5kbGVEZXRhaWxlZFBocmFzZSIsIndhcm4iLCJlcnIiLCJsb2NhbFN0b3JhZ2UiLCJnZXRJdGVtIiwiUmVjb2duaXplIiwiaGFuZGxlUmVjb2duaXplIiwiYmluZCIsIkVycm9yIiwibmV4dEdyYW1tYXJzIiwibmV4dExhbmciLCJuZXh0Q29udGludW91cyIsIm5leHRJbnRlcmltUmVzdWx0cyIsIm5leHRNYXhBbHRlcm5hdGl2ZXMiLCJuZXh0U2VydmljZVVSSSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFBQTs7SUFBWUEsZTs7QUFDWjs7Ozs7Ozs7Ozs7O0FBRUEsSUFBTUMsU0FBUyxDQUFmO0FBQ0EsSUFBTUMsT0FBTyxDQUFiO0FBQ0EsSUFBTUMsUUFBUSxDQUFkO0FBQ0EsSUFBTUMsY0FBYyxDQUFwQjtBQUNBLElBQU1DLGNBQWMsQ0FBcEI7QUFDQSxJQUFNQyxlQUFlLENBQXJCO0FBQ0EsSUFBTUMsYUFBYSxDQUFuQjtBQUNBLElBQU1DLFlBQVksQ0FBbEI7QUFDQSxJQUFNQyxZQUFZLENBQWxCO0FBQ0EsSUFBTUMsTUFBTSxDQUFaOztBQUVBLElBQU1DLGNBQWMsQ0FDbEIsSUFEa0IsRUFFbEIsSUFGa0IsRUFHbEIsT0FIa0IsRUFJbEIsWUFKa0IsRUFLbEIsWUFMa0IsRUFNbEIsYUFOa0IsRUFPbEIsV0FQa0Is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cUJDLElBQXJCLENBQTBCLElBQTFCLENBQTFCO0FBQ0EsV0FBS3hCLFVBQUwsQ0FBZ0JsRSxLQUFoQjtBQUNEOzs7MkJBRU07QUFDTCxZQUFNLElBQUkyRixLQUFKLENBQVUsZUFBVixDQUFOO0FBQ0Q7Ozt3QkF0S2M7QUFBRTtBQUFTLEs7c0JBQ2JDLFksRUFBYztBQUN6QjtBQUNEOzs7d0JBRVU7QUFBRSxhQUFPLEtBQUszRSxLQUFaO0FBQW9CLEs7c0JBQ3hCNEUsUSxFQUFVO0FBQUUsV0FBSzVFLEtBQUwsR0FBYTRFLFFBQWI7QUFBd0I7Ozt3QkFFNUI7QUFBRSxhQUFPLEtBQVA7QUFBZSxLO3NCQUNuQkMsYyxFQUFnQjtBQUFFLFlBQU0sSUFBSUgsS0FBSixDQUFVLGVBQVYsQ0FBTjtBQUFtQzs7O3dCQUUvQztBQUFFLGFBQU8sSUFBUDtBQUFjLEs7c0JBQ2xCSSxrQixFQUFvQjtBQUNyQyxVQUFJLENBQUNBLGtCQUFMLEVBQXlCO0FBQ3ZCLGNBQU0sSUFBSUosS0FBSixDQUFVLGVBQVYsQ0FBTjtBQUNEO0FBQ0Y7Ozt3QkFFcUI7QUFBRSxhQUFPLENBQVA7QUFBVyxLO3NCQUNmSyxtQixFQUFxQjtBQUFFLFlBQU0sSUFBSUwsS0FBSixDQUFVLGVBQVYsQ0FBTjtBQUFtQzs7O3dCQUU3RDtBQUFFLGFBQU8sSUFBUDtBQUFjLEs7c0JBQ2xCTSxjLEVBQWdCO0FBQUUsWUFBTSxJQUFJTixLQUFKLENBQVUsZUFBVixDQUFOO0FBQW1DOzs7Ozs7a0JBbUp2RDNFLGtDIiwiZmlsZSI6IkNvZ25pdGl2ZVNlcnZpY2VzU3BlZWNoUmVjb2duaXRpb24uanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBDb2duaXRpdmVTcGVlY2ggZnJvbSAnbWljcm9zb2Z0LXNwZWVjaC1icm93c2VyLXNkayc7XG5pbXBvcnQgbWVtb2l6ZSBmcm9tICdtZW1vaXplLW9uZSc7XG5cbmNvbnN0IFVOSU5JVCA9IDA7XG5jb25zdCBJRExFID0gMTtcbmNvbnN0IFNUQVJUID0gMjtcbmNvbnN0IEFVRElPX1NUQVJUID0gMztcbmNvbnN0IFNPVU5EX1NUQVJUID0gNDtcbmNvbnN0IFNQRUVDSF9TVEFSVCA9IDU7XG5jb25zdCBTUEVFQ0hfRU5EID0gNjtcbmNvbnN0IFNPVU5EX0VORCA9IDc7XG5jb25zdCBBVURJT19FTkQgPSA4O1xuY29uc3QgRU5EID0gOTtcblxuY29uc3QgRVZFTlRfVFlQRVMgPSBbXG4gIG51bGwsXG4gIG51bGwsXG4gICdzdGFydCcsXG4gICdhdWRpb3N0YXJ0JyxcbiAgJ3NvdW5kc3RhcnQnLFxuICAnc3BlZWNoc3RhcnQnLFxuICAnc3BlZWNoZW5kJyxcbiAgJ3NvdW5kZW5kJyxcbiAgJ2F1ZGlvZW5kJyxcbiAgJ2VuZCdcbl07XG5cbmZ1bmN0aW9uIGJ1aWxkU3BlZWNoUmVzdWx0KHRyYW5zY3JpcHQsIGNvbmZpZGVuY2UsIGlzRmluYWwpIHtcbiAgY29uc3QgcmVzdWx0ID0gW3sgY29uZmlkZW5jZSwgdHJhbnNjcmlwdCB9XTtcblxuICByZXN1bHQuaXNGaW5hbCA9IGlzRmluYWw7XG5cbiAgcmV0dXJuIHsgcmVzdWx0czogW3Jlc3VsdF0sIHR5cGU6ICdyZXN1bHQnIH07XG59XG5cbmNsYXNzIENvZ25pdGl2ZVNlcnZpY2VzU3BlZWNoUmVjb2duaXRpb24ge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLl9sYW5nID0gJyc7XG5cbiAgICB0aGlzLnJlYWR5U3RhdGUgPSAwO1xuXG4gICAgdGhpcy5vbmF1ZGlvc3RhcnQgPSBudWxsO1xuICAgIHRoaXMub25hdWRpb2VuZCA9IG51bGw7XG4gICAgdGhpcy5vbmVuZCA9IG51bGw7XG4gICAgdGhpcy5vbmVycm9yID0gbnVsbDtcbiAgICB0aGlzLm9ubm9tYXRjaCA9IG51bGw7XG4gICAgdGhpcy5vbnJlc3VsdCA9IG51bGw7XG4gICAgdGhpcy5vbnNvdW5kc3RhcnQgPSBudWxsO1xuICAgIHRoaXMub25zb3VuZGVuZCA9IG51bGw7XG4gICAgdGhpcy5vbnNwZWVjaHN0YXJ0ID0gbnVsbDtcbiAgICB0aGlzLm9uc3BlZWNoZW5kID0gbnVsbDtcbiAgICB0aGlzLm9uc3RhcnQgPSBudWxsO1xuXG4gICAgdGhpcy5jcmVhdGVSZWNvZ25pemVyID0gbWVtb2l6ZSgoXG4gICAgICBzdWJzY3JpcHRpb25LZXlPclRva2VuRmV0Y2gsXG4gICAgICBsYW5nID0gbmF2aWdhdG9yLmxhbmd1YWdlLFxuICAgICAgbW9kZSA9IENvZ25pdGl2ZVNwZWVjaC5SZWNvZ25pdGlvbk1vZGUuSW50ZXJhY3RpdmVcbiAgICApID0+IHtcbiAgICAgIGNvbnN0IHBsYXRmb3JtID0gd2luZG93Lm5hdmlnYXRvci51c2VyQWdlbnQ7XG4gICAgICBjb25zdCBuYW1lID0gJ0Jyb3dzZXInO1xuICAgICAgY29uc3Qgb3NWZXJzaW9uID0gVkVSU0lPTjtcbiAgICAgIGNvbnN0IG1hbnVmYWN0dXJlciA9ICd3ZWItc3BlZWNoLWNvZ25pdGl2ZS1zZXJ2aWNlcyc7XG4gICAgICBjb25zdCBtb2RlbCA9ICd3ZWItc3BlZWNoLWNvZ25pdGl2ZS1zZXJ2aWNlcyc7XG4gICAgICBjb25zdCBkZXZpY2VWZXJzaW9uID0gVkVSU0lPTjtcblxuICAgICAgY29uc3QgY29uZmlnID0gbmV3IENvZ25pdGl2ZVNwZWVjaC5SZWNvZ25pemVyQ29uZmlnKFxuICAgICAgICBuZXcgQ29nbml0aXZlU3BlZWNoLlNwZWVjaENvbmZpZyhcbiAgICAgICAgICBuZXcgQ29nbml0aXZlU3BlZWNoLkNvbnRleHQoXG4gICAgICAgICAgICBuZXcgQ29nbml0aXZlU3BlZWNoLk9TKHBsYXRmb3JtLCBuYW1lLCBvc1ZlcnNpb24pLFxuICAgICAgICAgICAgbmV3IENvZ25pdGl2ZVNwZWVjaC5EZXZpY2UobWFudWZhY3R1cmVyLCBtb2RlbCwgZGV2aWNlVmVyc2lvbilcbiAgICAgICAgICApXG4gICAgICAgICksXG4gICAgICAgIG1vZGUsXG4gICAgICAgIGxhbmcsXG4gICAgICAgIENvZ25pdGl2ZVNwZWVjaC5TcGVlY2hSZXN1bHRGb3JtYXQuRGV0YWlsZWRcbiAgICAgICk7XG5cbiAgICAgIGxldCBhdXRoO1xuXG4gICAgICBpZiAodHlwZW9mIHN1YnNjcmlwdGlvbktleU9yVG9rZW5GZXRjaCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBhdXRoID0gbmV3IENvZ25pdGl2ZVNwZWVjaC5Db2duaXRpdmVUb2tlbkF1dGhlbnRpY2F0aW9uKFxuICAgICAgICAgIGFzeW5jIGF1dGhGZXRjaEV2ZW50SUQgPT4gYXdhaXQgc3Vic2NyaXB0aW9uS2V5T3JUb2tlbkZldGNoKGF1dGhGZXRjaEV2ZW50SUQsIGZhbHNlKSxcbiAgICAgICAgICBhc3luYyBhdXRoRmV0Y2hFdmVudElEID0+IGF3YWl0IHN1YnNjcmlwdGlvbktleU9yVG9rZW5GZXRjaChhdXRoRmV0Y2hFdmVudElELCB0cnVlKVxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXV0aCA9IG5ldyBDb2duaXRpdmVTcGVlY2guQ29nbml0aXZlU3Vic2NyaXB0aW9uS2V5QXV0aGVudGljYXRpb24oc3Vic2NyaXB0aW9uS2V5T3JUb2tlbkZldGNoKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIENvZ25pdGl2ZVNwZWVjaC5DcmVhdGVSZWNvZ25pemVyKGNvbmZpZywgYXV0aCk7XG4gICAgfSk7XG4gIH1cblxuICBnZXQgZ3JhbW1hcnMoKSB7IHJldHVybjsgfVxuICBzZXQgZ3JhbW1hcnMobmV4dEdyYW1tYXJzKSB7XG4gICAgLy8gdGhyb3cgbmV3IEVycm9yKCdub3Qgc3VwcG9ydGVkJyk7XG4gIH1cblxuICBnZXQgbGFuZygpIHsgcmV0dXJuIHRoaXMuX2xhbmc7IH1cbiAgc2V0IGxhbmcobmV4dExhbmcpIHsgdGhpcy5fbGFuZyA9IG5leHRMYW5nOyB9XG5cbiAgZ2V0IGNvbnRpbnVvdXMoKSB7IHJldHVybiBmYWxzZTsgfVxuICBzZXQgY29udGludW91cyhuZXh0Q29udGludW91cykgeyB0aHJvdyBuZXcgRXJyb3IoJ25vdCBzdXBwb3J0ZWQnKTsgfVxuXG4gIGdldCBpbnRlcmltUmVzdWx0cygpIHsgcmV0dXJuIHRydWU7IH1cbiAgc2V0IGludGVyaW1SZXN1bHRzKG5leHRJbnRlcmltUmVzdWx0cykge1xuICAgIGlmICghbmV4dEludGVyaW1SZXN1bHRzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ25vdCBzdXBwb3J0ZWQnKTtcbiAgICB9XG4gIH1cblxuICBnZXQgbWF4QWx0ZXJuYXRpdmVzKCkgeyByZXR1cm4gMTsgfVxuICBzZXQgbWF4QWx0ZXJuYXRpdmVzKG5leHRNYXhBbHRlcm5hdGl2ZXMpIHsgdGhyb3cgbmV3IEVycm9yKCdub3Qgc3VwcG9ydGVkJyk7IH1cblxuICBnZXQgc2VydmljZVVSSSgpIHsgcmV0dXJuIG51bGw7IH1cbiAgc2V0IHNlcnZpY2VVUkkobmV4dFNlcnZpY2VVUkkpIHsgdGhyb3cgbmV3IEVycm9yKCdub3Qgc3VwcG9ydGVkJyk7IH1cblxuICBfdHJhbnNpdFRvKG5leHRSZWFkeVN0YXRlKSB7XG4gICAgLy8gY29uc29sZS5sb2coYF90cmFuc2l0VG86IHJlYWR5U3RhdGUgPSAkeyB0aGlzLnJlYWR5U3RhdGUgfSwgbmV4dFJlYWR5U3RhdGUgPSAkeyBuZXh0UmVhZHlTdGF0ZSB9YCk7XG5cbiAgICBpZiAobmV4dFJlYWR5U3RhdGUgPiB0aGlzLnJlYWR5U3RhdGUpIHtcbiAgICAgIGNvbnN0IGxpZmVjeWNsZUV2ZW50cyA9IFtcbiAgICAgICAgbnVsbCxcbiAgICAgICAgbnVsbCxcbiAgICAgICAgdGhpcy5vbnN0YXJ0LFxuICAgICAgICB0aGlzLm9uYXVkaW9zdGFydCxcbiAgICAgICAgdGhpcy5vbnNvdW5kc3RhcnQsXG4gICAgICAgIHRoaXMub25zcGVlY2hzdGFydCxcbiAgICAgICAgdGhpcy5vbnNwZWVjaGVuZCxcbiAgICAgICAgdGhpcy5vbnNvdW5kZW5kLFxuICAgICAgICB0aGlzLm9uYXVkaW9lbmQsXG4gICAgICAgIHRoaXMub25lbmRcbiAgICAgIF07XG5cbiAgICAgIGlmIChcbiAgICAgICAgdGhpcy5yZWFkeVN0YXRlID09PSBBVURJT19TVEFSVFxuICAgICAgICAmJiBuZXh0UmVhZHlTdGF0ZSA+PSBBVURJT19FTkRcbiAgICAgICkge1xuICAgICAgICAvLyBJZiBzb3VuZHN0YXJ0LCBzcGVlY2hzdGFydCwgc3BlZWNoZW5kLCBhbmQgc291bmRlbmQgYXJlIG5vdCBmaXJlZCBhZnRlciBhdWRpb3N0YXJ0LFxuICAgICAgICAvLyB3ZSBjYW4gc2tpcCB0aGVtIGFuZCBqdXN0IGZpcmUgYXVkaW9lbmQgZGlyZWN0bHlcbiAgICAgICAgdGhpcy5yZWFkeVN0YXRlID0gU09VTkRfRU5EO1xuICAgICAgfVxuXG4gICAgICBmb3IgKGxldCB0cmFuc2l0aW9uID0gdGhpcy5yZWFkeVN0YXRlICsgMTsgdHJhbnNpdGlvbiA8PSBuZXh0UmVhZHlTdGF0ZTsgdHJhbnNpdGlvbisrKSB7XG4gICAgICAgIGNvbnN0IGV2ZW50TGlzdGVuZXIgPSBsaWZlY3ljbGVFdmVudHNbdHJhbnNpdGlvbl07XG5cbiAgICAgICAgLy8gZXZlbnRMaXN0ZW5lciAmJiBjb25zb2xlLmxvZyhgRmlyaW5nIFwiJHsgRVZFTlRfVFlQRVNbdHJhbnNpdGlvbl0gfVwiYCk7XG4gICAgICAgIGV2ZW50TGlzdGVuZXIgJiYgZXZlbnRMaXN0ZW5lcih7IHR5cGU6IEVWRU5UX1RZUEVTW3RyYW5zaXRpb25dIH0pO1xuICAgICAgfVxuXG4gICAgICBpZiAobmV4dFJlYWR5U3RhdGUgPT09IEVORCkge1xuICAgICAgICB0aGlzLnJlYWR5U3RhdGUgPSBJRExFO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5yZWFkeVN0YXRlID0gbmV4dFJlYWR5U3RhdGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgX2hhbmRsZURldGFpbGVkUGhyYXNlKGV2ZW50KSB7XG4gICAgY29uc29sZS5sb2coZXZlbnQpO1xuXG4gICAgdGhpcy5fdHJhbnNpdFRvKEFVRElPX0VORCk7XG5cbiAgICBpZiAoQ29nbml0aXZlU3BlZWNoLlJlY29nbml0aW9uU3RhdHVzW2V2ZW50LlJlc3VsdC5SZWNvZ25pdGlvblN0YXR1c10gPT09IENvZ25pdGl2ZVNwZWVjaC5SZWNvZ25pdGlvblN0YXR1cy5TdWNjZXNzKSB7XG4gICAgICBjb25zdCB7IE5CZXN0OiBuQmVzdCB9ID0gZXZlbnQuUmVzdWx0O1xuXG4gICAgICB0aGlzLm9ucmVzdWx0ICYmIHRoaXMub25yZXN1bHQoYnVpbGRTcGVlY2hSZXN1bHQoZXZlbnQuUmVzdWx0Lk5CZXN0WzBdLkRpc3BsYXksIGV2ZW50LlJlc3VsdC5OQmVzdFswXS5Db25maWRlbmNlLCB0cnVlKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMub25lcnJvciAmJiB0aGlzLm9uZXJyb3IoeyBlcnJvcjogZXZlbnQuUmVzdWx0LlJlY29nbml0aW9uU3RhdHVzLCB0eXBlOiAnZXJyb3InIH0pO1xuICAgIH1cbiAgfVxuXG4gIF9oYW5kbGVIeXBvdGhlc2lzKGV2ZW50KSB7XG4gICAgY29uc29sZS5sb2coZXZlbnQpO1xuXG4gICAgdGhpcy5vbnJlc3VsdCAmJiB0aGlzLm9ucmVzdWx0KGJ1aWxkU3BlZWNoUmVzdWx0KGV2ZW50LlJlc3VsdC5UZXh0LCAuNSwgZmFsc2UpKTtcbiAgfVxuXG4gIGFib3J0KCkge1xuICAgIGNvbnN0IHsgQXVkaW9Tb3VyY2UgfSA9IHRoaXMucmVjb2duaXplciB8fCB7fTtcblxuICAgIGNvbnNvbGUubG9nKGBBQk9SVDogJHsgQXVkaW9Tb3VyY2UgfWApO1xuXG4gICAgQXVkaW9Tb3VyY2UgJiYgQXVkaW9Tb3VyY2UuVHVybk9mZigpO1xuICB9XG5cbiAgaGFuZGxlUmVjb2duaXplKGV2ZW50KSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHsgTmFtZTogbmFtZSB9ID0gZXZlbnQ7XG5cbiAgICAgIGNvbnNvbGUubG9nKGBoYW5kbGVSZWNvZ25pemU6ICR7IG5hbWUgfWApO1xuXG4gICAgICBzd2l0Y2ggKG5hbWUpIHtcbiAgICAgIGNhc2UgJ0xpc3RlbmluZ1N0YXJ0ZWRFdmVudCc6XG4gICAgICAgIHRoaXMuX3RyYW5zaXRUbyhBVURJT19TVEFSVCk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdSZWNvZ25pdGlvbkVuZGVkRXZlbnQnOlxuICAgICAgICBpZiAoZXZlbnQuU3RhdHVzICE9PSBDb2duaXRpdmVTcGVlY2guUmVjb2duaXRpb25Db21wbGV0aW9uU3RhdHVzLlN1Y2Nlc3MpIHtcbiAgICAgICAgICB0aGlzLl90cmFuc2l0VG8oQVVESU9fRU5EKTtcbiAgICAgICAgICB0aGlzLm9uZXJyb3IgJiYgdGhpcy5vbmVycm9yKHsgZXJyb3I6IENvZ25pdGl2ZVNwZWVjaC5SZWNvZ25pdGlvbkNvbXBsZXRpb25TdGF0dXNbZXZlbnQuU3RhdHVzXSwgdHlwZTogJ2Vycm9yJyB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX3RyYW5zaXRUbyhFTkQpO1xuXG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdSZWNvZ25pdGlvblN0YXJ0ZWRFdmVudCc6XG4gICAgICAgIHRoaXMuX3RyYW5zaXRUbyhTUEVFQ0hfU1RBUlQpO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnUmVjb2duaXRpb25UcmlnZ2VyZWRFdmVudCc6XG4gICAgICAgIHRoaXMuX3RyYW5zaXRUbyhTVEFSVCk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdTcGVlY2hFbmREZXRlY3RlZEV2ZW50JzpcbiAgICAgICAgdGhpcy5fdHJhbnNpdFRvKFNQRUVDSF9FTkQpO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnU3BlZWNoU3RhcnREZXRlY3RlZEV2ZW50JzpcbiAgICAgICAgdGhpcy5fdHJhbnNpdFRvKFNQRUVDSF9TVEFSVCk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdTcGVlY2hIeXBvdGhlc2lzRXZlbnQnOlxuICAgICAgICB0aGlzLl9oYW5kbGVIeXBvdGhlc2lzKGV2ZW50KTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJ1NwZWVjaERldGFpbGVkUGhyYXNlRXZlbnQnOlxuICAgICAgICB0aGlzLl9oYW5kbGVEZXRhaWxlZFBocmFzZShldmVudCk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdDb25uZWN0aW5nVG9TZXJ2aWNlRXZlbnQnOlxuICAgICAgY2FzZSAnU3BlZWNoU2ltcGxlUGhyYXNlRXZlbnQnOlxuICAgICAgICBicmVhaztcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgY29uc29sZS53YXJuKGBVbmV4cGVjdGVkIGV2ZW50IFxcXCIkeyBuYW1lIH1cXFwiIGZyb20gQ29nbml0aXZlIFNlcnZpY2VzLCBwbGVhc2UgZmlsZSBhIGJ1ZyB0byBodHRwczovL2dpdGh1Yi5jb20vY29tcHVsaW0vd2ViLXNwZWVjaC1jb2duaXRpdmUtc2VydmljZXNgKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAvLyBDb2duaXRpdmUgU2VydmljZXMgd2lsbCBoaWRlIGFsbCBleGNlcHRpb25zIHRocm93biBpbiB0aGUgZXZlbnQgbGlzdGVuZXJcbiAgICAgIC8vIFdlIG5lZWQgdG8gc2hvdyBpdCBvdGhlcndpc2Ugd2hlbiBleGNlcHRpb24gaGFwcGVuLCB3ZSB3aWxsIG5vdCBrbm93IHdoYXQncyBnb2luZyBvblxuICAgICAgY29uc29sZS5lcnJvcihlcnIpO1xuICAgICAgdGhyb3cgZXJyO1xuICAgIH1cbiAgfVxuXG4gIHN0YXJ0KCkge1xuICAgIHRoaXMucmVjb2duaXplciA9IHRoaXMuY3JlYXRlUmVjb2duaXplcihcbiAgICAgIHdpbmRvdy5sb2NhbFN0b3JhZ2UuZ2V0SXRlbSgnU1BFRUNIX0tFWScpLFxuICAgICAgdGhpcy5sYW5nXG4gICAgKTtcblxuICAgIHRoaXMucmVjb2duaXplci5SZWNvZ25pemUodGhpcy5oYW5kbGVSZWNvZ25pemUuYmluZCh0aGlzKSk7XG4gICAgdGhpcy5fdHJhbnNpdFRvKFNUQVJUKTtcbiAgfVxuXG4gIHN0b3AoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdub3Qgc3VwcG9ydGVkJyk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgQ29nbml0aXZlU2VydmljZXNTcGVlY2hSZWNvZ25pdGlvblxuIl19
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9Db2duaXRpdmVTZXJ2aWNlc1NwZWVjaFJlY29nbml0aW9uLmpzIl0sIm5hbWVzIjpbIkNvZ25pdGl2ZVNwZWVjaCIsIlVOSU5JVCIsIklETEUiLCJTVEFSVCIsIkFVRElPX1NUQVJUIiwiU09VTkRfU1RBUlQiLCJTUEVFQ0hfU1RBUlQiLCJTUEVFQ0hfRU5EIiwiU09VTkRfRU5EIiwiQVVESU9fRU5EIiwiRU5EIiwiRVZFTlRfVFlQRVMiLCJidWlsZFNwZWVjaFJlc3VsdCIsInRyYW5zY3JpcHQiLCJjb25maWRlbmNlIiwiaXNGaW5hbCIsInJlc3VsdCIsInJlc3VsdHMiLCJ0eXBlIiwiQ29nbml0aXZlU2VydmljZXNTcGVlY2hSZWNvZ25pdGlvbiIsIl9sYW5nIiwicmVhZHlTdGF0ZSIsIm9uYXVkaW9zdGFydCIsIm9uYXVkaW9lbmQiLCJvbmVuZCIsIm9uZXJyb3IiLCJvbm5vbWF0Y2giLCJvbnJlc3VsdCIsIm9uc291bmRzdGFydCIsIm9uc291bmRlbmQiLCJvbnNwZWVjaHN0YXJ0Iiwib25zcGVlY2hlbmQiLCJvbnN0YXJ0IiwiY3JlYXRlUmVjb2duaXplciIsInN1YnNjcmlwdGlvbktleU9yVG9rZW5GZXRjaCIsImxhbmciLCJuYXZpZ2F0b3IiLCJsYW5ndWFnZSIsIm1vZGUiLCJSZWNvZ25pdGlvbk1vZGUiLCJJbnRlcmFjdGl2ZSIsInBsYXRmb3JtIiwid2luZG93IiwidXNlckFnZW50IiwibmFtZSIsIm9zVmVyc2lvbiIsIm1hbnVmYWN0dXJlciIsIm1vZGVsIiwiZGV2aWNlVmVyc2lvbiIsImNvbmZpZyIsIlJlY29nbml6ZXJDb25maWciLCJTcGVlY2hDb25maWciLCJDb250ZXh0IiwiT1MiLCJEZXZpY2UiLCJTcGVlY2hSZXN1bHRGb3JtYXQiLCJEZXRhaWxlZCIsImF1dGgiLCJDb2duaXRpdmVUb2tlbkF1dGhlbnRpY2F0aW9uIiwiYXV0aEZldGNoRXZlbnRJRCIsIkNvZ25pdGl2ZVN1YnNjcmlwdGlvbktleUF1dGhlbnRpY2F0aW9uIiwiQ3JlYXRlUmVjb2duaXplciIsInJlY29nbml6ZXIiLCJBdWRpb1NvdXJjZSIsIlR1cm5PZmYiLCJfYWJvcnRlZCIsImV2ZW50IiwibGlzdGVuZXIiLCJjYWxsIiwiRXJyb3IiLCJsb2NhbFN0b3JhZ2UiLCJnZXRJdGVtIiwidG9Qcm9taXNlIiwiZXZlbnRMaXN0ZW5lciIsInByb21pc2VzIiwiUmVjb2duaXplIiwicmVjb2duaXRpb25UcmlnZ2VyZWQiLCJlcnJvciIsIlByb21pc2UiLCJyYWNlIiwibGlzdGVuaW5nU3RhcnRlZCIsInJlY29nbml0aW9uRW5kZWQiLCJOYW1lIiwiU3RhdHVzIiwiUmVjb2duaXRpb25Db21wbGV0aW9uU3RhdHVzIiwiQXVkaW9Tb3VyY2VFcnJvciIsImVtaXQiLCJjb25uZWN0aW5nVG9TZXJ2aWNlIiwicmVjb2duaXRpb25TdGFydGVkIiwiQ29ubmVjdEVycm9yIiwiZ290Rmlyc3RIeXBvdGhlc2lzIiwiZ2V0U3BlZWNoSHlwb3RoZXNpc1Byb21pc2UiLCJzcGVlY2hFbmREZXRlY3RlZCIsInNwZWVjaEh5cG90aGVzaXMiLCJSZXN1bHQiLCJUZXh0Iiwic3BlZWNoRGV0YWlsZWRQaHJhc2UiLCJyZWNvZ25pdGlvblJlc3VsdCIsIlJlY29nbml0aW9uU3RhdHVzIiwiU3VjY2VzcyIsIk5CZXN0IiwiRGlzcGxheSIsIkNvbmZpZGVuY2UiLCJOb01hdGNoIiwiSW5pdGlhbFNpbGVuY2VUaW1lb3V0IiwibmV4dEdyYW1tYXJzIiwibmV4dExhbmciLCJuZXh0Q29udGludW91cyIsIm5leHRJbnRlcmltUmVzdWx0cyIsIm5leHRNYXhBbHRlcm5hdGl2ZXMiLCJuZXh0U2VydmljZVVSSSIsImV2ZW50cyIsIkNvbm5lY3RpbmdUb1NlcnZpY2VFdmVudCIsIkV2ZW50QXNQcm9taXNlIiwiTGlzdGVuaW5nU3RhcnRlZEV2ZW50IiwiUmVjb2duaXRpb25FbmRlZEV2ZW50IiwiUmVjb2duaXRpb25TdGFydGVkRXZlbnQiLCJSZWNvZ25pdGlvblRyaWdnZXJlZEV2ZW50IiwiU3BlZWNoRGV0YWlsZWRQaHJhc2VFdmVudCIsIlNwZWVjaEVuZERldGVjdGVkRXZlbnQiLCJTcGVlY2hIeXBvdGhlc2lzRXZlbnQiLCJTcGVlY2hTaW1wbGVQaHJhc2VFdmVudCIsIlNwZWVjaFN0YXJ0RGV0ZWN0ZWRFdmVudCIsInVwY29taW5nIiwic3BlZWNoU2ltcGxlUGhyYXNlIiwic3BlZWNoU3RhcnREZXRlY3RlZCIsImV2ZW50QXNQcm9taXNlIiwiY29uc29sZSIsIndhcm4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7QUFBQTs7SUFBWUEsZTs7QUFDWjs7OztBQUNBOzs7Ozs7Ozs7Ozs7OztBQUVBLElBQU1DLFNBQVMsQ0FBZjtBQUNBLElBQU1DLE9BQU8sQ0FBYjtBQUNBLElBQU1DLFFBQVEsQ0FBZDtBQUNBLElBQU1DLGNBQWMsQ0FBcEI7QUFDQSxJQUFNQyxjQUFjLENBQXBCO0FBQ0EsSUFBTUMsZUFBZSxDQUFyQjtBQUNBLElBQU1DLGFBQWEsQ0FBbkI7QUFDQSxJQUFNQyxZQUFZLENBQWxCO0FBQ0EsSUFBTUMsWUFBWSxDQUFsQjtBQUNBLElBQU1DLE1BQU0sQ0FBWjs7QUFFQSxJQUFNQyxjQUFjLENBQ2xCLElBRGtCLEVBRWxCLElBRmtCLEVBR2xCLE9BSGtCLEVBSWxCLFlBSmtCLEVBS2xCLFlBTGtCLEVBTWxCLGFBTmtCLEVBT2xCLFdBUGtCLEVBUWxCLFVBUmtCLEVBU2xCLFVBVGtCLEVBVWxCLEtBVmtCLENBQXBCOztBQWFBLFNBQVNDLGlCQUFULENBQTJCQyxVQUEzQixFQUF1Q0MsVUFBdkMsRUFBbURDLE9BQW5ELEVBQTREO0FBQzFELE1BQU1DLFNBQVMsQ0FBQyxFQUFFRixzQkFBRixFQUFjRCxzQkFBZCxFQUFELENBQWY7O0FBRUFHLFNBQU9ELE9BQVAsR0FBaUJBLE9BQWpCOztBQUVBLFNBQU8sRUFBRUUsU0FBUyxDQUFDRCxNQUFELENBQVgsRUFBcUJFLE1BQU0sUUFBM0IsRUFBUDtBQUNEOztJQUVLQyxrQztBQUNKLGdEQUFjO0FBQUE7O0FBQUE7O0FBQ1osU0FBS0Ms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LENBQStCRSxRQUEvQixFQVRmO0FBVUxFLHlCQUFxQmQsT0FBT1csd0JBQVAsQ0FBZ0NDLFFBQWhDLEVBVmhCO0FBV0xsRCxtQkFBZSw4QkFBUztBQUFBLFVBQ1I3QixJQURRLEdBQ0NzQixLQURELENBQ2RnQixJQURjOztBQUV0QixVQUFNNEMsaUJBQWlCZixPQUFPbkUsSUFBUCxDQUF2Qjs7QUFFQSxVQUFJa0YsY0FBSixFQUFvQjtBQUNsQkEsdUJBQWVyRCxhQUFmLENBQTZCTCxJQUE3QixDQUFrQyxJQUFsQyxFQUF3Q0YsS0FBeEM7QUFDRCxPQUZELE1BRU87QUFDTDZELGdCQUFRQyxJQUFSLHdCQUFvQ3BGLElBQXBDO0FBQ0Q7QUFDRjtBQXBCSSxHQUFQO0FBc0JEOztrQkFFY3pCLGtDIiwiZmlsZSI6IkNvZ25pdGl2ZVNlcnZpY2VzU3BlZWNoUmVjb2duaXRpb24uanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBDb2duaXRpdmVTcGVlY2ggZnJvbSAnbWljcm9zb2Z0LXNwZWVjaC1icm93c2VyLXNkayc7XG5pbXBvcnQgRXZlbnRBc1Byb21pc2UgZnJvbSAnZXZlbnQtYXMtcHJvbWlzZSc7XG5pbXBvcnQgbWVtb2l6ZSBmcm9tICdtZW1vaXplLW9uZSc7XG5cbmNvbnN0IFVOSU5JVCA9IDA7XG5jb25zdCBJRExFID0gMTtcbmNvbnN0IFNUQVJUID0gMjtcbmNvbnN0IEFVRElPX1NUQVJUID0gMztcbmNvbnN0IFNPVU5EX1NUQVJUID0gNDtcbmNvbnN0IFNQRUVDSF9TVEFSVCA9IDU7XG5jb25zdCBTUEVFQ0hfRU5EID0gNjtcbmNvbnN0IFNPVU5EX0VORCA9IDc7XG5jb25zdCBBVURJT19FTkQgPSA4O1xuY29uc3QgRU5EID0gOTtcblxuY29uc3QgRVZFTlRfVFlQRVMgPSBbXG4gIG51bGwsXG4gIG51bGwsXG4gICdzdGFydCcsXG4gICdhdWRpb3N0YXJ0JyxcbiAgJ3NvdW5kc3RhcnQnLFxuICAnc3BlZWNoc3RhcnQnLFxuICAnc3BlZWNoZW5kJyxcbiAgJ3NvdW5kZW5kJyxcbiAgJ2F1ZGlvZW5kJyxcbiAgJ2VuZCdcbl07XG5cbmZ1bmN0aW9uIGJ1aWxkU3BlZWNoUmVzdWx0KHRyYW5zY3JpcHQsIGNvbmZpZGVuY2UsIGlzRmluYWwpIHtcbiAgY29uc3QgcmVzdWx0ID0gW3sgY29uZmlkZW5jZSwgdHJhbnNjcmlwdCB9XTtcblxuICByZXN1bHQuaXNGaW5hbCA9IGlzRmluYWw7XG5cbiAgcmV0dXJuIHsgcmVzdWx0czogW3Jlc3VsdF0sIHR5cGU6ICdyZXN1bHQnIH07XG59XG5cbmNsYXNzIENvZ25pdGl2ZVNlcnZpY2VzU3BlZWNoUmVjb2duaXRpb24ge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLl9sYW5nID0gJyc7XG5cbiAgICB0aGlzLnJlYWR5U3RhdGUgPSAwO1xuXG4gICAgdGhpcy5vbmF1ZGlvc3RhcnQgPSBudWxsO1xuICAgIHRoaXMub25hdWRpb2VuZCA9IG51bGw7XG4gICAgdGhpcy5vbmVuZCA9IG51bGw7XG4gICAgdGhpcy5vbmVycm9yID0gbnVsbDtcbiAgICB0aGlzLm9ubm9tYXRjaCA9IG51bGw7XG4gICAgdGhpcy5vbnJlc3VsdCA9IG51bGw7XG4gICAgdGhpcy5vbnNvdW5kc3RhcnQgPSBudWxsO1xuICAgIHRoaXMub25zb3VuZGVuZCA9IG51bGw7XG4gICAgdGhpcy5vbnNwZWVjaHN0YXJ0ID0gbnVsbDtcbiAgICB0aGlzLm9uc3BlZWNoZW5kID0gbnVsbDtcbiAgICB0aGlzLm9uc3RhcnQgPSBudWxsO1xuXG4gICAgdGhpcy5jcmVhdGVSZWNvZ25pemVyID0gbWVtb2l6ZSgoXG4gICAgICBzdWJzY3JpcHRpb25LZXlPclRva2VuRmV0Y2gsXG4gICAgICBsYW5nID0gbmF2aWdhdG9yLmxhbmd1YWdlLFxuICAgICAgbW9kZSA9IENvZ25pdGl2ZVNwZWVjaC5SZWNvZ25pdGlvbk1vZGUuSW50ZXJhY3RpdmVcbiAgICApID0+IHtcbiAgICAgIGNvbnN0IHBsYXRmb3JtID0gd2luZG93Lm5hdmlnYXRvci51c2VyQWdlbnQ7XG4gICAgICBjb25zdCBuYW1lID0gJ0Jyb3dzZXInO1xuICAgICAgY29uc3Qgb3NWZXJzaW9uID0gVkVSU0lPTjtcbiAgICAgIGNvbnN0IG1hbnVmYWN0dXJlciA9ICd3ZWItc3BlZWNoLWNvZ25pdGl2ZS1zZXJ2aWNlcyc7XG4gICAgICBjb25zdCBtb2RlbCA9ICd3ZWItc3BlZWNoLWNvZ25pdGl2ZS1zZXJ2aWNlcyc7XG4gICAgICBjb25zdCBkZXZpY2VWZXJzaW9uID0gVkVSU0lPTjtcblxuICAgICAgY29uc3QgY29uZmlnID0gbmV3IENvZ25pdGl2ZVNwZWVjaC5SZWNvZ25pemVyQ29uZmlnKFxuICAgICAgICBuZXcgQ29nbml0aXZlU3BlZWNoLlNwZWVjaENvbmZpZyhcbiAgICAgICAgICBuZXcgQ29nbml0aXZlU3BlZWNoLkNvbnRleHQoXG4gICAgICAgICAgICBuZXcgQ29nbml0aXZlU3BlZWNoLk9TKHBsYXRmb3JtLCBuYW1lLCBvc1ZlcnNpb24pLFxuICAgICAgICAgICAgbmV3IENvZ25pdGl2ZVNwZWVjaC5EZXZpY2UobWFudWZhY3R1cmVyLCBtb2RlbCwgZGV2aWNlVmVyc2lvbilcbiAgICAgICAgICApXG4gICAgICAgICksXG4gICAgICAgIG1vZGUsXG4gICAgICAgIGxhbmcsXG4gICAgICAgIENvZ25pdGl2ZVNwZWVjaC5TcGVlY2hSZXN1bHRGb3JtYXQuRGV0YWlsZWRcbiAgICAgICk7XG5cbiAgICAgIGxldCBhdXRoO1xuXG4gICAgICBpZiAodHlwZW9mIHN1YnNjcmlwdGlvbktleU9yVG9rZW5GZXRjaCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBhdXRoID0gbmV3IENvZ25pdGl2ZVNwZWVjaC5Db2duaXRpdmVUb2tlbkF1dGhlbnRpY2F0aW9uKFxuICAgICAgICAgIGFzeW5jIGF1dGhGZXRjaEV2ZW50SUQgPT4gYXdhaXQgc3Vic2NyaXB0aW9uS2V5T3JUb2tlbkZldGNoKGF1dGhGZXRjaEV2ZW50SUQsIGZhbHNlKSxcbiAgICAgICAgICBhc3luYyBhdXRoRmV0Y2hFdmVudElEID0+IGF3YWl0IHN1YnNjcmlwdGlvbktleU9yVG9rZW5GZXRjaChhdXRoRmV0Y2hFdmVudElELCB0cnVlKVxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXV0aCA9IG5ldyBDb2duaXRpdmVTcGVlY2guQ29nbml0aXZlU3Vic2NyaXB0aW9uS2V5QXV0aGVudGljYXRpb24oc3Vic2NyaXB0aW9uS2V5T3JUb2tlbkZldGNoKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIENvZ25pdGl2ZVNwZWVjaC5DcmVhdGVSZWNvZ25pemVyKGNvbmZpZywgYXV0aCk7XG4gICAgfSk7XG4gIH1cblxuICBnZXQgZ3JhbW1hcnMoKSB7IHJldHVybjsgfVxuICBzZXQgZ3JhbW1hcnMobmV4dEdyYW1tYXJzKSB7XG4gICAgLy8gdGhyb3cgbmV3IEVycm9yKCdub3Qgc3VwcG9ydGVkJyk7XG4gIH1cblxuICBnZXQgbGFuZygpIHsgcmV0dXJuIHRoaXMuX2xhbmc7IH1cbiAgc2V0IGxhbmcobmV4dExhbmcpIHsgdGhpcy5fbGFuZyA9IG5leHRMYW5nOyB9XG5cbiAgZ2V0IGNvbnRpbnVvdXMoKSB7IHJldHVybiBmYWxzZTsgfVxuICBzZXQgY29udGludW91cyhuZXh0Q29udGludW91cykgeyB0aHJvdyBuZXcgRXJyb3IoJ25vdCBzdXBwb3J0ZWQnKTsgfVxuXG4gIGdldCBpbnRlcmltUmVzdWx0cygpIHsgcmV0dXJuIHRydWU7IH1cbiAgc2V0IGludGVyaW1SZXN1bHRzKG5leHRJbnRlcmltUmVzdWx0cykge1xuICAgIGlmICghbmV4dEludGVyaW1SZXN1bHRzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ25vdCBzdXBwb3J0ZWQnKTtcbiAgICB9XG4gIH1cblxuICBnZXQgbWF4QWx0ZXJuYXRpdmVzKCkgeyByZXR1cm4gMTsgfVxuICBzZXQgbWF4QWx0ZXJuYXRpdmVzKG5leHRNYXhBbHRlcm5hdGl2ZXMpIHsgdGhyb3cgbmV3IEVycm9yKCdub3Qgc3VwcG9ydGVkJyk7IH1cblxuICBnZXQgc2VydmljZVVSSSgpIHsgcmV0dXJuIG51bGw7IH1cbiAgc2V0IHNlcnZpY2VVUkkobmV4dFNlcnZpY2VVUkkpIHsgdGhyb3cgbmV3IEVycm9yKCdub3Qgc3VwcG9ydGVkJyk7IH1cblxuICBhYm9ydCgpIHtcbiAgICAvLyBUT0RPOiBTaG91bGQgcmVkZXNpZ24gaG93IHRvIHN0b3AgYSByZWNvZ25pdGlvbiBzZXNzaW9uXG4gICAgLy8gICAgICAgQWZ0ZXIgYWJvcnQgaXMgY2FsbGVkLCB3ZSBzaG91bGQgbm90IHNhdyBpdCBpcyBhIFwic3VjY2Vzc1wiLCBcInNpbGVudFwiLCBvciBcIm5vIG1hdGNoXCJcbiAgICBjb25zdCB7IEF1ZGlvU291cmNlIH0gPSB0aGlzLnJlY29nbml6ZXIgfHwge307XG5cbiAgICBBdWRpb1NvdXJjZSAmJiBBdWRpb1NvdXJjZS5UdXJuT2ZmKCk7XG5cbiAgICB0aGlzLl9hYm9ydGVkID0gdHJ1ZTtcbiAgfVxuXG4gIGVtaXQobmFtZSwgZXZlbnQpIHtcbiAgICBjb25zdCBsaXN0ZW5lciA9IHRoaXNbYG9uJHsgbmFtZSB9YF07XG5cbiAgICBsaXN0ZW5lciAmJiBsaXN0ZW5lci5jYWxsKHRoaXMsIHsgLi4uZXZlbnQsIHR5cGU6IG5hbWUgfSk7XG4gIH1cblxuICBzdG9wKCkge1xuICAgIHRocm93IG5ldyBFcnJvcignbm90IHN1cHBvcnRlZCcpO1xuICB9XG5cbiAgYXN5bmMgc3RhcnQoKSB7XG4gICAgY29uc3QgcmVjb2duaXplciA9IHRoaXMucmVjb2duaXplciA9IHRoaXMuY3JlYXRlUmVjb2duaXplcihcbiAgICAgIHdpbmRvdy5sb2NhbFN0b3JhZ2UuZ2V0SXRlbSgnU1BFRUNIX0tFWScpLFxuICAgICAgdGhpcy5sYW5nXG4gICAgKTtcblxuICAgIGNvbnN0IHsgZXZlbnRMaXN0ZW5lciwgLi4ucHJvbWlzZXMgfSA9IHRvUHJvbWlzZSgpO1xuXG4gICAgcmVjb2duaXplci5SZWNvZ25pemUoZXZlbnRMaXN0ZW5lcik7XG4gICAgdGhpcy5fYWJvcnRlZCA9IGZhbHNlO1xuXG4gICAgYXdhaXQgcHJvbWlzZXMucmVjb2duaXRpb25UcmlnZ2VyZWQ7XG5cbiAgICBsZXQgZXJyb3I7XG5cbiAgICBjb25zdCBsaXN0ZW5pbmdTdGFydGVkID0gYXdhaXQgUHJvbWlzZS5yYWNlKFtcbiAgICAgIHByb21pc2VzLmxpc3RlbmluZ1N0YXJ0ZWQsXG4gICAgICBwcm9taXNlcy5yZWNvZ25pdGlvbkVuZGVkXG4gICAgXSk7XG5cbiAgICBpZiAobGlzdGVuaW5nU3RhcnRlZC5OYW1lID09PSAnUmVjb2duaXRpb25FbmRlZEV2ZW50Jykge1xuICAgICAgLy8gUG9zc2libHkgbm90IGF1dGhvcml6ZWQgdG8gdXNlIG1pY3JvcGhvbmVcbiAgICAgIGlmIChsaXN0ZW5pbmdTdGFydGVkLlN0YXR1cyA9PT0gQ29nbml0aXZlU3BlZWNoLlJlY29nbml0aW9uQ29tcGxldGlvblN0YXR1cy5BdWRpb1NvdXJjZUVycm9yKSB7XG4gICAgICAgIGVycm9yID0gJ25vdC1hbGxvd2VkJztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGVycm9yID0gQ29nbml0aXZlU3BlZWNoLlJlY29nbml0aW9uQ29tcGxldGlvblN0YXR1c1tsaXN0ZW5pbmdTdGFydGVkLlN0YXR1c107XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZW1pdCgnc3RhcnQnKTtcblxuICAgICAgYXdhaXQgcHJvbWlzZXMuY29ubmVjdGluZ1RvU2VydmljZTtcblxuICAgICAgY29uc3QgcmVjb2duaXRpb25TdGFydGVkID0gYXdhaXQgUHJvbWlzZS5yYWNlKFtcbiAgICAgICAgcHJvbWlzZXMucmVjb2duaXRpb25TdGFydGVkLFxuICAgICAgICBwcm9taXNlcy5yZWNvZ25pdGlvbkVuZGVkXG4gICAgICBdKTtcblxuICAgICAgdGhpcy5lbWl0KCdhdWRpb3N0YXJ0Jyk7XG5cbiAgICAgIGlmIChyZWNvZ25pdGlvblN0YXJ0ZWQuTmFtZSA9PT0gJ1JlY29nbml0aW9uRW5kZWRFdmVudCcpIHtcbiAgICAgICAgLy8gUG9zc2libHkgbmV0d29yayBlcnJvclxuICAgICAgICBpZiAocmVjb2duaXRpb25TdGFydGVkLlN0YXR1cyA9PT0gQ29nbml0aXZlU3BlZWNoLlJlY29nbml0aW9uQ29tcGxldGlvblN0YXR1cy5Db25uZWN0RXJyb3IpIHtcbiAgICAgICAgICBlcnJvciA9ICduZXR3b3JrJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBlcnJvciA9IENvZ25pdGl2ZVNwZWVjaC5SZWNvZ25pdGlvbkNvbXBsZXRpb25TdGF0dXNbcmVjb2duaXRpb25TdGFydGVkLlN0YXR1c107XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxldCBnb3RGaXJzdEh5cG90aGVzaXM7XG5cbiAgICAgICAgZm9yICg7Oykge1xuICAgICAgICAgIGNvbnN0IHNwZWVjaEh5cG90aGVzaXMgPSBhd2FpdCBQcm9taXNlLnJhY2UoW1xuICAgICAgICAgICAgcHJvbWlzZXMuZ2V0U3BlZWNoSHlwb3RoZXNpc1Byb21pc2UoKSxcbiAgICAgICAgICAgIHByb21pc2VzLnNwZWVjaEVuZERldGVjdGVkXG4gICAgICAgICAgXSk7XG5cbiAgICAgICAgICBpZiAoc3BlZWNoSHlwb3RoZXNpcy5OYW1lID09PSAnU3BlZWNoRW5kRGV0ZWN0ZWRFdmVudCcpIHtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICghZ290Rmlyc3RIeXBvdGhlc2lzKSB7XG4gICAgICAgICAgICBnb3RGaXJzdEh5cG90aGVzaXMgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5lbWl0KCdzb3VuZHN0YXJ0Jyk7XG4gICAgICAgICAgICB0aGlzLmVtaXQoJ3NwZWVjaHN0YXJ0Jyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdGhpcy5lbWl0KCdyZXN1bHQnLCBidWlsZFNwZWVjaFJlc3VsdChzcGVlY2hIeXBvdGhlc2lzLlJlc3VsdC5UZXh0LCAuNSwgZmFsc2UpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChnb3RGaXJzdEh5cG90aGVzaXMpIHtcbiAgICAgICAgICB0aGlzLmVtaXQoJ3NwZWVjaGVuZCcpO1xuICAgICAgICAgIHRoaXMuZW1pdCgnc291bmRlbmQnKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB0aGlzLmVtaXQoJ2F1ZGlvZW5kJyk7XG5cbiAgICAgIGlmICh0aGlzLl9hYm9ydGVkKSB7XG4gICAgICAgIGVycm9yID0gJ2Fib3J0ZWQnO1xuXG4gICAgICAgIGF3YWl0IHByb21pc2VzLnJlY29nbml0aW9uRW5kZWQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBzcGVlY2hEZXRhaWxlZFBocmFzZSA9IGF3YWl0IFByb21pc2UucmFjZShbXG4gICAgICAgICAgcHJvbWlzZXMuc3BlZWNoRGV0YWlsZWRQaHJhc2UsXG4gICAgICAgICAgcHJvbWlzZXMucmVjb2duaXRpb25FbmRlZFxuICAgICAgICBdKTtcblxuICAgICAgICBpZiAoc3BlZWNoRGV0YWlsZWRQaHJhc2UuTmFtZSAhPT0gJ1JlY29nbml0aW9uRW5kZWRFdmVudCcpIHtcbiAgICAgICAgICBjb25zdCByZWNvZ25pdGlvblJlc3VsdCA9IENvZ25pdGl2ZVNwZWVjaC5SZWNvZ25pdGlvblN0YXR1c1tzcGVlY2hEZXRhaWxlZFBocmFzZS5SZXN1bHQuUmVjb2duaXRpb25TdGF0dXNdO1xuXG4gICAgICAgICAgaWYgKHJlY29nbml0aW9uUmVzdWx0ID09PSBDb2duaXRpdmVTcGVlY2guUmVjb2duaXRpb25TdGF0dXMuU3VjY2Vzcykge1xuICAgICAgICAgICAgdGhpcy5lbWl0KCdyZXN1bHQnLCBidWlsZFNwZWVjaFJlc3VsdChzcGVlY2hEZXRhaWxlZFBocmFzZS5SZXN1bHQuTkJlc3RbMF0uRGlzcGxheSwgc3BlZWNoRGV0YWlsZWRQaHJhc2UuUmVzdWx0Lk5CZXN0WzBdLkNvbmZpZGVuY2UsIHRydWUpKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKHJlY29nbml0aW9uUmVzdWx0ICE9PSBDb2duaXRpdmVTcGVlY2guUmVjb2duaXRpb25TdGF0dXMuTm9NYXRjaCkge1xuICAgICAgICAgICAgLy8gUG9zc2libHkgc2lsZW50IG9yIG11dGVkXG4gICAgICAgICAgICBpZiAocmVjb2duaXRpb25SZXN1bHQgPT09IENvZ25pdGl2ZVNwZWVjaC5SZWNvZ25pdGlvblN0YXR1cy5Jbml0aWFsU2lsZW5jZVRpbWVvdXQpIHtcbiAgICAgICAgICAgICAgZXJyb3IgPSAnbm8tc3BlZWNoJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGVycm9yID0gc3BlZWNoRGV0YWlsZWRQaHJhc2UuUmVzdWx0LlJlY29nbml0aW9uU3RhdHVzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGF3YWl0IHByb21pc2VzLnJlY29nbml0aW9uRW5kZWQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBlcnJvciAmJiB0aGlzLmVtaXQoJ2Vycm9yJywgeyBlcnJvciB9KTtcbiAgICB0aGlzLmVtaXQoJ2VuZCcpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRvUHJvbWlzZSgpIHtcbiAgY29uc3QgZXZlbnRzID0ge1xuICAgIENvbm5lY3RpbmdUb1NlcnZpY2VFdmVudDogbmV3IEV2ZW50QXNQcm9taXNlKCksXG4gICAgTGlzdGVuaW5nU3RhcnRlZEV2ZW50OiBuZXcgRXZlbnRBc1Byb21pc2UoKSxcbiAgICBSZWNvZ25pdGlvbkVuZGVkRXZlbnQ6IG5ldyBFdmVudEFzUHJvbWlzZSgpLFxuICAgIFJlY29nbml0aW9uU3RhcnRlZEV2ZW50OiBuZXcgRXZlbnRBc1Byb21pc2UoKSxcbiAgICBSZWNvZ25pdGlvblRyaWdnZXJlZEV2ZW50OiBuZXcgRXZlbnRBc1Byb21pc2UoKSxcbiAgICBTcGVlY2hEZXRhaWxlZFBocmFzZUV2ZW50OiBuZXcgRXZlbnRBc1Byb21pc2UoKSxcbiAgICBTcGVlY2hFbmREZXRlY3RlZEV2ZW50OiBuZXcgRXZlbnRBc1Byb21pc2UoKSxcbiAgICBTcGVlY2hIeXBvdGhlc2lzRXZlbnQ6IG5ldyBFdmVudEFzUHJvbWlzZSgpLFxuICAgIFNwZWVjaFNpbXBsZVBocmFzZUV2ZW50OiBuZXcgRXZlbnRBc1Byb21pc2UoKSxcbiAgICBTcGVlY2hTdGFydERldGVjdGVkRXZlbnQ6IG5ldyBFdmVudEFzUHJvbWlzZSgpXG4gIH07XG5cbiAgcmV0dXJuIHtcbiAgICBjb25uZWN0aW5nVG9TZXJ2aWNlOiBldmVudHMuQ29ubmVjdGluZ1RvU2VydmljZUV2ZW50LnVwY29taW5nKCksXG4gICAgbGlzdGVuaW5nU3RhcnRlZDogZXZlbnRzLkxpc3RlbmluZ1N0YXJ0ZWRFdmVudC51cGNvbWluZygpLFxuICAgIHJlY29nbml0aW9uRW5kZWQ6IGV2ZW50cy5SZWNvZ25pdGlvbkVuZGVkRXZlbnQudXBjb21pbmcoKSxcbiAgICByZWNvZ25pdGlvblN0YXJ0ZWQ6IGV2ZW50cy5SZWNvZ25pdGlvblN0YXJ0ZWRFdmVudC51cGNvbWluZygpLFxuICAgIHJlY29nbml0aW9uVHJpZ2dlcmVkOiBldmVudHMuUmVjb2duaXRpb25UcmlnZ2VyZWRFdmVudC51cGNvbWluZygpLFxuICAgIHNwZWVjaERldGFpbGVkUGhyYXNlOiBldmVudHMuU3BlZWNoRGV0YWlsZWRQaHJhc2VFdmVudC51cGNvbWluZygpLFxuICAgIHNwZWVjaEVuZERldGVjdGVkOiBldmVudHMuU3BlZWNoRW5kRGV0ZWN0ZWRFdmVudC51cGNvbWluZygpLFxuICAgIGdldFNwZWVjaEh5cG90aGVzaXNQcm9taXNlOiAoKSA9PiBldmVudHMuU3BlZWNoSHlwb3RoZXNpc0V2ZW50LnVwY29taW5nKCksXG4gICAgc3BlZWNoU2ltcGxlUGhyYXNlOiBldmVudHMuU3BlZWNoU2ltcGxlUGhyYXNlRXZlbnQudXBjb21pbmcoKSxcbiAgICBzcGVlY2hTdGFydERldGVjdGVkOiBldmVudHMuU3BlZWNoU3RhcnREZXRlY3RlZEV2ZW50LnVwY29taW5nKCksXG4gICAgZXZlbnRMaXN0ZW5lcjogZXZlbnQgPT4ge1xuICAgICAgY29uc3QgeyBOYW1lOiBuYW1lIH0gPSBldmVudDtcbiAgICAgIGNvbnN0IGV2ZW50QXNQcm9taXNlID0gZXZlbnRzW25hbWVdO1xuXG4gICAgICBpZiAoZXZlbnRBc1Byb21pc2UpIHtcbiAgICAgICAgZXZlbnRBc1Byb21pc2UuZXZlbnRMaXN0ZW5lci5jYWxsKG51bGwsIGV2ZW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUud2FybihgVW5leHBlY3RlZCBldmVudCBcXFwiJHsgbmFtZSB9XFxcIiBmcm9tIENvZ25pdGl2ZSBTZXJ2aWNlcywgcGxlYXNlIGZpbGUgYSBidWcgdG8gaHR0cHM6Ly9naXRodWIuY29tL2NvbXB1bGltL3dlYi1zcGVlY2gtY29nbml0aXZlLXNlcnZpY2VzYCk7XG4gICAgICB9XG4gICAgfVxuICB9O1xufVxuXG5leHBvcnQgZGVmYXVsdCBDb2duaXRpdmVTZXJ2aWNlc1NwZWVjaFJlY29nbml0aW9uXG4iXX0=
{
"name": "web-speech-cognitive-services",
"version": "0.0.1-master.869e22a",
"version": "0.0.1-master.9c30f69",
"description": "",

@@ -31,8 +31,10 @@ "keywords": [],

"babel-plugin-version-transform": "^1.0.0",
"babel-polyfill": "^6.26.0",
"babel-preset-stage-3": "^6.24.1",
"classnames": "^2.2.6",
"event-as-promise": "^1.0.3",
"glamor": "^2.20.40",
"jest": "^22.4.4",
"lerna": "^2.11.0",
"microsoft-speech-browser-sdk": "0.0.12",
"microsoft-speech-browser-sdk": "^0.0.12",
"react": "^16.4.1",

@@ -39,0 +41,0 @@ "react-dictate-button": "^1.0.0",

# web-speech-cognitive-services
[![npm version](https://badge.fury.io/js/we-bspeech-cognitive-services.svg)](https://badge.fury.io/js/we-bspeech-cognitive-services) [![Build Status](https://travis-ci.org/compulim/we-bspeech-cognitive-services.svg?branch=master)](https://travis-ci.org/compulim/web-speech-cognitive-services)
[![npm version](https://badge.fury.io/js/web-speech-cognitive-services.svg)](https://badge.fury.io/js/web-speech-cognitive-services) [![Build Status](https://travis-ci.org/compulim/web-speech-cognitive-services.svg?branch=master)](https://travis-ci.org/compulim/web-speech-cognitive-services)
Polyfill Web Speech API with Cognitive Services.
Polyfill Web Speech API with Cognitive Services Speech-to-Text service.
## Event lifecycle mapping from Cognitive Services
This scaffold is provided by [`react-component-template`](https://github.com/compulim/react-component-template/).
| # | WebSpeech | Cognitive Services | Notes |
| - | - | - | - |
| 1 | `start` | `RecognitionTriggeredEvent` | |
| 2 | `audiostart` | `ListeningStartedEvent` | |
| 3 | | `ConnectingToServiceEvent` | |
| 4 | `soundstart`, `speechstart` | `RecognitionStartedEvent` | |
| 5 | `onresult(isFinal = false)` | `SpeechHypothesisEvent` | |
| 6 | `speechend`, `soundend`, `audioend` | `SpeechEndDetectedEvent` | `speechend` and `soundend` only fire if either `speechstart` and `soundstart` was fired |
| 7 | `onresult(isFinal = true)`, `onerror` | `SpeechSimplePhraseEvent` | |
| 8 | `end` | `RecognitionEndedEvent` | |
# Demo
### Scenarios
Try out our demo at https://compulim.github.io/web-speech-cognitive-services?s=your-subscription-key.
* Happy path
We use [`react-dictate-button`](https://github.com/compulim/react-dictate-button/) to quickly setup the playground.
# Background
Web Speech API is not widely adopted on popular browsers and platforms. Polyfilling the API using cloud services is a great way to enable wider adoption. Nonetheless, Web Speech API in Google Chrome is also backed by cloud services.
Microsoft Azure [Cognitive Services Speech-to-Text](https://azure.microsoft.com/en-us/services/cognitive-services/speech-to-text/) service provide speech recognition with great accuracy. But unfortunately, the APIs are not based on Web Speech API.
This package will polyfill Web Speech API by turning Cognitive Services Speech-to-Text API into Web Speech API. We test this package with popular combination of platforms and browsers.
# How to use
First, run `npm install web-speech-cognitive-services` for latest production build. Or `npm install web-speech-cognitive-services@master` for latest development build.
```jsx
import CognitiveServicesSpeechRecognition from 'web-speech-cognitive-services';
const recognition = new CognitiveServicesSpeechRecognition();
// There are two ways to provide your credential:
// 1. Provide a subscription key (good for prototype, not for production)
// 2. Provide a mechanism to obtain/refresh access token
// If you are using subscription key
recognition.subscriptionKey = 'your subscription key';
// If you are using access token, refreshToken === true, if we are renewing the token, otherwise, false
recognition.tokenFetch = async (authFetchEventID, refreshToken) => {
};
recognition.lang = 'en-US';
recognition.onresult = ({ results }) => {
console.log(results);
};
recognition.start();
```
# Test matrix
Browsers are all latest as of 2018-06-28, except:
* macOS was 10.13.1 (2017-10-31), instead of 10.13.5
* There should be no change on the matrix since Safari does not support Web Speech API
* Xbox was tested on Insider build (1806) with Kinect sensor connected
* The latest Insider build does not support both WebRTC and Web Speech API, so we suspect the production build also does not support both
Quick grab:
* Web Speech API works on most popular platforms, except iOS
* iOS: No browsers on iOS support Web Speech API
* Some platforms requires non-default browser (unsupported in Microsoft Edge)
* Cognitive Services Speech-to-Text work on all popular platforms with their default browsers
* iOS: Chrome and Edge does not support Cognitive Services because iOS WebView does not support WebRTC
| Platform | OS | Browser | Cognitive Services (WebRTC) | Web Speech API |
| - | - | - | - | - |
| PC | Windows 10 (1803) | Chrome 67.0.3396.99 | Yes | Yes |
| PC | Windows 10 (1803) | Edge 42.17134.1.0 | Yes | No, `SpeechRecognition` not implemented |
| PC | Windows 10 (1803) | Firefox 61.0 | Yes | No, `SpeechRecognition` not implemented |
| MacBook Pro | macOS High Sierra 10.13.1 | Chrome 67.0.3396.99 | Yes | Yes |
| MacBook Pro | macOS High Sierra 10.13.1 | Safari 11.0.1 | Yes | No, `SpeechRecognition` not implemented |
| Apple iPhone X | iOS 11.4 | Chrome 67.0.3396.87 | No, `AudioSourceError` | No, `SpeechRecognition` not implemented |
| Apple iPhone X | iOS 11.4 | Edge 42.2.2.0 | No, `AudioSourceError` | No, `SpeechRecognition` not implemented |
| Apple iPhone X | iOS 11.4 | Safari | Yes | No, `SpeechRecognition` not implemented |
| Apple iPod (6th gen) | iOS 11.4 | Chrome 67.0.3396.87 | No, `AudioSourceError` | No, `SpeechRecognition` not implemented |
| Apple iPod (6th gen) | iOS 11.4 | Edge 42.2.2.0 | No, `AudioSourceError` | No, `SpeechRecognition` not implemented |
| Apple iPod (6th gen) | iOS 11.4 | Safari | No, `AudioSourceError` | No, `SpeechRecognition` not implemented |
| Google Pixel 2 | Android 8.1.0 | Chrome 67.0.3396.87 | Yes | Yes |
| Google Pixel 2 | Android 8.1.0 | Edge 42.0.0.2057 | Yes | Yes |
| Google Pixel 2 | Android 8.1.0 | Firefox 60.1.0 | Yes | Yes |
| Microsoft Lumia 950 | Windows 10 (1709) | Edge 40.15254.489.0 | No, `AudioSourceError` | No, `SpeechRecognition` not implemented |
| Microsoft Xbox One | Windows 10 (1806) 17134.4054 | Edge 42.17134.4054.0 | No, `AudioSourceError` | No, `SpeechRecognition` not implemented |
## Event lifecycle scenarios
We test multiple scenarios to make sure the package polyfill Web Speech API correctly. Following are events and its firing order, in Cognitive Services and Web Speech API respectively.
* [Happy path](#happy-path)
* [Abort during recognition](#abort-during-recognition)
* [Network issues](#network-issues)
* [Audio muted or volume too low](#audio-muted-or-volume-too-low)
* [No speech is recognized](#no-speech-is-recognized)
* [Not authorized to use microphone](#not-authorized-to-use-microphone)
### Happy path
Everything works, including multiple interim results.
* Cognitive Services
1. `RecognitionTriggeredEvent`

@@ -29,11 +108,64 @@ 2. `ListeningStartedEvent`

6. `SpeechEndDetectedEvent`
7. `SpeechSimplePhraseEvent`
7. `SpeechDetailedPhraseEvent`
8. `RecognitionEndedEvent`
* Network issues
* Web Speech API
1. `start`
2. `audiostart`
3. `soundstart`
4. `speechstart`
5. `result` (multiple times)
6. `speechend`
7. `soundend`
8. `audioend`
9. `result(results = [{ isFinal = true }])`
10. `end`
### Abort during recognition
#### Abort before first recognition is made
* Cognitive Services
* Essentially muted the microphone, very similar to [happy path](#happy-path), could still result in success, silent, or no match
* Web Speech API
1. `start`
2. `audiostart`
8. `audioend`
9. `error(error = 'aborted')`
10. `end`
#### Abort after some speech is recognized
* Cognitive Services
* Essentially muted the microphone, very similar to [happy path](#happy-path), could still result in success, silent, or no match
* Web Speech API
1. `start`
2. `audiostart`
3. `soundstart` (optional)
4. `speechstart` (optional)
5. `result` (optional)
6. `speechend` (optional)
7. `soundend` (optional)
8. `audioend`
9. `error(error = 'aborted')`
10. `end`
### Network issues
Turn on airplane mode.
* Cognitive Services
1. `RecognitionTriggeredEvent`
2. `ListeningStartedEvent`
3. `ConnectingToServiceEvent`
4. `SpeechSimplePhraseEvent`
5. `RecognitionEndedEvent`
* Audio muted or volume too low
5. `RecognitionEndedEvent(Result.RecognitionStatus = 'ConnectError')`
* Web Speech API
1. `start`
2. `audiostart`
3. `audioend`
4. `error(error = 'network')`
5. `end`
### Audio muted or volume too low
* Cognitive Services
1. `RecognitionTriggeredEvent`

@@ -44,5 +176,16 @@ 2. `ListeningStartedEvent`

5. `SpeechEndDetectedEvent`
6. `SpeechSimplePhraseEvent(Result.RecognitionStatus = 'InitialSilenceTimeout')`
6. `SpeechDetailedPhraseEvent(Result.RecognitionStatus = 'InitialSilenceTimeout')`
7. `RecognitionEndedEvent`
* Failed to recognize speech (a.k.a. no match)
* Web Speech API
1. `start`
2. `audiostart`
3. `audioend`
4. `error(error = 'no-speech')`
5. `end`
### No speech is recognized
Some sounds are heard, but they cannot be recognized as text. There could be some interim results with recognized text, but the confidence is so low it dropped out of final result.
* Cognitive Services
1. `RecognitionTriggeredEvent`

@@ -54,13 +197,41 @@ 2. `ListeningStartedEvent`

6. `SpeechEndDetectedEvent`
7. `SpeechSimplePhraseEvent(Result.RecognitionStatus = 'NoMatch')`
7. `SpeechDetailedPhraseEvent(Result.RecognitionStatus = 'NoMatch')`
8. `RecognitionEndedEvent`
* User abort
* Essentially muted the speech, that could result in success, silent, or no match
* Web Speech API
1. `start`
2. `audiostart`
3. `soundstart`
4. `speechstart`
5. `result`
6. `speechend`
7. `soundend`
8. `audioend`
9. `end`
> Note: the Web Speech API has `onnomatch` event, but unfortunately, Google Chrome did not fire this event.
### Not authorized to use microphone
The user click "deny" on the permission dialog, or there are no microphone detected in the system.
* Cognitive Services
1. `RecognitionTriggeredEvent`
2. `RecognitionEndedEvent(Result.RecognitionStatus = 'AudioSourceError')`
* Web Speech API
1. `error(error = 'not-allowed')`
2. `end`
# Known issues
* Interim results do not return confidence, final result do have confidence
* We always return `0.5` for interim results
* Cognitive Services support grammar list but not in JSGF format, more work to be done in this area
* Although Google Chrome support setting the grammar list, it seems the grammar list is not used at all
# Contributions
Like us? [Star](https://github.com/compulim/we-bspeech-cognitive-services/stargazers) us.
Like us? [Star](https://github.com/compulim/web-speech-cognitive-services/stargazers) us.
Want to make it better? [File](https://github.com/compulim/we-bspeech-cognitive-services/issues) us an issue.
Want to make it better? [File](https://github.com/compulim/web-speech-cognitive-services/issues) us an issue.
Don't like something you see? [Submit](https://github.com/compulim/web-speech-cognitive-services/pulls) a pull request.
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc