@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.
@@ -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, ManifestRoot, DeltaEvent } from '@travetto/manifest';
5
+ import type { ManifestContext, DeltaEvent } from '@travetto/manifest';
5
6
 
6
- import type { CompilerOp, CompilerProgressEvent, CompilerServerEvent } from '../types';
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.log.bind(null, 'compiler-exec');
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, manifest: ManifestRoot, changed: DeltaEvent[], op: CompilerOp, signal: AbortSignal): AsyncIterable<CompilerServerEvent> {
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
- // Track progress if not in run mode
49
- if (op !== 'run') {
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
- let proc: cp.ChildProcess | undefined;
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.workspacePath, ctx.outputFolder, 'node_modules', ctx.mainModule),
48
+ TRV_MANIFEST: path.resolve(ctx.workspace.path, ctx.build.outputFolder, 'node_modules', ctx.workspace.name),
74
49
  },
75
- stdio: ['pipe', 'pipe', 2, 'ipc'],
50
+ detached: true,
51
+ stdio: ['pipe', 1, 2, 'ipc'],
76
52
  })
77
- .on('message', msg => {
78
- if (msg && typeof msg === 'object' && 'type' in msg) {
79
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
80
- queue.add(msg as CompilerServerEvent);
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
- kill = (): void => { proc?.kill('SIGKILL'); };
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
- log('debug', `exit code: ${proc?.exitCode}`);
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('exit', kill);
70
+ process.off('SIGINT', kill);
104
71
  }
72
+ rmSync(deltaFile, { force: true });
105
73
  }
106
74
  }
107
75
  }
@@ -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, CompilerServerEvent, CompilerServerEventType, CompilerServerInfo } from '../types';
7
+ import type { CompilerMode, CompilerOp, CompilerProgressEvent, CompilerEvent, CompilerEventType, CompilerServerInfo } from '../types';
8
8
  import { LogUtil } from '../log';
9
- import { CompilerClientUtil } from './client';
9
+ import { CompilerClient } from './client';
10
10
  import { CommonUtil } from '../util';
11
11
 
12
- const log = LogUtil.log.bind(LogUtil, 'compiler-server');
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: CompilerServerEventType }[] = [];
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.workspacePath,
50
- url: ctx.compilerUrl
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
- // Connect
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: CompilerServerEvent): boolean {
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 CompilerClientUtil.getServerInfo(this.#ctx);
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.#ctx.compilerUrl);
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 CompilerClientUtil.waitForState(this.#ctx, ['close'], this.signal);
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: CompilerServerEvent): void {
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.workspacePath, f), { recursive: true, force: true })));
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.#ctx.compilerUrl}${req.url}`).pathname.split('/');
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<CompilerServerEvent>): Promise<void> {
160
+ async processEvents(src: (signal: AbortSignal) => AsyncIterable<CompilerEvent>): Promise<void> {
158
161
 
159
- CompilerClientUtil.streamLogs(this.#ctx, this.signal); // Send logs to stdout
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.#ctx.compilerUrl);
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 fs from 'fs/promises';
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 ManifestRoot, Package } from '@travetto/manifest';
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', 'index.ts', '__index__.ts', 'src', 'support', 'bin'];
12
- const PRECOMPILE_MODS = ['@travetto/terminal', '@travetto/manifest', '@travetto/transformer', '@travetto/compiler'];
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 a compiled manifest
23
+ * Import compiled manifest utilities
22
24
  */
23
- static #importManifest = (ctx: ManifestContext): Promise<typeof import('@travetto/manifest')> =>
24
- import(path.resolve(ctx.workspacePath, ctx.compilerFolder, 'node_modules', '@travetto/manifest/__index__.js'));
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.workspacePath, ctx.compilerFolder, 'node_modules');
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.moduleType, files }, null, 2);
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 = (ctx.mainModule === module) ?
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.workspacePath, ctx.compilerFolder, 'node_modules', module);
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 manifest and set of changes that need to be processed
171
+ * Sets up compiler, and produces a set of changes that need to be processed
166
172
  */
167
- static async setup(ctx: ManifestContext): Promise<{ manifest: ManifestRoot, changed: DeltaEvent[] }> {
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
- const count = (await this.#compileIfStale(ctx, 'precompile', mod, SOURCE_SEED)).length;
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, PackageUtil } = await this.#importManifest(ctx);
180
-
181
- PackageUtil.clearCache();
182
+ const { ManifestUtil, ManifestDeltaUtil } = await this.#importManifest(ctx);
182
183
 
183
- const manifest = await LogUtil.withLogger('manifest', () => ManifestUtil.buildManifest(ctx));
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.mainModule } as const];
196
+ return [{ type: 'changed', file: '*', module: ctx.workspace.name, sourceFile: '' } as const];
195
197
  } else {
196
- return ManifestDeltaUtil.produceDelta(ctx, manifest);
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.workspacePath, ctx.outputFolder), { recursive: true, force: true });
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(ctx, manifest);
210
- log('debug', `Wrote manifest ${ctx.mainModule}`);
211
+ await ManifestUtil.writeManifest(manifest);
212
+ log('debug', `Wrote manifest ${ctx.workspace.name}`);
211
213
 
212
- // Update all manifests
213
- if (delta.length && ctx.monoRepo && !ctx.mainFolder) {
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.mainModule);
217
+ const mods = Object.values(manifest.modules).filter(x => x.local && x.name !== ctx.workspace.name);
216
218
  for (const mod of mods) {
217
- await ManifestUtil.rewriteManifest(path.resolve(ctx.workspacePath, mod.sourceFolder));
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
- const changed = delta.filter(x => x.type === 'added' || x.type === 'changed');
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 CompilerServerEvent =
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 CompilerServerEventType = CompilerServerEvent['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 { createRequire } from 'module';
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.workspacePath in OPT_CACHE)) {
18
- let tsconfig = path.resolve(ctx.workspacePath, 'tsconfig.json');
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 = SRC_REQ.resolve('@travetto/compiler/tsconfig.trv.json');
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.workspacePath
26
+ ts.readJsonConfigFile(tsconfig, ts.sys.readFile), ts.sys, ctx.workspace.path
28
27
  );
29
28
 
30
- OPT_CACHE[ctx.workspacePath] = {
29
+ OPT_CACHE[ctx.workspace.path] = {
31
30
  ...options,
32
31
  allowJs: true,
33
32
  resolveJsonModule: true,
34
- sourceRoot: ctx.workspacePath,
35
- rootDir: ctx.workspacePath,
36
- outDir: path.resolve(ctx.workspacePath),
37
- module: ctx.moduleType === 'commonjs' ? ts.ModuleKind.CommonJS : ts.ModuleKind.ESNext,
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.workspacePath];
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.workspacePath, ctx.outputFolder);
104
- process.env.TRV_MANIFEST = path.resolve(outputRoot, 'node_modules', ctx.mainModule); // Setup for running
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
  }