>>2]>>>24-8*(r%4)&255)<<16|(l[r+1>>>2]>>>24-8*((r+1)%4)&255)<<8|l[r+2>>>2]>>>24-8*((r+2)%4)&255,v=0;4>v&&r+0.75*v>>6*(3-v)&63));if(l=t.charAt(64))for(;d.length%4;)d.push(l);return d.join(\"\")},parse:function(d){var l=d.length,s=this._map,t=s.charAt(64);t&&(t=d.indexOf(t),-1!=t&&(l=t));for(var t=[],r=0,w=0;w<\nl;w++)if(w%4){var v=s.indexOf(d.charAt(w-1))<<2*(w%4),b=s.indexOf(d.charAt(w))>>>6-2*(w%4);t[r>>>2]|=(v|b)<<24-8*(r%4);r++}return p.create(t,r)},_map:\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\"}})();\n\n// BlockCipher\n(function(u){function p(b,n,a,c,e,j,k){b=b+(n&a|~n&c)+e+k;return(b<>>32-j)+n}function d(b,n,a,c,e,j,k){b=b+(n&c|a&~c)+e+k;return(b<>>32-j)+n}function l(b,n,a,c,e,j,k){b=b+(n^a^c)+e+k;return(b<>>32-j)+n}function s(b,n,a,c,e,j,k){b=b+(a^(n|~c))+e+k;return(b<>>32-j)+n}for(var t=CryptoJS,r=t.lib,w=r.WordArray,v=r.Hasher,r=t.algo,b=[],x=0;64>x;x++)b[x]=4294967296*u.abs(u.sin(x+1))|0;r=r.MD5=v.extend({_doReset:function(){this._hash=new w.init([1732584193,4023233417,2562383102,271733878])},\n_doProcessBlock:function(q,n){for(var a=0;16>a;a++){var c=n+a,e=q[c];q[c]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360}var a=this._hash.words,c=q[n+0],e=q[n+1],j=q[n+2],k=q[n+3],z=q[n+4],r=q[n+5],t=q[n+6],w=q[n+7],v=q[n+8],A=q[n+9],B=q[n+10],C=q[n+11],u=q[n+12],D=q[n+13],E=q[n+14],x=q[n+15],f=a[0],m=a[1],g=a[2],h=a[3],f=p(f,m,g,h,c,7,b[0]),h=p(h,f,m,g,e,12,b[1]),g=p(g,h,f,m,j,17,b[2]),m=p(m,g,h,f,k,22,b[3]),f=p(f,m,g,h,z,7,b[4]),h=p(h,f,m,g,r,12,b[5]),g=p(g,h,f,m,t,17,b[6]),m=p(m,g,h,f,w,22,b[7]),\nf=p(f,m,g,h,v,7,b[8]),h=p(h,f,m,g,A,12,b[9]),g=p(g,h,f,m,B,17,b[10]),m=p(m,g,h,f,C,22,b[11]),f=p(f,m,g,h,u,7,b[12]),h=p(h,f,m,g,D,12,b[13]),g=p(g,h,f,m,E,17,b[14]),m=p(m,g,h,f,x,22,b[15]),f=d(f,m,g,h,e,5,b[16]),h=d(h,f,m,g,t,9,b[17]),g=d(g,h,f,m,C,14,b[18]),m=d(m,g,h,f,c,20,b[19]),f=d(f,m,g,h,r,5,b[20]),h=d(h,f,m,g,B,9,b[21]),g=d(g,h,f,m,x,14,b[22]),m=d(m,g,h,f,z,20,b[23]),f=d(f,m,g,h,A,5,b[24]),h=d(h,f,m,g,E,9,b[25]),g=d(g,h,f,m,k,14,b[26]),m=d(m,g,h,f,v,20,b[27]),f=d(f,m,g,h,D,5,b[28]),h=d(h,f,\nm,g,j,9,b[29]),g=d(g,h,f,m,w,14,b[30]),m=d(m,g,h,f,u,20,b[31]),f=l(f,m,g,h,r,4,b[32]),h=l(h,f,m,g,v,11,b[33]),g=l(g,h,f,m,C,16,b[34]),m=l(m,g,h,f,E,23,b[35]),f=l(f,m,g,h,e,4,b[36]),h=l(h,f,m,g,z,11,b[37]),g=l(g,h,f,m,w,16,b[38]),m=l(m,g,h,f,B,23,b[39]),f=l(f,m,g,h,D,4,b[40]),h=l(h,f,m,g,c,11,b[41]),g=l(g,h,f,m,k,16,b[42]),m=l(m,g,h,f,t,23,b[43]),f=l(f,m,g,h,A,4,b[44]),h=l(h,f,m,g,u,11,b[45]),g=l(g,h,f,m,x,16,b[46]),m=l(m,g,h,f,j,23,b[47]),f=s(f,m,g,h,c,6,b[48]),h=s(h,f,m,g,w,10,b[49]),g=s(g,h,f,m,\nE,15,b[50]),m=s(m,g,h,f,r,21,b[51]),f=s(f,m,g,h,u,6,b[52]),h=s(h,f,m,g,k,10,b[53]),g=s(g,h,f,m,B,15,b[54]),m=s(m,g,h,f,e,21,b[55]),f=s(f,m,g,h,v,6,b[56]),h=s(h,f,m,g,x,10,b[57]),g=s(g,h,f,m,t,15,b[58]),m=s(m,g,h,f,D,21,b[59]),f=s(f,m,g,h,z,6,b[60]),h=s(h,f,m,g,C,10,b[61]),g=s(g,h,f,m,j,15,b[62]),m=s(m,g,h,f,A,21,b[63]);a[0]=a[0]+f|0;a[1]=a[1]+m|0;a[2]=a[2]+g|0;a[3]=a[3]+h|0},_doFinalize:function(){var b=this._data,n=b.words,a=8*this._nDataBytes,c=8*b.sigBytes;n[c>>>5]|=128<<24-c%32;var e=u.floor(a/\n4294967296);n[(c+64>>>9<<4)+15]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360;n[(c+64>>>9<<4)+14]=(a<<8|a>>>24)&16711935|(a<<24|a>>>8)&4278255360;b.sigBytes=4*(n.length+1);this._process();b=this._hash;n=b.words;for(a=0;4>a;a++)c=n[a],n[a]=(c<<8|c>>>24)&16711935|(c<<24|c>>>8)&4278255360;return b},clone:function(){var b=v.clone.call(this);b._hash=this._hash.clone();return b}});t.MD5=v._createHelper(r);t.HmacMD5=v._createHmacHelper(r)})(Math);\n(function(){var u=CryptoJS,p=u.lib,d=p.Base,l=p.WordArray,p=u.algo,s=p.EvpKDF=d.extend({cfg:d.extend({keySize:4,hasher:p.MD5,iterations:1}),init:function(d){this.cfg=this.cfg.extend(d)},compute:function(d,r){for(var p=this.cfg,s=p.hasher.create(),b=l.create(),u=b.words,q=p.keySize,p=p.iterations;u.length>>2]&255}};d.BlockCipher=v.extend({cfg:v.cfg.extend({mode:b,padding:q}),reset:function(){v.reset.call(this);var a=this.cfg,b=a.iv,a=a.mode;if(this._xformMode==this._ENC_XFORM_MODE)var c=a.createEncryptor;else c=a.createDecryptor,this._minBufferSize=1;this._mode=c.call(a,\nthis,b&&b.words)},_doProcessBlock:function(a,b){this._mode.processBlock(a,b)},_doFinalize:function(){var a=this.cfg.padding;if(this._xformMode==this._ENC_XFORM_MODE){a.pad(this._data,this.blockSize);var b=this._process(!0)}else b=this._process(!0),a.unpad(b);return b},blockSize:4});var n=d.CipherParams=l.extend({init:function(a){this.mixIn(a)},toString:function(a){return(a||this.formatter).stringify(this)}}),b=(p.format={}).OpenSSL={stringify:function(a){var b=a.ciphertext;a=a.salt;return(a?s.create([1398893684,\n1701076831]).concat(a).concat(b):b).toString(r)},parse:function(a){a=r.parse(a);var b=a.words;if(1398893684==b[0]&&1701076831==b[1]){var c=s.create(b.slice(2,4));b.splice(0,4);a.sigBytes-=16}return n.create({ciphertext:a,salt:c})}},a=d.SerializableCipher=l.extend({cfg:l.extend({format:b}),encrypt:function(a,b,c,d){d=this.cfg.extend(d);var l=a.createEncryptor(c,d);b=l.finalize(b);l=l.cfg;return n.create({ciphertext:b,key:c,iv:l.iv,algorithm:a,mode:l.mode,padding:l.padding,blockSize:a.blockSize,formatter:d.format})},\ndecrypt:function(a,b,c,d){d=this.cfg.extend(d);b=this._parse(b,d.format);return a.createDecryptor(c,d).finalize(b.ciphertext)},_parse:function(a,b){return\"string\"==typeof a?b.parse(a,this):a}}),p=(p.kdf={}).OpenSSL={execute:function(a,b,c,d){d||(d=s.random(8));a=w.create({keySize:b+c}).compute(a,d);c=s.create(a.words.slice(b),4*c);a.sigBytes=4*b;return n.create({key:a,iv:c,salt:d})}},c=d.PasswordBasedCipher=a.extend({cfg:a.cfg.extend({kdf:p}),encrypt:function(b,c,d,l){l=this.cfg.extend(l);d=l.kdf.execute(d,\nb.keySize,b.ivSize);l.iv=d.iv;b=a.encrypt.call(this,b,c,d.key,l);b.mixIn(d);return b},decrypt:function(b,c,d,l){l=this.cfg.extend(l);c=this._parse(c,l.format);d=l.kdf.execute(d,b.keySize,b.ivSize,c.salt);l.iv=d.iv;return a.decrypt.call(this,b,c,d.key,l)}})}();\n\n// AES\n(function(){for(var u=CryptoJS,p=u.lib.BlockCipher,d=u.algo,l=[],s=[],t=[],r=[],w=[],v=[],b=[],x=[],q=[],n=[],a=[],c=0;256>c;c++)a[c]=128>c?c<<1:c<<1^283;for(var e=0,j=0,c=0;256>c;c++){var k=j^j<<1^j<<2^j<<3^j<<4,k=k>>>8^k&255^99;l[e]=k;s[k]=e;var z=a[e],F=a[z],G=a[F],y=257*a[k]^16843008*k;t[e]=y<<24|y>>>8;r[e]=y<<16|y>>>16;w[e]=y<<8|y>>>24;v[e]=y;y=16843009*G^65537*F^257*z^16843008*e;b[k]=y<<24|y>>>8;x[k]=y<<16|y>>>16;q[k]=y<<8|y>>>24;n[k]=y;e?(e=z^a[a[a[G^z]]],j^=a[a[j]]):e=j=1}var H=[0,1,2,4,8,\n16,32,64,128,27,54],d=d.AES=p.extend({_doReset:function(){for(var a=this._key,c=a.words,d=a.sigBytes/4,a=4*((this._nRounds=d+6)+1),e=this._keySchedule=[],j=0;j>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255]):(k=k<<8|k>>>24,k=l[k>>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255],k^=H[j/d|0]<<24);e[j]=e[j-d]^k}c=this._invKeySchedule=[];for(d=0;dd||4>=j?k:b[l[k>>>24]]^x[l[k>>>16&255]]^q[l[k>>>\n8&255]]^n[l[k&255]]},encryptBlock:function(a,b){this._doCryptBlock(a,b,this._keySchedule,t,r,w,v,l)},decryptBlock:function(a,c){var d=a[c+1];a[c+1]=a[c+3];a[c+3]=d;this._doCryptBlock(a,c,this._invKeySchedule,b,x,q,n,s);d=a[c+1];a[c+1]=a[c+3];a[c+3]=d},_doCryptBlock:function(a,b,c,d,e,j,l,f){for(var m=this._nRounds,g=a[b]^c[0],h=a[b+1]^c[1],k=a[b+2]^c[2],n=a[b+3]^c[3],p=4,r=1;r>>24]^e[h>>>16&255]^j[k>>>8&255]^l[n&255]^c[p++],s=d[h>>>24]^e[k>>>16&255]^j[n>>>8&255]^l[g&255]^c[p++],t=\nd[k>>>24]^e[n>>>16&255]^j[g>>>8&255]^l[h&255]^c[p++],n=d[n>>>24]^e[g>>>16&255]^j[h>>>8&255]^l[k&255]^c[p++],g=q,h=s,k=t;q=(f[g>>>24]<<24|f[h>>>16&255]<<16|f[k>>>8&255]<<8|f[n&255])^c[p++];s=(f[h>>>24]<<24|f[k>>>16&255]<<16|f[n>>>8&255]<<8|f[g&255])^c[p++];t=(f[k>>>24]<<24|f[n>>>16&255]<<16|f[g>>>8&255]<<8|f[h&255])^c[p++];n=(f[n>>>24]<<24|f[g>>>16&255]<<16|f[h>>>8&255]<<8|f[k&255])^c[p++];a[b]=q;a[b+1]=s;a[b+2]=t;a[b+3]=n},keySize:8});u.AES=p._createHelper(d)})();\n\n// Mode ECB\nCryptoJS.mode.ECB = (function () {\n var ECB = CryptoJS.lib.BlockCipherMode.extend();\n\n ECB.Encryptor = ECB.extend({\n processBlock: function (words, offset) {\n this._cipher.encryptBlock(words, offset);\n }\n });\n\n ECB.Decryptor = ECB.extend({\n processBlock: function (words, offset) {\n this._cipher.decryptBlock(words, offset);\n }\n });\n\n return ECB;\n}());// Moved to hmac-sha-256.js\n//# sourceMappingURL=ringcentral-bundle.js.map","module RingCentral.sdk.core.utils {\n\n var hasOwn = Object.prototype.hasOwnProperty,\n toString = Object.prototype.toString,\n rdigit = /\\d/,\n class2type = {};\n\n // Populate the class2type map\n 'Boolean Number String Function Array Date RegExp Object'.split(' ').forEach((name) => {\n class2type[\"[object \" + name + \"]\"] = name.toLowerCase();\n });\n\n /**\n * Ported from jQuery.fn.extend\n * Optional first parameter makes deep copy\n */\n export function extend(targetObject:any, sourceObject:any, ...args) {\n\n var options, name, src, copy, copyIsArray, clone,\n target = arguments[0] || {},\n i = 1,\n length = arguments.length,\n deep = false;\n\n // Handle a deep copy situation\n if (typeof target === \"boolean\") {\n deep = target;\n\n // skip the boolean and the target\n target = arguments[i] || {};\n i++;\n }\n\n // Handle case when target is a string or something (possible in deep copy)\n if (typeof target !== \"object\" && !isFunction(target)) {\n target = {};\n }\n\n for (; i < length; i++) {\n\n // Only deal with non-null/undefined values\n if ((options = arguments[i]) !== null) {\n\n // Extend the base object\n for (name in options) {\n\n src = target[name];\n copy = options[name];\n\n // Prevent never-ending loop\n if (target === copy) {\n continue;\n }\n\n // Recurse if we're merging plain objects or arrays\n if (deep && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) {\n\n if (copyIsArray) {\n copyIsArray = false;\n clone = src && isArray(src) ? src : [];\n } else {\n clone = src && isPlainObject(src) ? src : {};\n }\n\n // Never move original objects, clone them\n target[name] = extend(deep, clone, copy);\n\n // Don't bring in undefined values\n } else if (copy !== undefined) {\n\n target[name] = copy;\n\n }\n }\n }\n }\n\n // Return the modified object\n return target;\n\n }\n\n export function forEach(object, cb) {\n\n for (var i in object) {\n\n if (!object.hasOwnProperty(i)) continue;\n\n var res = cb(object[i], i);\n\n if (res === false) break;\n\n }\n\n }\n\n /**\n * TODO Replace with something better\n * @see https://github.com/joyent/node/blob/master/lib/querystring.js\n * @param {object} parameters\n * @returns {string}\n */\n export function queryStringify(parameters) {\n\n var array = [];\n\n forEach(parameters, (v, i) => {\n\n if (isArray(v)) {\n v.forEach((vv) => {\n array.push(encodeURIComponent(i) + '=' + encodeURIComponent(vv));\n });\n } else {\n array.push(encodeURIComponent(i) + '=' + encodeURIComponent(v));\n }\n\n });\n\n return array.join('&');\n\n }\n\n /**\n * TODO Replace with something better\n * @see https://github.com/joyent/node/blob/master/lib/querystring.js\n * @param {string} queryString\n * @returns {object}\n */\n export function parseQueryString(queryString:string):any {\n\n var argsParsed = {},\n self = this;\n\n queryString.split('&').forEach((arg) => {\n\n arg = decodeURIComponent(arg);\n\n if (arg.indexOf('=') == -1) {\n\n argsParsed[arg.trim()] = true;\n\n } else {\n\n var pair = arg.split('='),\n key = pair[0].trim(),\n value = pair[1].trim();\n\n if (key in argsParsed) {\n if (key in argsParsed && !self.isArray(argsParsed[key])) argsParsed[key] = [argsParsed[key]];\n argsParsed[key].push(value);\n } else {\n argsParsed[key] = value;\n }\n\n }\n\n });\n\n return argsParsed;\n\n }\n\n /**\n * Returns true if the passed value is valid email address.\n * Checks multiple comma separated emails according to RFC 2822 if parameter `multiple` is `true`\n */\n export function isEmail(v:string, multiple:boolean):boolean {\n if (!!multiple) {\n //this Regexp is also suitable for multiple emails (comma separated)\n return /^(?:[a-z0-9!#$%&'*+\\/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+\\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?[ ,;]*)+$/i.test(v);\n } else {\n return /^[a-z0-9!#$%&'*+\\/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+\\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i.test(v);\n }\n\n }\n\n export function isPhoneNumber(v:string):boolean {\n return (/\\+?1[0-9]{3}[0-9a-z]{7}/im.test(v.toString().split(/[^0-9a-z\\+]/im).join('')));\n }\n\n /**\n * @param args\n * @returns {Array}\n */\n export function argumentsToArray(args:any) {\n return Array.prototype.slice.call(args || [], 0);\n }\n\n export function isDate(obj:any):boolean {\n return type(obj) === \"date\";\n }\n\n export function isFunction(obj:any):boolean {\n return type(obj) === \"function\";\n }\n\n export function isArray(obj:any):boolean {\n return Array.isArray ? Array.isArray(obj) : type(obj) === \"array\";\n }\n\n // A crude way of determining if an object is a window\n export function isWindow(obj:any):boolean {\n return obj && typeof obj === \"object\" && \"setInterval\" in obj;\n }\n\n export function isNan(obj:any):boolean {\n return obj === null || !rdigit.test(obj) || isNaN(obj);\n }\n\n export function type(obj:any):string {\n return obj === null\n ? String(obj)\n : class2type[toString.call(obj)] || \"object\";\n }\n\n export function isPlainObject(obj:any):boolean {\n\n // Must be an Object.\n // Because of IE, we also have to check the presence of the constructor property.\n // Make sure that DOM nodes and window objects don't pass through, as well\n if (!obj || type(obj) !== \"object\" || obj.nodeType || isWindow(obj)) {\n return false;\n }\n\n // Not own constructor property must be Object\n if (obj.constructor && !hasOwn.call(obj, \"constructor\") && !hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\")) {\n return false;\n }\n\n // Own properties are enumerated firstly, so to speed up,\n // if last one is own, then all properties are own.\n\n var key;\n for (key in obj) {}\n\n return key === undefined || hasOwn.call(obj, key);\n\n }\n\n export function getProperty(obj:any, property:string):any {\n\n return property\n .split(/[.[\\]]/)\n .reduce((res, part) => {\n if (!res) return undefined;\n return part ? res[part] : res;\n }, obj);\n\n }\n\n export function poll(fn, interval?:number, timeout?:any):any { //NodeJS.Timer|number\n\n stopPolling(timeout);\n\n interval = interval || 1000;\n\n var next = (delay?:number):any => {\n\n delay = delay || interval;\n\n interval = delay;\n\n return setTimeout(() => {\n\n fn(next, delay);\n\n }, delay);\n\n };\n\n return next();\n\n }\n\n export function stopPolling(timeout) {\n if (timeout) clearTimeout(timeout);\n }\n\n export function parseString(s:any):string {\n return s ? s.toString() : '';\n }\n\n export function parseNumber(n:any):number {\n if (!n) return 0;\n n = parseFloat(n);\n return isNan(n) ? 0 : n;\n }\n\n export function isNodeJS():boolean {\n return (typeof process !== 'undefined');\n }\n\n export function isBrowser():boolean {\n return (typeof window !== 'undefined');\n }\n\n}","/// \n/// \n\nmodule RingCentral.sdk.core {\n\n /**\n * @see https://github.com/Microsoft/TypeScript/issues/275\n */\n export class Observable> {\n\n private _listeners:any;\n\n constructor() {\n if (!(this instanceof Observable)) throw new Error('Observable(): New operator was omitted');\n this.off();\n }\n\n hasListeners(event) {\n return (event in this._listeners);\n }\n\n on(events:any, callback:(...args)=>any):T {\n\n if (typeof events == 'string') events = [events];\n if (!events) throw new Error('No events to subscribe to');\n if (typeof callback !== 'function') throw new Error('Callback must be a function');\n\n events.forEach((event:string) => {\n\n if (!this.hasListeners(event)) this._listeners[event] = [];\n\n this._listeners[event].push(callback);\n\n });\n\n return this;\n\n }\n\n emit(event:string, ...args):any {\n\n var result = null;\n\n if (!this.hasListeners(event)) return null;\n\n this._listeners[event].some((callback:()=>any) => {\n\n result = callback.apply(this, args);\n return (result === false);\n\n });\n\n return result;\n\n }\n\n off(event?:string, callback?):T {\n\n if (!event) {\n\n this._listeners = {};\n\n } else {\n\n if (!callback) {\n\n delete this._listeners[event];\n\n } else {\n\n if (!this.hasListeners(event)) return this;\n\n this._listeners[event].forEach((cb, i) => {\n\n if (cb === callback) delete this._listeners[event][i];\n\n });\n\n }\n\n }\n\n return this;\n\n }\n\n destroy():T {\n this.off();\n log.debug('Observable.destroy(): Listeners were destroyed');\n return this;\n }\n\n }\n\n}\n\n\n","/// \n\nmodule RingCentral.sdk.core {\n\n export class PageVisibility extends Observable {\n\n public events = {\n change: 'change'\n };\n\n protected _visible:boolean;\n\n constructor() {\n\n super();\n\n var hidden = \"hidden\",\n onchange = (evt) => {\n\n evt = evt || window.event;\n\n var v = 'visible',\n h = 'hidden',\n evtMap = {\n focus: v, focusin: v, pageshow: v, blur: h, focusout: h, pagehide: h\n };\n\n this._visible = (evt.type in evtMap) ? evtMap[evt.type] == v : !document[hidden];\n\n this.emit(this.events.change, this._visible);\n\n };\n\n this._visible = true;\n\n if (typeof document == 'undefined' || typeof window == 'undefined') return;\n\n // Standards:\n\n if (hidden in document)\n document.addEventListener(\"visibilitychange\", onchange);\n else if ((hidden = \"mozHidden\") in document)\n document.addEventListener(\"mozvisibilitychange\", onchange);\n else if ((hidden = \"webkitHidden\") in document)\n document.addEventListener(\"webkitvisibilitychange\", onchange);\n else if ((hidden = \"msHidden\") in document)\n document.addEventListener(\"msvisibilitychange\", onchange);\n // IE 9 and lower:\n else if ('onfocusin' in document)\n (document).onfocusin = (document).onfocusout = onchange;\n // All others:\n else\n window.onpageshow = window.onpagehide = window.onfocus = window.onblur = onchange;\n\n }\n\n visible() {\n return this._visible;\n }\n\n }\n\n}","/// \n/// \n\nmodule RingCentral.sdk.mocks {\n\n export class Mock {\n\n protected _method:string;\n protected _path:string;\n protected _delay:number;\n protected _json:any;\n protected _status:number;\n protected _statusText:string;\n\n constructor(method:string, path:string, json?:any, status?:number, statusText?:string, delay?:number) {\n this._method = method.toUpperCase();\n this._path = path;\n this._json = json || {};\n this._delay = delay || 10;\n this._status = status || 200;\n this._statusText = statusText || 'OK';\n }\n\n path() {\n return this._path;\n }\n\n method() {\n return this._method;\n }\n\n test(request:Request) {\n\n return request.url.indexOf(this._path) > -1 &&\n request.method.toUpperCase() == this._method;\n\n }\n\n getResponse(request:Request):Response|Promise {\n\n return new externals._Promise((resolve, reject) => {\n\n setTimeout(() => {\n\n resolve(this.createResponse(this._json));\n\n }, this._delay);\n\n });\n\n }\n\n createResponse(json?:any, init?:ResponseInit|any) {\n\n init = init || {};\n\n init.status = init.status || this._status;\n init.statusText = init.statusText || this._statusText;\n\n var str = JSON.stringify(json),\n res = http.Client.createResponse(str, init);\n\n res.headers.set(http.ApiResponse.contentType, http.ApiResponse.jsonContentType);\n\n return res;\n\n }\n\n }\n\n}","/// \n\nmodule RingCentral.sdk.mocks {\n\n export class Registry {\n\n protected _mocks:Mock[];\n\n constructor() {\n this._mocks = [];\n }\n\n add(mock:Mock) {\n this._mocks.push(mock);\n return this;\n }\n\n clear() {\n this._mocks = [];\n return this;\n }\n\n find(request:Request):Mock {\n\n //console.log('Registry is looking for', request);\n\n var mock = this._mocks.shift();\n\n if (!mock) throw new Error('No mock in registry for request ' + request.method + ' ' + request.url);\n\n if (!mock.test(request)) throw new Error('Wrong request ' + request.method + ' ' + request.url +\n ' for expected mock ' + mock.method() + ' ' + mock.path());\n\n return mock;\n\n }\n\n apiCall(method:string, path:string, response:any, status?:number, statusText?:string) {\n\n this.add(new Mock(method, path, response, status, statusText));\n\n return this;\n\n }\n\n authentication() {\n\n this.apiCall('POST', '/restapi/oauth/token', {\n 'access_token': 'ACCESS_TOKEN',\n 'token_type': 'bearer',\n 'expires_in': 3600,\n 'refresh_token': 'REFRESH_TOKEN',\n 'refresh_token_expires_in': 60480,\n 'scope': 'SMS RCM Foo Boo',\n 'expireTime': new Date().getTime() + 3600000\n });\n\n return this;\n\n }\n\n logout() {\n\n this.apiCall('POST', '/restapi/oauth/revoke', {});\n\n return this;\n\n }\n\n presenceLoad(id) {\n\n this.apiCall('GET', '/restapi/v1.0/account/~/extension/' + id + '/presence', {\n \"uri\": \"https://platform.ringcentral.com/restapi/v1.0/account/123/extension/\" + id + \"/presence\",\n \"extension\": {\n \"uri\": \"https://platform.ringcentral.com/restapi/v1.0/account/123/extension/\" + id,\n \"id\": id,\n \"extensionNumber\": \"101\"\n },\n \"activeCalls\": [],\n \"presenceStatus\": \"Available\",\n \"telephonyStatus\": \"Ringing\",\n \"userStatus\": \"Available\",\n \"dndStatus\": \"TakeAllCalls\",\n \"extensionId\": id\n });\n\n return this;\n\n }\n\n subscribeGeneric(expiresIn?:number) {\n\n expiresIn = expiresIn || 15 * 60 * 60;\n\n var date = new Date();\n\n this.apiCall('POST', '/restapi/v1.0/subscription', {\n 'eventFilters': [\n '/restapi/v1.0/account/~/extension/~/presence'\n ],\n 'expirationTime': new Date(date.getTime() + (expiresIn * 1000)).toISOString(),\n 'expiresIn': expiresIn,\n 'deliveryMode': {\n 'transportType': 'PubNub',\n 'encryption': false,\n 'address': '123_foo',\n 'subscriberKey': 'sub-c-foo',\n 'secretKey': 'sec-c-bar'\n },\n 'id': 'foo-bar-baz',\n 'creationTime': date.toISOString(),\n 'status': 'Active',\n 'uri': 'https://platform.ringcentral.com/restapi/v1.0/subscription/foo-bar-baz'\n });\n\n return this;\n\n }\n\n subscribeOnPresence(id?:string, detailed?:boolean) {\n\n id = id || '1';\n\n var date = new Date();\n\n this.apiCall('POST', '/restapi/v1.0/subscription', {\n 'eventFilters': ['/restapi/v1.0/account/~/extension/' + id + '/presence' + (detailed ? '?detailedTelephonyState=true' : '')],\n 'expirationTime': new Date(date.getTime() + (15 * 60 * 60 * 1000)).toISOString(),\n 'deliveryMode': {\n 'transportType': 'PubNub',\n 'encryption': true,\n 'address': '123_foo',\n 'subscriberKey': 'sub-c-foo',\n 'secretKey': 'sec-c-bar',\n 'encryptionAlgorithm': 'AES',\n 'encryptionKey': 'VQwb6EVNcQPBhE/JgFZ2zw=='\n },\n 'creationTime': date.toISOString(),\n 'id': 'foo-bar-baz',\n 'status': 'Active',\n 'uri': 'https://platform.ringcentral.com/restapi/v1.0/subscription/foo-bar-baz'\n });\n\n return this;\n\n }\n\n tokenRefresh(failure?:boolean) {\n\n if (!failure) {\n\n this.apiCall('POST', '/restapi/oauth/token', {\n 'access_token': 'ACCESS_TOKEN_FROM_REFRESH',\n 'token_type': 'bearer',\n 'expires_in': 3600,\n 'refresh_token': 'REFRESH_TOKEN_FROM_REFRESH',\n 'refresh_token_expires_in': 60480,\n 'scope': 'SMS RCM Foo Boo'\n });\n\n } else {\n\n this.apiCall('POST', '/restapi/oauth/token', {\n 'message': 'Wrong token',\n 'error_description': 'Wrong token',\n 'description': 'Wrong token'\n }, 400);\n\n }\n\n return this;\n\n }\n\n }\n\n}","/// \n\nmodule RingCentral.sdk.externals {\n\n export var _Promise:typeof Promise;\n export var _fetch:Fetch;\n export var _Response:typeof Response;\n export var _Request:typeof Request;\n export var _Headers:typeof Headers;\n export var _PUBNUB:PUBNUB;\n\n export function get() {\n\n var root = Function('return this')();\n\n if (!_PUBNUB) _PUBNUB = root.PUBNUB;\n if (!_Promise) _Promise = root.Promise;\n if (!_fetch) _fetch = root.fetch;\n if (!_Headers) _Headers = root.Headers;\n if (!_Request) _Request = root.Request;\n if (!_Response) _Response = root.Response;\n\n return externals;\n\n }\n\n}\n\n","/// \n/// \n/// \n\nmodule RingCentral.sdk.http {\n\n /**\n * @TODO Bring back tests\n */\n export class ApiResponse {\n\n static contentType = 'Content-Type';\n static jsonContentType = 'application/json';\n static multipartContentType = 'multipart/mixed';\n static urlencodedContentType = 'application/x-www-form-urlencoded';\n static headerSeparator = ':';\n static bodySeparator = '\\n\\n';\n static boundarySeparator = '--';\n\n protected _json:any;\n protected _text:string;\n protected _request:Request;\n protected _response:Response;\n protected _multipartTransactions:ApiResponse[];\n\n constructor(request?:Request, response?:Response, responseText?:string) {\n\n this._text = responseText;\n this._request = request;\n this._response = response;\n this._json = null;\n this._multipartTransactions = null;\n\n }\n\n response() {\n return this._response;\n }\n\n request() {\n return this._request;\n }\n\n ok() {\n return this._response && this._response.ok;\n }\n\n text() {\n return this._text;\n }\n\n json() {\n\n if (!this._isJson()) throw new Error('Response is not JSON');\n\n if (!this._json) {\n this._json = this._text ? JSON.parse(this._text) : null;\n }\n\n return this._json;\n\n }\n\n error(skipOKCheck?:boolean) {\n\n if (this.ok() && !skipOKCheck) return null;\n\n var message = (this._response && this._response.status ? this._response.status + ' ' : '') +\n (this._response && this._response.statusText ? this._response.statusText : '');\n\n try {\n\n var json = this.json();\n\n if (json.message) message = json.message;\n if (json.error_description) message = json.error_description;\n if (json.description) message = json.description;\n\n } catch (ex) {}\n\n return message;\n\n }\n\n multipart():ApiResponse[] {\n\n if (!this._isMultipart()) throw new Error('Response is not multipart');\n\n if (null === this._multipartTransactions) {\n\n // Step 1. Split multipart response\n\n if (!this._text) throw new Error('No response body');\n\n var boundary = this._response.headers.get('Content-Type').match(/boundary=([^;]+)/i)[1];\n\n if (!boundary) throw new Error('Cannot find boundary');\n\n var parts = this._text.toString().split(ApiResponse.boundarySeparator + boundary);\n\n if (parts[0].trim() === '') parts.shift();\n if (parts[parts.length - 1].trim() == ApiResponse.boundarySeparator) parts.pop();\n\n if (parts.length < 1) throw new Error('No parts in body');\n\n // Step 2. Parse status info\n\n var statusInfo = ApiResponse.create(parts.shift(), this._response.status, this._response.statusText);\n\n // Step 3. Parse all other parts\n\n this._multipartTransactions = parts.map((part:string, i) => { //FIXME It will not work since parts contain both headers and body\n\n var status = statusInfo.json().response[i].status;\n\n return ApiResponse.create(part, status);\n\n });\n\n }\n\n return this._multipartTransactions;\n\n }\n\n /**\n * Short-hand method to get only JSON content of responses\n */\n multipartJson():any[] {\n\n return this.multipart().map((res)=> {\n return res.json();\n });\n\n }\n\n protected _isContentType(contentType:string):boolean {\n return this._getContentType().indexOf(contentType) > -1;\n }\n\n protected _getContentType():string {\n return this._response.headers.get(ApiResponse.contentType) || '';\n }\n\n protected _isMultipart():boolean {\n return this._isContentType(ApiResponse.multipartContentType);\n }\n\n protected _isUrlEncoded():boolean {\n return this._isContentType(ApiResponse.urlencodedContentType);\n }\n\n protected _isJson():boolean {\n return this._isContentType(ApiResponse.jsonContentType);\n }\n\n /**\n * Method is used to create Transaction objects from string parts of multipart/mixed response\n * @param text\n * @param status\n * @param statusText\n * @return {ApiResponse}\n */\n static create(text?:string, status?:number, statusText?:string):ApiResponse {\n\n status = status || 200;\n statusText = statusText || 'OK';\n\n text = text.replace(/\\r/g, '');\n\n var headers = new externals._Headers(),\n headersAndBody = text.split(ApiResponse.bodySeparator),\n headersText = (headersAndBody.length > 1) ? headersAndBody.shift() : '';\n\n text = headersAndBody.join(ApiResponse.bodySeparator);\n\n (headersText || '')\n .split('\\n')\n .forEach((header:string) => {\n\n var split = header.trim().split(ApiResponse.headerSeparator),\n key = split.shift().trim(),\n value = split.join(ApiResponse.headerSeparator).trim();\n\n if (key) headers.append(key, value);\n\n });\n\n return new ApiResponse(null, Client.createResponse(text, {\n headers: headers,\n status: status,\n statusText: statusText\n }), text);\n\n }\n\n }\n\n}","/// \n/// \n/// \n/// \n/// \n/// \n\nmodule RingCentral.sdk.http {\n\n var allowedMethods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS', 'HEAD'];\n\n export class Client extends core.Observable {\n\n public events = {\n beforeRequest: 'beforeRequest', // parameters: ajax\n requestSuccess: 'requestSuccess', // means that response was successfully fetched from server\n requestError: 'requestError' // means that request failed completely\n };\n\n sendRequest(request:Request):Promise {\n\n var res = new ApiResponse(request); //FIXME Potential leak\n\n return new externals._Promise((resolve) => {\n\n //TODO Stop request if listeners return false\n this.emit(this.events.beforeRequest, res);\n\n resolve(this._loadResponse(request));\n\n })\n .then((response:Response) => {\n\n res['_response'] = Client.cloneResponse(response);\n\n return response.text();\n\n })\n .then((text:string) => {\n\n res['_text'] = text;\n\n if (!res.ok()) throw Client.makeError(new Error('Response has unsuccessful status'), res);\n\n this.emit(this.events.requestSuccess, res);\n\n return res;\n\n })\n .catch((e:IApiError):any=> {\n\n if (!e.apiResponse) {\n // we don't pass response since most likely it's parsing caused an error\n e = Client.makeError(e, res);\n }\n\n this.emit(this.events.requestError, e);\n\n throw e;\n\n });\n\n }\n\n protected _loadResponse(request:Request):Promise {\n return externals._fetch.call(null, request);\n }\n\n /**\n * Wraps the JS Error object with transaction information\n * @param {Error} e\n * @param {ApiResponse} apiResponse\n * @return {IApiError}\n */\n static makeError(e:Error, apiResponse?:ApiResponse) {\n\n var error = e;\n\n // Wrap only if regular error\n if (!error.hasOwnProperty('apiResponse') && !error.hasOwnProperty('originalMessage')) {\n\n error.apiResponse = apiResponse;\n error.originalMessage = error.message;\n error.message = (apiResponse && apiResponse.error(true)) || error.originalMessage;\n\n }\n\n return error;\n\n }\n\n /**\n * TODO Wait for\n * - https://github.com/github/fetch/issues/185\n * - https://github.com/bitinn/node-fetch/issues/34\n * @param {Response} response\n * @return {Response}\n */\n static cloneResponse(response:Response):Response {\n\n if (core.utils.isFunction(response.clone)) return response.clone();\n\n var body = '';\n\n if (response.hasOwnProperty('_bodyInit')) body = response['_bodyInit'];\n if (response.hasOwnProperty('_bodyText')) body = response['_bodyText'];\n if (response.hasOwnProperty('_bodyBlob')) body = response['_bodyBlob'].slice();\n if (response.hasOwnProperty('_bodyFormData')) body = response['_bodyFormData'];\n\n if (response.hasOwnProperty('_raw')) body = response['_raw'].join('');\n\n var clone = new externals._Response(body, response);\n\n if (response.hasOwnProperty('body')) clone['body'] = response['body']; // accessing non-standard properties\n\n return clone;\n\n }\n\n /**\n * Creates a response\n * @param stringBody\n * @param init\n * @return {Response}\n */\n static createResponse(stringBody?:string, init?:ResponseInit):Response {\n\n init = init || {};\n\n return new externals._Response(stringBody, init);\n\n }\n\n static createRequest(input:string|Request, init?:IClientRequestInit) {\n\n init = init || {};\n\n var body = init.body;\n\n // Assign request with empty body, Github's fetch throws errors if it cannot recognize the body type\n var req = new externals._Request(input, core.utils.extend({}, init, {body: null}));\n\n if (!req.url) throw new Error('Url is not defined');\n if (!req.method) req.method = 'GET';\n if (req.method && allowedMethods.indexOf(req.method) < 0) throw new Error('Method has wrong value: ' + req.method);\n\n if (!req.headers.has('Accept')) req.headers.set('Accept', 'application/json');\n\n // Serialize body\n if (core.utils.isPlainObject(init.body) || !init.body) {\n\n if (!req.headers.has('Content-Type')) req.headers.set('Content-Type', 'application/json');\n\n var contentType = req.headers.get('Content-Type');\n\n if (contentType.indexOf('application/json') > -1) {\n\n body = JSON.stringify(init.body);\n\n } else if (contentType.indexOf('application/x-www-form-urlencoded') > -1) {\n\n body = core.utils.queryStringify(init.body);\n\n }\n\n }\n\n req.credentials = 'include';\n req.mode = 'cors';\n\n if (init.query) {\n req.url = req.url + (req.url.indexOf('?') > -1 ? '&' : '?') + core.utils.queryStringify(init.query);\n }\n\n // Create another request with encoded body\n req = new externals._Request(req.url, core.utils.extend(req, {body: body}));\n\n // Keep the original body accessible directly (for mocks)\n req.body = init.body;\n\n return req;\n\n }\n\n }\n\n export interface IApiError extends Error {\n stack?:string;\n originalMessage:string;\n apiResponse:ApiResponse;\n }\n\n export interface IClientRequestInit extends RequestInit {\n query?: string;\n }\n\n}","/// \n/// \n/// \n/// \n\nmodule RingCentral.sdk.platform {\n\n export class Queue {\n\n protected _cacheId:string;\n protected _pollInterval:number;\n protected _releaseTimeout:number;\n\n protected _cache:core.Cache;\n protected _promise:Promise;\n\n constructor(cache:core.Cache, cacheId:string) {\n\n this._cache = cache;\n this._cacheId = cacheId;\n\n this.setPollInterval(250);\n this.setReleaseTimeout(5000); // If queue was not released then force it to do so after some timeout\n\n }\n\n isPaused() {\n\n var storage = this._cache,\n cacheId = this._cacheId,\n time = storage.getItem(cacheId);\n\n return !!time && Date.now() - parseInt(time) < this._releaseTimeout;\n }\n\n pause() {\n this._cache.setItem(this._cacheId, Date.now());\n return this;\n }\n\n resume() {\n this._cache.removeItem(this._cacheId);\n return this;\n }\n\n poll() {\n\n if (this._promise) return this._promise;\n\n this._promise = new externals._Promise((resolve, reject) => {\n\n core.utils.poll((next) => {\n\n if (this.isPaused()) return next();\n\n this._promise = null;\n\n this.resume(); // this is actually not needed but why not\n\n resolve(null);\n\n }, this._pollInterval);\n\n });\n\n return this._promise;\n\n }\n\n releaseTimeout() {\n return this._releaseTimeout;\n }\n\n pollInterval() {\n return this._pollInterval;\n }\n\n setReleaseTimeout(releaseTimeout:number) {\n this._releaseTimeout = releaseTimeout;\n return this;\n }\n\n setPollInterval(pollInterval:number) {\n this._pollInterval = pollInterval;\n return this;\n }\n\n }\n\n}","/// \n/// \n/// \n/// \n/// \n/// \n/// \n/// \n/// \n\nmodule RingCentral.sdk.platform {\n\n export class Platform extends core.Observable {\n\n protected static _urlPrefix:string = '/restapi';\n protected static _apiVersion:string = 'v1.0';\n protected static _accessTokenTtl:number = null; // Platform server by default sets it to 60 * 60 = 1 hour\n protected static _refreshTokenTtl:number = 10 * 60 * 60; // 10 hours\n protected static _refreshTokenTtlRemember:number = 7 * 24 * 60 * 60; // 1 week\n protected static _tokenEndpoint:string = '/restapi/oauth/token';\n protected static _revokeEndpoint:string = '/restapi/oauth/revoke';\n protected static _authorizeEndpoint:string = '/restapi/oauth/authorize';\n\n protected _server:string;\n protected _appKey:string;\n protected _appSecret:string;\n\n protected _refreshDelayMs:number = 100;\n protected _clearCacheOnRefreshError:boolean = true;\n protected _cacheId:string = 'platform';\n\n protected _queue:Queue;\n protected _cache:core.Cache;\n protected _client:http.Client;\n protected _auth:Auth;\n\n public events = {\n accessViolation: 'accessViolation',\n logoutSuccess: 'logoutSuccess',\n logoutError: 'logoutError',\n authorizeSuccess: 'authorizeSuccess',\n authorizeError: 'authorizeError',\n refreshSuccess: 'refreshSuccess',\n refreshError: 'refreshError'\n };\n\n constructor(client:http.Client,\n cache:core.Cache,\n queue:Queue,\n server:string,\n appKey:string,\n appSecret:string) {\n\n super();\n\n this._server = server;\n this._appKey = appKey;\n this._appSecret = appSecret;\n\n this._cache = cache;\n this._client = client;\n this._queue = new Queue(this._cache, this._cacheId + '-refresh');\n this._auth = new Auth(this._cache, this._cacheId);\n\n }\n\n auth():Auth {\n return this._auth;\n }\n\n createUrl(path, options?:{addMethod?: string; addToken?: boolean; addServer?: boolean}):string {\n\n path = path || '';\n options = options || {};\n\n var builtUrl = '',\n hasHttp = path.indexOf('http://') != -1 || path.indexOf('https://') != -1;\n\n if (options.addServer && !hasHttp) builtUrl += this._server;\n\n if (path.indexOf(Platform._urlPrefix) == -1 && !hasHttp) builtUrl += Platform._urlPrefix + '/' + Platform._apiVersion;\n\n builtUrl += path;\n\n if (options.addMethod || options.addToken) builtUrl += (path.indexOf('?') > -1 ? '&' : '?');\n\n if (options.addMethod) builtUrl += '_method=' + options.addMethod;\n if (options.addToken) builtUrl += (options.addMethod ? '&' : '') + 'access_token=' + this._auth.accessToken();\n\n return builtUrl;\n\n }\n\n authUrl(options:{\n redirectUri:string;\n display?:string; // page|popup|touch|mobile, default 'page'\n prompt?:string; // sso|login|consent, default is 'login sso consent'\n state?:string;\n brandId?:string|number;\n }) {\n\n options = options || {};\n\n return this.createUrl(Platform._authorizeEndpoint + '?' + core.utils.queryStringify({\n 'response_type': 'code',\n 'redirect_uri': options.redirectUri || '',\n 'client_id': this._appKey,\n 'state': options.state || '',\n 'brand_id': options.brandId || '',\n 'display': options.display || '',\n 'prompt': options.prompt || ''\n }), {addServer: true})\n\n }\n\n parseAuthRedirectUrl(url:string) {\n\n var qs = core.utils.parseQueryString(url.split('?').reverse()[0]),\n error = qs.error_description || qs.error;\n\n if (error) {\n var e = new Error(error);\n e.error = qs.error;\n throw e;\n }\n\n return qs;\n\n }\n\n loggedIn():Promise {\n\n return this._ensureAuthentication()\n .then(()=> {\n return true;\n })\n .catch(()=> {\n return false;\n });\n\n }\n\n login(options?:{\n username?:string;\n password?: string;\n extension?:string;\n endpointId?:string;\n code?:string;\n redirectUri?:string;\n clientId?:string;\n remember?:boolean\n }):Promise {\n\n options = options || {};\n\n options.remember = options.remember || false;\n\n var body = {\n \"access_token_ttl\": Platform._accessTokenTtl,\n \"refresh_token_ttl\": options.remember ? Platform._refreshTokenTtlRemember : Platform._refreshTokenTtl\n };\n\n if (!options.code) {\n\n body.grant_type = 'password';\n body.username = options.username;\n body.password = options.password;\n body.extension = options.extension || '';\n\n } else if (options.code) {\n\n body.grant_type = 'authorization_code';\n body.code = options.code;\n body.redirect_uri = options.redirectUri;\n //body.client_id = this.getCredentials().key; // not needed\n\n }\n\n if (options.endpointId) body.endpoint_id = options.endpointId;\n\n return this._tokenRequest(Platform._tokenEndpoint, body).then((res:http.ApiResponse) => {\n\n this._auth\n .setData(res.json())\n .setRemember(options.remember);\n\n this.emit(this.events.authorizeSuccess, res);\n\n return res;\n\n }).catch((e:http.IApiError):any => {\n\n this._cache.clean();\n\n this.emit(this.events.authorizeError, e);\n\n throw e;\n\n });\n\n }\n\n refresh():Promise {\n\n var refresh = >new externals._Promise((resolve, reject) => {\n\n if (this._queue.isPaused()) {\n return resolve(this._refreshPolling());\n }\n\n this._queue.pause();\n\n // Make sure all existing AJAX calls had a chance to reach the server\n setTimeout(() => {\n\n core.log.debug('Platform.refresh(): Performing token refresh (access token', this._auth.accessToken(), ', refresh token', this._auth.refreshToken(), ')');\n\n // Perform sanity checks\n if (!this._auth.refreshToken()) return reject(new Error('Refresh token is missing'));\n if (!this._auth.refreshTokenValid()) return reject(new Error('Refresh token has expired'));\n if (!this._queue.isPaused()) return reject(new Error('Queue was resumed before refresh call'));\n\n resolve(this._tokenRequest(Platform._tokenEndpoint, {\n \"grant_type\": \"refresh_token\",\n \"refresh_token\": this._auth.refreshToken(),\n \"access_token_ttl\": Platform._accessTokenTtl,\n \"refresh_token_ttl\": this._auth.remember() ? Platform._refreshTokenTtlRemember : Platform._refreshTokenTtl\n }));\n\n }, this._refreshDelayMs);\n\n });\n\n return refresh.then((res:http.ApiResponse) => {\n\n // This means refresh has happened elsewhere and we are here because of timeout\n if (res && res.json && res.json()) {\n\n var json = res.json();\n\n core.log.info('Platform.refresh(): Token was refreshed', res);\n\n if (!json.refresh_token || !json.access_token) {\n throw http.Client.makeError(new Error('Malformed OAuth response'), res);\n }\n\n this._auth.setData(json);\n this._queue.resume();\n\n }\n\n this.emit(this.events.refreshSuccess, res);\n\n return res;\n\n }).catch((e:http.IApiError):any => {\n\n e = http.Client.makeError(e);\n\n if (this._clearCacheOnRefreshError) {\n this._cache.clean();\n }\n\n this.emit(this.events.accessViolation, e);\n this.emit(this.events.refreshError, e);\n\n throw e;\n\n });\n\n }\n\n /**\n * @returns {Promise}\n */\n logout():Promise {\n\n this._queue.pause();\n\n return this._tokenRequest(Platform._revokeEndpoint, {\n token: this._auth.accessToken()\n }).then((res) => {\n\n this._queue.resume();\n this._cache.clean();\n\n this.emit(this.events.logoutSuccess, res);\n\n return res;\n\n }).catch((e:http.IApiError):any => {\n\n this._queue.resume();\n\n this.emit(this.events.accessViolation, e);\n this.emit(this.events.logoutError, e);\n\n throw e;\n\n });\n\n }\n\n inflateRequest(request:Request, options?:IPlatformOptions):Promise {\n\n options = options || {};\n\n if (options.skipAuthCheck) return externals._Promise.resolve(request);\n\n return this\n ._ensureAuthentication()\n .then(() => {\n\n request.headers.set('Authorization', this._authHeader());\n request.url = this.createUrl(request.url, {addServer: true});\n\n return request;\n\n });\n\n }\n\n sendRequest(request:Request, options?:IPlatformOptions):Promise {\n\n return this\n .inflateRequest(request, options)\n .then((req) => {\n return this._client.sendRequest(req);\n })\n .catch((e:http.IApiError) => {\n\n // Guard is for errors that come from polling\n if (!e.apiResponse || !e.apiResponse.response() || (e.apiResponse.response().status != 401)) throw e;\n\n this._auth.cancelAccessToken();\n\n return this.sendRequest(request, options);\n\n });\n\n }\n\n /**\n * General purpose function to send anything to server\n */\n send(url:string, options?:IPlatformCombinedOptions):Promise {\n\n try {\n\n // This has to be done here in order to let NodeJS Fetch to create Request\n url = this.createUrl(url, {addServer: true});\n\n return this.sendRequest(http.Client.createRequest(url, options), options);\n\n } catch (e) {\n return externals._Promise.reject(e);\n }\n\n }\n\n get(url:string, options?:IPlatformCombinedOptions) {\n options = options || {};\n options.method = 'GET';\n return this.send(url, options);\n }\n\n post(url:string, options:IPlatformCombinedOptions) {\n options = options || {};\n options.method = 'POST';\n return this.send(url, options);\n }\n\n put(url:string, options:IPlatformCombinedOptions) {\n options = options || {};\n options.method = 'PUT';\n return this.send(url, options);\n }\n\n 'delete'(url:string, options?:IPlatformCombinedOptions) {\n options = options || {};\n options.method = 'DELETE';\n return this.send(url, options);\n }\n\n protected _tokenRequest(path:string, body:any):Promise {\n\n return this.send(path, {\n skipAuthCheck: true,\n body: body,\n method: 'POST',\n headers: {\n 'Authorization': 'Basic ' + this._apiKey(),\n 'Content-Type': 'application/x-www-form-urlencoded',\n }\n });\n\n }\n\n protected _ensureAuthentication() {\n\n if (this._isAccessTokenValid()) return externals._Promise.resolve(null);\n return this.refresh();\n\n }\n\n protected _isAccessTokenValid():boolean {\n\n return (this._auth.accessTokenValid() && !this._queue.isPaused());\n\n }\n\n protected _refreshPolling():Promise {\n\n core.log.warn('Platform.refresh(): Refresh is already in progress, polling started');\n\n return this._queue.poll().then(()=> {\n\n if (!this._isAccessTokenValid()) {\n throw new Error('Automatic authentification timeout');\n }\n\n return null;\n\n });\n\n }\n\n protected _apiKey() {\n var apiKey = this._appKey + ':' + this._appSecret;\n return (typeof btoa == 'function') ? btoa(apiKey) : new Buffer(apiKey).toString('base64');\n }\n\n protected _authHeader() {\n var token = this._auth.accessToken();\n return this._auth.tokenType() + (token ? ' ' + token : '');\n }\n\n }\n\n export interface IAuthError extends Error {\n error?:string;\n }\n\n export interface IPlatformOptions {\n skipAuthCheck?:boolean;\n }\n\n export interface IPlatformCombinedOptions extends IPlatformOptions, http.IClientRequestInit {}\n\n}","/// \n/// \n/// \n/// \n/// \n/// \n\nmodule RingCentral.sdk.subscription {\n\n\n export class Subscription extends core.Observable {\n\n protected _renewHandicapMs = 2 * 60 * 1000;\n\n protected _subscription:ISubscription|any;\n protected _timeout;\n protected _eventFilters:string[];\n protected _pubnub:PUBNUBInstance;\n\n protected _platform:platform.Platform;\n protected _pubnubFactory:pubnub.PubnubFactory;\n\n public events = {\n notification: 'notification',\n removeSuccess: 'removeSuccess',\n removeError: 'removeError',\n renewSuccess: 'renewSuccess',\n renewError: 'renewError',\n subscribeSuccess: 'subscribeSuccess',\n subscribeError: 'subscribeError'\n };\n\n constructor(pubnubFactory:pubnub.PubnubFactory, platform:platform.Platform) {\n\n super();\n\n this._pubnubFactory = pubnubFactory;\n this._platform = platform;\n\n this._pubnub = null;\n this._eventFilters = [];\n this._timeout = null;\n this._subscription = null;\n\n }\n\n alive() {\n\n return this._subscription &&\n this._subscription.id &&\n this._subscription.deliveryMode &&\n this._subscription.deliveryMode.subscriberKey &&\n this._subscription.deliveryMode.address;\n\n }\n\n setSubscription(subscription) {\n\n this._clearTimeout();\n\n this._subscription = subscription;\n\n if (!this._pubnub) this._subscribeAtPubnub();\n\n this._setTimeout();\n\n return this;\n\n }\n\n subscription():ISubscription {\n return this._subscription;\n }\n\n /**\n * Creates or updates subscription if there is an active one\n * @param {{events?:string[]}} [options] New array of events\n * @returns {Promise}\n */\n register(options?:{events?:string[]}):Promise {\n\n if (this.alive()) {\n return this.renew(options);\n } else {\n return this.subscribe(options);\n }\n\n }\n\n addEvents(events:string[]) {\n this._eventFilters = this._eventFilters.concat(events);\n return this;\n }\n\n setEvents(events:string[]) {\n this._eventFilters = events;\n return this;\n }\n\n subscribe(options?:{events?:string[]}):Promise {\n\n options = options || {};\n\n if (options.events) this.setEvents(options.events);\n\n this._clearTimeout();\n\n return >new externals._Promise((resolve, reject) => {\n\n if (!this._eventFilters || !this._eventFilters.length) throw new Error('Events are undefined');\n\n resolve(this._platform.post('/restapi/v1.0/subscription', {\n body: {\n eventFilters: this._getFullEventFilters(),\n deliveryMode: {\n transportType: 'PubNub'\n }\n }\n }));\n\n }).then((ajax:http.ApiResponse) => {\n\n this.setSubscription(ajax.json())\n .emit(this.events.subscribeSuccess, ajax);\n\n return ajax;\n\n }).catch((e):any => {\n\n e = http.Client.makeError(e);\n\n this.reset()\n .emit(this.events.subscribeError, e);\n\n throw e;\n\n });\n\n }\n\n renew(options?:{events?:string[]}):Promise {\n\n options = options || {};\n\n if (options.events) this.setEvents(options.events);\n\n this._clearTimeout();\n\n return >new externals._Promise((resolve, reject) => {\n\n if (!this.alive()) throw new Error('Subscription is not alive');\n\n if (!this._eventFilters || !this._eventFilters.length) throw new Error('Events are undefined');\n\n return this._platform.put('/restapi/v1.0/subscription/' + this._subscription.id, {\n body: {\n eventFilters: this._getFullEventFilters()\n }\n });\n\n })\n .then((ajax:http.ApiResponse) => {\n\n this.setSubscription(ajax.json())\n .emit(this.events.renewSuccess, ajax.json());\n\n return ajax;\n\n })\n .catch((e):any => {\n\n e = http.Client.makeError(e);\n\n this.reset()\n .emit(this.events.renewError, e);\n\n throw e;\n\n });\n\n }\n\n remove():Promise {\n\n return >new externals._Promise((resolve, reject) => {\n\n if (!this._subscription || !this._subscription.id) throw new Error('Subscription ID is required');\n\n resolve(this._platform.delete('/restapi/v1.0/subscription/' + this._subscription.id));\n\n }).then((ajax:http.ApiResponse) => {\n\n this.reset()\n .emit(this.events.removeSuccess, ajax);\n\n return ajax;\n\n }).catch((e):any => {\n\n e = http.Client.makeError(e);\n\n this.emit(this.events.removeError, e);\n\n throw e;\n\n });\n\n }\n\n /**\n * Remove subscription and disconnect from PUBNUB\n * This method resets subscription at client side but backend is not notified\n */\n reset() {\n this._clearTimeout();\n if (this.alive() && this._pubnub) this._pubnub.unsubscribe({channel: this._subscription.deliveryMode.address});\n this._subscription = null;\n return this;\n }\n\n destroy():Subscription {\n\n this.reset();\n\n core.log.info('RC.subscription.Subscription: Destroyed');\n\n return super.destroy();\n\n }\n\n protected _getFullEventFilters() {\n\n return this._eventFilters.map((event) => {\n return this._platform.createUrl(event);\n });\n\n }\n\n protected _setTimeout() {\n\n this._clearTimeout();\n\n if (!this.alive()) throw new Error('Subscription is not alive');\n\n var timeToExpiration = (this._subscription.expiresIn * 1000) - this._renewHandicapMs;\n\n this._timeout = setTimeout(() => {\n\n this.renew({});\n\n }, timeToExpiration);\n\n return this;\n\n }\n\n protected _clearTimeout() {\n\n clearTimeout(this._timeout);\n\n return this;\n\n }\n\n protected _decrypt(message:any) {\n\n if (!this.alive()) throw new Error('Subscription is not alive');\n\n if (this._subscription.deliveryMode.encryptionKey) {\n\n var PUBNUB = this._pubnubFactory.getPubnub();\n\n message = PUBNUB.crypto_obj.decrypt(message, this._subscription.deliveryMode.encryptionKey, {\n encryptKey: false,\n keyEncoding: 'base64',\n keyLength: 128,\n mode: 'ecb'\n });\n\n }\n\n return message;\n\n }\n\n protected _notify(message:any) {\n\n this.emit(this.events.notification, this._decrypt(message));\n\n return this;\n\n }\n\n protected _subscribeAtPubnub():Subscription {\n\n if (!this.alive()) throw new Error('Subscription is not alive');\n\n var PUBNUB = this._pubnubFactory.getPubnub();\n\n this._pubnub = PUBNUB.init({\n ssl: true,\n subscribe_key: this._subscription.deliveryMode.subscriberKey\n });\n\n this._pubnub.ready();\n\n this._pubnub.subscribe({\n channel: this._subscription.deliveryMode.address,\n message: (message, env, channel) => {\n\n core.log.info('RC.core.Subscription: Incoming message', message);\n this._notify(message);\n\n },\n connect: () => {\n core.log.info('RC.core.Subscription: PUBNUB connected');\n }\n });\n\n return this;\n\n }\n\n }\n\n export interface ISubscription {\n id?:string;\n uri?: string;\n eventFilters?:string[];\n expirationTime?:string; // 2014-03-12T19:54:35.613Z\n expiresIn?:number;\n deliveryMode?: {\n transportType?:string;\n encryption?:boolean;\n address?:string;\n subscriberKey?:string;\n encryptionKey?:string;\n secretKey?:string;\n };\n creationTime?:string; // 2014-03-12T19:54:35.613Z\n status?:string; // Active\n }\n\n}","/// \n/// \n/// \n\nmodule RingCentral.sdk.pubnub {\n\n export class PubnubMock extends core.Observable implements PUBNUBInstance {\n\n private options:PUBNUBInitOptions;\n crypto_obj:PUBNUBCryptoObj;\n\n constructor(options:PUBNUBInitOptions) {\n super();\n this.options = options;\n this.crypto_obj = externals._PUBNUB.crypto_obj;\n }\n\n ready() {}\n\n subscribe(options:PUBNUBSubscribeOptions) {\n this.on('message-' + options.channel, options.message);\n }\n\n unsubscribe(options:PUBNUBUnsubscribeOptions) {\n this.off('message-' + options.channel);\n }\n\n receiveMessage(msg, channel) {\n this.emit('message-' + channel, msg, 'env', channel);\n }\n\n }\n\n export class PubnubMockFactory implements PUBNUB {\n\n crypto_obj:PUBNUBCryptoObj;\n\n constructor() {\n this.crypto_obj = externals._PUBNUB.crypto_obj;\n }\n\n init(options:PUBNUBInitOptions) {\n return new PubnubMock(options);\n }\n\n }\n\n}","/// \n/// \n\nmodule RingCentral.sdk.pubnub {\n\n export class PubnubFactory {\n\n private _useMock:boolean = false;\n private _mock:PubnubMockFactory;\n\n constructor(flag:boolean) {\n this._useMock = !!flag;\n this._mock = new PubnubMockFactory();\n }\n\n getPubnub():PUBNUB {\n return this._useMock ? this._mock : externals._PUBNUB;\n }\n\n }\n\n}","/// \n/// \n/// \n/// \n/// \n/// \n/// \n/// \n/// \n/// \n/// \n/// \n\nmodule RingCentral.sdk {\n\n export class SDK {\n\n static version = '2.0.0';\n\n static server = {\n sandbox: 'https://platform.devtest.ringcentral.com',\n production: 'https://platform.ringcentral.com'\n };\n\n private _platform:platform.Platform;\n private _cache:core.Cache;\n private _queue:platform.Queue;\n private _client:http.Client;\n private _pubnubFactory:pubnub.PubnubFactory;\n private _mockRegistry:mocks.Registry;\n\n constructor(options?:{\n server:string;\n appKey:string;\n appSecret:string;\n appName?:string;\n appVersion?:string;\n cachePrefix?:string;\n useHttpMock?:boolean;\n usePubnubMock?:boolean;\n }) {\n\n options = options || {};\n\n externals.get();\n\n this._mockRegistry = new mocks.Registry();\n\n this._cache = new core.Cache(typeof localStorage !== 'undefined' ? localStorage : {}, options.cachePrefix);\n\n this._queue = new platform.Queue(this._cache, 'platform-refresh');\n\n this._client = options.useHttpMock ? new http.ClientMock(this._mockRegistry) : new http.Client();\n\n this._platform = new platform.Platform(this._client, this._cache, this._queue, options.server, options.appKey, options.appSecret);\n\n this._pubnubFactory = new pubnub.PubnubFactory(options.usePubnubMock);\n\n //TODO Link Platform events with Subscriptions and the rest\n\n }\n\n platform():platform.Platform {\n return this._platform;\n }\n\n cache():core.Cache {\n return this._cache;\n }\n\n createSubscription():subscription.Subscription {\n return new subscription.Subscription(this._pubnubFactory, this._platform);\n }\n\n createPageVisibility() {\n return new core.PageVisibility();\n }\n\n createObservable() {\n return new core.Observable();\n }\n\n log() {\n return core.log;\n }\n\n utils() {\n return core.utils;\n }\n\n mockRegistry() { return this._mockRegistry; }\n\n }\n\n}\n\nvar e = RingCentral.sdk.externals.get();\n\nif (typeof define === 'function' && define.amd) {\n\n define(['pubnub'], function(PUBNUB) {\n e._PUBNUB = PUBNUB;\n return RingCentral.sdk;\n });\n\n} else if (typeof module === 'object' && module.exports) {\n\n e._PUBNUB = require('pubnub');\n e._Promise = typeof (Promise) !== 'undefined' ? Promise : require('es6-promise').Promise;\n e._fetch = require('node-fetch');\n e._Request = e._fetch['Request'];\n e._Response = e._fetch['Response'];\n e._Headers = e._fetch['Headers'];\n\n module.exports = RingCentral.sdk;\n\n} else {\n\n //TODO noConflict\n\n}\n","/// \n/// \n/// \n/// \n/// \n/// \n\nmodule RingCentral.sdk.http {\n\n export class ClientMock extends Client {\n\n private _registry:mocks.Registry;\n\n constructor(registry:mocks.Registry) {\n super();\n this._registry = registry;\n }\n\n protected _loadResponse(request:Request):Promise {\n\n return new externals._Promise((resolve) => {\n\n core.log.debug('API REQUEST', request.method, request.url);\n\n var mock = this._registry.find(request);\n\n resolve(mock.getResponse(request));\n\n });\n\n }\n\n }\n\n}","///