344 lines
16 KiB
JavaScript
344 lines
16 KiB
JavaScript
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
// Licensed under the MIT license.
|
||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
|
});
|
||
|
};
|
||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||
|
exports.waitUntilPackagerIsRunning = exports.waitUntilDevServerIsRunning = exports.waitUntil = exports.startDebugging = exports.runPackager = exports.runNodeDebugger = exports.runDevServer = exports.parsePlatform = exports.parseDebuggingMethod = exports.isPackagerRunning = exports.isDevServerRunning = exports.Platform = exports.AppType = void 0;
|
||
|
const AdmZip = require("adm-zip");
|
||
|
const fetch = require("node-fetch");
|
||
|
const fs = require("fs");
|
||
|
const fspath = require("path");
|
||
|
const devCerts = require("office-addin-dev-certs");
|
||
|
const devSettings = require("office-addin-dev-settings");
|
||
|
const os = require("os");
|
||
|
const office_addin_dev_settings_1 = require("office-addin-dev-settings");
|
||
|
const office_addin_manifest_1 = require("office-addin-manifest");
|
||
|
const nodeDebugger = require("office-addin-node-debugger");
|
||
|
const debugInfo = require("./debugInfo");
|
||
|
const port_1 = require("./port");
|
||
|
const process_1 = require("./process");
|
||
|
const defaults_1 = require("./defaults");
|
||
|
const office_addin_usage_data_1 = require("office-addin-usage-data");
|
||
|
/* global process, console, setTimeout */
|
||
|
var AppType;
|
||
|
(function (AppType) {
|
||
|
AppType["Desktop"] = "desktop";
|
||
|
AppType["Web"] = "web";
|
||
|
})(AppType = exports.AppType || (exports.AppType = {}));
|
||
|
var Platform;
|
||
|
(function (Platform) {
|
||
|
Platform["Android"] = "android";
|
||
|
Platform["Desktop"] = "desktop";
|
||
|
Platform["iOS"] = "ios";
|
||
|
Platform["MacOS"] = "macos";
|
||
|
Platform["Win32"] = "win32";
|
||
|
Platform["Web"] = "web";
|
||
|
})(Platform = exports.Platform || (exports.Platform = {}));
|
||
|
function defaultDebuggingMethod() {
|
||
|
return office_addin_dev_settings_1.DebuggingMethod.Direct;
|
||
|
}
|
||
|
function delay(milliseconds) {
|
||
|
return new Promise((resolve) => {
|
||
|
setTimeout(resolve, milliseconds);
|
||
|
});
|
||
|
}
|
||
|
function isDevServerRunning(port) {
|
||
|
return __awaiter(this, void 0, void 0, function* () {
|
||
|
// isPortInUse(port) will return false when webpack-dev-server is running.
|
||
|
// it should be fixed, but for now, use getProcessIdsForPort(port)
|
||
|
const processIds = yield (0, port_1.getProcessIdsForPort)(port);
|
||
|
const isRunning = processIds.length > 0;
|
||
|
return isRunning;
|
||
|
});
|
||
|
}
|
||
|
exports.isDevServerRunning = isDevServerRunning;
|
||
|
function isPackagerRunning(statusUrl) {
|
||
|
return __awaiter(this, void 0, void 0, function* () {
|
||
|
const statusRunningResponse = `packager-status:running`;
|
||
|
try {
|
||
|
const response = yield fetch.default(statusUrl);
|
||
|
console.log(`packager: ${response.status} ${response.statusText}`);
|
||
|
const text = yield response.text();
|
||
|
console.log(`packager: ${text}`);
|
||
|
return statusRunningResponse === text;
|
||
|
}
|
||
|
catch (err) {
|
||
|
return false;
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
exports.isPackagerRunning = isPackagerRunning;
|
||
|
function parseDebuggingMethod(text) {
|
||
|
switch (text) {
|
||
|
case "direct":
|
||
|
return office_addin_dev_settings_1.DebuggingMethod.Direct;
|
||
|
case "proxy":
|
||
|
return office_addin_dev_settings_1.DebuggingMethod.Proxy;
|
||
|
default:
|
||
|
return undefined;
|
||
|
}
|
||
|
}
|
||
|
exports.parseDebuggingMethod = parseDebuggingMethod;
|
||
|
function parsePlatform(text) {
|
||
|
if (text === AppType.Desktop) {
|
||
|
text = process.platform;
|
||
|
}
|
||
|
switch (text) {
|
||
|
case "android":
|
||
|
return Platform.Android;
|
||
|
case "darwin":
|
||
|
return Platform.MacOS;
|
||
|
case "ios":
|
||
|
return Platform.iOS;
|
||
|
case "macos":
|
||
|
return Platform.MacOS;
|
||
|
case "web":
|
||
|
return Platform.Web;
|
||
|
case "win32":
|
||
|
return Platform.Win32;
|
||
|
default:
|
||
|
throw new office_addin_usage_data_1.ExpectedError(`The current platform is not supported: ${text}`);
|
||
|
}
|
||
|
}
|
||
|
exports.parsePlatform = parsePlatform;
|
||
|
function runDevServer(commandLine, port) {
|
||
|
return __awaiter(this, void 0, void 0, function* () {
|
||
|
if (commandLine) {
|
||
|
// if the dev server is running
|
||
|
if (port !== undefined && (yield isDevServerRunning(port))) {
|
||
|
console.log(`The dev server is already running on port ${port}.`);
|
||
|
}
|
||
|
else {
|
||
|
// On non-Windows platforms, prompt for installing the dev certs before starting the dev server.
|
||
|
// This is a workaround for the fact that the detached process does not show a window on Mac,
|
||
|
// therefore the user cannot enter the password when prompted.
|
||
|
if (process.platform !== "win32") {
|
||
|
if (!devCerts.verifyCertificates()) {
|
||
|
yield devCerts.ensureCertificatesAreInstalled();
|
||
|
}
|
||
|
}
|
||
|
// start the dev server
|
||
|
console.log(`Starting the dev server... (${commandLine})`);
|
||
|
const devServerProcess = (0, process_1.startDetachedProcess)(commandLine);
|
||
|
yield debugInfo.saveDevServerProcessId(devServerProcess.pid);
|
||
|
if (port !== undefined) {
|
||
|
// wait until the dev server is running
|
||
|
const isRunning = yield waitUntilDevServerIsRunning(port);
|
||
|
if (isRunning) {
|
||
|
console.log(`The dev server is running on port ${port}. Process id: ${devServerProcess.pid}`);
|
||
|
}
|
||
|
else {
|
||
|
throw new Error(`The dev server is not running on port ${port}.`);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
exports.runDevServer = runDevServer;
|
||
|
function runNodeDebugger(host, port) {
|
||
|
return __awaiter(this, void 0, void 0, function* () {
|
||
|
nodeDebugger.run(host, port);
|
||
|
console.log("The node debugger is running.");
|
||
|
});
|
||
|
}
|
||
|
exports.runNodeDebugger = runNodeDebugger;
|
||
|
function runPackager(commandLine, host = "localhost", port = "8081") {
|
||
|
return __awaiter(this, void 0, void 0, function* () {
|
||
|
if (commandLine) {
|
||
|
const packagerUrl = `http://${host}:${port}`;
|
||
|
const statusUrl = `${packagerUrl}/status`;
|
||
|
// if the packager is running
|
||
|
if (yield isPackagerRunning(statusUrl)) {
|
||
|
console.log(`The packager is already running. ${packagerUrl}`);
|
||
|
}
|
||
|
else {
|
||
|
// start the packager
|
||
|
console.log(`Starting the packager... (${commandLine})`);
|
||
|
yield (0, process_1.startDetachedProcess)(commandLine);
|
||
|
// wait until the packager is running
|
||
|
if (yield waitUntilPackagerIsRunning(statusUrl)) {
|
||
|
console.log(`The packager is running. ${packagerUrl}`);
|
||
|
}
|
||
|
else {
|
||
|
throw new Error(`The packager is not running. ${packagerUrl}`);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
exports.runPackager = runPackager;
|
||
|
/**
|
||
|
* Start debugging
|
||
|
* @param options startDebugging options.
|
||
|
*/
|
||
|
function startDebugging(manifestPath, options) {
|
||
|
var _a, _b, _c;
|
||
|
return __awaiter(this, void 0, void 0, function* () {
|
||
|
const { appType, app, debuggingMethod, sourceBundleUrlComponents, devServerCommandLine, devServerPort, packagerCommandLine, packagerHost, packagerPort, enableDebugging, enableLiveReload, enableSideload, openDevTools, document, } = Object.assign(Object.assign({}, options), {
|
||
|
// Defaults when variable is undefined.
|
||
|
debuggingMethod: options.debuggingMethod || defaultDebuggingMethod(), enableDebugging: (_a = options.enableDebugging) !== null && _a !== void 0 ? _a : true, enableSideload: (_b = options.enableSideload) !== null && _b !== void 0 ? _b : true, enableLiveReload: (_c = options.enableLiveReload) !== null && _c !== void 0 ? _c : true });
|
||
|
try {
|
||
|
if (appType === undefined) {
|
||
|
throw new office_addin_usage_data_1.ExpectedError("Please specify the application type to debug.");
|
||
|
}
|
||
|
const isWindowsPlatform = process.platform === "win32";
|
||
|
const isDesktopAppType = appType === AppType.Desktop;
|
||
|
const isProxyDebuggingMethod = debuggingMethod === office_addin_dev_settings_1.DebuggingMethod.Proxy;
|
||
|
// live reload can only be enabled for the desktop app type
|
||
|
// when using proxy debugging and the packager
|
||
|
const canEnableLiveReload = isDesktopAppType && isProxyDebuggingMethod && !!packagerCommandLine;
|
||
|
// only use live reload if enabled and it can be enabled
|
||
|
const useLiveReload = enableLiveReload && canEnableLiveReload;
|
||
|
console.log(enableDebugging ? "Debugging is being started..." : "Starting without debugging...");
|
||
|
console.log(`App type: ${appType}`);
|
||
|
if (manifestPath.endsWith(".zip")) {
|
||
|
manifestPath = yield extractManifest(manifestPath);
|
||
|
}
|
||
|
const manifestInfo = yield office_addin_manifest_1.OfficeAddinManifest.readManifestFile(manifestPath);
|
||
|
if (!manifestInfo.id) {
|
||
|
throw new office_addin_usage_data_1.ExpectedError("Manifest does not contain the id for the Office Add-in.");
|
||
|
}
|
||
|
// enable loopback for Edge
|
||
|
if (isWindowsPlatform && parseInt(os.release(), 10) === 10) {
|
||
|
const name = isDesktopAppType ? "EdgeWebView" : "EdgeWebBrowser";
|
||
|
try {
|
||
|
yield devSettings.ensureLoopbackIsEnabled(name);
|
||
|
}
|
||
|
catch (err) {
|
||
|
// if add loopback exemption failed, report the error then continue
|
||
|
console.error(err);
|
||
|
console.warn("Failed to add loopback exemption.\nWill try to sideload the Office Add-in without the loopback exemption, but it might not load correctly from localhost.\n");
|
||
|
defaults_1.usageDataObject.reportException("startDebugging()", err, {
|
||
|
app: app,
|
||
|
document: document,
|
||
|
appType: appType,
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
// enable debugging
|
||
|
if (isDesktopAppType && isWindowsPlatform) {
|
||
|
yield devSettings.enableDebugging(manifestInfo.id, enableDebugging, debuggingMethod, openDevTools);
|
||
|
if (enableDebugging) {
|
||
|
console.log(`Enabled debugging for add-in ${manifestInfo.id}.`);
|
||
|
}
|
||
|
}
|
||
|
// enable live reload
|
||
|
if (isDesktopAppType && isWindowsPlatform) {
|
||
|
yield devSettings.enableLiveReload(manifestInfo.id, useLiveReload);
|
||
|
if (useLiveReload) {
|
||
|
console.log(`Enabled live-reload for add-in ${manifestInfo.id}.`);
|
||
|
}
|
||
|
}
|
||
|
// set source bundle url
|
||
|
if (isDesktopAppType && isWindowsPlatform) {
|
||
|
if (sourceBundleUrlComponents) {
|
||
|
yield devSettings.setSourceBundleUrl(manifestInfo.id, sourceBundleUrlComponents);
|
||
|
}
|
||
|
}
|
||
|
// Run packager and dev server at the same time and wait for them to complete.
|
||
|
let packagerPromise;
|
||
|
let devServerPromise;
|
||
|
if (packagerCommandLine && isProxyDebuggingMethod && isDesktopAppType) {
|
||
|
packagerPromise = runPackager(packagerCommandLine, packagerHost, packagerPort);
|
||
|
}
|
||
|
if (devServerCommandLine) {
|
||
|
devServerPromise = runDevServer(devServerCommandLine, devServerPort);
|
||
|
}
|
||
|
if (packagerPromise !== undefined) {
|
||
|
try {
|
||
|
yield packagerPromise;
|
||
|
}
|
||
|
catch (err) {
|
||
|
console.log(`Unable to start the packager. ${err}`);
|
||
|
}
|
||
|
}
|
||
|
if (devServerPromise !== undefined) {
|
||
|
try {
|
||
|
yield devServerPromise;
|
||
|
}
|
||
|
catch (err) {
|
||
|
console.log(`Unable to start the dev server. ${err}`);
|
||
|
}
|
||
|
}
|
||
|
if (enableDebugging && isProxyDebuggingMethod && isDesktopAppType) {
|
||
|
try {
|
||
|
yield runNodeDebugger();
|
||
|
}
|
||
|
catch (err) {
|
||
|
console.log(`Unable to start the node debugger. ${err}`);
|
||
|
}
|
||
|
}
|
||
|
if (enableSideload) {
|
||
|
try {
|
||
|
console.log(`Sideloading the Office Add-in...`);
|
||
|
yield (0, office_addin_dev_settings_1.sideloadAddIn)(manifestPath, app, true, appType, document);
|
||
|
}
|
||
|
catch (err) {
|
||
|
throw new Error(`Unable to sideload the Office Add-in. \n${err}`);
|
||
|
}
|
||
|
}
|
||
|
console.log(enableDebugging ? "Debugging started." : "Started.");
|
||
|
defaults_1.usageDataObject.reportSuccess("startDebugging()", {
|
||
|
app: app,
|
||
|
document: document,
|
||
|
appType: appType,
|
||
|
});
|
||
|
}
|
||
|
catch (err) {
|
||
|
defaults_1.usageDataObject.reportException("startDebugging()", err, {
|
||
|
app: app,
|
||
|
document: document,
|
||
|
appType: appType,
|
||
|
});
|
||
|
throw err;
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
exports.startDebugging = startDebugging;
|
||
|
function waitUntil(callback, retryCount, retryDelay) {
|
||
|
return __awaiter(this, void 0, void 0, function* () {
|
||
|
let done = yield callback();
|
||
|
while (!done && retryCount) {
|
||
|
--retryCount;
|
||
|
yield delay(retryDelay);
|
||
|
done = yield callback();
|
||
|
}
|
||
|
return done;
|
||
|
});
|
||
|
}
|
||
|
exports.waitUntil = waitUntil;
|
||
|
function waitUntilDevServerIsRunning(port, retryCount = 30, retryDelay = 1000) {
|
||
|
return __awaiter(this, void 0, void 0, function* () {
|
||
|
return waitUntil(() => __awaiter(this, void 0, void 0, function* () { return yield isDevServerRunning(port); }), retryCount, retryDelay);
|
||
|
});
|
||
|
}
|
||
|
exports.waitUntilDevServerIsRunning = waitUntilDevServerIsRunning;
|
||
|
function waitUntilPackagerIsRunning(statusUrl, retryCount = 30, retryDelay = 1000) {
|
||
|
return __awaiter(this, void 0, void 0, function* () {
|
||
|
return waitUntil(() => __awaiter(this, void 0, void 0, function* () { return yield isPackagerRunning(statusUrl); }), retryCount, retryDelay);
|
||
|
});
|
||
|
}
|
||
|
exports.waitUntilPackagerIsRunning = waitUntilPackagerIsRunning;
|
||
|
function extractManifest(zipPath) {
|
||
|
return __awaiter(this, void 0, void 0, function* () {
|
||
|
const targetPath = fspath.join(process.env.TEMP, "addinManifest");
|
||
|
const zip = new AdmZip(zipPath); // reading archives
|
||
|
zip.extractAllTo(targetPath, true); // overwrite
|
||
|
const manifestPath = fspath.join(targetPath, "manifest.json");
|
||
|
if (fs.existsSync(manifestPath)) {
|
||
|
return manifestPath;
|
||
|
}
|
||
|
else {
|
||
|
throw new Error(`The zip file '${zipPath}' does not contain a "manifest.json" file`);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
//# sourceMappingURL=start.js.map
|