@travetto/compiler 3.4.4 → 4.0.0-rc.1

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 CHANGED
@@ -30,7 +30,8 @@ The compiler cli supports the following operations:
30
30
  * `build` - Ensure the project is built and upto date
31
31
  * `clean` - Clean out the output and compiler caches
32
32
  * `info` - Retrieve the compiler information, if running
33
- * `manifest [output] [prod]` - Generate the project manifest
33
+ * `event <log|progress|state>` - Watch events in realtime as newline delimited JSON
34
+ * `manifest --prod [output]` - Generate the project manifest
34
35
  In addition to the normal output, the compiler supports an environment variable `TRV_BUILD` that supports the following values: `debug`, `info`, `warn` or `none`. This provides different level of logging during the build process which is helpful to diagnose any odd behaviors. When invoking an unknown command (e.g. `<other>` from above), the default level is `warn`. Otherwise the default logging level is `info`.
35
36
 
36
37
  **Terminal: Sample trv output with debug logging**
@@ -38,34 +39,35 @@ In addition to the normal output, the compiler supports an environment variable
38
39
  $ TRV_BUILD=debug trvc build
39
40
 
40
41
  2029-03-14T04:00:00.618Z info [compiler-server] Starting server http://127.0.0.1:25539
41
- 2029-03-14T04:00:00.837Z debug [compiler-client] Starting watch for events of type "log"
42
+ 2029-03-14T04:00:00.837Z debug [client.main ] Start Server
42
43
  2029-03-14T04:00:01.510Z debug [event-stream ] Started event stream
43
44
  2029-03-14T04:00:02.450Z debug [precompile ] Started
44
- 2029-03-14T04:00:02.762Z debug [compiler-server] Receive request { action: 'event', subAction: 'log' }
45
- 2029-03-14T04:00:02.947Z debug [precompile ] Skipped @travetto/terminal
46
- 2029-03-14T04:00:03.093Z debug [precompile ] Skipped @travetto/manifest
47
- 2029-03-14T04:00:04.003Z debug [precompile ] Skipped @travetto/transformer
48
- 2029-03-14T04:00:04.495Z debug [precompile ] Skipped @travetto/compiler
49
- 2029-03-14T04:00:05.066Z debug [precompile ] Completed
50
- 2029-03-14T04:00:05.307Z debug [manifest ] Started
51
- 2029-03-14T04:00:05.952Z debug [manifest ] Completed
52
- 2029-03-14T04:00:06.859Z debug [transformers ] Started
53
- 2029-03-14T04:00:07.720Z debug [transformers ] Skipped @travetto/base
54
- 2029-03-14T04:00:08.179Z debug [transformers ] Skipped @travetto/cli
55
- 2029-03-14T04:00:08.588Z debug [transformers ] Skipped @travetto/manifest
56
- 2029-03-14T04:00:09.493Z debug [transformers ] Skipped @travetto/registry
57
- 2029-03-14T04:00:10.395Z debug [transformers ] Skipped @travetto/schema
58
- 2029-03-14T04:00:10.407Z debug [transformers ] Completed
59
- 2029-03-14T04:00:10.799Z debug [delta ] Started
60
- 2029-03-14T04:00:11.013Z debug [delta ] Completed
61
- 2029-03-14T04:00:11.827Z debug [manifest ] Started
62
- 2029-03-14T04:00:11.894Z debug [manifest ] Wrote manifest @travetto-doc/compiler
63
- 2029-03-14T04:00:12.133Z debug [manifest ] Completed
64
- 2029-03-14T04:00:13.123Z info [compiler-server] State changed: compile-end
65
- 2029-03-14T04:00:14.014Z debug [compiler-exec ] Skipped
66
- 2029-03-14T04:00:14.924Z debug [event-stream ] Finished event stream
67
- 2029-03-14T04:00:15.690Z info [compiler-server] Closing down server
68
- 2029-03-14T04:00:15.865Z debug [compiler-client] Stopping watch for events of type "log"
45
+ 2029-03-14T04:00:02.762Z debug [precompile ] Skipped @travetto/manifest
46
+ 2029-03-14T04:00:02.947Z debug [precompile ] Skipped @travetto/transformer
47
+ 2029-03-14T04:00:03.093Z debug [precompile ] Skipped @travetto/compiler
48
+ 2029-03-14T04:00:04.003Z debug [precompile ] Completed
49
+ 2029-03-14T04:00:04.495Z debug [manifest ] Started
50
+ 2029-03-14T04:00:05.066Z debug [manifest ] Completed
51
+ 2029-03-14T04:00:05.307Z debug [transformers ] Started
52
+ 2029-03-14T04:00:05.952Z debug [transformers ] Skipped @travetto/base
53
+ 2029-03-14T04:00:06.859Z debug [transformers ] Skipped @travetto/cli
54
+ 2029-03-14T04:00:07.720Z debug [transformers ] Skipped @travetto/manifest
55
+ 2029-03-14T04:00:08.179Z debug [transformers ] Skipped @travetto/registry
56
+ 2029-03-14T04:00:08.588Z debug [transformers ] Skipped @travetto/schema
57
+ 2029-03-14T04:00:09.493Z debug [transformers ] Completed
58
+ 2029-03-14T04:00:10.395Z debug [delta ] Started
59
+ 2029-03-14T04:00:10.407Z debug [delta ] Completed
60
+ 2029-03-14T04:00:10.799Z debug [manifest ] Started
61
+ 2029-03-14T04:00:11.013Z debug [manifest ] Wrote manifest @travetto-doc/compiler
62
+ 2029-03-14T04:00:11.827Z debug [manifest ] Completed
63
+ 2029-03-14T04:00:11.894Z info [compiler-server] State changed: compile-end
64
+ 2029-03-14T04:00:12.133Z debug [compiler-exec ] Skipped
65
+ 2029-03-14T04:00:13.123Z debug [event-stream ] Finished event stream
66
+ 2029-03-14T04:00:14.014Z info [compiler-server] Closing down server
67
+ 2029-03-14T04:00:14.924Z debug [compiler-server] Server close event
68
+ 2029-03-14T04:00:15.690Z info [compiler-server] Closed down server
69
+ 2029-03-14T04:00:15.865Z debug [compiler-server] Finished processing events
70
+ 2029-03-14T04:00:16.757Z debug [client.main ] End Server
69
71
  ```
70
72
 
71
73
  **Terminal: Sample trv output with default log level**
package/bin/common.js CHANGED
@@ -1,55 +1,60 @@
1
1
  // @ts-check
2
-
3
- import fs from 'fs/promises';
4
- import path from 'path';
5
- import { createRequire } from 'module';
2
+ import { statSync, readFileSync, writeFileSync, mkdirSync, readdirSync, existsSync, rmSync } from 'node:fs';
3
+ import path from 'node:path';
6
4
 
7
5
  import { getManifestContext } from '@travetto/manifest/bin/context.js';
8
6
 
9
- const COMPILER_FILES = [...['entry.trvc', 'log', 'queue', 'server/client', 'server/runner', 'server/server', 'setup', 'util'].map(x => `support/${x}.ts`), 'package.json'];
7
+ /** @typedef {import('@travetto/manifest').ManifestContext} Ctx */
10
8
 
11
- /** @return {Promise<ReturnType<import('@travetto/compiler/support/entry.trvc').main>>} */
12
- export const getEntry = async () => {
13
- const ctx = await getManifestContext();
14
- const tsconfigFile = path.resolve(ctx.workspacePath, 'tsconfig.json');
15
- if (!(await fs.stat(tsconfigFile).catch(() => undefined))) {
16
- await fs.writeFile(tsconfigFile, JSON.stringify({ extends: '@travetto/compiler/tsconfig.trv.json' }), 'utf8');
17
- }
18
- const compMod = path.dirname(createRequire(path.resolve(ctx.workspacePath, 'node_modules')).resolve('@travetto/compiler/package.json'));
19
- const files = [];
20
-
21
- for (const file of COMPILER_FILES) {
22
- const target = path.resolve(ctx.workspacePath, ctx.compilerFolder, 'node_modules', '@travetto/compiler', file).replace(/[.]tsx?$/, '.js');
23
- const src = path.resolve(compMod, file);
24
-
25
- const targetTime = await fs.stat(target).then(s => Math.max(s.mtimeMs, s.ctimeMs)).catch(() => 0);
26
- const srcTime = await fs.stat(src).then(s => Math.max(s.mtimeMs, s.ctimeMs));
27
- // If stale
28
- if (srcTime > targetTime) {
29
- const ts = (await import('typescript')).default;
30
- const module = ctx.moduleType === 'module' ? ts.ModuleKind.ESNext : ts.ModuleKind.CommonJS;
31
- await fs.mkdir(path.dirname(target), { recursive: true });
32
- const text = await fs.readFile(src, 'utf8');
33
- if (/[.]tsx?$/.test(file)) {
34
- const content = ts.transpile(
35
- text,
36
- { target: ts.ScriptTarget.ES2022, module, esModuleInterop: true, allowSyntheticDefaultImports: true }
37
- )
38
- .replace(/^((?:im|ex)port .*from '[.][^']+)(')/mg, (_, a, b) => `${a}.js${b}`)
39
- .replace(/^(import [^\n]*from '[^.][^\n/]+[/][^\n/]+[/][^\n']+)(')/mg, (_, a, b) => `${a}.js${b}`);
40
- await fs.writeFile(target, content, 'utf8');
41
- } else {
42
- const pkg = JSON.parse(text);
43
- pkg.type = ctx.moduleType;
44
- await fs.writeFile(target, JSON.stringify(pkg, null, 2), 'utf8');
45
- }
46
- // Compile
9
+ const TS_EXT = /[.]tsx?$/;
10
+
11
+ const getAge = (/** @type {{mtimeMs:number, ctimeMs:number}} */ st) => Math.max(st.mtimeMs, st.ctimeMs);
12
+
13
+ const getTarget = (/** @type {Ctx} */ ctx, file = '') => ({
14
+ dest: path.resolve(ctx.workspace.path, ctx.build.compilerFolder, 'node_modules', '@travetto/compiler', file).replace(TS_EXT, '.js'),
15
+ src: path.resolve(ctx.workspace.path, ctx.build.compilerModuleFolder, file),
16
+ async writeIfStale(/** @type {(text:string)=>(string|Promise<string>)}*/ transform) {
17
+ if (!existsSync(this.dest) || getAge(statSync(this.dest)) < getAge(statSync(this.src))) {
18
+ const text = readFileSync(this.src, 'utf8');
19
+ mkdirSync(path.dirname(this.dest), { recursive: true });
20
+ writeFileSync(this.dest, await transform(text), 'utf8');
47
21
  }
48
- files.push(target);
49
22
  }
23
+ });
24
+
25
+ const getTranspiler = async (/** @type {Ctx} */ ctx) => {
26
+ const ts = (await import('typescript')).default;
27
+ const module = ctx.workspace.type === 'module' ? ts.ModuleKind.ESNext : ts.ModuleKind.CommonJS;
28
+ return (content = '') => ts.transpile(content, { target: ts.ScriptTarget.ES2022, module, esModuleInterop: true, allowSyntheticDefaultImports: true });
29
+ };
30
+
31
+ /** @returns {Promise<import('@travetto/compiler/support/entry.trvc')>} */
32
+ async function imp(f = '') { try { return require(f); } catch (err) { return import(f); } }
50
33
 
51
- const rootCtx = await (ctx.monoRepo ? getManifestContext(ctx.workspacePath) : ctx);
34
+ export async function getEntry() {
35
+ process.setSourceMapsEnabled(true); // Ensure source map during compilation/development
36
+ process.env.NODE_OPTIONS = `${process.env.NODE_OPTIONS ?? ''} --enable-source-maps`; // Ensure it passes to children
52
37
 
53
- try { return require(files[0]).main(rootCtx, ctx); }
54
- catch { return import(files[0]).then(v => v.main(rootCtx, ctx)); }
55
- };
38
+ const ctx = getManifestContext();
39
+ const target = getTarget.bind(null, ctx);
40
+
41
+ // Setup Tsconfig
42
+ const tsconfig = path.resolve(ctx.workspace.path, 'tsconfig.json');
43
+ existsSync(tsconfig) || writeFileSync(tsconfig, JSON.stringify({ extends: '@travetto/compiler/tsconfig.trv.json' }), 'utf8');
44
+
45
+ // Compile support folder
46
+ await target('package.json').writeIfStale(text => JSON.stringify(Object.assign(JSON.parse(text), { type: ctx.workspace.type }), null, 2));
47
+
48
+ let transpile;
49
+ for (const file of readdirSync(target('support').src, { recursive: true, encoding: 'utf8' })) {
50
+ if (TS_EXT.test(file)) { await target(`support/${file}`).writeIfStale(async (text) => (transpile ??= await getTranspiler(ctx))(text)); }
51
+ }
52
+
53
+ // Load
54
+ try {
55
+ return await imp(target('support/entry.trvc.ts').dest).then(v => v.main(ctx));
56
+ } catch (err) {
57
+ rmSync(target('.').dest, { recursive: true, force: true });
58
+ throw err;
59
+ }
60
+ }
package/bin/trvc.js CHANGED
@@ -7,30 +7,37 @@ const help = () => [
7
7
  'npx trvc [command]',
8
8
  '',
9
9
  'Available Commands:',
10
- ' * start|watch - Run the compiler in watch mode',
11
- ' * stop - Stop the compiler if running',
12
- ' * restart - Restart the compiler in watch mode',
13
- ' * build - Ensure the project is built and upto date',
14
- ' * clean - Clean out the output and compiler caches',
15
- ' * info - Retrieve the compiler information, if running',
16
- ' * manifest [output] [prod] - Generate the project manifest',
10
+ ' * start|watch - Run the compiler in watch mode',
11
+ ' * stop - Stop the compiler if running',
12
+ ' * restart - Restart the compiler in watch mode',
13
+ ' * build - Ensure the project is built and upto date',
14
+ ' * clean - Clean out the output and compiler caches',
15
+ ' * info - Retrieve the compiler information, if running',
16
+ ' * event <log|progress|state> - Watch events in realtime as newline delimited JSON',
17
+ ' * manifest --prod [output] - Generate the project manifest',
17
18
  ].join('\n');
18
19
 
19
20
  getEntry().then(async (ops) => {
20
- const [op, ...args] = process.argv.slice(2);
21
- const baseArgs = args.filter(x => !x.startsWith('-'));
21
+ const [op, ...all] = process.argv.slice(2);
22
+ const args = all.filter(x => !x.startsWith('-'));
23
+ const flags = all.filter(x => x.startsWith('-'));
22
24
 
23
25
  switch (op) {
24
26
  case undefined:
25
27
  case 'help': return console.log(`\n${help()}\n`);
26
- case 'restart': return ops.stop().then(() => ops.compile('watch'));
28
+ case 'restart': return ops.restart();
27
29
  case 'stop': return ops.stop();
28
30
  case 'info': return ops.info().then(v => console.log(JSON.stringify(v, null, 2)));
31
+ case 'event': return ops.events(args[0], v => {
32
+ if (!process.stdout.write(`${JSON.stringify(v)}\n`)) {
33
+ return new Promise(r => process.stdout.once('drain', r));
34
+ }
35
+ });
29
36
  case 'clean': return ops.clean();
30
- case 'manifest': return ops.manifest(baseArgs[0], /prod/i.test(baseArgs[1] ?? ''));
31
- case 'start': return ops.compile('watch');
32
- case 'watch':
33
- case 'build': return ops.compile(op);
37
+ case 'manifest': return ops.manifest(args[0], flags.some(x => x === '--prod'));
38
+ case 'start':
39
+ case 'watch': return ops.watch();
40
+ case 'build': return ops.build();
34
41
  default: console.error(`Unknown trvc operation: ${op}\n`); return console.error(help());
35
42
  }
36
43
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/compiler",
3
- "version": "3.4.4",
3
+ "version": "4.0.0-rc.1",
4
4
  "description": "The compiler infrastructure for the Travetto framework",
5
5
  "keywords": [
6
6
  "compiler",
@@ -30,14 +30,13 @@
30
30
  "directory": "module/compiler"
31
31
  },
32
32
  "dependencies": {
33
- "@parcel/watcher": "^2.3.0",
34
- "@travetto/manifest": "^3.4.0",
35
- "@travetto/terminal": "^3.4.0",
36
- "@travetto/transformer": "^3.4.3",
37
- "@types/node": "^20.9.2"
33
+ "@parcel/watcher": "^2.4.0",
34
+ "@travetto/manifest": "^4.0.0-rc.1",
35
+ "@travetto/transformer": "^4.0.0-rc.1",
36
+ "@types/node": "^20.11.16"
38
37
  },
39
38
  "peerDependencies": {
40
- "@travetto/cli": "^3.4.6"
39
+ "@travetto/cli": "^4.0.0-rc.1"
41
40
  },
42
41
  "peerDependenciesMeta": {
43
42
  "@travetto/cli": {
package/src/compiler.ts CHANGED
@@ -1,8 +1,9 @@
1
- import { install } from 'source-map-support';
2
1
  import ts from 'typescript';
3
- import fs from 'fs/promises';
2
+ import timers from 'node:timers/promises';
3
+ import fs from 'node:fs/promises';
4
+ import { setMaxListeners } from 'node:events';
4
5
 
5
- import { ManifestModuleUtil, RootIndex } from '@travetto/manifest';
6
+ import { ManifestModuleUtil, RuntimeIndex } from '@travetto/manifest';
6
7
 
7
8
  import { CompilerUtil } from './util';
8
9
  import { CompilerState } from './state';
@@ -21,22 +22,65 @@ export class Compiler {
21
22
  */
22
23
  static async main(): Promise<void> {
23
24
  const [dirty, watch] = process.argv.slice(2);
24
- const state = await CompilerState.get(RootIndex);
25
+ const state = await CompilerState.get(RuntimeIndex);
26
+ Log.debug('Running compiler with dirty file', dirty);
25
27
  const dirtyFiles = ManifestModuleUtil.getFileType(dirty) === 'ts' ? [dirty] : (await fs.readFile(dirty, 'utf8')).split(/\n/).filter(x => !!x);
26
28
  await new Compiler(state, dirtyFiles, watch === 'true').run();
27
- process.exit();
28
29
  }
29
30
 
30
31
  #state: CompilerState;
31
32
  #dirtyFiles: string[];
32
33
  #watch?: boolean;
34
+ #ctrl: AbortController;
35
+ #signal: AbortSignal;
36
+ #shuttingDown = false;
33
37
 
34
38
  constructor(state: CompilerState, dirtyFiles: string[], watch?: boolean) {
35
39
  this.#state = state;
36
40
  this.#dirtyFiles = dirtyFiles[0] === '*' ?
37
41
  this.#state.getAllFiles() :
38
- dirtyFiles.map(f => this.#state.getBySource(f)!.input);
42
+ dirtyFiles.map(f => this.#state.getBySource(f)!.inputFile);
39
43
  this.#watch = watch;
44
+
45
+ this.#ctrl = new AbortController();
46
+ this.#signal = this.#ctrl.signal;
47
+ setMaxListeners(1000, this.#signal);
48
+ process
49
+ .once('disconnect', () => this.#shutdown('manual'))
50
+ .on('message', ev => (ev === 'shutdown') && this.#shutdown('manual'));
51
+ }
52
+
53
+ #shutdown(mode: 'error' | 'manual' | 'complete' | 'reset', err?: Error): void {
54
+ if (this.#shuttingDown) {
55
+ return;
56
+ }
57
+
58
+ this.#shuttingDown = true;
59
+ switch (mode) {
60
+ case 'manual': {
61
+ Log.error('Shutting down manually');
62
+ process.exitCode = 2;
63
+ break;
64
+ }
65
+ case 'error': {
66
+ process.exitCode = 1;
67
+ if (err) {
68
+ Log.error('Shutting down due to failure', err.message);
69
+ }
70
+ break;
71
+ }
72
+ case 'reset': {
73
+ Log.info('Triggering reset due to change in core files');
74
+ EventUtil.sendEvent('state', { state: 'reset' });
75
+ process.exitCode = 0;
76
+ break;
77
+ }
78
+ }
79
+ // No longer listen to disconnect
80
+ process.removeAllListeners('disconnect');
81
+ process.removeAllListeners('message');
82
+ this.#ctrl.abort();
83
+ setTimeout(() => process.exit(), 1000).unref(); // Allow upto 1s to shutdown gracefully
40
84
  }
41
85
 
42
86
  /**
@@ -50,6 +94,7 @@ export class Compiler {
50
94
  if (needsNewProgram) {
51
95
  program = this.#state.createProgram(program);
52
96
  }
97
+ await timers.setImmediate();
53
98
  const result = this.#state.writeInputFile(program, inputFile);
54
99
  if (result?.diagnostics?.length) {
55
100
  return result.diagnostics;
@@ -72,6 +117,7 @@ export class Compiler {
72
117
  async * emit(files: string[], emitter: CompileEmitter): AsyncIterable<CompileEmitEvent> {
73
118
  let i = 0;
74
119
  let lastSent = Date.now();
120
+
75
121
  for (const file of files) {
76
122
  const err = await emitter(file);
77
123
  const imp = file.replace(/.*node_modules\//, '');
@@ -80,8 +126,14 @@ export class Compiler {
80
126
  lastSent = Date.now();
81
127
  EventUtil.sendEvent('progress', { total: files.length, idx: i, message: imp, operation: 'compile' });
82
128
  }
129
+ if (this.#signal.aborted) {
130
+ break;
131
+ }
83
132
  }
84
133
  EventUtil.sendEvent('progress', { total: files.length, idx: files.length, message: 'Complete', operation: 'compile', complete: true });
134
+
135
+ await timers.setTimeout(1);
136
+
85
137
  Log.debug(`Compiled ${i} files`);
86
138
  }
87
139
 
@@ -89,16 +141,10 @@ export class Compiler {
89
141
  * Run the compiler
90
142
  */
91
143
  async run(): Promise<void> {
92
- install();
93
-
94
144
  Log.debug('Compilation started');
95
145
 
96
146
  EventUtil.sendEvent('state', { state: 'init', extra: { pid: process.pid } });
97
147
 
98
- if (process.send) {
99
- process.on('disconnect', () => process.exit(0));
100
- }
101
-
102
148
  const emitter = await this.getCompiler();
103
149
  let failed = false;
104
150
 
@@ -114,9 +160,12 @@ export class Compiler {
114
160
  EventUtil.sendEvent('log', { level: 'error', message: compileError.toString(), time: Date.now() });
115
161
  }
116
162
  }
117
- if (failed) {
163
+ if (this.#signal.aborted) {
164
+ Log.debug('Compilation aborted');
165
+ } else if (failed) {
118
166
  Log.debug('Compilation failed');
119
- process.exit(1);
167
+ process.exitCode = 1;
168
+ return;
120
169
  } else {
121
170
  Log.debug('Compilation succeeded');
122
171
  }
@@ -128,43 +177,47 @@ export class Compiler {
128
177
 
129
178
  EventUtil.sendEvent('state', { state: 'compile-end' });
130
179
 
131
- if (this.#watch) {
180
+ if (this.#watch && !this.#signal.aborted) {
132
181
  Log.info('Watch is ready');
133
182
 
134
183
  EventUtil.sendEvent('state', { state: 'watch-start' });
135
-
136
- for await (const ev of CompilerWatcher.watch(this.#state)) {
137
- if (ev.action === 'reset') {
138
- Log.info(`Triggering reset due to change in ${ev.file}`);
139
- EventUtil.sendEvent('state', { state: 'reset' });
140
- return;
141
- }
142
- const { action, entry } = ev;
143
- if (action !== 'delete') {
144
- const err = await emitter(entry.input, true);
145
- if (err) {
146
- Log.info('Compilation Error', CompilerUtil.buildTranspileError(entry.input, err));
184
+ try {
185
+ for await (const ev of new CompilerWatcher(this.#state, this.#signal).watchChanges()) {
186
+ if (ev.action !== 'delete') {
187
+ const err = await emitter(ev.entry.inputFile, true);
188
+ if (err) {
189
+ Log.info('Compilation Error', CompilerUtil.buildTranspileError(ev.entry.inputFile, err));
190
+ } else {
191
+ Log.info(`Compiled ${ev.entry.sourceFile} on ${ev.action}`);
192
+ }
147
193
  } else {
148
- Log.info(`Compiled ${entry.source}`);
194
+ if (ev.entry.outputFile) {
195
+ // Remove output
196
+ Log.info(`Removed ${ev.entry.sourceFile}, ${ev.entry.outputFile}`);
197
+ await fs.rm(ev.entry.outputFile, { force: true }); // Ensure output is deleted
198
+ }
149
199
  }
150
- } else {
151
- // Remove output
152
- Log.info(`Removed ${entry.source}, ${entry.output}`);
153
- await fs.rm(entry.output!, { force: true }); // Ensure output is deleted
200
+
201
+ // Send change events
202
+ EventUtil.sendEvent('change', {
203
+ action: ev.action,
204
+ time: Date.now(),
205
+ file: ev.file,
206
+ output: ev.entry.outputFile!,
207
+ module: ev.entry.module.name
208
+ });
154
209
  }
210
+ EventUtil.sendEvent('state', { state: 'watch-end' });
155
211
 
156
- // Send change events
157
- EventUtil.sendEvent('change', {
158
- action: ev.action,
159
- time: Date.now(),
160
- file: ev.file,
161
- folder: ev.folder,
162
- output: ev.entry.output!,
163
- module: ev.entry.module.name
164
- });
212
+ } catch (err) {
213
+ if (err instanceof Error) {
214
+ this.#shutdown(err.message === 'RESET' ? 'reset' : 'error', err);
215
+ }
165
216
  }
166
-
167
- EventUtil.sendEvent('state', { state: 'watch-end' });
168
217
  }
218
+
219
+ Log.debug('Compiler process shutdown');
220
+
221
+ this.#shutdown('complete');
169
222
  }
170
223
  }
package/src/event.ts CHANGED
@@ -1,7 +1,7 @@
1
- import type { CompilerServerEvent, CompilerServerEventType } from '../support/types';
1
+ import type { CompilerEvent, CompilerEventType } from '../support/types';
2
2
 
3
3
  export class EventUtil {
4
- static sendEvent<K extends CompilerServerEventType, T extends CompilerServerEvent & { type: K }>(type: K, payload: T['payload']): void {
5
- process.send?.({ type, payload });
4
+ static sendEvent<K extends CompilerEventType, T extends CompilerEvent & { type: K }>(type: K, payload: T['payload']): void {
5
+ process.connected && process.send!({ type, payload }, undefined, { swallowErrors: true });
6
6
  }
7
7
  }
package/src/log.ts CHANGED
@@ -3,7 +3,7 @@ import { EventUtil } from './event';
3
3
 
4
4
  function log(level: CompilerLogLevel, message: string, ...args: unknown[]): void {
5
5
  EventUtil.sendEvent('log', { level, message, args, time: Date.now(), scope: 'compiler-exec' });
6
- if (!process.send) {
6
+ if (!process.connected) {
7
7
  // eslint-disable-next-line no-console
8
8
  console[level](message, ...args);
9
9
  }