@travetto/compiler 7.0.0-rc.0 → 7.0.0-rc.2

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/src/watch.ts CHANGED
@@ -19,15 +19,15 @@ export class CompilerWatcher {
19
19
  #cleanup: Partial<Record<'tool' | 'workspace' | 'canary', () => (void | Promise<void>)>> = {};
20
20
  #watchCanary: string = '.trv/canary.id';
21
21
  #lastWorkspaceModified = Date.now();
22
- #watchCanaryFreq = 5;
22
+ #watchCanaryFrequency = 5;
23
23
  #root: string;
24
- #q: AsyncQueue<CompilerWatchEvent>;
24
+ #queue: AsyncQueue<CompilerWatchEvent>;
25
25
 
26
26
  constructor(state: CompilerState, signal: AbortSignal) {
27
27
  this.#state = state;
28
28
  this.#root = state.manifest.workspace.path;
29
- this.#q = new AsyncQueue(signal);
30
- signal.addEventListener('abort', () => Object.values(this.#cleanup).forEach(x => x()));
29
+ this.#queue = new AsyncQueue(signal);
30
+ signal.addEventListener('abort', () => Object.values(this.#cleanup).forEach(fn => fn()));
31
31
  }
32
32
 
33
33
  async #getWatchIgnores(): Promise<string[]> {
@@ -53,7 +53,7 @@ export class CompilerWatcher {
53
53
  ignores.add(item);
54
54
  }
55
55
  }
56
- return [...ignores].toSorted().map(x => x.endsWith('/') ? x : `${x}/`);
56
+ return [...ignores].toSorted().map(ignore => ignore.endsWith('/') ? ignore : `${ignore}/`);
57
57
  }
58
58
 
59
59
  #toCandidateEvent(action: CompilerWatchEvent['action'], file: string): CompilerWatchEventCandidate {
@@ -69,16 +69,16 @@ export class CompilerWatcher {
69
69
  return { entry, file: entry?.sourceFile ?? file, action };
70
70
  }
71
71
 
72
- #isValidEvent(ev: CompilerWatchEventCandidate): ev is CompilerWatchEvent {
73
- const relativeFile = ev.file.replace(`${this.#root}/`, '');
72
+ #isValidEvent(event: CompilerWatchEventCandidate): event is CompilerWatchEvent {
73
+ const relativeFile = event.file.replace(`${this.#root}/`, '');
74
74
  if (relativeFile === this.#watchCanary) {
75
75
  return false;
76
76
  } else if (relativeFile.startsWith('.')) {
77
77
  return false;
78
- } else if (!ev.entry) {
78
+ } else if (!event.entry) {
79
79
  log.debug(`Skipping unknown file ${relativeFile}`);
80
80
  return false;
81
- } else if (ev.action === 'update' && !this.#state.checkIfSourceChanged(ev.entry.sourceFile)) {
81
+ } else if (event.action === 'update' && !this.#state.checkIfSourceChanged(event.entry.sourceFile)) {
82
82
  log.debug(`Skipping update, as contents unchanged ${relativeFile}`);
83
83
  return false;
84
84
  } else if (!CompilerUtil.validFile(ManifestModuleUtil.getFileType(relativeFile))) {
@@ -89,19 +89,19 @@ export class CompilerWatcher {
89
89
 
90
90
  #getManifestUpdateEventsByParents(events: CompilerWatchEvent[]): Map<string, CompilerWatchEvent[]> {
91
91
  const eventsByMod = new Map<string, CompilerWatchEvent[]>();
92
- for (const ev of events) {
93
- if (ev.action === 'update') {
92
+ for (const event of events) {
93
+ if (event.action === 'update') {
94
94
  continue;
95
95
  }
96
96
 
97
- const mod = ev.entry.module;
98
- const moduleSet = new Set(this.#state.manifestIndex.getDependentModules(mod.name, 'parents').map(x => x.name));
97
+ const mod = event.entry.module;
98
+ const moduleSet = new Set(this.#state.manifestIndex.getDependentModules(mod.name, 'parents').map(indexedMod => indexedMod.name));
99
99
  moduleSet.add(this.#state.manifest.workspace.name);
100
- for (const m of moduleSet) {
101
- if (!eventsByMod.has(m)) {
102
- eventsByMod.set(m, []);
100
+ for (const moduleName of moduleSet) {
101
+ if (!eventsByMod.has(moduleName)) {
102
+ eventsByMod.set(moduleName, []);
103
103
  }
104
- eventsByMod.get(m)!.push(ev);
104
+ eventsByMod.get(moduleName)!.push(event);
105
105
  }
106
106
  }
107
107
  return eventsByMod;
@@ -120,7 +120,7 @@ export class CompilerWatcher {
120
120
  const roleType = ManifestModuleUtil.getFileRole(relativeFile)!;
121
121
 
122
122
  const manifestModuleFiles = manifest.modules[moduleName].files[folderKey] ??= [];
123
- const idx = manifestModuleFiles.findIndex(x => x[0] === relativeFile);
123
+ const idx = manifestModuleFiles.findIndex(indexedFile => indexedFile[0] === relativeFile);
124
124
  const wrappedIdx = idx < 0 ? manifestModuleFiles.length : idx;
125
125
 
126
126
  switch (action) {
@@ -137,8 +137,8 @@ export class CompilerWatcher {
137
137
  const moduleManifest = ManifestUtil.readManifestSync(manifestLocation);
138
138
 
139
139
  log.debug('Updating manifest', { module: mod, events: events.length });
140
- for (const ev of events) {
141
- this.#updateManifestForEvent(ev, moduleManifest);
140
+ for (const event of events) {
141
+ this.#updateManifestForEvent(event, moduleManifest);
142
142
  }
143
143
  await ManifestUtil.writeManifest(moduleManifest);
144
144
  }
@@ -149,44 +149,44 @@ export class CompilerWatcher {
149
149
  async #listenWorkspace(): Promise<void> {
150
150
  const lib = await import('@parcel/watcher');
151
151
  const ignore = await this.#getWatchIgnores();
152
- const packageFiles = new Set(['package-lock.json', 'yarn.lock', 'package.json'].map(x => path.resolve(this.#root, x)));
152
+ const packageFiles = new Set(['package-lock.json', 'yarn.lock', 'package.json'].map(file => path.resolve(this.#root, file)));
153
153
 
154
154
  log.debug('Ignore Globs', ignore);
155
155
  log.debug('Watching', this.#root);
156
156
 
157
157
  await this.#cleanup.workspace?.();
158
158
 
159
- const listener = await lib.subscribe(this.#root, async (err, events) => {
159
+ const listener = await lib.subscribe(this.#root, async (error, events) => {
160
160
  this.#lastWorkspaceModified = Date.now();
161
161
 
162
162
  try {
163
- if (err) {
164
- throw err instanceof Error ? err : new Error(`${err}`);
163
+ if (error) {
164
+ throw error instanceof Error ? error : new Error(`${error}`);
165
165
  } else if (events.length > 25) {
166
166
  throw new CompilerReset(`Large influx of file changes: ${events.length}`);
167
- } else if (events.some(ev => packageFiles.has(path.toPosix(ev.path)))) {
167
+ } else if (events.some(event => packageFiles.has(path.toPosix(event.path)))) {
168
168
  throw new CompilerReset('Package information changed');
169
169
  }
170
170
 
171
171
  const items = events
172
- .map(x => this.#toCandidateEvent(x.type, path.toPosix(x.path)))
173
- .filter(x => this.#isValidEvent(x));
172
+ .map(event => this.#toCandidateEvent(event.type, path.toPosix(event.path)))
173
+ .filter(event => this.#isValidEvent(event));
174
174
 
175
175
  try {
176
176
  await this.#reconcileManifestUpdates(items);
177
- } catch (mErr) {
178
- log.info('Restarting due to manifest rebuild failure', mErr);
179
- throw new CompilerReset(`Manifest rebuild failure: ${mErr}`);
177
+ } catch (manifestError) {
178
+ log.info('Restarting due to manifest rebuild failure', manifestError);
179
+ throw new CompilerReset(`Manifest rebuild failure: ${manifestError}`);
180
180
  }
181
181
 
182
182
  for (const item of items) {
183
- this.#q.add(item);
183
+ this.#queue.add(item);
184
184
  }
185
185
  } catch (out) {
186
186
  if (out instanceof Error && out.message.includes('Events were dropped by the FSEvents client.')) {
187
187
  out = new CompilerReset('FSEvents failure, requires restart');
188
188
  }
189
- return this.#q.throw(out instanceof Error ? out : new Error(`${out}`));
189
+ return this.#queue.throw(out instanceof Error ? out : new Error(`${out}`));
190
190
  }
191
191
  }, { ignore });
192
192
 
@@ -198,20 +198,20 @@ export class CompilerWatcher {
198
198
  const toolRootFolder = path.dirname(path.resolve(this.#root, build.compilerFolder));
199
199
  const toolFolders = new Set([
200
200
  toolRootFolder, build.compilerFolder, build.typesFolder, build.outputFolder
201
- ].map(x => path.resolve(this.#root, x)));
201
+ ].map(folder => path.resolve(this.#root, folder)));
202
202
 
203
- log.debug('Tooling Folders', [...toolFolders].map(x => x.replace(`${this.#root}/`, '')));
203
+ log.debug('Tooling Folders', [...toolFolders].map(folder => folder.replace(`${this.#root}/`, '')));
204
204
 
205
205
  await this.#cleanup.tool?.();
206
206
 
207
- const listener = watch(toolRootFolder, { encoding: 'utf8' }, async (ev, f) => {
208
- if (!f) {
207
+ const listener = watch(toolRootFolder, { encoding: 'utf8' }, async (event, file) => {
208
+ if (!file) {
209
209
  return;
210
210
  }
211
- const full = path.resolve(toolRootFolder, f);
211
+ const full = path.resolve(toolRootFolder, file);
212
212
  const stat = await fs.stat(full).catch(() => null);
213
213
  if (toolFolders.has(full) && !stat) {
214
- this.#q.throw(new CompilerReset(`Tooling folder removal ${full}`));
214
+ this.#queue.throw(new CompilerReset(`Tooling folder removal ${full}`));
215
215
  }
216
216
  });
217
217
  this.#cleanup.tool = (): void => listener.close();
@@ -228,15 +228,15 @@ export class CompilerWatcher {
228
228
  if (delta > 600) {
229
229
  log.error('Restarting canary due to extra long delay');
230
230
  this.#lastWorkspaceModified = Date.now(); // Reset
231
- } else if (delta > this.#watchCanaryFreq * 2) {
232
- this.#q.throw(new CompilerReset(`Workspace watch stopped responding ${delta}s ago`));
233
- } else if (delta > this.#watchCanaryFreq) {
231
+ } else if (delta > this.#watchCanaryFrequency * 2) {
232
+ this.#queue.throw(new CompilerReset(`Workspace watch stopped responding ${delta}s ago`));
233
+ } else if (delta > this.#watchCanaryFrequency) {
234
234
  log.error('Restarting parcel due to inactivity');
235
235
  await this.#listenWorkspace();
236
236
  } else {
237
237
  await fs.utimes(full, new Date(), new Date());
238
238
  }
239
- }, this.#watchCanaryFreq * 1000);
239
+ }, this.#watchCanaryFrequency * 1000);
240
240
 
241
241
  this.#cleanup.canary = (): void => clearInterval(canaryId);
242
242
  }
@@ -247,6 +247,6 @@ export class CompilerWatcher {
247
247
  this.#listenToolFolder();
248
248
  this.#listenCanary();
249
249
  }
250
- return this.#q[Symbol.asyncIterator]();
250
+ return this.#queue[Symbol.asyncIterator]();
251
251
  }
252
252
  }
@@ -19,8 +19,8 @@ export const main = (ctx: ManifestContext) => {
19
19
  Log.initLevel('error');
20
20
 
21
21
  /** Main entry point for compilation */
22
- const compile = async (op: CompilerMode, setupOnly = false): Promise<void> => {
23
- const server = await new CompilerServer(ctx, op).listen();
22
+ const compile = async (operation: CompilerMode, setupOnly = false): Promise<void> => {
23
+ const server = await new CompilerServer(ctx, operation).listen();
24
24
  const log = Log.scoped('main');
25
25
 
26
26
  // Wait for build to be ready
@@ -29,20 +29,20 @@ export const main = (ctx: ManifestContext) => {
29
29
  await server.processEvents(async function* (signal) {
30
30
  const changed = await CompilerSetup.setup(ctx);
31
31
  if (!setupOnly) {
32
- yield* CompilerRunner.runProcess(ctx, changed, op, signal);
32
+ yield* CompilerRunner.runProcess(ctx, changed, operation, signal);
33
33
  }
34
34
  });
35
35
  log.debug('End Server');
36
36
  } else {
37
37
  log.info('Server already running, waiting for initial compile to complete');
38
- const ctrl = new AbortController();
39
- Log.consumeProgressEvents(() => client.fetchEvents('progress', { until: ev => !!ev.complete, signal: ctrl.signal }));
38
+ const controller = new AbortController();
39
+ Log.consumeProgressEvents(() => client.fetchEvents('progress', { until: event => !!event.complete, signal: controller.signal }));
40
40
  await client.waitForState(['compile-end', 'watch-start'], 'Successfully built');
41
- ctrl.abort();
41
+ controller.abort();
42
42
  }
43
43
  };
44
44
 
45
- const ops = {
45
+ const operations = {
46
46
  /** Stop the server */
47
47
  async stop(): Promise<void> {
48
48
  if (await client.stop()) {
@@ -53,7 +53,7 @@ export const main = (ctx: ManifestContext) => {
53
53
  },
54
54
 
55
55
  /** Restart the server */
56
- async restart(): Promise<void> { await client.stop().then(() => ops.watch()); },
56
+ async restart(): Promise<void> { await client.stop().then(() => operations.watch()); },
57
57
 
58
58
  /** Get server info */
59
59
  info: (): Promise<CompilerServerInfo | undefined> => client.info(),
@@ -64,17 +64,17 @@ export const main = (ctx: ManifestContext) => {
64
64
  return console.log(`Clean triggered ${ctx.workspace.path}:`, buildFolders);
65
65
  } else {
66
66
  try {
67
- await Promise.all(buildFolders.map(f => fs.rm(CommonUtil.resolveWorkspace(ctx, f), { force: true, recursive: true })));
67
+ await Promise.all(buildFolders.map(file => fs.rm(CommonUtil.resolveWorkspace(ctx, file), { force: true, recursive: true })));
68
68
  } catch { }
69
69
  return console.log(`Cleaned ${ctx.workspace.path}:`, buildFolders);
70
70
  }
71
71
  },
72
72
 
73
73
  /** Stream events */
74
- events: async (type: string, handler: (ev: unknown) => unknown): Promise<void> => {
74
+ events: async (type: string, handler: (event: unknown) => unknown): Promise<void> => {
75
75
  if (type === 'change' || type === 'log' || type === 'progress' || type === 'state' || type === 'all') {
76
76
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
77
- for await (const ev of client.fetchEvents(type as 'change')) { await handler(ev); }
77
+ for await (const event of client.fetchEvents(type as 'change')) { await handler(event); }
78
78
  } else {
79
79
  throw new Error(`Unknown event type: ${type}`);
80
80
  }
@@ -113,7 +113,7 @@ export const main = (ctx: ManifestContext) => {
113
113
  await CompilerSetup.exportManifest(ctx, output, prod); return;
114
114
  }
115
115
  };
116
- return ops;
116
+ return operations;
117
117
  };
118
118
 
119
119
  export type Operations = ReturnType<typeof main>;
package/support/log.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { CompilerLogEvent, CompilerLogLevel, CompilerProgressEvent } from './types.ts';
2
2
 
3
- const LEVEL_TO_PRI: Record<CompilerLogLevel | 'none', number> = { debug: 1, info: 2, warn: 3, error: 4, none: 5 };
3
+ const LEVEL_TO_PRIORITY: Record<CompilerLogLevel | 'none', number> = { debug: 1, info: 2, warn: 3, error: 4, none: 5 };
4
4
  const SCOPE_MAX = 15;
5
5
 
6
6
  type LogConfig = {
@@ -31,7 +31,7 @@ export class Logger implements LogConfig, LogShape {
31
31
  const done = process.stdout.write(`${ESC}1G${text}${ESC}0K`);
32
32
  this.#linePartial = !!text;
33
33
  if (!done) {
34
- return new Promise<void>(r => process.stdout.once('drain', r));
34
+ return new Promise<void>(resolve => process.stdout.once('drain', resolve));
35
35
  }
36
36
  }
37
37
 
@@ -42,25 +42,27 @@ export class Logger implements LogConfig, LogShape {
42
42
  scope?: string;
43
43
  parent?: Logger;
44
44
 
45
- constructor(cfg: LogConfig = {}) {
46
- Object.assign(this, cfg);
45
+ constructor(config: LogConfig = {}) {
46
+ Object.assign(this, config);
47
47
  }
48
48
 
49
- valid(ev: CompilerLogEvent): boolean {
50
- return LEVEL_TO_PRI[this.level ?? this.parent?.level!] <= LEVEL_TO_PRI[ev.level];
49
+ valid(event: CompilerLogEvent): boolean {
50
+ return LEVEL_TO_PRIORITY[this.level ?? this.parent?.level!] <= LEVEL_TO_PRIORITY[event.level];
51
51
  }
52
52
 
53
53
  /** Log event with filtering by level */
54
- render(ev: CompilerLogEvent): void {
55
- if (!this.valid(ev)) { return; }
56
- const params = [ev.message, ...ev.args ?? []].map(x => typeof x === 'string' ? x.replaceAll(this.root ?? this.parent?.root!, '.') : x);
57
- if (ev.scope ?? this.scope) {
58
- params.unshift(`[${(ev.scope ?? this.scope!).padEnd(SCOPE_MAX, ' ')}]`);
54
+ render(event: CompilerLogEvent): void {
55
+ if (!this.valid(event)) { return; }
56
+ const params = [event.message, ...event.args ?? []]
57
+ .map(arg => typeof arg === 'string' ? arg.replaceAll(this.root ?? this.parent?.root!, '.') : arg);
58
+
59
+ if (event.scope ?? this.scope) {
60
+ params.unshift(`[${(event.scope ?? this.scope!).padEnd(SCOPE_MAX, ' ')}]`);
59
61
  }
60
- params.unshift(new Date().toISOString(), `${ev.level.padEnd(5)}`);
62
+ params.unshift(new Date().toISOString(), `${event.level.padEnd(5)}`);
61
63
  Logger.rewriteLine(''); // Clear out progress line, if active
62
64
  // eslint-disable-next-line no-console
63
- console[ev.level]!(...params);
65
+ console[event.level]!(...params);
64
66
  }
65
67
 
66
68
  info(message: string, ...args: unknown[]): void { return this.render({ level: 'info', message, args }); }
@@ -82,9 +84,9 @@ class $RootLogger extends Logger {
82
84
 
83
85
  /** Set level for operation */
84
86
  initLevel(defaultLevel: CompilerLogLevel | 'none'): void {
85
- const val = process.env.TRV_QUIET !== 'true' ? process.env.TRV_BUILD : 'none';
86
- switch (val) {
87
- case 'debug': case 'warn': case 'error': case 'info': this.level = val; break;
87
+ const value = process.env.TRV_QUIET !== 'true' ? process.env.TRV_BUILD : 'none';
88
+ switch (value) {
89
+ case 'debug': case 'warn': case 'error': case 'info': this.level = value; break;
88
90
  case undefined: this.level = defaultLevel; break;
89
91
  case 'none': default: this.level = 'none';
90
92
  }
@@ -96,23 +98,23 @@ class $RootLogger extends Logger {
96
98
  }
97
99
 
98
100
  /** Scope and provide a callback pattern for access to a logger */
99
- wrap<T = unknown>(scope: string, op: (log: Logger) => Promise<T>, basic = true): Promise<T> {
100
- const l = this.scoped(scope);
101
- return basic ? (l.debug('Started'), op(l).finally(() => l.debug('Completed'))) : op(l);
101
+ wrap<T = unknown>(scope: string, operation: (log: Logger) => Promise<T>, basic = true): Promise<T> {
102
+ const logger = this.scoped(scope);
103
+ return basic ? (logger.debug('Started'), operation(logger).finally(() => logger.debug('Completed'))) : operation(logger);
102
104
  }
103
105
 
104
106
  /** Write progress event, if active */
105
- onProgressEvent(ev: CompilerProgressEvent): void | Promise<void> {
107
+ onProgressEvent(event: CompilerProgressEvent): void | Promise<void> {
106
108
  if (!(this.logProgress)) { return; }
107
- const pct = Math.trunc(ev.idx * 100 / ev.total);
108
- const text = ev.complete ? '' : `Compiling [${'#'.repeat(Math.trunc(pct / 10)).padEnd(10, ' ')}] [${ev.idx}/${ev.total}] ${ev.message}`;
109
+ const progress = Math.trunc(event.idx * 100 / event.total);
110
+ const text = event.complete ? '' : `Compiling [${'#'.repeat(Math.trunc(progress / 10)).padEnd(10, ' ')}] [${event.idx}/${event.total}] ${event.message}`;
109
111
  return Logger.rewriteLine(text);
110
112
  }
111
113
 
112
114
  /** Write all progress events if active */
113
- async consumeProgressEvents(src: () => AsyncIterable<CompilerProgressEvent>): Promise<void> {
115
+ async consumeProgressEvents(input: () => AsyncIterable<CompilerProgressEvent>): Promise<void> {
114
116
  if (!(this.logProgress)) { return; }
115
- for await (const ev of src()) { this.onProgressEvent(ev); }
117
+ for await (const event of input()) { this.onProgressEvent(event); }
116
118
  Logger.reset();
117
119
  }
118
120
  }
@@ -120,13 +122,13 @@ class $RootLogger extends Logger {
120
122
  export const Log = new $RootLogger();
121
123
 
122
124
  export class IpcLogger extends Logger {
123
- render(ev: CompilerLogEvent): void {
124
- if (!this.valid(ev)) { return; }
125
+ render(event: CompilerLogEvent): void {
126
+ if (!this.valid(event)) { return; }
125
127
  if (process.connected && process.send) {
126
- process.send({ type: 'log', payload: ev });
128
+ process.send({ type: 'log', payload: event });
127
129
  }
128
130
  if (!process.connected) {
129
- super.render(ev);
131
+ super.render(event);
130
132
  }
131
133
  }
132
134
  }
package/support/queue.ts CHANGED
@@ -1,15 +1,7 @@
1
- type PromiseResolver<T> = { resolve: (v: T) => void, reject: (err?: unknown) => void };
2
-
3
- function resolvablePromise<T = void>(): Promise<T> & PromiseResolver<T> {
4
- let ops: PromiseResolver<T>;
5
- const prom = new Promise<T>((resolve, reject) => ops = { resolve, reject });
6
- return Object.assign(prom, ops!);
7
- }
8
-
9
1
  export class AsyncQueue<X> implements AsyncIterator<X>, AsyncIterable<X> {
10
2
  #queue: X[] = [];
11
3
  #done = false;
12
- #ready = resolvablePromise();
4
+ #ready = Promise.withResolvers<void>();
13
5
 
14
6
  constructor(signal?: AbortSignal) {
15
7
  signal?.addEventListener('abort', () => this.close());
@@ -22,15 +14,15 @@ export class AsyncQueue<X> implements AsyncIterator<X>, AsyncIterable<X> {
22
14
 
23
15
  async next(): Promise<IteratorResult<X>> {
24
16
  while (!this.#done && !this.#queue.length) {
25
- await this.#ready;
26
- this.#ready = resolvablePromise();
17
+ await this.#ready.promise;
18
+ this.#ready = Promise.withResolvers<void>();
27
19
  }
28
20
  return { value: (this.#queue.length ? this.#queue.shift() : undefined)!, done: this.#done };
29
21
  }
30
22
 
31
- async throw(e?: Error): Promise<IteratorResult<X>> {
23
+ async throw(error?: Error): Promise<IteratorResult<X>> {
32
24
  this.#done = true;
33
- this.#ready.reject(e);
25
+ this.#ready.reject(error);
34
26
  return { value: undefined, done: this.#done };
35
27
  }
36
28
 
@@ -11,7 +11,7 @@ import { ProcessHandle } from './process-handle.ts';
11
11
 
12
12
  type FetchEventsConfig<T> = {
13
13
  signal?: AbortSignal;
14
- until?: (ev: T) => boolean;
14
+ until?: (event: T) => boolean;
15
15
  enforceIteration?: boolean;
16
16
  };
17
17
 
@@ -44,26 +44,26 @@ export class CompilerClient {
44
44
  return this.#url;
45
45
  }
46
46
 
47
- async #fetch(rel: string, opts?: RequestInit & { timeout?: number }, logTimeout = true): Promise<{ ok: boolean, text: string }> {
48
- const ctrl = new AbortController();
49
- const timeoutCtrl = new AbortController();
47
+ async #fetch(urlPath: string, options?: RequestInit & { timeout?: number }, logTimeout = true): Promise<{ ok: boolean, text: string }> {
48
+ const controller = new AbortController();
49
+ const timeoutController = new AbortController();
50
50
 
51
- opts?.signal?.addEventListener('abort', () => ctrl.abort());
52
- timers.setTimeout(opts?.timeout ?? 100, undefined, { ref: false, signal: timeoutCtrl.signal })
51
+ options?.signal?.addEventListener('abort', () => controller.abort());
52
+ timers.setTimeout(options?.timeout ?? 100, undefined, { ref: false, signal: timeoutController.signal })
53
53
  .then(() => {
54
- logTimeout && this.#log.error(`Timeout on request to ${this.#url}${rel}`);
55
- ctrl.abort('TIMEOUT');
54
+ logTimeout && this.#log.error(`Timeout on request to ${this.#url}${urlPath}`);
55
+ controller.abort('TIMEOUT');
56
56
  })
57
57
  .catch(() => { });
58
- const response = await fetch(`${this.#url}${rel}`, { ...opts, signal: ctrl.signal });
58
+ const response = await fetch(`${this.#url}${urlPath}`, { ...options, signal: controller.signal });
59
59
  const out = { ok: response.ok, text: await response.text() };
60
- timeoutCtrl.abort();
60
+ timeoutController.abort();
61
61
  return out;
62
62
  }
63
63
 
64
64
  /** Get server information, if server is running */
65
65
  info(): Promise<CompilerServerInfo | undefined> {
66
- return this.#fetch('/info', { timeout: 200 }, false).then(v => JSON.parse(v.text), () => undefined);
66
+ return this.#fetch('/info', { timeout: 200 }, false).then(response => JSON.parse(response.text), () => undefined);
67
67
  }
68
68
 
69
69
  async isWatching(): Promise<boolean> {
@@ -72,7 +72,7 @@ export class CompilerClient {
72
72
 
73
73
  /** Clean the server */
74
74
  clean(): Promise<boolean> {
75
- return this.#fetch('/clean', { timeout: 300 }).then(v => v.ok, () => false);
75
+ return this.#fetch('/clean', { timeout: 300 }).then(response => response.ok, () => false);
76
76
  }
77
77
 
78
78
  /** Stop server and wait for shutdown */
@@ -81,7 +81,7 @@ export class CompilerClient {
81
81
  if (!info) {
82
82
  this.#log.debug('Stopping server, info not found, manual killing');
83
83
  return Promise.all([this.#handle.server.kill(), this.#handle.compiler.kill()])
84
- .then(v => v.some(x => x));
84
+ .then(results => results.some(result => result));
85
85
  }
86
86
 
87
87
  await this.#fetch('/stop').catch(() => { }); // Trigger
@@ -94,9 +94,9 @@ export class CompilerClient {
94
94
  fetchEvents<
95
95
  V extends CompilerEventType,
96
96
  T extends (CompilerEvent & { type: V })['payload']
97
- >(type: V, cfg?: FetchEventsConfig<T>): AsyncIterable<T>;
98
- fetchEvents(type: 'all', cfg?: FetchEventsConfig<CompilerEvent>): AsyncIterable<CompilerEvent>;
99
- async * fetchEvents<T = unknown>(type: string, cfg: FetchEventsConfig<T> = {}): AsyncIterable<T> {
97
+ >(type: V, config?: FetchEventsConfig<T>): AsyncIterable<T>;
98
+ fetchEvents(type: 'all', config?: FetchEventsConfig<CompilerEvent>): AsyncIterable<CompilerEvent>;
99
+ async * fetchEvents<T = unknown>(type: string, config: FetchEventsConfig<T> = {}): AsyncIterable<T> {
100
100
  let info = await this.info();
101
101
  if (!info) {
102
102
  return;
@@ -104,40 +104,40 @@ export class CompilerClient {
104
104
 
105
105
  this.#log.debug(`Starting watch for events of type "${type}"`);
106
106
 
107
- let signal = cfg.signal;
107
+ let signal = config.signal;
108
108
 
109
109
  // Ensure we capture end of process at least
110
110
  if (!signal) {
111
- const ctrl = new AbortController();
112
- process.on('SIGINT', () => ctrl.abort());
113
- signal = ctrl.signal;
111
+ const controller = new AbortController();
112
+ process.on('SIGINT', () => controller.abort());
113
+ signal = controller.signal;
114
114
  }
115
115
 
116
116
  const { iteration } = info;
117
117
 
118
118
  for (; ;) {
119
- const ctrl = new AbortController();
120
- const quit = (): void => ctrl.abort();
119
+ const controller = new AbortController();
120
+ const quit = (): void => controller.abort();
121
121
  try {
122
122
  signal.addEventListener('abort', quit);
123
123
  const response = await new Promise<http.IncomingMessage>((resolve, reject) =>
124
- http.get(`${this.#url}/event/${type}`, { agent: streamAgent, signal: ctrl.signal }, resolve)
124
+ http.get(`${this.#url}/event/${type}`, { agent: streamAgent, signal: controller.signal }, resolve)
125
125
  .on('error', reject)
126
126
  );
127
127
 
128
128
  for await (const line of rl.createInterface(response)) {
129
129
  if (line.trim().charAt(0) === '{') {
130
- const val: T = JSON.parse(line);
131
- if (cfg.until?.(val)) {
130
+ const event: T = JSON.parse(line);
131
+ if (config.until?.(event)) {
132
132
  await CommonUtil.queueMacroTask();
133
- ctrl.abort();
133
+ controller.abort();
134
134
  }
135
- yield val;
135
+ yield event;
136
136
  }
137
137
  }
138
- } catch (err) {
139
- const aborted = ctrl.signal.aborted || (typeof err === 'object' && err && 'code' in err && err.code === 'ECONNRESET');
140
- if (!aborted) { throw err; }
138
+ } catch (error) {
139
+ const aborted = controller.signal.aborted || (typeof error === 'object' && error && 'code' in error && error.code === 'ECONNRESET');
140
+ if (!aborted) { throw error; }
141
141
  }
142
142
  signal.removeEventListener('abort', quit);
143
143
 
@@ -145,12 +145,12 @@ export class CompilerClient {
145
145
 
146
146
  info = await this.info();
147
147
 
148
- if (ctrl.signal.reason === 'TIMEOUT') {
148
+ if (controller.signal.reason === 'TIMEOUT') {
149
149
  this.#log.debug('Failed due to timeout');
150
150
  return;
151
151
  }
152
152
 
153
- if (ctrl.signal.aborted || !info || (cfg.enforceIteration && info.iteration !== iteration)) { // If health check fails, or aborted
153
+ if (controller.signal.aborted || !info || (config.enforceIteration && info.iteration !== iteration)) { // If health check fails, or aborted
154
154
  this.#log.debug(`Stopping watch for events of type "${type}"`);
155
155
  return;
156
156
  } else {
@@ -164,7 +164,7 @@ export class CompilerClient {
164
164
  const set = new Set(states);
165
165
  // Loop until
166
166
  this.#log.debug(`Waiting for states, ${states.join(', ')}`);
167
- for await (const _ of this.fetchEvents('state', { signal, until: s => set.has(s.state) })) { }
167
+ for await (const _ of this.fetchEvents('state', { signal, until: event => set.has(event.state) })) { }
168
168
  this.#log.debug(`Found state, one of ${states.join(', ')} `);
169
169
  if (message) {
170
170
  this.#log.info(message);