@travetto/compiler 8.0.0-alpha.2 → 8.0.0-alpha.21
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 +5 -5
- package/__index__.ts +4 -4
- package/bin/hook.js +6 -9
- package/bin/trvc-target.js +3 -1
- package/bin/trvc.js +3 -1
- package/package.json +4 -4
- package/src/common.ts +15 -9
- package/src/compiler.ts +61 -66
- package/src/event.ts +7 -5
- package/src/log.ts +57 -22
- package/src/queue.ts +4 -2
- package/src/server/client.ts +38 -24
- package/src/server/manager.ts +18 -12
- package/src/server/process-handle.ts +14 -10
- package/src/server/server.ts +49 -25
- package/src/state.ts +145 -74
- package/src/ts-proxy.ts +6 -3
- package/src/types.ts +22 -19
- package/src/util.ts +1 -34
- package/src/watch.ts +81 -69
- package/support/invoke.ts +65 -29
- package/tsconfig.trv.json +6 -15
package/src/server/client.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import rl from 'node:readline/promises';
|
|
2
|
-
import timers from 'node:timers/promises';
|
|
3
1
|
import fs from 'node:fs/promises';
|
|
4
2
|
import http, { Agent } from 'node:http';
|
|
3
|
+
import rl from 'node:readline/promises';
|
|
4
|
+
import timers from 'node:timers/promises';
|
|
5
5
|
|
|
6
6
|
import type { ManifestContext } from '@travetto/manifest';
|
|
7
7
|
|
|
8
|
-
import type { CompilerEventPayload, CompilerEventType, CompilerServerInfo, CompilerStateType } from '../types.ts';
|
|
9
|
-
import type { LogShape } from '../log.ts';
|
|
10
8
|
import { CommonUtil } from '../common.ts';
|
|
9
|
+
import type { LogShape } from '../log.ts';
|
|
10
|
+
import type { CompilerEventPayload, CompilerEventType, CompilerServerInfo, CompilerStateType } from '../types.ts';
|
|
11
11
|
import { ProcessHandle } from './process-handle.ts';
|
|
12
12
|
|
|
13
13
|
type FetchEventsConfig<T> = {
|
|
@@ -26,7 +26,6 @@ const streamAgent = new Agent({
|
|
|
26
26
|
* Compiler Client Operations
|
|
27
27
|
*/
|
|
28
28
|
export class CompilerClient {
|
|
29
|
-
|
|
30
29
|
#url: string;
|
|
31
30
|
#log: LogShape;
|
|
32
31
|
#handle: Record<'compiler' | 'server', ProcessHandle>;
|
|
@@ -47,17 +46,18 @@ export class CompilerClient {
|
|
|
47
46
|
return this.#url;
|
|
48
47
|
}
|
|
49
48
|
|
|
50
|
-
async #fetch(urlPath: string, options?: RequestInit & { timeout?: number }, logTimeout = true): Promise<{ ok: boolean
|
|
49
|
+
async #fetch(urlPath: string, options?: RequestInit & { timeout?: number }, logTimeout = true): Promise<{ ok: boolean; text: string }> {
|
|
51
50
|
const controller = new AbortController();
|
|
52
51
|
const timeoutController = new AbortController();
|
|
53
52
|
|
|
54
53
|
options?.signal?.addEventListener('abort', () => controller.abort());
|
|
55
|
-
timers
|
|
54
|
+
timers
|
|
55
|
+
.setTimeout(options?.timeout ?? 100, undefined, { ref: false, signal: timeoutController.signal })
|
|
56
56
|
.then(() => {
|
|
57
57
|
logTimeout && this.#log.error(`Timeout on request to ${this.#url}${urlPath}`);
|
|
58
58
|
controller.abort('TIMEOUT');
|
|
59
59
|
})
|
|
60
|
-
.catch(() => {
|
|
60
|
+
.catch(() => {});
|
|
61
61
|
const response = await fetch(`${this.#url}${urlPath}`, { ...options, signal: controller.signal });
|
|
62
62
|
const out = { ok: response.ok, text: await response.text() };
|
|
63
63
|
timeoutController.abort();
|
|
@@ -66,7 +66,10 @@ export class CompilerClient {
|
|
|
66
66
|
|
|
67
67
|
/** Get server information, if server is running */
|
|
68
68
|
info(): Promise<CompilerServerInfo | undefined> {
|
|
69
|
-
return this.#fetch('/info', { timeout: 200 }, false).then(
|
|
69
|
+
return this.#fetch('/info', { timeout: 200 }, false).then(
|
|
70
|
+
response => JSON.parse(response.text),
|
|
71
|
+
() => undefined
|
|
72
|
+
);
|
|
70
73
|
}
|
|
71
74
|
|
|
72
75
|
async isWatching(): Promise<boolean> {
|
|
@@ -75,13 +78,19 @@ export class CompilerClient {
|
|
|
75
78
|
|
|
76
79
|
/** Clean the server */
|
|
77
80
|
async clean(forceOnFailure?: boolean): Promise<boolean> {
|
|
78
|
-
const result = await this.#fetch('/clean', { timeout: 300 }).then(
|
|
81
|
+
const result = await this.#fetch('/clean', { timeout: 300 }).then(
|
|
82
|
+
response => response.ok,
|
|
83
|
+
() => false
|
|
84
|
+
);
|
|
79
85
|
if (!result && forceOnFailure) {
|
|
80
86
|
this.#log.warn('Clean request failed, forcing cleanup');
|
|
81
87
|
try {
|
|
82
|
-
await Promise.all(
|
|
83
|
-
.
|
|
84
|
-
|
|
88
|
+
await Promise.all(
|
|
89
|
+
[this.#ctx.build.outputFolder, this.#ctx.build.typesFolder].map(file =>
|
|
90
|
+
fs.rm(CommonUtil.resolveWorkspace(this.#ctx, file), { force: true, recursive: true })
|
|
91
|
+
)
|
|
92
|
+
);
|
|
93
|
+
} catch {}
|
|
85
94
|
}
|
|
86
95
|
return result;
|
|
87
96
|
}
|
|
@@ -91,18 +100,20 @@ export class CompilerClient {
|
|
|
91
100
|
const info = await this.info();
|
|
92
101
|
if (!info) {
|
|
93
102
|
this.#log.debug('Stopping server, info not found, manual killing');
|
|
94
|
-
return Promise.all([this.#handle.server.kill(), this.#handle.compiler.kill()])
|
|
95
|
-
.then(results => results.some(result => result));
|
|
103
|
+
return Promise.all([this.#handle.server.kill(), this.#handle.compiler.kill()]).then(results => results.some(result => result));
|
|
96
104
|
}
|
|
97
105
|
|
|
98
|
-
await this.#fetch('/stop').catch(() => {
|
|
106
|
+
await this.#fetch('/stop').catch(() => {}); // Trigger
|
|
99
107
|
this.#log.debug('Waiting for compiler to exit');
|
|
100
108
|
await this.#handle.compiler.ensureKilled();
|
|
101
109
|
return true;
|
|
102
110
|
}
|
|
103
111
|
|
|
104
112
|
/** Fetch compiler events */
|
|
105
|
-
async *
|
|
113
|
+
async *fetchEvents<V extends CompilerEventType, T extends CompilerEventPayload<V>>(
|
|
114
|
+
type: V,
|
|
115
|
+
config: FetchEventsConfig<T> = {}
|
|
116
|
+
): AsyncIterable<T> {
|
|
106
117
|
let info = await this.info();
|
|
107
118
|
if (!info) {
|
|
108
119
|
return;
|
|
@@ -121,14 +132,13 @@ export class CompilerClient {
|
|
|
121
132
|
|
|
122
133
|
const { iteration } = info;
|
|
123
134
|
|
|
124
|
-
for (
|
|
135
|
+
for (;;) {
|
|
125
136
|
const controller = new AbortController();
|
|
126
137
|
const quit = (): void => controller.abort();
|
|
127
138
|
try {
|
|
128
139
|
signal.addEventListener('abort', quit);
|
|
129
140
|
const response = await new Promise<http.IncomingMessage>((resolve, reject) =>
|
|
130
|
-
http.get(`${this.#url}/event/${type}`, { agent: streamAgent, signal: controller.signal }, resolve)
|
|
131
|
-
.on('error', reject)
|
|
141
|
+
http.get(`${this.#url}/event/${type}`, { agent: streamAgent, signal: controller.signal }, resolve).on('error', reject)
|
|
132
142
|
);
|
|
133
143
|
|
|
134
144
|
for await (const line of rl.createInterface(response)) {
|
|
@@ -143,7 +153,9 @@ export class CompilerClient {
|
|
|
143
153
|
}
|
|
144
154
|
} catch (error) {
|
|
145
155
|
const aborted = controller.signal.aborted || (typeof error === 'object' && error && 'code' in error && error.code === 'ECONNRESET');
|
|
146
|
-
if (!aborted) {
|
|
156
|
+
if (!aborted) {
|
|
157
|
+
throw error;
|
|
158
|
+
}
|
|
147
159
|
}
|
|
148
160
|
signal.removeEventListener('abort', quit);
|
|
149
161
|
|
|
@@ -156,7 +168,8 @@ export class CompilerClient {
|
|
|
156
168
|
return;
|
|
157
169
|
}
|
|
158
170
|
|
|
159
|
-
if (controller.signal.aborted || !info || (config.enforceIteration && info.iteration !== iteration)) {
|
|
171
|
+
if (controller.signal.aborted || !info || (config.enforceIteration && info.iteration !== iteration)) {
|
|
172
|
+
// If health check fails, or aborted
|
|
160
173
|
this.#log.debug(`Stopping watch for events of type "${type}"`);
|
|
161
174
|
return;
|
|
162
175
|
} else {
|
|
@@ -170,10 +183,11 @@ export class CompilerClient {
|
|
|
170
183
|
const set = new Set(states);
|
|
171
184
|
// Loop until
|
|
172
185
|
this.#log.debug(`Waiting for states, ${states.join(', ')}`);
|
|
173
|
-
for await (const _ of this.fetchEvents('state', { signal, until: event => set.has(event.state) })) {
|
|
186
|
+
for await (const _ of this.fetchEvents('state', { signal, until: event => set.has(event.state) })) {
|
|
187
|
+
}
|
|
174
188
|
this.#log.debug(`Found state, one of ${states.join(', ')} `);
|
|
175
189
|
if (message) {
|
|
176
190
|
this.#log.info(message);
|
|
177
191
|
}
|
|
178
192
|
}
|
|
179
|
-
}
|
|
193
|
+
}
|
package/src/server/manager.ts
CHANGED
|
@@ -2,11 +2,11 @@ import { spawn } from 'node:child_process';
|
|
|
2
2
|
|
|
3
3
|
import type { ManifestContext } from '@travetto/manifest';
|
|
4
4
|
|
|
5
|
-
import type { CompilerEvent, CompilerLogLevel } from '../types.ts';
|
|
6
|
-
import { AsyncQueue } from '../queue.ts';
|
|
7
|
-
import { Log } from '../log.ts';
|
|
8
5
|
import { CommonUtil } from '../common.ts';
|
|
9
6
|
import { EventUtil } from '../event.ts';
|
|
7
|
+
import { Log } from '../log.ts';
|
|
8
|
+
import { AsyncQueue } from '../queue.ts';
|
|
9
|
+
import type { CompilerEvent, CompilerLogLevel } from '../types.ts';
|
|
10
10
|
import type { CompilerClient } from './client.ts';
|
|
11
11
|
import { CompilerServer } from './server.ts';
|
|
12
12
|
|
|
@@ -17,7 +17,7 @@ const log = Log.scoped('compiler-exec');
|
|
|
17
17
|
*/
|
|
18
18
|
export class CompilerManager {
|
|
19
19
|
/** Run compile process */
|
|
20
|
-
static async
|
|
20
|
+
static async *#runTarget(ctx: ManifestContext, watching: boolean, signal: AbortSignal): AsyncIterable<CompilerEvent> {
|
|
21
21
|
if (signal.aborted) {
|
|
22
22
|
log.debug('Skipping, shutting down');
|
|
23
23
|
return;
|
|
@@ -30,17 +30,17 @@ export class CompilerManager {
|
|
|
30
30
|
env: {
|
|
31
31
|
...process.env,
|
|
32
32
|
TRV_COMPILER_WATCH: String(watching),
|
|
33
|
-
TRV_MANIFEST: CommonUtil.resolveWorkspace(ctx, ctx.build.outputFolder, 'node_modules', ctx.workspace.name)
|
|
33
|
+
TRV_MANIFEST: CommonUtil.resolveWorkspace(ctx, ctx.build.outputFolder, 'node_modules', ctx.workspace.name)
|
|
34
34
|
},
|
|
35
35
|
detached: true,
|
|
36
|
-
stdio: ['pipe', 1, 2, 'ipc']
|
|
36
|
+
stdio: ['pipe', 1, 2, 'ipc']
|
|
37
37
|
})
|
|
38
38
|
.on('message', message => EventUtil.isCompilerEvent(message) && queue.add(message))
|
|
39
39
|
.on('exit', () => queue.close());
|
|
40
40
|
|
|
41
41
|
const kill = (): unknown => {
|
|
42
42
|
log.debug('Shutting down process');
|
|
43
|
-
return
|
|
43
|
+
return subProcess.connected ? subProcess.send('shutdown', () => subProcess.kill()) : subProcess.kill();
|
|
44
44
|
};
|
|
45
45
|
|
|
46
46
|
process.once('SIGINT', kill);
|
|
@@ -48,8 +48,9 @@ export class CompilerManager {
|
|
|
48
48
|
|
|
49
49
|
yield* queue;
|
|
50
50
|
|
|
51
|
-
if (subProcess.exitCode !== 0) {
|
|
51
|
+
if (subProcess.exitCode !== 0 && subProcess.exitCode) {
|
|
52
52
|
log.error(`Terminated during compilation, code=${subProcess.exitCode}, killed=${subProcess.killed}`);
|
|
53
|
+
process.exitCode = subProcess.exitCode;
|
|
53
54
|
}
|
|
54
55
|
process.off('SIGINT', kill);
|
|
55
56
|
|
|
@@ -57,11 +58,15 @@ export class CompilerManager {
|
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
/** Main entry point for compilation */
|
|
60
|
-
static async compile(
|
|
61
|
+
static async compile(
|
|
62
|
+
ctx: ManifestContext,
|
|
63
|
+
client: CompilerClient,
|
|
64
|
+
config: { watch?: boolean; logLevel?: CompilerLogLevel; forceRestart?: boolean }
|
|
65
|
+
): Promise<void> {
|
|
61
66
|
Log.initLevel(config.logLevel ?? 'info');
|
|
62
67
|
const watch = !!config.watch;
|
|
63
68
|
|
|
64
|
-
if (config.forceRestart && await client.stop()) {
|
|
69
|
+
if (config.forceRestart && (await client.stop())) {
|
|
65
70
|
log.info('Stopped existing server');
|
|
66
71
|
}
|
|
67
72
|
|
|
@@ -83,8 +88,9 @@ export class CompilerManager {
|
|
|
83
88
|
|
|
84
89
|
/** Compile only if necessary */
|
|
85
90
|
static async compileIfNecessary(ctx: ManifestContext, client: CompilerClient): Promise<void> {
|
|
86
|
-
if (!(await client.isWatching())) {
|
|
91
|
+
if (!(await client.isWatching())) {
|
|
92
|
+
// Short circuit if we can
|
|
87
93
|
await this.compile(ctx, client, { watch: false, logLevel: 'error' });
|
|
88
94
|
}
|
|
89
95
|
}
|
|
90
|
-
}
|
|
96
|
+
}
|
|
@@ -3,11 +3,10 @@ import path from 'node:path';
|
|
|
3
3
|
|
|
4
4
|
import type { ManifestContext } from '@travetto/manifest';
|
|
5
5
|
|
|
6
|
-
import { Log, type Logger } from '../log.ts';
|
|
7
6
|
import { CommonUtil } from '../common.ts';
|
|
7
|
+
import { Log, type Logger } from '../log.ts';
|
|
8
8
|
|
|
9
9
|
export class ProcessHandle {
|
|
10
|
-
|
|
11
10
|
#file: string;
|
|
12
11
|
#log: Logger;
|
|
13
12
|
|
|
@@ -22,13 +21,17 @@ export class ProcessHandle {
|
|
|
22
21
|
}
|
|
23
22
|
|
|
24
23
|
getProcessId(): Promise<number | undefined> {
|
|
25
|
-
return fs.readFile(this.#file, 'utf8')
|
|
26
|
-
|
|
24
|
+
return fs.readFile(this.#file, 'utf8').then(
|
|
25
|
+
processId => (+processId > 0 ? +processId : undefined),
|
|
26
|
+
() => undefined
|
|
27
|
+
);
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
async isRunning(): Promise<boolean> {
|
|
30
31
|
const processId = await this.getProcessId();
|
|
31
|
-
if (!processId) {
|
|
32
|
+
if (!processId) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
32
35
|
try {
|
|
33
36
|
process.kill(processId, 0); // See if process is still running
|
|
34
37
|
this.#log.debug('Is running', processId);
|
|
@@ -41,11 +44,11 @@ export class ProcessHandle {
|
|
|
41
44
|
|
|
42
45
|
async kill(): Promise<boolean> {
|
|
43
46
|
const processId = await this.getProcessId();
|
|
44
|
-
if (processId && await this.isRunning()) {
|
|
47
|
+
if (processId && (await this.isRunning())) {
|
|
45
48
|
try {
|
|
46
49
|
this.#log.debug('Killing', processId);
|
|
47
50
|
return process.kill(processId);
|
|
48
|
-
} catch {
|
|
51
|
+
} catch {}
|
|
49
52
|
}
|
|
50
53
|
return false;
|
|
51
54
|
}
|
|
@@ -58,8 +61,9 @@ export class ProcessHandle {
|
|
|
58
61
|
}
|
|
59
62
|
|
|
60
63
|
this.#log.debug('Ensuring Killed', processId);
|
|
61
|
-
while (
|
|
62
|
-
|
|
64
|
+
while (Date.now() - start < gracePeriod) {
|
|
65
|
+
// Ensure its done
|
|
66
|
+
if (!(await this.isRunning())) {
|
|
63
67
|
return true;
|
|
64
68
|
}
|
|
65
69
|
await CommonUtil.blockingTimeout(100);
|
|
@@ -67,7 +71,7 @@ export class ProcessHandle {
|
|
|
67
71
|
try {
|
|
68
72
|
this.#log.debug('Force Killing', processId);
|
|
69
73
|
process.kill(processId); // Force kill
|
|
70
|
-
} catch {
|
|
74
|
+
} catch {}
|
|
71
75
|
this.#log.debug('Did Kill', this.#file, !!processId);
|
|
72
76
|
return true;
|
|
73
77
|
}
|
package/src/server/server.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import http from 'node:http';
|
|
2
|
-
import fs from 'node:fs/promises';
|
|
3
1
|
import { setMaxListeners } from 'node:events';
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
import http from 'node:http';
|
|
4
4
|
|
|
5
5
|
import type { ManifestContext } from '@travetto/manifest';
|
|
6
6
|
|
|
7
|
-
import type { CompilerProgressEvent, CompilerEvent, CompilerEventType, CompilerServerInfo } from '../types.ts';
|
|
8
|
-
import { Log } from '../log.ts';
|
|
9
7
|
import { CommonUtil } from '../common.ts';
|
|
8
|
+
import { EventUtil } from '../event.ts';
|
|
9
|
+
import { Log } from '../log.ts';
|
|
10
|
+
import type { CompilerEvent, CompilerEventType, CompilerProgressEvent, CompilerServerInfo } from '../types.ts';
|
|
10
11
|
import { CompilerClient } from './client.ts';
|
|
11
12
|
import { ProcessHandle } from './process-handle.ts';
|
|
12
|
-
import { EventUtil } from '../event.ts';
|
|
13
13
|
|
|
14
14
|
const log = Log.scoped('server');
|
|
15
15
|
|
|
@@ -17,7 +17,6 @@ const log = Log.scoped('server');
|
|
|
17
17
|
* Compiler Server Class
|
|
18
18
|
*/
|
|
19
19
|
export class CompilerServer {
|
|
20
|
-
|
|
21
20
|
#ctx: ManifestContext;
|
|
22
21
|
#server: http.Server;
|
|
23
22
|
#listenersAll = new Set<http.ServerResponse>();
|
|
@@ -27,12 +26,14 @@ export class CompilerServer {
|
|
|
27
26
|
#client: CompilerClient;
|
|
28
27
|
#url: string;
|
|
29
28
|
#handle: Record<'compiler' | 'server', ProcessHandle>;
|
|
29
|
+
#suppressLogs: boolean;
|
|
30
30
|
|
|
31
|
-
constructor(ctx: ManifestContext, watching: boolean) {
|
|
31
|
+
constructor(ctx: ManifestContext, watching: boolean, suppressLogs?: boolean) {
|
|
32
32
|
this.#ctx = ctx;
|
|
33
33
|
this.#client = new CompilerClient(ctx, Log.scoped('server.client'));
|
|
34
34
|
this.#url = this.#client.url;
|
|
35
35
|
this.#handle = { server: new ProcessHandle(ctx, 'server'), compiler: new ProcessHandle(ctx, 'compiler') };
|
|
36
|
+
this.#suppressLogs = suppressLogs ?? /^(1|true|on|yes)$/i.test(process.env.TRV_QUIET ?? '');
|
|
36
37
|
|
|
37
38
|
this.info = {
|
|
38
39
|
state: 'startup',
|
|
@@ -44,11 +45,14 @@ export class CompilerServer {
|
|
|
44
45
|
url: this.#url
|
|
45
46
|
};
|
|
46
47
|
|
|
47
|
-
this.#server = http.createServer(
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
this.#server = http.createServer(
|
|
49
|
+
{
|
|
50
|
+
keepAlive: true,
|
|
51
|
+
requestTimeout: 1000 * 60 * 60,
|
|
52
|
+
keepAliveTimeout: 1000 * 60 * 60
|
|
53
|
+
},
|
|
54
|
+
(request, response) => this.#onRequest(request, response)
|
|
55
|
+
);
|
|
52
56
|
|
|
53
57
|
setMaxListeners(1000, this.signal);
|
|
54
58
|
}
|
|
@@ -72,7 +76,7 @@ export class CompilerServer {
|
|
|
72
76
|
.on('error', async error => {
|
|
73
77
|
if ('code' in error && error.code === 'EADDRINUSE') {
|
|
74
78
|
const info = await this.#client.info();
|
|
75
|
-
resolve(
|
|
79
|
+
resolve(info && !info.watching && this.watching ? 'retry' : 'running');
|
|
76
80
|
} else {
|
|
77
81
|
log.warn('Failed in running server', error);
|
|
78
82
|
reject(error);
|
|
@@ -104,7 +108,8 @@ export class CompilerServer {
|
|
|
104
108
|
const id = `id_${Date.now()}_${Math.random()}`.replace('.', '1');
|
|
105
109
|
(this.#listeners[type] ??= {})[id] = response;
|
|
106
110
|
this.#listenersAll.add(response);
|
|
107
|
-
if (type === 'state' || type === 'all') {
|
|
111
|
+
if (type === 'state' || type === 'all') {
|
|
112
|
+
// Send on initial connect
|
|
108
113
|
this.#emitEvent({ type: 'state', payload: { state: this.info.state } }, id);
|
|
109
114
|
} else {
|
|
110
115
|
response.write('\n'); // Send at least one byte on listen
|
|
@@ -144,15 +149,20 @@ export class CompilerServer {
|
|
|
144
149
|
this.info.iteration = Date.now();
|
|
145
150
|
await CommonUtil.blockingTimeout(20);
|
|
146
151
|
for (const listener of this.#listenersAll) {
|
|
147
|
-
try {
|
|
152
|
+
try {
|
|
153
|
+
listener.end();
|
|
154
|
+
} catch {}
|
|
148
155
|
}
|
|
149
156
|
this.#listeners = {}; // Ensure its empty
|
|
150
157
|
this.#listenersAll.clear();
|
|
151
158
|
}
|
|
152
159
|
|
|
153
160
|
async #clean(): Promise<{ clean: boolean }> {
|
|
154
|
-
await Promise.all(
|
|
155
|
-
.
|
|
161
|
+
await Promise.all(
|
|
162
|
+
[this.#ctx.build.outputFolder, this.#ctx.build.typesFolder].map(folder =>
|
|
163
|
+
fs.rm(CommonUtil.resolveWorkspace(this.#ctx, folder), { recursive: true, force: true })
|
|
164
|
+
)
|
|
165
|
+
);
|
|
156
166
|
return { clean: true };
|
|
157
167
|
}
|
|
158
168
|
|
|
@@ -173,10 +183,16 @@ export class CompilerServer {
|
|
|
173
183
|
}
|
|
174
184
|
return;
|
|
175
185
|
}
|
|
176
|
-
case 'clean':
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
186
|
+
case 'clean':
|
|
187
|
+
out = await this.#clean();
|
|
188
|
+
break;
|
|
189
|
+
case 'stop':
|
|
190
|
+
out = JSON.stringify({ closing: true });
|
|
191
|
+
close = true;
|
|
192
|
+
break;
|
|
193
|
+
default:
|
|
194
|
+
out = this.info ?? {};
|
|
195
|
+
break;
|
|
180
196
|
}
|
|
181
197
|
response.end(JSON.stringify(out));
|
|
182
198
|
if (close) {
|
|
@@ -197,7 +213,12 @@ export class CompilerServer {
|
|
|
197
213
|
|
|
198
214
|
if (event.type === 'state') {
|
|
199
215
|
this.info.state = event.payload.state;
|
|
200
|
-
if (
|
|
216
|
+
if (
|
|
217
|
+
event.payload.state === 'init' &&
|
|
218
|
+
event.payload.extra &&
|
|
219
|
+
'processId' in event.payload.extra &&
|
|
220
|
+
typeof event.payload.extra.processId === 'number'
|
|
221
|
+
) {
|
|
201
222
|
if (this.info.watching && !this.info.compilerProcessId) {
|
|
202
223
|
// Ensure we are killing in watch mode on first set
|
|
203
224
|
await this.#handle.compiler.kill();
|
|
@@ -207,7 +228,9 @@ export class CompilerServer {
|
|
|
207
228
|
}
|
|
208
229
|
log.info(`State changed: ${this.info.state}`);
|
|
209
230
|
} else if (event.type === 'log') {
|
|
210
|
-
|
|
231
|
+
if (!this.#suppressLogs) {
|
|
232
|
+
log.render(event.payload);
|
|
233
|
+
}
|
|
211
234
|
}
|
|
212
235
|
if (this.isResetEvent(event)) {
|
|
213
236
|
await this.#disconnectActive();
|
|
@@ -243,7 +266,8 @@ export class CompilerServer {
|
|
|
243
266
|
this.#shutdown.abort();
|
|
244
267
|
});
|
|
245
268
|
});
|
|
246
|
-
} catch {
|
|
269
|
+
} catch {
|
|
270
|
+
// Timeout or other error
|
|
247
271
|
// Force shutdown
|
|
248
272
|
this.#server.closeAllConnections();
|
|
249
273
|
await this.#handle.compiler.kill();
|
|
@@ -256,7 +280,7 @@ export class CompilerServer {
|
|
|
256
280
|
* Start the server listening
|
|
257
281
|
*/
|
|
258
282
|
async listen(): Promise<CompilerServer | undefined> {
|
|
259
|
-
const running = await this.#tryListen() === 'ok';
|
|
283
|
+
const running = (await this.#tryListen()) === 'ok';
|
|
260
284
|
log.info(running ? 'Starting server' : 'Server already running under a different process', this.#url);
|
|
261
285
|
return running ? this : undefined;
|
|
262
286
|
}
|