@travetto/compiler 3.0.0-rc.13 → 3.0.0-rc.15
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/__index__.ts +4 -1
- package/bin/trv.js +15 -11
- package/package.json +5 -5
- package/src/compiler.ts +43 -82
- package/src/log.ts +18 -0
- package/src/state.ts +146 -144
- package/src/types.ts +14 -0
- package/src/util.ts +16 -12
- package/src/watch.ts +142 -0
- package/support/launcher.ts +45 -65
- package/support/lock-pinger.ts +25 -0
- package/support/lock.ts +237 -0
- package/support/log.ts +31 -0
- package/support/transpile.ts +63 -37
package/__index__.ts
CHANGED
package/bin/trv.js
CHANGED
|
@@ -9,6 +9,8 @@ import { getManifestContext } from '@travetto/manifest/bin/context.js';
|
|
|
9
9
|
|
|
10
10
|
const VALID_OPS = { watch: 'watch', build: 'build', clean: 'clean', manifest: 'manifest' };
|
|
11
11
|
|
|
12
|
+
const COMPILER_FILES = [...['launcher', 'transpile', 'lock', 'log', 'lock-pinger'].map(x => `support/${x}.js`), 'package.json'];
|
|
13
|
+
|
|
12
14
|
/**
|
|
13
15
|
* @param {import('@travetto/manifest').ManifestContext} ctx
|
|
14
16
|
* @return {Promise<import('@travetto/compiler/support/launcher').launch>}
|
|
@@ -17,7 +19,7 @@ const $getLauncher = async (ctx) => {
|
|
|
17
19
|
const compPkg = createRequire(path.resolve('node_modules')).resolve('@travetto/compiler/package.json');
|
|
18
20
|
const files = [];
|
|
19
21
|
|
|
20
|
-
for (const file of
|
|
22
|
+
for (const file of COMPILER_FILES) {
|
|
21
23
|
const target = path.resolve(ctx.workspacePath, ctx.compilerFolder, 'node_modules', '@travetto/compiler', file);
|
|
22
24
|
const src = compPkg.replace('package.json', file.replace(/[.]js$/, '.ts'));
|
|
23
25
|
|
|
@@ -30,13 +32,12 @@ const $getLauncher = async (ctx) => {
|
|
|
30
32
|
await fs.mkdir(path.dirname(target), { recursive: true });
|
|
31
33
|
const text = await fs.readFile(src, 'utf8');
|
|
32
34
|
if (file.endsWith('.js')) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
35
|
+
const content = ts.transpile(
|
|
36
|
+
text,
|
|
37
|
+
{ target: ts.ScriptTarget.ES2020, module, esModuleInterop: true, allowSyntheticDefaultImports: true }
|
|
38
|
+
)
|
|
39
|
+
.replace(/^((?:im|ex)port .*from '[.][^']+)(')/mg, (_, a, b) => `${a}.js${b}`)
|
|
40
|
+
.replace(/^(import [^\n]*from '[^.][^\n/]+[/][^\n/]+[/][^\n']+)(')/mg, (_, a, b) => `${a}.js${b}`);
|
|
40
41
|
await fs.writeFile(target, content, 'utf8');
|
|
41
42
|
} else {
|
|
42
43
|
const pkg = JSON.parse(text);
|
|
@@ -57,11 +58,14 @@ const $getLauncher = async (ctx) => {
|
|
|
57
58
|
const [op, args] = [VALID_OPS[process.argv[2]], process.argv.slice(3)];
|
|
58
59
|
|
|
59
60
|
if (op === 'clean') {
|
|
60
|
-
|
|
61
|
+
const folders = process.argv.find(x => x === '--all' || x === '-a') ? [ctx.outputFolder, ctx.compilerFolder] : [ctx.outputFolder];
|
|
62
|
+
for (const f of folders) {
|
|
61
63
|
await fs.rm(path.resolve(ctx.workspacePath, f), { force: true, recursive: true });
|
|
62
64
|
}
|
|
63
|
-
return console.log(`Cleaned ${ctx.workspacePath}: [${
|
|
65
|
+
return console.log(`Cleaned ${ctx.workspacePath}: [${folders.join(', ')}]`);
|
|
64
66
|
}
|
|
65
67
|
|
|
66
|
-
|
|
68
|
+
const rootCtx = ctx.monoRepo ? await getManifestContext(ctx.workspacePath) : ctx;
|
|
69
|
+
|
|
70
|
+
return (await $getLauncher(ctx))(ctx, rootCtx, op, args);
|
|
67
71
|
})();
|
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.15",
|
|
4
4
|
"description": "Compiler",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"compiler",
|
|
@@ -31,12 +31,12 @@
|
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@parcel/watcher": "^2.1.0",
|
|
34
|
-
"@travetto/manifest": "^3.0.0-rc.
|
|
35
|
-
"@travetto/terminal": "^3.0.0-rc.
|
|
36
|
-
"@travetto/transformer": "^3.0.0-rc.
|
|
34
|
+
"@travetto/manifest": "^3.0.0-rc.10",
|
|
35
|
+
"@travetto/terminal": "^3.0.0-rc.7",
|
|
36
|
+
"@travetto/transformer": "^3.0.0-rc.13"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
|
-
"@travetto/cli": "^3.0.0-rc.
|
|
39
|
+
"@travetto/cli": "^3.0.0-rc.12"
|
|
40
40
|
},
|
|
41
41
|
"peerDependenciesMeta": {
|
|
42
42
|
"@travetto/cli": {
|
package/src/compiler.ts
CHANGED
|
@@ -1,37 +1,18 @@
|
|
|
1
|
-
import util from 'util';
|
|
2
1
|
import { install } from 'source-map-support';
|
|
2
|
+
import timers from 'timers/promises';
|
|
3
3
|
import ts from 'typescript';
|
|
4
4
|
import fs from 'fs/promises';
|
|
5
5
|
|
|
6
6
|
import { GlobalTerminal, TerminalProgressEvent } from '@travetto/terminal';
|
|
7
|
-
import { RootIndex
|
|
8
|
-
import { TransformerManager } from '@travetto/transformer';
|
|
7
|
+
import { RootIndex } from '@travetto/manifest';
|
|
9
8
|
|
|
10
9
|
import { CompilerUtil } from './util';
|
|
11
10
|
import { CompilerState } from './state';
|
|
12
|
-
import
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
init(checker: ts.TypeChecker): void;
|
|
16
|
-
get(): ts.CustomTransformers | undefined;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
type EmitError = Error | readonly ts.Diagnostic[];
|
|
20
|
-
type Emitter = (file: string, newProgram?: boolean) => Promise<EmitError | undefined>;
|
|
21
|
-
type EmitEvent = { file: string, i: number, total: number, err?: EmitError };
|
|
22
|
-
|
|
23
|
-
function log(level: 'info' | 'debug', message: string, ...args: unknown[]): void {
|
|
24
|
-
if (process.send) {
|
|
25
|
-
const ev: CompilerLogEvent = [level, util.format(message, ...args)];
|
|
26
|
-
process.send(ev);
|
|
27
|
-
} else {
|
|
28
|
-
// eslint-disable-next-line no-console
|
|
29
|
-
console[level](message, ...args);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
11
|
+
import { CompilerWatcher } from './watch';
|
|
12
|
+
import { Log } from './log';
|
|
13
|
+
import { CompileEmitError, CompileEmitEvent, CompileEmitter } from './types';
|
|
32
14
|
|
|
33
|
-
const
|
|
34
|
-
const info = log.bind(null, 'info');
|
|
15
|
+
const PING_THRESHOLD = 1000;
|
|
35
16
|
|
|
36
17
|
/**
|
|
37
18
|
* Compilation support
|
|
@@ -45,78 +26,50 @@ export class Compiler {
|
|
|
45
26
|
const [dirty, watch] = process.argv.slice(2);
|
|
46
27
|
install();
|
|
47
28
|
const dirtyFiles = (await fs.readFile(dirty, 'utf8')).split(/\n/).filter(x => !!x);
|
|
48
|
-
return new Compiler(dirtyFiles).run(watch === 'true');
|
|
29
|
+
return new Compiler().init(dirtyFiles).then(c => c.run(watch === 'true'));
|
|
49
30
|
}
|
|
50
31
|
|
|
51
32
|
#state: CompilerState;
|
|
52
33
|
#dirtyFiles: string[];
|
|
53
34
|
|
|
54
|
-
|
|
55
|
-
this.#state =
|
|
35
|
+
async init(dirtyFiles: string[]): Promise<this> {
|
|
36
|
+
this.#state = await CompilerState.get(RootIndex);
|
|
56
37
|
this.#dirtyFiles = dirtyFiles[0] === '*' ?
|
|
57
38
|
this.#state.getAllFiles() :
|
|
58
|
-
dirtyFiles.map(f => this.#state.
|
|
59
|
-
}
|
|
39
|
+
dirtyFiles.map(f => this.#state.getBySource(f)!.input);
|
|
60
40
|
|
|
61
|
-
|
|
62
|
-
return this.#state;
|
|
41
|
+
return this;
|
|
63
42
|
}
|
|
64
43
|
|
|
65
44
|
/**
|
|
66
45
|
* Watches local modules
|
|
67
46
|
*/
|
|
68
|
-
|
|
69
|
-
|
|
47
|
+
#watchLocalModules(emit: CompileEmitter): Promise<() => Promise<void>> {
|
|
48
|
+
return new CompilerWatcher(this.#state).watchFiles(async file => {
|
|
70
49
|
const err = await emit(file, true);
|
|
71
50
|
if (err) {
|
|
72
|
-
info('Compilation Error', CompilerUtil.buildTranspileError(file, err));
|
|
51
|
+
Log.info('Compilation Error', CompilerUtil.buildTranspileError(file, err));
|
|
73
52
|
} else {
|
|
74
|
-
info(`Compiled ${file.split('node_modules/')[1]}`);
|
|
53
|
+
Log.info(`Compiled ${file.split('node_modules/')[1]}`);
|
|
75
54
|
}
|
|
76
|
-
|
|
77
|
-
const watcher = this.state.getWatcher({
|
|
78
|
-
create: emitWithError,
|
|
79
|
-
update: emitWithError,
|
|
80
|
-
delete: (outputFile) => fs.unlink(outputFile).catch(() => { })
|
|
81
|
-
});
|
|
82
|
-
return watchFolders(RootIndex.getLocalInputFolders(), watcher, {
|
|
83
|
-
filter: ev => ev.file.endsWith('.ts') || ev.file.endsWith('.js'),
|
|
84
|
-
ignore: ['node_modules']
|
|
55
|
+
return err;
|
|
85
56
|
});
|
|
86
57
|
}
|
|
87
58
|
|
|
88
|
-
async createTransformerProvider(): Promise<TransformerProvider> {
|
|
89
|
-
return TransformerManager.create(this.state.transformers);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
59
|
/**
|
|
93
60
|
* Compile in a single pass, only emitting dirty files
|
|
94
61
|
*/
|
|
95
|
-
async getCompiler(): Promise<
|
|
62
|
+
async getCompiler(): Promise<CompileEmitter> {
|
|
96
63
|
let program: ts.Program;
|
|
97
64
|
|
|
98
|
-
const
|
|
99
|
-
const options = await this.state.getCompilerOptions();
|
|
100
|
-
const host = this.state.getCompilerHost(options);
|
|
101
|
-
|
|
102
|
-
const emit = async (file: string, needsNewProgram = program === undefined): Promise<EmitError | undefined> => {
|
|
65
|
+
const emit = async (inputFile: string, needsNewProgram = program === undefined): Promise<CompileEmitError | undefined> => {
|
|
103
66
|
try {
|
|
104
67
|
if (needsNewProgram) {
|
|
105
|
-
program =
|
|
106
|
-
transformers.init(program.getTypeChecker());
|
|
68
|
+
program = this.#state.createProgram(program);
|
|
107
69
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
host.writeFile(file, ts.transpile(host.readFile(file)!, options), false);
|
|
112
|
-
} else {
|
|
113
|
-
const result = program.emit(
|
|
114
|
-
program.getSourceFile(file)!, host.writeFile, undefined, false, transformers.get()
|
|
115
|
-
);
|
|
116
|
-
|
|
117
|
-
if (result.diagnostics?.length) {
|
|
118
|
-
return result.diagnostics;
|
|
119
|
-
}
|
|
70
|
+
const result = this.#state.writeInputFile(program, inputFile);
|
|
71
|
+
if (result?.diagnostics?.length) {
|
|
72
|
+
return result.diagnostics;
|
|
120
73
|
}
|
|
121
74
|
} catch (err) {
|
|
122
75
|
if (err instanceof Error) {
|
|
@@ -133,28 +86,28 @@ export class Compiler {
|
|
|
133
86
|
/**
|
|
134
87
|
* Emit all files as a stream
|
|
135
88
|
*/
|
|
136
|
-
async * emit(files: string[], emitter:
|
|
89
|
+
async * emit(files: string[], emitter: CompileEmitter): AsyncIterable<CompileEmitEvent> {
|
|
137
90
|
let i = 0;
|
|
138
91
|
for (const file of files) {
|
|
139
92
|
const err = await emitter(file);
|
|
140
93
|
const imp = file.replace(/.*node_modules\//, '');
|
|
141
94
|
yield { file: imp, i: i += 1, err, total: files.length };
|
|
142
95
|
}
|
|
143
|
-
debug(`Compiled ${i} files`);
|
|
96
|
+
Log.debug(`Compiled ${i} files`);
|
|
144
97
|
}
|
|
145
98
|
|
|
146
99
|
/**
|
|
147
100
|
* Run the compiler
|
|
148
101
|
*/
|
|
149
102
|
async run(watch?: boolean): Promise<void> {
|
|
150
|
-
debug('Compilation started');
|
|
103
|
+
Log.debug('Compilation started');
|
|
151
104
|
|
|
152
105
|
const emitter = await this.getCompiler();
|
|
153
106
|
let failed = false;
|
|
154
107
|
|
|
155
|
-
debug('Compiler loaded');
|
|
108
|
+
Log.debug('Compiler loaded');
|
|
156
109
|
|
|
157
|
-
const resolveEmittedFile = ({ file, total, i, err }:
|
|
110
|
+
const resolveEmittedFile = ({ file, total, i, err }: CompileEmitEvent): TerminalProgressEvent => {
|
|
158
111
|
if (err) {
|
|
159
112
|
failed = true;
|
|
160
113
|
console.error(CompilerUtil.buildTranspileError(file, err));
|
|
@@ -165,21 +118,29 @@ export class Compiler {
|
|
|
165
118
|
if (this.#dirtyFiles.length) {
|
|
166
119
|
await GlobalTerminal.trackProgress(this.emit(this.#dirtyFiles, emitter), resolveEmittedFile, { position: 'bottom' });
|
|
167
120
|
if (failed) {
|
|
168
|
-
debug('Compilation failed');
|
|
121
|
+
Log.debug('Compilation failed');
|
|
169
122
|
process.exit(1);
|
|
170
123
|
} else {
|
|
171
|
-
debug('Compilation succeeded');
|
|
124
|
+
Log.debug('Compilation succeeded');
|
|
172
125
|
}
|
|
126
|
+
} else if (watch) {
|
|
127
|
+
// Prime compiler before complete
|
|
128
|
+
const resolved = this.#state.getArbitraryInputFile();
|
|
129
|
+
await emitter(resolved, true);
|
|
173
130
|
}
|
|
174
131
|
|
|
132
|
+
process.send?.('build-complete');
|
|
133
|
+
|
|
175
134
|
if (watch) {
|
|
176
|
-
|
|
177
|
-
const resolved = this.state.resolveInput(RootIndex.getModule('@travetto/manifest')!.files.src[0].sourceFile);
|
|
178
|
-
await emitter(resolved, true);
|
|
179
|
-
}
|
|
180
|
-
info('Watch is ready');
|
|
135
|
+
Log.info('Watch is ready');
|
|
181
136
|
await this.#watchLocalModules(emitter);
|
|
182
|
-
await
|
|
137
|
+
for await (const _ of timers.setInterval(PING_THRESHOLD)) {
|
|
138
|
+
if (!await fs.stat(this.#state.resolveOutputFile('.')).catch(() => false)) { // Output removed
|
|
139
|
+
process.send?.('restart');
|
|
140
|
+
} else {
|
|
141
|
+
process.send?.('ping');
|
|
142
|
+
}
|
|
143
|
+
}
|
|
183
144
|
}
|
|
184
145
|
}
|
|
185
146
|
}
|
package/src/log.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import util from 'util';
|
|
2
|
+
|
|
3
|
+
import type { CompilerLogEvent } from '../support/log';
|
|
4
|
+
|
|
5
|
+
function log(level: 'info' | 'debug', message: string, ...args: unknown[]): void {
|
|
6
|
+
if (process.send) {
|
|
7
|
+
const ev: CompilerLogEvent = [level, util.format(message, ...args)];
|
|
8
|
+
process.send(ev);
|
|
9
|
+
} else {
|
|
10
|
+
// eslint-disable-next-line no-console
|
|
11
|
+
console[level](message, ...args);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const Log = {
|
|
16
|
+
debug: log.bind(null, 'debug'),
|
|
17
|
+
info: log.bind(null, 'info')
|
|
18
|
+
};
|