@travetto/compiler 5.0.8 → 5.0.10

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/watch.ts +63 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/compiler",
3
- "version": "5.0.8",
3
+ "version": "5.0.10",
4
4
  "description": "The compiler infrastructure for the Travetto framework",
5
5
  "keywords": [
6
6
  "compiler",
package/src/watch.ts CHANGED
@@ -7,6 +7,9 @@ import { CompilerState } from './state';
7
7
  import { CompilerUtil } from './util';
8
8
 
9
9
  import { AsyncQueue } from '../support/queue';
10
+ import { IpcLogger } from '../support/log';
11
+
12
+ const log = new IpcLogger({ level: 'debug' });
10
13
 
11
14
  type WatchAction = 'create' | 'update' | 'delete';
12
15
  type WatchEvent = { action: WatchAction, file: string };
@@ -19,6 +22,8 @@ type FileShape = {
19
22
  action: WatchAction;
20
23
  };
21
24
 
25
+ const DEFAULT_WRITE_LIMIT = 1000 * 60 * 5;
26
+
22
27
  /**
23
28
  * Watch support, based on compiler state and manifest details
24
29
  */
@@ -31,6 +36,30 @@ export class CompilerWatcher {
31
36
  this.#signal = signal;
32
37
  }
33
38
 
39
+ #watchDog(): { reset(file: string): void, close(): void } {
40
+ let lastWrite = Date.now();
41
+ let writeThreshold = DEFAULT_WRITE_LIMIT;
42
+ log.info('Starting watchdog');
43
+ const value = setInterval(() => {
44
+ if (Date.now() > (lastWrite + writeThreshold)) {
45
+ const delta = (Date.now() - lastWrite) / (1000 * 60);
46
+ log.info(`Watch has not seen changes in ${Math.trunc(delta)}m`);
47
+ writeThreshold += DEFAULT_WRITE_LIMIT;
48
+ }
49
+ }, DEFAULT_WRITE_LIMIT / 10);
50
+ return {
51
+ close: (): void => {
52
+ log.info('Closing watchdog');
53
+ clearInterval(value);
54
+ },
55
+ reset: (file: string): void => {
56
+ log.debug('Resetting watchdog', file);
57
+ lastWrite = Date.now();
58
+ writeThreshold = DEFAULT_WRITE_LIMIT;
59
+ }
60
+ };
61
+ }
62
+
34
63
  #reset(ev: WatchEvent): never {
35
64
  throw new Error('RESET', { cause: `${ev.action}:${ev.file}` });
36
65
  }
@@ -150,26 +179,41 @@ export class CompilerWatcher {
150
179
  }
151
180
 
152
181
  const manifest = this.#state.manifest;
153
- const ROOT_LOCK = path.resolve(manifest.workspace.path, 'package-lock.json');
154
- const ROOT_PKG = path.resolve(manifest.workspace.path, 'package.json');
155
- const OUTPUT_PATH = path.resolve(manifest.workspace.path, manifest.build.outputFolder);
156
- const COMPILER_PATH = path.resolve(manifest.workspace.path, manifest.build.compilerFolder);
182
+ const ROOT = manifest.workspace.path;
183
+ const ROOT_LOCK = 'package-lock.json';
184
+ const ROOT_PKG = 'package.json';
185
+ const OUTPUT_PATH = manifest.build.outputFolder;
186
+ const COMPILER_PATH = manifest.build.compilerFolder;
187
+ const TYPES_PATH = manifest.build.typesFolder;
188
+ const COMPILER_ROOT = path.dirname(COMPILER_PATH);
189
+
190
+ const IGNORE_RE = new RegExp(`^[.]|(${COMPILER_PATH}|${TYPES_PATH}|${OUTPUT_PATH})`);
191
+
192
+ const watchDog = this.#watchDog();
157
193
 
158
- for await (const events of this.#watchFolder(this.#state.manifest.workspace.path)) {
194
+ for await (const events of this.#watchFolder(ROOT)) {
159
195
 
160
196
  const outEvents: CompilerWatchEvent[] = [];
161
197
 
162
198
  for (const ev of events) {
163
199
  const { action, file: sourceFile } = ev;
164
200
 
201
+ const relativeFile = sourceFile.replace(`${ROOT}/`, '');
202
+
165
203
  if (
166
- sourceFile === ROOT_LOCK ||
167
- sourceFile === ROOT_PKG ||
168
- (action === 'delete' && (sourceFile === OUTPUT_PATH || sourceFile === COMPILER_PATH))
204
+ relativeFile === ROOT_LOCK ||
205
+ relativeFile === ROOT_PKG ||
206
+ (action === 'delete' && relativeFile === COMPILER_ROOT)
169
207
  ) {
170
208
  this.#reset(ev);
171
209
  }
172
210
 
211
+ if (IGNORE_RE.test(relativeFile)) {
212
+ continue;
213
+ }
214
+
215
+ watchDog.reset(relativeFile);
216
+
173
217
  const fileType = ManifestModuleUtil.getFileType(sourceFile);
174
218
  if (!CompilerUtil.validFile(fileType)) {
175
219
  continue;
@@ -179,6 +223,7 @@ export class CompilerWatcher {
179
223
 
180
224
  const mod = entry?.module ?? this.#state.manifestIndex.findModuleForArbitraryFile(sourceFile);
181
225
  if (!mod) { // Unknown module
226
+ log.debug(`Unknown module for a given file ${relativeFile}`);
182
227
  continue;
183
228
  }
184
229
 
@@ -188,8 +233,10 @@ export class CompilerWatcher {
188
233
  if (action === 'create') {
189
234
  entry = this.#state.registerInput(mod, moduleFile);
190
235
  } else if (!entry) {
236
+ log.debug(`Unknown file ${relativeFile}`);
191
237
  continue;
192
238
  } else if (action === 'update' && !this.#state.checkIfSourceChanged(entry.sourceFile)) {
239
+ log.debug(`Skipping update, as contents unchanged ${relativeFile}`);
193
240
  continue;
194
241
  } else if (action === 'delete') {
195
242
  this.#state.removeSource(entry.sourceFile);
@@ -198,8 +245,15 @@ export class CompilerWatcher {
198
245
  outEvents.push({ action, file: entry.sourceFile, entry });
199
246
  }
200
247
 
201
- await this.#rebuildManifestsIfNeeded(outEvents);
248
+ try {
249
+ await this.#rebuildManifestsIfNeeded(outEvents);
250
+ } catch (err) {
251
+ log.info('Restarting due to manifest rebuild failure', err);
252
+ this.#reset(events[0]);
253
+ }
202
254
  yield* outEvents;
203
255
  }
256
+
257
+ watchDog.close();
204
258
  }
205
259
  }