azure-devops-extension-sdk
Advanced tools
Comparing version 1.141.3 to 1.141.4
@@ -1,1 +0,698 @@ | ||
if(typeof Object.assign!="function"){Object.assign=function(target,varArgs){"use strict";if(target==null){throw new TypeError("Cannot convert undefined or null to object")}var to=Object(target);for(var index=1;index<arguments.length;index++){var nextSource=arguments[index];if(nextSource!=null){for(var nextKey in nextSource){if(Object.prototype.hasOwnProperty.call(nextSource,nextKey)){to[nextKey]=nextSource[nextKey]}}}}return to}}(function(global,factory){typeof exports==="object"&&typeof module!=="undefined"?module.exports=factory():global.ES6Promise=factory()})(this,function(){"use strict";function objectOrFunction(x){return typeof x==="function"||typeof x==="object"&&x!==null}function isFunction(x){return typeof x==="function"}var _isArray=undefined;if(!Array.isArray){_isArray=function(x){return Object.prototype.toString.call(x)==="[object Array]"}}else{_isArray=Array.isArray}var isArray=_isArray;var len=0;var vertxNext=undefined;var customSchedulerFn=undefined;var asap=function asap(callback,arg){queue[len]=callback;queue[len+1]=arg;len+=2;if(len===2){if(customSchedulerFn){customSchedulerFn(flush)}else{scheduleFlush()}}};function setScheduler(scheduleFn){customSchedulerFn=scheduleFn}function setAsap(asapFn){asap=asapFn}var browserWindow=typeof window!=="undefined"?window:undefined;var browserGlobal=browserWindow||{};var BrowserMutationObserver=browserGlobal.MutationObserver||browserGlobal.WebKitMutationObserver;var isNode=typeof self==="undefined"&&typeof process!=="undefined"&&{}.toString.call(process)==="[object process]";var isWorker=typeof Uint8ClampedArray!=="undefined"&&typeof importScripts!=="undefined"&&typeof MessageChannel!=="undefined";function useNextTick(){return function(){return process.nextTick(flush)}}function useVertxTimer(){if(typeof vertxNext!=="undefined"){return function(){vertxNext(flush)}}return useSetTimeout()}function useMutationObserver(){var iterations=0;var observer=new BrowserMutationObserver(flush);var node=document.createTextNode("");observer.observe(node,{characterData:true});return function(){node.data=iterations=++iterations%2}}function useMessageChannel(){var channel=new MessageChannel;channel.port1.onmessage=flush;return function(){return channel.port2.postMessage(0)}}function useSetTimeout(){var globalSetTimeout=setTimeout;return function(){return globalSetTimeout(flush,1)}}var queue=new Array(1e3);function flush(){for(var i=0;i<len;i+=2){var callback=queue[i];var arg=queue[i+1];callback(arg);queue[i]=undefined;queue[i+1]=undefined}len=0}function attemptVertx(){try{var r=require;var vertx=r("vertx");vertxNext=vertx.runOnLoop||vertx.runOnContext;return useVertxTimer()}catch(e){return useSetTimeout()}}var scheduleFlush=undefined;if(isNode){scheduleFlush=useNextTick()}else if(BrowserMutationObserver){scheduleFlush=useMutationObserver()}else if(isWorker){scheduleFlush=useMessageChannel()}else if(browserWindow===undefined&&typeof require==="function"){scheduleFlush=attemptVertx()}else{scheduleFlush=useSetTimeout()}function then(onFulfillment,onRejection){var _arguments=arguments;var parent=this;var child=new this.constructor(noop);if(child[PROMISE_ID]===undefined){makePromise(child)}var _state=parent._state;if(_state){(function(){var callback=_arguments[_state-1];asap(function(){return invokeCallback(_state,child,callback,parent._result)})})()}else{subscribe(parent,child,onFulfillment,onRejection)}return child}function resolve(object){var Constructor=this;if(object&&typeof object==="object"&&object.constructor===Constructor){return object}var promise=new Constructor(noop);_resolve(promise,object);return promise}var PROMISE_ID=Math.random().toString(36).substring(16);function noop(){}var PENDING=void 0;var FULFILLED=1;var REJECTED=2;var GET_THEN_ERROR=new ErrorObject;function selfFulfillment(){return new TypeError("You cannot resolve a promise with itself")}function cannotReturnOwn(){return new TypeError("A promises callback cannot return that same promise.")}function getThen(promise){try{return promise.then}catch(error){GET_THEN_ERROR.error=error;return GET_THEN_ERROR}}function tryThen(then,value,fulfillmentHandler,rejectionHandler){try{then.call(value,fulfillmentHandler,rejectionHandler)}catch(e){return e}}function handleForeignThenable(promise,thenable,then){asap(function(promise){var sealed=false;var error=tryThen(then,thenable,function(value){if(sealed){return}sealed=true;if(thenable!==value){_resolve(promise,value)}else{fulfill(promise,value)}},function(reason){if(sealed){return}sealed=true;_reject(promise,reason)},"Settle: "+(promise._label||" unknown promise"));if(!sealed&&error){sealed=true;_reject(promise,error)}},promise)}function handleOwnThenable(promise,thenable){if(thenable._state===FULFILLED){fulfill(promise,thenable._result)}else if(thenable._state===REJECTED){_reject(promise,thenable._result)}else{subscribe(thenable,undefined,function(value){return _resolve(promise,value)},function(reason){return _reject(promise,reason)})}}function handleMaybeThenable(promise,maybeThenable,then$$){if(maybeThenable.constructor===promise.constructor&&then$$===then&&maybeThenable.constructor.resolve===resolve){handleOwnThenable(promise,maybeThenable)}else{if(then$$===GET_THEN_ERROR){_reject(promise,GET_THEN_ERROR.error)}else if(then$$===undefined){fulfill(promise,maybeThenable)}else if(isFunction(then$$)){handleForeignThenable(promise,maybeThenable,then$$)}else{fulfill(promise,maybeThenable)}}}function _resolve(promise,value){if(promise===value){_reject(promise,selfFulfillment())}else if(objectOrFunction(value)){handleMaybeThenable(promise,value,getThen(value))}else{fulfill(promise,value)}}function publishRejection(promise){if(promise._onerror){promise._onerror(promise._result)}publish(promise)}function fulfill(promise,value){if(promise._state!==PENDING){return}promise._result=value;promise._state=FULFILLED;if(promise._subscribers.length!==0){asap(publish,promise)}}function _reject(promise,reason){if(promise._state!==PENDING){return}promise._state=REJECTED;promise._result=reason;asap(publishRejection,promise)}function subscribe(parent,child,onFulfillment,onRejection){var _subscribers=parent._subscribers;var length=_subscribers.length;parent._onerror=null;_subscribers[length]=child;_subscribers[length+FULFILLED]=onFulfillment;_subscribers[length+REJECTED]=onRejection;if(length===0&&parent._state){asap(publish,parent)}}function publish(promise){var subscribers=promise._subscribers;var settled=promise._state;if(subscribers.length===0){return}var child=undefined,callback=undefined,detail=promise._result;for(var i=0;i<subscribers.length;i+=3){child=subscribers[i];callback=subscribers[i+settled];if(child){invokeCallback(settled,child,callback,detail)}else{callback(detail)}}promise._subscribers.length=0}function ErrorObject(){this.error=null}var TRY_CATCH_ERROR=new ErrorObject;function tryCatch(callback,detail){try{return callback(detail)}catch(e){TRY_CATCH_ERROR.error=e;return TRY_CATCH_ERROR}}function invokeCallback(settled,promise,callback,detail){var hasCallback=isFunction(callback),value=undefined,error=undefined,succeeded=undefined,failed=undefined;if(hasCallback){value=tryCatch(callback,detail);if(value===TRY_CATCH_ERROR){failed=true;error=value.error;value=null}else{succeeded=true}if(promise===value){_reject(promise,cannotReturnOwn());return}}else{value=detail;succeeded=true}if(promise._state!==PENDING){}else if(hasCallback&&succeeded){_resolve(promise,value)}else if(failed){_reject(promise,error)}else if(settled===FULFILLED){fulfill(promise,value)}else if(settled===REJECTED){_reject(promise,value)}}function initializePromise(promise,resolver){try{resolver(function resolvePromise(value){_resolve(promise,value)},function rejectPromise(reason){_reject(promise,reason)})}catch(e){_reject(promise,e)}}var id=0;function nextId(){return id++}function makePromise(promise){promise[PROMISE_ID]=id++;promise._state=undefined;promise._result=undefined;promise._subscribers=[]}function Enumerator(Constructor,input){this._instanceConstructor=Constructor;this.promise=new Constructor(noop);if(!this.promise[PROMISE_ID]){makePromise(this.promise)}if(isArray(input)){this._input=input;this.length=input.length;this._remaining=input.length;this._result=new Array(this.length);if(this.length===0){fulfill(this.promise,this._result)}else{this.length=this.length||0;this._enumerate();if(this._remaining===0){fulfill(this.promise,this._result)}}}else{_reject(this.promise,validationError())}}function validationError(){return new Error("Array Methods must be provided an Array")}Enumerator.prototype._enumerate=function(){var length=this.length;var _input=this._input;for(var i=0;this._state===PENDING&&i<length;i++){this._eachEntry(_input[i],i)}};Enumerator.prototype._eachEntry=function(entry,i){var c=this._instanceConstructor;var resolve$$=c.resolve;if(resolve$$===resolve){var _then=getThen(entry);if(_then===then&&entry._state!==PENDING){this._settledAt(entry._state,i,entry._result)}else if(typeof _then!=="function"){this._remaining--;this._result[i]=entry}else if(c===Promise){var promise=new c(noop);handleMaybeThenable(promise,entry,_then);this._willSettleAt(promise,i)}else{this._willSettleAt(new c(function(resolve$$){return resolve$$(entry)}),i)}}else{this._willSettleAt(resolve$$(entry),i)}};Enumerator.prototype._settledAt=function(state,i,value){var promise=this.promise;if(promise._state===PENDING){this._remaining--;if(state===REJECTED){_reject(promise,value)}else{this._result[i]=value}}if(this._remaining===0){fulfill(promise,this._result)}};Enumerator.prototype._willSettleAt=function(promise,i){var enumerator=this;subscribe(promise,undefined,function(value){return enumerator._settledAt(FULFILLED,i,value)},function(reason){return enumerator._settledAt(REJECTED,i,reason)})};function all(entries){return new Enumerator(this,entries).promise}function race(entries){var Constructor=this;if(!isArray(entries)){return new Constructor(function(_,reject){return reject(new TypeError("You must pass an array to race."))})}else{return new Constructor(function(resolve,reject){var length=entries.length;for(var i=0;i<length;i++){Constructor.resolve(entries[i]).then(resolve,reject)}})}}function reject(reason){var Constructor=this;var promise=new Constructor(noop);_reject(promise,reason);return promise}function needsResolver(){throw new TypeError("You must pass a resolver function as the first argument to the promise constructor")}function needsNew(){throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.")}function Promise(resolver){this[PROMISE_ID]=nextId();this._result=this._state=undefined;this._subscribers=[];if(noop!==resolver){typeof resolver!=="function"&&needsResolver();this instanceof Promise?initializePromise(this,resolver):needsNew()}}Promise.all=all;Promise.race=race;Promise.resolve=resolve;Promise.reject=reject;Promise._setScheduler=setScheduler;Promise._setAsap=setAsap;Promise._asap=asap;Promise.prototype={constructor:Promise,then:then,catch:function _catch(onRejection){return this.then(null,onRejection)}};function polyfill(){var local=undefined;if(typeof global!=="undefined"){local=global}else if(typeof self!=="undefined"){local=self}else{try{local=Function("return this")()}catch(e){throw new Error("polyfill failed because global object is unavailable in this environment")}}var P=local.Promise;if(P){var promiseToString=null;try{promiseToString=Object.prototype.toString.call(P.resolve())}catch(e){}if(promiseToString==="[object Promise]"&&!P.cast){return}}local.Promise=Promise}Promise.polyfill=polyfill;Promise.Promise=Promise;return Promise});ES6Promise.polyfill();var XDM={};(function(XDM){var smallestRandom=parseInt("10000000000",36);var maxSafeInteger=Number.MAX_SAFE_INTEGER||9007199254740991;function newFingerprint(){return Math.floor(Math.random()*(maxSafeInteger-smallestRandom)+smallestRandom).toString(36)+Math.floor(Math.random()*(maxSafeInteger-smallestRandom)+smallestRandom).toString(36)}var XDMObjectRegistry=function(){function XDMObjectRegistry(){this._registeredObjects={}}XDMObjectRegistry.prototype.register=function(instanceId,instance){this._registeredObjects[instanceId]=instance};XDMObjectRegistry.prototype.unregister=function(instanceId){delete this._registeredObjects[instanceId]};XDMObjectRegistry.prototype.getInstance=function(instanceId,contextData){var instance=this._registeredObjects[instanceId];if(!instance){return null}if(typeof instance==="function"){return instance(contextData)}else{return instance}};return XDMObjectRegistry}();XDM.XDMObjectRegistry=XDMObjectRegistry;XDM.globalObjectRegistry=new XDMObjectRegistry;var MAX_XDM_DEPTH=100;var nextChannelId=1;var XDMChannel=function(){function XDMChannel(postToWindow,targetOrigin){this.promises={};this.nextMessageId=1;this.nextProxyId=1;this.proxyFunctions={};this.postToWindow=postToWindow;this.targetOrigin=targetOrigin;this.registry=new XDMObjectRegistry;this.channelId=nextChannelId++;if(!this.targetOrigin){this.handshakeToken=newFingerprint()}}XDMChannel.prototype.getObjectRegistry=function(){return this.registry};XDMChannel.prototype.invokeRemoteMethod=function(methodName,instanceId,params,instanceContextData,serializationSettings){var _this=this;var message={id:this.nextMessageId++,methodName:methodName,instanceId:instanceId,instanceContext:instanceContextData,params:this._customSerializeObject(params,serializationSettings),serializationSettings:serializationSettings};if(!this.targetOrigin){message.handshakeToken=this.handshakeToken}var promise=new Promise(function(resolve,reject){_this.promises[message.id]={resolve:resolve,reject:reject}});this._sendRpcMessage(message);return promise};XDMChannel.prototype.getRemoteObjectProxy=function(instanceId,contextData){return this.invokeRemoteMethod("",instanceId,undefined,contextData)};XDMChannel.prototype.invokeMethod=function(registeredInstance,rpcMessage){var _this=this;if(!rpcMessage.methodName){this._success(rpcMessage,registeredInstance,rpcMessage.handshakeToken);return}var method=registeredInstance[rpcMessage.methodName];if(typeof method!=="function"){this.error(rpcMessage,new Error("RPC method not found: "+rpcMessage.methodName));return}try{var methodArgs=[];if(rpcMessage.params){methodArgs=this._customDeserializeObject(rpcMessage.params,{})}var result=method.apply(registeredInstance,methodArgs);if(result&&result.then&&typeof result.then==="function"){result.then(function(asyncResult){_this._success(rpcMessage,asyncResult,rpcMessage.handshakeToken)},function(e){_this.error(rpcMessage,e)})}else{this._success(rpcMessage,result,rpcMessage.handshakeToken)}}catch(exception){this.error(rpcMessage,exception)}};XDMChannel.prototype.getRegisteredObject=function(instanceId,instanceContext){if(instanceId==="__proxyFunctions"){return this.proxyFunctions}var registeredObject=this.registry.getInstance(instanceId,instanceContext);if(!registeredObject){registeredObject=exports.globalObjectRegistry.getInstance(instanceId,instanceContext)}return registeredObject};XDMChannel.prototype.onMessage=function(rpcMessage){var _this=this;if(rpcMessage.instanceId){var registeredObject=this.getRegisteredObject(rpcMessage.instanceId,rpcMessage.instanceContext);if(!registeredObject){return false}if(typeof registeredObject["then"]==="function"){registeredObject.then(function(resolvedInstance){_this.invokeMethod(resolvedInstance,rpcMessage)},function(e){_this.error(rpcMessage,e)})}else{this.invokeMethod(registeredObject,rpcMessage)}}else{var promise=this.promises[rpcMessage.id];if(!promise){return false}if(rpcMessage.error){promise.reject(this._customDeserializeObject([rpcMessage.error],{})[0])}else{promise.resolve(this._customDeserializeObject([rpcMessage.result],{})[0])}delete this.promises[rpcMessage.id]}return true};XDMChannel.prototype.owns=function(source,origin,rpcMessage){if(this.postToWindow===source){if(this.targetOrigin){if(origin){return origin.toLowerCase()==="null"||this.targetOrigin.toLowerCase().indexOf(origin.toLowerCase())===0}else{return false}}else{if(rpcMessage.handshakeToken&&rpcMessage.handshakeToken===this.handshakeToken){this.targetOrigin=origin;return true}}}return false};XDMChannel.prototype.error=function(messageObj,errorObj){this._sendRpcMessage({id:messageObj.id,error:this._customSerializeObject([errorObj],messageObj.serializationSettings)[0],handshakeToken:messageObj.handshakeToken})};XDMChannel.prototype._success=function(messageObj,result,handshakeToken){this._sendRpcMessage({id:messageObj.id,result:this._customSerializeObject([result],messageObj.serializationSettings)[0],handshakeToken:handshakeToken})};XDMChannel.prototype._sendRpcMessage=function(message){this.postToWindow.postMessage(JSON.stringify(message),"*")};XDMChannel.prototype._customSerializeObject=function(obj,settings,prevParentObjects,nextCircularRefId,depth){var _this=this;if(nextCircularRefId===void 0){nextCircularRefId=1}if(depth===void 0){depth=1}if(!obj||depth>MAX_XDM_DEPTH){return undefined}if(obj instanceof Node||obj instanceof Window||obj instanceof Event){return undefined}var returnValue;var parentObjects;if(!prevParentObjects){parentObjects={newObjects:[],originalObjects:[]}}else{parentObjects=prevParentObjects}parentObjects.originalObjects.push(obj);var serializeMember=function(parentObject,newObject,key){var item;try{item=parentObject[key]}catch(ex){}var itemType=typeof item;if(itemType==="undefined"){return}var parentItemIndex=-1;if(itemType==="object"){parentItemIndex=parentObjects.originalObjects.indexOf(item)}if(parentItemIndex>=0){var parentItem=parentObjects.newObjects[parentItemIndex];if(!parentItem.__circularReferenceId){parentItem.__circularReferenceId=nextCircularRefId++}newObject[key]={__circularReference:parentItem.__circularReferenceId}}else{if(itemType==="function"){var proxyFunctionId=_this.nextProxyId++;newObject[key]={__proxyFunctionId:_this._registerProxyFunction(item,obj),_channelId:_this.channelId}}else if(itemType==="object"){if(item&&item instanceof Date){newObject[key]={__proxyDate:item.getTime()}}else{newObject[key]=_this._customSerializeObject(item,settings,parentObjects,nextCircularRefId,depth+1)}}else if(key!=="__proxyFunctionId"){newObject[key]=item}}};if(obj instanceof Array){returnValue=[];parentObjects.newObjects.push(returnValue);for(var i=0,l=obj.length;i<l;i++){serializeMember(obj,returnValue,i)}}else{returnValue={};parentObjects.newObjects.push(returnValue);var keys={};try{for(var key in obj){keys[key]=true}var ownProperties=Object.getOwnPropertyNames(obj);for(var i=0,l=ownProperties.length;i<l;i++){keys[ownProperties[i]]=true}}catch(ex){}for(var key in keys){if(key&&key[0]!=="_"||settings&&settings.includeUnderscoreProperties){serializeMember(obj,returnValue,key)}}}parentObjects.originalObjects.pop();parentObjects.newObjects.pop();return returnValue};XDMChannel.prototype._registerProxyFunction=function(func,context){var proxyFunctionId=this.nextProxyId++;this.proxyFunctions["proxy"+proxyFunctionId]=function(){return func.apply(context,Array.prototype.slice.call(arguments,0))};return proxyFunctionId};XDMChannel.prototype._customDeserializeObject=function(obj,circularRefs){var _this=this;var that=this;if(!obj){return null}var deserializeMember=function(parentObject,key){var item=parentObject[key];var itemType=typeof item;if(key==="__circularReferenceId"&&itemType==="number"){circularRefs[item]=parentObject;delete parentObject[key]}else if(itemType==="object"&&item){if(item.__proxyFunctionId){parentObject[key]=function(){return that.invokeRemoteMethod("proxy"+item.__proxyFunctionId,"__proxyFunctions",Array.prototype.slice.call(arguments,0),{},{includeUnderscoreProperties:true})}}else if(item.__proxyDate){parentObject[key]=new Date(item.__proxyDate)}else if(item.__circularReference){parentObject[key]=circularRefs[item.__circularReference]}else{_this._customDeserializeObject(item,circularRefs)}}};if(obj instanceof Array){for(var i=0,l=obj.length;i<l;i++){deserializeMember(obj,i)}}else if(typeof obj==="object"){for(var key in obj){deserializeMember(obj,key)}}return obj};return XDMChannel}();XDM.parentChannel=new XDMChannel(window.parent);window.addEventListener("message",function(event){var rpcMessage;if(typeof event.data==="string"){try{rpcMessage=JSON.parse(event.data)}catch(error){}}if(rpcMessage){var channel=XDM.parentChannel;if(channel.owns(event.source,event.origin,rpcMessage)){var handled=channel.onMessage(rpcMessage)||handled;if(!handled){if(window.console){console.error("No handler found for message: "+JSON.stringify(rpcMessage))}if(rpcMessage.instanceId){channel.error(rpcMessage,new Error("The registered object "+rpcMessage.instanceId+" could not be found."))}}}}})})(XDM);var DevOps={};(function(DevOps){DevOps.sdkVersion=3;var hostControlId="DevOps.HostControl";var serviceManagerId="DevOps.ServiceManager";var extensionContext;var initialConfiguration;var initialContributionId;var userContext;var hostContext;var isReady=false;var readyCallbacks=[];var themeElement;var parentChannel=XDM.parentChannel;DevOps.init=function(options){window.setTimeout(function(){var initOptions=Object.assign({},options,{sdkVersion:DevOps.sdkVersion});parentChannel.invokeRemoteMethod("initialHandshake",hostControlId,[initOptions]).then(function(handshakeData){initialConfiguration=handshakeData.initialConfig||{};initialContributionId=handshakeData.contributionId;var context=handshakeData.context;if(context){extensionContext=context.extension;userContext=context.user;hostContext=context.host}if(handshakeData.themeData){DevOps.applyTheme(handshakeData.themeData)}triggerReady()})},0)};DevOps.ready=function(callback){if(isReady){window.setTimeout(callback,0)}else{readyCallbacks.push(callback)}};DevOps.notifyLoadSucceeded=function(){return parentChannel.invokeRemoteMethod("notifyLoadSucceeded",hostControlId)};DevOps.notifyLoadFailed=function(e){return parentChannel.invokeRemoteMethod("notifyLoadFailed",hostControlId,[e])};DevOps.getConfiguration=function(){return initialConfiguration};DevOps.getContributionId=function(){return initialContributionId};DevOps.getUser=function(){return userContext};DevOps.getHost=function(){return hostContext};DevOps.getExtensionContext=function(){return extensionContext};DevOps.getService=function(contributionId){return new Promise(function(resolve,reject){DevOps.ready(function(){parentChannel.invokeRemoteMethod("getService",serviceManagerId,[contributionId]).then(resolve,reject)})})};DevOps.register=function(instanceId,instance){parentChannel.getObjectRegistry().register(instanceId,instance)};DevOps.unregister=function(instanceId){parentChannel.getObjectRegistry().unregister(instanceId)};DevOps.getAccessToken=function(){return parentChannel.invokeRemoteMethod("getAccessToken",hostControlId).then(function(tokenObj){return tokenObj.token})};DevOps.getAppToken=function(){return parentChannel.invokeRemoteMethod("getAppToken",hostControlId).then(function(tokenObj){return tokenObj.token})};DevOps.resize=function(width,height){var body=document.body;if(body){var newWidth=typeof width==="number"?width:body?body.scrollWidth:undefined;var newHeight=typeof height==="number"?height:body?body.scrollHeight:undefined}parentChannel.invokeRemoteMethod("resize",hostControlId,[newWidth,newHeight])};DevOps.applyTheme=function(themeData){if(!themeElement){themeElement=document.createElement("style");themeElement.type="text/css";document.head.appendChild(themeElement)}var cssVariables=[];if(themeData){for(var varName in themeData){cssVariables.push("--"+varName+": "+themeData[varName])}}themeElement.innerText=":root { "+cssVariables.join("; ")+" } body { color: var(--text-primary-color) }"};function triggerReady(){isReady=true;if(readyCallbacks){var savedReadyCallbacks=readyCallbacks;readyCallbacks=[];savedReadyCallbacks.forEach(function(callback){callback()})}}})(DevOps); | ||
// Copyright (C) Microsoft Corporation. All rights reserved. | ||
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : | ||
typeof define === 'function' && define.amd ? define(factory) : | ||
(global.DevOps = factory()); | ||
}(this, (function () { 'use strict'; | ||
/** | ||
* Cross-document messaging capabilities for talking with the host frame | ||
*/ | ||
var XDM = {}; | ||
(function (XDM) { | ||
var smallestRandom = parseInt("10000000000", 36); | ||
var maxSafeInteger = Number.MAX_SAFE_INTEGER || 9007199254740991; | ||
/** | ||
* Create a new random 22-character fingerprint. | ||
* @return string fingerprint | ||
*/ | ||
function newFingerprint() { | ||
// smallestRandom ensures we will get a 11-character result from the base-36 conversion. | ||
return Math.floor((Math.random() * (maxSafeInteger - smallestRandom)) + smallestRandom).toString(36) + | ||
Math.floor((Math.random() * (maxSafeInteger - smallestRandom)) + smallestRandom).toString(36); | ||
} | ||
/** | ||
* Catalog of objects exposed for XDM | ||
*/ | ||
var XDMObjectRegistry = /** @class */ (function () { | ||
function XDMObjectRegistry() { | ||
this._registeredObjects = {}; | ||
} | ||
/** | ||
* Register an object (instance or factory method) exposed by this frame to callers in a remote frame | ||
* | ||
* @param instanceId unique id of the registered object | ||
* @param instance Either: (1) an object instance, or (2) a function that takes optional context data and returns an object instance. | ||
*/ | ||
XDMObjectRegistry.prototype.register = function (instanceId, instance) { | ||
this._registeredObjects[instanceId] = instance; | ||
}; | ||
/** | ||
* Unregister an object (instance or factory method) that was previously registered by this frame | ||
* | ||
* @param instanceId unique id of the registered object | ||
*/ | ||
XDMObjectRegistry.prototype.unregister = function (instanceId) { | ||
delete this._registeredObjects[instanceId]; | ||
}; | ||
/** | ||
* Get an instance of an object registered with the given id | ||
* | ||
* @param instanceId unique id of the registered object | ||
* @param contextData Optional context data to pass to a registered object's factory method | ||
*/ | ||
XDMObjectRegistry.prototype.getInstance = function (instanceId, contextData) { | ||
var instance = this._registeredObjects[instanceId]; | ||
if (!instance) { | ||
return null; | ||
} | ||
if (typeof instance === "function") { | ||
return instance(contextData); | ||
} | ||
else { | ||
return instance; | ||
} | ||
}; | ||
return XDMObjectRegistry; | ||
}()); | ||
XDM.XDMObjectRegistry = XDMObjectRegistry; | ||
/** | ||
* The registry of global XDM handlers | ||
*/ | ||
XDM.globalObjectRegistry = new XDMObjectRegistry(); | ||
var MAX_XDM_DEPTH = 100; | ||
var nextChannelId = 1; | ||
/** | ||
* Represents a channel of communication between frames\document | ||
* Stays "alive" across multiple funtion\method calls | ||
*/ | ||
var XDMChannel = /** @class */ (function () { | ||
function XDMChannel(postToWindow, targetOrigin) { | ||
this.promises = {}; | ||
this.nextMessageId = 1; | ||
this.nextProxyId = 1; | ||
this.proxyFunctions = {}; | ||
this.postToWindow = postToWindow; | ||
this.targetOrigin = targetOrigin; | ||
this.registry = new XDMObjectRegistry(); | ||
this.channelId = nextChannelId++; | ||
if (!this.targetOrigin) { | ||
this.handshakeToken = newFingerprint(); | ||
} | ||
} | ||
/** | ||
* Get the object registry to handle messages from this specific channel. | ||
* Upon receiving a message, this channel registry will be used first, then | ||
* the global registry will be used if no handler is found here. | ||
*/ | ||
XDMChannel.prototype.getObjectRegistry = function () { | ||
return this.registry; | ||
}; | ||
/** | ||
* Invoke a method via RPC. Lookup the registered object on the remote end of the channel and invoke the specified method. | ||
* | ||
* @param method Name of the method to invoke | ||
* @param instanceId unique id of the registered object | ||
* @param params Arguments to the method to invoke | ||
* @param instanceContextData Optional context data to pass to a registered object's factory method | ||
* @param serializationSettings Optional serialization settings | ||
*/ | ||
XDMChannel.prototype.invokeRemoteMethod = function (methodName, instanceId, params, instanceContextData, serializationSettings) { | ||
var _this = this; | ||
var message = { | ||
id: this.nextMessageId++, | ||
methodName: methodName, | ||
instanceId: instanceId, | ||
instanceContext: instanceContextData, | ||
params: this._customSerializeObject(params, serializationSettings), | ||
serializationSettings: serializationSettings | ||
}; | ||
if (!this.targetOrigin) { | ||
message.handshakeToken = this.handshakeToken; | ||
} | ||
var promise = new Promise(function (resolve, reject) { | ||
_this.promises[message.id] = { resolve: resolve, reject: reject }; | ||
}); | ||
this._sendRpcMessage(message); | ||
return promise; | ||
}; | ||
/** | ||
* Get a proxied object that represents the object registered with the given instance id on the remote side of this channel. | ||
* | ||
* @param instanceId unique id of the registered object | ||
* @param contextData Optional context data to pass to a registered object's factory method | ||
*/ | ||
XDMChannel.prototype.getRemoteObjectProxy = function (instanceId, contextData) { | ||
return this.invokeRemoteMethod("", instanceId, undefined, contextData); | ||
}; | ||
XDMChannel.prototype.invokeMethod = function (registeredInstance, rpcMessage) { | ||
var _this = this; | ||
if (!rpcMessage.methodName) { | ||
// Null/empty method name indicates to return the registered object itself. | ||
this._success(rpcMessage, registeredInstance, rpcMessage.handshakeToken); | ||
return; | ||
} | ||
var method = registeredInstance[rpcMessage.methodName]; | ||
if (typeof method !== "function") { | ||
this.error(rpcMessage, new Error("RPC method not found: " + rpcMessage.methodName)); | ||
return; | ||
} | ||
try { | ||
// Call specified method. Add nested success and error call backs with closure | ||
// so we can post back a response as a result or error as appropriate | ||
var methodArgs = []; | ||
if (rpcMessage.params) { | ||
methodArgs = this._customDeserializeObject(rpcMessage.params, {}); | ||
} | ||
var result = method.apply(registeredInstance, methodArgs); | ||
if (result && result.then && typeof result.then === "function") { | ||
result.then(function (asyncResult) { | ||
_this._success(rpcMessage, asyncResult, rpcMessage.handshakeToken); | ||
}, function (e) { | ||
_this.error(rpcMessage, e); | ||
}); | ||
} | ||
else { | ||
this._success(rpcMessage, result, rpcMessage.handshakeToken); | ||
} | ||
} | ||
catch (exception) { | ||
// send back as error if an exception is thrown | ||
this.error(rpcMessage, exception); | ||
} | ||
}; | ||
XDMChannel.prototype.getRegisteredObject = function (instanceId, instanceContext) { | ||
if (instanceId === "__proxyFunctions") { | ||
// Special case for proxied functions of remote instances | ||
return this.proxyFunctions; | ||
} | ||
// Look in the channel registry first | ||
var registeredObject = this.registry.getInstance(instanceId, instanceContext); | ||
if (!registeredObject) { | ||
// Look in the global registry as a fallback | ||
registeredObject = exports.globalObjectRegistry.getInstance(instanceId, instanceContext); | ||
} | ||
return registeredObject; | ||
}; | ||
/** | ||
* Handle a received message on this channel. Dispatch to the appropriate object found via object registry | ||
* | ||
* @param rpcMessage Message data | ||
* @return True if the message was handled by this channel. Otherwise false. | ||
*/ | ||
XDMChannel.prototype.onMessage = function (rpcMessage) { | ||
var _this = this; | ||
if (rpcMessage.instanceId) { | ||
// Find the object that handles this requestNeed to find implementation | ||
// Look in the channel registry first | ||
var registeredObject = this.getRegisteredObject(rpcMessage.instanceId, rpcMessage.instanceContext); | ||
if (!registeredObject) { | ||
// If not found return false to indicate that the message was not handled | ||
return false; | ||
} | ||
if (typeof registeredObject["then"] === "function") { | ||
registeredObject.then(function (resolvedInstance) { | ||
_this.invokeMethod(resolvedInstance, rpcMessage); | ||
}, function (e) { | ||
_this.error(rpcMessage, e); | ||
}); | ||
} | ||
else { | ||
this.invokeMethod(registeredObject, rpcMessage); | ||
} | ||
} | ||
else { | ||
var promise = this.promises[rpcMessage.id]; | ||
if (!promise) { | ||
// Message not handled by this channel. | ||
return false; | ||
} | ||
if (rpcMessage.error) { | ||
promise.reject(this._customDeserializeObject([rpcMessage.error], {})[0]); | ||
} | ||
else { | ||
promise.resolve(this._customDeserializeObject([rpcMessage.result], {})[0]); | ||
} | ||
delete this.promises[rpcMessage.id]; | ||
} | ||
// Message handled by this channel | ||
return true; | ||
}; | ||
XDMChannel.prototype.owns = function (source, origin, rpcMessage) { | ||
/// Determines whether the current message belongs to this channel or not | ||
if (this.postToWindow === source) { | ||
// For messages coming from sandboxed iframes the origin will be set to the string "null". This is | ||
// how onprem works. If it is not a sandboxed iFrame we will get the origin as expected. | ||
if (this.targetOrigin) { | ||
if (origin) { | ||
return origin.toLowerCase() === "null" || this.targetOrigin.toLowerCase().indexOf(origin.toLowerCase()) === 0; | ||
} | ||
else { | ||
return false; | ||
} | ||
} | ||
else { | ||
if (rpcMessage.handshakeToken && rpcMessage.handshakeToken === this.handshakeToken) { | ||
this.targetOrigin = origin; | ||
return true; | ||
} | ||
} | ||
} | ||
return false; | ||
}; | ||
XDMChannel.prototype.error = function (messageObj, errorObj) { | ||
this._sendRpcMessage({ | ||
id: messageObj.id, | ||
error: this._customSerializeObject([errorObj], messageObj.serializationSettings)[0], | ||
handshakeToken: messageObj.handshakeToken | ||
}); | ||
}; | ||
XDMChannel.prototype._success = function (messageObj, result, handshakeToken) { | ||
this._sendRpcMessage({ | ||
id: messageObj.id, | ||
result: this._customSerializeObject([result], messageObj.serializationSettings)[0], | ||
handshakeToken: handshakeToken | ||
}); | ||
}; | ||
XDMChannel.prototype._sendRpcMessage = function (message) { | ||
this.postToWindow.postMessage(JSON.stringify(message), "*"); | ||
}; | ||
XDMChannel.prototype._customSerializeObject = function (obj, settings, prevParentObjects, nextCircularRefId, depth) { | ||
var _this = this; | ||
if (nextCircularRefId === void 0) { nextCircularRefId = 1; } | ||
if (depth === void 0) { depth = 1; } | ||
if (!obj || depth > MAX_XDM_DEPTH) { | ||
return undefined; | ||
} | ||
if (obj instanceof Node || obj instanceof Window || obj instanceof Event) { | ||
return undefined; | ||
} | ||
var returnValue; | ||
var parentObjects; | ||
if (!prevParentObjects) { | ||
parentObjects = { | ||
newObjects: [], | ||
originalObjects: [] | ||
}; | ||
} | ||
else { | ||
parentObjects = prevParentObjects; | ||
} | ||
parentObjects.originalObjects.push(obj); | ||
var serializeMember = function (parentObject, newObject, key) { | ||
var item; | ||
try { | ||
item = parentObject[key]; | ||
} | ||
catch (ex) { | ||
// Cannot access this property. Skip its serialization. | ||
} | ||
var itemType = typeof item; | ||
if (itemType === "undefined") { | ||
return; | ||
} | ||
// Check for a circular reference by looking at parent objects | ||
var parentItemIndex = -1; | ||
if (itemType === "object") { | ||
parentItemIndex = parentObjects.originalObjects.indexOf(item); | ||
} | ||
if (parentItemIndex >= 0) { | ||
// Circular reference found. Add reference to parent | ||
var parentItem = parentObjects.newObjects[parentItemIndex]; | ||
if (!parentItem.__circularReferenceId) { | ||
parentItem.__circularReferenceId = nextCircularRefId++; | ||
} | ||
newObject[key] = { | ||
__circularReference: parentItem.__circularReferenceId | ||
}; | ||
} | ||
else { | ||
if (itemType === "function") { | ||
var proxyFunctionId = _this.nextProxyId++; | ||
newObject[key] = { | ||
__proxyFunctionId: _this._registerProxyFunction(item, obj), | ||
_channelId: _this.channelId | ||
}; | ||
} | ||
else if (itemType === "object") { | ||
if (item && item instanceof Date) { | ||
newObject[key] = { | ||
__proxyDate: item.getTime() | ||
}; | ||
} | ||
else { | ||
newObject[key] = _this._customSerializeObject(item, settings, parentObjects, nextCircularRefId, depth + 1); | ||
} | ||
} | ||
else if (key !== "__proxyFunctionId") { | ||
// Just add non object/function properties as-is. Don't include "__proxyFunctionId" to protect | ||
// our proxy methods from being invoked from other messages. | ||
newObject[key] = item; | ||
} | ||
} | ||
}; | ||
if (obj instanceof Array) { | ||
returnValue = []; | ||
parentObjects.newObjects.push(returnValue); | ||
for (var i = 0, l = obj.length; i < l; i++) { | ||
serializeMember(obj, returnValue, i); | ||
} | ||
} | ||
else { | ||
returnValue = {}; | ||
parentObjects.newObjects.push(returnValue); | ||
var keys = {}; | ||
try { | ||
// We want to get both enumerable and non-enumerable properties | ||
// including inherited enumerable properties. for..in grabs | ||
// enumerable properties (including inherited properties) and | ||
// getOwnPropertyNames includes non-enumerable properties. | ||
// Merge these results together. | ||
for (var key in obj) { | ||
keys[key] = true; | ||
} | ||
var ownProperties = Object.getOwnPropertyNames(obj); | ||
for (var i = 0, l = ownProperties.length; i < l; i++) { | ||
keys[ownProperties[i]] = true; | ||
} | ||
} | ||
catch (ex) { | ||
// We may not be able to access the iterator of this object. Skip its serialization. | ||
} | ||
for (var key in keys) { | ||
// Don't serialize properties that start with an underscore. | ||
if ((key && key[0] !== "_") || (settings && settings.includeUnderscoreProperties)) { | ||
serializeMember(obj, returnValue, key); | ||
} | ||
} | ||
} | ||
parentObjects.originalObjects.pop(); | ||
parentObjects.newObjects.pop(); | ||
return returnValue; | ||
}; | ||
XDMChannel.prototype._registerProxyFunction = function (func, context) { | ||
var proxyFunctionId = this.nextProxyId++; | ||
this.proxyFunctions["proxy" + proxyFunctionId] = function () { | ||
return func.apply(context, Array.prototype.slice.call(arguments, 0)); | ||
}; | ||
return proxyFunctionId; | ||
}; | ||
XDMChannel.prototype._customDeserializeObject = function (obj, circularRefs) { | ||
var _this = this; | ||
var that = this; | ||
if (!obj) { | ||
return null; | ||
} | ||
var deserializeMember = function (parentObject, key) { | ||
var item = parentObject[key]; | ||
var itemType = typeof item; | ||
if (key === "__circularReferenceId" && itemType === 'number') { | ||
circularRefs[item] = parentObject; | ||
delete parentObject[key]; | ||
} | ||
else if (itemType === "object" && item) { | ||
if (item.__proxyFunctionId) { | ||
parentObject[key] = function () { | ||
return that.invokeRemoteMethod("proxy" + item.__proxyFunctionId, "__proxyFunctions", Array.prototype.slice.call(arguments, 0), {}, { includeUnderscoreProperties: true }); | ||
}; | ||
} | ||
else if (item.__proxyDate) { | ||
parentObject[key] = new Date(item.__proxyDate); | ||
} | ||
else if (item.__circularReference) { | ||
parentObject[key] = circularRefs[item.__circularReference]; | ||
} | ||
else { | ||
_this._customDeserializeObject(item, circularRefs); | ||
} | ||
} | ||
}; | ||
if (obj instanceof Array) { | ||
for (var i = 0, l = obj.length; i < l; i++) { | ||
deserializeMember(obj, i); | ||
} | ||
} | ||
else if (typeof obj === "object") { | ||
for (var key in obj) { | ||
deserializeMember(obj, key); | ||
} | ||
} | ||
return obj; | ||
}; | ||
return XDMChannel; | ||
}()); | ||
XDM.parentChannel = new XDMChannel(window.parent); | ||
window.addEventListener("message", function (event) { | ||
// get channel and dispatch to it | ||
var rpcMessage; | ||
if (typeof event.data === "string") { | ||
try { | ||
rpcMessage = JSON.parse(event.data); | ||
} | ||
catch (error) { | ||
// The message is not a valid JSON string. Not one of our events. | ||
} | ||
} | ||
if (rpcMessage) { | ||
var channel = XDM.parentChannel; | ||
if (channel.owns(event.source, event.origin, rpcMessage)) { | ||
var handled = channel.onMessage(rpcMessage) || handled; | ||
if (!handled) { | ||
if (window.console) { | ||
console.error("No handler found for message: " + JSON.stringify(rpcMessage)); | ||
} | ||
// for instance based proxies, send an error on the channel owning the message to resolve any control creation promises | ||
// on the host frame. | ||
if (rpcMessage.instanceId) { | ||
channel.error(rpcMessage, new Error("The registered object " + rpcMessage.instanceId + " could not be found.")); | ||
} | ||
} | ||
} | ||
} | ||
}); | ||
})(XDM); | ||
/** | ||
* DevOps SDK | ||
*/ | ||
var DevOps = {}; | ||
(function (DevOps) { | ||
/** | ||
* Web SDK version number. Can be specified in an extension's set of demands like: vss-sdk-version/3.0 | ||
*/ | ||
DevOps.sdkVersion = 3.0; | ||
var hostControlId = "DevOps.HostControl"; | ||
var serviceManagerId = "DevOps.ServiceManager"; | ||
var extensionContext; | ||
var initialConfiguration; | ||
var initialContributionId; | ||
var userContext; | ||
var hostContext; | ||
var isReady = false; | ||
var readyCallbacks = []; | ||
var themeElement; | ||
var parentChannel = XDM.parentChannel; | ||
/** | ||
* Initiates the handshake with the host window. | ||
* | ||
* @param options Initialization options for the extension. | ||
*/ | ||
DevOps.init = function (options) { | ||
// Run this after current execution path is complete - allows objects to get initialized | ||
window.setTimeout(function () { | ||
// Avoid Object.assign for IE11 support | ||
var initOptions = {}; | ||
if (options) { | ||
for (var key in options) { | ||
initOptions[key] = options[key]; | ||
} | ||
} | ||
initOptions.sdkVersion = DevOps.sdkVersion; | ||
parentChannel.invokeRemoteMethod("initialHandshake", hostControlId, [initOptions]).then(function (handshakeData) { | ||
initialConfiguration = handshakeData.initialConfig || {}; | ||
initialContributionId = handshakeData.contributionId; | ||
var context = handshakeData.context; | ||
if (context) { | ||
extensionContext = context.extension; | ||
userContext = context.user; | ||
hostContext = context.host; | ||
} | ||
if (handshakeData.themeData) { | ||
DevOps.applyTheme(handshakeData.themeData); | ||
} | ||
triggerReady(); | ||
}); | ||
}, 0); | ||
} | ||
/** | ||
* Register a callback that gets called once the initial setup/handshake has completed. | ||
* If the initial setup is already completed, the callback is invoked at the end of the current call stack. | ||
*/ | ||
DevOps.ready = function (callback) { | ||
if (isReady) { | ||
window.setTimeout(callback, 0); | ||
} | ||
else { | ||
readyCallbacks.push(callback); | ||
} | ||
} | ||
/** | ||
* Notifies the host that the extension successfully loaded (stop showing the loading indicator) | ||
*/ | ||
DevOps.notifyLoadSucceeded = function () { | ||
return parentChannel.invokeRemoteMethod("notifyLoadSucceeded", hostControlId); | ||
} | ||
/** | ||
* Notifies the host that the extension failed to load | ||
*/ | ||
DevOps.notifyLoadFailed = function (e) { | ||
return parentChannel.invokeRemoteMethod("notifyLoadFailed", hostControlId, [e]); | ||
} | ||
/** | ||
* Get the configuration data passed in the initial handshake from the parent frame | ||
*/ | ||
DevOps.getConfiguration = function () { | ||
return initialConfiguration; | ||
} | ||
/** | ||
* Gets the information about the contribution that first caused this extension to load. | ||
*/ | ||
DevOps.getContributionId = function () { | ||
return initialContributionId; | ||
} | ||
/** | ||
* Gets information about the current user | ||
*/ | ||
DevOps.getUser = function () { | ||
return userContext; | ||
} | ||
/** | ||
* Gets information about the host (i.e. an Azure DevOps organization) that the page is targeting | ||
*/ | ||
DevOps.getHost = function () { | ||
return hostContext; | ||
} | ||
/** | ||
* Get the context about the extension that owns the content that is being hosted | ||
*/ | ||
DevOps.getExtensionContext = function () { | ||
return extensionContext; | ||
} | ||
/** | ||
* Get the contribution with the given contribution id. The returned contribution has a method to get a registered object within that contribution. | ||
* | ||
* @param contributionId Id of the contribution to get | ||
*/ | ||
DevOps.getService = function (contributionId) { | ||
return new Promise(function(resolve, reject) { | ||
DevOps.ready(function () { | ||
parentChannel.invokeRemoteMethod("getService", serviceManagerId, [contributionId]).then(resolve, reject); | ||
}); | ||
}); | ||
} | ||
/** | ||
* Register an object (instance or factory method) that this extension exposes to the host frame. | ||
* | ||
* @param instanceId unique id of the registered object | ||
* @param instance Either: (1) an object instance, or (2) a function that takes optional context data and returns an object instance. | ||
*/ | ||
DevOps.register = function (instanceId, instance) { | ||
parentChannel.getObjectRegistry().register(instanceId, instance); | ||
} | ||
/** | ||
* Removes an object that this extension exposed to the host frame. | ||
* | ||
* @param instanceId unique id of the registered object | ||
*/ | ||
DevOps.unregister = function (instanceId) { | ||
parentChannel.getObjectRegistry().unregister(instanceId); | ||
} | ||
/** | ||
* Fetch an access token which will allow calls to be made to other DevOps services | ||
*/ | ||
DevOps.getAccessToken = function () { | ||
return parentChannel.invokeRemoteMethod("getAccessToken", hostControlId).then(function (tokenObj) { return tokenObj.token; }); | ||
} | ||
/** | ||
* Fetch an token which can be used to identify the current user | ||
*/ | ||
DevOps.getAppToken = function () { | ||
return parentChannel.invokeRemoteMethod("getAppToken", hostControlId).then(function (tokenObj) { return tokenObj.token; }); | ||
} | ||
/** | ||
* Requests the parent window to resize the container for this extension based on the current extension size. | ||
* | ||
* @param width Optional width, defaults to scrollWidth | ||
* @param height Optional height, defaults to scrollHeight | ||
*/ | ||
DevOps.resize = function (width, height) { | ||
var body = document.body; | ||
if (body) { | ||
var newWidth = typeof width === "number" ? width : (body ? body.scrollWidth : undefined); | ||
var newHeight = typeof height === "number" ? height : (body ? body.scrollHeight : undefined); | ||
} | ||
parentChannel.invokeRemoteMethod("resize", hostControlId, [newWidth, newHeight]); | ||
} | ||
/** | ||
* Applies theme variables to the current document | ||
*/ | ||
DevOps.applyTheme = function(themeData) { | ||
if (!themeElement) { | ||
themeElement = document.createElement("style"); | ||
themeElement.type = "text/css"; | ||
document.head.appendChild(themeElement); | ||
} | ||
var cssVariables = []; | ||
if (themeData) { | ||
for (var varName in themeData) { | ||
cssVariables.push("--" + varName + ": " + themeData[varName]); | ||
} | ||
} | ||
themeElement.innerText = ":root { " + cssVariables.join("; ") + " } body { color: var(--text-primary-color) }"; | ||
} | ||
function triggerReady() { | ||
isReady = true; | ||
if (readyCallbacks) { | ||
var savedReadyCallbacks = readyCallbacks; | ||
readyCallbacks = []; | ||
savedReadyCallbacks.forEach(function (callback) { | ||
callback(); | ||
}); | ||
} | ||
} | ||
})(DevOps); | ||
return DevOps; | ||
}))); |
{ | ||
"name": "azure-devops-extension-sdk", | ||
"version": "1.141.3", | ||
"version": "1.141.4", | ||
"description": "Azure DevOps web extension JavaScript library and types.", | ||
@@ -24,6 +24,3 @@ "repository": { | ||
"homepage": "https://docs.microsoft.com/en-us/azure/devops/integrate", | ||
"jspm": { | ||
"main": "lib/DevOps.SDK", | ||
"format": "global" | ||
}, | ||
"main": "lib/DevOps.SDK", | ||
"types": "./typings/index.d.ts", | ||
@@ -30,0 +27,0 @@ "devDependencies": { |
@@ -1,2 +0,625 @@ | ||
/// <reference path="DevOps.SDK.d.ts" /> | ||
/// <reference path="CommonServices.d.ts" /> | ||
export as namespace DevOps; | ||
/** | ||
* Options for extension initialization -- passed to DevOps.init() | ||
*/ | ||
export interface IExtensionInitOptions { | ||
/** | ||
* True indicates that the content of this extension is ready to be shown/used as soon as the | ||
* init handshake has completed. Otherwise, the extension must call DevOps.notifyLoadSucceeded() | ||
* once it has finished loading. | ||
*/ | ||
loaded?: boolean; | ||
/** | ||
* Extensions that show UI should specify this to true in order for the current user's theme | ||
* to be applied to this extension content. | ||
*/ | ||
applyTheme?: boolean; | ||
} | ||
/** | ||
* Information about the current user | ||
*/ | ||
export interface IUserContext { | ||
/** | ||
* Unique id for the user | ||
*/ | ||
id: string; | ||
/** | ||
* Name of the user (email/login) | ||
*/ | ||
name: string; | ||
/** | ||
* The user's display name (First name / Last name) | ||
*/ | ||
displayName: string; | ||
/** | ||
* Url to the user's profile image | ||
*/ | ||
imageUrl: string; | ||
} | ||
/** | ||
* DevOps host level | ||
*/ | ||
export const enum HostType { | ||
/** | ||
* The Deployment host | ||
*/ | ||
Deployment = 1, | ||
/** | ||
* The Enterprise host | ||
*/ | ||
Enterprise = 2, | ||
/** | ||
* The organization host | ||
*/ | ||
Organization = 4 | ||
} | ||
/** | ||
* Information about the current DevOps host (organization) | ||
*/ | ||
export interface IHostContext { | ||
/** | ||
* Unique GUID for this host | ||
*/ | ||
id: string; | ||
/** | ||
* Name of the host (i.e. Organization name) | ||
*/ | ||
name: string; | ||
/** | ||
* DevOps host level | ||
*/ | ||
type: HostType; | ||
} | ||
/** | ||
* Identifier for the current extension | ||
*/ | ||
export interface IExtensionContext { | ||
/** | ||
* Full id of the extension {publisher}.{extension} | ||
*/ | ||
id: string; | ||
/** | ||
* Id of the publisher | ||
*/ | ||
publisherId: string; | ||
/** | ||
* Id of the extension (without the publisher prefix) | ||
*/ | ||
extensionId: string; | ||
} | ||
/** | ||
* Version of the DevOps SDK | ||
*/ | ||
export const sdkVersion: number; | ||
/** | ||
* Initiates the handshake with the host window, allowing bi-directional communication between | ||
* this extension and the host frame. | ||
* | ||
* @param options Initialization options for the extension. | ||
*/ | ||
export function init(options: IExtensionInitOptions): void; | ||
/** | ||
* Register a callback that gets called once the initial setup/handshake has completed. | ||
* If the initial setup is already completed, the callback is invoked at the end of the current call stack. | ||
* | ||
* @param callback The callback invoked once the init handshake has completed, or immediately if it already has. | ||
*/ | ||
export function ready(callback: () => void): void; | ||
/** | ||
* Notifies the host that the extension successfully loaded (stop showing the loading indicator) | ||
*/ | ||
export function notifyLoadSucceeded(): Promise<void>; | ||
/** | ||
* Notifies the host that the extension failed to load | ||
*/ | ||
export function notifyLoadFailed(e: any): Promise<void>; | ||
/** | ||
* Get the configuration data passed in the initial handshake from the parent frame | ||
*/ | ||
export function getConfiguration(): any; | ||
/** | ||
* Gets information about the current user | ||
*/ | ||
export function getUser(): IUserContext; | ||
/** | ||
* Gets information about the host (i.e. an Azure DevOps organization) that the page is targeting | ||
*/ | ||
export function getHost(): IHostContext; | ||
/** | ||
* Get the context about the extension that owns the content that is being hosted | ||
*/ | ||
export function getExtensionContext(): IExtensionContext; | ||
/** | ||
* Get a contributed service from the parent host | ||
* | ||
* @param contributionId Full Id of the service contribution to get the instance of | ||
*/ | ||
export function getService<T>(contributionId: string): Promise<T>; | ||
/** | ||
* Register an object (instance or factory method) that this extension exposes to the host frame. | ||
* | ||
* @param instanceId unique id of the registered object | ||
* @param instance Either: (1) an object instance, or (2) a function that takes optional context data and returns an object instance. | ||
*/ | ||
export function register(instanceId: string, instance: Object | { (contextData?: any): Object; }): void; | ||
/** | ||
* Removes an object that this extension exposed to the host frame. | ||
* | ||
* @param instanceId unique id of the registered object | ||
*/ | ||
export function unregister(instanceId: string): void; | ||
/** | ||
* Fetch an access token which will allow calls to be made to other DevOps services | ||
*/ | ||
export function getAccessToken(): Promise<string>; | ||
/** | ||
* Fetch an token which can be used to identify the current user | ||
*/ | ||
export function getAppToken(): Promise<string>; | ||
/** | ||
* Requests the parent window to resize the container for this extension based on the current extension size. | ||
* | ||
* @param width Optional width, defaults to scrollWidth | ||
* @param height Optional height, defaults to scrollHeight | ||
*/ | ||
export function resize(width?: number, height?: number): void; | ||
/** | ||
* Applies the specified theme variables to the current extension document | ||
* | ||
* @param themeData Key/value pairs of themed CSS variables | ||
*/ | ||
export function applyTheme(themeData: { [themedVariableName: string]: string }): void; | ||
/** | ||
* Contribution ids of core DevOps services which can be obtained from DevOps.getService | ||
*/ | ||
export const enum CommonServiceIds { | ||
/** | ||
* Service for interacting with the host window's navigation (URLs, new windows, etc.) | ||
*/ | ||
HostNavigationService = "ms.vss-features.host-navigation-service", | ||
/** | ||
* Service for opening dialogs in the host frame | ||
*/ | ||
HostDialogService = "ms.vss-features.host-dialog-service", | ||
/** | ||
* Service for opening panels in the host frame | ||
*/ | ||
HostPanelService = "ms.vss-features.host-panel-service", | ||
/** | ||
* Service for interacting with the extension data service | ||
*/ | ||
ExtensionDataService = "ms.vss-features.extension-data-service", | ||
/** | ||
* Exposes project-related information from the current page | ||
*/ | ||
ProjectPageService = "ms.vss-tfs-web.tfs-page-data-service", | ||
/** | ||
* Service for showing global message banners at the top of the page | ||
*/ | ||
GlobalMessagesService = "ms.vss-tfs-web.tfs-global-messages-service" | ||
} | ||
/** | ||
* Service for interacting with the host window's navigation (URLs, new windows, etc.) | ||
*/ | ||
export interface IHostNavigationService { | ||
/** | ||
* Add a callback to be invoked each time the hash navigation has changed | ||
* | ||
* @param callback Method invoked on each navigation hash change | ||
*/ | ||
onHashChanged(callback: (hash: string) => void): void; | ||
/** | ||
* Gets the current hash. | ||
*/ | ||
getHash(): Promise<string>; | ||
/** | ||
* Sets the provided hash from the hosted content. | ||
*/ | ||
setHash(hash: string): void; | ||
/** | ||
* Replace existing hash with the provided hash from the hosted content. | ||
*/ | ||
replaceHash(hash: string): void; | ||
/** | ||
* Update the host document's title (appears as the browser tab title). | ||
* | ||
* @param title The new title of the window | ||
*/ | ||
setDocumentTitle(title: string): void; | ||
/** | ||
* Reloads the parent frame | ||
*/ | ||
reload(): void; | ||
/** | ||
* Navigate the parent page to the specified url | ||
* | ||
* @param url Url to navigate to | ||
*/ | ||
navigate(url: string): void; | ||
/** | ||
* Open a new window to the specified url | ||
* | ||
* @param url Url of the new window | ||
* @param features Comma-separated list of features/specs sent as the 3rd parameter to window.open. For example: "height=400,width=400". | ||
*/ | ||
openNewWindow(url: string, features: string): void; | ||
} | ||
/** | ||
* Options for showing host dialogs | ||
*/ | ||
export interface IDialogOptions<TResult> { | ||
/** | ||
* Dialog title | ||
*/ | ||
title?: string; | ||
/** | ||
* Callback invoked when the dialog is closed | ||
*/ | ||
onClose?: (result: TResult | undefined) => void; | ||
} | ||
/** | ||
* Options for showing a message dialog | ||
*/ | ||
export interface IMessageDialogOptions extends IDialogOptions<boolean> { | ||
/** | ||
* If true, show the cancel button | ||
*/ | ||
showCancel?: boolean; | ||
/** | ||
* Custom text for the OK button | ||
*/ | ||
okText?: string; | ||
/** | ||
* Custom text for the Cancel button | ||
*/ | ||
cancelText?: string; | ||
} | ||
/** | ||
* Service for external content to show dialogs in the host frame | ||
*/ | ||
export interface IHostDialogService { | ||
/** | ||
* Open a dialog in the host frame, showing custom external content | ||
* | ||
* @param contentContributionId Id of the dialog content contribution that specifies the content to display in the dialog. | ||
* @param options Dialog options | ||
*/ | ||
openCustomDialog: <TResult>(contentContributionId: string, options?: IDialogOptions<TResult>) => void; | ||
/** | ||
* Open a dialog in the host frame, showing the specified text message, an OK and optional Cancel button | ||
* | ||
* @param message Dialog message text | ||
* @param options Dialog options | ||
*/ | ||
openMessageDialog: (message: string, options?: IMessageDialogOptions) => void; | ||
} | ||
/** | ||
* Size (width) options for panel | ||
*/ | ||
export const enum PanelSize { | ||
Small = 0, | ||
Medium = 1, | ||
Large = 2, | ||
} | ||
/** | ||
* Options for showing panels | ||
*/ | ||
export interface IPanelOptions<TResult> { | ||
/** | ||
* Callback invoked when the dialog is closed | ||
*/ | ||
onClose?: (result: TResult | undefined) => void; | ||
/** | ||
* The panel title you want to display. | ||
*/ | ||
title?: string; | ||
/** | ||
* Optional, description of panel. | ||
*/ | ||
description?: string; | ||
/** | ||
* Size of the panel. | ||
* @default PanelSize.Medium | ||
*/ | ||
size?: PanelSize; | ||
} | ||
/** | ||
* Service for external content to show a panel in the host frame | ||
*/ | ||
export interface IHostPanelService { | ||
/** | ||
* Open a panel in the host frame, showing custom external content | ||
* | ||
* @param contentContributionId Id of the panel content contribution that specifies the content to display in the panel. | ||
* @param options Panel display options | ||
*/ | ||
openPanel: <TResult>(contentContributionId: string, options: IPanelOptions<TResult>) => void; | ||
} | ||
/** | ||
* Interface for options that can be supplied with document actions | ||
*/ | ||
export interface IDocumentOptions { | ||
/** | ||
* The scope of where the document is stored. Can be Default or User. | ||
*/ | ||
scopeType?: string; | ||
/** | ||
* The value of the scope where the document is stored. Can be Current or Me. | ||
*/ | ||
scopeValue?: string; | ||
/** | ||
* The default value to return when using getValue(). If the document has no value, | ||
* this value will be used instead. | ||
*/ | ||
defaultValue?: any; | ||
} | ||
/** | ||
* Represents a single collection for extension data documents | ||
*/ | ||
export interface ExtensionDataCollection { | ||
/** | ||
* The name of the collection | ||
*/ | ||
collectionName: string; | ||
/** | ||
* A list of documents belonging to the collection | ||
*/ | ||
documents: any[]; | ||
/** | ||
* The type of the collection's scope, such as Default or User | ||
*/ | ||
scopeType: string; | ||
/** | ||
* The value of the collection's scope, such as Current or Me | ||
*/ | ||
scopeValue: string; | ||
} | ||
export interface IExtensionDataManager { | ||
/** | ||
* Returns a promise for retrieving a setting at the provided key and scope | ||
* | ||
* @param key The key to retrieve a value for | ||
* @param documentOptions Extension document options, the default scope value is account-wide | ||
*/ | ||
getValue<T>(key: string, documentOptions?: IDocumentOptions): Promise<T>; | ||
/** | ||
* Returns a promise for saving a setting at the provided key and scope | ||
* | ||
* @param key The key to save a value for | ||
* @param value The value to save | ||
* @param documentOptions Extension document options, the default scope value is account-wide | ||
*/ | ||
setValue<T>(key: string, value: T, documentOptions?: IDocumentOptions): Promise<T>; | ||
/** | ||
* Returns a promise for getting a document with the provided id in the provided collection | ||
* | ||
* @param collectionName The name of the collection where the document lives | ||
* @param id The id of the document in the collection | ||
* @param documentOptions Extension document options, the default scope value is account-wide | ||
*/ | ||
getDocument(collectionName: string, id: string, documentOptions?: IDocumentOptions): Promise<any>; | ||
/** | ||
* Returns a promise for getting all of the documents in the provided collection | ||
* | ||
* @param collectionName The name of the collection where the document lives | ||
* @param documentOptions Extension document options, the default scope value is account-wide | ||
*/ | ||
getDocuments(collectionName: string, documentOptions?: IDocumentOptions): Promise<any[]>; | ||
/** | ||
* Returns a promise for creating a document in the provided collection | ||
* | ||
* @param collectionName The name of the collection where the document lives | ||
* @param doc The document to store | ||
* @param documentOptions Extension document options, the default scope value is account-wide | ||
*/ | ||
createDocument(collectionName: string, doc: any, documentOptions?: IDocumentOptions): Promise<any>; | ||
/** | ||
* Returns a promise for setting a document in the provided collection | ||
* Creates the document if it does not exist, otherwise updates the existing document with the id provided | ||
* | ||
* @param collectionName The name of the collection where the document lives | ||
* @param doc The document to store | ||
* @param documentOptions Extension document options, the default scope value is account-wide | ||
*/ | ||
setDocument(collectionName: string, doc: any, documentOptions?: IDocumentOptions): Promise<any>; | ||
/** | ||
* Returns a promise for updating a document in the provided collection | ||
* A document with the id provided must exist | ||
* | ||
* @param collectionName The name of the collection where the document lives | ||
* @param doc The document to store | ||
* @param documentOptions Extension document options, the default scope value is account-wide | ||
*/ | ||
updateDocument(collectionName: string, doc: any, documentOptions?: IDocumentOptions): Promise<any>; | ||
/** | ||
* Returns a promise for deleting the document at the provided scope, collection and id | ||
* | ||
* @param collectionName The name of the collection where the document lives | ||
* @param id The id of the document in the collection | ||
* @param documentOptions Extension document options, the default scope value is account-wide | ||
*/ | ||
deleteDocument(collectionName: string, id: string, documentOptions?: IDocumentOptions): Promise<void>; | ||
/** | ||
* Returns a promise for querying a set of collections | ||
* | ||
* @param collections The list of collections to query. Assumes Default Scope Type and Current Scope Value | ||
*/ | ||
queryCollectionsByName(collectionNames: string[]): Promise<ExtensionDataCollection[]>; | ||
/** | ||
* Returns a promise for querying a set of collections | ||
* | ||
* @param collections The list of collections to query. Each collection will contain its collectionName, scopeType, and scopeValue | ||
*/ | ||
queryCollections(collections: ExtensionDataCollection[]): Promise<ExtensionDataCollection[]>; | ||
} | ||
export interface IExtensionDataService { | ||
/** | ||
* Gets a class that can be used to manage extension data. | ||
* | ||
* @param extensionId Id of the extension (publisher.extension) | ||
* @param accessToken Access token to use for the extension | ||
*/ | ||
getExtensionDataManager(extensionId: string, accessToken: string): Promise<IExtensionDataManager>; | ||
} | ||
export interface IProjectInfo { | ||
/** | ||
* Unique identifier (GUID) of the project | ||
*/ | ||
id: string; | ||
/** | ||
* Name of the project | ||
*/ | ||
name: string; | ||
} | ||
export interface IProjectPageService { | ||
/** | ||
* Gets the project associated with the current page | ||
*/ | ||
getProject(): Promise<IProjectInfo>; | ||
} | ||
export interface IGlobalMessageLink { | ||
/** | ||
* Hyperlink text | ||
*/ | ||
name: string; | ||
/** | ||
* Url of the link target | ||
*/ | ||
href: string; | ||
} | ||
export const enum MessageBannerLevel { | ||
info = 0, | ||
warning = 1, | ||
error = 2, | ||
success = 3 | ||
} | ||
export interface IGlobalMessageBanner { | ||
/** | ||
* banner level (controls the background and icon of the banner) | ||
*/ | ||
level?: MessageBannerLevel; | ||
/** | ||
* Banner message. Ignored if messageFormat is also provided | ||
*/ | ||
message?: string; | ||
/** | ||
* Banner message format string. Arguments (like {0}, {1} are filled in with hyperlinks supplied in messageLinks) | ||
*/ | ||
messageFormat?: string; | ||
/** | ||
* Links to supply to the format arguments in `messageFormat` | ||
*/ | ||
messageLinks?: IGlobalMessageLink[]; | ||
} | ||
export interface IGlobalMessagesService { | ||
/** | ||
* Sets the currently displayed global message banner | ||
* | ||
* @param banner The message banner to display | ||
*/ | ||
setGlobalMessageBanner(banner: IGlobalMessageBanner): void | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
0
0
1
71492
7
1233