organise
Version:
A solution to reference errors when organizing your project
128 lines (120 loc) • 4.29 kB
JavaScript
const { updateImports, updateExports } = require('./util');
const { EventEmitter } = require('events'),
chokidar = require('chokidar');
/**
*
* @class Watcher - The Event Handler for file changes,
* Looks for global file changes and updates the
* dirTree only for linked files.
*
*/
class Watcher extends EventEmitter {
/**
*
* Set up a single global watcher for getting all the move events and set
* individual fs watchers on files for rename events, then on any update,
* rebuild or update the dirTree and change the imports in the linked files
*
* @constructor - creates a globalWatcher (instance of chokidar watcher)
* and looks for file changes over the whole project dir.
*
* @param {Object} files - The AllFiles Object created by the @makeDirTree
*
*/
constructor(files) {
super();
this.files = files;
this.fileList = [];
this.globalWatcher = chokidar.watch('.', { ignored: [/node_modules/, /tree.json/], ignoreInitial: true });
this.watch();
}
/**
*
* @method watch - watches for updates of files that are linked,
* and emits @event update for recreating the dirTree
*
*/
watch() {
let eventList = [],
filesList = [];
this.globalWatcher.on('all', (e, f) => {
if (eventList.length === 0) {
setTimeout(async() => {
await this.updateFiles(eventList, filesList);
eventList = [];
filesList = [];
clearTimeout();
}, 500);
}
eventList.push(e);
filesList.push(f);
})
}
/**
* @method update
*
* @param {Object} newFiles - The Updated AllFiles
*
*/
update(newFiles) {
this.files = newFiles;
}
/**
* @method updateFiles
*
* @param {Array} events - The Array of All Events
* @param {Array} files - The Array of All Paths
*
*/
async updateFiles(events, files) {
let renameOrMove = false,
newPath = '';
for (let i = 0; i < events.length; i++) {
if (events[i] === 'add') {
if (events.length > 1) {
this.fileList.push(files[i]);
renameOrMove = true;
} else this.emit('update');
}
if (events[i] === 'unlink') {
if (renameOrMove) {
await this.updatePath(files[i], this.fileList.shift());
} else this.emit('update');
}
}
this.emit('update');
}
/**
* @method updatePath - Updates the paths of the reference links in the file
*
* @param {String} oldPath - The Old Path of the file
* @param {String} newPath - The New Path of the file
*
* @returns {Array}
*
*/
async updatePath(oldPath, newPath) {
oldPath = oldPath.replace('\\', '/');
newPath = newPath.replace('\\', '/');
console.log(`WHILE UPDATING PATHS OLD_PATH : ${oldPath}, NEW_PATH : ${newPath}`);
let promiseList = [];
oldPath = './' + oldPath;
newPath = './' + newPath;
for (let i of Object.keys(this.files)) {
this.files[i].path = this.files[i].path.replace('\\', '/');
if (this.files[i].path === oldPath) {
this.files[i].path = newPath;
this.files[i].name = newPath.slice(newPath.lastIndexOf('/') + 1);
oldPath = oldPath.slice(0, oldPath.lastIndexOf('.'));
newPath = newPath.slice(0, newPath.lastIndexOf('.'));
if (this.files[i].imports.length > 0) {
await updateImports(this.files[i], oldPath, newPath);
}
if (this.files[i].exports.length > 0) {
await updateExports(this.files, this.files[i], oldPath, newPath);
}
}
}
}
}
module.exports = Watcher;