pcf-scripts
Version:
This package contains a module for building PowerApps Component Framework (PCF) controls. See project homepage how to install.
144 lines (142 loc) • 5.83 kB
JavaScript
;
// Copyright (C) Microsoft Corporation. All rights reserved.
Object.defineProperty(exports, "__esModule", { value: true });
exports.PCFFileWatcher = void 0;
const chokidar = require("chokidar");
const path = require("path");
const constants = require("./constants");
const designTypesTask_1 = require("./tasks/designTypesTask");
const manifestTypesTask_1 = require("./tasks/manifestTypesTask");
const outputTask_1 = require("./tasks/outputTask");
const validateTask_1 = require("./tasks/validateTask");
class PCFFileWatcher {
constructor() {
this._isReady = false;
this._errorsExist = false;
}
// Returning promise is resolved only when watcher is ready. Mainly needed for testing purposes.
async start(context, watchBehavior) {
try {
const pathsToWatchArr = await this.getUpdatedPathsToWatch(context);
const pathsToWatch = pathsToWatchArr[0];
return new Promise((resolve, _reject) => {
this._watcher = chokidar
.watch(pathsToWatch, {
awaitWriteFinish: {
stabilityThreshold: 2000,
pollInterval: 100,
},
})
.on("ready", () => {
this._isReady = true;
return resolve("Watch is now ready");
})
.on("change", (filePath) => {
if (!this._isReady) {
return;
}
if (watchBehavior) {
watchBehavior(context);
}
else {
this.processFileChange(filePath, context).catch(() => context.getDiagnostic().flush(true));
}
});
});
}
catch {
context.getDiagnostic().flush(true);
return Promise.reject(new Error());
}
}
async getUpdatedPathsToWatch(context) {
const pathsToWatch = [];
return context.mapControls((control) => {
const manifestPath = path.resolve(control.getControlPath(), constants.MANIFEST_INPUT_FILE_NAME);
pathsToWatch.push(manifestPath);
const resourcePaths = control.getControlManifest().getResources(true);
for (const resourcePath of resourcePaths) {
pathsToWatch.push(path.resolve(control.getControlPath(), resourcePath));
}
return Promise.resolve(pathsToWatch);
});
}
async processFileChange(filePath, context) {
if (filePath.includes(constants.INDEX_FILE_NAME)) {
if (this._errorsExist) {
return Promise.reject(new Error());
}
return Promise.resolve();
}
else if (filePath.includes(constants.MANIFEST_INPUT_FILE_NAME)) {
return this.recompileWatchedFiles(context)
.then(() => {
this._errorsExist = false;
// eslint-disable-next-line promise/no-return-wrap
return Promise.resolve();
})
.catch(() => {
this._errorsExist = true;
// eslint-disable-next-line promise/no-return-wrap
return Promise.reject(new Error());
});
}
else {
const createOutputTask = new outputTask_1.CreateOutputTask();
return createOutputTask.run(context).catch(() => {
this._errorsExist = true;
// eslint-disable-next-line promise/no-return-wrap
return Promise.reject(new Error());
});
}
}
async recompileWatchedFiles(context) {
const diag = context.getDiagnostic();
context.getDiagnostic().clear();
return context
.mapControls((control) => {
return Promise.resolve(control.reloadManifest(diag));
})
.then(async () => {
const validateManifestTask = new validateTask_1.ValidateManifestTask();
const generateManifestTypesTask = new manifestTypesTask_1.GenerateManifestTypesTask();
const generateDesignTypesTask = new designTypesTask_1.GenerateDesignTypesTask();
const createOutputTask = new outputTask_1.CreateOutputTask();
await validateManifestTask.run(context);
await generateManifestTypesTask.run(context);
await generateDesignTypesTask.run(context);
await createOutputTask.run(context);
await this.updateWatchedPaths(context);
});
}
async updateWatchedPaths(context) {
const oldWatchedPaths = this.getPreviousPathsToWatch();
const newWatchedPathsArr = await this.getUpdatedPathsToWatch(context);
const newWatchedPaths = newWatchedPathsArr[0];
const unwatchPaths = [];
oldWatchedPaths.forEach((watchedPath) => {
if (!newWatchedPaths.includes(watchedPath)) {
unwatchPaths.push(watchedPath);
}
});
this._watcher?.unwatch(unwatchPaths);
this._watcher?.add(newWatchedPaths);
return Promise.resolve();
}
stop() {
if (!this._watcher) {
return;
}
void this._watcher.close();
}
getPreviousPathsToWatch() {
const watchedPathsObject = this._watcher?.getWatched();
if (!watchedPathsObject) {
return [];
}
const watchedPaths = Object.entries(watchedPathsObject).flatMap(([directoryPath, pathsArr]) => pathsArr.map((filePath) => path.join(directoryPath, filePath)));
return watchedPaths;
}
}
exports.PCFFileWatcher = PCFFileWatcher;
//# sourceMappingURL=pcfFileWatcher.js.map