@travetto/compiler 3.0.0-rc.13 → 3.0.0-rc.15

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