@travetto/compiler 4.0.0-rc.3 → 4.0.0-rc.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/compiler",
3
- "version": "4.0.0-rc.3",
3
+ "version": "4.0.0-rc.5",
4
4
  "description": "The compiler infrastructure for the Travetto framework",
5
5
  "keywords": [
6
6
  "compiler",
@@ -31,12 +31,12 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@parcel/watcher": "^2.4.0",
34
- "@travetto/manifest": "^4.0.0-rc.3",
35
- "@travetto/transformer": "^4.0.0-rc.3",
34
+ "@travetto/manifest": "^4.0.0-rc.5",
35
+ "@travetto/transformer": "^4.0.0-rc.5",
36
36
  "@types/node": "^20.11.16"
37
37
  },
38
38
  "peerDependencies": {
39
- "@travetto/cli": "^4.0.0-rc.4"
39
+ "@travetto/cli": "^4.0.0-rc.6"
40
40
  },
41
41
  "peerDependenciesMeta": {
42
42
  "@travetto/cli": {
package/src/compiler.ts CHANGED
@@ -70,7 +70,7 @@ export class Compiler {
70
70
  break;
71
71
  }
72
72
  case 'reset': {
73
- Log.info('Triggering reset due to change in core files');
73
+ Log.info('Triggering reset due to change in core files', err?.cause);
74
74
  EventUtil.sendEvent('state', { state: 'reset' });
75
75
  process.exitCode = 0;
76
76
  break;
package/src/watch.ts CHANGED
@@ -128,7 +128,7 @@ export class CompilerWatcher {
128
128
  sourceFile === ROOT_PKG ||
129
129
  (action === 'delete' && (sourceFile === OUTPUT_PATH || sourceFile === COMPILER_PATH))
130
130
  ) {
131
- throw new Error('RESET');
131
+ throw new Error('RESET', { cause: `${action}:${sourceFile}` });
132
132
  }
133
133
 
134
134
  const fileType = ManifestModuleUtil.getFileType(sourceFile);
@@ -47,6 +47,7 @@ export const main = (ctx: ManifestContext) => {
47
47
  const ops = {
48
48
  /** Stop the server */
49
49
  async stop(): Promise<void> {
50
+ LogUtil.initLogs(ctx);
50
51
  if (await client.stop()) {
51
52
  console.log(`Stopped server ${ctx.workspace.path}: ${client}`);
52
53
  } else {
@@ -62,6 +63,7 @@ export const main = (ctx: ManifestContext) => {
62
63
 
63
64
  /** Clean the server */
64
65
  async clean(): Promise<void> {
66
+ LogUtil.initLogs(ctx);
65
67
  if (await client.clean()) {
66
68
  return console.log(`Clean triggered ${ctx.workspace.path}:`, buildFolders);
67
69
  } else {
@@ -90,7 +92,7 @@ export const main = (ctx: ManifestContext) => {
90
92
  async getLoader(): Promise<(mod: string) => Promise<unknown>> {
91
93
  // Short circuit if we can
92
94
  if (!(await client.isWatching())) {
93
- await compile('build', 'error');
95
+ await compile('build', LogUtil.isInteractiveShell ? 'info' : 'error');
94
96
  }
95
97
  return CommonUtil.moduleLoader(ctx);
96
98
  },
package/support/log.ts CHANGED
@@ -31,10 +31,15 @@ export class LogUtil {
31
31
  }
32
32
  }
33
33
 
34
+ /** Are we in a shell that is interactive */
35
+ static get isInteractiveShell(): boolean {
36
+ return !!process.env.PS1 && process.stdout.isTTY;
37
+ }
38
+
34
39
  /**
35
40
  * Set level for operation
36
41
  */
37
- static initLogs(ctx: ManifestContext, defaultLevel: CompilerLogLevel): void {
42
+ static initLogs(ctx: ManifestContext, defaultLevel?: CompilerLogLevel): void {
38
43
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
39
44
  const build = process.env.TRV_BUILD as CompilerLogLevel | 'none';
40
45
  if (build !== 'none' && process.env.TRV_QUIET !== 'true') {
@@ -42,7 +47,7 @@ export class LogUtil {
42
47
  }
43
48
  this.root = ctx.workspace.path;
44
49
  // If we are in info or a terminal and also in a tty
45
- this.logProgress = ((this.isLevelActive('info') || process.env.PS1) && process.stdout.isTTY) ? this.#logProgressEvent : undefined;
50
+ this.logProgress = (this.isLevelActive('info') && process.stdout.isTTY) ? this.#logProgressEvent : undefined;
46
51
  if (this.logProgress) {
47
52
  process.stdout.write(`${ESC}?25l`); // Hide cursor
48
53
  }
@@ -43,7 +43,7 @@ export class CompilerClient {
43
43
  const timeoutId = setTimeout(() => {
44
44
  logTimeout && this.#log('error', `Timeout on request to ${this.#url}${rel}`);
45
45
  ctrl.abort('TIMEOUT');
46
- }, 100).unref();
46
+ }, opts?.timeout ?? 100).unref();
47
47
  try {
48
48
  return await fetch(`${this.#url}${rel}`, { ...opts, signal: ctrl.signal });
49
49
  } finally {
@@ -53,7 +53,7 @@ export class CompilerClient {
53
53
 
54
54
  /** Get server information, if server is running */
55
55
  info(): Promise<CompilerServerInfo | undefined> {
56
- return this.#fetch('/info', {}, false).then(v => v.json(), () => undefined)
56
+ return this.#fetch('/info', { timeout: 200 }, false).then(v => v.json(), () => undefined)
57
57
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
58
58
  .then(v => v as CompilerServerInfo);
59
59
  }
@@ -3,13 +3,16 @@ import path from 'node:path';
3
3
  import timers from 'node:timers/promises';
4
4
 
5
5
  import type { ManifestContext } from '@travetto/manifest';
6
+ import { CompilerLogger, LogUtil } from '../log';
6
7
 
7
8
  export class ProcessHandle {
8
9
 
9
10
  #file: string;
11
+ #log: CompilerLogger;
10
12
 
11
13
  constructor(ctx: ManifestContext, name: string) {
12
14
  this.#file = path.resolve(ctx.workspace.path, ctx.build.toolFolder, `${name}.pid`);
15
+ this.#log = LogUtil.logger(`process-handle.${name}`);
13
16
  }
14
17
 
15
18
  async writePid(pid: number): Promise<void> {
@@ -26,15 +29,19 @@ export class ProcessHandle {
26
29
  if (!pid) { return false; }
27
30
  try {
28
31
  process.kill(pid, 0); // See if process is still running
29
- return false;
30
- } catch { }
31
- return true; // Still running
32
+ this.#log('debug', 'Is running', pid);
33
+ return true;
34
+ } catch {
35
+ this.#log('debug', 'Is not running', pid);
36
+ }
37
+ return false; // Not running
32
38
  }
33
39
 
34
40
  async kill(): Promise<boolean> {
35
41
  const pid = await this.getPid();
36
42
  if (pid && await this.isRunning()) {
37
43
  try {
44
+ this.#log('debug', 'Killing', pid);
38
45
  return process.kill(pid);
39
46
  } catch { }
40
47
  }
@@ -44,6 +51,7 @@ export class ProcessHandle {
44
51
  async ensureKilled(gracePeriod: number = 3000): Promise<boolean> {
45
52
  const start = Date.now();
46
53
  const pid = await this.getPid();
54
+ this.#log('debug', 'Ensuring Killed', pid);
47
55
  while (pid && (Date.now() - start) < gracePeriod) { // Ensure its done
48
56
  if (!await this.isRunning()) {
49
57
  return true;
@@ -51,8 +59,10 @@ export class ProcessHandle {
51
59
  await timers.setTimeout(100);
52
60
  }
53
61
  try {
62
+ this.#log('debug', 'Force Killing', pid);
54
63
  pid && process.kill(pid); // Force kill
55
64
  } catch { }
65
+ this.#log('debug', 'Did Kill', this.#file, !!pid);
56
66
  return pid !== undefined;
57
67
  }
58
68
  }
@@ -7,8 +7,8 @@ import type { ManifestContext } from '@travetto/manifest';
7
7
 
8
8
  import type { CompilerMode, CompilerProgressEvent, CompilerEvent, CompilerEventType, CompilerServerInfo } from '../types';
9
9
  import { LogUtil } from '../log';
10
- import { CompilerClient } from './client';
11
10
  import { CommonUtil } from '../util';
11
+ import { CompilerClient } from './client';
12
12
  import { ProcessHandle } from './process-handle';
13
13
 
14
14
  const log = LogUtil.logger('compiler-server');
@@ -123,8 +123,9 @@ export class CompilerServer {
123
123
  this.info.iteration = Date.now();
124
124
  await new Promise(r => setTimeout(r, 20));
125
125
  for (const el of Object.values(this.#listeners)) {
126
- el.res.end();
126
+ try { el.res.end(); } catch { }
127
127
  }
128
+ this.#listeners = {}; // Ensure its empty
128
129
  }
129
130
 
130
131
  async #clean(): Promise<{ clean: boolean }> {
@@ -144,19 +145,18 @@ export class CompilerServer {
144
145
  log('debug', 'Receive request', { action, subAction });
145
146
 
146
147
  let out: unknown;
148
+ let close = false;
147
149
  switch (action) {
148
150
  case 'event': return await this.#addListener(subAction, res);
149
151
  case 'clean': out = await this.#clean(); break;
150
- case 'stop': {
151
- // Must send immediately
152
- res.end(JSON.stringify({ closing: true }));
153
- await this.close();
154
- break;
155
- }
152
+ case 'stop': out = JSON.stringify({ closing: true }); close = true; break;
156
153
  case 'info':
157
154
  default: out = this.info ?? {}; break;
158
155
  }
159
156
  res.end(JSON.stringify(out));
157
+ if (close) {
158
+ await this.close();
159
+ }
160
160
  }
161
161
 
162
162
  /**
@@ -217,11 +217,7 @@ export class CompilerServer {
217
217
  } catch { // Timeout or other error
218
218
  // Force shutdown
219
219
  this.#server.closeAllConnections();
220
- if (this.info.compilerPid) { // Ensure its killed
221
- try {
222
- process.kill(this.info.compilerPid);
223
- } catch { }
224
- }
220
+ await this.#handle.compiler.kill();
225
221
  }
226
222
 
227
223
  log('info', 'Closed down server');
package/support/setup.ts CHANGED
@@ -216,7 +216,7 @@ export class CompilerSetup {
216
216
  const names: string[] = [];
217
217
  const mods = Object.values(manifest.modules).filter(x => x.workspace && x.name !== ctx.workspace.name);
218
218
  for (const mod of mods) {
219
- const modCtx = ManifestUtil.getModuleContext(ctx, mod.sourceFolder);
219
+ const modCtx = ManifestUtil.getModuleContext(ctx, mod.sourceFolder, true);
220
220
  const modManifest = await ManifestUtil.buildManifest(modCtx);
221
221
  await ManifestUtil.writeManifest(modManifest);
222
222
  names.push(mod.name);
package/support/util.ts CHANGED
@@ -63,7 +63,8 @@ export class CommonUtil {
63
63
  const controller = new AbortController();
64
64
  setMaxListeners(1000, controller.signal);
65
65
  // Chain
66
- parent.addEventListener('abort', () => controller.abort());
66
+ const kill = (): void => controller.abort();
67
+ parent.addEventListener('abort', kill);
67
68
 
68
69
  const comp = src(controller.signal);
69
70
 
@@ -75,6 +76,7 @@ export class CommonUtil {
75
76
  if (shouldRestart(ev)) {
76
77
  log('debug', 'Restarting stream');
77
78
  controller.abort(); // Ensure terminated of process
79
+ parent.removeEventListener('abort', kill);
78
80
  continue outer;
79
81
  }
80
82
  }