279 lines
8.5 KiB
JavaScript
279 lines
8.5 KiB
JavaScript
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
/* global require, process, console */
|
|
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
const util = require("util");
|
|
const childProcess = require("child_process");
|
|
const hosts = ["excel", "onenote", "outlook", "powerpoint", "project", "word"];
|
|
|
|
if (process.argv.length <= 2) {
|
|
const hostList = hosts.map((host) => `'${host}'`).join(", ");
|
|
console.log("SYNTAX: convertToSingleHost.js <host> <manifestType> <projectName> <appId>");
|
|
console.log();
|
|
console.log(` host (required): Specifies which Office app will host the add-in: ${hostList}`);
|
|
console.log(` manifestType: Specify the type of manifest to use: 'xml' or 'json'. Defaults to 'xml'`);
|
|
console.log(` projectName: The name of the project (use quotes when there are spaces in the name). Defaults to 'My Office Add-in'`);
|
|
console.log(` appId: The id of the project or 'random' to generate one. Defaults to 'random'`);
|
|
console.log();
|
|
process.exit(1);
|
|
}
|
|
|
|
const host = process.argv[2];
|
|
const manifestType = process.argv[3];
|
|
const projectName = process.argv[4];
|
|
let appId = process.argv[5];
|
|
const testPackages = [
|
|
"@types/mocha",
|
|
"@types/node",
|
|
"mocha",
|
|
"office-addin-mock",
|
|
"office-addin-test-helpers",
|
|
"office-addin-test-server",
|
|
"ts-node",
|
|
];
|
|
const readFileAsync = util.promisify(fs.readFile);
|
|
const unlinkFileAsync = util.promisify(fs.unlink);
|
|
const writeFileAsync = util.promisify(fs.writeFile);
|
|
|
|
async function modifyProjectForSingleHost(host) {
|
|
if (!host) {
|
|
throw new Error("The host was not provided.");
|
|
}
|
|
if (!hosts.includes(host)) {
|
|
throw new Error(`'${host}' is not a supported host.`);
|
|
}
|
|
|
|
await convertProjectToSingleHost(host);
|
|
await updatePackageJsonForSingleHost(host);
|
|
await updateLaunchJsonFile(host);
|
|
}
|
|
|
|
async function convertProjectToSingleHost(host) {
|
|
// Copy host-specific manifest over manifest.xml
|
|
const manifestContent = await readFileAsync(`./manifest.${host}.xml`, "utf8");
|
|
await writeFileAsync(`./manifest.xml`, manifestContent);
|
|
|
|
// Copy host-specific office-document.ts over src/office-document.ts
|
|
const srcContent = await readFileAsync(`./src/taskpane/${host}.ts`, "utf8");
|
|
await writeFileAsync(`./src/taskpane/taskpane.ts`, srcContent);
|
|
|
|
// Delete all host-specific files
|
|
hosts.forEach(async function (host) {
|
|
await unlinkFileAsync(`./manifest.${host}.xml`);
|
|
await unlinkFileAsync(`./src/taskpane/${host}.ts`);
|
|
});
|
|
|
|
// Delete test folder
|
|
deleteFolder(path.resolve(`./test`));
|
|
|
|
// Delete the .github folder
|
|
deleteFolder(path.resolve(`./.github`));
|
|
|
|
// Delete CI/CD pipeline files
|
|
deleteFolder(path.resolve(`./.azure-devops`));
|
|
|
|
// Delete repo support files
|
|
await deleteSupportFiles();
|
|
}
|
|
|
|
async function updatePackageJsonForSingleHost(host) {
|
|
// Update package.json to reflect selected host
|
|
const packageJson = `./package.json`;
|
|
const data = await readFileAsync(packageJson, "utf8");
|
|
let content = JSON.parse(data);
|
|
|
|
// Update 'config' section in package.json to use selected host
|
|
content.config["app_to_debug"] = host;
|
|
|
|
// Remove 'engines' section
|
|
delete content.engines;
|
|
|
|
// Remove scripts that are unrelated to the selected host
|
|
Object.keys(content.scripts).forEach(function (key) {
|
|
if (key === "convert-to-single-host") {
|
|
delete content.scripts[key];
|
|
}
|
|
});
|
|
|
|
// Remove test-related scripts
|
|
Object.keys(content.scripts).forEach(function (key) {
|
|
if (key.includes("test")) {
|
|
delete content.scripts[key];
|
|
}
|
|
});
|
|
|
|
// Remove test-related packages
|
|
Object.keys(content.devDependencies).forEach(function (key) {
|
|
if (testPackages.includes(key)) {
|
|
delete content.devDependencies[key];
|
|
}
|
|
});
|
|
|
|
// Write updated JSON to file
|
|
await writeFileAsync(packageJson, JSON.stringify(content, null, 2));
|
|
}
|
|
|
|
async function updateLaunchJsonFile(host) {
|
|
// Remove unneeded configuration from launch.json
|
|
const launchJson = `.vscode/launch.json`;
|
|
const launchJsonContent = await readFileAsync(launchJson, "utf8");
|
|
let content = JSON.parse(launchJsonContent);
|
|
content.configurations = content.configurations.filter(function (config) {
|
|
return config.name.toLowerCase().startsWith(host);
|
|
});
|
|
|
|
await writeFileAsync(launchJson, JSON.stringify(content, null, 2));
|
|
}
|
|
|
|
function deleteFolder(folder) {
|
|
try {
|
|
if (fs.existsSync(folder)) {
|
|
fs.readdirSync(folder).forEach(function (file) {
|
|
const curPath = `${folder}/${file}`;
|
|
|
|
if (fs.lstatSync(curPath).isDirectory()) {
|
|
deleteFolder(curPath);
|
|
} else {
|
|
fs.unlinkSync(curPath);
|
|
}
|
|
});
|
|
fs.rmdirSync(folder);
|
|
}
|
|
} catch (err) {
|
|
throw new Error(`Unable to delete folder "${folder}".\n${err}`);
|
|
}
|
|
}
|
|
|
|
async function deleteSupportFiles() {
|
|
await unlinkFileAsync("CONTRIBUTING.md");
|
|
await unlinkFileAsync("LICENSE");
|
|
await unlinkFileAsync("README.md");
|
|
await unlinkFileAsync("SECURITY.md");
|
|
await unlinkFileAsync("./convertToSingleHost.js");
|
|
await unlinkFileAsync(".npmrc");
|
|
await unlinkFileAsync("package-lock.json");
|
|
}
|
|
|
|
async function deleteJSONManifestRelatedFiles() {
|
|
await unlinkFileAsync("assets/color.png");
|
|
await unlinkFileAsync("assets/outline.png");
|
|
}
|
|
|
|
async function deleteXMLManifestRelatedFiles() {
|
|
await unlinkFileAsync("manifest.xml");
|
|
}
|
|
|
|
async function updatePackageJsonForXMLManifest() {
|
|
const packageJson = `./package.json`;
|
|
const data = await readFileAsync(packageJson, "utf8");
|
|
let content = JSON.parse(data);
|
|
|
|
// Write updated JSON to file
|
|
await writeFileAsync(packageJson, JSON.stringify(content, null, 2));
|
|
}
|
|
|
|
async function updatePackageJsonForJSONManifest() {
|
|
const packageJson = `./package.json`;
|
|
const data = await readFileAsync(packageJson, "utf8");
|
|
let content = JSON.parse(data);
|
|
|
|
// Change manifest file name extension
|
|
content.scripts.start = "office-addin-debugging start manifest.json";
|
|
content.scripts.stop = "office-addin-debugging stop manifest.json";
|
|
content.scripts.validate = "office-addin-manifest validate manifest.json";
|
|
|
|
// Write updated JSON to file
|
|
await writeFileAsync(packageJson, JSON.stringify(content, null, 2));
|
|
}
|
|
|
|
async function updateTasksJsonFileForJSONManifest() {
|
|
const tasksJson = `.vscode/tasks.json`;
|
|
const data = await readFileAsync(tasksJson, "utf8");
|
|
let content = JSON.parse(data);
|
|
|
|
content.tasks.forEach(function (task) {
|
|
if (task.label.startsWith("Build")) {
|
|
task.dependsOn = ["Install"];
|
|
}
|
|
if (task.label === "Debug: Outlook Desktop") {
|
|
task.script = "start";
|
|
task.dependsOn = ["Check OS", "Install"];
|
|
}
|
|
});
|
|
|
|
const checkOSTask = {
|
|
label: "Check OS",
|
|
type: "shell",
|
|
windows: {
|
|
command: "echo 'Sideloading in Outlook on Windows is supported'",
|
|
},
|
|
linux: {
|
|
command: "echo 'Sideloading on Linux is not supported' && exit 1",
|
|
},
|
|
osx: {
|
|
command: "echo 'Sideloading in Outlook on Mac is not supported' && exit 1",
|
|
},
|
|
presentation: {
|
|
clear: true,
|
|
panel: "dedicated",
|
|
},
|
|
};
|
|
|
|
content.tasks.push(checkOSTask);
|
|
await writeFileAsync(tasksJson, JSON.stringify(content, null, 2));
|
|
}
|
|
|
|
async function updateWebpackConfigForJSONManifest() {
|
|
const webPack = `webpack.config.js`;
|
|
const webPackContent = await readFileAsync(webPack, "utf8");
|
|
const updatedContent = webPackContent.replace(".xml", ".json");
|
|
await writeFileAsync(webPack, updatedContent);
|
|
}
|
|
|
|
async function modifyProjectForJSONManifest() {
|
|
await updatePackageJsonForJSONManifest();
|
|
await updateWebpackConfigForJSONManifest();
|
|
await updateTasksJsonFileForJSONManifest();
|
|
await deleteXMLManifestRelatedFiles();
|
|
}
|
|
|
|
/**
|
|
* Modify the project so that it only supports a single host.
|
|
* @param host The host to support.
|
|
*/
|
|
modifyProjectForSingleHost(host).catch((err) => {
|
|
console.error(`Error modifying for single host: ${err instanceof Error ? err.message : err}`);
|
|
process.exitCode = 1;
|
|
});
|
|
|
|
let manifestPath = "manifest.xml";
|
|
|
|
if (host !== "outlook" || manifestType !== "json") {
|
|
// Remove things that are only relevant to JSON manifest
|
|
deleteJSONManifestRelatedFiles();
|
|
updatePackageJsonForXMLManifest();
|
|
} else {
|
|
manifestPath = "manifest.json";
|
|
modifyProjectForJSONManifest().catch((err) => {
|
|
console.error(`Error modifying for JSON manifest: ${err instanceof Error ? err.message : err}`);
|
|
process.exitCode = 1;
|
|
});
|
|
}
|
|
|
|
if (projectName) {
|
|
if (!appId) {
|
|
appId = "random";
|
|
}
|
|
|
|
// Modify the manifest to include the name and id of the project
|
|
const cmdLine = `npx office-addin-manifest modify ${manifestPath} -g ${appId} -d "${projectName}"`;
|
|
childProcess.exec(cmdLine, (error, stdout) => {
|
|
if (error) {
|
|
Promise.reject(stdout);
|
|
} else {
|
|
Promise.resolve();
|
|
}
|
|
});
|
|
}
|