pcf-scripts
Version:
This package contains a module for building PowerApps Component Framework (PCF) controls. See project homepage how to install.
105 lines (103 loc) • 5.58 kB
JavaScript
;
// Copyright (C) Microsoft Corporation. All rights reserved.
Object.defineProperty(exports, "__esModule", { value: true });
exports.CreateOutputTask = void 0;
const fs = require("fs-extra");
const path = require("node:path");
const constants = require("../constants");
const diagnosticMessages_generated_1 = require("../diagnosticMessages.generated");
const locale_1 = require("../generated/locale");
const manifestProcessor_1 = require("../manifestProcessor");
class CreateOutputTask {
constructor() {
this._options = {};
}
getDescription() {
return (0, locale_1.translate)(diagnosticMessages_generated_1.strings.task_generate_build_outputs.key);
}
setOptions(options) {
this._options = { ...this._options, ...options };
}
run(context) {
const outDir = context.getOutDir();
if (!outDir) {
context.getDiagnostic().push(diagnosticMessages_generated_1.strings.buildconfig_no_outdir);
return Promise.reject(new Error());
}
return context.mapControls((control) => {
return this.copyResourcesToOutdir(control, outDir, context.getDiagnostic());
});
}
// Copy all control's resources (except code) and preview-image (if present) to output folder; process names if necessary
copyResourcesToOutdir(context, outDir, diag) {
const controlOutputDir = path.join(outDir, context.getControlFolderName());
fs.ensureDirSync(controlOutputDir);
const controlPath = context.getControlPath();
const processor = new manifestProcessor_1.ManifestProcessor(context.getControlManifest().getManifestData(), controlPath, diag);
const result = processor.getProcessedManifest();
if (diag.hasErrors()) {
return Promise.reject(new Error());
}
const processedManifest = result.processedManifest;
const resourcesMap = result.resourcesMap;
const processedXmlString = processedManifest.getManifestXmlString();
const processedManifestPath = path.join(controlOutputDir, constants.PROCESSED_MANIFEST_FILE_NAME);
fs.writeFileSync(processedManifestPath, processedXmlString);
let relativePaths = context.getControlManifest().getResources(false);
const previewImagePath = context.getControlManifest().getPreviewImagePath();
const designMapFilePath = context.getControlManifest().getDesignMapsFilePath();
if (previewImagePath) {
relativePaths = relativePaths.concat(previewImagePath);
}
if (designMapFilePath) {
const themingFileDestination = path.resolve(controlOutputDir, path.dirname(designMapFilePath), path.basename(designMapFilePath));
fs.ensureFileSync(themingFileDestination);
const themingFileSource = path.resolve(context.getControlPath(), designMapFilePath);
fs.copyFileSync(themingFileSource, themingFileDestination);
}
const copyResourcesResults = relativePaths.flatMap((relativePath) => {
const processedPath = resourcesMap[relativePath];
const desPath = path.join(controlOutputDir, processedPath);
fs.ensureDirSync(path.dirname(desPath));
const resourcePath = path.resolve(context.getControlPath(), relativePath);
const resxEndMatch = /\.\d{4}\.resx$/i;
if (!fs.existsSync(resourcePath)) {
diag.pushA(diagnosticMessages_generated_1.strings.resource_file_not_found, [resourcePath]);
return Promise.reject(new Error());
}
if (fs.statSync(resourcePath).isDirectory()) {
diag.pushA(diagnosticMessages_generated_1.strings.path_must_be_file, [relativePath]);
return Promise.reject(new Error());
}
// Control loading has special logic where only one resx file needs to be referenced and if there are other unreferenced
// resx files with a different lcid, copy them as well
if (resxEndMatch.test(resourcePath)) {
const baseNameNoExt = path.basename(resourcePath).replace(resxEndMatch, "");
const dirFiles = fs.readdirSync(path.dirname(resourcePath));
const unreferencedRegexFiles = dirFiles.filter((x) => {
if (
// basenames - xxxx.resx don't match
x.replace(resxEndMatch, "").toUpperCase() !== baseNameNoExt.toUpperCase() ||
// file already referenced by manifest so don't copy again
resourcesMap[relativePath.replace(path.basename(relativePath), path.basename(x))]) {
return false;
}
return true;
});
const fileMap = unreferencedRegexFiles
// add all unreferenced basename.xxxx.resx files
.map((x) => ({
source: resourcePath.replace(path.basename(resourcePath), path.basename(x)),
dest: desPath.replace(path.basename(desPath), path.basename(x)),
}))
// original resx file
.concat({ source: resourcePath, dest: desPath });
return fileMap.map(({ source, dest }) => fs.copyFile(source, dest));
}
return fs.copyFile(resourcePath, desPath);
});
return Promise.all(copyResourcesResults);
}
}
exports.CreateOutputTask = CreateOutputTask;
//# sourceMappingURL=outputTask.js.map