@travetto/compiler 3.4.2 → 4.0.0-rc.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 +31 -29
- package/bin/common.js +37 -45
- package/bin/trvc.js +19 -11
- package/package.json +5 -6
- package/src/compiler.ts +37 -15
- package/src/event.ts +3 -3
- package/src/internal/watch-core.ts +23 -20
- package/src/log.ts +1 -1
- package/src/state.ts +4 -4
- package/src/util.ts +2 -2
- package/src/watch.ts +17 -30
- package/support/entry.trvc.ts +31 -26
- package/support/log.ts +56 -23
- package/support/queue.ts +5 -6
- package/support/server/client.ts +86 -73
- package/support/server/runner.ts +27 -59
- package/support/server/server.ts +40 -29
- package/support/setup.ts +38 -36
- package/support/types.ts +2 -2
- package/support/util.ts +16 -23
package/support/server/runner.ts
CHANGED
|
@@ -1,41 +1,26 @@
|
|
|
1
|
-
import cp from 'child_process';
|
|
2
|
-
import path from 'path';
|
|
1
|
+
import cp from 'node:child_process';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { rmSync } from 'node:fs';
|
|
3
4
|
|
|
4
|
-
import type { ManifestContext,
|
|
5
|
+
import type { ManifestContext, DeltaEvent } from '@travetto/manifest';
|
|
5
6
|
|
|
6
|
-
import type { CompilerOp,
|
|
7
|
+
import type { CompilerOp, CompilerEvent } from '../types';
|
|
7
8
|
import { AsyncQueue } from '../queue';
|
|
8
9
|
import { LogUtil } from '../log';
|
|
9
10
|
import { CommonUtil } from '../util';
|
|
10
|
-
import { CompilerClientUtil } from './client';
|
|
11
11
|
|
|
12
|
-
const log = LogUtil.
|
|
12
|
+
const log = LogUtil.scoped('compiler-exec');
|
|
13
|
+
const isEvent = (msg: unknown): msg is CompilerEvent => !!msg && typeof msg === 'object' && 'type' in msg;
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* Running the compiler
|
|
16
17
|
*/
|
|
17
18
|
export class CompilerRunner {
|
|
18
19
|
|
|
19
|
-
/**
|
|
20
|
-
* Track compiler progress
|
|
21
|
-
*/
|
|
22
|
-
static async trackProgress(ctx: ManifestContext, src: AsyncIterable<CompilerProgressEvent>): Promise<void> {
|
|
23
|
-
const compiler = path.resolve(ctx.workspacePath, ctx.compilerFolder);
|
|
24
|
-
const main = path.resolve(compiler, 'node_modules', '@travetto/terminal/__index__.js');
|
|
25
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
26
|
-
const { GlobalTerminal } = await import(main) as typeof import('@travetto/terminal');
|
|
27
|
-
|
|
28
|
-
await GlobalTerminal.init();
|
|
29
|
-
await GlobalTerminal.trackProgress(src,
|
|
30
|
-
x => ({ ...x, text: `Compiling [%idx/%total] -- ${x.message}` }),
|
|
31
|
-
{ position: 'bottom', minDelay: 50, staticMessage: 'Compiling' }
|
|
32
|
-
);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
20
|
/**
|
|
36
21
|
* Run compile process
|
|
37
22
|
*/
|
|
38
|
-
static async* runProcess(ctx: ManifestContext,
|
|
23
|
+
static async * runProcess(ctx: ManifestContext, changed: DeltaEvent[], op: CompilerOp, signal: AbortSignal): AsyncIterable<CompilerEvent> {
|
|
39
24
|
const watch = op === 'watch';
|
|
40
25
|
if (!changed.length && !watch) {
|
|
41
26
|
yield { type: 'state', payload: { state: 'compile-end' } };
|
|
@@ -45,63 +30,46 @@ export class CompilerRunner {
|
|
|
45
30
|
log('debug', `Started watch=${watch} changed=${changed.slice(0, 10).map(x => `${x.module}/${x.file}`)}`);
|
|
46
31
|
}
|
|
47
32
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
this.trackProgress(ctx, CompilerClientUtil.fetchEvents(ctx, 'progress', signal, ev => !!ev.complete));
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const compiler = path.resolve(ctx.workspacePath, ctx.compilerFolder);
|
|
54
|
-
const main = path.resolve(compiler, 'node_modules', '@travetto/compiler/support/entry.compiler.js');
|
|
55
|
-
const deltaFile = path.resolve(ctx.workspacePath, ctx.toolFolder, 'manifest-delta.json');
|
|
33
|
+
const main = path.resolve(ctx.workspace.path, ctx.build.compilerFolder, 'node_modules', '@travetto/compiler/support/entry.compiler.js');
|
|
34
|
+
const deltaFile = path.resolve(ctx.workspace.path, ctx.build.compilerFolder, `manifest-delta-${Date.now()}.json`);
|
|
56
35
|
|
|
57
|
-
const changedFiles = changed[0]?.file === '*' ? ['*'] : changed.map(ev =>
|
|
58
|
-
path.resolve(manifest.workspacePath, manifest.modules[ev.module].sourceFolder, ev.file)
|
|
59
|
-
);
|
|
36
|
+
const changedFiles = changed[0]?.file === '*' ? ['*'] : changed.map(ev => ev.sourceFile);
|
|
60
37
|
|
|
61
|
-
|
|
38
|
+
const queue = new AsyncQueue<CompilerEvent>();
|
|
62
39
|
let kill: (() => void) | undefined;
|
|
63
40
|
|
|
64
|
-
const queue = new AsyncQueue<CompilerServerEvent>(signal);
|
|
65
|
-
|
|
66
41
|
try {
|
|
67
42
|
await CommonUtil.writeTextFile(deltaFile, changedFiles.join('\n'));
|
|
68
43
|
|
|
69
44
|
log('info', 'Launching compiler');
|
|
70
|
-
proc = cp.spawn(process.argv0, [main, deltaFile, `${watch}`], {
|
|
45
|
+
const proc = cp.spawn(process.argv0, [main, deltaFile, `${watch}`], {
|
|
71
46
|
env: {
|
|
72
47
|
...process.env,
|
|
73
|
-
TRV_MANIFEST: path.resolve(ctx.
|
|
48
|
+
TRV_MANIFEST: path.resolve(ctx.workspace.path, ctx.build.outputFolder, 'node_modules', ctx.workspace.name),
|
|
74
49
|
},
|
|
75
|
-
|
|
50
|
+
detached: true,
|
|
51
|
+
stdio: ['pipe', 1, 2, 'ipc'],
|
|
76
52
|
})
|
|
77
|
-
.on('message', msg =>
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
})
|
|
83
|
-
.on('exit', code => {
|
|
84
|
-
if (code !== null && code > 0) {
|
|
85
|
-
log('error', 'Failed during compilation');
|
|
86
|
-
}
|
|
87
|
-
queue.close();
|
|
88
|
-
});
|
|
53
|
+
.on('message', msg => isEvent(msg) && queue.add(msg))
|
|
54
|
+
.on('exit', () => queue.close());
|
|
55
|
+
|
|
56
|
+
kill = (): unknown => proc.kill('SIGINT');
|
|
89
57
|
|
|
90
|
-
|
|
58
|
+
process.once('SIGINT', kill);
|
|
91
59
|
signal.addEventListener('abort', kill);
|
|
92
|
-
process.on('exit', kill);
|
|
93
60
|
|
|
94
61
|
yield* queue;
|
|
95
62
|
|
|
96
|
-
|
|
63
|
+
if (!proc.killed && proc.exitCode !== 0) {
|
|
64
|
+
log('error', `Failed during compilation, code=${proc.exitCode}, killed=${proc.killed}`);
|
|
65
|
+
}
|
|
66
|
+
|
|
97
67
|
log('debug', 'Finished');
|
|
98
68
|
} finally {
|
|
99
|
-
if (proc?.killed === false) {
|
|
100
|
-
proc.kill('SIGKILL');
|
|
101
|
-
}
|
|
102
69
|
if (kill) {
|
|
103
|
-
process.off('
|
|
70
|
+
process.off('SIGINT', kill);
|
|
104
71
|
}
|
|
72
|
+
rmSync(deltaFile, { force: true });
|
|
105
73
|
}
|
|
106
74
|
}
|
|
107
75
|
}
|
package/support/server/server.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import http from 'http';
|
|
2
|
-
import fs from 'fs/promises';
|
|
3
|
-
import path from 'path';
|
|
1
|
+
import http from 'node:http';
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
4
|
|
|
5
5
|
import type { ManifestContext } from '@travetto/manifest';
|
|
6
6
|
|
|
7
|
-
import type { CompilerMode, CompilerOp,
|
|
7
|
+
import type { CompilerMode, CompilerOp, CompilerProgressEvent, CompilerEvent, CompilerEventType, CompilerServerInfo } from '../types';
|
|
8
8
|
import { LogUtil } from '../log';
|
|
9
|
-
import {
|
|
9
|
+
import { CompilerClient } from './client';
|
|
10
10
|
import { CommonUtil } from '../util';
|
|
11
11
|
|
|
12
|
-
const log = LogUtil.
|
|
12
|
+
const log = LogUtil.scoped('compiler-server');
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Compiler Server Class
|
|
@@ -33,21 +33,25 @@ export class CompilerServer {
|
|
|
33
33
|
|
|
34
34
|
#ctx: ManifestContext;
|
|
35
35
|
#server: http.Server;
|
|
36
|
-
#listeners: { res: http.ServerResponse, type:
|
|
36
|
+
#listeners: { res: http.ServerResponse, type: CompilerEventType }[] = [];
|
|
37
37
|
#shutdown = new AbortController();
|
|
38
38
|
signal = this.#shutdown.signal;
|
|
39
39
|
info: CompilerServerInfo;
|
|
40
|
+
#client: CompilerClient;
|
|
41
|
+
#url: string;
|
|
40
42
|
|
|
41
43
|
constructor(ctx: ManifestContext, op: CompilerOp) {
|
|
42
44
|
this.#ctx = ctx;
|
|
45
|
+
this.#client = new CompilerClient(ctx, LogUtil.scoped('client.server'));
|
|
46
|
+
this.#url = this.#client.url;
|
|
43
47
|
this.info = {
|
|
44
48
|
state: 'startup',
|
|
45
49
|
iteration: Date.now(),
|
|
46
50
|
mode: op === 'run' ? 'build' : op,
|
|
47
51
|
serverPid: process.pid,
|
|
48
52
|
compilerPid: -1,
|
|
49
|
-
path: ctx.
|
|
50
|
-
url:
|
|
53
|
+
path: ctx.workspace.path,
|
|
54
|
+
url: this.#url
|
|
51
55
|
};
|
|
52
56
|
|
|
53
57
|
this.#server = http.createServer({
|
|
@@ -56,15 +60,14 @@ export class CompilerServer {
|
|
|
56
60
|
keepAliveTimeout: 1000 * 60 * 60,
|
|
57
61
|
}, (req, res) => this.#onRequest(req, res));
|
|
58
62
|
|
|
59
|
-
|
|
60
|
-
process.on('SIGINT', () => this.#shutdown.abort());
|
|
63
|
+
process.once('exit', () => this.#shutdown.abort());
|
|
61
64
|
}
|
|
62
65
|
|
|
63
66
|
get mode(): CompilerMode {
|
|
64
67
|
return this.info.mode;
|
|
65
68
|
}
|
|
66
69
|
|
|
67
|
-
isResetEvent(ev:
|
|
70
|
+
isResetEvent(ev: CompilerEvent): boolean {
|
|
68
71
|
return ev.type === 'state' && ev.payload.state === 'reset';
|
|
69
72
|
}
|
|
70
73
|
|
|
@@ -74,14 +77,14 @@ export class CompilerServer {
|
|
|
74
77
|
.on('listening', () => resolve('ok'))
|
|
75
78
|
.on('error', async err => {
|
|
76
79
|
if ('code' in err && err.code === 'EADDRINUSE') {
|
|
77
|
-
const info = await
|
|
80
|
+
const info = await this.#client.info();
|
|
78
81
|
resolve((info && info.mode === 'build' && this.mode === 'watch') ? 'retry' : 'running');
|
|
79
82
|
} else {
|
|
80
83
|
reject(err);
|
|
81
84
|
}
|
|
82
85
|
});
|
|
83
86
|
|
|
84
|
-
const url = new URL(this.#
|
|
87
|
+
const url = new URL(this.#url);
|
|
85
88
|
setTimeout(() => this.#server.listen(+url.port, url.hostname), 1); // Run async
|
|
86
89
|
});
|
|
87
90
|
|
|
@@ -91,7 +94,7 @@ export class CompilerServer {
|
|
|
91
94
|
}
|
|
92
95
|
log('info', 'Waiting for build to finish, before retrying');
|
|
93
96
|
// Let the server finish
|
|
94
|
-
await
|
|
97
|
+
await this.#client.waitForState(['close'], 'Server closed', this.signal);
|
|
95
98
|
return this.#tryListen(attempt + 1);
|
|
96
99
|
}
|
|
97
100
|
|
|
@@ -107,7 +110,7 @@ export class CompilerServer {
|
|
|
107
110
|
res.end();
|
|
108
111
|
}
|
|
109
112
|
|
|
110
|
-
#emitEvent(ev:
|
|
113
|
+
#emitEvent(ev: CompilerEvent): void {
|
|
111
114
|
const msg = `${JSON.stringify(ev.payload)}\n`;
|
|
112
115
|
for (const el of this.#listeners) {
|
|
113
116
|
if (!el.res.closed && el.type === ev.type) {
|
|
@@ -124,8 +127,8 @@ export class CompilerServer {
|
|
|
124
127
|
}
|
|
125
128
|
|
|
126
129
|
async #clean(): Promise<{ clean: boolean }> {
|
|
127
|
-
await Promise.all([this.#ctx.compilerFolder, this.#ctx.outputFolder]
|
|
128
|
-
.map(f => fs.rm(path.resolve(this.#ctx.
|
|
130
|
+
await Promise.all([this.#ctx.build.compilerFolder, this.#ctx.build.outputFolder]
|
|
131
|
+
.map(f => fs.rm(path.resolve(this.#ctx.workspace.path, f), { recursive: true, force: true })));
|
|
129
132
|
return { clean: true };
|
|
130
133
|
}
|
|
131
134
|
|
|
@@ -135,7 +138,7 @@ export class CompilerServer {
|
|
|
135
138
|
async #onRequest(req: http.IncomingMessage, res: http.ServerResponse): Promise<void> {
|
|
136
139
|
res.setHeader('Content-Type', 'application/json');
|
|
137
140
|
|
|
138
|
-
const [, action, subAction] = new URL(`${this.#
|
|
141
|
+
const [, action, subAction] = new URL(`${this.#url}${req.url}`).pathname.split('/');
|
|
139
142
|
|
|
140
143
|
log('debug', 'Receive request', { action, subAction });
|
|
141
144
|
|
|
@@ -143,7 +146,7 @@ export class CompilerServer {
|
|
|
143
146
|
switch (action) {
|
|
144
147
|
case 'send-event': await this.#emitEvent(await CompilerServer.readJSONRequest(req)); out = { received: true }; break;
|
|
145
148
|
case 'event': return await this.#addListener(subAction, res);
|
|
146
|
-
case 'stop': out = await this.close(); break;
|
|
149
|
+
case 'stop': out = await this.close(true); break;
|
|
147
150
|
case 'clean': out = await this.#clean(); break;
|
|
148
151
|
case 'info':
|
|
149
152
|
default: out = this.info ?? {}; break;
|
|
@@ -154,11 +157,16 @@ export class CompilerServer {
|
|
|
154
157
|
/**
|
|
155
158
|
* Process events
|
|
156
159
|
*/
|
|
157
|
-
async processEvents(src: (signal: AbortSignal) => AsyncIterable<
|
|
160
|
+
async processEvents(src: (signal: AbortSignal) => AsyncIterable<CompilerEvent>): Promise<void> {
|
|
158
161
|
|
|
159
|
-
|
|
162
|
+
LogUtil.log('compiler', 'debug', 'Started, streaming logs');
|
|
163
|
+
LogUtil.consumeLogEvents(this.#client.fetchEvents('log', { signal: this.signal }));
|
|
160
164
|
|
|
161
165
|
for await (const ev of CommonUtil.restartableEvents(src, this.signal, this.isResetEvent)) {
|
|
166
|
+
if (ev.type === 'progress') {
|
|
167
|
+
await LogUtil.logProgress?.(ev.payload);
|
|
168
|
+
}
|
|
169
|
+
|
|
162
170
|
this.#emitEvent(ev);
|
|
163
171
|
|
|
164
172
|
if (ev.type === 'state') {
|
|
@@ -174,19 +182,22 @@ export class CompilerServer {
|
|
|
174
182
|
}
|
|
175
183
|
|
|
176
184
|
// Terminate, after letting all remaining events emit
|
|
177
|
-
await this.close();
|
|
185
|
+
await this.close(this.signal.aborted);
|
|
178
186
|
}
|
|
179
187
|
|
|
180
188
|
/**
|
|
181
189
|
* Close server
|
|
182
190
|
*/
|
|
183
|
-
async close(): Promise<unknown> {
|
|
184
|
-
if (this.signal.aborted) {
|
|
185
|
-
return;
|
|
186
|
-
}
|
|
187
|
-
|
|
191
|
+
async close(force: boolean): Promise<unknown> {
|
|
188
192
|
log('info', 'Closing down server');
|
|
189
193
|
await new Promise(r => {
|
|
194
|
+
|
|
195
|
+
if (force) {
|
|
196
|
+
const cancel: CompilerProgressEvent = { complete: true, idx: 0, total: 0, message: 'Complete', operation: 'compile' };
|
|
197
|
+
LogUtil.logProgress?.(cancel);
|
|
198
|
+
this.#emitEvent({ type: 'progress', payload: cancel });
|
|
199
|
+
}
|
|
200
|
+
|
|
190
201
|
this.#server.close(r);
|
|
191
202
|
this.#emitEvent({ type: 'state', payload: { state: 'close' } });
|
|
192
203
|
this.#server.unref();
|
|
@@ -203,7 +214,7 @@ export class CompilerServer {
|
|
|
203
214
|
*/
|
|
204
215
|
async listen(): Promise<CompilerServer | undefined> {
|
|
205
216
|
const running = await this.#tryListen() === 'ok';
|
|
206
|
-
log('info', running ? 'Starting server' : 'Server already running under a different process', this.#
|
|
217
|
+
log('info', running ? 'Starting server' : 'Server already running under a different process', this.#url);
|
|
207
218
|
return running ? this : undefined;
|
|
208
219
|
}
|
|
209
220
|
}
|
package/support/setup.ts
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
import
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import fs from 'node:fs/promises';
|
|
3
4
|
|
|
4
|
-
import { type DeltaEvent, type ManifestContext, type
|
|
5
|
+
import { type DeltaEvent, type ManifestContext, type Package } from '@travetto/manifest';
|
|
5
6
|
|
|
6
7
|
import { LogUtil } from './log';
|
|
7
8
|
import { CommonUtil } from './util';
|
|
8
9
|
|
|
9
10
|
type ModFile = { input: string, output: string, stale: boolean };
|
|
10
11
|
|
|
11
|
-
const SOURCE_SEED = ['package.json', '
|
|
12
|
-
const PRECOMPILE_MODS = ['@travetto/
|
|
12
|
+
const SOURCE_SEED = ['package.json', '__index__.ts', 'src', 'support', 'bin'];
|
|
13
|
+
const PRECOMPILE_MODS = ['@travetto/manifest', '@travetto/transformer', '@travetto/compiler'];
|
|
13
14
|
const RECENT_STAT = (stat: { ctimeMs: number, mtimeMs: number }): number => Math.max(stat.ctimeMs, stat.mtimeMs);
|
|
15
|
+
const REQ = createRequire(path.resolve('node_modules')).resolve.bind(null);
|
|
14
16
|
|
|
15
17
|
/**
|
|
16
18
|
* Compiler Setup Utilities
|
|
@@ -18,10 +20,16 @@ const RECENT_STAT = (stat: { ctimeMs: number, mtimeMs: number }): number => Math
|
|
|
18
20
|
export class CompilerSetup {
|
|
19
21
|
|
|
20
22
|
/**
|
|
21
|
-
* Import
|
|
23
|
+
* Import compiled manifest utilities
|
|
22
24
|
*/
|
|
23
|
-
static #importManifest = (ctx: ManifestContext): Promise<
|
|
24
|
-
import(
|
|
25
|
+
static #importManifest = (ctx: ManifestContext): Promise<
|
|
26
|
+
Pick<typeof import('@travetto/manifest'), 'ManifestDeltaUtil' | 'ManifestUtil'>
|
|
27
|
+
> => {
|
|
28
|
+
const all = ['util', 'delta'].map(f =>
|
|
29
|
+
import(path.resolve(ctx.workspace.path, ctx.build.compilerFolder, 'node_modules', `@travetto/manifest/src/${f}.js`))
|
|
30
|
+
);
|
|
31
|
+
return Promise.all(all).then(props => Object.assign({}, ...props));
|
|
32
|
+
};
|
|
25
33
|
|
|
26
34
|
/** Convert a file to a given ext */
|
|
27
35
|
static #sourceToExtension(inputFile: string, ext: string): string {
|
|
@@ -41,7 +49,7 @@ export class CompilerSetup {
|
|
|
41
49
|
static async #transpileFile(ctx: ManifestContext, inputFile: string, outputFile: string): Promise<void> {
|
|
42
50
|
const type = CommonUtil.getFileType(inputFile);
|
|
43
51
|
if (type === 'js' || type === 'ts') {
|
|
44
|
-
const compilerOut = path.resolve(ctx.
|
|
52
|
+
const compilerOut = path.resolve(ctx.workspace.path, ctx.build.compilerFolder, 'node_modules');
|
|
45
53
|
|
|
46
54
|
const text = (await fs.readFile(inputFile, 'utf8'))
|
|
47
55
|
.replace(/from '([.][^']+)'/g, (_, i) => `from '${i.replace(/[.]js$/, '')}.js'`)
|
|
@@ -59,7 +67,7 @@ export class CompilerSetup {
|
|
|
59
67
|
const main = pkg.main ? this.#sourceToOutputExt(pkg.main) : undefined;
|
|
60
68
|
const files = pkg.files?.map(x => this.#sourceToOutputExt(x));
|
|
61
69
|
|
|
62
|
-
const content = JSON.stringify({ ...pkg, main, type: ctx.
|
|
70
|
+
const content = JSON.stringify({ ...pkg, main, type: ctx.workspace.type, files }, null, 2);
|
|
63
71
|
await CommonUtil.writeTextFile(outputFile, content);
|
|
64
72
|
}
|
|
65
73
|
}
|
|
@@ -68,9 +76,7 @@ export class CompilerSetup {
|
|
|
68
76
|
* Scan directory to find all project sources for comparison
|
|
69
77
|
*/
|
|
70
78
|
static async #getModuleSources(ctx: ManifestContext, module: string, seed: string[]): Promise<ModFile[]> {
|
|
71
|
-
const inputFolder = (
|
|
72
|
-
process.cwd() :
|
|
73
|
-
CommonUtil.resolveModuleFolder(module);
|
|
79
|
+
const inputFolder = path.dirname(REQ(`${module}/package.json`));
|
|
74
80
|
|
|
75
81
|
const folders = seed.filter(x => !/[.]/.test(x)).map(x => path.resolve(inputFolder, x));
|
|
76
82
|
const files = seed.filter(x => /[.]/.test(x)).map(x => path.resolve(inputFolder, x));
|
|
@@ -98,7 +104,7 @@ export class CompilerSetup {
|
|
|
98
104
|
}
|
|
99
105
|
}
|
|
100
106
|
|
|
101
|
-
const outputFolder = path.resolve(ctx.
|
|
107
|
+
const outputFolder = path.resolve(ctx.workspace.path, ctx.build.compilerFolder, 'node_modules', module);
|
|
102
108
|
const out: ModFile[] = [];
|
|
103
109
|
for (const input of files) {
|
|
104
110
|
const output = this.#sourceToOutputExt(input.replace(inputFolder, outputFolder));
|
|
@@ -162,25 +168,21 @@ export class CompilerSetup {
|
|
|
162
168
|
}
|
|
163
169
|
|
|
164
170
|
/**
|
|
165
|
-
* Sets up compiler, and produces a
|
|
171
|
+
* Sets up compiler, and produces a set of changes that need to be processed
|
|
166
172
|
*/
|
|
167
|
-
static async setup(ctx: ManifestContext): Promise<
|
|
173
|
+
static async setup(ctx: ManifestContext): Promise<DeltaEvent[]> {
|
|
168
174
|
let changes = 0;
|
|
169
175
|
|
|
170
176
|
await LogUtil.withLogger('precompile', async () => {
|
|
171
177
|
for (const mod of PRECOMPILE_MODS) {
|
|
172
|
-
|
|
173
|
-
if (mod !== '@travetto/terminal') {
|
|
174
|
-
changes += count;
|
|
175
|
-
}
|
|
178
|
+
changes += (await this.#compileIfStale(ctx, 'precompile', mod, SOURCE_SEED)).length;
|
|
176
179
|
}
|
|
177
180
|
});
|
|
178
181
|
|
|
179
|
-
const { ManifestUtil, ManifestDeltaUtil
|
|
180
|
-
|
|
181
|
-
PackageUtil.clearCache();
|
|
182
|
+
const { ManifestUtil, ManifestDeltaUtil } = await this.#importManifest(ctx);
|
|
182
183
|
|
|
183
|
-
const manifest = await LogUtil.withLogger('manifest', () =>
|
|
184
|
+
const manifest = await LogUtil.withLogger('manifest', () =>
|
|
185
|
+
ManifestUtil.buildManifest(ManifestUtil.getWorkspaceContext(ctx)));
|
|
184
186
|
|
|
185
187
|
await LogUtil.withLogger('transformers', async () => {
|
|
186
188
|
for (const mod of Object.values(manifest.modules).filter(m => m.files.$transformer?.length)) {
|
|
@@ -191,30 +193,32 @@ export class CompilerSetup {
|
|
|
191
193
|
const delta = await LogUtil.withLogger('delta', async log => {
|
|
192
194
|
if (changes) {
|
|
193
195
|
log('debug', 'Skipping, everything changed');
|
|
194
|
-
return [{ type: 'changed', file: '*', module: ctx.
|
|
196
|
+
return [{ type: 'changed', file: '*', module: ctx.workspace.name, sourceFile: '' } as const];
|
|
195
197
|
} else {
|
|
196
|
-
return ManifestDeltaUtil.produceDelta(
|
|
198
|
+
return ManifestDeltaUtil.produceDelta(manifest);
|
|
197
199
|
}
|
|
198
200
|
});
|
|
199
201
|
|
|
200
202
|
if (changes) {
|
|
201
203
|
await LogUtil.withLogger('reset', async log => {
|
|
202
|
-
await fs.rm(path.resolve(ctx.
|
|
204
|
+
await fs.rm(path.resolve(ctx.workspace.path, ctx.build.outputFolder), { recursive: true, force: true });
|
|
203
205
|
log('info', 'Clearing output due to compiler changes');
|
|
204
206
|
}, false);
|
|
205
207
|
}
|
|
206
208
|
|
|
207
209
|
// Write manifest
|
|
208
210
|
await LogUtil.withLogger('manifest', async log => {
|
|
209
|
-
await ManifestUtil.writeManifest(
|
|
210
|
-
log('debug', `Wrote manifest ${ctx.
|
|
211
|
+
await ManifestUtil.writeManifest(manifest);
|
|
212
|
+
log('debug', `Wrote manifest ${ctx.workspace.name}`);
|
|
211
213
|
|
|
212
|
-
// Update all manifests
|
|
213
|
-
if (delta.length && ctx.
|
|
214
|
+
// Update all manifests when in mono repo
|
|
215
|
+
if (delta.length && ctx.workspace.mono) {
|
|
214
216
|
const names: string[] = [];
|
|
215
|
-
const mods = Object.values(manifest.modules).filter(x => x.local && x.name !== ctx.
|
|
217
|
+
const mods = Object.values(manifest.modules).filter(x => x.local && x.name !== ctx.workspace.name);
|
|
216
218
|
for (const mod of mods) {
|
|
217
|
-
|
|
219
|
+
const modCtx = ManifestUtil.getModuleContext(ctx, mod.sourceFolder);
|
|
220
|
+
const modManifest = await ManifestUtil.buildManifest(modCtx);
|
|
221
|
+
await ManifestUtil.writeManifest(modManifest);
|
|
218
222
|
names.push(mod.name);
|
|
219
223
|
}
|
|
220
224
|
log('debug', `Changes triggered ${delta.slice(0, 10).map(x => `${x.type}:${x.module}:${x.file}`)}`);
|
|
@@ -222,8 +226,6 @@ export class CompilerSetup {
|
|
|
222
226
|
}
|
|
223
227
|
});
|
|
224
228
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
return { manifest, changed };
|
|
229
|
+
return delta.filter(x => x.type === 'added' || x.type === 'changed');
|
|
228
230
|
}
|
|
229
231
|
}
|
package/support/types.ts
CHANGED
|
@@ -8,13 +8,13 @@ export type CompilerLogEvent = { level: CompilerLogLevel, message: string, time:
|
|
|
8
8
|
export type CompilerProgressEvent = { idx: number, total: number, message: string, operation: 'compile', complete?: boolean };
|
|
9
9
|
export type CompilerStateEvent = { state: CompilerStateType, extra?: Record<string, unknown> };
|
|
10
10
|
|
|
11
|
-
export type
|
|
11
|
+
export type CompilerEvent =
|
|
12
12
|
{ type: 'change', payload: CompilerChangeEvent } |
|
|
13
13
|
{ type: 'log', payload: CompilerLogEvent } |
|
|
14
14
|
{ type: 'progress', payload: CompilerProgressEvent } |
|
|
15
15
|
{ type: 'state', payload: CompilerStateEvent };
|
|
16
16
|
|
|
17
|
-
export type
|
|
17
|
+
export type CompilerEventType = CompilerEvent['type'];
|
|
18
18
|
|
|
19
19
|
export type CompilerServerInfo = {
|
|
20
20
|
path: string;
|
package/support/util.ts
CHANGED
|
@@ -1,50 +1,42 @@
|
|
|
1
|
-
import fs from 'fs/promises';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import {
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { setMaxListeners } from 'node:events';
|
|
4
4
|
|
|
5
5
|
import type { ManifestContext } from '@travetto/manifest';
|
|
6
6
|
|
|
7
7
|
import { LogUtil } from './log';
|
|
8
8
|
|
|
9
9
|
const OPT_CACHE: Record<string, import('typescript').CompilerOptions> = {};
|
|
10
|
-
const SRC_REQ = createRequire(path.resolve('node_modules'));
|
|
11
10
|
|
|
12
11
|
export class CommonUtil {
|
|
13
12
|
/**
|
|
14
13
|
* Returns the compiler options
|
|
15
14
|
*/
|
|
16
15
|
static async getCompilerOptions(ctx: ManifestContext): Promise<{}> {
|
|
17
|
-
if (!(ctx.
|
|
18
|
-
let tsconfig = path.resolve(ctx.
|
|
16
|
+
if (!(ctx.workspace.path in OPT_CACHE)) {
|
|
17
|
+
let tsconfig = path.resolve(ctx.workspace.path, 'tsconfig.json');
|
|
19
18
|
|
|
20
19
|
if (!await fs.stat(tsconfig).then(_ => true, _ => false)) {
|
|
21
|
-
tsconfig =
|
|
20
|
+
tsconfig = path.resolve(ctx.workspace.path, ctx.build.compilerModuleFolder, 'tsconfig.trv.json');
|
|
22
21
|
}
|
|
23
22
|
|
|
24
23
|
const ts = (await import('typescript')).default;
|
|
25
24
|
|
|
26
25
|
const { options } = ts.parseJsonSourceFileConfigFileContent(
|
|
27
|
-
ts.readJsonConfigFile(tsconfig, ts.sys.readFile), ts.sys, ctx.
|
|
26
|
+
ts.readJsonConfigFile(tsconfig, ts.sys.readFile), ts.sys, ctx.workspace.path
|
|
28
27
|
);
|
|
29
28
|
|
|
30
|
-
OPT_CACHE[ctx.
|
|
29
|
+
OPT_CACHE[ctx.workspace.path] = {
|
|
31
30
|
...options,
|
|
32
31
|
allowJs: true,
|
|
33
32
|
resolveJsonModule: true,
|
|
34
|
-
sourceRoot: ctx.
|
|
35
|
-
rootDir: ctx.
|
|
36
|
-
outDir: path.resolve(ctx.
|
|
37
|
-
module: ctx.
|
|
33
|
+
sourceRoot: ctx.workspace.path,
|
|
34
|
+
rootDir: ctx.workspace.path,
|
|
35
|
+
outDir: path.resolve(ctx.workspace.path),
|
|
36
|
+
module: ctx.workspace.type === 'commonjs' ? ts.ModuleKind.CommonJS : ts.ModuleKind.ESNext,
|
|
38
37
|
};
|
|
39
38
|
}
|
|
40
|
-
return OPT_CACHE[ctx.
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Resolve module location
|
|
45
|
-
*/
|
|
46
|
-
static resolveModuleFolder(mod: string): string {
|
|
47
|
-
return path.dirname(SRC_REQ.resolve(`${mod}/package.json`));
|
|
39
|
+
return OPT_CACHE[ctx.workspace.path];
|
|
48
40
|
}
|
|
49
41
|
|
|
50
42
|
/**
|
|
@@ -68,6 +60,7 @@ export class CommonUtil {
|
|
|
68
60
|
static async * restartableEvents<T>(src: (signal: AbortSignal) => AsyncIterable<T>, parent: AbortSignal, shouldRestart: (item: T) => boolean): AsyncIterable<T> {
|
|
69
61
|
outer: while (!parent.aborted) {
|
|
70
62
|
const controller = new AbortController();
|
|
63
|
+
setMaxListeners(1000, controller.signal);
|
|
71
64
|
// Chain
|
|
72
65
|
parent.addEventListener('abort', () => controller.abort());
|
|
73
66
|
|
|
@@ -100,8 +93,8 @@ export class CommonUtil {
|
|
|
100
93
|
*/
|
|
101
94
|
static moduleLoader(ctx: ManifestContext): (mod: string) => Promise<unknown> {
|
|
102
95
|
return (mod) => {
|
|
103
|
-
const outputRoot = path.resolve(ctx.
|
|
104
|
-
process.env.TRV_MANIFEST = path.resolve(outputRoot, 'node_modules', ctx.
|
|
96
|
+
const outputRoot = path.resolve(ctx.workspace.path, ctx.build.outputFolder);
|
|
97
|
+
process.env.TRV_MANIFEST = path.resolve(outputRoot, 'node_modules', ctx.main.name); // Setup for running
|
|
105
98
|
return import(path.join(outputRoot, 'node_modules', mod)); // Return function to run import on a module
|
|
106
99
|
};
|
|
107
100
|
}
|