watcher.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. const tslib_1 = require("tslib");
  4. const path_1 = tslib_1.__importDefault(require("path"));
  5. const chokidar_1 = tslib_1.__importDefault(require("chokidar"));
  6. const assert_1 = tslib_1.__importDefault(require("assert"));
  7. const events_1 = require("events");
  8. const utils = tslib_1.__importStar(require("./utils"));
  9. const generator_1 = require("./generator");
  10. const debug_1 = tslib_1.__importDefault(require("debug"));
  11. const debug = (0, debug_1.default)('egg-ts-helper#watcher');
  12. class Watcher extends events_1.EventEmitter {
  13. constructor(helper) {
  14. super();
  15. this.helper = helper;
  16. this.throttleTick = null;
  17. this.throttleStack = [];
  18. this.helper = helper;
  19. }
  20. init(options) {
  21. const generatorName = options.generator || 'class';
  22. this.config = this.helper.config;
  23. this.name = options.name;
  24. this.ref = options.ref;
  25. const generator = (0, generator_1.loadGenerator)(generatorName, { cwd: this.config.cwd });
  26. if (utils.isClass(generator)) {
  27. const instance = new generator(this.config, this.helper);
  28. this.generator = (config) => instance.render(config);
  29. }
  30. else {
  31. this.generator = generator;
  32. }
  33. options = this.options = Object.assign(Object.assign({ trigger: ['add', 'unlink'], generator: generatorName, pattern: '**/*.(ts|js)', watch: true }, generator.defaultConfig), utils.cleanEmpty(options));
  34. this.pattern = utils.toArray(this.options.pattern)
  35. .map(utils.formatPath)
  36. .concat(utils.toArray(this.options.ignore).map(p => `!${utils.formatPath(p)}`));
  37. (0, assert_1.default)(options.directory, `options.directory must set in ${generatorName}`);
  38. const baseDir = options.directory.replace(/\/|\\/, path_1.default.sep);
  39. this.dir = path_1.default.resolve(this.config.cwd, baseDir);
  40. this.dtsDir = path_1.default.resolve(this.config.typings, path_1.default.relative(this.config.cwd, this.dir));
  41. // watch file change
  42. if (this.options.watch) {
  43. this.watch();
  44. }
  45. // exec at init
  46. if (this.options.execAtInit) {
  47. this.execute();
  48. }
  49. }
  50. destroy() {
  51. if (this.fsWatcher) {
  52. this.fsWatcher.close();
  53. }
  54. clearTimeout(this.throttleTick);
  55. this.throttleTick = null;
  56. this.throttleStack.length = 0;
  57. this.removeAllListeners();
  58. }
  59. // watch file change
  60. watch() {
  61. if (this.fsWatcher) {
  62. this.fsWatcher.close();
  63. }
  64. const watcherOption = Object.assign({ cwd: this.dir, ignoreInitial: true }, (this.config.watchOptions || {}));
  65. const watcher = chokidar_1.default.watch(this.pattern, watcherOption);
  66. // listen watcher event
  67. this.options.trigger.forEach(evt => {
  68. watcher.on(evt, this.onChange.bind(this));
  69. });
  70. // auto remove js while ts was deleted
  71. if (this.config.autoRemoveJs) {
  72. watcher.on('unlink', utils.removeSameNameJs);
  73. }
  74. this.fsWatcher = watcher;
  75. }
  76. // execute generator
  77. execute(file) {
  78. debug('execution %s', file);
  79. let _fileList;
  80. // use utils.extend to extend getter
  81. const newConfig = utils.extend({}, this.options, {
  82. file,
  83. dir: this.dir,
  84. dtsDir: this.dtsDir,
  85. pattern: this.pattern,
  86. get fileList() {
  87. return _fileList || (_fileList = utils.loadFiles(this.dir, this.pattern));
  88. },
  89. });
  90. const startTime = Date.now();
  91. const result = this.generator(newConfig, this.config, this.helper);
  92. if (result) {
  93. this.emit('update', result, file, startTime);
  94. }
  95. return result;
  96. }
  97. // on file change
  98. onChange(filePath) {
  99. filePath = path_1.default.resolve(this.dir, filePath);
  100. debug('file changed %s %o', filePath, this.throttleStack);
  101. if (!this.throttleStack.includes(filePath)) {
  102. this.throttleStack.push(filePath);
  103. }
  104. if (this.throttleTick) {
  105. return;
  106. }
  107. this.throttleTick = setTimeout(() => {
  108. while (this.throttleStack.length) {
  109. this.execute(this.throttleStack.pop());
  110. }
  111. this.throttleTick = null;
  112. }, this.config.throttle);
  113. }
  114. }
  115. exports.default = Watcher;