UNPKG

azure-devops-extension-sdk

Version:
263 lines (260 loc) 8.86 kB
import { channelManager } from './XDM.js'; /** * Web SDK version number. Can be specified in an extension's set of demands like: vss-sdk-version/3.0 */ const sdkVersion = 4.0; const global = window; if (global._AzureDevOpsSDKVersion) { console.error("The AzureDevOps SDK is already loaded. Only one version of this module can be loaded in a given document."); } global._AzureDevOpsSDKVersion = sdkVersion; /** * DevOps host level */ var HostType; (function (HostType) { HostType[HostType["Unknown"] = 0] = "Unknown"; /** * The Deployment host */ HostType[HostType["Deployment"] = 1] = "Deployment"; /** * The Enterprise host */ HostType[HostType["Enterprise"] = 2] = "Enterprise"; /** * The organization host */ HostType[HostType["Organization"] = 4] = "Organization"; })(HostType || (HostType = {})); const hostControlId = "DevOps.HostControl"; const serviceManagerId = "DevOps.ServiceManager"; const parentChannel = channelManager.addChannel(window.parent); let teamContext; let webContext; let hostPageContext; let extensionContext; let initialConfiguration; let initialContributionId; let userContext; let hostContext; let themeElement; let resolveReady; const readyPromise = new Promise((resolve) => { resolveReady = resolve; }); /** * Register a method so that the host frame can invoke events */ function dispatchEvent(eventName, params) { const global = window; let evt; if (typeof global.CustomEvent === "function") { evt = new global.CustomEvent(eventName, params); } else { params = params || { bubbles: false, cancelable: false }; evt = document.createEvent('CustomEvent'); evt.initCustomEvent(eventName, params.bubbles, params.cancelable, params.detail); } window.dispatchEvent(evt); } parentChannel.getObjectRegistry().register("DevOps.SdkClient", { dispatchEvent: dispatchEvent }); /** * Initiates the handshake with the host window. * * @param options - Initialization options for the extension. */ function init(options) { return new Promise((resolve) => { const initOptions = { ...options, sdkVersion }; parentChannel.invokeRemoteMethod("initialHandshake", hostControlId, [initOptions]).then((handshakeData) => { const context = handshakeData.context; hostPageContext = context.pageContext; webContext = hostPageContext ? hostPageContext.webContext : undefined; teamContext = webContext ? webContext.team : undefined; initialConfiguration = handshakeData.initialConfig || {}; initialContributionId = handshakeData.contributionId; extensionContext = context.extension; userContext = context.user; hostContext = context.host; if (handshakeData.themeData) { applyTheme(handshakeData.themeData); window.addEventListener("themeChanged", (ev) => { applyTheme(ev.detail.data); }); } resolveReady(); resolve(); }); }); } /** * 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. */ async function ready() { return readyPromise; } /** * Notifies the host that the extension successfully loaded (stop showing the loading indicator) */ function notifyLoadSucceeded() { return parentChannel.invokeRemoteMethod("notifyLoadSucceeded", hostControlId); } /** * Notifies the host that the extension failed to load */ function notifyLoadFailed(e) { return parentChannel.invokeRemoteMethod("notifyLoadFailed", hostControlId, [e]); } function getWaitForReadyError(method) { return `Attempted to call ${method}() before init() was complete. Wait for init to complete or place within a ready() callback.`; } /** * Get the configuration data passed in the initial handshake from the parent frame */ function getConfiguration() { if (!initialConfiguration) { throw new Error(getWaitForReadyError("getConfiguration")); } return initialConfiguration; } /** * Gets the information about the contribution that first caused this extension to load. */ function getContributionId() { if (!initialContributionId) { throw new Error(getWaitForReadyError("getContributionId")); } return initialContributionId; } /** * Gets information about the current user */ function getUser() { if (!userContext) { throw new Error(getWaitForReadyError("getUser")); } return userContext; } /** * Gets information about the host (i.e. an Azure DevOps organization) that the page is targeting */ function getHost() { if (!hostContext) { throw new Error(getWaitForReadyError("getHost")); } return hostContext; } /** * Get the context about the extension that owns the content that is being hosted */ function getExtensionContext() { if (!extensionContext) { throw new Error(getWaitForReadyError("getExtensionContext")); } return extensionContext; } /** * Gets information about the team that the page is targeting */ function getTeamContext() { if (!teamContext) { throw new Error(getWaitForReadyError("getTeamContext")); } return teamContext; } /** * Get the context about the host page */ function getPageContext() { if (!hostPageContext) { throw new Error(getWaitForReadyError("getPageContext")); } return hostPageContext; } /** * Get the context about the web */ function getWebContext() { if (!webContext) { throw new Error(getWaitForReadyError("getWebContext")); } return webContext; } /** * 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 */ async function getService(contributionId) { return ready().then(() => { return parentChannel.invokeRemoteMethod("getService", serviceManagerId, [contributionId]); }); } /** * 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. */ function register(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 */ function unregister(instanceId) { parentChannel.getObjectRegistry().unregister(instanceId); } /** * Fetch an access token which will allow calls to be made to other DevOps services */ async function getAccessToken() { return parentChannel.invokeRemoteMethod("getAccessToken", hostControlId).then((tokenObj) => { return tokenObj.token; }); } /** * Fetch an token which can be used to identify the current user */ async function getAppToken() { return parentChannel.invokeRemoteMethod("getAppToken", hostControlId).then((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 */ function resize(width, height) { const body = document.body; if (body) { const newWidth = typeof width === "number" ? width : (body ? body.scrollWidth : undefined); const newHeight = typeof height === "number" ? height : (body ? body.scrollHeight : undefined); parentChannel.invokeRemoteMethod("resize", hostControlId, [newWidth, newHeight]); } } /** * Applies theme variables to the current document */ function applyTheme(themeData) { if (!themeElement) { themeElement = document.createElement("style"); themeElement.type = "text/css"; document.head.appendChild(themeElement); } const cssVariables = []; if (themeData) { for (const varName in themeData) { cssVariables.push("--" + varName + ": " + themeData[varName]); } } themeElement.innerText = ":root { " + cssVariables.join("; ") + " } body { color: var(--text-primary-color) }"; dispatchEvent("themeApplied", { detail: themeData }); } export { HostType, applyTheme, getAccessToken, getAppToken, getConfiguration, getContributionId, getExtensionContext, getHost, getPageContext, getService, getTeamContext, getUser, getWebContext, init, notifyLoadFailed, notifyLoadSucceeded, ready, register, resize, sdkVersion, unregister }; //# sourceMappingURL=SDK.js.map