@travetto/compiler 3.0.0-rc.27 → 3.0.0-rc.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -3
- package/src/compiler.ts +19 -17
- package/support/launcher.ts +15 -2
- package/support/lock.ts +14 -17
- package/support/log.ts +22 -7
- package/support/transpile.ts +9 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/compiler",
|
|
3
|
-
"version": "3.0.0-rc.
|
|
3
|
+
"version": "3.0.0-rc.29",
|
|
4
4
|
"description": "Compiler",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"compiler",
|
|
@@ -32,11 +32,11 @@
|
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@parcel/watcher": "^2.1.0",
|
|
34
34
|
"@travetto/manifest": "^3.0.0-rc.15",
|
|
35
|
-
"@travetto/terminal": "^3.0.0-rc.
|
|
35
|
+
"@travetto/terminal": "^3.0.0-rc.10",
|
|
36
36
|
"@travetto/transformer": "^3.0.0-rc.19"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
|
-
"@travetto/cli": "^3.0.0-rc.
|
|
39
|
+
"@travetto/cli": "^3.0.0-rc.20"
|
|
40
40
|
},
|
|
41
41
|
"peerDependenciesMeta": {
|
|
42
42
|
"@travetto/cli": {
|
package/src/compiler.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { install } from 'source-map-support';
|
|
2
|
-
import timers from 'timers/promises';
|
|
3
2
|
import ts from 'typescript';
|
|
4
3
|
import fs from 'fs/promises';
|
|
5
4
|
|
|
@@ -12,8 +11,6 @@ import { CompilerWatcher } from './watch';
|
|
|
12
11
|
import { Log } from './log';
|
|
13
12
|
import { CompileEmitError, CompileEmitEvent, CompileEmitter } from './types';
|
|
14
13
|
|
|
15
|
-
const PING_THRESHOLD = 1000;
|
|
16
|
-
|
|
17
14
|
/**
|
|
18
15
|
* Compilation support
|
|
19
16
|
*/
|
|
@@ -24,21 +21,22 @@ export class Compiler {
|
|
|
24
21
|
*/
|
|
25
22
|
static async main(): Promise<void> {
|
|
26
23
|
const [dirty, watch] = process.argv.slice(2);
|
|
27
|
-
|
|
24
|
+
const state = await CompilerState.get(RootIndex);
|
|
28
25
|
const dirtyFiles = (await fs.readFile(dirty, 'utf8')).split(/\n/).filter(x => !!x);
|
|
29
|
-
|
|
26
|
+
await new Compiler(state, dirtyFiles, watch === 'true').run();
|
|
27
|
+
process.exit(0);
|
|
30
28
|
}
|
|
31
29
|
|
|
32
30
|
#state: CompilerState;
|
|
33
31
|
#dirtyFiles: string[];
|
|
32
|
+
#watch?: boolean;
|
|
34
33
|
|
|
35
|
-
|
|
36
|
-
this.#state =
|
|
34
|
+
constructor(state: CompilerState, dirtyFiles: string[], watch?: boolean) {
|
|
35
|
+
this.#state = state;
|
|
37
36
|
this.#dirtyFiles = dirtyFiles[0] === '*' ?
|
|
38
37
|
this.#state.getAllFiles() :
|
|
39
38
|
dirtyFiles.map(f => this.#state.getBySource(f)!.input);
|
|
40
|
-
|
|
41
|
-
return this;
|
|
39
|
+
this.#watch = watch;
|
|
42
40
|
}
|
|
43
41
|
|
|
44
42
|
/**
|
|
@@ -99,9 +97,14 @@ export class Compiler {
|
|
|
99
97
|
/**
|
|
100
98
|
* Run the compiler
|
|
101
99
|
*/
|
|
102
|
-
async run(
|
|
100
|
+
async run(): Promise<void> {
|
|
101
|
+
await GlobalTerminal.init();
|
|
102
|
+
install();
|
|
103
|
+
|
|
103
104
|
Log.debug('Compilation started');
|
|
104
105
|
|
|
106
|
+
process.on('disconnect', () => process.exit(0));
|
|
107
|
+
|
|
105
108
|
const emitter = await this.getCompiler();
|
|
106
109
|
let failed = false;
|
|
107
110
|
|
|
@@ -123,7 +126,7 @@ export class Compiler {
|
|
|
123
126
|
} else {
|
|
124
127
|
Log.debug('Compilation succeeded');
|
|
125
128
|
}
|
|
126
|
-
} else if (watch) {
|
|
129
|
+
} else if (this.#watch) {
|
|
127
130
|
// Prime compiler before complete
|
|
128
131
|
const resolved = this.#state.getArbitraryInputFile();
|
|
129
132
|
await emitter(resolved, true);
|
|
@@ -131,16 +134,15 @@ export class Compiler {
|
|
|
131
134
|
|
|
132
135
|
process.send?.('build-complete');
|
|
133
136
|
|
|
134
|
-
if (watch) {
|
|
137
|
+
if (this.#watch) {
|
|
135
138
|
Log.info('Watch is ready');
|
|
136
139
|
await this.#watchLocalModules(emitter);
|
|
137
|
-
|
|
138
|
-
|
|
140
|
+
const output = this.#state.resolveOutputFile('.');
|
|
141
|
+
for await (const _ of fs.watch(output)) {
|
|
142
|
+
if (!await fs.stat(output).catch(() => false)) {
|
|
139
143
|
process.send?.('restart');
|
|
140
|
-
} else {
|
|
141
|
-
process.send?.('ping');
|
|
142
144
|
}
|
|
143
145
|
}
|
|
144
146
|
}
|
|
145
147
|
}
|
|
146
|
-
}
|
|
148
|
+
}
|
package/support/launcher.ts
CHANGED
|
@@ -21,7 +21,10 @@ async function compile(ctx: ManifestContext, op: 'watch' | 'build' | undefined,
|
|
|
21
21
|
|
|
22
22
|
await LogUtil.withLogger('precompile', async () => {
|
|
23
23
|
for (const mod of PRECOMPILE_MODS) {
|
|
24
|
-
|
|
24
|
+
const count = (await TranspileUtil.compileIfStale(ctx, 'precompile', mod, SOURCE_SEED)).length;
|
|
25
|
+
if (mod !== '@travetto/terminal') {
|
|
26
|
+
changes += count;
|
|
27
|
+
}
|
|
25
28
|
}
|
|
26
29
|
});
|
|
27
30
|
|
|
@@ -108,7 +111,14 @@ async function exportManifest(ctx: ManifestContext, output?: string, env = 'dev'
|
|
|
108
111
|
* Launch
|
|
109
112
|
*/
|
|
110
113
|
export async function launch(ctx: ManifestContext, root: ManifestContext, op?: 'build' | 'watch' | 'manifest', args: (string | undefined)[] = []): Promise<void> {
|
|
114
|
+
// If quiet enabled, turn off all output by default
|
|
115
|
+
LogUtil.level = process.env.TRV_BUILD ?? (process.env.TRV_QUIET ? 'none' : (!op ? 'warn' : 'info'));
|
|
116
|
+
|
|
111
117
|
if (op !== 'manifest' && await LockManager.getCompileAction(root, op) === 'build') {
|
|
118
|
+
|
|
119
|
+
// Ready signal
|
|
120
|
+
process.send?.('ready');
|
|
121
|
+
|
|
112
122
|
await LockManager.withLocks(root, async (acquire, release) => {
|
|
113
123
|
let action: CompileResult;
|
|
114
124
|
do {
|
|
@@ -118,7 +128,10 @@ export async function launch(ctx: ManifestContext, root: ManifestContext, op?: '
|
|
|
118
128
|
}
|
|
119
129
|
action = await compile(root, op, msg => {
|
|
120
130
|
switch (msg) {
|
|
121
|
-
case 'build-complete':
|
|
131
|
+
case 'build-complete': {
|
|
132
|
+
release('build');
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
122
135
|
}
|
|
123
136
|
});
|
|
124
137
|
} while (action === 'restart');
|
package/support/lock.ts
CHANGED
|
@@ -28,7 +28,7 @@ export class LockManager {
|
|
|
28
28
|
* Get the lock file name
|
|
29
29
|
*/
|
|
30
30
|
static #getFileName(ctx: ManifestContext, type: LockType): string {
|
|
31
|
-
return path.resolve(ctx.workspacePath, ctx.toolFolder, `${type}.
|
|
31
|
+
return path.resolve(ctx.workspacePath, ctx.toolFolder, `${type}.lock`);
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
/**
|
|
@@ -47,10 +47,9 @@ export class LockManager {
|
|
|
47
47
|
const stale = this.#isStale(stat);
|
|
48
48
|
let pid: number | undefined;
|
|
49
49
|
if (stat) {
|
|
50
|
-
const
|
|
51
|
-
const filePid = parseInt(content, 10);
|
|
50
|
+
const { pid: filePid } = JSON.parse(await fs.readFile(file, 'utf8'));
|
|
52
51
|
if (stale) {
|
|
53
|
-
LogUtil.log('lock', [], '
|
|
52
|
+
LogUtil.log('lock', [], 'debug', `${type} file is stale: ${stat.mtimeMs} vs ${Date.now()}`);
|
|
54
53
|
} else {
|
|
55
54
|
pid = filePid;
|
|
56
55
|
}
|
|
@@ -65,7 +64,7 @@ export class LockManager {
|
|
|
65
64
|
const file = this.#getFileName(ctx, type);
|
|
66
65
|
mkdirSync(path.dirname(file), { recursive: true });
|
|
67
66
|
LogUtil.log('lock', [], 'debug', `Acquiring ${type}`);
|
|
68
|
-
writeFileSync(file,
|
|
67
|
+
writeFileSync(file, JSON.stringify({ pid: process.pid }), 'utf8');
|
|
69
68
|
}
|
|
70
69
|
|
|
71
70
|
/**
|
|
@@ -118,25 +117,24 @@ export class LockManager {
|
|
|
118
117
|
* Read the watch lock file and determine its result, communicating with the user as necessary
|
|
119
118
|
*/
|
|
120
119
|
static async #getWatchAction(ctx: ManifestContext, log: CompilerLogger, lockType: LockType | undefined, buildState: LockDetails): Promise<LockAction> {
|
|
121
|
-
const level = lockType ? 'info' : 'debug';
|
|
122
120
|
if (lockType === 'watch') {
|
|
123
|
-
log(
|
|
121
|
+
log('info', 'Already running');
|
|
124
122
|
return 'skip';
|
|
125
123
|
} else {
|
|
126
124
|
if (buildState.pid) {
|
|
127
|
-
log('
|
|
125
|
+
log('warn', 'Already running, waiting for build to finish');
|
|
128
126
|
switch (await this.#waitForRelease(ctx, 'build')) {
|
|
129
127
|
case 'complete': {
|
|
130
|
-
log(
|
|
128
|
+
log('info', 'Completed build');
|
|
131
129
|
return 'skip';
|
|
132
130
|
}
|
|
133
131
|
case 'stale': {
|
|
134
|
-
log(
|
|
132
|
+
log('info', 'Became stale, retrying');
|
|
135
133
|
return 'retry';
|
|
136
134
|
}
|
|
137
135
|
}
|
|
138
136
|
} else {
|
|
139
|
-
log(
|
|
137
|
+
log('info', 'Already running, and has built');
|
|
140
138
|
return 'skip';
|
|
141
139
|
}
|
|
142
140
|
}
|
|
@@ -146,21 +144,20 @@ export class LockManager {
|
|
|
146
144
|
* Read the build lock file and determine its result, communicating with the user as necessary
|
|
147
145
|
*/
|
|
148
146
|
static async #getBuildAction(ctx: ManifestContext, log: CompilerLogger, lockType: LockType | undefined): Promise<LockAction> {
|
|
149
|
-
const level = lockType ? 'info' : 'debug';
|
|
150
147
|
if (lockType === 'watch') {
|
|
151
|
-
log('
|
|
148
|
+
log('warn', 'Build already running, waiting to begin watch');
|
|
152
149
|
const res = await this.#waitForRelease(ctx, 'build');
|
|
153
|
-
log(
|
|
150
|
+
log('info', `Finished with status of ${res}, retrying`);
|
|
154
151
|
return 'retry';
|
|
155
152
|
} else {
|
|
156
|
-
log('
|
|
153
|
+
log('warn', 'Already running, waiting for completion');
|
|
157
154
|
switch (await this.#waitForRelease(ctx, lockType ?? 'build')) {
|
|
158
155
|
case 'complete': {
|
|
159
|
-
log(
|
|
156
|
+
log('info', 'Completed');
|
|
160
157
|
return 'skip';
|
|
161
158
|
}
|
|
162
159
|
case 'stale': {
|
|
163
|
-
log(
|
|
160
|
+
log('info', 'Became stale, retrying');
|
|
164
161
|
return 'retry';
|
|
165
162
|
}
|
|
166
163
|
}
|
package/support/log.ts
CHANGED
|
@@ -2,16 +2,24 @@ export type CompilerLogEvent = [level: 'info' | 'debug' | 'warn', message: strin
|
|
|
2
2
|
export type CompilerLogger = (...args: CompilerLogEvent) => void;
|
|
3
3
|
export type WithLogger<T> = (log: CompilerLogger) => Promise<T>;
|
|
4
4
|
|
|
5
|
-
const ENV_LEVEL = process.env.TRV_BUILD ?? 'info';
|
|
6
|
-
const LEVELS = {
|
|
7
|
-
warn: /^(debug|info|warn)$/.test(ENV_LEVEL),
|
|
8
|
-
info: /^(debug|info)$/.test(ENV_LEVEL),
|
|
9
|
-
debug: /^debug$/.test(ENV_LEVEL),
|
|
10
|
-
};
|
|
11
5
|
const SCOPE_MAX = 15;
|
|
12
6
|
|
|
13
7
|
export class LogUtil {
|
|
14
8
|
|
|
9
|
+
static levels: {
|
|
10
|
+
debug: boolean;
|
|
11
|
+
info: boolean;
|
|
12
|
+
warn: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
static set level(value: string) {
|
|
16
|
+
this.levels = {
|
|
17
|
+
warn: /^(debug|info|warn)$/.test(value),
|
|
18
|
+
info: /^(debug|info)$/.test(value),
|
|
19
|
+
debug: /^debug$/.test(value),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
15
23
|
/**
|
|
16
24
|
* Is object a log event
|
|
17
25
|
*/
|
|
@@ -22,7 +30,14 @@ export class LogUtil {
|
|
|
22
30
|
*/
|
|
23
31
|
static log(scope: string, args: string[], ...[level, msg]: CompilerLogEvent): void {
|
|
24
32
|
const message = msg.replaceAll(process.cwd(), '.');
|
|
25
|
-
|
|
33
|
+
if (LogUtil.levels[level]) {
|
|
34
|
+
const params = [`[${scope.padEnd(SCOPE_MAX, ' ')}]`, ...args, message];
|
|
35
|
+
if (!/(0|false|off|no)$/i.test(process.env.TRV_LOG_TIME ?? '')) {
|
|
36
|
+
params.unshift(new Date().toISOString());
|
|
37
|
+
}
|
|
38
|
+
// eslint-disable-next-line no-console
|
|
39
|
+
console[level]!(...params);
|
|
40
|
+
}
|
|
26
41
|
}
|
|
27
42
|
|
|
28
43
|
/**
|
package/support/transpile.ts
CHANGED
|
@@ -131,8 +131,8 @@ export class TranspileUtil {
|
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
/**
|
|
134
|
-
|
|
135
|
-
|
|
134
|
+
* Recompile folder if stale
|
|
135
|
+
*/
|
|
136
136
|
static async compileIfStale(ctx: ManifestContext, scope: string, mod: string, seed: string[]): Promise<string[]> {
|
|
137
137
|
const files = await this.getModuleSources(ctx, mod, seed);
|
|
138
138
|
const changes = files.filter(x => x.stale).map(x => x.input);
|
|
@@ -166,13 +166,14 @@ export class TranspileUtil {
|
|
|
166
166
|
static async runCompiler(ctx: ManifestContext, manifest: ManifestRoot, changed: DeltaEvent[], watch: boolean, onMessage: (msg: unknown) => void): Promise<CompileResult> {
|
|
167
167
|
const compiler = path.resolve(ctx.workspacePath, ctx.compilerFolder);
|
|
168
168
|
const main = path.resolve(compiler, 'node_modules', '@travetto/compiler/support/compiler-entry.js');
|
|
169
|
-
const deltaFile = path.resolve(os.tmpdir(), `manifest-delta.${
|
|
169
|
+
const deltaFile = path.resolve(os.tmpdir(), `manifest-delta.${process.pid}.${process.ppid}.${Date.now()}.json`);
|
|
170
170
|
|
|
171
171
|
const changedFiles = changed[0]?.file === '*' ? ['*'] : changed.map(ev =>
|
|
172
172
|
path.resolve(manifest.workspacePath, manifest.modules[ev.module].sourceFolder, ev.file)
|
|
173
173
|
);
|
|
174
174
|
|
|
175
175
|
let proc: cp.ChildProcess | undefined;
|
|
176
|
+
let kill: (() => void) | undefined;
|
|
176
177
|
|
|
177
178
|
try {
|
|
178
179
|
await this.writeTextFile(deltaFile, changedFiles.join('\n'));
|
|
@@ -195,9 +196,14 @@ export class TranspileUtil {
|
|
|
195
196
|
}
|
|
196
197
|
})
|
|
197
198
|
.on('exit', code => (code !== null && code > 0) ? rej(new Error('Failed during compilation')) : res('complete'));
|
|
199
|
+
kill = (): void => { proc?.kill('SIGKILL'); };
|
|
200
|
+
process.on('exit', kill);
|
|
198
201
|
}));
|
|
199
202
|
} finally {
|
|
200
203
|
if (proc?.killed === false) { proc.kill('SIGKILL'); }
|
|
204
|
+
if (kill) {
|
|
205
|
+
process.removeListener('exit', kill);
|
|
206
|
+
}
|
|
201
207
|
await fs.rm(deltaFile, { force: true });
|
|
202
208
|
}
|
|
203
209
|
}
|