@travetto/compiler 7.0.0-rc.1 → 7.0.0-rc.2
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/bin/entry.common.js +26 -26
- package/bin/gen.context.mjs +6 -6
- package/bin/trvc.js +16 -16
- package/package.json +4 -4
- package/src/compiler.ts +41 -40
- package/src/state.ts +16 -16
- package/src/types.ts +1 -1
- package/src/util.ts +4 -4
- package/src/watch.ts +43 -43
- package/support/entry.main.ts +12 -12
- package/support/log.ts +30 -28
- package/support/queue.ts +5 -13
- package/support/server/client.ts +33 -33
- package/support/server/process-handle.ts +19 -19
- package/support/server/runner.ts +9 -8
- package/support/server/server.ts +46 -46
- package/support/setup.ts +33 -28
- package/support/types.ts +2 -2
- package/support/util.ts +5 -5
package/bin/entry.common.js
CHANGED
|
@@ -4,17 +4,17 @@ const { stat, readFile, writeFile, mkdir, rm, readdir } = require('node:fs/promi
|
|
|
4
4
|
const path = require('node:path');
|
|
5
5
|
|
|
6
6
|
const COMP_MOD = '@travetto/compiler';
|
|
7
|
-
const
|
|
8
|
-
const
|
|
7
|
+
const SOURCE_EXT_REGEX = /[.][cm]?[tj]sx?$/;
|
|
8
|
+
const BARE_IMPORT_REGEX = /^(@[^/]+[/])?[^.][^@/]+$/;
|
|
9
9
|
const OUTPUT_EXT = '.js';
|
|
10
10
|
|
|
11
|
-
async function writeIfStale(
|
|
12
|
-
const [srcStat, destStat] = await Promise.all([
|
|
11
|
+
async function writeIfStale(sourceFile = '', destinationFile = '', transform = async (text = '') => text) {
|
|
12
|
+
const [srcStat, destStat] = await Promise.all([sourceFile, destinationFile].map(file => stat(`${file}`).then(stats => stats.mtimeMs, () => 0)));
|
|
13
13
|
|
|
14
14
|
if (!destStat || destStat < srcStat) {
|
|
15
|
-
const text =
|
|
16
|
-
await mkdir(path.dirname(
|
|
17
|
-
await writeFile(
|
|
15
|
+
const text = sourceFile ? await readFile(sourceFile, 'utf8') : '';
|
|
16
|
+
await mkdir(path.dirname(destinationFile), { recursive: true });
|
|
17
|
+
await writeFile(destinationFile, await transform(text), 'utf8');
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
@@ -32,35 +32,35 @@ async function transpile(content = '', esm = true, full = true) {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
async function getContext() {
|
|
35
|
-
const
|
|
35
|
+
const ctxFile = require.resolve('@travetto/manifest/src/context.ts');
|
|
36
36
|
const ctxDest = path.resolve(__dirname, 'gen.context.mjs');
|
|
37
|
-
await writeIfStale(
|
|
38
|
-
const ctx = await import(ctxDest).then((/** @type {import('@travetto/manifest')} */
|
|
37
|
+
await writeIfStale(ctxFile, ctxDest, content => transpile(content, true, false));
|
|
38
|
+
const ctx = await import(ctxDest).then((/** @type {import('@travetto/manifest')} */ value) => value.getManifestContext());
|
|
39
39
|
|
|
40
40
|
const srcPath = path.resolve.bind(path, ctx.workspace.path, ctx.build.compilerModuleFolder);
|
|
41
41
|
const destPath = (file = '') =>
|
|
42
|
-
path.resolve(ctx.workspace.path, ctx.build.compilerFolder, 'node_modules', file).replace(
|
|
42
|
+
path.resolve(ctx.workspace.path, ctx.build.compilerFolder, 'node_modules', file).replace(SOURCE_EXT_REGEX, OUTPUT_EXT);
|
|
43
43
|
|
|
44
44
|
return {
|
|
45
45
|
packageType: ctx.workspace.type,
|
|
46
46
|
srcPath,
|
|
47
47
|
destPath,
|
|
48
48
|
tsconfig: path.resolve(ctx.workspace.path, 'tsconfig.json'),
|
|
49
|
-
cleanImports: (
|
|
50
|
-
.replace(/from ['"]((@travetto|[.]+)[^'"]+)['"]/g, (_,
|
|
51
|
-
const
|
|
52
|
-
const
|
|
53
|
-
return `from '${
|
|
49
|
+
cleanImports: (text = '') => text
|
|
50
|
+
.replace(/from ['"]((@travetto|[.]+)[^'"]+)['"]/g, (_, location, module) => {
|
|
51
|
+
const root = (module === '@travetto' ? destPath(location) : location).replace(SOURCE_EXT_REGEX, OUTPUT_EXT);
|
|
52
|
+
const suffix = root.endsWith(OUTPUT_EXT) ? '' : (BARE_IMPORT_REGEX.test(location) ? `/__index__${OUTPUT_EXT}` : OUTPUT_EXT);
|
|
53
|
+
return `from '${root}${suffix}'`;
|
|
54
54
|
}),
|
|
55
55
|
loadMain: () => import(destPath(`${COMP_MOD}/support/entry.main.ts`))
|
|
56
|
-
.then((/** @type {import('../support/entry.main.ts')} */
|
|
56
|
+
.then((/** @type {import('../support/entry.main.ts')} */ value) => value.main(ctx)),
|
|
57
57
|
supportFiles: () => readdir(srcPath('support'), { recursive: true, encoding: 'utf8' })
|
|
58
|
-
.then(
|
|
58
|
+
.then(files => files.filter(file => file.endsWith('.ts')).map(file => `support/${file}`))
|
|
59
59
|
};
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
/** @template T */
|
|
63
|
-
async function load(/** @type {(
|
|
63
|
+
async function load(/** @type {(operations: import('../support/entry.main.ts').Operations) => T} */ callback) {
|
|
64
64
|
const ctx = await getContext();
|
|
65
65
|
|
|
66
66
|
try {
|
|
@@ -70,19 +70,19 @@ async function load(/** @type {(ops: import('../support/entry.main.ts').Operatio
|
|
|
70
70
|
await writeIfStale(ctx.srcPath('package.json'), ctx.destPath(`${COMP_MOD}/package.json`),
|
|
71
71
|
async text => JSON.stringify({ ...JSON.parse(text || '{}'), type: ctx.packageType }, null, 2));
|
|
72
72
|
|
|
73
|
-
await Promise.all((await ctx.supportFiles()).map(
|
|
74
|
-
writeIfStale(ctx.srcPath(
|
|
75
|
-
|
|
73
|
+
await Promise.all((await ctx.supportFiles()).map(file =>
|
|
74
|
+
writeIfStale(ctx.srcPath(file), ctx.destPath(`${COMP_MOD}/${file}`),
|
|
75
|
+
text => transpile(ctx.cleanImports(text), ctx.packageType === 'module'))));
|
|
76
76
|
|
|
77
77
|
process.setSourceMapsEnabled(true); // Ensure source map during compilation/development
|
|
78
78
|
process.env.NODE_OPTIONS = `${process.env.NODE_OPTIONS ?? ''} --enable-source-maps`; // Ensure it passes to children
|
|
79
|
-
const
|
|
79
|
+
const result = await ctx.loadMain();
|
|
80
80
|
// @ts-ignore
|
|
81
81
|
try { module.enableCompileCache(); } catch { }
|
|
82
|
-
return
|
|
83
|
-
} catch (
|
|
82
|
+
return callback(result);
|
|
83
|
+
} catch (error) {
|
|
84
84
|
await rm(ctx.destPath(COMP_MOD), { recursive: true, force: true });
|
|
85
|
-
throw
|
|
85
|
+
throw error;
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
|
package/bin/gen.context.mjs
CHANGED
|
@@ -2,22 +2,22 @@ import { existsSync, readFileSync } from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { createRequire } from 'node:module';
|
|
4
4
|
// eslint-disable-next-line no-bitwise
|
|
5
|
-
const toPort = (
|
|
6
|
-
const toPosix = (
|
|
5
|
+
const toPort = (location) => (Math.abs([...location].reduce((a, b) => (a * 33) ^ b.charCodeAt(0), 5381)) % 29000) + 20000;
|
|
6
|
+
const toPosix = (location) => location.replaceAll('\\', '/');
|
|
7
7
|
const readPackage = (file) => ({ ...JSON.parse(readFileSync(file, 'utf8')), path: toPosix(path.dirname(file)) });
|
|
8
8
|
/** Find package */
|
|
9
9
|
function findPackage(base, pred) {
|
|
10
10
|
let folder = `${base}/.`;
|
|
11
|
-
let
|
|
11
|
+
let previous;
|
|
12
12
|
let pkg;
|
|
13
13
|
const packages = [];
|
|
14
14
|
do {
|
|
15
15
|
pkg && packages.push(pkg);
|
|
16
|
-
|
|
16
|
+
previous = folder;
|
|
17
17
|
folder = path.dirname(folder);
|
|
18
18
|
const folderPkg = path.resolve(folder, 'package.json');
|
|
19
19
|
pkg = existsSync(folderPkg) ? readPackage(folderPkg) : pkg;
|
|
20
|
-
} while (
|
|
20
|
+
} while (previous !== folder && // Not at root
|
|
21
21
|
!pred(pkg) && // Matches criteria
|
|
22
22
|
!existsSync(path.resolve(folder, '.git')) // Not at source root
|
|
23
23
|
);
|
|
@@ -66,4 +66,4 @@ export function getManifestContext(root = process.cwd()) {
|
|
|
66
66
|
}
|
|
67
67
|
};
|
|
68
68
|
}
|
|
69
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
69
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kdWxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsibW9kdWxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ25ELE9BQU8sSUFBSSxNQUFNLFdBQVcsQ0FBQztBQUM3QixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBTzVDLHNDQUFzQztBQUN0QyxNQUFNLE1BQU0sR0FBRyxDQUFDLFFBQWdCLEVBQVUsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsUUFBUSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQyxHQUFHLEtBQUssQ0FBQztBQUMxSSxNQUFNLE9BQU8sR0FBRyxDQUFDLFFBQWdCLEVBQVUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBQzdFLE1BQU0sV0FBVyxHQUFHLENBQUMsSUFBWSxFQUFPLEVBQUUsQ0FBQyxDQUFDLEVBQUUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7QUFFOUgsbUJBQW1CO0FBQ25CLFNBQVMsV0FBVyxDQUFDLElBQVksRUFBRSxJQUEyQjtJQUM1RCxJQUFJLE1BQU0sR0FBRyxHQUFHLElBQUksSUFBSSxDQUFDO0lBQ3pCLElBQUksUUFBZ0IsQ0FBQztJQUNyQixJQUFJLEdBQW9CLENBQUM7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
|
package/bin/trvc.js
CHANGED
|
@@ -14,26 +14,26 @@ Available Commands:
|
|
|
14
14
|
* manifest --prod [output] - Generate the project manifest
|
|
15
15
|
`;
|
|
16
16
|
|
|
17
|
-
const toJson = (/** @type {number} */ depth) =>
|
|
18
|
-
new Promise(
|
|
17
|
+
const toJson = (/** @type {number} */ depth) => value => process.stdout.write(`${JSON.stringify(value, undefined, depth)}\n`) ||
|
|
18
|
+
new Promise(resolve => process.stdout.once('drain', resolve));
|
|
19
19
|
|
|
20
|
-
require('./entry.common.js').load(
|
|
21
|
-
const [
|
|
22
|
-
const args = all.filter(
|
|
20
|
+
require('./entry.common.js').load(operations => {
|
|
21
|
+
const [operation, ...all] = process.argv.slice(2);
|
|
22
|
+
const args = all.filter(arg => !arg.startsWith('-'));
|
|
23
23
|
|
|
24
|
-
switch (
|
|
24
|
+
switch (operation) {
|
|
25
25
|
case undefined:
|
|
26
26
|
case 'help': return console.log(help);
|
|
27
|
-
case 'info': return
|
|
28
|
-
case 'event': return
|
|
29
|
-
case 'manifest': return
|
|
30
|
-
case 'exec': return
|
|
31
|
-
case 'build': return
|
|
32
|
-
case 'clean': return
|
|
27
|
+
case 'info': return operations.info().then(toJson(2));
|
|
28
|
+
case 'event': return operations.events(args[0], toJson(0));
|
|
29
|
+
case 'manifest': return operations.manifest(args[0], all.some(arg => arg === '--prod'));
|
|
30
|
+
case 'exec': return operations.exec(args[0], all.slice(1));
|
|
31
|
+
case 'build': return operations.build();
|
|
32
|
+
case 'clean': return operations.clean();
|
|
33
33
|
case 'start':
|
|
34
|
-
case 'watch': return
|
|
35
|
-
case 'stop': return
|
|
36
|
-
case 'restart': return
|
|
37
|
-
default: console.error(`\nUnknown trvc operation: ${
|
|
34
|
+
case 'watch': return operations.watch();
|
|
35
|
+
case 'stop': return operations.stop();
|
|
36
|
+
case 'restart': return operations.restart();
|
|
37
|
+
default: console.error(`\nUnknown trvc operation: ${operation}\n${help}`);
|
|
38
38
|
}
|
|
39
39
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/compiler",
|
|
3
|
-
"version": "7.0.0-rc.
|
|
3
|
+
"version": "7.0.0-rc.2",
|
|
4
4
|
"description": "The compiler infrastructure for the Travetto framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"compiler",
|
|
@@ -30,11 +30,11 @@
|
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@parcel/watcher": "^2.5.1",
|
|
33
|
-
"@travetto/manifest": "^7.0.0-rc.
|
|
34
|
-
"@travetto/transformer": "^7.0.0-rc.
|
|
33
|
+
"@travetto/manifest": "^7.0.0-rc.1",
|
|
34
|
+
"@travetto/transformer": "^7.0.0-rc.2"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
|
-
"@travetto/cli": "^7.0.0-rc.
|
|
37
|
+
"@travetto/cli": "^7.0.0-rc.2"
|
|
38
38
|
},
|
|
39
39
|
"peerDependenciesMeta": {
|
|
40
40
|
"@travetto/cli": {
|
package/src/compiler.ts
CHANGED
|
@@ -26,7 +26,8 @@ export class Compiler {
|
|
|
26
26
|
const [dirty, watch] = process.argv.slice(2);
|
|
27
27
|
const state = await CompilerState.get(new ManifestIndex());
|
|
28
28
|
log.debug('Running compiler with dirty file', dirty);
|
|
29
|
-
const dirtyFiles = ManifestModuleUtil.getFileType(dirty) === 'ts' ? [dirty] :
|
|
29
|
+
const dirtyFiles = ManifestModuleUtil.getFileType(dirty) === 'ts' ? [dirty] :
|
|
30
|
+
(await fs.readFile(dirty, 'utf8')).split(/\n/).filter(line => !!line);
|
|
30
31
|
log.debug('Running compiler with dirty file', dirtyFiles);
|
|
31
32
|
await new Compiler(state, dirtyFiles, watch === 'true').run();
|
|
32
33
|
}
|
|
@@ -34,7 +35,7 @@ export class Compiler {
|
|
|
34
35
|
#state: CompilerState;
|
|
35
36
|
#dirtyFiles: string[];
|
|
36
37
|
#watch?: boolean;
|
|
37
|
-
#
|
|
38
|
+
#controller: AbortController;
|
|
38
39
|
#signal: AbortSignal;
|
|
39
40
|
#shuttingDown = false;
|
|
40
41
|
|
|
@@ -42,18 +43,18 @@ export class Compiler {
|
|
|
42
43
|
this.#state = state;
|
|
43
44
|
this.#dirtyFiles = dirtyFiles[0] === '*' ?
|
|
44
45
|
this.#state.getAllFiles() :
|
|
45
|
-
dirtyFiles.map(
|
|
46
|
+
dirtyFiles.map(file => this.#state.getBySource(file)!.sourceFile);
|
|
46
47
|
this.#watch = watch;
|
|
47
48
|
|
|
48
|
-
this.#
|
|
49
|
-
this.#signal = this.#
|
|
49
|
+
this.#controller = new AbortController();
|
|
50
|
+
this.#signal = this.#controller.signal;
|
|
50
51
|
setMaxListeners(1000, this.#signal);
|
|
51
52
|
process
|
|
52
53
|
.once('disconnect', () => this.#shutdown('manual'))
|
|
53
|
-
.on('message',
|
|
54
|
+
.on('message', event => (event === 'shutdown') && this.#shutdown('manual'));
|
|
54
55
|
}
|
|
55
56
|
|
|
56
|
-
#shutdown(mode: 'error' | 'manual' | 'complete' | 'reset',
|
|
57
|
+
#shutdown(mode: 'error' | 'manual' | 'complete' | 'reset', error?: Error): void {
|
|
57
58
|
if (this.#shuttingDown) {
|
|
58
59
|
return;
|
|
59
60
|
}
|
|
@@ -67,14 +68,14 @@ export class Compiler {
|
|
|
67
68
|
}
|
|
68
69
|
case 'error': {
|
|
69
70
|
process.exitCode = 1;
|
|
70
|
-
if (
|
|
71
|
-
EventUtil.sendEvent('log', { level: 'error', message:
|
|
72
|
-
log.error('Shutting down due to failure',
|
|
71
|
+
if (error) {
|
|
72
|
+
EventUtil.sendEvent('log', { level: 'error', message: error.toString(), time: Date.now() });
|
|
73
|
+
log.error('Shutting down due to failure', error.stack);
|
|
73
74
|
}
|
|
74
75
|
break;
|
|
75
76
|
}
|
|
76
77
|
case 'reset': {
|
|
77
|
-
log.info('Reset due to',
|
|
78
|
+
log.info('Reset due to', error?.message);
|
|
78
79
|
EventUtil.sendEvent('state', { state: 'reset' });
|
|
79
80
|
process.exitCode = 0;
|
|
80
81
|
break;
|
|
@@ -83,7 +84,7 @@ export class Compiler {
|
|
|
83
84
|
// No longer listen to disconnect
|
|
84
85
|
process.removeAllListeners('disconnect');
|
|
85
86
|
process.removeAllListeners('message');
|
|
86
|
-
this.#
|
|
87
|
+
this.#controller.abort();
|
|
87
88
|
CommonUtil.nonBlockingTimeout(1000).then(() => process.exit()); // Allow upto 1s to shutdown gracefully
|
|
88
89
|
}
|
|
89
90
|
|
|
@@ -92,7 +93,7 @@ export class Compiler {
|
|
|
92
93
|
*/
|
|
93
94
|
logStatistics(metrics: CompileEmitEvent[]): void {
|
|
94
95
|
// Simple metrics
|
|
95
|
-
const durations = metrics.map(
|
|
96
|
+
const durations = metrics.map(event => event.duration);
|
|
96
97
|
const total = durations.reduce((a, b) => a + b, 0);
|
|
97
98
|
const avg = total / durations.length;
|
|
98
99
|
const sorted = [...durations].sort((a, b) => a - b);
|
|
@@ -102,7 +103,7 @@ export class Compiler {
|
|
|
102
103
|
const slowest = [...metrics]
|
|
103
104
|
.sort((a, b) => b.duration - a.duration)
|
|
104
105
|
.slice(0, 5)
|
|
105
|
-
.map(
|
|
106
|
+
.map(event => ({ file: event.file, duration: event.duration }));
|
|
106
107
|
|
|
107
108
|
log.debug('Compilation Statistics', {
|
|
108
109
|
files: metrics.length,
|
|
@@ -131,12 +132,12 @@ export class Compiler {
|
|
|
131
132
|
|
|
132
133
|
for (const file of files) {
|
|
133
134
|
const start = Date.now();
|
|
134
|
-
const
|
|
135
|
+
const error = await emitter(file);
|
|
135
136
|
const duration = Date.now() - start;
|
|
136
|
-
const
|
|
137
|
-
const nodeModIdx = file.lastIndexOf(
|
|
138
|
-
const imp = nodeModIdx >= 0 ? file.substring(nodeModIdx +
|
|
139
|
-
yield { file: imp, i: i += 1,
|
|
137
|
+
const nodeModSeparator = 'node_modules/';
|
|
138
|
+
const nodeModIdx = file.lastIndexOf(nodeModSeparator);
|
|
139
|
+
const imp = nodeModIdx >= 0 ? file.substring(nodeModIdx + nodeModSeparator.length) : file;
|
|
140
|
+
yield { file: imp, i: i += 1, error, total: files.length, duration };
|
|
140
141
|
if ((Date.now() - lastSent) > 50) { // Limit to 1 every 50ms
|
|
141
142
|
lastSent = Date.now();
|
|
142
143
|
EventUtil.sendEvent('progress', { total: files.length, idx: i, message: imp, operation: 'compile' });
|
|
@@ -158,7 +159,7 @@ export class Compiler {
|
|
|
158
159
|
async run(): Promise<void> {
|
|
159
160
|
log.debug('Compilation started');
|
|
160
161
|
|
|
161
|
-
EventUtil.sendEvent('state', { state: 'init', extra: {
|
|
162
|
+
EventUtil.sendEvent('state', { state: 'init', extra: { processId: process.pid } });
|
|
162
163
|
|
|
163
164
|
const emitter = await this.getCompiler();
|
|
164
165
|
let failure: Error | undefined;
|
|
@@ -170,13 +171,13 @@ export class Compiler {
|
|
|
170
171
|
const metrics: CompileEmitEvent[] = [];
|
|
171
172
|
|
|
172
173
|
if (this.#dirtyFiles.length) {
|
|
173
|
-
for await (const
|
|
174
|
-
if (
|
|
175
|
-
const compileError = CompilerUtil.buildTranspileError(
|
|
174
|
+
for await (const event of this.emit(this.#dirtyFiles, emitter)) {
|
|
175
|
+
if (event.error) {
|
|
176
|
+
const compileError = CompilerUtil.buildTranspileError(event.file, event.error);
|
|
176
177
|
failure ??= compileError;
|
|
177
178
|
EventUtil.sendEvent('log', { level: 'error', message: compileError.toString(), time: Date.now() });
|
|
178
179
|
}
|
|
179
|
-
metrics.push(
|
|
180
|
+
metrics.push(event);
|
|
180
181
|
}
|
|
181
182
|
if (this.#signal.aborted) {
|
|
182
183
|
log.debug('Compilation aborted');
|
|
@@ -203,35 +204,35 @@ export class Compiler {
|
|
|
203
204
|
|
|
204
205
|
EventUtil.sendEvent('state', { state: 'watch-start' });
|
|
205
206
|
try {
|
|
206
|
-
for await (const
|
|
207
|
-
if (
|
|
208
|
-
const
|
|
209
|
-
if (
|
|
210
|
-
log.info('Compilation Error', CompilerUtil.buildTranspileError(
|
|
207
|
+
for await (const event of new CompilerWatcher(this.#state, this.#signal)) {
|
|
208
|
+
if (event.action !== 'delete') {
|
|
209
|
+
const error = await emitter(event.entry.sourceFile, true);
|
|
210
|
+
if (error) {
|
|
211
|
+
log.info('Compilation Error', CompilerUtil.buildTranspileError(event.entry.sourceFile, error));
|
|
211
212
|
} else {
|
|
212
|
-
log.info(`Compiled ${
|
|
213
|
+
log.info(`Compiled ${event.entry.sourceFile} on ${event.action}`);
|
|
213
214
|
}
|
|
214
215
|
} else {
|
|
215
|
-
if (
|
|
216
|
+
if (event.entry.outputFile) {
|
|
216
217
|
// Remove output
|
|
217
|
-
log.info(`Removed ${
|
|
218
|
-
await fs.rm(
|
|
218
|
+
log.info(`Removed ${event.entry.sourceFile}, ${event.entry.outputFile}`);
|
|
219
|
+
await fs.rm(event.entry.outputFile, { force: true }); // Ensure output is deleted
|
|
219
220
|
}
|
|
220
221
|
}
|
|
221
222
|
|
|
222
223
|
// Send change events
|
|
223
224
|
EventUtil.sendEvent('change', {
|
|
224
|
-
action:
|
|
225
|
+
action: event.action,
|
|
225
226
|
time: Date.now(),
|
|
226
|
-
file:
|
|
227
|
-
output:
|
|
228
|
-
module:
|
|
227
|
+
file: event.file,
|
|
228
|
+
output: event.entry.outputFile!,
|
|
229
|
+
module: event.entry.module.name
|
|
229
230
|
});
|
|
230
231
|
}
|
|
231
232
|
EventUtil.sendEvent('state', { state: 'watch-end' });
|
|
232
|
-
} catch (
|
|
233
|
-
if (
|
|
234
|
-
this.#shutdown(
|
|
233
|
+
} catch (error) {
|
|
234
|
+
if (error instanceof Error) {
|
|
235
|
+
this.#shutdown(error instanceof CompilerReset ? 'reset' : 'error', error);
|
|
235
236
|
}
|
|
236
237
|
}
|
|
237
238
|
}
|
package/src/state.ts
CHANGED
|
@@ -46,7 +46,7 @@ export class CompilerState implements ts.CompilerHost {
|
|
|
46
46
|
#writeExternalTypings(location: string, text: string, bom: boolean): void {
|
|
47
47
|
let core = location.replace('.map', '');
|
|
48
48
|
if (!this.#outputToEntry.has(core)) {
|
|
49
|
-
core = core.replace(ManifestModuleUtil.
|
|
49
|
+
core = core.replace(ManifestModuleUtil.TYPINGS_EXT_REGEX, ManifestModuleUtil.OUTPUT_EXT);
|
|
50
50
|
}
|
|
51
51
|
const entry = this.#outputToEntry.get(core);
|
|
52
52
|
if (entry) {
|
|
@@ -72,8 +72,8 @@ export class CompilerState implements ts.CompilerHost {
|
|
|
72
72
|
this.#modules = Object.values(this.#manifest.modules);
|
|
73
73
|
|
|
74
74
|
// Register all inputs
|
|
75
|
-
for (const
|
|
76
|
-
const base =
|
|
75
|
+
for (const mod of this.#modules) {
|
|
76
|
+
const base = mod?.files ?? {};
|
|
77
77
|
const files = [
|
|
78
78
|
...base.bin ?? [],
|
|
79
79
|
...base.src ?? [],
|
|
@@ -85,7 +85,7 @@ export class CompilerState implements ts.CompilerHost {
|
|
|
85
85
|
];
|
|
86
86
|
for (const [file, type] of files) {
|
|
87
87
|
if (CompilerUtil.validFile(type)) {
|
|
88
|
-
this.registerInput(
|
|
88
|
+
this.registerInput(mod, file);
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
}
|
|
@@ -109,7 +109,7 @@ export class CompilerState implements ts.CompilerHost {
|
|
|
109
109
|
|
|
110
110
|
getArbitraryInputFile(): string {
|
|
111
111
|
const randomSource = this.#manifestIndex.getWorkspaceModules()
|
|
112
|
-
.filter(
|
|
112
|
+
.filter(mod => mod.files.src?.length)[0]
|
|
113
113
|
.files.src[0].sourceFile;
|
|
114
114
|
|
|
115
115
|
return this.getBySource(randomSource)!.sourceFile;
|
|
@@ -149,11 +149,11 @@ export class CompilerState implements ts.CompilerHost {
|
|
|
149
149
|
return result?.diagnostics?.length ? result.diagnostics : undefined;
|
|
150
150
|
}
|
|
151
151
|
}
|
|
152
|
-
} catch (
|
|
153
|
-
if (
|
|
154
|
-
return
|
|
152
|
+
} catch (error) {
|
|
153
|
+
if (error instanceof Error) {
|
|
154
|
+
return error;
|
|
155
155
|
} else {
|
|
156
|
-
throw
|
|
156
|
+
throw error;
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
159
|
}
|
|
@@ -235,7 +235,7 @@ export class CompilerState implements ts.CompilerHost {
|
|
|
235
235
|
/* Start Compiler Host */
|
|
236
236
|
getCanonicalFileName(file: string): string { return file; }
|
|
237
237
|
getCurrentDirectory(): string { return this.#manifest.workspace.path; }
|
|
238
|
-
getDefaultLibFileName(
|
|
238
|
+
getDefaultLibFileName(options: ts.CompilerOptions): string { return ts.getDefaultLibFileName(options); }
|
|
239
239
|
getNewLine(): string { return ts.sys.newLine; }
|
|
240
240
|
useCaseSensitiveFileNames(): boolean { return ts.sys.useCaseSensitiveFileNames; }
|
|
241
241
|
getDefaultLibLocation(): string { return path.dirname(ts.getDefaultLibFilePath(this.#compilerOptions)); }
|
|
@@ -244,8 +244,8 @@ export class CompilerState implements ts.CompilerHost {
|
|
|
244
244
|
return this.#sourceToEntry.has(sourceFile) || ts.sys.fileExists(sourceFile);
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
-
directoryExists(
|
|
248
|
-
return this.#sourceDirectory.has(
|
|
247
|
+
directoryExists(sourceDirectory: string): boolean {
|
|
248
|
+
return this.#sourceDirectory.has(sourceDirectory) || ts.sys.directoryExists(sourceDirectory);
|
|
249
249
|
}
|
|
250
250
|
|
|
251
251
|
writeFile(
|
|
@@ -258,7 +258,7 @@ export class CompilerState implements ts.CompilerHost {
|
|
|
258
258
|
}
|
|
259
259
|
const location = this.#tscOutputFileToOuptut.get(outputFile) ?? outputFile;
|
|
260
260
|
|
|
261
|
-
if (ManifestModuleUtil.
|
|
261
|
+
if (ManifestModuleUtil.TYPINGS_WITH_MAP_EXT_REGEX.test(outputFile) || outputFile.endsWith('package.json')) {
|
|
262
262
|
this.#writeExternalTypings(location, text, bom);
|
|
263
263
|
}
|
|
264
264
|
|
|
@@ -266,9 +266,9 @@ export class CompilerState implements ts.CompilerHost {
|
|
|
266
266
|
}
|
|
267
267
|
|
|
268
268
|
readFile(sourceFile: string): string | undefined {
|
|
269
|
-
const
|
|
270
|
-
this.#sourceContents.set(sourceFile,
|
|
271
|
-
return
|
|
269
|
+
const contents = this.#sourceContents.get(sourceFile) ?? this.#readFile(sourceFile);
|
|
270
|
+
this.#sourceContents.set(sourceFile, contents);
|
|
271
|
+
return contents;
|
|
272
272
|
}
|
|
273
273
|
|
|
274
274
|
getSourceFile(sourceFile: string, language: ts.ScriptTarget): ts.SourceFile {
|
package/src/types.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type { ManifestModule } from '@travetto/manifest';
|
|
|
4
4
|
|
|
5
5
|
export type CompileEmitError = Error | readonly ts.Diagnostic[];
|
|
6
6
|
export type CompileEmitter = (file: string, newProgram?: boolean) => Promise<CompileEmitError | undefined>;
|
|
7
|
-
export type CompileEmitEvent = { file: string, i: number, total: number,
|
|
7
|
+
export type CompileEmitEvent = { file: string, i: number, total: number, error?: CompileEmitError, duration: number };
|
|
8
8
|
export type CompileStateEntry = { sourceFile: string, tscOutputFile: string, outputFile?: string, module: ManifestModule };
|
|
9
9
|
export type CompilerWatchEvent = { action: 'create' | 'update' | 'delete', file: string, entry: CompileStateEntry };
|
|
10
10
|
export class CompilerReset extends Error { }
|
package/src/util.ts
CHANGED
|
@@ -24,7 +24,7 @@ export class CompilerUtil {
|
|
|
24
24
|
static rewritePackageJSON(manifest: ManifestRoot, text: string): string {
|
|
25
25
|
const pkg: Package = JSON.parse(text);
|
|
26
26
|
if (pkg.files) {
|
|
27
|
-
pkg.files = pkg.files.map(
|
|
27
|
+
pkg.files = pkg.files.map(file => ManifestModuleUtil.withOutputExtension(file));
|
|
28
28
|
}
|
|
29
29
|
if (pkg.main) {
|
|
30
30
|
pkg.main = ManifestModuleUtil.withOutputExtension(pkg.main);
|
|
@@ -32,9 +32,9 @@ export class CompilerUtil {
|
|
|
32
32
|
pkg.type = manifest.workspace.type;
|
|
33
33
|
for (const key of ['devDependencies', 'dependencies', 'peerDependencies'] as const) {
|
|
34
34
|
if (key in pkg) {
|
|
35
|
-
for (const
|
|
36
|
-
if (
|
|
37
|
-
pkg[key]![
|
|
35
|
+
for (const dependency of Object.keys(pkg[key] ?? {})) {
|
|
36
|
+
if (dependency in manifest.modules) {
|
|
37
|
+
pkg[key]![dependency] = manifest.modules[dependency].version;
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
}
|