@travetto/compiler 4.0.0-rc.6 → 4.0.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/README.md CHANGED
@@ -38,8 +38,8 @@ In addition to the normal output, the compiler supports an environment variable
38
38
  ```bash
39
39
  $ TRV_BUILD=debug trvc build
40
40
 
41
- 2029-03-14T04:00:00.618Z info [compiler-server] Starting server http://127.0.0.1:25539
42
- 2029-03-14T04:00:00.837Z debug [client.main ] Start Server
41
+ 2029-03-14T04:00:00.618Z info [server ] Starting server http://127.0.0.1:25539
42
+ 2029-03-14T04:00:00.837Z debug [main ] Start Server
43
43
  2029-03-14T04:00:01.510Z debug [event-stream ] Started event stream
44
44
  2029-03-14T04:00:02.450Z debug [precompile ] Started
45
45
  2029-03-14T04:00:02.762Z debug [precompile ] Skipped @travetto/manifest
@@ -60,14 +60,14 @@ $ TRV_BUILD=debug trvc build
60
60
  2029-03-14T04:00:10.799Z debug [manifest ] Started
61
61
  2029-03-14T04:00:11.013Z debug [manifest ] Wrote manifest @travetto-doc/compiler
62
62
  2029-03-14T04:00:11.827Z debug [manifest ] Completed
63
- 2029-03-14T04:00:11.894Z info [compiler-server] State changed: compile-end
63
+ 2029-03-14T04:00:11.894Z info [server ] State changed: compile-end
64
64
  2029-03-14T04:00:12.133Z debug [compiler-exec ] Skipped
65
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
66
+ 2029-03-14T04:00:14.014Z info [server ] Closing down server
67
+ 2029-03-14T04:00:14.924Z debug [server ] Server close event
68
+ 2029-03-14T04:00:15.690Z info [server ] Closed down server
69
+ 2029-03-14T04:00:15.865Z debug [server ] Finished processing events
70
+ 2029-03-14T04:00:16.757Z debug [main ] End Server
71
71
  ```
72
72
 
73
73
  **Terminal: Sample trv output with default log level**
package/__index__.ts CHANGED
@@ -2,5 +2,4 @@ export * from './src/compiler';
2
2
  export * from './src/state';
3
3
  export * from './src/util';
4
4
  export * from './src/watch';
5
- export * from './src/log';
6
5
  export * from './src/types';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/compiler",
3
- "version": "4.0.0-rc.6",
3
+ "version": "4.0.0",
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.6",
35
- "@travetto/transformer": "^4.0.0-rc.6",
34
+ "@travetto/manifest": "^4.0.0",
35
+ "@travetto/transformer": "^4.0.0",
36
36
  "@types/node": "^20.11.16"
37
37
  },
38
38
  "peerDependencies": {
39
- "@travetto/cli": "^4.0.0-rc.7"
39
+ "@travetto/cli": "^4.0.0"
40
40
  },
41
41
  "peerDependenciesMeta": {
42
42
  "@travetto/cli": {
package/src/compiler.ts CHANGED
@@ -7,10 +7,13 @@ import { ManifestModuleUtil, RuntimeIndex } from '@travetto/manifest';
7
7
  import { CompilerUtil } from './util';
8
8
  import { CompilerState } from './state';
9
9
  import { CompilerWatcher } from './watch';
10
- import { Log } from './log';
11
10
  import { CompileEmitEvent, CompileEmitter } from './types';
12
11
  import { EventUtil } from './event';
13
12
 
13
+ import { IpcLogger } from '../support/log';
14
+
15
+ const log = new IpcLogger({ level: 'debug' });
16
+
14
17
  /**
15
18
  * Compilation support
16
19
  */
@@ -22,7 +25,7 @@ export class Compiler {
22
25
  static async main(): Promise<void> {
23
26
  const [dirty, watch] = process.argv.slice(2);
24
27
  const state = await CompilerState.get(RuntimeIndex);
25
- Log.debug('Running compiler with dirty file', dirty);
28
+ log.debug('Running compiler with dirty file', dirty);
26
29
  const dirtyFiles = ManifestModuleUtil.getFileType(dirty) === 'ts' ? [dirty] : (await fs.readFile(dirty, 'utf8')).split(/\n/).filter(x => !!x);
27
30
  await new Compiler(state, dirtyFiles, watch === 'true').run();
28
31
  }
@@ -57,19 +60,19 @@ export class Compiler {
57
60
  this.#shuttingDown = true;
58
61
  switch (mode) {
59
62
  case 'manual': {
60
- Log.error('Shutting down manually');
63
+ log.error('Shutting down manually');
61
64
  process.exitCode = 2;
62
65
  break;
63
66
  }
64
67
  case 'error': {
65
68
  process.exitCode = 1;
66
69
  if (err) {
67
- Log.error('Shutting down due to failure', err.message);
70
+ log.error('Shutting down due to failure', err.message);
68
71
  }
69
72
  break;
70
73
  }
71
74
  case 'reset': {
72
- Log.info('Triggering reset due to change in core files', err?.cause);
75
+ log.info('Triggering reset due to change in core files', err?.cause);
73
76
  EventUtil.sendEvent('state', { state: 'reset' });
74
77
  process.exitCode = 0;
75
78
  break;
@@ -112,21 +115,21 @@ export class Compiler {
112
115
 
113
116
  await timers.setTimeout(1);
114
117
 
115
- Log.debug(`Compiled ${i} files`);
118
+ log.debug(`Compiled ${i} files`);
116
119
  }
117
120
 
118
121
  /**
119
122
  * Run the compiler
120
123
  */
121
124
  async run(): Promise<void> {
122
- Log.debug('Compilation started');
125
+ log.debug('Compilation started');
123
126
 
124
127
  EventUtil.sendEvent('state', { state: 'init', extra: { pid: process.pid } });
125
128
 
126
129
  const emitter = await this.getCompiler();
127
130
  let failed = false;
128
131
 
129
- Log.debug('Compiler loaded');
132
+ log.debug('Compiler loaded');
130
133
 
131
134
  EventUtil.sendEvent('state', { state: 'compile-start' });
132
135
 
@@ -139,13 +142,13 @@ export class Compiler {
139
142
  }
140
143
  }
141
144
  if (this.#signal.aborted) {
142
- Log.debug('Compilation aborted');
145
+ log.debug('Compilation aborted');
143
146
  } else if (failed) {
144
- Log.debug('Compilation failed');
147
+ log.debug('Compilation failed');
145
148
  process.exitCode = 1;
146
149
  return;
147
150
  } else {
148
- Log.debug('Compilation succeeded');
151
+ log.debug('Compilation succeeded');
149
152
  }
150
153
  } else if (this.#watch) {
151
154
  // Prime compiler before complete
@@ -156,7 +159,7 @@ export class Compiler {
156
159
  EventUtil.sendEvent('state', { state: 'compile-end' });
157
160
 
158
161
  if (this.#watch && !this.#signal.aborted) {
159
- Log.info('Watch is ready');
162
+ log.info('Watch is ready');
160
163
 
161
164
  EventUtil.sendEvent('state', { state: 'watch-start' });
162
165
  try {
@@ -164,14 +167,14 @@ export class Compiler {
164
167
  if (ev.action !== 'delete') {
165
168
  const err = await emitter(ev.entry.inputFile, true);
166
169
  if (err) {
167
- Log.info('Compilation Error', CompilerUtil.buildTranspileError(ev.entry.inputFile, err));
170
+ log.info('Compilation Error', CompilerUtil.buildTranspileError(ev.entry.inputFile, err));
168
171
  } else {
169
- Log.info(`Compiled ${ev.entry.sourceFile} on ${ev.action}`);
172
+ log.info(`Compiled ${ev.entry.sourceFile} on ${ev.action}`);
170
173
  }
171
174
  } else {
172
175
  if (ev.entry.outputFile) {
173
176
  // Remove output
174
- Log.info(`Removed ${ev.entry.sourceFile}, ${ev.entry.outputFile}`);
177
+ log.info(`Removed ${ev.entry.sourceFile}, ${ev.entry.outputFile}`);
175
178
  await fs.rm(ev.entry.outputFile, { force: true }); // Ensure output is deleted
176
179
  }
177
180
  }
@@ -194,7 +197,7 @@ export class Compiler {
194
197
  }
195
198
  }
196
199
 
197
- Log.debug('Compiler process shutdown');
200
+ log.debug('Compiler process shutdown');
198
201
 
199
202
  this.#shutdown('complete');
200
203
  }
@@ -4,8 +4,8 @@ import path from 'node:path';
4
4
 
5
5
  import type { ManifestContext } from '@travetto/manifest';
6
6
 
7
- import type { CompilerLogLevel, CompilerMode, CompilerServerInfo } from './types';
8
- import { CompilerLogger } from './log';
7
+ import type { CompilerMode, CompilerServerInfo } from './types';
8
+ import { Log } from './log';
9
9
  import { CommonUtil } from './util';
10
10
  import { CompilerSetup } from './setup';
11
11
  import { CompilerServer } from './server/server';
@@ -14,15 +14,15 @@ import { CompilerClient } from './server/client';
14
14
 
15
15
  // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
16
16
  export const main = (ctx: ManifestContext) => {
17
- const client = new CompilerClient(ctx, new CompilerLogger('client'));
17
+ const client = new CompilerClient(ctx, Log.scoped('client'));
18
18
  const buildFolders = [ctx.build.outputFolder, ctx.build.compilerFolder];
19
+ Log.root = ctx.workspace.path;
20
+ Log.initLevel('error');
19
21
 
20
22
  /** Main entry point for compilation */
21
- const compile = async (op: CompilerMode, logLevel: CompilerLogLevel, setupOnly = false): Promise<void> => {
22
- CompilerLogger.init(ctx, logLevel ?? 'info');
23
-
23
+ const compile = async (op: CompilerMode, setupOnly = false): Promise<void> => {
24
24
  const server = await new CompilerServer(ctx, op).listen();
25
- const log = new CompilerLogger('main');
25
+ const log = Log.scoped('main');
26
26
 
27
27
  // Wait for build to be ready
28
28
  if (server) {
@@ -37,7 +37,7 @@ export const main = (ctx: ManifestContext) => {
37
37
  } else {
38
38
  log.info('Server already running, waiting for initial compile to complete');
39
39
  const ctrl = new AbortController();
40
- log.consumeProgressEvents(() => client.fetchEvents('progress', { until: ev => !!ev.complete, signal: ctrl.signal }));
40
+ Log.consumeProgressEvents(() => client.fetchEvents('progress', { until: ev => !!ev.complete, signal: ctrl.signal }));
41
41
  await client.waitForState(['compile-end', 'watch-start'], 'Successfully built');
42
42
  ctrl.abort();
43
43
  }
@@ -46,7 +46,6 @@ export const main = (ctx: ManifestContext) => {
46
46
  const ops = {
47
47
  /** Stop the server */
48
48
  async stop(): Promise<void> {
49
- CompilerLogger.init(ctx);
50
49
  if (await client.stop()) {
51
50
  console.log(`Stopped server ${ctx.workspace.path}: ${client}`);
52
51
  } else {
@@ -62,7 +61,6 @@ export const main = (ctx: ManifestContext) => {
62
61
 
63
62
  /** Clean the server */
64
63
  async clean(): Promise<void> {
65
- CompilerLogger.init(ctx);
66
64
  if (await client.clean()) {
67
65
  return console.log(`Clean triggered ${ctx.workspace.path}:`, buildFolders);
68
66
  } else {
@@ -73,7 +71,6 @@ export const main = (ctx: ManifestContext) => {
73
71
 
74
72
  /** Stream events */
75
73
  events: async (type: string, handler: (ev: unknown) => unknown): Promise<void> => {
76
- CompilerLogger.init(ctx, 'error');
77
74
  if (type === 'change' || type === 'log' || type === 'progress' || type === 'state') {
78
75
  for await (const ev of client.fetchEvents(type)) { await handler(ev); }
79
76
  } else {
@@ -82,23 +79,30 @@ export const main = (ctx: ManifestContext) => {
82
79
  },
83
80
 
84
81
  /** Build the project */
85
- async build(): Promise<void> { await compile('build', 'info'); },
82
+ async build(): Promise<void> {
83
+ Log.initLevel('info');
84
+ await compile('build');
85
+ },
86
86
 
87
87
  /** Build and watch the project */
88
- async watch(): Promise<void> { await compile('watch', 'info'); },
88
+ async watch(): Promise<void> {
89
+ Log.initLevel('info');
90
+ await compile('watch');
91
+ },
89
92
 
90
93
  /** Build and return a loader */
91
94
  async getLoader(): Promise<(mod: string) => Promise<unknown>> {
92
- // Short circuit if we can
93
- if (!(await client.isWatching())) {
94
- await compile('build', 'error');
95
+ Log.initLevel('none');
96
+ if (!(await client.isWatching())) { // Short circuit if we can
97
+ Log.initLevel('error');
98
+ await compile('build');
95
99
  }
96
100
  return CommonUtil.moduleLoader(ctx);
97
101
  },
98
102
 
99
103
  /** Manifest entry point */
100
104
  async manifest(output?: string, prod?: boolean): Promise<void> {
101
- await compile('build', 'error', true);
105
+ await compile('build', true);
102
106
  await CompilerSetup.exportManifest(ctx, output, prod); return;
103
107
  }
104
108
  };
package/support/log.ts CHANGED
@@ -1,18 +1,23 @@
1
- import type { ManifestContext } from '@travetto/manifest';
2
- import type { CompilerLogEvent, CompilerLogLevel, CompilerProgressEvent } from './types';
1
+ import { CompilerLogEvent, CompilerLogLevel, CompilerProgressEvent } from './types';
3
2
 
4
- const LEVEL_TO_PRI: Record<CompilerLogLevel, number> = { debug: 1, info: 2, warn: 3, error: 4 };
3
+ const LEVEL_TO_PRI: Record<CompilerLogLevel | 'none', number> = { debug: 1, info: 2, warn: 3, error: 4, none: 5 };
5
4
  const SCOPE_MAX = 15;
5
+
6
+ type LogConfig = {
7
+ level?: CompilerLogLevel | 'none';
8
+ root?: string;
9
+ scope?: string;
10
+ parent?: Logger;
11
+ };
12
+
13
+ export type LogShape = Record<'info' | 'debug' | 'warn' | 'error', (message: string, ...args: unknown[]) => void>;
14
+
6
15
  const ESC = '\x1b[';
7
16
 
8
- export class CompilerLogger {
17
+ export class Logger implements LogConfig, LogShape {
9
18
 
10
- static #root = process.cwd();
11
- static #logLevel: CompilerLogLevel = 'error';
12
19
  static #linePartial: boolean | undefined;
13
20
 
14
- static logProgress = false;
15
-
16
21
  /** Rewrite text line, tracking cleanup as necessary */
17
22
  static rewriteLine(text: string): Promise<void> | void {
18
23
  if ((!text && !this.#linePartial) || !process.stdout.isTTY) {
@@ -30,78 +35,96 @@ export class CompilerLogger {
30
35
  }
31
36
  }
32
37
 
33
- /** Are we in a shell that is interactive */
34
- static get isInteractiveShell(): boolean {
35
- return !!process.env.PS1 && process.stdout.isTTY;
36
- }
38
+ static reset(): void { process.stdout.write(`${ESC}!p${ESC}?25h`); }
37
39
 
38
- /**
39
- * Set level for operation
40
- */
41
- static init(ctx: ManifestContext, defaultLevel?: CompilerLogLevel): void {
42
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
43
- const build = process.env.TRV_BUILD as CompilerLogLevel | 'none';
44
- if (build !== 'none' && process.env.TRV_QUIET !== 'true') {
45
- this.#logLevel = build || defaultLevel;
46
- this.logProgress = this.isInteractiveShell;
47
- }
48
- this.#root = ctx.workspace.path;
49
- }
40
+ level?: CompilerLogLevel | 'none';
41
+ root: string = process.cwd();
42
+ scope?: string;
43
+ parent?: Logger;
50
44
 
51
- /** Cleanup to restore behavior */
52
- static reset(): void {
53
- if (process.stdout.isTTY) {
54
- process.stdout.write(`${ESC}!p${ESC}?25h`);
55
- }
45
+ constructor(cfg: LogConfig = {}) {
46
+ Object.assign(this, cfg);
56
47
  }
57
48
 
58
- constructor(
59
- private scope: string,
60
- private level?: CompilerLogLevel,
61
- private logProgress?: boolean,
62
- private root = CompilerLogger.#root,
63
- ) { }
64
-
65
- isActive(level: CompilerLogLevel): boolean {
66
- return LEVEL_TO_PRI[this.level ?? CompilerLogger.#logLevel] <= LEVEL_TO_PRI[level];
49
+ valid(ev: CompilerLogEvent): boolean {
50
+ return LEVEL_TO_PRI[this.level ?? this.parent?.level!] <= LEVEL_TO_PRI[ev.level];
67
51
  }
68
52
 
69
53
  /** Log event with filtering by level */
70
- onLogEvent(ev: CompilerLogEvent): void {
71
- if (!this.isActive(ev.level)) { return; }
72
- const params = [ev.message, ...ev.args ?? []].map(x => typeof x === 'string' ? x.replaceAll(this.root, '.') : x);
73
- if (ev.scope) {
74
- params.unshift(`[${ev.scope.padEnd(SCOPE_MAX, ' ')}]`);
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, ' ')}]`);
75
59
  }
76
60
  params.unshift(new Date().toISOString(), `${ev.level.padEnd(5)}`);
77
- CompilerLogger.rewriteLine(''); // Clear out progress line, if active
61
+ Logger.rewriteLine(''); // Clear out progress line, if active
78
62
  // eslint-disable-next-line no-console
79
63
  console[ev.level]!(...params);
80
64
  }
81
65
 
66
+ info(message: string, ...args: unknown[]): void { return this.render({ level: 'info', message, args }); }
67
+ debug(message: string, ...args: unknown[]): void { return this.render({ level: 'debug', message, args }); }
68
+ warn(message: string, ...args: unknown[]): void { return this.render({ level: 'warn', message, args }); }
69
+ error(message: string, ...args: unknown[]): void { return this.render({ level: 'error', message, args }); }
70
+ }
71
+
72
+
73
+ class $RootLogger extends Logger {
74
+ #logProgress?: boolean;
75
+
76
+ /** Get if we should log progress */
77
+ get logProgress(): boolean {
78
+ if (this.#logProgress === undefined) {
79
+ this.#logProgress = !!process.env.PS1 && process.stdout.isTTY && process.env.TRV_BUILD !== 'none' && process.env.TRV_QUIET !== 'true';
80
+ }
81
+ return this.#logProgress;
82
+ }
83
+
84
+ /** Set level for operation */
85
+ initLevel(defaultLevel: CompilerLogLevel | 'none'): void {
86
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
87
+ const build = process.env.TRV_BUILD as CompilerLogLevel | 'none';
88
+ this.level = (build !== 'none' && process.env.TRV_QUIET !== 'true') ? (build || defaultLevel) : 'none';
89
+ }
90
+
91
+ /** Produce a scoped logger */
92
+ scoped(name: string): Logger {
93
+ return new Logger({ parent: this, scope: name });
94
+ }
95
+
96
+ /** Scope and provide a callback pattern for access to a logger */
97
+ wrap<T = unknown>(scope: string, op: (log: Logger) => Promise<T>, basic = true): Promise<T> {
98
+ const l = this.scoped(scope);
99
+ return basic ? (l.debug('Started'), op(l).finally(() => l.debug('Completed'))) : op(l);
100
+ }
101
+
82
102
  /** Write progress event, if active */
83
103
  onProgressEvent(ev: CompilerProgressEvent): void | Promise<void> {
84
- if (!(this.logProgress ?? CompilerLogger.logProgress)) { return; }
104
+ if (!(this.logProgress)) { return; }
85
105
  const pct = Math.trunc(ev.idx * 100 / ev.total);
86
106
  const text = ev.complete ? '' : `Compiling [${'#'.repeat(Math.trunc(pct / 10)).padEnd(10, ' ')}] [${ev.idx}/${ev.total}] ${ev.message}`;
87
- return CompilerLogger.rewriteLine(text);
107
+ return Logger.rewriteLine(text);
88
108
  }
89
109
 
90
110
  /** Write all progress events if active */
91
111
  async consumeProgressEvents(src: () => AsyncIterable<CompilerProgressEvent>): Promise<void> {
92
- if (!(this.logProgress ?? CompilerLogger.logProgress)) { return; }
112
+ if (!(this.logProgress)) { return; }
93
113
  for await (const ev of src()) { this.onProgressEvent(ev); }
94
- await CompilerLogger.reset();
114
+ Logger.reset();
95
115
  }
116
+ }
96
117
 
97
- log(level: CompilerLogLevel, message: string, args: unknown[]): void {
98
- this.onLogEvent({ scope: this.scope, message, level, args, time: Date.now() });
99
- }
100
- info(message: string, ...args: unknown[]): void { return this.log('info', message, args); }
101
- debug(message: string, ...args: unknown[]): void { return this.log('debug', message, args); }
102
- warn(message: string, ...args: unknown[]): void { return this.log('warn', message, args); }
103
- error(message: string, ...args: unknown[]): void { return this.log('error', message, args); }
104
- wrap<T = unknown>(op: (log: typeof this) => Promise<T>, basic = false): Promise<T> {
105
- return basic ? (this.debug('Started'), op(this).finally(() => this.debug('Completed'))) : op(this);
118
+ export const Log = new $RootLogger();
119
+
120
+ export class IpcLogger extends Logger {
121
+ render(ev: CompilerLogEvent): void {
122
+ if (!this.valid(ev)) { return; }
123
+ if (process.connected && process.send) {
124
+ process.send({ type: 'log', payload: ev });
125
+ }
126
+ if (!process.connected) {
127
+ super.render(ev);
128
+ }
106
129
  }
107
- }
130
+ }
@@ -5,7 +5,7 @@ import { Readable } from 'node:stream';
5
5
  import { ManifestContext } from '@travetto/manifest';
6
6
 
7
7
  import type { CompilerEvent, CompilerEventType, CompilerServerInfo, CompilerStateType } from '../types';
8
- import type { CompilerLogger } from '../log';
8
+ import type { LogShape } from '../log';
9
9
  import { ProcessHandle } from './process-handle';
10
10
 
11
11
  type FetchEventsConfig<T> = {
@@ -14,18 +14,16 @@ type FetchEventsConfig<T> = {
14
14
  enforceIteration?: boolean;
15
15
  };
16
16
 
17
- type SimpleLogger = Pick<CompilerLogger, 'error' | 'info' | 'debug'>;
18
-
19
17
  /**
20
18
  * Compiler Client Operations
21
19
  */
22
20
  export class CompilerClient {
23
21
 
24
22
  #url: string;
25
- #log: SimpleLogger;
23
+ #log: LogShape;
26
24
  #handle: Record<'compiler' | 'server', ProcessHandle>;
27
25
 
28
- constructor(ctx: ManifestContext, log: SimpleLogger) {
26
+ constructor(ctx: ManifestContext, log: LogShape) {
29
27
  this.#url = ctx.build.compilerUrl.replace('localhost', '127.0.0.1');
30
28
  this.#log = log;
31
29
  this.#handle = { compiler: new ProcessHandle(ctx, 'compiler'), server: new ProcessHandle(ctx, 'server') };
@@ -3,16 +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 } from '../log';
6
+ import { Log, Logger } from '../log';
7
7
 
8
8
  export class ProcessHandle {
9
9
 
10
10
  #file: string;
11
- #log: CompilerLogger;
11
+ #log: Logger;
12
12
 
13
13
  constructor(ctx: ManifestContext, name: string) {
14
14
  this.#file = path.resolve(ctx.workspace.path, ctx.build.toolFolder, `${name}.pid`);
15
- this.#log = new CompilerLogger(`process-handle.${name}`);
15
+ this.#log = Log.scoped(`process-handle.${name}`);
16
16
  }
17
17
 
18
18
  async writePid(pid: number): Promise<void> {
@@ -6,10 +6,10 @@ import type { ManifestContext, DeltaEvent } from '@travetto/manifest';
6
6
 
7
7
  import type { CompilerEvent, CompilerMode } from '../types';
8
8
  import { AsyncQueue } from '../queue';
9
- import { CompilerLogger } from '../log';
9
+ import { Log } from '../log';
10
10
  import { CommonUtil } from '../util';
11
11
 
12
- const log = new CompilerLogger('compiler-exec');
12
+ const log = Log.scoped('compiler-exec');
13
13
  const isEvent = (msg: unknown): msg is CompilerEvent => !!msg && typeof msg === 'object' && 'type' in msg;
14
14
 
15
15
  /**
@@ -6,12 +6,12 @@ import { setMaxListeners } from 'node:events';
6
6
  import type { ManifestContext } from '@travetto/manifest';
7
7
 
8
8
  import type { CompilerMode, CompilerProgressEvent, CompilerEvent, CompilerEventType, CompilerServerInfo } from '../types';
9
- import { CompilerLogger } from '../log';
9
+ import { Log } from '../log';
10
10
  import { CommonUtil } from '../util';
11
11
  import { CompilerClient } from './client';
12
12
  import { ProcessHandle } from './process-handle';
13
13
 
14
- const log = new CompilerLogger('compiler-server');
14
+ const log = Log.scoped('server');
15
15
 
16
16
  /**
17
17
  * Compiler Server Class
@@ -30,7 +30,7 @@ export class CompilerServer {
30
30
 
31
31
  constructor(ctx: ManifestContext, mode: CompilerMode) {
32
32
  this.#ctx = ctx;
33
- this.#client = new CompilerClient(ctx, new CompilerLogger('client.server'));
33
+ this.#client = new CompilerClient(ctx, Log.scoped('server.client'));
34
34
  this.#url = this.#client.url;
35
35
  this.#handle = { server: new ProcessHandle(ctx, 'server'), compiler: new ProcessHandle(ctx, 'compiler') };
36
36
 
@@ -163,7 +163,7 @@ export class CompilerServer {
163
163
  async processEvents(src: (signal: AbortSignal) => AsyncIterable<CompilerEvent>): Promise<void> {
164
164
  for await (const ev of CommonUtil.restartableEvents(src, this.signal, this.isResetEvent)) {
165
165
  if (ev.type === 'progress') {
166
- await log.onProgressEvent(ev.payload);
166
+ await Log.onProgressEvent(ev.payload);
167
167
  }
168
168
 
169
169
  this.#emitEvent(ev);
@@ -176,7 +176,7 @@ export class CompilerServer {
176
176
  }
177
177
  log.info(`State changed: ${this.info.state}`);
178
178
  } else if (ev.type === 'log') {
179
- log.onLogEvent(ev.payload);
179
+ log.render(ev.payload);
180
180
  }
181
181
  if (this.isResetEvent(ev)) {
182
182
  await this.#disconnectActive();
@@ -198,7 +198,7 @@ export class CompilerServer {
198
198
  // If we are in a place where progress exists
199
199
  if (this.info.state === 'compile-start') {
200
200
  const cancel: CompilerProgressEvent = { complete: true, idx: 0, total: 0, message: 'Complete', operation: 'compile' };
201
- await log.onProgressEvent(cancel);
201
+ await Log.onProgressEvent(cancel);
202
202
  this.#emitEvent({ type: 'progress', payload: cancel });
203
203
  }
204
204
 
package/support/setup.ts CHANGED
@@ -4,7 +4,7 @@ import fs from 'node:fs/promises';
4
4
 
5
5
  import { type DeltaEvent, type ManifestContext, type Package } from '@travetto/manifest';
6
6
 
7
- import { CompilerLogger } from './log';
7
+ import { Log } from './log';
8
8
  import { CommonUtil } from './util';
9
9
 
10
10
  type ModFile = { input: string, output: string, stale: boolean };
@@ -128,7 +128,7 @@ export class CompilerSetup {
128
128
  const out: string[] = [];
129
129
 
130
130
  try {
131
- await new CompilerLogger(scope).wrap(async log => {
131
+ await Log.wrap(scope, async log => {
132
132
  if (files.some(f => f.stale)) {
133
133
  log.debug('Starting', mod);
134
134
  for (const file of files.filter(x => x.stale)) {
@@ -173,7 +173,7 @@ export class CompilerSetup {
173
173
  static async setup(ctx: ManifestContext): Promise<DeltaEvent[]> {
174
174
  let changes = 0;
175
175
 
176
- await new CompilerLogger('precompile').wrap(async () => {
176
+ await Log.wrap('precompile', async () => {
177
177
  for (const mod of PRECOMPILE_MODS) {
178
178
  changes += (await this.#compileIfStale(ctx, 'precompile', mod, SOURCE_SEED)).length;
179
179
  }
@@ -181,16 +181,16 @@ export class CompilerSetup {
181
181
 
182
182
  const { ManifestUtil, ManifestDeltaUtil } = await this.#importManifest(ctx);
183
183
 
184
- const manifest = await new CompilerLogger('manifest').wrap(() =>
184
+ const manifest = await Log.wrap('manifest', () =>
185
185
  ManifestUtil.buildManifest(ManifestUtil.getWorkspaceContext(ctx)));
186
186
 
187
- await new CompilerLogger('transformers').wrap(async () => {
187
+ await Log.wrap('transformers', async () => {
188
188
  for (const mod of Object.values(manifest.modules).filter(m => m.files.$transformer?.length)) {
189
189
  changes += (await this.#compileIfStale(ctx, 'transformers', mod.name, ['package.json', ...mod.files.$transformer!.map(x => x[0])])).length;
190
190
  }
191
191
  });
192
192
 
193
- const delta = await new CompilerLogger('delta').wrap(async log => {
193
+ const delta = await Log.wrap('delta', async log => {
194
194
  if (changes) {
195
195
  log.debug('Skipping, everything changed');
196
196
  return [{ type: 'changed', file: '*', module: ctx.workspace.name, sourceFile: '' } as const];
@@ -200,14 +200,14 @@ export class CompilerSetup {
200
200
  });
201
201
 
202
202
  if (changes) {
203
- await new CompilerLogger('reset').wrap(async log => {
203
+ await Log.wrap('reset', async log => {
204
204
  await fs.rm(path.resolve(ctx.workspace.path, ctx.build.outputFolder), { recursive: true, force: true });
205
205
  log.info('Clearing output due to compiler changes');
206
206
  }, false);
207
207
  }
208
208
 
209
209
  // Write manifest
210
- await new CompilerLogger('manifest').wrap(async log => {
210
+ await Log.wrap('manifest', async log => {
211
211
  await ManifestUtil.writeManifest(manifest);
212
212
  log.debug(`Wrote manifest ${ctx.workspace.name}`);
213
213
 
package/support/types.ts CHANGED
@@ -3,7 +3,7 @@ export type CompilerMode = 'build' | 'watch';
3
3
  export type CompilerStateType = 'startup' | 'init' | 'compile-start' | 'compile-end' | 'watch-start' | 'watch-end' | 'reset' | 'close';
4
4
  export type CompilerChangeEvent = { file: string, action: 'create' | 'update' | 'delete', output: string, module: string, time: number };
5
5
  export type CompilerLogLevel = 'info' | 'debug' | 'warn' | 'error';
6
- export type CompilerLogEvent = { level: CompilerLogLevel, message: string, time: number, args?: unknown[], scope?: string };
6
+ export type CompilerLogEvent = { level: CompilerLogLevel, message: string, time?: number, args?: unknown[], scope?: string };
7
7
  export type CompilerProgressEvent = { idx: number, total: number, message: string, operation: 'compile', complete?: boolean };
8
8
  export type CompilerStateEvent = { state: CompilerStateType, extra?: Record<string, unknown> };
9
9
 
package/support/util.ts CHANGED
@@ -4,7 +4,7 @@ import { setMaxListeners } from 'node:events';
4
4
 
5
5
  import type { ManifestContext } from '@travetto/manifest';
6
6
 
7
- import { CompilerLogger } from './log';
7
+ import { Log } from './log';
8
8
 
9
9
  const OPT_CACHE: Record<string, import('typescript').CompilerOptions> = {};
10
10
 
@@ -58,7 +58,7 @@ export class CommonUtil {
58
58
  * Restartable Event Stream
59
59
  */
60
60
  static async * restartableEvents<T>(src: (signal: AbortSignal) => AsyncIterable<T>, parent: AbortSignal, shouldRestart: (item: T) => boolean): AsyncIterable<T> {
61
- const log = new CompilerLogger('event-stream');
61
+ const log = Log.scoped('event-stream');
62
62
  outer: while (!parent.aborted) {
63
63
  const controller = new AbortController();
64
64
  setMaxListeners(1000, controller.signal);
package/src/log.ts DELETED
@@ -1,17 +0,0 @@
1
- import type { CompilerLogLevel } from '../support/types';
2
- import { EventUtil } from './event';
3
-
4
- function log(level: CompilerLogLevel, message: string, ...args: unknown[]): void {
5
- EventUtil.sendEvent('log', { level, message, args, time: Date.now(), scope: 'compiler-exec' });
6
- if (!process.connected) {
7
- // eslint-disable-next-line no-console
8
- console[level](message, ...args);
9
- }
10
- }
11
-
12
- export const Log = {
13
- warn: log.bind(null, 'warn'),
14
- debug: log.bind(null, 'debug'),
15
- info: log.bind(null, 'info'),
16
- error: log.bind(null, 'error'),
17
- };