"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const path_1 = tslib_1.__importDefault(require("path")); const chokidar_1 = tslib_1.__importDefault(require("chokidar")); const assert_1 = tslib_1.__importDefault(require("assert")); const events_1 = require("events"); const utils = tslib_1.__importStar(require("./utils")); const generator_1 = require("./generator"); const debug_1 = tslib_1.__importDefault(require("debug")); const debug = (0, debug_1.default)('egg-ts-helper#watcher'); class Watcher extends events_1.EventEmitter { constructor(helper) { super(); this.helper = helper; this.throttleTick = null; this.throttleStack = []; this.helper = helper; } init(options) { const generatorName = options.generator || 'class'; this.config = this.helper.config; this.name = options.name; this.ref = options.ref; const generator = (0, generator_1.loadGenerator)(generatorName, { cwd: this.config.cwd }); if (utils.isClass(generator)) { const instance = new generator(this.config, this.helper); this.generator = (config) => instance.render(config); } else { this.generator = generator; } options = this.options = Object.assign(Object.assign({ trigger: ['add', 'unlink'], generator: generatorName, pattern: '**/*.(ts|js)', watch: true }, generator.defaultConfig), utils.cleanEmpty(options)); this.pattern = utils.toArray(this.options.pattern) .map(utils.formatPath) .concat(utils.toArray(this.options.ignore).map(p => `!${utils.formatPath(p)}`)); (0, assert_1.default)(options.directory, `options.directory must set in ${generatorName}`); const baseDir = options.directory.replace(/\/|\\/, path_1.default.sep); this.dir = path_1.default.resolve(this.config.cwd, baseDir); this.dtsDir = path_1.default.resolve(this.config.typings, path_1.default.relative(this.config.cwd, this.dir)); // watch file change if (this.options.watch) { this.watch(); } // exec at init if (this.options.execAtInit) { this.execute(); } } destroy() { if (this.fsWatcher) { this.fsWatcher.close(); } clearTimeout(this.throttleTick); this.throttleTick = null; this.throttleStack.length = 0; this.removeAllListeners(); } // watch file change watch() { if (this.fsWatcher) { this.fsWatcher.close(); } const watcherOption = Object.assign({ cwd: this.dir, ignoreInitial: true }, (this.config.watchOptions || {})); const watcher = chokidar_1.default.watch(this.pattern, watcherOption); // listen watcher event this.options.trigger.forEach(evt => { watcher.on(evt, this.onChange.bind(this)); }); // auto remove js while ts was deleted if (this.config.autoRemoveJs) { watcher.on('unlink', utils.removeSameNameJs); } this.fsWatcher = watcher; } // execute generator execute(file) { debug('execution %s', file); let _fileList; // use utils.extend to extend getter const newConfig = utils.extend({}, this.options, { file, dir: this.dir, dtsDir: this.dtsDir, pattern: this.pattern, get fileList() { return _fileList || (_fileList = utils.loadFiles(this.dir, this.pattern)); }, }); const startTime = Date.now(); const result = this.generator(newConfig, this.config, this.helper); if (result) { this.emit('update', result, file, startTime); } return result; } // on file change onChange(filePath) { filePath = path_1.default.resolve(this.dir, filePath); debug('file changed %s %o', filePath, this.throttleStack); if (!this.throttleStack.includes(filePath)) { this.throttleStack.push(filePath); } if (this.throttleTick) { return; } this.throttleTick = setTimeout(() => { while (this.throttleStack.length) { this.execute(this.throttleStack.pop()); } this.throttleTick = null; }, this.config.throttle); } } exports.default = Watcher;