@oasisdigital/ng-doc-portal-plugin
Version:
Nx plugin for adding the ng-doc-portal system to your nx workspace
186 lines • 8.55 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.DocPageLoadersCompiler = void 0;
const tslib_1 = require("tslib");
const devkit_1 = require("@nx/devkit");
const chalk_1 = require("chalk");
const chokidar_1 = require("chokidar");
const fast_glob_1 = require("fast-glob");
const rxjs_1 = require("rxjs");
const util_1 = require("./util");
const fs_1 = require("fs");
class DocPageLoadersCompiler {
constructor(configFileLocation, docPageLoadersFileLocation, silenced = false) {
this.configFileLocation = configFileLocation;
this.docPageLoadersFileLocation = docPageLoadersFileLocation;
this.silenced = silenced;
if (!(0, fs_1.existsSync)(this.configFileLocation)) {
throw new Error(`Could not find config file at ${this.configFileLocation}`);
}
const config = (0, devkit_1.readJsonFile)(this.configFileLocation);
let patterns = config.globPatterns;
if (!patterns && config.globPattern) {
patterns = [config.globPattern];
}
if (!patterns) {
throw new Error('No glob patterns detected in configuration file');
}
this.globPatterns = patterns;
}
runOnce() {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
const initialFileEvent = this.buildInitialFileEvent();
const handledFileEvents = this.handleFileEvents(initialFileEvent);
return yield (0, rxjs_1.firstValueFrom)(handledFileEvents);
});
}
watch() {
const fileEvents = (0, rxjs_1.concat)(this.buildInitialFileEvent(), this.buildWatcher());
const handledFileEvents = this.handleFileEvents(fileEvents).pipe((0, rxjs_1.shareReplay)(1));
handledFileEvents.pipe((0, rxjs_1.take)(1)).subscribe(() => {
console.log((0, chalk_1.blue)('Watching doc-portal files for changes...\n'));
});
return handledFileEvents;
}
handleFileEvents(obs) {
return obs.pipe((0, rxjs_1.concatMap)((event) => this.addPayloadToEvent(event)), (0, rxjs_1.filter)((fileEvent) => !!fileEvent), (0, rxjs_1.scan)(util_1.accumulatePayloads, new Array()), (0, rxjs_1.debounceTime)(500), (0, rxjs_1.map)((payloads) => this.detectAndHandleDuplicateTitles(payloads)), (0, rxjs_1.map)((eventPayloads) => eventPayloads.map((eventPayload) => (0, util_1.generateDocPageLoader)(eventPayload.filePath, eventPayload.title))), (0, rxjs_1.map)(util_1.wrapTypescriptBoilerplate), (0, rxjs_1.switchMap)((content) => (0, util_1.formatContent)(content)), (0, rxjs_1.switchMap)((content) => this.writeDynamicPageContentToFile(content)));
}
/**
* Build an Observable that emits the initial list of file paths.
* @private
*/
buildInitialFileEvent() {
this.log((0, chalk_1.blue)('Searching for component document page files...'));
const startTime = Date.now();
const patternStrings = (0, util_1.convertPatternOrGlobPatternArray)(this.globPatterns);
return (0, rxjs_1.from)((0, fast_glob_1.glob)(patternStrings, {
unique: true,
dot: true,
onlyFiles: true,
ignore: ['node_modules'],
})).pipe((0, rxjs_1.map)((filePaths) => ({ type: 'init', filePaths })), (0, rxjs_1.tap)(() => {
const endTime = Date.now();
this.log((0, chalk_1.green)(`Searching complete in ${endTime - startTime}ms\n`));
}));
}
/**
* Generate an Observable of the raw file events.
* @private
*/
buildWatcher() {
return new rxjs_1.Observable((observer) => {
const patternStrings = (0, util_1.convertPatternOrGlobPatternArray)(this.globPatterns);
const watcher = (0, chokidar_1.watch)(patternStrings, {
ignored: 'node_modules',
ignoreInitial: true,
}).on('all', (event, rawFilePath) => tslib_1.__awaiter(this, void 0, void 0, function* () {
observer.next(this.buildRawFileEvent(rawFilePath, event));
}));
return () => {
watcher.unwatch(patternStrings);
watcher.close();
};
});
}
/**
* Create the RawFileEvent from the chokidar event.
*
* @param rawFilePath The file that was modified
* @param event The type of chokidar change
* @private
*/
buildRawFileEvent(rawFilePath, event) {
const filePath = rawFilePath.replace(/\\/g, '/');
if (event === 'add' || event === 'addDir') {
this.log((0, chalk_1.green)(`${(0, util_1.timeNow)()} - ADDED - ${filePath}`));
return { type: 'add', filePath };
}
else if (event === 'unlink' || event === 'unlinkDir') {
this.log((0, chalk_1.red)(`${(0, util_1.timeNow)()} - DELETED - ${filePath}`));
return { type: 'unlink', filePath };
}
else {
this.log((0, chalk_1.yellow)(`${(0, util_1.timeNow)()} - CHANGED - ${filePath}`));
return { type: 'change', filePath };
}
}
/**
* Process a raw file event, adding loader string payloads.
*
* @param fileEvent The raw file event that describe which file(s)
* is affected and what is happening.
* @private
*/
addPayloadToEvent(fileEvent) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
try {
if (fileEvent.type === 'init') {
const payload = [];
this.log((0, chalk_1.blue)('Compiling component document page files...'));
const startTime = Number(new Date());
for (const filePath of fileEvent.filePaths) {
const title = yield (0, util_1.extractTitleFromDocPageFile)(filePath, this.globPatterns);
payload.push({ filePath, title });
}
const endTime = Number(new Date());
this.log((0, chalk_1.green)(`Finished compiling component document page files in ${endTime - startTime}ms\n`));
return Object.assign(Object.assign({}, fileEvent), { payload });
}
else if (fileEvent.type === 'add' || fileEvent.type === 'change') {
const startTime = Date.now();
const title = yield (0, util_1.extractTitleFromDocPageFile)(fileEvent.filePath, this.globPatterns);
const endTime = Date.now();
this.log((0, chalk_1.blue)(`${(0, util_1.timeNow)()} - COMPILE - recompiled in ${endTime - startTime}ms`));
return Object.assign(Object.assign({}, fileEvent), { title });
}
else {
return fileEvent;
}
}
catch (error) {
this.log((0, chalk_1.red)(`Unexpected error occurred while compiling...\n${error}`));
return null;
}
});
}
detectAndHandleDuplicateTitles(eventPayloads) {
let duplicatesDetected = false;
const titles = {};
for (const payload of eventPayloads) {
if (titles[payload.title] !== undefined) {
duplicatesDetected = true;
this.log((0, chalk_1.yellow)(`Duplicated title of "${payload.title}" detected in file '${payload.filePath}'`));
payload.title += ` ${++titles[payload.title]}`;
}
titles[payload.title] = 1;
}
if (duplicatesDetected) {
this.log((0, chalk_1.yellow)('\nPlease resolve duplicated titles before publishing!\n'));
}
return eventPayloads;
}
/**
* Generate a file to hold the loader content.
*
* @param content The loader content generated from our path files
* @private
*/
writeDynamicPageContentToFile(content) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
try {
(0, fs_1.writeFileSync)(this.docPageLoadersFileLocation, content);
}
catch (e) {
console.error(e);
this.log((0, chalk_1.red)(`\n\nUnexpected error occurred while generating doc-page-loaders.ts\n`));
}
});
}
log(message) {
if (!this.silenced) {
console.log(message);
}
}
}
exports.DocPageLoadersCompiler = DocPageLoadersCompiler;
//# sourceMappingURL=doc-page-loaders-compiler.js.map