@e-mc/watch 0.13.9 → 0.14.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 +7 -7
- package/filegroup/index.js +13 -11
- package/index.js +78 -76
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @e-mc/watch
|
|
2
2
|
|
|
3
|
-
* NodeJS
|
|
3
|
+
* NodeJS 20 (Minimum 18)
|
|
4
4
|
* ES2022
|
|
5
5
|
|
|
6
6
|
## General Usage
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
## Interface
|
|
11
11
|
|
|
12
|
-
* [View Source](https://www.unpkg.com/@e-mc/types@0.
|
|
12
|
+
* [View Source](https://www.unpkg.com/@e-mc/types@0.14.0/lib/index.d.ts)
|
|
13
13
|
|
|
14
14
|
```typescript
|
|
15
15
|
import type { IFileManager, ModuleConstructor } from "./index";
|
|
@@ -110,11 +110,11 @@ instance.start(assets, { disk_read: ["/path/workspace/output/**"] });
|
|
|
110
110
|
|
|
111
111
|
## References
|
|
112
112
|
|
|
113
|
-
- https://www.unpkg.com/@e-mc/types@0.
|
|
114
|
-
- https://www.unpkg.com/@e-mc/types@0.
|
|
115
|
-
- https://www.unpkg.com/@e-mc/types@0.
|
|
116
|
-
- https://www.unpkg.com/@e-mc/types@0.
|
|
117
|
-
- https://www.unpkg.com/@e-mc/types@0.
|
|
113
|
+
- https://www.unpkg.com/@e-mc/types@0.14.0/lib/asset.d.ts
|
|
114
|
+
- https://www.unpkg.com/@e-mc/types@0.14.0/lib/core.d.ts
|
|
115
|
+
- https://www.unpkg.com/@e-mc/types@0.14.0/lib/filemanager.d.ts
|
|
116
|
+
- https://www.unpkg.com/@e-mc/types@0.14.0/lib/settings.d.ts
|
|
117
|
+
- https://www.unpkg.com/@e-mc/types@0.14.0/lib/watch.d.ts
|
|
118
118
|
|
|
119
119
|
* https://www.npmjs.com/package/@types/ws
|
|
120
120
|
|
package/filegroup/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
2
|
+
|
|
3
|
+
const util = require('node:util');
|
|
4
|
+
const pm = require('picomatch');
|
|
5
|
+
const { WebSocket } = require('ws');
|
|
6
|
+
const { cloneObject, isArray, isObject, supported } = require('@e-mc/types');
|
|
7
|
+
const { AbortComponent, Permission } = require('@e-mc/core');
|
|
7
8
|
class SocketRequest {
|
|
8
9
|
expires;
|
|
9
10
|
socketId;
|
|
@@ -18,11 +19,11 @@ class SocketRequest {
|
|
|
18
19
|
return expires > 0 && expires !== Infinity && Date.now() > expires;
|
|
19
20
|
}
|
|
20
21
|
}
|
|
21
|
-
class FileGroup extends
|
|
22
|
+
class FileGroup extends AbortComponent {
|
|
22
23
|
static CONNECTION_TIMEOUT = 10 * 60000;
|
|
23
24
|
static CLIENT_SESSION = new Map();
|
|
24
25
|
static checkTimeout(client) {
|
|
25
|
-
if (client.readyState !==
|
|
26
|
+
if (client.readyState !== WebSocket.OPEN) {
|
|
26
27
|
return false;
|
|
27
28
|
}
|
|
28
29
|
const session = this.CLIENT_SESSION;
|
|
@@ -38,7 +39,7 @@ class FileGroup extends core_1.AbortComponent {
|
|
|
38
39
|
}
|
|
39
40
|
static cloneAsset(file) {
|
|
40
41
|
const watch = file.watch;
|
|
41
|
-
return
|
|
42
|
+
return cloneObject(file, isObject(watch) && isArray(watch.assets) ? new WeakMap([[watch.assets, watch.assets]]) : true);
|
|
42
43
|
}
|
|
43
44
|
captured = false;
|
|
44
45
|
port = NaN;
|
|
@@ -73,8 +74,8 @@ class FileGroup extends core_1.AbortComponent {
|
|
|
73
74
|
}
|
|
74
75
|
this._abortable = abortable === true;
|
|
75
76
|
this.#startTime = startTime || Date.now();
|
|
76
|
-
if (recursive &&
|
|
77
|
-
this.#recursive = (Array.isArray(recursive) ? recursive : typeof recursive === 'string' ? [recursive] : []).map(value =>
|
|
77
|
+
if (recursive && supported(19, 1)) {
|
|
78
|
+
this.#recursive = (Array.isArray(recursive) ? recursive : typeof recursive === 'string' ? [recursive] : []).map(value => Permission.toPosix(value));
|
|
78
79
|
}
|
|
79
80
|
}
|
|
80
81
|
connection(server, port = 0, secure = false) {
|
|
@@ -140,7 +141,7 @@ class FileGroup extends core_1.AbortComponent {
|
|
|
140
141
|
if (!this.recursive) {
|
|
141
142
|
return false;
|
|
142
143
|
}
|
|
143
|
-
return this.#recursive?.length ? pm.isMatch(
|
|
144
|
+
return this.#recursive?.length ? pm.isMatch(Permission.toPosix(value), this.#recursive, { nocase: process.platform === 'win32' }) : true;
|
|
144
145
|
}
|
|
145
146
|
get server() {
|
|
146
147
|
return this.#server;
|
|
@@ -222,4 +223,5 @@ class FileGroup extends core_1.AbortComponent {
|
|
|
222
223
|
}
|
|
223
224
|
}
|
|
224
225
|
}
|
|
226
|
+
|
|
225
227
|
module.exports = FileGroup;
|
package/index.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const pm = require(
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
2
|
+
|
|
3
|
+
const path = require('node:path');
|
|
4
|
+
const fs = require('node:fs');
|
|
5
|
+
const https = require('node:https');
|
|
6
|
+
const pm = require('picomatch');
|
|
7
|
+
const { WebSocketServer } = require('ws');
|
|
8
|
+
const { THRESHOLD, WATCH_EVENT, cloneObject, createAbortError, errorMessage, errorValue, existsFlag, hasGlob, ignoreFlag, isArray, isEmpty, isObject, isPlainObject, isString, parseExpires, parseTime, watchFlag } = require('@e-mc/types');
|
|
9
|
+
const { Client } = require('@e-mc/core');
|
|
10
|
+
const { asInt, checkRetryable } = require('@e-mc/request/util');
|
|
11
|
+
const Request = require('@e-mc/request');
|
|
12
|
+
const FileGroup = require('@e-mc/watch/filegroup');
|
|
12
13
|
const kWatch = Symbol.for('watch:constructor');
|
|
13
14
|
const HTTP_MAP = new Map();
|
|
14
15
|
const DISK_MAP = new Map();
|
|
@@ -25,9 +26,9 @@ function abortTimeout(group) {
|
|
|
25
26
|
}
|
|
26
27
|
function getInterval({ watch }) {
|
|
27
28
|
let interval;
|
|
28
|
-
if (
|
|
29
|
+
if (isObject(watch) && (interval = watch.interval)) {
|
|
29
30
|
if (typeof interval === 'string') {
|
|
30
|
-
interval =
|
|
31
|
+
interval = parseTime(interval);
|
|
31
32
|
}
|
|
32
33
|
if (interval > 0) {
|
|
33
34
|
return interval;
|
|
@@ -62,7 +63,7 @@ function wasAborted(result, current) {
|
|
|
62
63
|
function getErrorMessage(item, status) {
|
|
63
64
|
switch (status) {
|
|
64
65
|
case 1:
|
|
65
|
-
if (
|
|
66
|
+
if (existsFlag(item)) {
|
|
66
67
|
return;
|
|
67
68
|
}
|
|
68
69
|
return "ETag not supported";
|
|
@@ -76,7 +77,7 @@ function getErrorMessage(item, status) {
|
|
|
76
77
|
}
|
|
77
78
|
const isMap = (value) => value ? value.size > 0 : false;
|
|
78
79
|
const formatDate = (value) => new Date(value).toLocaleString().replace(/\/20\d+, /, '@').replace(/:\d+ (AM|PM)$/, (...match) => match[1]);
|
|
79
|
-
class Watch extends
|
|
80
|
+
class Watch extends Client {
|
|
80
81
|
static [kWatch] = true;
|
|
81
82
|
static PROCESS_TIMEOUT = 5 * 1000;
|
|
82
83
|
static createServer(port, secure, active) {
|
|
@@ -86,37 +87,37 @@ class Watch extends core_1.Client {
|
|
|
86
87
|
}
|
|
87
88
|
let wss;
|
|
88
89
|
try {
|
|
89
|
-
if (
|
|
90
|
+
if (isPlainObject(secure)) {
|
|
90
91
|
if (wss = SECURE_MAP.get(port.toString())) {
|
|
91
92
|
return wss;
|
|
92
93
|
}
|
|
93
94
|
const { ca, passphrase, ciphers, version, config } = secure;
|
|
94
95
|
let { key, cert } = secure;
|
|
95
|
-
if (key && cert && (key =
|
|
96
|
+
if (key && cert && (key = Request.readTLSKey(key, true)) && (cert = Request.readTLSKey(cert, true))) {
|
|
96
97
|
const server = https.createServer({
|
|
97
98
|
...config,
|
|
98
|
-
ca: ca &&
|
|
99
|
+
ca: ca && Request.readCACert(ca, true) || undefined,
|
|
99
100
|
key: passphrase ? [{ pem: key, passphrase }] : key,
|
|
100
101
|
cert,
|
|
101
102
|
ciphers,
|
|
102
103
|
minVersion: version || config?.minVersion
|
|
103
104
|
});
|
|
104
105
|
server.listen(port);
|
|
105
|
-
wss = new
|
|
106
|
+
wss = new WebSocketServer({ server });
|
|
106
107
|
SECURE_MAP.set(port.toString(), wss);
|
|
107
108
|
if (active) {
|
|
108
109
|
STATE_MAP.add(wss);
|
|
109
110
|
}
|
|
110
111
|
}
|
|
111
112
|
else {
|
|
112
|
-
this.writeFail("TLS/SSL key and cert not found",
|
|
113
|
+
this.writeFail("TLS/SSL key and cert not found", errorMessage('ws', "Missing TLS/SSL credentials"));
|
|
113
114
|
}
|
|
114
115
|
}
|
|
115
116
|
else if (wss = PORT_MAP.get(port.toString())) {
|
|
116
117
|
return wss;
|
|
117
118
|
}
|
|
118
119
|
else {
|
|
119
|
-
wss = new
|
|
120
|
+
wss = new WebSocketServer({ port });
|
|
120
121
|
PORT_MAP.set(port.toString(), wss);
|
|
121
122
|
if (active) {
|
|
122
123
|
STATE_MAP.add(wss);
|
|
@@ -131,19 +132,19 @@ class Watch extends core_1.Client {
|
|
|
131
132
|
}
|
|
132
133
|
wss.on('connection', function (socket) {
|
|
133
134
|
socket.on('message', function () {
|
|
134
|
-
|
|
135
|
+
FileGroup.CLIENT_SESSION.delete(this);
|
|
135
136
|
});
|
|
136
137
|
socket.on('close', function () {
|
|
137
|
-
|
|
138
|
+
FileGroup.CLIENT_SESSION.delete(this);
|
|
138
139
|
});
|
|
139
140
|
for (const client of this.clients) {
|
|
140
|
-
|
|
141
|
+
FileGroup.checkTimeout(client);
|
|
141
142
|
}
|
|
142
143
|
});
|
|
143
144
|
wss.on('error', function (err) {
|
|
144
|
-
const data = JSON.stringify({ event:
|
|
145
|
+
const data = JSON.stringify({ event: WATCH_EVENT.ERROR, errors: [err.message] });
|
|
145
146
|
for (const client of this.clients) {
|
|
146
|
-
if (
|
|
147
|
+
if (FileGroup.checkTimeout(client)) {
|
|
147
148
|
client.send(data);
|
|
148
149
|
}
|
|
149
150
|
}
|
|
@@ -160,19 +161,19 @@ class Watch extends core_1.Client {
|
|
|
160
161
|
closeFileGroup(DISK_MAP);
|
|
161
162
|
closeServer(PORT_MAP);
|
|
162
163
|
closeServer(SECURE_MAP);
|
|
163
|
-
|
|
164
|
+
FileGroup.CLIENT_SESSION.clear();
|
|
164
165
|
STATE_MAP = new WeakSet();
|
|
165
166
|
}
|
|
166
167
|
static checkTimeout(client) {
|
|
167
|
-
return
|
|
168
|
+
return FileGroup.checkTimeout(client);
|
|
168
169
|
}
|
|
169
170
|
static setTimeout(value) {
|
|
170
|
-
if ((value =
|
|
171
|
-
|
|
171
|
+
if ((value = parseTime(value)) > 0) {
|
|
172
|
+
FileGroup.CONNECTION_TIMEOUT = Math.min(value, Client.MAX_TIMEOUT);
|
|
172
173
|
}
|
|
173
174
|
}
|
|
174
175
|
static isConnectionError(err) {
|
|
175
|
-
return
|
|
176
|
+
return checkRetryable(err);
|
|
176
177
|
}
|
|
177
178
|
connectTimeout = Watch.PROCESS_TIMEOUT;
|
|
178
179
|
_moduleName = 'watch';
|
|
@@ -180,7 +181,7 @@ class Watch extends core_1.Client {
|
|
|
180
181
|
_extensions = [];
|
|
181
182
|
_recursiveMap = Object.create(null);
|
|
182
183
|
_hostEvents = [];
|
|
183
|
-
#internal =
|
|
184
|
+
#internal = THRESHOLD.WATCH_INTERVAL;
|
|
184
185
|
#port = 80;
|
|
185
186
|
#securePort = 443;
|
|
186
187
|
#ca = '';
|
|
@@ -195,13 +196,13 @@ class Watch extends core_1.Client {
|
|
|
195
196
|
init(config) {
|
|
196
197
|
const { interval, port, secure } = this.module;
|
|
197
198
|
if (secure) {
|
|
198
|
-
this.securePort =
|
|
199
|
+
this.securePort = asInt(secure.port);
|
|
199
200
|
if (secure.cert && secure.key) {
|
|
200
201
|
this.configureServer(secure);
|
|
201
202
|
}
|
|
202
203
|
}
|
|
203
|
-
this.interval =
|
|
204
|
-
this.port =
|
|
204
|
+
this.interval = asInt(interval);
|
|
205
|
+
this.port = asInt(port);
|
|
205
206
|
return super.init(config);
|
|
206
207
|
}
|
|
207
208
|
start(assets, permission) {
|
|
@@ -214,9 +215,9 @@ class Watch extends core_1.Client {
|
|
|
214
215
|
const settings = this.getUserSettings();
|
|
215
216
|
const destMap = Object.create(null);
|
|
216
217
|
for (const item of assets) {
|
|
217
|
-
if (!
|
|
218
|
+
if (!ignoreFlag(item)) {
|
|
218
219
|
const { bundleId, uri, localUri } = item;
|
|
219
|
-
if (!
|
|
220
|
+
if (!isEmpty(bundleId)) {
|
|
220
221
|
(destMap[':' + bundleId] ||= []).push(item);
|
|
221
222
|
}
|
|
222
223
|
else if (uri && localUri) {
|
|
@@ -242,12 +243,12 @@ class Watch extends core_1.Client {
|
|
|
242
243
|
const related = [];
|
|
243
244
|
for (let i = 0, length = items.length; i < length; ++i) {
|
|
244
245
|
const watch = items[i].watch;
|
|
245
|
-
if (
|
|
246
|
+
if (isObject(watch)) {
|
|
246
247
|
watch.assets?.forEach(other => {
|
|
247
248
|
if (!items.includes(other)) {
|
|
248
|
-
if (
|
|
249
|
+
if (watchFlag(other)) {
|
|
249
250
|
if (!other.watch) {
|
|
250
|
-
other =
|
|
251
|
+
other = FileGroup.cloneAsset(other);
|
|
251
252
|
other.watch = { ...watch };
|
|
252
253
|
}
|
|
253
254
|
other.flags &= ~1;
|
|
@@ -272,16 +273,16 @@ class Watch extends core_1.Client {
|
|
|
272
273
|
watch = false;
|
|
273
274
|
if (uri && !(watch = settings[uri])) {
|
|
274
275
|
for (const pattern in settings) {
|
|
275
|
-
if (
|
|
276
|
+
if (hasGlob(pattern) && pm.isMatch(uri, pattern, { matchBase: true }) && (watch = settings[pattern])) {
|
|
276
277
|
break;
|
|
277
278
|
}
|
|
278
279
|
}
|
|
279
280
|
}
|
|
280
281
|
if (!watch && localUri && !(watch = settings[localUri])) {
|
|
281
|
-
const pathname =
|
|
282
|
-
const options =
|
|
282
|
+
const pathname = Client.PLATFORM_WIN32 ? Client.toPosix(localUri) : localUri;
|
|
283
|
+
const options = Client.PLATFORM_WIN32 ? { matchBase: true, nocase: true, windows: true } : { matchBase: true };
|
|
283
284
|
for (const pattern in settings) {
|
|
284
|
-
if (
|
|
285
|
+
if (hasGlob(pattern) && pm.isMatch(pathname, pattern, options) && (watch = settings[pattern])) {
|
|
285
286
|
break;
|
|
286
287
|
}
|
|
287
288
|
}
|
|
@@ -295,20 +296,20 @@ class Watch extends core_1.Client {
|
|
|
295
296
|
}
|
|
296
297
|
}
|
|
297
298
|
let startTime = Date.now();
|
|
298
|
-
if (
|
|
299
|
+
if (isPlainObject(watch)) {
|
|
299
300
|
const reload = watch.reload;
|
|
300
301
|
id = watch.id;
|
|
301
302
|
if (watch.main) {
|
|
302
303
|
main = item;
|
|
303
304
|
}
|
|
304
305
|
if (watch.start) {
|
|
305
|
-
const offset =
|
|
306
|
+
const offset = parseTime(watch.start);
|
|
306
307
|
if (offset > 0) {
|
|
307
308
|
startTime += offset;
|
|
308
309
|
}
|
|
309
310
|
}
|
|
310
311
|
if (watch.expires) {
|
|
311
|
-
expires =
|
|
312
|
+
expires = parseExpires(watch.expires, startTime);
|
|
312
313
|
}
|
|
313
314
|
if (watch.recursive) {
|
|
314
315
|
recursive = true;
|
|
@@ -327,7 +328,7 @@ class Watch extends core_1.Client {
|
|
|
327
328
|
wss = Watch.createServer(port ||= this.port);
|
|
328
329
|
}
|
|
329
330
|
if (!wss) {
|
|
330
|
-
this.writeFail("Unable to create WebSocket server",
|
|
331
|
+
this.writeFail("Unable to create WebSocket server", errorMessage(secure ? 'wss' : 'ws', "Invalid parameters", 'port: ' + (port || "Unknown")), 16);
|
|
331
332
|
socketId = undefined;
|
|
332
333
|
port = undefined;
|
|
333
334
|
secure = undefined;
|
|
@@ -339,7 +340,7 @@ class Watch extends core_1.Client {
|
|
|
339
340
|
}
|
|
340
341
|
const interval = getInterval(item) || watchInterval || this.interval;
|
|
341
342
|
const watching = (uri, esm) => {
|
|
342
|
-
const group = new
|
|
343
|
+
const group = new FileGroup(uri, main ? assets : items, startTime, this.willAbort("(watch)"), recursive);
|
|
343
344
|
group.add(expires, socketId, id);
|
|
344
345
|
if (main) {
|
|
345
346
|
group.main = main;
|
|
@@ -426,7 +427,7 @@ class Watch extends core_1.Client {
|
|
|
426
427
|
data.set(dest, target);
|
|
427
428
|
return 0;
|
|
428
429
|
};
|
|
429
|
-
if (
|
|
430
|
+
if (Client.isFile(uri, 'http/s')) {
|
|
430
431
|
group.url = item.url;
|
|
431
432
|
group.etag = item.etag;
|
|
432
433
|
group.lastModified = item.lastModified;
|
|
@@ -438,7 +439,7 @@ class Watch extends core_1.Client {
|
|
|
438
439
|
return pre;
|
|
439
440
|
}
|
|
440
441
|
const url = group.url ||= new URL(uri);
|
|
441
|
-
const request = this.host?.Request || new
|
|
442
|
+
const request = this.host?.Request || new Request();
|
|
442
443
|
const agentTimeout = Math.max(timeout.interval * 10, this.connectTimeout);
|
|
443
444
|
const opts = request.opts(url, { method: 'HEAD', httpVersion: 1, timeout: agentTimeout, agentTimeout });
|
|
444
445
|
(function recurse() {
|
|
@@ -450,7 +451,7 @@ class Watch extends core_1.Client {
|
|
|
450
451
|
return;
|
|
451
452
|
}
|
|
452
453
|
if (this.aborted) {
|
|
453
|
-
reject(
|
|
454
|
+
reject(createAbortError());
|
|
454
455
|
return;
|
|
455
456
|
}
|
|
456
457
|
const statusCode = res.statusCode;
|
|
@@ -498,7 +499,7 @@ class Watch extends core_1.Client {
|
|
|
498
499
|
}
|
|
499
500
|
else {
|
|
500
501
|
if (isMap(map)) {
|
|
501
|
-
reject(valid ?
|
|
502
|
+
reject(valid ? errorValue("ETag not supported", uri) : errorMessage(statusCode, "Invalid HTTP request", uri));
|
|
502
503
|
return;
|
|
503
504
|
}
|
|
504
505
|
this.watchExpired(HTTP_MAP, group);
|
|
@@ -517,7 +518,7 @@ class Watch extends core_1.Client {
|
|
|
517
518
|
})
|
|
518
519
|
.on('timeout', () => {
|
|
519
520
|
if (!timeout.aborted && ++timeout.retries > 10) {
|
|
520
|
-
reject(
|
|
521
|
+
reject(errorMessage(408, "HTTP request timeout"));
|
|
521
522
|
}
|
|
522
523
|
else {
|
|
523
524
|
resolve();
|
|
@@ -546,7 +547,7 @@ class Watch extends core_1.Client {
|
|
|
546
547
|
}).call(this);
|
|
547
548
|
HTTP_MAP.set(uri, new Map([[dest, target]]));
|
|
548
549
|
}
|
|
549
|
-
else if (esm || path.isAbsolute(uri =
|
|
550
|
+
else if (esm || path.isAbsolute(uri = Client.resolveFile(uri)) && this.canRead(uri, { hostPermissionOnly: !!this.host })) {
|
|
550
551
|
const pre = checkPreceding(DISK_MAP);
|
|
551
552
|
const options = {};
|
|
552
553
|
let src = uri;
|
|
@@ -575,7 +576,7 @@ class Watch extends core_1.Client {
|
|
|
575
576
|
let ptime = 0;
|
|
576
577
|
target.watcher = fs.watch(src, options, (event, filename) => {
|
|
577
578
|
if (this.aborted || group.aborted) {
|
|
578
|
-
this.#sendFatalError(
|
|
579
|
+
this.#sendFatalError(createAbortError(), DISK_MAP, target);
|
|
579
580
|
return;
|
|
580
581
|
}
|
|
581
582
|
const map = DISK_MAP.get(uri);
|
|
@@ -585,7 +586,7 @@ class Watch extends core_1.Client {
|
|
|
585
586
|
try {
|
|
586
587
|
const mtime = Math.floor(fs.statSync(uri).mtimeMs);
|
|
587
588
|
if (mtime > ptime) {
|
|
588
|
-
ptime = mtime +
|
|
589
|
+
ptime = mtime + THRESHOLD.WATCH_CHANGE;
|
|
589
590
|
if (filename && options.recursive && !group.matchRecursive(path.join(src, filename.toString()))) {
|
|
590
591
|
this.formatMessage(16, 'WATCH', ['File modification ignored', 'recursive'], path.join(src, filename.toString()), { titleColor: 'yellow' });
|
|
591
592
|
return;
|
|
@@ -634,7 +635,7 @@ class Watch extends core_1.Client {
|
|
|
634
635
|
}
|
|
635
636
|
return 0;
|
|
636
637
|
};
|
|
637
|
-
if (
|
|
638
|
+
if (isArray(sourceFiles) && (sourceFiles = sourceFiles.filter(file => this.canRead(file, { hostPermissionOnly: !!this.host }))).length > 0) {
|
|
638
639
|
let index = 0;
|
|
639
640
|
for (const file of Array.from(new Set(sourceFiles)).sort((a, b) => a.length - b.length)) {
|
|
640
641
|
if (index++ > 0) {
|
|
@@ -656,7 +657,7 @@ class Watch extends core_1.Client {
|
|
|
656
657
|
}
|
|
657
658
|
if (status > 0) {
|
|
658
659
|
if (message ||= getErrorMessage(item, status)) {
|
|
659
|
-
this.formatFail((16 | (status === 2 ? 8192 : 0)), 'WATCH', ["Unable to watch file", watched && path.basename(watched)],
|
|
660
|
+
this.formatFail((16 | (status === 2 ? 8192 : 0)), 'WATCH', ["Unable to watch file", watched && path.basename(watched)], errorValue(message, watched), { fatal: false });
|
|
660
661
|
}
|
|
661
662
|
}
|
|
662
663
|
else {
|
|
@@ -670,19 +671,19 @@ class Watch extends core_1.Client {
|
|
|
670
671
|
let message = "File modified", uri = watch.uri;
|
|
671
672
|
if (recursive.length > 0) {
|
|
672
673
|
const time = this.#recursiveTime.get(watch) || 0;
|
|
673
|
-
if (time +
|
|
674
|
+
if (time + THRESHOLD.WATCH_RECURSIVE_CHANGE >= Date.now()) {
|
|
674
675
|
return;
|
|
675
676
|
}
|
|
676
677
|
message = "Directory was modified";
|
|
677
678
|
uri = path.dirname(watch.uri);
|
|
678
679
|
this.#recursiveTime.set(watch, Date.now());
|
|
679
680
|
}
|
|
680
|
-
this.formatMessage(16, 'WATCH', message, uri, { ...
|
|
681
|
+
this.formatMessage(16, 'WATCH', message, uri, { ...Client.LOG_STYLE_WARN });
|
|
681
682
|
const { host, assets } = this;
|
|
682
683
|
let items, sanitize = false;
|
|
683
684
|
if (watch.main) {
|
|
684
685
|
sanitize = watch.assets.length > assets.length;
|
|
685
|
-
items = sanitize ? watch.assets.map(item =>
|
|
686
|
+
items = sanitize ? watch.assets.map(item => FileGroup.cloneAsset(item)) : assets.map(item => cloneObject(item, true));
|
|
686
687
|
}
|
|
687
688
|
else {
|
|
688
689
|
items = [];
|
|
@@ -693,16 +694,16 @@ class Watch extends core_1.Client {
|
|
|
693
694
|
sanitize = true;
|
|
694
695
|
break;
|
|
695
696
|
}
|
|
696
|
-
items.push(
|
|
697
|
+
items.push(cloneObject(item, true));
|
|
697
698
|
}
|
|
698
699
|
}
|
|
699
700
|
else {
|
|
700
701
|
sanitize = true;
|
|
701
702
|
}
|
|
702
703
|
if (sanitize) {
|
|
703
|
-
items = watch.assets.map(item =>
|
|
704
|
+
items = watch.assets.map(item => FileGroup.cloneAsset(item));
|
|
704
705
|
}
|
|
705
|
-
if (
|
|
706
|
+
if (isArray(watch.related)) {
|
|
706
707
|
items.push(...watch.related);
|
|
707
708
|
}
|
|
708
709
|
}
|
|
@@ -737,7 +738,7 @@ class Watch extends core_1.Client {
|
|
|
737
738
|
if (host.hasDocument(instance, watch.document)) {
|
|
738
739
|
const result = instance.watchInit?.(watch, items, sanitize);
|
|
739
740
|
if (result) {
|
|
740
|
-
if (
|
|
741
|
+
if (isArray(result.using)) {
|
|
741
742
|
manager.using(...result.using);
|
|
742
743
|
}
|
|
743
744
|
if (Array.isArray(result.dataSource)) {
|
|
@@ -761,25 +762,25 @@ class Watch extends core_1.Client {
|
|
|
761
762
|
}
|
|
762
763
|
}
|
|
763
764
|
configureServer({ ca, key, cert, passphrase, version, ciphers, config }) {
|
|
764
|
-
if (!
|
|
765
|
+
if (!isString(key) || !isString(cert)) {
|
|
765
766
|
return false;
|
|
766
767
|
}
|
|
767
768
|
if (ca) {
|
|
768
769
|
this.setCA(ca);
|
|
769
770
|
}
|
|
770
|
-
if (
|
|
771
|
+
if (Request.isCert(key) || Client.isPath(key = path.resolve(key)) && this.canRead(key, { ownPermissionOnly: true })) {
|
|
771
772
|
this.#tlsKey = key;
|
|
772
773
|
}
|
|
773
|
-
if (
|
|
774
|
+
if (Request.isCert(cert) || Client.isPath(cert = path.resolve(cert)) && this.canRead(cert, { ownPermissionOnly: true })) {
|
|
774
775
|
this.#tlsCert = cert;
|
|
775
776
|
}
|
|
776
|
-
if (
|
|
777
|
+
if (isString(passphrase)) {
|
|
777
778
|
this.#tlsPassphrase = passphrase;
|
|
778
779
|
}
|
|
779
|
-
if (
|
|
780
|
+
if (isString(ciphers)) {
|
|
780
781
|
this.#ciphers = ciphers;
|
|
781
782
|
}
|
|
782
|
-
if (!
|
|
783
|
+
if (!isPlainObject(config)) {
|
|
783
784
|
config = undefined;
|
|
784
785
|
}
|
|
785
786
|
else if (version ||= config.minVersion) {
|
|
@@ -801,7 +802,7 @@ class Watch extends core_1.Client {
|
|
|
801
802
|
return this.hasSecureProtocol();
|
|
802
803
|
}
|
|
803
804
|
setCA(value) {
|
|
804
|
-
if (
|
|
805
|
+
if (isString(value) && Client.isPath(value = path.resolve(value)) && this.canRead(value, { ownPermissionOnly: true })) {
|
|
805
806
|
this.#ca = value;
|
|
806
807
|
return true;
|
|
807
808
|
}
|
|
@@ -810,10 +811,10 @@ class Watch extends core_1.Client {
|
|
|
810
811
|
setSSLKey(value) {
|
|
811
812
|
this.#tlsConfig = { secureProtocol: 'SSLv23_method' };
|
|
812
813
|
this.#tlsVersion = undefined;
|
|
813
|
-
return !!(this.#tlsKey =
|
|
814
|
+
return !!(this.#tlsKey = Request.readTLSKey(value, true));
|
|
814
815
|
}
|
|
815
816
|
setSSLCert(value) {
|
|
816
|
-
return !!(this.#tlsCert =
|
|
817
|
+
return !!(this.#tlsCert = Request.readTLSCert(value, true));
|
|
817
818
|
}
|
|
818
819
|
hasSecureProtocol() {
|
|
819
820
|
return !!this.#tlsKey && !!this.#tlsCert;
|
|
@@ -850,7 +851,7 @@ class Watch extends core_1.Client {
|
|
|
850
851
|
}
|
|
851
852
|
set host(value) {
|
|
852
853
|
super.host = value;
|
|
853
|
-
if (
|
|
854
|
+
if (isArray(value?.assets)) {
|
|
854
855
|
this.assets = value.assets;
|
|
855
856
|
}
|
|
856
857
|
}
|
|
@@ -861,7 +862,7 @@ class Watch extends core_1.Client {
|
|
|
861
862
|
const length = value.length;
|
|
862
863
|
const items = new Array(length);
|
|
863
864
|
for (let i = 0; i < length; ++i) {
|
|
864
|
-
items[i] = Object.freeze(
|
|
865
|
+
items[i] = Object.freeze(cloneObject(value[i], true));
|
|
865
866
|
}
|
|
866
867
|
this._assets = items;
|
|
867
868
|
}
|
|
@@ -893,4 +894,5 @@ class Watch extends core_1.Client {
|
|
|
893
894
|
return this.#securePort;
|
|
894
895
|
}
|
|
895
896
|
}
|
|
897
|
+
|
|
896
898
|
module.exports = Watch;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@e-mc/watch",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "Watch constructor for E-mc.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -19,10 +19,10 @@
|
|
|
19
19
|
"license": "BSD-3-Clause",
|
|
20
20
|
"homepage": "https://github.com/anpham6/e-mc#readme",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@e-mc/core": "0.
|
|
23
|
-
"@e-mc/request": "0.
|
|
24
|
-
"@e-mc/types": "0.
|
|
25
|
-
"picomatch": "^4.0.
|
|
26
|
-
"ws": "^8.
|
|
22
|
+
"@e-mc/core": "0.14.0",
|
|
23
|
+
"@e-mc/request": "0.14.0",
|
|
24
|
+
"@e-mc/types": "0.14.0",
|
|
25
|
+
"picomatch": "^4.0.4",
|
|
26
|
+
"ws": "^8.20.0"
|
|
27
27
|
}
|
|
28
28
|
}
|