@e-mc/watch 0.5.2 → 0.6.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/filegroup/index.js +36 -17
- package/index.js +469 -442
- package/package.json +4 -4
package/filegroup/index.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var _a, _b, _c, _d, _e;
|
|
2
|
+
var _a, _b, _c, _d, _e, _f;
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const util = require("util");
|
|
5
|
+
const ws = require("ws");
|
|
4
6
|
const types_1 = require("../../types");
|
|
5
7
|
const core_1 = require("../../core");
|
|
6
|
-
const kPaused = Symbol('paused');
|
|
7
8
|
const kServer = Symbol('server');
|
|
9
|
+
const kStarted = Symbol('started');
|
|
10
|
+
const kPaused = Symbol('paused');
|
|
8
11
|
const kAssets = Symbol('assets');
|
|
9
12
|
const kSockets = Symbol('sockets');
|
|
10
13
|
const kStartTime = Symbol('startTime');
|
|
@@ -24,21 +27,23 @@ class SocketRequest {
|
|
|
24
27
|
}
|
|
25
28
|
class FileGroup extends core_1.AbortComponent {
|
|
26
29
|
static checkTimeout(client) {
|
|
27
|
-
if (client.readyState
|
|
28
|
-
|
|
29
|
-
if (!lastTime) {
|
|
30
|
-
FileGroup.CLIENT_SESSION.set(client, Date.now());
|
|
31
|
-
}
|
|
32
|
-
else if (FileGroup.CONNECTION_TIMEOUT > 0 && lastTime + FileGroup.CONNECTION_TIMEOUT <= Date.now()) {
|
|
33
|
-
client.terminate();
|
|
34
|
-
return false;
|
|
35
|
-
}
|
|
36
|
-
return true;
|
|
30
|
+
if (client.readyState !== ws.OPEN) {
|
|
31
|
+
return false;
|
|
37
32
|
}
|
|
38
|
-
|
|
33
|
+
const session = this.CLIENT_SESSION;
|
|
34
|
+
const lastTime = session.get(client);
|
|
35
|
+
if (!lastTime) {
|
|
36
|
+
session.set(client, Date.now());
|
|
37
|
+
}
|
|
38
|
+
else if (lastTime + this.CONNECTION_TIMEOUT <= Date.now() && this.CONNECTION_TIMEOUT > 0) {
|
|
39
|
+
client.terminate();
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
return true;
|
|
39
43
|
}
|
|
40
44
|
static cloneAsset(file) {
|
|
41
|
-
|
|
45
|
+
const watch = file.watch;
|
|
46
|
+
return (0, types_1.cloneObject)(file, (0, types_1.isPlainObject)(watch) && (0, types_1.isArray)(watch.assets) ? new WeakSet([watch.assets]) : true);
|
|
42
47
|
}
|
|
43
48
|
constructor(uri, assets, startTime, abortable) {
|
|
44
49
|
super();
|
|
@@ -51,9 +56,10 @@ class FileGroup extends core_1.AbortComponent {
|
|
|
51
56
|
this._abortable = false;
|
|
52
57
|
this[_a] = null;
|
|
53
58
|
this[_b] = false;
|
|
54
|
-
this[_c] =
|
|
59
|
+
this[_c] = false;
|
|
55
60
|
this[_d] = '';
|
|
56
|
-
this[_e] =
|
|
61
|
+
this[_e] = '';
|
|
62
|
+
this[_f] = [];
|
|
57
63
|
this[kUri] = uri;
|
|
58
64
|
this[kAssets] = assets;
|
|
59
65
|
if (typeof startTime === 'boolean') {
|
|
@@ -94,6 +100,16 @@ class FileGroup extends core_1.AbortComponent {
|
|
|
94
100
|
if (server && (data.socketId = this.socketId)) {
|
|
95
101
|
data.event = event;
|
|
96
102
|
data.always ?? (data.always = this.always);
|
|
103
|
+
const value = data.value;
|
|
104
|
+
if (value && (util.types.isAnyArrayBuffer(value) || util.types.isArrayBufferView(value))) {
|
|
105
|
+
try {
|
|
106
|
+
data.value = Buffer.from(value).toString('base64');
|
|
107
|
+
data.encoding = 'base64';
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
delete data.value;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
97
113
|
const outgoing = JSON.stringify(data);
|
|
98
114
|
server.clients.forEach(client => {
|
|
99
115
|
if (FileGroup.checkTimeout(client)) {
|
|
@@ -126,6 +142,9 @@ class FileGroup extends core_1.AbortComponent {
|
|
|
126
142
|
get startTime() {
|
|
127
143
|
return this[kStartTime];
|
|
128
144
|
}
|
|
145
|
+
get started() {
|
|
146
|
+
return this[kStarted] || (this[kStarted] = Date.now() >= this.startTime);
|
|
147
|
+
}
|
|
129
148
|
get assets() {
|
|
130
149
|
return this[kAssets];
|
|
131
150
|
}
|
|
@@ -186,7 +205,7 @@ class FileGroup extends core_1.AbortComponent {
|
|
|
186
205
|
return this._abortable;
|
|
187
206
|
}
|
|
188
207
|
}
|
|
189
|
-
_a = kServer, _b =
|
|
208
|
+
_a = kServer, _b = kStarted, _c = kPaused, _d = kEtag, _e = kLastModified, _f = kSockets;
|
|
190
209
|
FileGroup.CONNECTION_TIMEOUT = 10 * 60000 /* TIME.m */;
|
|
191
210
|
FileGroup.CLIENT_SESSION = new Map();
|
|
192
211
|
exports.default = FileGroup;
|
package/index.js
CHANGED
|
@@ -37,12 +37,36 @@ function isConnectionTimeout(err) {
|
|
|
37
37
|
}
|
|
38
38
|
function abortTimeout(group) {
|
|
39
39
|
group.timeout.aborted = true;
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
const watcher = group.watcher;
|
|
41
|
+
if (watcher) {
|
|
42
|
+
watcher.close();
|
|
42
43
|
group.watcher = null;
|
|
43
44
|
}
|
|
44
45
|
}
|
|
45
|
-
|
|
46
|
+
function getInterval({ watch }) {
|
|
47
|
+
let interval;
|
|
48
|
+
if ((0, types_1.isObject)(watch) && (interval = watch.interval)) {
|
|
49
|
+
if (typeof interval === 'string') {
|
|
50
|
+
interval = (0, types_1.parseTime)(interval);
|
|
51
|
+
}
|
|
52
|
+
if (interval > 0) {
|
|
53
|
+
return interval;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return 0;
|
|
57
|
+
}
|
|
58
|
+
function closeFileGroup(map) {
|
|
59
|
+
for (const uri in map) {
|
|
60
|
+
for (const group of map[uri].values()) {
|
|
61
|
+
abortTimeout(group);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function closeServer(map) {
|
|
66
|
+
for (const port in map) {
|
|
67
|
+
map[port].close(err => err && Watch.writeFail([`Unable to shutdown ${map === PORT_MAP ? 'WS' : 'WSS'} server`, 'port: ' + port], err));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
46
70
|
const formatDate = (value) => new Date(value).toLocaleString().replace(/\/20\d+, /, '@').replace(/:\d+ (AM|PM)$/, (...match) => match[1]);
|
|
47
71
|
class Watch extends core_1.Client {
|
|
48
72
|
static createServer(port, secure, active) {
|
|
@@ -53,79 +77,70 @@ class Watch extends core_1.Client {
|
|
|
53
77
|
let wss;
|
|
54
78
|
try {
|
|
55
79
|
if ((0, types_1.isPlainObject)(secure)) {
|
|
56
|
-
if (
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
else {
|
|
75
|
-
this.writeFail('TLS/SSL key and cert not found', (0, types_1.errorMessage)('ws', 'Missing TLS/SSL credentials'));
|
|
80
|
+
if (wss = SECURE_MAP[port]) {
|
|
81
|
+
return wss;
|
|
82
|
+
}
|
|
83
|
+
const { ca, passphrase, version, config } = secure;
|
|
84
|
+
let { key, cert } = secure;
|
|
85
|
+
if (key && cert && (key = request_1.default.readTLSKey(key, true)) && (cert = request_1.default.readTLSKey(cert, true))) {
|
|
86
|
+
const server = https.createServer({
|
|
87
|
+
...config,
|
|
88
|
+
ca: ca && request_1.default.readCACert(ca, true) || undefined,
|
|
89
|
+
key: passphrase ? [{ pem: key, passphrase }] : key,
|
|
90
|
+
cert,
|
|
91
|
+
minVersion: version || config?.minVersion
|
|
92
|
+
});
|
|
93
|
+
server.listen(port);
|
|
94
|
+
wss = new ws.Server({ server });
|
|
95
|
+
SECURE_MAP[port] = wss;
|
|
96
|
+
if (active) {
|
|
97
|
+
STATE_MAP.add(wss);
|
|
76
98
|
}
|
|
77
99
|
}
|
|
78
100
|
else {
|
|
79
|
-
|
|
101
|
+
this.writeFail('TLS/SSL key and cert not found', (0, types_1.errorMessage)('ws', 'Missing TLS/SSL credentials'));
|
|
80
102
|
}
|
|
81
103
|
}
|
|
82
|
-
else if (
|
|
104
|
+
else if (wss = PORT_MAP[port]) {
|
|
105
|
+
return wss;
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
83
108
|
wss = new ws.Server({ port });
|
|
84
109
|
PORT_MAP[port] = wss;
|
|
85
110
|
if (active) {
|
|
86
111
|
STATE_MAP.add(wss);
|
|
87
112
|
}
|
|
88
113
|
}
|
|
89
|
-
else {
|
|
90
|
-
return wss;
|
|
91
|
-
}
|
|
92
114
|
}
|
|
93
115
|
catch (err) {
|
|
94
116
|
this.writeFail("Unknown" /* ERR_MESSAGE.UNKNOWN */, err);
|
|
95
117
|
}
|
|
96
|
-
if (wss) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
filegroup_1.default.CLIENT_SESSION.delete(this);
|
|
103
|
-
});
|
|
104
|
-
this.clients.forEach(client => filegroup_1.default.checkTimeout(client));
|
|
105
|
-
});
|
|
106
|
-
wss.on('error', function (err) {
|
|
107
|
-
const data = JSON.stringify({ event: types_1.WATCH_EVENT.ERROR, errors: [err.message] });
|
|
108
|
-
this.clients.forEach(client => filegroup_1.default.checkTimeout(client) && client.send(data));
|
|
118
|
+
if (!wss) {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
wss.on('connection', function (socket) {
|
|
122
|
+
socket.on('message', function () {
|
|
123
|
+
filegroup_1.default.CLIENT_SESSION.delete(this);
|
|
109
124
|
});
|
|
110
|
-
|
|
111
|
-
|
|
125
|
+
socket.on('close', function () {
|
|
126
|
+
filegroup_1.default.CLIENT_SESSION.delete(this);
|
|
112
127
|
});
|
|
113
|
-
|
|
114
|
-
}
|
|
128
|
+
this.clients.forEach(client => filegroup_1.default.checkTimeout(client));
|
|
129
|
+
});
|
|
130
|
+
wss.on('error', function (err) {
|
|
131
|
+
const data = JSON.stringify({ event: types_1.WATCH_EVENT.ERROR, errors: [err.message] });
|
|
132
|
+
this.clients.forEach(client => filegroup_1.default.checkTimeout(client) && client.send(data));
|
|
133
|
+
});
|
|
134
|
+
wss.on('close', function () {
|
|
135
|
+
this.clients.forEach(client => client.terminate());
|
|
136
|
+
});
|
|
137
|
+
return wss;
|
|
115
138
|
}
|
|
116
139
|
static shutdown() {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
for (const item of [PORT_MAP, SECURE_MAP]) {
|
|
125
|
-
for (const port in item) {
|
|
126
|
-
item[port].close(err => err && this.writeFail([`Unable to shutdown ${item === PORT_MAP ? 'WS' : 'WSS'} server`, 'port: ' + port], err));
|
|
127
|
-
}
|
|
128
|
-
}
|
|
140
|
+
closeFileGroup(HTTP_MAP);
|
|
141
|
+
closeFileGroup(DISK_MAP);
|
|
142
|
+
closeServer(PORT_MAP);
|
|
143
|
+
closeServer(SECURE_MAP);
|
|
129
144
|
filegroup_1.default.CLIENT_SESSION.clear();
|
|
130
145
|
HTTP_MAP = {};
|
|
131
146
|
DISK_MAP = {};
|
|
@@ -160,7 +175,7 @@ class Watch extends core_1.Client {
|
|
|
160
175
|
let interval;
|
|
161
176
|
if ((0, types_1.isPlainObject)(data)) {
|
|
162
177
|
let secure;
|
|
163
|
-
({ interval, port, secure } = data);
|
|
178
|
+
({ interval, port, secure, extensions } = data);
|
|
164
179
|
if (secure) {
|
|
165
180
|
securePort = secure.port;
|
|
166
181
|
if (secure.cert && secure.key) {
|
|
@@ -171,7 +186,7 @@ class Watch extends core_1.Client {
|
|
|
171
186
|
this.interval = (0, util_1.asInt)(interval);
|
|
172
187
|
this.port = (0, util_1.asInt)(port);
|
|
173
188
|
this.securePort = (0, util_1.asInt)(securePort);
|
|
174
|
-
if (
|
|
189
|
+
if (Array.isArray(extensions)) {
|
|
175
190
|
this.module.extensions = extensions;
|
|
176
191
|
}
|
|
177
192
|
}
|
|
@@ -183,7 +198,6 @@ class Watch extends core_1.Client {
|
|
|
183
198
|
if (permission) {
|
|
184
199
|
this.permission = permission;
|
|
185
200
|
}
|
|
186
|
-
const startTime = Date.now();
|
|
187
201
|
const username = this.host?.username;
|
|
188
202
|
const destMap = Object.create(null);
|
|
189
203
|
for (const item of assets) {
|
|
@@ -216,8 +230,8 @@ class Watch extends core_1.Client {
|
|
|
216
230
|
const related = [];
|
|
217
231
|
for (let i = 0, length = items.length; i < length; ++i) {
|
|
218
232
|
const watch = items[i].watch;
|
|
219
|
-
if ((0, types_1.isObject)(watch)
|
|
220
|
-
watch.assets
|
|
233
|
+
if ((0, types_1.isObject)(watch)) {
|
|
234
|
+
watch.assets?.forEach(other => {
|
|
221
235
|
if (items.includes(other)) {
|
|
222
236
|
return;
|
|
223
237
|
}
|
|
@@ -238,391 +252,403 @@ class Watch extends core_1.Client {
|
|
|
238
252
|
}
|
|
239
253
|
for (const item of items) {
|
|
240
254
|
let { watch, sourceFiles } = item;
|
|
241
|
-
if (watch) {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
return
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
}
|
|
268
|
-
if (!watch && localUri && !(watch = settings[localUri])) {
|
|
269
|
-
for (const pattern in settings) {
|
|
270
|
-
if ((0, types_1.hasGlob)(pattern) && pm.isMatch(localUri, pattern, { nocase: PLATFORM_WIN32 }) && (watch = settings[pattern])) {
|
|
271
|
-
break;
|
|
272
|
-
}
|
|
255
|
+
if (!watch) {
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
const fatalError = (map, target, err) => {
|
|
259
|
+
const uri = target.value.uri;
|
|
260
|
+
delete map[uri];
|
|
261
|
+
abortTimeout(target);
|
|
262
|
+
this.writeFail(["Unable to watch file" /* ERR_MESSAGE.WATCH_FILE */, uri], err, 16 /* LOG_TYPE.WATCH */);
|
|
263
|
+
};
|
|
264
|
+
const watchExpired = (map, target, message = 'Expired') => {
|
|
265
|
+
this.formatMessage(16 /* LOG_TYPE.WATCH */, 'WATCH', [message, target.startTime ? 'since ' + formatDate(target.startTime) : ''], target.uri, { titleColor: 'grey' });
|
|
266
|
+
const data = map[target.uri];
|
|
267
|
+
if (!data || data.size === 0) {
|
|
268
|
+
delete map[target.uri];
|
|
269
|
+
return true;
|
|
270
|
+
}
|
|
271
|
+
return false;
|
|
272
|
+
};
|
|
273
|
+
let expires = 0, status = 0, wss = null, main, id, socketId, port, secure, hot, always, watched, message, settings;
|
|
274
|
+
if (watch === true && username && (settings = this.settings.users?.[username])) {
|
|
275
|
+
const { uri, localUri, mimeType } = item;
|
|
276
|
+
watch = false;
|
|
277
|
+
if (uri && !(watch = settings[uri])) {
|
|
278
|
+
for (const pattern in settings) {
|
|
279
|
+
if ((0, types_1.hasGlob)(pattern) && pm.isMatch(uri, pattern, { matchBase: true }) && (watch = settings[pattern])) {
|
|
280
|
+
break;
|
|
273
281
|
}
|
|
274
282
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
283
|
+
}
|
|
284
|
+
if (!watch && localUri && !(watch = settings[localUri])) {
|
|
285
|
+
for (const pattern in settings) {
|
|
286
|
+
if ((0, types_1.hasGlob)(pattern) && pm.isMatch(localUri, pattern, { nocase: PLATFORM_WIN32 }) && (watch = settings[pattern])) {
|
|
287
|
+
break;
|
|
280
288
|
}
|
|
281
289
|
}
|
|
282
290
|
}
|
|
283
|
-
if (
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
main = item;
|
|
288
|
-
}
|
|
289
|
-
if (watch.expires) {
|
|
290
|
-
expires = (0, types_1.parseExpires)(watch.expires, startTime);
|
|
291
|
-
}
|
|
292
|
-
if (reload && (socketId = reload.socketId)) {
|
|
293
|
-
({ port, module: hot, always } = reload);
|
|
294
|
-
if (reload.secure) {
|
|
295
|
-
const key = this[kTlsKey];
|
|
296
|
-
const cert = this[kTlsCert];
|
|
297
|
-
if (key && cert) {
|
|
298
|
-
wss = Watch.createServer(port || (port = this.securePort), { ca: this[kCa], key, cert, passphrase: this[kTlsPassphrase], version: this[kTlsVersion], config: this[kTlsConfig] });
|
|
299
|
-
}
|
|
300
|
-
secure = true;
|
|
301
|
-
}
|
|
302
|
-
else {
|
|
303
|
-
wss = Watch.createServer(port || (port = this.port));
|
|
304
|
-
}
|
|
305
|
-
if (!wss) {
|
|
306
|
-
this.writeFail('Unable to create WebSocket server', (0, types_1.errorMessage)(secure ? 'wss' : 'ws', "Invalid parameters" /* ERR_MESSAGE.PARAMETERS */, 'port: ' + (port || "Unknown" /* ERR_MESSAGE.UNKNOWN */)), 16 /* LOG_TYPE.WATCH */);
|
|
307
|
-
socketId = undefined;
|
|
308
|
-
port = undefined;
|
|
309
|
-
secure = undefined;
|
|
310
|
-
hot = undefined;
|
|
311
|
-
always = undefined;
|
|
291
|
+
if (!watch && mimeType && !(watch = settings[mimeType])) {
|
|
292
|
+
for (const pattern in settings) {
|
|
293
|
+
if (/^[^*/]+\/\*+$/.test(pattern) && pm.isMatch(mimeType, pattern) && (watch = settings[pattern])) {
|
|
294
|
+
break;
|
|
312
295
|
}
|
|
313
296
|
}
|
|
314
|
-
item.watch = watch;
|
|
315
297
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
if (
|
|
327
|
-
|
|
328
|
-
}
|
|
329
|
-
if (item.document) {
|
|
330
|
-
group.document = item.document;
|
|
298
|
+
}
|
|
299
|
+
let startTime = Date.now();
|
|
300
|
+
if ((0, types_1.isPlainObject)(watch)) {
|
|
301
|
+
const { start, expires: expired, reload } = watch;
|
|
302
|
+
id = watch.id;
|
|
303
|
+
if (watch.main) {
|
|
304
|
+
main = item;
|
|
305
|
+
}
|
|
306
|
+
if (start) {
|
|
307
|
+
const offset = (0, types_1.parseTime)(start);
|
|
308
|
+
if (offset > 0) {
|
|
309
|
+
startTime += offset;
|
|
331
310
|
}
|
|
332
|
-
|
|
333
|
-
|
|
311
|
+
}
|
|
312
|
+
if (expired) {
|
|
313
|
+
expires = (0, types_1.parseExpires)(expired, startTime);
|
|
314
|
+
}
|
|
315
|
+
if (reload && (socketId = reload.socketId)) {
|
|
316
|
+
({ port, module: hot, always } = reload);
|
|
317
|
+
if (reload.secure) {
|
|
318
|
+
const key = this[kTlsKey];
|
|
319
|
+
const cert = this[kTlsCert];
|
|
320
|
+
if (key && cert) {
|
|
321
|
+
wss = Watch.createServer(port || (port = this.securePort), { ca: this[kCa], key, cert, passphrase: this[kTlsPassphrase], version: this[kTlsVersion], config: this[kTlsConfig] });
|
|
322
|
+
}
|
|
323
|
+
secure = true;
|
|
334
324
|
}
|
|
335
|
-
|
|
336
|
-
|
|
325
|
+
else {
|
|
326
|
+
wss = Watch.createServer(port || (port = this.port));
|
|
337
327
|
}
|
|
338
|
-
if (
|
|
339
|
-
|
|
328
|
+
if (!wss) {
|
|
329
|
+
this.writeFail('Unable to create WebSocket server', (0, types_1.errorMessage)(secure ? 'wss' : 'ws', "Invalid parameters" /* ERR_MESSAGE.PARAMETERS */, 'port: ' + (port || "Unknown" /* ERR_MESSAGE.UNKNOWN */)), 16 /* LOG_TYPE.WATCH */);
|
|
330
|
+
socketId = undefined;
|
|
331
|
+
port = undefined;
|
|
332
|
+
secure = undefined;
|
|
333
|
+
hot = undefined;
|
|
334
|
+
always = undefined;
|
|
340
335
|
}
|
|
341
|
-
|
|
342
|
-
|
|
336
|
+
}
|
|
337
|
+
item.watch = watch;
|
|
338
|
+
}
|
|
339
|
+
const interval = getInterval(item) || watchInterval || this.interval;
|
|
340
|
+
const watching = (uri, esm) => {
|
|
341
|
+
const group = new filegroup_1.default(uri, main ? assets : items, startTime, this.willAbort("(watch)" /* ABORT_NAME.WATCH */));
|
|
342
|
+
group.add(expires, socketId, id);
|
|
343
|
+
if (main) {
|
|
344
|
+
group.main = main;
|
|
345
|
+
}
|
|
346
|
+
else if (related.length) {
|
|
347
|
+
group.related = related;
|
|
348
|
+
}
|
|
349
|
+
if (bundleMain) {
|
|
350
|
+
group.bundleMain = bundleMain;
|
|
351
|
+
}
|
|
352
|
+
if (item.document) {
|
|
353
|
+
group.document = item.document;
|
|
354
|
+
}
|
|
355
|
+
if (hot) {
|
|
356
|
+
group.hot = true;
|
|
357
|
+
}
|
|
358
|
+
if (always) {
|
|
359
|
+
group.always = true;
|
|
360
|
+
}
|
|
361
|
+
if (sourceFiles) {
|
|
362
|
+
group.sourceFiles = sourceFiles.filter(file => file !== uri);
|
|
363
|
+
}
|
|
364
|
+
if (wss) {
|
|
365
|
+
group.connection(wss, port, secure);
|
|
366
|
+
}
|
|
367
|
+
const timeout = { interval, retries: 0, aborted: false };
|
|
368
|
+
const target = { value: group, timeout, watcher: null };
|
|
369
|
+
const isMap = (value) => value ? value.size > 0 : false;
|
|
370
|
+
const checkAborted = (result, current) => result?.aborted && current.abortable && current.abort();
|
|
371
|
+
const checkPreceding = (map) => {
|
|
372
|
+
const data = map[uri];
|
|
373
|
+
if (!data) {
|
|
374
|
+
return;
|
|
343
375
|
}
|
|
344
|
-
const
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
if (current && !current.expired) {
|
|
355
|
-
let reset;
|
|
356
|
-
if (id) {
|
|
357
|
-
const sockets = current.sockets;
|
|
358
|
-
for (let i = 0, active; i < sockets.length; ++i) {
|
|
359
|
-
const socket = sockets[i];
|
|
360
|
-
if (socket.id === id) {
|
|
361
|
-
if (active) {
|
|
362
|
-
sockets.splice(i, 1);
|
|
363
|
-
}
|
|
364
|
-
else {
|
|
365
|
-
reset = true;
|
|
366
|
-
}
|
|
367
|
-
break;
|
|
376
|
+
const current = data.get(dest)?.value;
|
|
377
|
+
if (current && !current.expired) {
|
|
378
|
+
let reset;
|
|
379
|
+
if (id) {
|
|
380
|
+
const sockets = current.sockets;
|
|
381
|
+
for (let i = 0, active; i < sockets.length; ++i) {
|
|
382
|
+
const socket = sockets[i];
|
|
383
|
+
if (socket.id === id) {
|
|
384
|
+
if (active) {
|
|
385
|
+
sockets.splice(i, 1);
|
|
368
386
|
}
|
|
369
|
-
|
|
370
|
-
|
|
387
|
+
else {
|
|
388
|
+
reset = true;
|
|
371
389
|
}
|
|
390
|
+
break;
|
|
391
|
+
}
|
|
392
|
+
if (!socket.expired) {
|
|
393
|
+
active = true;
|
|
372
394
|
}
|
|
373
395
|
}
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
else {
|
|
386
|
-
delete PORT_MAP[port];
|
|
387
|
-
}
|
|
388
|
-
wss.close();
|
|
396
|
+
}
|
|
397
|
+
if (!reset) {
|
|
398
|
+
if (wss) {
|
|
399
|
+
const server = current.server;
|
|
400
|
+
if (!server) {
|
|
401
|
+
current.connection(wss, port, secure);
|
|
402
|
+
}
|
|
403
|
+
else if (server !== wss) {
|
|
404
|
+
if (wss.clients.size === 0 && !STATE_MAP.has(wss)) {
|
|
405
|
+
if (secure) {
|
|
406
|
+
delete SECURE_MAP[port];
|
|
389
407
|
}
|
|
390
|
-
|
|
391
|
-
|
|
408
|
+
else {
|
|
409
|
+
delete PORT_MAP[port];
|
|
410
|
+
}
|
|
411
|
+
wss.close();
|
|
392
412
|
}
|
|
413
|
+
message = 'Destination already watched @ ' + (current.secure ? 'wss' : 'ws') + '://hostname:' + current.port;
|
|
414
|
+
return 3 /* ERR.SERVER */;
|
|
393
415
|
}
|
|
394
|
-
const socket = socketId && current.find(socketId);
|
|
395
|
-
if (socket) {
|
|
396
|
-
socket.expires = expires;
|
|
397
|
-
}
|
|
398
|
-
else {
|
|
399
|
-
current.add(expires, socketId, id);
|
|
400
|
-
}
|
|
401
|
-
return 0 /* ERR.NONE */;
|
|
402
416
|
}
|
|
417
|
+
const socket = socketId && current.find(socketId);
|
|
418
|
+
if (socket) {
|
|
419
|
+
socket.expires = expires;
|
|
420
|
+
}
|
|
421
|
+
else {
|
|
422
|
+
current.add(expires, socketId, id);
|
|
423
|
+
}
|
|
424
|
+
return 0 /* ERR.NONE */;
|
|
403
425
|
}
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
426
|
+
}
|
|
427
|
+
data.set(dest, target);
|
|
428
|
+
return 0 /* ERR.NONE */;
|
|
429
|
+
};
|
|
430
|
+
if (core_1.Client.isFile(uri, 'http/s')) {
|
|
431
|
+
group.url = item.url;
|
|
432
|
+
group.etag = item.etag;
|
|
433
|
+
group.lastModified = item.lastModified;
|
|
434
|
+
if (!group.etag && !group.lastModified) {
|
|
435
|
+
return 1 /* ERR.ETAG */;
|
|
436
|
+
}
|
|
437
|
+
if ((status = checkPreceding(HTTP_MAP)) !== undefined) {
|
|
438
|
+
return status;
|
|
439
|
+
}
|
|
440
|
+
const url = group.url || (group.url = new URL(uri));
|
|
441
|
+
const request = this.host?.Request || new request_1.default();
|
|
442
|
+
const agentTimeout = Math.max(timeout.interval * 10, this.connectTimeout);
|
|
443
|
+
const opts = request.opts(url, { method: 'HEAD', httpVersion: 1, timeout: agentTimeout, agentTimeout });
|
|
444
|
+
(function recurse() {
|
|
445
|
+
let client = null;
|
|
446
|
+
new Promise((resolve, reject) => {
|
|
447
|
+
client = request.open(uri, opts)
|
|
448
|
+
.on('response', res => {
|
|
449
|
+
if (group.aborted) {
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
if (this.aborted) {
|
|
453
|
+
reject((0, types_1.createAbortError)());
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
const statusCode = res.statusCode;
|
|
457
|
+
const valid = statusCode >= 200 /* HTTP_STATUS.OK */ && statusCode < 300 /* HTTP_STATUS.MULTIPLE_CHOICES */;
|
|
458
|
+
const map = HTTP_MAP[uri];
|
|
459
|
+
const etag = res.headers.etag;
|
|
460
|
+
const lastModified = res.headers['last-modified'];
|
|
461
|
+
if (valid && map?.size && (etag || lastModified)) {
|
|
462
|
+
for (const [destUrl, input] of map) {
|
|
463
|
+
const value = input.value;
|
|
464
|
+
if (value.paused) {
|
|
465
|
+
continue;
|
|
466
|
+
}
|
|
467
|
+
let aborted = value.aborted;
|
|
468
|
+
if (!aborted) {
|
|
469
|
+
if (value.expired) {
|
|
470
|
+
aborted = true;
|
|
443
471
|
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
else if (value.etag) {
|
|
450
|
-
if (etag) {
|
|
451
|
-
if (etag !== value.etag) {
|
|
452
|
-
value.etag = etag;
|
|
472
|
+
else if (value.etag) {
|
|
473
|
+
if (etag) {
|
|
474
|
+
if (etag !== value.etag) {
|
|
475
|
+
value.etag = etag;
|
|
476
|
+
if (value.started) {
|
|
453
477
|
this.modified(value).then(result => checkAborted(result, value));
|
|
454
478
|
}
|
|
455
479
|
}
|
|
456
480
|
}
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
481
|
+
}
|
|
482
|
+
else if (value.lastModified && lastModified) {
|
|
483
|
+
if (lastModified !== value.lastModified) {
|
|
484
|
+
value.lastModified = lastModified;
|
|
485
|
+
if (value.started) {
|
|
460
486
|
this.modified(value).then(result => checkAborted(result, value));
|
|
461
487
|
}
|
|
462
488
|
}
|
|
463
489
|
}
|
|
464
|
-
if (aborted) {
|
|
465
|
-
map.delete(destUrl);
|
|
466
|
-
if (watchExpired(HTTP_MAP, value)) {
|
|
467
|
-
abortTimeout(target);
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
490
|
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
491
|
+
if (aborted) {
|
|
492
|
+
map.delete(destUrl);
|
|
493
|
+
if (watchExpired(HTTP_MAP, value)) {
|
|
494
|
+
abortTimeout(target);
|
|
495
|
+
}
|
|
476
496
|
}
|
|
477
|
-
watchExpired(HTTP_MAP, group);
|
|
478
|
-
abortTimeout(target);
|
|
479
|
-
}
|
|
480
|
-
if (client) {
|
|
481
|
-
client.destroy();
|
|
482
|
-
}
|
|
483
|
-
resolve();
|
|
484
|
-
})
|
|
485
|
-
.on('error', err => {
|
|
486
|
-
if (!timeout.aborted && !(isConnectionTimeout(err) && ++timeout.retries <= 10 /* HTTP.TIMEOUT_LIMIT */)) {
|
|
487
|
-
reject(err);
|
|
488
|
-
return;
|
|
489
|
-
}
|
|
490
|
-
resolve();
|
|
491
|
-
})
|
|
492
|
-
.on('timeout', () => {
|
|
493
|
-
if (!timeout.aborted && ++timeout.retries > 10 /* HTTP.TIMEOUT_LIMIT */) {
|
|
494
|
-
reject((0, types_1.errorMessage)(408 /* HTTP_STATUS.REQUEST_TIMEOUT */, 'HTTP request timeout'));
|
|
495
|
-
return;
|
|
496
497
|
}
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
})
|
|
500
|
-
.then(() => {
|
|
501
|
-
if (!timeout.aborted) {
|
|
502
|
-
const map = HTTP_MAP[uri];
|
|
498
|
+
}
|
|
499
|
+
else {
|
|
503
500
|
if (isMap(map)) {
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
ms = Math.min(session.timeout.interval, ms);
|
|
507
|
-
}
|
|
508
|
-
setTimeout(recurse.bind(this), timeout.interval = ms);
|
|
509
|
-
}
|
|
510
|
-
else {
|
|
511
|
-
delete HTTP_MAP[uri];
|
|
501
|
+
reject(valid ? (0, types_1.errorValue)('ETag not supported', uri) : (0, types_1.errorMessage)(statusCode, 'Invalid HTTP request', uri));
|
|
502
|
+
return;
|
|
512
503
|
}
|
|
504
|
+
watchExpired(HTTP_MAP, group);
|
|
505
|
+
abortTimeout(target);
|
|
513
506
|
}
|
|
514
|
-
})
|
|
515
|
-
.catch(err => {
|
|
516
|
-
fatalError(HTTP_MAP, target, err);
|
|
517
507
|
if (client) {
|
|
518
508
|
client.destroy();
|
|
519
509
|
}
|
|
510
|
+
resolve();
|
|
511
|
+
})
|
|
512
|
+
.on('error', err => {
|
|
513
|
+
if (!timeout.aborted && !(isConnectionTimeout(err) && ++timeout.retries <= 10 /* HTTP.TIMEOUT_LIMIT */)) {
|
|
514
|
+
reject(err);
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
resolve();
|
|
518
|
+
})
|
|
519
|
+
.on('timeout', () => {
|
|
520
|
+
if (!timeout.aborted && ++timeout.retries > 10 /* HTTP.TIMEOUT_LIMIT */) {
|
|
521
|
+
reject((0, types_1.errorMessage)(408 /* HTTP_STATUS.REQUEST_TIMEOUT */, 'HTTP request timeout'));
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
resolve();
|
|
520
525
|
});
|
|
521
|
-
})
|
|
522
|
-
|
|
526
|
+
})
|
|
527
|
+
.then(() => {
|
|
528
|
+
if (!timeout.aborted) {
|
|
529
|
+
const map = HTTP_MAP[uri];
|
|
530
|
+
if (isMap(map)) {
|
|
531
|
+
let ms = Watch.MAX_TIMEOUT;
|
|
532
|
+
for (const session of map.values()) {
|
|
533
|
+
ms = Math.min(session.timeout.interval, ms);
|
|
534
|
+
}
|
|
535
|
+
setTimeout(recurse.bind(this), timeout.interval = ms);
|
|
536
|
+
}
|
|
537
|
+
else {
|
|
538
|
+
delete HTTP_MAP[uri];
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
})
|
|
542
|
+
.catch(err => {
|
|
543
|
+
fatalError(HTTP_MAP, target, err);
|
|
544
|
+
if (client) {
|
|
545
|
+
client.destroy();
|
|
546
|
+
}
|
|
547
|
+
});
|
|
548
|
+
}).call(this);
|
|
549
|
+
HTTP_MAP[uri] = new Map([[dest, target]]);
|
|
550
|
+
}
|
|
551
|
+
else if (esm || path.isAbsolute(uri = core_1.Client.resolveFile(uri)) && this.canRead(uri, { hostPermissionOnly: !!this.host })) {
|
|
552
|
+
if ((status = checkPreceding(DISK_MAP)) !== undefined) {
|
|
553
|
+
return status;
|
|
523
554
|
}
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
555
|
+
let ptime = 0;
|
|
556
|
+
target.watcher = fs.watch(uri, (event, filename) => {
|
|
557
|
+
if (this.aborted || group.aborted) {
|
|
558
|
+
fatalError(DISK_MAP, target, (0, types_1.createAbortError)());
|
|
559
|
+
return;
|
|
527
560
|
}
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
for (const [key, input] of map) {
|
|
542
|
-
const value = input.value;
|
|
543
|
-
if (value.expired) {
|
|
544
|
-
map.delete(key);
|
|
545
|
-
if (watchExpired(DISK_MAP, value)) {
|
|
546
|
-
abortTimeout(target);
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
else if (value.aborted) {
|
|
550
|
-
map.delete(key);
|
|
551
|
-
if (map.size === 0) {
|
|
552
|
-
abortTimeout(target);
|
|
553
|
-
}
|
|
561
|
+
const map = DISK_MAP[uri];
|
|
562
|
+
switch (event) {
|
|
563
|
+
case 'change': {
|
|
564
|
+
if (isMap(map)) {
|
|
565
|
+
try {
|
|
566
|
+
const mtime = Math.floor(fs.statSync(uri).mtimeMs);
|
|
567
|
+
if (mtime > ptime) {
|
|
568
|
+
for (const [key, input] of map) {
|
|
569
|
+
const value = input.value;
|
|
570
|
+
if (value.expired) {
|
|
571
|
+
map.delete(key);
|
|
572
|
+
if (watchExpired(DISK_MAP, value)) {
|
|
573
|
+
abortTimeout(target);
|
|
554
574
|
}
|
|
555
|
-
|
|
556
|
-
|
|
575
|
+
}
|
|
576
|
+
else if (value.aborted) {
|
|
577
|
+
map.delete(key);
|
|
578
|
+
if (map.size === 0) {
|
|
579
|
+
abortTimeout(target);
|
|
557
580
|
}
|
|
558
581
|
}
|
|
559
|
-
|
|
582
|
+
else if (value.started) {
|
|
583
|
+
this.modified(value).then(result => checkAborted(result, value));
|
|
584
|
+
}
|
|
560
585
|
}
|
|
561
|
-
|
|
562
|
-
}
|
|
563
|
-
catch (err) {
|
|
564
|
-
this.writeFail(["Unable to read file" /* ERR_MESSAGE.READ_FILE */, path.basename(uri)], err, { type: 32 /* LOG_TYPE.FILE */, fatal: false });
|
|
586
|
+
ptime = mtime + types_1.THRESHOLD.WATCH_CHANGE;
|
|
565
587
|
}
|
|
588
|
+
break;
|
|
566
589
|
}
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
if (map) {
|
|
570
|
-
map.clear();
|
|
590
|
+
catch (err) {
|
|
591
|
+
this.writeFail(["Unable to read file" /* ERR_MESSAGE.READ_FILE */, path.basename(uri)], err, { type: 32 /* LOG_TYPE.FILE */, fatal: false });
|
|
571
592
|
}
|
|
572
|
-
|
|
573
|
-
abortTimeout(target);
|
|
574
|
-
break;
|
|
593
|
+
}
|
|
575
594
|
}
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
};
|
|
584
|
-
if ((0, types_1.isArray)(sourceFiles) && sourceFiles.some(file => this.canRead(file, { hostPermissionOnly: !!this.host }))) {
|
|
585
|
-
let index = 0;
|
|
586
|
-
for (const file of new Set(sourceFiles)) {
|
|
587
|
-
if (index++ > 0) {
|
|
588
|
-
watching(file, true);
|
|
589
|
-
}
|
|
590
|
-
else if ((status = watching(watched = file, true)) > 0) {
|
|
591
|
-
break;
|
|
595
|
+
case 'rename':
|
|
596
|
+
if (map) {
|
|
597
|
+
map.clear();
|
|
598
|
+
}
|
|
599
|
+
watchExpired(DISK_MAP, group, event === 'rename' ? 'File renamed: ' + filename : undefined);
|
|
600
|
+
abortTimeout(target);
|
|
601
|
+
break;
|
|
592
602
|
}
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
else if (watched = item.uri) {
|
|
596
|
-
status = watching(watched, false);
|
|
603
|
+
});
|
|
604
|
+
DISK_MAP[uri] = new Map([[dest, target]]);
|
|
597
605
|
}
|
|
598
606
|
else {
|
|
599
|
-
|
|
607
|
+
return 2 /* ERR.LOCAL_ACCESS */;
|
|
600
608
|
}
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
message = 'No read permission';
|
|
612
|
-
break;
|
|
613
|
-
case 3 /* ERR.SERVER */:
|
|
614
|
-
message = 'Server already in use';
|
|
615
|
-
break;
|
|
616
|
-
default:
|
|
617
|
-
message = "Unknown" /* ERR_MESSAGE.UNKNOWN */;
|
|
618
|
-
break;
|
|
619
|
-
}
|
|
609
|
+
return 0 /* ERR.NONE */;
|
|
610
|
+
};
|
|
611
|
+
if ((0, types_1.isArray)(sourceFiles) && sourceFiles.some(file => this.canRead(file, { hostPermissionOnly: !!this.host }))) {
|
|
612
|
+
let index = 0;
|
|
613
|
+
for (const file of new Set(sourceFiles)) {
|
|
614
|
+
if (index++ > 0) {
|
|
615
|
+
watching(file, true);
|
|
616
|
+
}
|
|
617
|
+
else if ((status = watching(watched = file, true)) > 0) {
|
|
618
|
+
break;
|
|
620
619
|
}
|
|
621
|
-
this.formatFail((16 /* LOG_TYPE.WATCH */ | (status === 2 /* ERR.LOCAL_ACCESS */ ? 8192 /* LOG_TYPE.PERMISSION */ : 0)), 'WATCH', ["Unable to watch file" /* ERR_MESSAGE.WATCH_FILE */, watched && path.basename(watched)], (0, types_1.errorValue)(message, watched));
|
|
622
620
|
}
|
|
623
|
-
|
|
624
|
-
|
|
621
|
+
}
|
|
622
|
+
else if (watched = item.uri) {
|
|
623
|
+
status = watching(watched, false);
|
|
624
|
+
}
|
|
625
|
+
else {
|
|
626
|
+
continue;
|
|
627
|
+
}
|
|
628
|
+
if (status > 0) {
|
|
629
|
+
if (!message) {
|
|
630
|
+
switch (status) {
|
|
631
|
+
case 1 /* ERR.ETAG */:
|
|
632
|
+
if ((0, types_1.existsFlag)(item.flags)) {
|
|
633
|
+
continue;
|
|
634
|
+
}
|
|
635
|
+
message = 'ETag unavailable';
|
|
636
|
+
break;
|
|
637
|
+
case 2 /* ERR.LOCAL_ACCESS */:
|
|
638
|
+
message = 'No read permission';
|
|
639
|
+
break;
|
|
640
|
+
case 3 /* ERR.SERVER */:
|
|
641
|
+
message = 'Server already in use';
|
|
642
|
+
break;
|
|
643
|
+
default:
|
|
644
|
+
message = "Unknown" /* ERR_MESSAGE.UNKNOWN */;
|
|
645
|
+
break;
|
|
646
|
+
}
|
|
625
647
|
}
|
|
648
|
+
this.formatFail((16 /* LOG_TYPE.WATCH */ | (status === 2 /* ERR.LOCAL_ACCESS */ ? 8192 /* LOG_TYPE.PERMISSION */ : 0)), 'WATCH', ["Unable to watch file" /* ERR_MESSAGE.WATCH_FILE */, watched && path.basename(watched)], (0, types_1.errorValue)(message, watched));
|
|
649
|
+
}
|
|
650
|
+
else {
|
|
651
|
+
this.formatMessage(16 /* LOG_TYPE.WATCH */, 'WATCH', ['Start', interval + 'ms ' + (expires ? formatDate(expires) : 'never')], watched, { titleColor: 'blue' });
|
|
626
652
|
}
|
|
627
653
|
}
|
|
628
654
|
}
|
|
@@ -678,72 +704,73 @@ class Watch extends core_1.Client {
|
|
|
678
704
|
catch {
|
|
679
705
|
}
|
|
680
706
|
}
|
|
681
|
-
if (manager) {
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
const document = manager.find(instance.moduleName);
|
|
692
|
-
if (document) {
|
|
693
|
-
document.dataSource = result.dataSource;
|
|
694
|
-
}
|
|
695
|
-
}
|
|
707
|
+
if (!manager) {
|
|
708
|
+
return;
|
|
709
|
+
}
|
|
710
|
+
if (host && watch.document) {
|
|
711
|
+
for (const { instance } of host.Document) {
|
|
712
|
+
if (host.hasDocument(instance, watch.document)) {
|
|
713
|
+
const result = instance.watchInit?.(watch, items, sanitize);
|
|
714
|
+
if (result) {
|
|
715
|
+
if ((0, types_1.isArray)(result.using)) {
|
|
716
|
+
manager.using(...result.using);
|
|
696
717
|
}
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
718
|
+
if (Array.isArray(result.dataSource)) {
|
|
719
|
+
const document = manager.find(instance.moduleName);
|
|
720
|
+
if (document) {
|
|
721
|
+
document.dataSource = result.dataSource;
|
|
722
|
+
}
|
|
700
723
|
}
|
|
701
724
|
}
|
|
725
|
+
const listener = instance.watchModified?.(watch, items);
|
|
726
|
+
if (typeof listener === 'function') {
|
|
727
|
+
manager.on('end', listener);
|
|
728
|
+
}
|
|
702
729
|
}
|
|
703
730
|
}
|
|
704
|
-
return await manager.start();
|
|
705
731
|
}
|
|
732
|
+
return await manager.start();
|
|
706
733
|
}
|
|
707
734
|
catch (err) {
|
|
708
735
|
this.writeFail(["Unknown" /* ERR_MESSAGE.UNKNOWN */, watch.url?.pathname || path.basename(watch.uri)], err);
|
|
709
736
|
}
|
|
710
737
|
}
|
|
711
738
|
configureServer({ ca, key, cert, passphrase, version, config }) {
|
|
712
|
-
if ((0, types_1.isString)(key)
|
|
713
|
-
|
|
714
|
-
this.setCA(ca);
|
|
715
|
-
}
|
|
716
|
-
if (request_1.default.isCert(key) || core_1.Client.isPath(key = path.resolve(key = key.trim())) && this.canRead(key, { ownPermissionOnly: true })) {
|
|
717
|
-
this[kTlsKey] = key.trim();
|
|
718
|
-
}
|
|
719
|
-
if (request_1.default.isCert(cert) || core_1.Client.isPath(cert = path.resolve(cert = cert.trim())) && this.canRead(cert, { ownPermissionOnly: true })) {
|
|
720
|
-
this[kTlsCert] = cert.trim();
|
|
721
|
-
}
|
|
722
|
-
if ((0, types_1.isString)(passphrase)) {
|
|
723
|
-
this[kTlsPassphrase] = passphrase;
|
|
724
|
-
}
|
|
725
|
-
if (!(0, types_1.isPlainObject)(config)) {
|
|
726
|
-
config = undefined;
|
|
727
|
-
}
|
|
728
|
-
else if (version || (version = config.minVersion)) {
|
|
729
|
-
delete config.minVersion;
|
|
730
|
-
delete config.secureProtocol;
|
|
731
|
-
}
|
|
732
|
-
switch (version) {
|
|
733
|
-
case 'TLSv1':
|
|
734
|
-
case 'TLSv1.1':
|
|
735
|
-
case 'TLSv1.2':
|
|
736
|
-
case 'TLSv1.3':
|
|
737
|
-
break;
|
|
738
|
-
default:
|
|
739
|
-
version = undefined;
|
|
740
|
-
break;
|
|
741
|
-
}
|
|
742
|
-
this[kTlsConfig] = config;
|
|
743
|
-
this[kTlsVersion] = version;
|
|
744
|
-
return this.hasSecureProtocol();
|
|
739
|
+
if (!(0, types_1.isString)(key) || !(0, types_1.isString)(cert)) {
|
|
740
|
+
return false;
|
|
745
741
|
}
|
|
746
|
-
|
|
742
|
+
if (ca) {
|
|
743
|
+
this.setCA(ca);
|
|
744
|
+
}
|
|
745
|
+
if (request_1.default.isCert(key) || core_1.Client.isPath(key = path.resolve(key = key.trim())) && this.canRead(key, { ownPermissionOnly: true })) {
|
|
746
|
+
this[kTlsKey] = key.trim();
|
|
747
|
+
}
|
|
748
|
+
if (request_1.default.isCert(cert) || core_1.Client.isPath(cert = path.resolve(cert = cert.trim())) && this.canRead(cert, { ownPermissionOnly: true })) {
|
|
749
|
+
this[kTlsCert] = cert.trim();
|
|
750
|
+
}
|
|
751
|
+
if ((0, types_1.isString)(passphrase)) {
|
|
752
|
+
this[kTlsPassphrase] = passphrase;
|
|
753
|
+
}
|
|
754
|
+
if (!(0, types_1.isPlainObject)(config)) {
|
|
755
|
+
config = undefined;
|
|
756
|
+
}
|
|
757
|
+
else if (version || (version = config.minVersion)) {
|
|
758
|
+
delete config.minVersion;
|
|
759
|
+
delete config.secureProtocol;
|
|
760
|
+
}
|
|
761
|
+
switch (version) {
|
|
762
|
+
case 'TLSv1':
|
|
763
|
+
case 'TLSv1.1':
|
|
764
|
+
case 'TLSv1.2':
|
|
765
|
+
case 'TLSv1.3':
|
|
766
|
+
break;
|
|
767
|
+
default:
|
|
768
|
+
version = undefined;
|
|
769
|
+
break;
|
|
770
|
+
}
|
|
771
|
+
this[kTlsConfig] = config;
|
|
772
|
+
this[kTlsVersion] = version;
|
|
773
|
+
return this.hasSecureProtocol();
|
|
747
774
|
}
|
|
748
775
|
setCA(value) {
|
|
749
776
|
if ((0, types_1.isString)(value) && core_1.Client.isPath(value = path.resolve(value = value.trim())) && this.canRead(value, { ownPermissionOnly: true })) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@e-mc/watch",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.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.
|
|
24
|
-
"@e-mc/request": "0.
|
|
25
|
-
"@e-mc/types": "0.
|
|
23
|
+
"@e-mc/core": "0.6.0",
|
|
24
|
+
"@e-mc/request": "0.6.0",
|
|
25
|
+
"@e-mc/types": "0.6.0",
|
|
26
26
|
"picomatch": "^2.3.1",
|
|
27
27
|
"ws": "^8.13.0"
|
|
28
28
|
}
|