@travetto/compiler 8.0.0-alpha.8 → 8.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 +3 -3
- package/__index__.ts +4 -4
- package/bin/hook.js +10 -4
- package/bin/trvc-target.js +2 -1
- package/bin/trvc.js +2 -1
- package/package.json +18 -18
- package/src/common.ts +15 -9
- package/src/compiler.ts +30 -30
- package/src/event.ts +8 -6
- package/src/log.ts +57 -22
- package/src/queue.ts +4 -2
- package/src/server/client.ts +38 -24
- package/src/server/manager.ts +16 -11
- package/src/server/process-handle.ts +14 -10
- package/src/server/server.ts +50 -26
- package/src/state.ts +85 -52
- package/src/ts-proxy.ts +5 -3
- package/src/types.ts +22 -15
- package/src/util.ts +2 -4
- package/src/watch.ts +80 -68
- package/support/invoke.ts +37 -22
- package/tsconfig.trv.json +4 -18
package/README.md
CHANGED
|
@@ -17,12 +17,12 @@ This module expands upon the [Typescript](https://typescriptlang.org) compiler,
|
|
|
17
17
|
* Integration with the [Transformation](https://github.com/travetto/travetto/tree/main/module/transformer#readme "Functionality for AST transformations, with transformer registration, and general utils") module, allowing for rich, type-aware transformations
|
|
18
18
|
* Automatic conversion to either [Ecmascript Module](https://nodejs.org/api/esm.html) or [CommonJS](https://nodejs.org/api/modules.html) based on the [Package JSON](https://docs.npmjs.com/cli/v9/configuring-npm/package-json) `type` value
|
|
19
19
|
* Removal of type only imports which can break [Ecmascript Module](https://nodejs.org/api/esm.html)-style output
|
|
20
|
-
* Automatic addition of `.js` extension to imports to also support
|
|
20
|
+
* Automatic addition of `.js` extension to imports to also support [Ecmascript Module](https://nodejs.org/api/esm.html)-style output
|
|
21
21
|
|
|
22
22
|
Beyond the [Typescript](https://typescriptlang.org) compiler functionality, the module provides the primary entry point into the development process.
|
|
23
23
|
|
|
24
24
|
## CLI
|
|
25
|
-
The compiler cli, [trvc](https://github.com/travetto/travetto/tree/main/module/compiler/bin/trvc.js) is the entry point for compilation-related operations. It has the ability to check for active builds, and ongoing watch operations to ensure only one process is building at a time.
|
|
25
|
+
The compiler cli, [trvc](https://github.com/travetto/travetto/tree/main/module/compiler/bin/trvc.js) is the entry point for compilation-related operations. It has the ability to check for active builds, and ongoing watch operations to ensure only one process is building at a time. Within the framework, regardless of mono-repo or not, the compilation always targets the entire project. With the efficient caching behavior, this leads to generally a minimal overhead but allows for centralization of all operations.
|
|
26
26
|
|
|
27
27
|
The compiler cli supports the following operations:
|
|
28
28
|
* `start` - Run the compiler in watch mode
|
|
@@ -36,7 +36,7 @@ The compiler cli supports the following operations:
|
|
|
36
36
|
* `manifest [output]` - Generate the project manifest
|
|
37
37
|
* `manifest:production [output]` - Generate the production project manifest
|
|
38
38
|
|
|
39
|
-
In addition to the normal output, the compiler supports an environment variable `TRV_BUILD` that supports the following values: `debug`, `info`, `warn` or `none`.
|
|
39
|
+
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`.
|
|
40
40
|
|
|
41
41
|
**Terminal: Sample trv output with debug logging**
|
|
42
42
|
```bash
|
package/__index__.ts
CHANGED
|
@@ -2,11 +2,11 @@ export * from './src/common.ts';
|
|
|
2
2
|
export * from './src/compiler.ts';
|
|
3
3
|
export * from './src/event.ts';
|
|
4
4
|
export * from './src/log.ts';
|
|
5
|
+
export * from './src/server/client.ts';
|
|
6
|
+
export * from './src/server/manager.ts';
|
|
7
|
+
export * from './src/server/process-handle.ts';
|
|
8
|
+
export * from './src/server/server.ts';
|
|
5
9
|
export * from './src/state.ts';
|
|
6
10
|
export * from './src/types.ts';
|
|
7
11
|
export * from './src/util.ts';
|
|
8
12
|
export * from './src/watch.ts';
|
|
9
|
-
export * from './src/server/client.ts';
|
|
10
|
-
export * from './src/server/server.ts';
|
|
11
|
-
export * from './src/server/manager.ts';
|
|
12
|
-
export * from './src/server/process-handle.ts';
|
package/bin/hook.js
CHANGED
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
// @ts-check
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
import { readFileSync } from 'node:fs';
|
|
4
|
+
import module from 'node:module';
|
|
4
5
|
import { fileURLToPath } from 'node:url';
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
const ogEmitWarning = process.emitWarning.bind(process);
|
|
7
8
|
|
|
8
9
|
module.registerHooks({
|
|
9
10
|
load: (url, context, nextLoad) => {
|
|
10
11
|
if (/[.]tsx?$/.test(url)) {
|
|
11
12
|
const source = readFileSync(fileURLToPath(url), 'utf8');
|
|
12
|
-
|
|
13
|
+
try {
|
|
14
|
+
process.emitWarning = () => {};
|
|
15
|
+
return { format: 'module', source: module.stripTypeScriptTypes(source), shortCircuit: true };
|
|
16
|
+
} finally {
|
|
17
|
+
process.emitWarning = ogEmitWarning;
|
|
18
|
+
}
|
|
13
19
|
} else {
|
|
14
20
|
return nextLoad(url, context);
|
|
15
21
|
}
|
|
16
22
|
}
|
|
17
|
-
});
|
|
23
|
+
});
|
package/bin/trvc-target.js
CHANGED
package/bin/trvc.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/compiler",
|
|
3
|
-
"version": "8.0.0
|
|
4
|
-
"
|
|
3
|
+
"version": "8.0.0",
|
|
4
|
+
"private": false,
|
|
5
5
|
"description": "The compiler infrastructure for the Travetto framework",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"compiler",
|
|
@@ -11,8 +11,15 @@
|
|
|
11
11
|
"homepage": "https://travetto.io",
|
|
12
12
|
"license": "MIT",
|
|
13
13
|
"author": {
|
|
14
|
-
"
|
|
15
|
-
"
|
|
14
|
+
"name": "Travetto Framework",
|
|
15
|
+
"email": "travetto.framework@gmail.com"
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"url": "git+https://github.com/travetto/travetto.git",
|
|
19
|
+
"directory": "module/compiler"
|
|
20
|
+
},
|
|
21
|
+
"bin": {
|
|
22
|
+
"trvc": "bin/trvc.js"
|
|
16
23
|
},
|
|
17
24
|
"files": [
|
|
18
25
|
"__index__.ts",
|
|
@@ -21,21 +28,18 @@
|
|
|
21
28
|
"support",
|
|
22
29
|
"tsconfig.trv.json"
|
|
23
30
|
],
|
|
31
|
+
"type": "module",
|
|
24
32
|
"main": "__index__.ts",
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
},
|
|
28
|
-
"repository": {
|
|
29
|
-
"url": "git+https://github.com/travetto/travetto.git",
|
|
30
|
-
"directory": "module/compiler"
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public"
|
|
31
35
|
},
|
|
32
36
|
"dependencies": {
|
|
33
|
-
"@parcel/watcher": "^2.
|
|
34
|
-
"@travetto/manifest": "^8.0.0
|
|
35
|
-
"@travetto/transformer": "^8.0.0
|
|
37
|
+
"@parcel/watcher": "^2.6.0",
|
|
38
|
+
"@travetto/manifest": "^8.0.0",
|
|
39
|
+
"@travetto/transformer": "^8.0.0"
|
|
36
40
|
},
|
|
37
41
|
"peerDependencies": {
|
|
38
|
-
"@travetto/cli": "^8.0.0
|
|
42
|
+
"@travetto/cli": "^8.0.0"
|
|
39
43
|
},
|
|
40
44
|
"peerDependenciesMeta": {
|
|
41
45
|
"@travetto/cli": {
|
|
@@ -47,9 +51,5 @@
|
|
|
47
51
|
"roles": [
|
|
48
52
|
"compile"
|
|
49
53
|
]
|
|
50
|
-
},
|
|
51
|
-
"private": false,
|
|
52
|
-
"publishConfig": {
|
|
53
|
-
"access": "public"
|
|
54
54
|
}
|
|
55
55
|
}
|
package/src/common.ts
CHANGED
|
@@ -6,11 +6,14 @@ import { type ManifestContext, path } from '@travetto/manifest';
|
|
|
6
6
|
import { Log } from './log.ts';
|
|
7
7
|
|
|
8
8
|
export class CommonUtil {
|
|
9
|
-
|
|
10
9
|
/**
|
|
11
10
|
* Restartable Event Stream
|
|
12
11
|
*/
|
|
13
|
-
static async *
|
|
12
|
+
static async *restartableEvents<T>(
|
|
13
|
+
input: (signal: AbortSignal) => AsyncIterable<T>,
|
|
14
|
+
parent: AbortSignal,
|
|
15
|
+
shouldRestart: (item: T) => boolean
|
|
16
|
+
): AsyncIterable<T> {
|
|
14
17
|
const log = Log.scoped('event-stream');
|
|
15
18
|
outer: while (!parent.aborted) {
|
|
16
19
|
const controller = new AbortController();
|
|
@@ -37,7 +40,8 @@ export class CommonUtil {
|
|
|
37
40
|
log.debug('Finished event stream');
|
|
38
41
|
|
|
39
42
|
// Natural exit, we done
|
|
40
|
-
if (!controller.signal.aborted) {
|
|
43
|
+
if (!controller.signal.aborted) {
|
|
44
|
+
// Shutdown source if still running
|
|
41
45
|
controller.abort();
|
|
42
46
|
}
|
|
43
47
|
return;
|
|
@@ -48,14 +52,14 @@ export class CommonUtil {
|
|
|
48
52
|
* Non-blocking timeout
|
|
49
53
|
*/
|
|
50
54
|
static nonBlockingTimeout(time: number): Promise<void> {
|
|
51
|
-
return timers.setTimeout(time, undefined, { ref: false }).catch(() => {
|
|
55
|
+
return timers.setTimeout(time, undefined, { ref: false }).catch(() => {});
|
|
52
56
|
}
|
|
53
57
|
|
|
54
58
|
/**
|
|
55
59
|
* Blocking timeout
|
|
56
60
|
*/
|
|
57
61
|
static blockingTimeout(time: number): Promise<void> {
|
|
58
|
-
return timers.setTimeout(time, undefined, { ref: true }).catch(() => {
|
|
62
|
+
return timers.setTimeout(time, undefined, { ref: true }).catch(() => {});
|
|
59
63
|
}
|
|
60
64
|
|
|
61
65
|
/**
|
|
@@ -76,8 +80,10 @@ export class CommonUtil {
|
|
|
76
80
|
* Write to stdout with backpressure handling
|
|
77
81
|
*/
|
|
78
82
|
static async writeStdout(level: number, data: unknown): Promise<void> {
|
|
79
|
-
if (data === undefined) {
|
|
83
|
+
if (data === undefined) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
80
86
|
process.stdout.write(`${JSON.stringify(data, undefined, level)}\n`) ||
|
|
81
|
-
await new Promise(resolve => process.stdout.once('drain', resolve));
|
|
82
|
-
}
|
|
83
|
-
}
|
|
87
|
+
(await new Promise(resolve => process.stdout.once('drain', resolve)));
|
|
88
|
+
}
|
|
89
|
+
}
|
package/src/compiler.ts
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import fs from 'node:fs/promises';
|
|
2
1
|
import { setMaxListeners } from 'node:events';
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
3
|
|
|
4
|
-
import { getManifestContext, ManifestDeltaUtil, ManifestIndex, ManifestUtil
|
|
4
|
+
import { type DeltaEvent, getManifestContext, ManifestDeltaUtil, ManifestIndex, ManifestUtil } from '@travetto/manifest';
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
import { CompilerWatcher } from './watch.ts';
|
|
8
|
-
import { type CompileEmitEvent, CompilerReset } from './types.ts';
|
|
6
|
+
import { CommonUtil } from './common.ts';
|
|
9
7
|
import { EventUtil } from './event.ts';
|
|
10
|
-
|
|
11
8
|
import { IpcLogger } from './log.ts';
|
|
12
|
-
import {
|
|
9
|
+
import { CompilerState } from './state.ts';
|
|
10
|
+
import { type CompileEmitEvent, CompilerReset } from './types.ts';
|
|
11
|
+
import { CompilerWatcher } from './watch.ts';
|
|
13
12
|
|
|
14
13
|
const log = new IpcLogger({ level: 'debug' });
|
|
15
14
|
|
|
@@ -17,7 +16,6 @@ const log = new IpcLogger({ level: 'debug' });
|
|
|
17
16
|
* Compilation support
|
|
18
17
|
*/
|
|
19
18
|
export class Compiler {
|
|
20
|
-
|
|
21
19
|
/**
|
|
22
20
|
* Run compiler as a main entry point
|
|
23
21
|
*/
|
|
@@ -31,8 +29,8 @@ export class Compiler {
|
|
|
31
29
|
|
|
32
30
|
#state: CompilerState;
|
|
33
31
|
#watch?: boolean;
|
|
34
|
-
#
|
|
35
|
-
#
|
|
32
|
+
#shutdownController: AbortController;
|
|
33
|
+
#shutdownSignal: AbortSignal;
|
|
36
34
|
#shuttingDown = false;
|
|
37
35
|
#deltaEvents: DeltaEvent[];
|
|
38
36
|
|
|
@@ -41,12 +39,10 @@ export class Compiler {
|
|
|
41
39
|
this.#watch = watch;
|
|
42
40
|
this.#deltaEvents = deltaEvents;
|
|
43
41
|
|
|
44
|
-
this.#
|
|
45
|
-
this.#
|
|
46
|
-
setMaxListeners(1000, this.#
|
|
47
|
-
process
|
|
48
|
-
.once('disconnect', () => this.#shutdown('manual'))
|
|
49
|
-
.on('message', event => (event === 'shutdown') && this.#shutdown('manual'));
|
|
42
|
+
this.#shutdownController = new AbortController();
|
|
43
|
+
this.#shutdownSignal = this.#shutdownController.signal;
|
|
44
|
+
setMaxListeners(1000, this.#shutdownSignal);
|
|
45
|
+
process.once('disconnect', () => this.#shutdown('manual')).on('message', event => event === 'shutdown' && this.#shutdown('manual'));
|
|
50
46
|
}
|
|
51
47
|
|
|
52
48
|
#shutdown(mode: 'error' | 'manual' | 'complete' | 'reset', errorMessage?: string): void {
|
|
@@ -78,7 +74,7 @@ export class Compiler {
|
|
|
78
74
|
// No longer listen to disconnect
|
|
79
75
|
process.removeAllListeners('disconnect');
|
|
80
76
|
process.removeAllListeners('message');
|
|
81
|
-
this.#
|
|
77
|
+
this.#shutdownController.abort();
|
|
82
78
|
CommonUtil.nonBlockingTimeout(1000).then(() => process.exit()); // Allow upto 1s to shutdown gracefully
|
|
83
79
|
}
|
|
84
80
|
|
|
@@ -111,7 +107,7 @@ export class Compiler {
|
|
|
111
107
|
/**
|
|
112
108
|
* Emit all files as a stream
|
|
113
109
|
*/
|
|
114
|
-
async *
|
|
110
|
+
async *emit(files: string[]): AsyncIterable<CompileEmitEvent> {
|
|
115
111
|
let i = 0;
|
|
116
112
|
let lastSent = Date.now();
|
|
117
113
|
|
|
@@ -122,12 +118,13 @@ export class Compiler {
|
|
|
122
118
|
const nodeModSeparator = 'node_modules/';
|
|
123
119
|
const nodeModIdx = file.lastIndexOf(nodeModSeparator);
|
|
124
120
|
const imp = nodeModIdx >= 0 ? file.substring(nodeModIdx + nodeModSeparator.length) : file;
|
|
125
|
-
yield { file: imp, i: i += 1, errors, total: files.length, duration };
|
|
126
|
-
if (
|
|
121
|
+
yield { file: imp, i: (i += 1), errors, total: files.length, duration };
|
|
122
|
+
if (Date.now() - lastSent > 50) {
|
|
123
|
+
// Limit to 1 every 50ms
|
|
127
124
|
lastSent = Date.now();
|
|
128
125
|
EventUtil.sendEvent('progress', { total: files.length, idx: i, message: imp, operation: 'compile' });
|
|
129
126
|
}
|
|
130
|
-
if (this.#
|
|
127
|
+
if (this.#shutdownSignal.aborted) {
|
|
131
128
|
break;
|
|
132
129
|
}
|
|
133
130
|
}
|
|
@@ -154,7 +151,7 @@ export class Compiler {
|
|
|
154
151
|
|
|
155
152
|
const metrics: CompileEmitEvent[] = [];
|
|
156
153
|
const isCompilerChanged = this.#deltaEvents.some(event => this.#state.isCompilerFile(event.sourceFile));
|
|
157
|
-
const changedFiles =
|
|
154
|
+
const changedFiles = isCompilerChanged ? this.#state.getAllFiles() : this.#deltaEvents.map(event => event.sourceFile);
|
|
158
155
|
|
|
159
156
|
if (changedFiles.length) {
|
|
160
157
|
for await (const event of this.emit(changedFiles)) {
|
|
@@ -170,13 +167,13 @@ export class Compiler {
|
|
|
170
167
|
}
|
|
171
168
|
metrics.push(event);
|
|
172
169
|
}
|
|
173
|
-
if (this.#
|
|
170
|
+
if (this.#shutdownSignal.aborted) {
|
|
174
171
|
log.debug('Compilation aborted');
|
|
175
172
|
} else if (failures.size) {
|
|
176
173
|
const sortedFailures = [...failures.entries()].sort((a, b) => a[0].localeCompare(b[0]));
|
|
177
|
-
log.
|
|
178
|
-
|
|
179
|
-
|
|
174
|
+
log.error(
|
|
175
|
+
'Compilation failed',
|
|
176
|
+
['', sortedFailures.flatMap(([file, count]) => `- ${file}: ${count} errors found`)].flat(3).join('\n')
|
|
180
177
|
);
|
|
181
178
|
} else {
|
|
182
179
|
log.debug('Compilation succeeded');
|
|
@@ -187,7 +184,7 @@ export class Compiler {
|
|
|
187
184
|
await ManifestUtil.writeManifest(manifest);
|
|
188
185
|
await ManifestUtil.writeDependentManifests(manifest);
|
|
189
186
|
|
|
190
|
-
if (failures.size) {
|
|
187
|
+
if (!this.#watch && failures.size) {
|
|
191
188
|
return this.#shutdown('error');
|
|
192
189
|
}
|
|
193
190
|
|
|
@@ -200,7 +197,7 @@ export class Compiler {
|
|
|
200
197
|
this.logStatistics(metrics);
|
|
201
198
|
}
|
|
202
199
|
|
|
203
|
-
if (this.#watch && !this.#
|
|
200
|
+
if (this.#watch && !this.#shutdownSignal.aborted) {
|
|
204
201
|
const resolved = this.#state.getArbitraryInputFile();
|
|
205
202
|
await this.#state.compileSourceFile(resolved);
|
|
206
203
|
|
|
@@ -208,11 +205,14 @@ export class Compiler {
|
|
|
208
205
|
|
|
209
206
|
EventUtil.sendEvent('state', { state: 'watch-start' });
|
|
210
207
|
try {
|
|
211
|
-
for await (const event of new CompilerWatcher(this.#state, this.#
|
|
208
|
+
for await (const event of new CompilerWatcher(this.#state, this.#shutdownSignal)) {
|
|
212
209
|
if (event.action !== 'delete') {
|
|
213
210
|
const errors = await this.#state.compileSourceFile(event.entry.sourceFile, true);
|
|
214
211
|
if (errors?.length) {
|
|
215
212
|
log.error('Compilation failed', `${event.entry.sourceFile}: ${errors.length} errors found`);
|
|
213
|
+
for (const error of errors) {
|
|
214
|
+
log.error(`ERROR ${event.file}:${error}`);
|
|
215
|
+
}
|
|
216
216
|
} else {
|
|
217
217
|
log.info(`Compiled ${event.entry.sourceFile} on ${event.action}`);
|
|
218
218
|
}
|
|
@@ -246,4 +246,4 @@ export class Compiler {
|
|
|
246
246
|
|
|
247
247
|
this.#shutdown('complete');
|
|
248
248
|
}
|
|
249
|
-
}
|
|
249
|
+
}
|
package/src/event.ts
CHANGED
|
@@ -3,14 +3,16 @@ import type { CompilerEvent, CompilerEventPayload, CompilerEventType } from './t
|
|
|
3
3
|
const VALID_EVENT_TYPES = new Set<CompilerEventType>(['change', 'log', 'progress', 'state', 'all', 'file']);
|
|
4
4
|
|
|
5
5
|
export class EventUtil {
|
|
6
|
-
|
|
7
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
8
|
-
static isComplilerEventType = (value: string): value is CompilerEventType => VALID_EVENT_TYPES.has(value as CompilerEventType);
|
|
6
|
+
static isCompilerEventType = (value: string): value is CompilerEventType => VALID_EVENT_TYPES.has(value as CompilerEventType);
|
|
9
7
|
|
|
10
8
|
static isCompilerEvent = (value: unknown): value is CompilerEvent =>
|
|
11
|
-
typeof value === 'object' &&
|
|
9
|
+
typeof value === 'object' &&
|
|
10
|
+
value !== null &&
|
|
11
|
+
'type' in value &&
|
|
12
|
+
typeof value.type === 'string' &&
|
|
13
|
+
EventUtil.isCompilerEventType(value.type);
|
|
12
14
|
|
|
13
15
|
static sendEvent<K extends CompilerEventType, T extends CompilerEventPayload<K>>(type: K, payload: T): void {
|
|
14
|
-
process.connected && process.send!({ type, payload }, undefined, undefined, () => {
|
|
16
|
+
process.connected && process.send!({ type, payload }, undefined, undefined, () => {});
|
|
15
17
|
}
|
|
16
|
-
}
|
|
18
|
+
}
|
package/src/log.ts
CHANGED
|
@@ -15,7 +15,6 @@ export type LogShape = Record<'info' | 'debug' | 'warn' | 'error', (message: str
|
|
|
15
15
|
const ESC = '\x1b[';
|
|
16
16
|
|
|
17
17
|
export class Logger implements LogConfig, LogShape {
|
|
18
|
-
|
|
19
18
|
static #linePartial: boolean | undefined;
|
|
20
19
|
|
|
21
20
|
/** Rewrite text line, tracking cleanup as necessary */
|
|
@@ -23,7 +22,8 @@ export class Logger implements LogConfig, LogShape {
|
|
|
23
22
|
if ((!text && !this.#linePartial) || !process.stdout.isTTY) {
|
|
24
23
|
return;
|
|
25
24
|
}
|
|
26
|
-
if (this.#linePartial === undefined) {
|
|
25
|
+
if (this.#linePartial === undefined) {
|
|
26
|
+
// First time
|
|
27
27
|
process.stdout.write(`${ESC}?25l`); // Hide cursor
|
|
28
28
|
process.on('exit', () => this.reset());
|
|
29
29
|
}
|
|
@@ -35,7 +35,9 @@ export class Logger implements LogConfig, LogShape {
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
static reset(): void {
|
|
38
|
+
static reset(): void {
|
|
39
|
+
process.stdout.write(`${ESC}!p${ESC}?25h`);
|
|
40
|
+
}
|
|
39
41
|
|
|
40
42
|
level?: CompilerLogLevel | 'none';
|
|
41
43
|
root: string = process.cwd();
|
|
@@ -47,28 +49,38 @@ export class Logger implements LogConfig, LogShape {
|
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
valid(event: CompilerLogEvent): boolean {
|
|
50
|
-
return LEVEL_TO_PRIORITY[this.level ?? this.parent?.level
|
|
52
|
+
return LEVEL_TO_PRIORITY[this.level ?? this.parent?.level ?? 'none'] <= LEVEL_TO_PRIORITY[event.level];
|
|
51
53
|
}
|
|
52
54
|
|
|
53
55
|
/** Log event with filtering by level */
|
|
54
56
|
render(event: CompilerLogEvent): void {
|
|
55
|
-
if (!this.valid(event)) {
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
if (!this.valid(event)) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const params = [event.message, ...(event.args ?? [])].map(arg =>
|
|
61
|
+
typeof arg === 'string' ? arg.replaceAll(this.root ?? this.parent?.root, '.') : arg
|
|
62
|
+
);
|
|
58
63
|
|
|
59
64
|
if (event.scope ?? this.scope) {
|
|
60
65
|
params.unshift(`[${(event.scope ?? this.scope!).padEnd(SCOPE_MAX, ' ')}]`);
|
|
61
66
|
}
|
|
62
67
|
params.unshift(new Date().toISOString(), `${event.level.padEnd(5)}`);
|
|
63
68
|
Logger.rewriteLine(''); // Clear out progress line, if active
|
|
64
|
-
// eslint-disable-next-line no-console
|
|
65
69
|
console[event.level]!(...params);
|
|
66
70
|
}
|
|
67
71
|
|
|
68
|
-
info(message: string, ...args: unknown[]): void {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
+
info(message: string, ...args: unknown[]): void {
|
|
73
|
+
this.render({ level: 'info', message, args });
|
|
74
|
+
}
|
|
75
|
+
debug(message: string, ...args: unknown[]): void {
|
|
76
|
+
this.render({ level: 'debug', message, args });
|
|
77
|
+
}
|
|
78
|
+
warn(message: string, ...args: unknown[]): void {
|
|
79
|
+
this.render({ level: 'warn', message, args });
|
|
80
|
+
}
|
|
81
|
+
error(message: string, ...args: unknown[]): void {
|
|
82
|
+
this.render({ level: 'error', message, args });
|
|
83
|
+
}
|
|
72
84
|
}
|
|
73
85
|
|
|
74
86
|
class $RootLogger extends Logger {
|
|
@@ -86,9 +98,17 @@ class $RootLogger extends Logger {
|
|
|
86
98
|
initLevel(defaultLevel: CompilerLogLevel | 'none'): void {
|
|
87
99
|
const value = process.env.TRV_QUIET !== 'true' ? process.env.TRV_BUILD : 'none';
|
|
88
100
|
switch (value) {
|
|
89
|
-
case 'debug':
|
|
90
|
-
case
|
|
91
|
-
case '
|
|
101
|
+
case 'debug':
|
|
102
|
+
case 'warn':
|
|
103
|
+
case 'error':
|
|
104
|
+
case 'info':
|
|
105
|
+
this.level = value;
|
|
106
|
+
break;
|
|
107
|
+
case undefined:
|
|
108
|
+
this.level = defaultLevel;
|
|
109
|
+
break;
|
|
110
|
+
default:
|
|
111
|
+
this.level = 'none';
|
|
92
112
|
}
|
|
93
113
|
}
|
|
94
114
|
|
|
@@ -100,21 +120,34 @@ class $RootLogger extends Logger {
|
|
|
100
120
|
/** Scope and provide a callback pattern for access to a logger */
|
|
101
121
|
wrap<T = unknown>(scope: string, operation: (log: Logger) => Promise<T>, basic = true): Promise<T> {
|
|
102
122
|
const logger = this.scoped(scope);
|
|
103
|
-
|
|
123
|
+
if (basic) {
|
|
124
|
+
logger.debug('Started');
|
|
125
|
+
return operation(logger).finally(() => logger.debug('Completed'));
|
|
126
|
+
} else {
|
|
127
|
+
return operation(logger);
|
|
128
|
+
}
|
|
104
129
|
}
|
|
105
130
|
|
|
106
131
|
/** Write progress event, if active */
|
|
107
132
|
onProgressEvent(event: CompilerProgressEvent): void | Promise<void> {
|
|
108
|
-
if (!
|
|
109
|
-
|
|
110
|
-
|
|
133
|
+
if (!this.logProgress) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const progress = Math.trunc((event.idx * 100) / event.total);
|
|
137
|
+
const text = event.complete
|
|
138
|
+
? ''
|
|
139
|
+
: `Compiling [${'#'.repeat(Math.trunc(progress / 10)).padEnd(10, ' ')}] [${event.idx}/${event.total}] ${event.message}`;
|
|
111
140
|
return Logger.rewriteLine(text);
|
|
112
141
|
}
|
|
113
142
|
|
|
114
143
|
/** Write all progress events if active */
|
|
115
144
|
async consumeProgressEvents(input: () => AsyncIterable<CompilerProgressEvent>): Promise<void> {
|
|
116
|
-
if (!
|
|
117
|
-
|
|
145
|
+
if (!this.logProgress) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
for await (const event of input()) {
|
|
149
|
+
this.onProgressEvent(event);
|
|
150
|
+
}
|
|
118
151
|
Logger.reset();
|
|
119
152
|
}
|
|
120
153
|
}
|
|
@@ -123,7 +156,9 @@ export const Log = new $RootLogger();
|
|
|
123
156
|
|
|
124
157
|
export class IpcLogger extends Logger {
|
|
125
158
|
render(event: CompilerLogEvent): void {
|
|
126
|
-
if (!this.valid(event)) {
|
|
159
|
+
if (!this.valid(event)) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
127
162
|
if (process.connected && process.send) {
|
|
128
163
|
process.send({ type: 'log', payload: event });
|
|
129
164
|
}
|
package/src/queue.ts
CHANGED
|
@@ -10,7 +10,9 @@ export class AsyncQueue<X> implements AsyncIterator<X>, AsyncIterable<X> {
|
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
[Symbol.asyncIterator](): AsyncIterator<X> {
|
|
13
|
+
[Symbol.asyncIterator](): AsyncIterator<X> {
|
|
14
|
+
return this;
|
|
15
|
+
}
|
|
14
16
|
|
|
15
17
|
async next(): Promise<IteratorResult<X>> {
|
|
16
18
|
while (!this.#done && !this.#queue.length) {
|
|
@@ -35,4 +37,4 @@ export class AsyncQueue<X> implements AsyncIterator<X>, AsyncIterable<X> {
|
|
|
35
37
|
this.#done = true;
|
|
36
38
|
this.#ready.resolve();
|
|
37
39
|
}
|
|
38
|
-
}
|
|
40
|
+
}
|