@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 +8 -8
- package/__index__.ts +0 -1
- package/package.json +4 -4
- package/src/compiler.ts +19 -16
- package/support/entry.trvc.ts +21 -17
- package/support/log.ts +81 -58
- package/support/server/client.ts +3 -5
- package/support/server/process-handle.ts +3 -3
- package/support/server/runner.ts +2 -2
- package/support/server/server.ts +6 -6
- package/support/setup.ts +8 -8
- package/support/types.ts +1 -1
- package/support/util.ts +2 -2
- package/src/log.ts +0 -17
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 [
|
|
42
|
-
2029-03-14T04:00:00.837Z debug [
|
|
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 [
|
|
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 [
|
|
67
|
-
2029-03-14T04:00:14.924Z debug [
|
|
68
|
-
2029-03-14T04:00:15.690Z info [
|
|
69
|
-
2029-03-14T04:00:15.865Z debug [
|
|
70
|
-
2029-03-14T04:00:16.757Z debug [
|
|
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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/compiler",
|
|
3
|
-
"version": "4.0.0
|
|
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
|
|
35
|
-
"@travetto/transformer": "^4.0.0
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
70
|
+
log.error('Shutting down due to failure', err.message);
|
|
68
71
|
}
|
|
69
72
|
break;
|
|
70
73
|
}
|
|
71
74
|
case 'reset': {
|
|
72
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
145
|
+
log.debug('Compilation aborted');
|
|
143
146
|
} else if (failed) {
|
|
144
|
-
|
|
147
|
+
log.debug('Compilation failed');
|
|
145
148
|
process.exitCode = 1;
|
|
146
149
|
return;
|
|
147
150
|
} else {
|
|
148
|
-
|
|
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
|
-
|
|
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
|
-
|
|
170
|
+
log.info('Compilation Error', CompilerUtil.buildTranspileError(ev.entry.inputFile, err));
|
|
168
171
|
} else {
|
|
169
|
-
|
|
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
|
-
|
|
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
|
-
|
|
200
|
+
log.debug('Compiler process shutdown');
|
|
198
201
|
|
|
199
202
|
this.#shutdown('complete');
|
|
200
203
|
}
|
package/support/entry.trvc.ts
CHANGED
|
@@ -4,8 +4,8 @@ import path from 'node:path';
|
|
|
4
4
|
|
|
5
5
|
import type { ManifestContext } from '@travetto/manifest';
|
|
6
6
|
|
|
7
|
-
import type {
|
|
8
|
-
import {
|
|
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,
|
|
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,
|
|
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 =
|
|
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
|
-
|
|
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> {
|
|
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> {
|
|
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
|
-
|
|
93
|
-
if (!(await client.isWatching())) {
|
|
94
|
-
|
|
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',
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
|
|
52
|
-
|
|
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
|
-
|
|
59
|
-
|
|
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
|
-
|
|
71
|
-
if (!this.
|
|
72
|
-
const params = [ev.message, ...ev.args ?? []].map(x => typeof x === 'string' ? x.replaceAll(this.root
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
112
|
+
if (!(this.logProgress)) { return; }
|
|
93
113
|
for await (const ev of src()) { this.onProgressEvent(ev); }
|
|
94
|
-
|
|
114
|
+
Logger.reset();
|
|
95
115
|
}
|
|
116
|
+
}
|
|
96
117
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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
|
+
}
|
package/support/server/client.ts
CHANGED
|
@@ -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 {
|
|
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:
|
|
23
|
+
#log: LogShape;
|
|
26
24
|
#handle: Record<'compiler' | 'server', ProcessHandle>;
|
|
27
25
|
|
|
28
|
-
constructor(ctx: ManifestContext, log:
|
|
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 {
|
|
6
|
+
import { Log, Logger } from '../log';
|
|
7
7
|
|
|
8
8
|
export class ProcessHandle {
|
|
9
9
|
|
|
10
10
|
#file: string;
|
|
11
|
-
#log:
|
|
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 =
|
|
15
|
+
this.#log = Log.scoped(`process-handle.${name}`);
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
async writePid(pid: number): Promise<void> {
|
package/support/server/runner.ts
CHANGED
|
@@ -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 {
|
|
9
|
+
import { Log } from '../log';
|
|
10
10
|
import { CommonUtil } from '../util';
|
|
11
11
|
|
|
12
|
-
const log =
|
|
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
|
/**
|
package/support/server/server.ts
CHANGED
|
@@ -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 {
|
|
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 =
|
|
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,
|
|
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
|
|
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.
|
|
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
|
|
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 {
|
|
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
|
|
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
|
|
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
|
|
184
|
+
const manifest = await Log.wrap('manifest', () =>
|
|
185
185
|
ManifestUtil.buildManifest(ManifestUtil.getWorkspaceContext(ctx)));
|
|
186
186
|
|
|
187
|
-
await
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 {
|
|
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 =
|
|
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
|
-
};
|