UNPKG

8.47 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const events_1 = require("events");
4const fs_1 = require("fs");
5const path_1 = require("path");
6const crypto_1 = require("crypto");
7const child_process_1 = require("child_process");
8class DirMonitor extends events_1.EventEmitter {
9 constructor(path, isFile = false) {
10 super();
11 this._isFile = false;
12 this._sub_file = new Map();
13 this._sub_dri = new Map();
14 this._path = path;
15 this._isFile = isFile;
16 }
17 init() {
18 // 先判断是文件夹还是文件
19 if (this._isFile) {
20 if (this._path.indexOf('.js') == -1) {
21 this._path = this._path + '.js';
22 }
23 this._fsw = fs_1.watch(this._path);
24 this._fsw.on("change", this._on_modify.bind(this));
25 this._fsw.on("error", this._on_error.bind(this));
26 if (fs_1.existsSync(this._path)) {
27 let md5 = crypto_1.createHash("md5").update(fs_1.readFileSync(this._path)).digest("hex");
28 this._sub_file.set(path_1.parse(this._path).base, md5);
29 this.emit("new", this._path);
30 }
31 return;
32 }
33 else {
34 // 初始化所有文件文件夹
35 if (!fs_1.existsSync(this._path)) {
36 fs_1.mkdirSync(this._path);
37 }
38 let files = fs_1.readdirSync(this._path);
39 for (let i = 0; i < files.length; i++) {
40 let filename = files[i];
41 let r_file = path_1.join(this._path, filename);
42 let stat = fs_1.statSync(r_file);
43 if (stat.isDirectory()) {
44 let mot = new DirMonitor(r_file);
45 mot.on("new", this._pip_event.bind(this, "new"));
46 mot.on("change", this._pip_event.bind(this, "change"));
47 mot.on("del", this._pip_event.bind(this, "del"));
48 mot.init();
49 this._sub_dri.set(filename, mot);
50 }
51 else {
52 let md5 = crypto_1.createHash("md5").update(fs_1.readFileSync(r_file)).digest("hex");
53 this._sub_file.set(filename, md5);
54 this.emit("new", r_file);
55 }
56 }
57 this._fsw = fs_1.watch(this._path);
58 this._fsw.on("change", this._on_modify.bind(this));
59 this._fsw.on("error", this._on_error.bind(this));
60 }
61 }
62 on(event, listener) {
63 return super.on(event, listener);
64 }
65 off(event, listener) {
66 return super.off(event, listener);
67 }
68 _pip_event(event, ...args) {
69 this.emit(event, ...args);
70 }
71 _on_error(error) {
72 // console.log(error);
73 // if (this._watch_files_limit && this._watch_files_limit.indexOf(filename) == -1) return;
74 }
75 _on_modify(event, filename) {
76 let r_path = '';
77 if (this._isFile) {
78 r_path = this._path;
79 }
80 else {
81 r_path = path_1.join(this._path, filename);
82 }
83 // 首先判断一下是否存在
84 if (!fs_1.existsSync(r_path)) {
85 if (this._sub_dri.has(filename)) {
86 // 文件夹关闭了那么删除掉目录
87 let dir = this._sub_dri.get(filename);
88 dir && dir.destory();
89 this._sub_dri.delete(filename);
90 }
91 else if (this._sub_file.has(filename)) {
92 this.emit("del", r_path);
93 this._sub_file.delete(filename);
94 }
95 }
96 else {
97 // 文件存在的,那么需要判断文件夹还是文件
98 let stat = fs_1.statSync(r_path);
99 if (stat.isDirectory()) {
100 // 如果是个文件夹事件,那么就检查一下是否有子文件夹需要监控
101 if (!this._sub_dri.has(filename)) {
102 let mot = new DirMonitor(r_path);
103 mot.on("new", this._pip_event.bind(this, "new"));
104 mot.on("change", this._pip_event.bind(this, "change"));
105 mot.on("del", this._pip_event.bind(this, "del"));
106 mot.init();
107 this._sub_dri.set(filename, mot);
108 }
109 }
110 else {
111 // 判断一下文件是否需要触发相应
112 let md5 = crypto_1.createHash("md5").update(fs_1.readFileSync(r_path)).digest("hex");
113 if (!this._sub_file.has(filename)) {
114 // 新增文件
115 this.emit("new", r_path);
116 }
117 else if (this._sub_file.get(filename) != md5) {
118 // 文件变动
119 this.emit("change", r_path);
120 }
121 this._sub_file.set(filename, md5);
122 }
123 }
124 }
125 destory() {
126 this._sub_file.forEach((v, k, m) => {
127 this.emit("del", path_1.join(this._path, k));
128 });
129 this._fsw && this._fsw.close();
130 this.removeAllListeners("new");
131 this.removeAllListeners("change");
132 this.removeAllListeners("del");
133 this._sub_dri.forEach((v, k, m) => {
134 v.destory();
135 });
136 }
137}
138class AutoLoaderModule extends events_1.EventEmitter {
139 constructor(dir, option) {
140 super();
141 this._ModuleCache_ = {};
142 this._option = option || {};
143 let md = new DirMonitor(dir, this._option.isFile ? true : false);
144 md.on("new", this.addModule.bind(this));
145 md.on("change", (f) => {
146 this.delModule(f);
147 this.addModule(f);
148 });
149 md.on("del", this.delModule.bind(this));
150 // md.init();
151 this._md = md;
152 AutoLoaderModule.cache[dir] = this;
153 }
154 /**
155 * 监听文件夹,加载文件夹中的所有js
156 * @param dir
157 */
158 static watch(dir, option) {
159 let tp = this.cache[dir];
160 if (!tp) {
161 tp = new AutoLoaderModule(dir, option);
162 this.cache[dir] = tp;
163 }
164 return tp;
165 }
166 /**
167 * 开始加载
168 */
169 load() {
170 this._md.init();
171 return this;
172 }
173 on(event, listener) {
174 return super.on(event, listener);
175 }
176 off(event, listener) {
177 return super.off(event, listener);
178 }
179 addModule(filename) {
180 // console.log(filename);
181 if (this._ModuleCache_.hasOwnProperty(filename)) {
182 // console.error('replete file occure', filename);
183 return;
184 }
185 let comp = false;
186 let ext = path_1.parse(filename).ext;
187 try {
188 if (ext == '.js') {
189 let __all = require(filename);
190 let __pre_all = AutoLoaderModule.del_cache[filename];
191 // 看看有什么需要替换的
192 if (__pre_all) {
193 for (let key in __all) {
194 __pre_all.exports[key] = __all[key];
195 }
196 delete AutoLoaderModule.del_cache[filename];
197 require.cache[filename] = __pre_all;
198 }
199 }
200 else if (ext == '.ts') {
201 // 这里要么黑科技一下 自动编译
202 // 暂时不用,可以使用
203 if (this._option.tsc) {
204 child_process_1.exec("tsc " + filename, (o) => {
205 // 编译
206 if (o)
207 console.error(o);
208 });
209 }
210 }
211 comp = true;
212 }
213 catch (e) {
214 console.error('load_module[%s]_error[%s]', filename, e);
215 }
216 if (ext == '.js') {
217 this._ModuleCache_[filename] = comp;
218 this.emit('add', filename, comp);
219 }
220 }
221 delModule(filename) {
222 AutoLoaderModule.del_cache[filename] = require.cache[filename];
223 delete this._ModuleCache_[filename];
224 delete require.cache[filename];
225 this.emit("del", filename, true);
226 }
227}
228exports.AutoLoaderModule = AutoLoaderModule;
229AutoLoaderModule.cache = {};
230AutoLoaderModule.del_cache = {};