@e-mc/watch 0.11.7 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # @e-mc/watch
2
2
 
3
- * NodeJS 16 LTS
4
- * ES2021
3
+ * NodeJS 18
4
+ * ES2022
5
5
 
6
6
  ## General Usage
7
7
 
@@ -9,7 +9,7 @@
9
9
 
10
10
  ## Interface
11
11
 
12
- * [View Source](https://www.unpkg.com/@e-mc/types@0.11.7/lib/index.d.ts)
12
+ * [View Source](https://www.unpkg.com/@e-mc/types@0.12.0/lib/index.d.ts)
13
13
 
14
14
  ```typescript
15
15
  import type { IFileManager, ModuleConstructor } from "./index";
@@ -31,6 +31,7 @@ interface IWatch extends IClient<IFileManager, WatchModule, ModifiedPostFinalize
31
31
  setSSLKey(value: string): boolean;
32
32
  setSSLCert(value: string): boolean;
33
33
  hasSecureProtocol(): boolean;
34
+ getRecursiveFiles(watch: IFileGroup<ExternalAsset>): [string, string[]][];
34
35
  whenModified?(assets: ExternalAsset[], postFinalize: PostFinalizeCallback): IFileManager;
35
36
  whenModified?(assets: ExternalAsset[], sanitize?: boolean, postFinalize?: PostFinalizeCallback): IFileManager;
36
37
  set assets(value: ExternalAsset[]);
@@ -109,11 +110,11 @@ instance.start(assets, { disk_read: ["/path/workspace/output/**"] });
109
110
 
110
111
  ## References
111
112
 
112
- - https://www.unpkg.com/@e-mc/types@0.11.7/lib/asset.d.ts
113
- - https://www.unpkg.com/@e-mc/types@0.11.7/lib/core.d.ts
114
- - https://www.unpkg.com/@e-mc/types@0.11.7/lib/filemanager.d.ts
115
- - https://www.unpkg.com/@e-mc/types@0.11.7/lib/settings.d.ts
116
- - https://www.unpkg.com/@e-mc/types@0.11.7/lib/watch.d.ts
113
+ - https://www.unpkg.com/@e-mc/types@0.12.0/lib/asset.d.ts
114
+ - https://www.unpkg.com/@e-mc/types@0.12.0/lib/core.d.ts
115
+ - https://www.unpkg.com/@e-mc/types@0.12.0/lib/filemanager.d.ts
116
+ - https://www.unpkg.com/@e-mc/types@0.12.0/lib/settings.d.ts
117
+ - https://www.unpkg.com/@e-mc/types@0.12.0/lib/watch.d.ts
117
118
 
118
119
  * https://www.npmjs.com/package/@types/ws
119
120
 
@@ -1,19 +1,13 @@
1
1
  "use strict";
2
- var _a, _b, _c, _d, _e, _f;
3
2
  const util = require("node:util");
3
+ const pm = require("picomatch");
4
4
  const ws = require("ws");
5
5
  const types_1 = require("@e-mc/types");
6
6
  const core_1 = require("@e-mc/core");
7
- const kServer = Symbol('server');
8
- const kStarted = Symbol('started');
9
- const kPaused = Symbol('paused');
10
- const kAssets = Symbol('assets');
11
- const kSockets = Symbol('sockets');
12
- const kStartTime = Symbol('startTime');
13
- const kUri = Symbol('uri');
14
- const kEtag = Symbol('etag');
15
- const kLastModified = Symbol('lastModified');
16
7
  class SocketRequest {
8
+ expires;
9
+ socketId;
10
+ id;
17
11
  constructor(expires, socketId, id = '') {
18
12
  this.expires = expires;
19
13
  this.socketId = socketId;
@@ -25,6 +19,8 @@ class SocketRequest {
25
19
  }
26
20
  }
27
21
  class FileGroup extends core_1.AbortComponent {
22
+ static CONNECTION_TIMEOUT = 10 * 60000;
23
+ static CLIENT_SESSION = new Map();
28
24
  static checkTimeout(client) {
29
25
  if (client.readyState !== ws.OPEN) {
30
26
  return false;
@@ -44,34 +40,45 @@ class FileGroup extends core_1.AbortComponent {
44
40
  const watch = file.watch;
45
41
  return (0, types_1.cloneObject)(file, (0, types_1.isPlainObject)(watch) && (0, types_1.isArray)(watch.assets) ? new WeakSet([watch.assets]) : true);
46
42
  }
47
- constructor(uri, assets, startTime, abortable) {
43
+ captured = false;
44
+ port = NaN;
45
+ secure = false;
46
+ hot = false;
47
+ always = false;
48
+ url;
49
+ document;
50
+ main;
51
+ bundleMain;
52
+ sourceFiles;
53
+ _related = [];
54
+ _abortable;
55
+ #server = null;
56
+ #started = false;
57
+ #paused = false;
58
+ #etag = '';
59
+ #lastModified = '';
60
+ #startTime;
61
+ #sockets = [];
62
+ #uri;
63
+ #assets;
64
+ #recursive;
65
+ constructor(uri, assets, startTime, abortable, recursive) {
48
66
  super();
49
- this.captured = false;
50
- this.port = NaN;
51
- this.secure = false;
52
- this.hot = false;
53
- this.always = false;
54
- this._related = [];
55
- this._abortable = false;
56
- this[_a] = null;
57
- this[_b] = false;
58
- this[_c] = false;
59
- this[_d] = '';
60
- this[_e] = '';
61
- this[_f] = [];
62
- this[kUri] = uri;
63
- this[kAssets] = assets;
67
+ this.#uri = uri;
68
+ this.#assets = assets;
64
69
  if (typeof startTime === 'boolean') {
70
+ recursive = abortable;
65
71
  abortable = startTime;
66
72
  startTime = undefined;
67
73
  }
68
- if (typeof abortable === 'boolean') {
69
- this._abortable = abortable;
74
+ this._abortable = abortable === true;
75
+ this.#startTime = startTime || Date.now();
76
+ if (recursive && (0, types_1.supported)(19, 1)) {
77
+ this.#recursive = (Array.isArray(recursive) ? recursive : typeof recursive === 'string' ? [recursive] : []).map(value => core_1.Permission.toPosix(value));
70
78
  }
71
- this[kStartTime] = startTime || Date.now();
72
79
  }
73
80
  connection(server, port = 0, secure = false) {
74
- this[kServer] = server;
81
+ this.#server = server;
75
82
  if (port > 0) {
76
83
  this.port = port;
77
84
  }
@@ -120,32 +127,38 @@ class FileGroup extends core_1.AbortComponent {
120
127
  return result;
121
128
  }
122
129
  pause() {
123
- this[kPaused] = true;
130
+ this.#paused = true;
124
131
  }
125
132
  resume() {
126
- this[kPaused] = false;
133
+ this.#paused = false;
127
134
  }
128
135
  reset() {
129
136
  super.reset();
130
137
  this.captured = false;
131
138
  }
139
+ matchRecursive(value) {
140
+ if (!this.recursive) {
141
+ return false;
142
+ }
143
+ return this.#recursive?.length ? pm.isMatch(core_1.Permission.toPosix(value), this.#recursive, { nocase: process.platform === 'win32' }) : true;
144
+ }
132
145
  get server() {
133
- return this[kServer];
146
+ return this.#server;
134
147
  }
135
148
  get uri() {
136
- return this[kUri];
149
+ return this.#uri;
137
150
  }
138
151
  get sockets() {
139
- return this[kSockets];
152
+ return this.#sockets;
140
153
  }
141
154
  get startTime() {
142
- return this[kStartTime];
155
+ return this.#startTime;
143
156
  }
144
157
  get started() {
145
- return this[kStarted] ||= Date.now() >= this.startTime;
158
+ return this.#started ||= Date.now() >= this.startTime;
146
159
  }
147
160
  get assets() {
148
- return this[kAssets];
161
+ return this.#assets;
149
162
  }
150
163
  set related(value) {
151
164
  this._related = value.map(item => {
@@ -170,19 +183,19 @@ class FileGroup extends core_1.AbortComponent {
170
183
  }
171
184
  set etag(value) {
172
185
  if (typeof value === 'string') {
173
- this[kEtag] = value;
186
+ this.#etag = value;
174
187
  }
175
188
  }
176
189
  get etag() {
177
- return this[kEtag];
190
+ return this.#etag;
178
191
  }
179
192
  set lastModified(value) {
180
193
  if (typeof value === 'string') {
181
- this[kLastModified] = value;
194
+ this.#lastModified = value;
182
195
  }
183
196
  }
184
197
  get lastModified() {
185
- return this[kEtag] ? '' : this[kLastModified];
198
+ return this.#etag ? '' : this.#lastModified;
186
199
  }
187
200
  get expires() {
188
201
  let result = 0;
@@ -198,13 +211,15 @@ class FileGroup extends core_1.AbortComponent {
198
211
  return this.sockets.every(item => item.expired);
199
212
  }
200
213
  get paused() {
201
- return this[kPaused];
214
+ return this.#paused;
202
215
  }
203
216
  get abortable() {
204
217
  return this._abortable;
205
218
  }
219
+ get recursive() {
220
+ if (this.#recursive) {
221
+ return true;
222
+ }
223
+ }
206
224
  }
207
- _a = kServer, _b = kStarted, _c = kPaused, _d = kEtag, _e = kLastModified, _f = kSockets;
208
- FileGroup.CONNECTION_TIMEOUT = 10 * 60000;
209
- FileGroup.CLIENT_SESSION = new Map();
210
225
  module.exports = FileGroup;
package/index.js CHANGED
@@ -1,5 +1,4 @@
1
1
  "use strict";
2
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
3
2
  const path = require("node:path");
4
3
  const fs = require("node:fs");
5
4
  const https = require("node:https");
@@ -10,16 +9,7 @@ const core_1 = require("@e-mc/core");
10
9
  const util_1 = require("@e-mc/request/util");
11
10
  const request_1 = require("@e-mc/request");
12
11
  const filegroup_1 = require("@e-mc/watch/filegroup");
13
- const kInterval = Symbol('interval');
14
- const kPort = Symbol('port');
15
- const kSecurePort = Symbol('securePort');
16
- const kCa = Symbol('ca');
17
- const kTlsKey = Symbol('tlsKey');
18
- const kTlsCert = Symbol('tlsCert');
19
- const kTlsVersion = Symbol('tlsVersion');
20
- const kTlsPassphrase = Symbol('tlsPassphrase');
21
- const kTlsConfig = Symbol('tlsConfig');
22
- const kCiphers = Symbol('ciphers');
12
+ const kWatch = Symbol.for('watch:constructor');
23
13
  const HTTP_MAP = new Map();
24
14
  const DISK_MAP = new Map();
25
15
  const PORT_MAP = new Map();
@@ -69,12 +59,6 @@ function wasAborted(result, current) {
69
59
  current.abort();
70
60
  }
71
61
  }
72
- function fatalError(instance, map, target, err) {
73
- const uri = target.value.uri;
74
- map.delete(uri);
75
- abortTimeout(target);
76
- instance.writeFail(["Unable to watch file", uri], err, 16);
77
- }
78
62
  function getErrorMessage(item, status) {
79
63
  switch (status) {
80
64
  case 1:
@@ -93,24 +77,8 @@ function getErrorMessage(item, status) {
93
77
  const isMap = (value) => value ? value.size > 0 : false;
94
78
  const formatDate = (value) => new Date(value).toLocaleString().replace(/\/20\d+, /, '@').replace(/:\d+ (AM|PM)$/, (...match) => match[1]);
95
79
  class Watch extends core_1.Client {
96
- constructor() {
97
- super(...arguments);
98
- this.connectTimeout = Watch.PROCESS_TIMEOUT;
99
- this._moduleName = 'watch';
100
- this._assets = [];
101
- this._extensions = [];
102
- this._hostEvents = [];
103
- this[_a] = types_1.THRESHOLD.WATCH_INTERVAL;
104
- this[_b] = 80;
105
- this[_c] = 443;
106
- this[_d] = '';
107
- this[_e] = '';
108
- this[_f] = '';
109
- this[_g] = '';
110
- this[_h] = '';
111
- this[_j] = undefined;
112
- this[_k] = undefined;
113
- }
80
+ static [kWatch] = true;
81
+ static PROCESS_TIMEOUT = 5 * 1000;
114
82
  static createServer(port, secure, active) {
115
83
  if (typeof secure === 'boolean') {
116
84
  active = secure;
@@ -206,6 +174,24 @@ class Watch extends core_1.Client {
206
174
  static isConnectionError(err) {
207
175
  return (0, util_1.checkRetryable)(err);
208
176
  }
177
+ connectTimeout = Watch.PROCESS_TIMEOUT;
178
+ _moduleName = 'watch';
179
+ _assets = [];
180
+ _extensions = [];
181
+ _recursiveMap = Object.create(null);
182
+ _hostEvents = [];
183
+ #internal = types_1.THRESHOLD.WATCH_INTERVAL;
184
+ #port = 80;
185
+ #securePort = 443;
186
+ #ca = '';
187
+ #ciphers = '';
188
+ #tlsKey = '';
189
+ #tlsCert = '';
190
+ #tlsPassphrase = '';
191
+ #tlsVersion = undefined;
192
+ #tlsConfig = undefined;
193
+ #recursiveTime = new WeakMap();
194
+ whenModified;
209
195
  init(config) {
210
196
  const { interval, port, secure } = this.module;
211
197
  if (secure) {
@@ -280,7 +266,7 @@ class Watch extends core_1.Client {
280
266
  if (!watch) {
281
267
  continue;
282
268
  }
283
- let expires = 0, status = 0, wss = null, main, id, socketId, port, secure, hot, always, watched, message;
269
+ let expires = 0, status = 0, wss = null, main, id, socketId, port, secure, hot, always, recursive, watched, message;
284
270
  if (watch === true && settings) {
285
271
  const { uri, localUri, mimeType } = item;
286
272
  watch = false;
@@ -292,8 +278,10 @@ class Watch extends core_1.Client {
292
278
  }
293
279
  }
294
280
  if (!watch && localUri && !(watch = settings[localUri])) {
281
+ const pathname = core_1.Client.PLATFORM_WIN32 ? core_1.Client.toPosix(localUri) : localUri;
282
+ const options = core_1.Client.PLATFORM_WIN32 ? { nocase: true, matchBase: true, windows: true, posixSlashes: true } : { matchBase: true };
295
283
  for (const pattern in settings) {
296
- if ((0, types_1.hasGlob)(pattern) && pm.isMatch(localUri, pattern, { nocase: core_1.Client.PLATFORM_WIN32 }) && (watch = settings[pattern])) {
284
+ if ((0, types_1.hasGlob)(pattern) && pm.isMatch(pathname, pattern, options) && (watch = settings[pattern])) {
297
285
  break;
298
286
  }
299
287
  }
@@ -308,27 +296,30 @@ class Watch extends core_1.Client {
308
296
  }
309
297
  let startTime = Date.now();
310
298
  if ((0, types_1.isPlainObject)(watch)) {
311
- const { start, expires: expired, reload } = watch;
299
+ const reload = watch.reload;
312
300
  id = watch.id;
313
301
  if (watch.main) {
314
302
  main = item;
315
303
  }
316
- if (start) {
317
- const offset = (0, types_1.parseTime)(start);
304
+ if (watch.start) {
305
+ const offset = (0, types_1.parseTime)(watch.start);
318
306
  if (offset > 0) {
319
307
  startTime += offset;
320
308
  }
321
309
  }
322
- if (expired) {
323
- expires = (0, types_1.parseExpires)(expired, startTime);
310
+ if (watch.expires) {
311
+ expires = (0, types_1.parseExpires)(watch.expires, startTime);
312
+ }
313
+ if (watch.recursive) {
314
+ recursive = true;
324
315
  }
325
316
  if (reload && (socketId = reload.socketId)) {
326
317
  ({ port, module: hot, always } = reload);
327
318
  if (reload.secure) {
328
- const key = this[kTlsKey];
329
- const cert = this[kTlsCert];
319
+ const key = this.#tlsKey;
320
+ const cert = this.#tlsCert;
330
321
  if (key && cert) {
331
- wss = Watch.createServer(port ||= this.securePort, { ca: this[kCa], key, cert, passphrase: this[kTlsPassphrase], version: this[kTlsVersion], ciphers: this[kCiphers], config: this[kTlsConfig] });
322
+ wss = Watch.createServer(port ||= this.securePort, { ca: this.#ca, key, cert, passphrase: this.#tlsPassphrase, version: this.#tlsVersion, ciphers: this.#ciphers, config: this.#tlsConfig });
332
323
  }
333
324
  secure = true;
334
325
  }
@@ -348,7 +339,7 @@ class Watch extends core_1.Client {
348
339
  }
349
340
  const interval = getInterval(item) || watchInterval || this.interval;
350
341
  const watching = (uri, esm) => {
351
- const group = new filegroup_1(uri, main ? assets : items, startTime, this.willAbort("(watch)"));
342
+ const group = new filegroup_1(uri, main ? assets : items, startTime, this.willAbort("(watch)"), recursive);
352
343
  group.add(expires, socketId, id);
353
344
  if (main) {
354
345
  group.main = main;
@@ -549,7 +540,7 @@ class Watch extends core_1.Client {
549
540
  }
550
541
  })
551
542
  .catch((err) => {
552
- fatalError(this, HTTP_MAP, target, err);
543
+ this.#sendFatalError(err, HTTP_MAP, target);
553
544
  client?.destroy();
554
545
  });
555
546
  }).call(this);
@@ -557,13 +548,34 @@ class Watch extends core_1.Client {
557
548
  }
558
549
  else if (esm || path.isAbsolute(uri = core_1.Client.resolveFile(uri)) && this.canRead(uri, { hostPermissionOnly: !!this.host })) {
559
550
  const pre = checkPreceding(DISK_MAP);
551
+ const options = {};
552
+ let src = uri;
553
+ if (group.matchRecursive(uri)) {
554
+ src = path.dirname(uri);
555
+ for (const pathname in this._recursiveMap) {
556
+ if (src === pathname || src.startsWith(pathname + path.sep)) {
557
+ const parent = this._recursiveMap[pathname].get(group);
558
+ if (parent) {
559
+ parent.push(uri);
560
+ }
561
+ else {
562
+ (this._recursiveMap[pathname] = new Map()).set(group, [uri]);
563
+ }
564
+ return 4;
565
+ }
566
+ }
567
+ if (pre === undefined) {
568
+ (this._recursiveMap[src] = new Map()).set(group, [uri]);
569
+ options.recursive = true;
570
+ }
571
+ }
560
572
  if (pre !== undefined) {
561
573
  return pre;
562
574
  }
563
575
  let ptime = 0;
564
- target.watcher = fs.watch(uri, (event, filename) => {
576
+ target.watcher = fs.watch(src, options, (event, filename) => {
565
577
  if (this.aborted || group.aborted) {
566
- fatalError(this, DISK_MAP, target, (0, types_1.createAbortError)());
578
+ this.#sendFatalError((0, types_1.createAbortError)(), DISK_MAP, target);
567
579
  return;
568
580
  }
569
581
  const map = DISK_MAP.get(uri);
@@ -573,6 +585,11 @@ class Watch extends core_1.Client {
573
585
  try {
574
586
  const mtime = Math.floor(fs.statSync(uri).mtimeMs);
575
587
  if (mtime > ptime) {
588
+ ptime = mtime + types_1.THRESHOLD.WATCH_CHANGE;
589
+ if (filename && options.recursive && !group.matchRecursive(path.join(src, filename))) {
590
+ this.formatMessage(16, 'WATCH', ['File modification ignored', 'recursive'], path.join(src, filename), { titleColor: 'yellow' });
591
+ return;
592
+ }
576
593
  for (const [key, input] of map) {
577
594
  const value = input.value;
578
595
  if (value.expired) {
@@ -593,7 +610,6 @@ class Watch extends core_1.Client {
593
610
  });
594
611
  }
595
612
  }
596
- ptime = mtime + types_1.THRESHOLD.WATCH_CHANGE;
597
613
  }
598
614
  break;
599
615
  }
@@ -602,6 +618,9 @@ class Watch extends core_1.Client {
602
618
  }
603
619
  }
604
620
  case 'rename':
621
+ if (event === 'rename' && group.recursive) {
622
+ return;
623
+ }
605
624
  map?.clear();
606
625
  this.watchExpired(DISK_MAP, group, event === 'rename' ? 'File renamed: ' + filename : undefined);
607
626
  abortTimeout(target);
@@ -617,11 +636,11 @@ class Watch extends core_1.Client {
617
636
  };
618
637
  if ((0, types_1.isArray)(sourceFiles) && (sourceFiles = sourceFiles.filter(file => this.canRead(file, { hostPermissionOnly: !!this.host }))).length > 0) {
619
638
  let index = 0;
620
- for (const file of new Set(sourceFiles)) {
639
+ for (const file of Array.from(new Set(sourceFiles)).sort((a, b) => a.length - b.length)) {
621
640
  if (index++ > 0) {
622
641
  watching(file, true);
623
642
  }
624
- else if ((status = watching(watched = file, true)) > 0) {
643
+ else if ((status = watching(watched = file, true)) > 0 && status < 4) {
625
644
  break;
626
645
  }
627
646
  }
@@ -632,6 +651,9 @@ class Watch extends core_1.Client {
632
651
  else {
633
652
  continue;
634
653
  }
654
+ if (status === 4) {
655
+ continue;
656
+ }
635
657
  if (status > 0) {
636
658
  if (message ||= getErrorMessage(item, status)) {
637
659
  this.formatFail((16 | (status === 2 ? 8192 : 0)), 'WATCH', ["Unable to watch file", watched && path.basename(watched)], (0, types_1.errorValue)(message, watched), { fatal: false });
@@ -644,7 +666,18 @@ class Watch extends core_1.Client {
644
666
  }
645
667
  }
646
668
  async modified(watch) {
647
- this.formatMessage(16, 'WATCH', "File modified", watch.uri, { ...core_1.Client.LOG_STYLE_WARN });
669
+ const recursive = this.getRecursiveFiles(watch);
670
+ let message = "File modified", uri = watch.uri;
671
+ if (recursive.length > 0) {
672
+ const time = this.#recursiveTime.get(watch) || 0;
673
+ if (time + types_1.THRESHOLD.WATCH_RECURSIVE_CHANGE >= Date.now()) {
674
+ return;
675
+ }
676
+ message = "Directory was modified";
677
+ uri = path.dirname(watch.uri);
678
+ this.#recursiveTime.set(watch, Date.now());
679
+ }
680
+ this.formatMessage(16, 'WATCH', message, uri, { ...core_1.Client.LOG_STYLE_WARN });
648
681
  const { host, assets } = this;
649
682
  let items, sanitize = false;
650
683
  if (watch.main) {
@@ -696,31 +729,32 @@ class Watch extends core_1.Client {
696
729
  catch {
697
730
  }
698
731
  }
699
- if (manager) {
700
- if (host && watch.document) {
701
- for (const { instance } of host.Document) {
702
- if (host.hasDocument(instance, watch.document)) {
703
- const result = instance.watchInit?.(watch, items, sanitize);
704
- if (result) {
705
- if ((0, types_1.isArray)(result.using)) {
706
- manager.using(...result.using);
707
- }
708
- if (Array.isArray(result.dataSource)) {
709
- const document = manager.find(instance.moduleName);
710
- if (document) {
711
- document.dataSource = result.dataSource;
712
- }
713
- }
732
+ if (!manager) {
733
+ return;
734
+ }
735
+ if (host && watch.document) {
736
+ for (const { instance } of host.Document) {
737
+ if (host.hasDocument(instance, watch.document)) {
738
+ const result = instance.watchInit?.(watch, items, sanitize);
739
+ if (result) {
740
+ if ((0, types_1.isArray)(result.using)) {
741
+ manager.using(...result.using);
714
742
  }
715
- const listener = instance.watchModified?.(watch, items);
716
- if (typeof listener === 'function') {
717
- manager.on('end', listener);
743
+ if (Array.isArray(result.dataSource)) {
744
+ const document = manager.find(instance.moduleName);
745
+ if (document) {
746
+ document.dataSource = result.dataSource;
747
+ }
718
748
  }
719
749
  }
750
+ const listener = instance.watchModified?.(watch, items, recursive);
751
+ if (typeof listener === 'function') {
752
+ manager.on('end', listener);
753
+ }
720
754
  }
721
755
  }
722
- return await manager.start();
723
756
  }
757
+ return await manager.start();
724
758
  }
725
759
  catch (err) {
726
760
  this.writeFail(["Unknown", watch.url?.pathname || path.basename(watch.uri)], err);
@@ -734,16 +768,16 @@ class Watch extends core_1.Client {
734
768
  this.setCA(ca);
735
769
  }
736
770
  if (request_1.isCert(key) || core_1.Client.isPath(key = path.resolve(key)) && this.canRead(key, { ownPermissionOnly: true })) {
737
- this[kTlsKey] = key;
771
+ this.#tlsKey = key;
738
772
  }
739
773
  if (request_1.isCert(cert) || core_1.Client.isPath(cert = path.resolve(cert)) && this.canRead(cert, { ownPermissionOnly: true })) {
740
- this[kTlsCert] = cert;
774
+ this.#tlsCert = cert;
741
775
  }
742
776
  if ((0, types_1.isString)(passphrase)) {
743
- this[kTlsPassphrase] = passphrase;
777
+ this.#tlsPassphrase = passphrase;
744
778
  }
745
779
  if ((0, types_1.isString)(ciphers)) {
746
- this[kCiphers] = ciphers;
780
+ this.#ciphers = ciphers;
747
781
  }
748
782
  if (!(0, types_1.isPlainObject)(config)) {
749
783
  config = undefined;
@@ -762,33 +796,45 @@ class Watch extends core_1.Client {
762
796
  version = undefined;
763
797
  break;
764
798
  }
765
- this[kTlsConfig] = config;
766
- this[kTlsVersion] = version;
799
+ this.#tlsConfig = config;
800
+ this.#tlsVersion = version;
767
801
  return this.hasSecureProtocol();
768
802
  }
769
803
  setCA(value) {
770
804
  if ((0, types_1.isString)(value) && core_1.Client.isPath(value = path.resolve(value = value.trim())) && this.canRead(value, { ownPermissionOnly: true })) {
771
- this[kCa] = value;
805
+ this.#ca = value;
772
806
  return true;
773
807
  }
774
808
  return false;
775
809
  }
776
810
  setSSLKey(value) {
777
- this[kTlsConfig] = { secureProtocol: 'SSLv23_method' };
778
- this[kTlsVersion] = undefined;
779
- return !!(this[kTlsKey] = request_1.readTLSKey(value, true));
811
+ this.#tlsConfig = { secureProtocol: 'SSLv23_method' };
812
+ this.#tlsVersion = undefined;
813
+ return !!(this.#tlsKey = request_1.readTLSKey(value, true));
780
814
  }
781
815
  setSSLCert(value) {
782
- return !!(this[kTlsCert] = request_1.readTLSCert(value, true));
816
+ return !!(this.#tlsCert = request_1.readTLSCert(value, true));
783
817
  }
784
818
  hasSecureProtocol() {
785
- return !!this[kTlsKey] && !!this[kTlsCert];
819
+ return !!this.#tlsKey && !!this.#tlsCert;
786
820
  }
787
821
  willAbort(value) {
788
822
  return this.host ? this.host.willAbort(value) : value === "(watch)";
789
823
  }
824
+ getRecursiveFiles(watch) {
825
+ const result = [];
826
+ if (watch.recursive) {
827
+ for (const pathname in this._recursiveMap) {
828
+ const files = this._recursiveMap[pathname].get(watch);
829
+ if (files) {
830
+ result.push([pathname, files]);
831
+ }
832
+ }
833
+ }
834
+ return result;
835
+ }
790
836
  watchExpired(map, target, message = "Expired") {
791
- this.formatMessage(16, 'WATCH', [message, target.startTime ? 'since ' + formatDate(target.startTime) : ''], target.uri, { titleColor: 'grey' });
837
+ this.formatMessage(16, 'WATCH', [message, target.startTime ? 'since ' + formatDate(target.startTime) : ''], this.getRecursiveFiles(target).length > 0 ? path.dirname(target.uri) : target.uri, { titleColor: 'grey' });
792
838
  const data = map.get(target.uri);
793
839
  if (!data?.size) {
794
840
  map.delete(target.uri);
@@ -796,6 +842,12 @@ class Watch extends core_1.Client {
796
842
  }
797
843
  return false;
798
844
  }
845
+ #sendFatalError(err, map, target) {
846
+ const uri = target.value.uri;
847
+ map.delete(uri);
848
+ abortTimeout(target);
849
+ this.writeFail(["Unable to watch file", uri], err, 16);
850
+ }
799
851
  set host(value) {
800
852
  super.host = value;
801
853
  if ((0, types_1.isArray)(value?.assets)) {
@@ -818,29 +870,27 @@ class Watch extends core_1.Client {
818
870
  }
819
871
  set interval(value) {
820
872
  if (value > 0) {
821
- this[kInterval] = value;
873
+ this.#internal = value;
822
874
  }
823
875
  }
824
876
  get interval() {
825
- return this[kInterval];
877
+ return this.#internal;
826
878
  }
827
879
  set port(value) {
828
880
  if (value > 0) {
829
- this[kPort] = value;
881
+ this.#port = value;
830
882
  }
831
883
  }
832
884
  get port() {
833
- return this[kPort];
885
+ return this.#port;
834
886
  }
835
887
  set securePort(value) {
836
888
  if (value > 0) {
837
- this[kSecurePort] = value;
889
+ this.#securePort = value;
838
890
  }
839
891
  }
840
892
  get securePort() {
841
- return this[kSecurePort];
893
+ return this.#securePort;
842
894
  }
843
895
  }
844
- _a = kInterval, _b = kPort, _c = kSecurePort, _d = kCa, _e = kCiphers, _f = kTlsKey, _g = kTlsCert, _h = kTlsPassphrase, _j = kTlsVersion, _k = kTlsConfig;
845
- Watch.PROCESS_TIMEOUT = 5 * 1000;
846
896
  module.exports = Watch;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@e-mc/watch",
3
- "version": "0.11.7",
3
+ "version": "0.12.0",
4
4
  "description": "Watch constructor for E-mc.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -20,9 +20,9 @@
20
20
  "license": "BSD-3-Clause",
21
21
  "homepage": "https://github.com/anpham6/e-mc#readme",
22
22
  "dependencies": {
23
- "@e-mc/core": "0.11.7",
24
- "@e-mc/request": "0.11.7",
25
- "@e-mc/types": "0.11.7",
23
+ "@e-mc/core": "0.12.0",
24
+ "@e-mc/request": "0.12.0",
25
+ "@e-mc/types": "0.12.0",
26
26
  "picomatch": "^4.0.2",
27
27
  "ws": "^8.18.1"
28
28
  }