@travetto/compiler 4.0.0-rc.2 → 4.0.0-rc.4

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/common.js CHANGED
@@ -25,7 +25,11 @@ const getTarget = (/** @type {Ctx} */ ctx, file = '') => ({
25
25
  const getTranspiler = async (/** @type {Ctx} */ ctx) => {
26
26
  const ts = (await import('typescript')).default;
27
27
  const module = ctx.workspace.type === 'module' ? ts.ModuleKind.ESNext : ts.ModuleKind.CommonJS;
28
- return (content = '') => ts.transpile(content, { target: ts.ScriptTarget.ES2022, module, esModuleInterop: true, allowSyntheticDefaultImports: true });
28
+ return (content = '') =>
29
+ ts.transpile(content, { target: ts.ScriptTarget.ES2022, module, esModuleInterop: true, allowSyntheticDefaultImports: true })
30
+ .replace(/from '([.][^']+)'/g, (_, i) => `from '${i.replace(/[.]js$/, '')}.js'`)
31
+ .replace(/from '(@travetto\/(.*?))'/g, (_, i, s) =>
32
+ `from '${path.resolve(ctx.workspace.path, ctx.build.compilerFolder, `${i}${s.includes('/') ? '.js' : '/__index__.js'}`)}'`);
29
33
  };
30
34
 
31
35
  /** @returns {Promise<import('@travetto/compiler/support/entry.trvc')>} */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/compiler",
3
- "version": "4.0.0-rc.2",
3
+ "version": "4.0.0-rc.4",
4
4
  "description": "The compiler infrastructure for the Travetto framework",
5
5
  "keywords": [
6
6
  "compiler",
@@ -31,12 +31,12 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@parcel/watcher": "^2.4.0",
34
- "@travetto/manifest": "^4.0.0-rc.2",
35
- "@travetto/transformer": "^4.0.0-rc.2",
34
+ "@travetto/manifest": "^4.0.0-rc.4",
35
+ "@travetto/transformer": "^4.0.0-rc.4",
36
36
  "@types/node": "^20.11.16"
37
37
  },
38
38
  "peerDependencies": {
39
- "@travetto/cli": "^4.0.0-rc.2"
39
+ "@travetto/cli": "^4.0.0-rc.5"
40
40
  },
41
41
  "peerDependenciesMeta": {
42
42
  "@travetto/cli": {
package/src/watch.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ManifestContext, ManifestModuleUtil, ManifestUtil, RuntimeIndex, path } from '@travetto/manifest';
1
+ import { ManifestContext, ManifestModuleUtil, ManifestUtil, PackageUtil, RuntimeIndex, path } from '@travetto/manifest';
2
2
 
3
3
  import type { CompileStateEntry } from './types';
4
4
  import { CompilerState } from './state';
@@ -22,10 +22,28 @@ export class CompilerWatcher {
22
22
  this.#signal = signal;
23
23
  }
24
24
 
25
+ #getIgnores(): string[] {
26
+ // TODO: Read .gitignore?
27
+ let ignores = PackageUtil.readPackage(this.#state.manifest.workspace.path)?.travetto?.build?.watchIgnores;
28
+
29
+ if (!ignores) {
30
+ ignores = ['node_modules/**'];
31
+ }
32
+
33
+ return [
34
+ ...ignores,
35
+ '.git', '**/.git',
36
+ `${this.#state.manifest.build.outputFolder}/node_modules/**`,
37
+ `${this.#state.manifest.build.compilerFolder}/node_modules/**`,
38
+ `${this.#state.manifest.build.toolFolder}/**`
39
+ ];
40
+ }
41
+
25
42
  /** Watch files */
26
43
  async * #watchFolder(rootPath: string): AsyncIterable<WatchEvent> {
27
44
  const q = new AsyncQueue<WatchEvent>(this.#signal);
28
45
  const lib = await import('@parcel/watcher');
46
+ const ignore = this.#getIgnores();
29
47
 
30
48
  const cleanup = await lib.subscribe(rootPath, (err, events) => {
31
49
  if (err) {
@@ -36,15 +54,7 @@ export class CompilerWatcher {
36
54
  for (const ev of events) {
37
55
  q.add({ action: ev.type, file: path.toPosix(ev.path) });
38
56
  }
39
- }, {
40
- // TODO: Read .gitignore?
41
- ignore: [
42
- 'node_modules', '**/node_modules', '.git', '**/.git',
43
- `${this.#state.manifest.build.outputFolder}/node_modules/**`,
44
- `${this.#state.manifest.build.compilerFolder}/node_modules/**`,
45
- `${this.#state.manifest.build.toolFolder}/**`
46
- ]
47
- });
57
+ }, { ignore });
48
58
 
49
59
  if (this.#signal.aborted) { // If already aborted, can happen async
50
60
  cleanup.unsubscribe();
@@ -1,2 +1,3 @@
1
+ // @trv-no-transform
1
2
  import { Compiler } from '../src/compiler';
2
3
  Compiler.main();
@@ -1,3 +1,4 @@
1
+ // @trv-no-transform
1
2
  import fs from 'node:fs/promises';
2
3
  import path from 'node:path';
3
4
 
@@ -40,6 +41,7 @@ export const main = (ctx: ManifestContext) => {
40
41
  await client.waitForState(['compile-end', 'watch-start'], 'Successfully built');
41
42
  ctrl.abort();
42
43
  }
44
+ LogUtil.cleanup();
43
45
  };
44
46
 
45
47
  const ops = {
package/support/log.ts CHANGED
@@ -10,6 +10,8 @@ const LEVEL_TO_PRI: Record<CompilerLogLevel, number> = { debug: 1, info: 2, warn
10
10
 
11
11
  const SCOPE_MAX = 15;
12
12
 
13
+ const ESC = '\x1b[';
14
+
13
15
  export class LogUtil {
14
16
 
15
17
  static root = process.cwd();
@@ -22,14 +24,13 @@ export class LogUtil {
22
24
 
23
25
  static #rewriteLine(text: string): Promise<void> | void {
24
26
  // Move to 1st position, and clear after text
25
- const done = process.stdout.write(`\x1b[1G${text}\x1b[0K`);
27
+ const done = process.stdout.write(`${ESC}1G${text}${ESC}0K`);
26
28
  this.linePartial = !!text;
27
29
  if (!done) {
28
30
  return new Promise<void>(r => process.stdout.once('drain', r));
29
31
  }
30
32
  }
31
33
 
32
-
33
34
  /**
34
35
  * Set level for operation
35
36
  */
@@ -40,7 +41,18 @@ export class LogUtil {
40
41
  this.logLevel = build || defaultLevel;
41
42
  }
42
43
  this.root = ctx.workspace.path;
43
- this.logProgress = (this.isLevelActive('info') && process.stdout.isTTY) ? this.#logProgressEvent : undefined;
44
+ // If we are in info or a terminal and also in a tty
45
+ this.logProgress = ((this.isLevelActive('info') || process.env.PS1) && process.stdout.isTTY) ? this.#logProgressEvent : undefined;
46
+ if (this.logProgress) {
47
+ process.stdout.write(`${ESC}?25l`); // Hide cursor
48
+ }
49
+ process.on('exit', () => this.cleanup());
50
+ }
51
+
52
+ static cleanup(): void {
53
+ if (this.logProgress) {
54
+ process.stdout.write(`${ESC}!p`); // Reset
55
+ }
44
56
  }
45
57
 
46
58
  static #logProgressEvent(ev: CompilerProgressEvent): Promise<void> | void {
@@ -37,11 +37,11 @@ export class CompilerClient {
37
37
  return this.#url;
38
38
  }
39
39
 
40
- async #fetch(rel: string, opts?: RequestInit & { timeout?: number }): Promise<Response> {
40
+ async #fetch(rel: string, opts?: RequestInit & { timeout?: number }, logTimeout = true): Promise<Response> {
41
41
  const ctrl = new AbortController();
42
42
  opts?.signal?.addEventListener('abort', () => ctrl.abort());
43
43
  const timeoutId = setTimeout(() => {
44
- this.#log('error', `Timeout on request to ${this.#url}${rel}`);
44
+ logTimeout && this.#log('error', `Timeout on request to ${this.#url}${rel}`);
45
45
  ctrl.abort('TIMEOUT');
46
46
  }, 100).unref();
47
47
  try {
@@ -53,7 +53,7 @@ export class CompilerClient {
53
53
 
54
54
  /** Get server information, if server is running */
55
55
  info(): Promise<CompilerServerInfo | undefined> {
56
- return this.#fetch('/info').then(v => v.json(), () => undefined)
56
+ return this.#fetch('/info', {}, false).then(v => v.json(), () => undefined)
57
57
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
58
58
  .then(v => v as CompilerServerInfo);
59
59
  }
@@ -12,7 +12,8 @@ export class ProcessHandle {
12
12
  this.#file = path.resolve(ctx.workspace.path, ctx.build.toolFolder, `${name}.pid`);
13
13
  }
14
14
 
15
- writePid(pid: number): Promise<void> {
15
+ async writePid(pid: number): Promise<void> {
16
+ await fs.mkdir(path.dirname(this.#file), { recursive: true });
16
17
  return fs.writeFile(this.#file, JSON.stringify(pid), 'utf8');
17
18
  }
18
19
 
@@ -20,7 +20,7 @@ export class CompilerServer {
20
20
 
21
21
  #ctx: ManifestContext;
22
22
  #server: http.Server;
23
- #listeners: { res: http.ServerResponse, type: CompilerEventType }[] = [];
23
+ #listeners: Record<string, { res: http.ServerResponse, type: CompilerEventType }> = {};
24
24
  #shutdown = new AbortController();
25
25
  signal = this.#shutdown.signal;
26
26
  info: CompilerServerInfo;
@@ -97,20 +97,21 @@ export class CompilerServer {
97
97
 
98
98
  async #addListener(type: string, res: http.ServerResponse): Promise<void> {
99
99
  res.writeHead(200);
100
+ const id = `id_${Date.now()}_${Math.random()}`.replace('.', '1');
100
101
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
101
- this.#listeners.push({ res, type: type as 'change' });
102
+ this.#listeners[id] = { res, type: type as 'change' };
102
103
  if (type === 'state') { // Send on initial connect
103
104
  res.write(JSON.stringify({ state: this.info.state }));
104
105
  }
105
106
  res.write('\n'); // Send at least one byte on listen
106
- await new Promise(resolve => res.on('close', resolve));
107
- this.#listeners.splice(this.#listeners.findIndex(x => x.res === res), 1);
108
- res.end();
107
+
108
+ // Do not wait on it
109
+ res.on('close', () => { delete this.#listeners[id]; });
109
110
  }
110
111
 
111
112
  #emitEvent(ev: CompilerEvent): void {
112
113
  const msg = `${JSON.stringify(ev.payload)}\n`;
113
- for (const el of this.#listeners) {
114
+ for (const el of Object.values(this.#listeners)) {
114
115
  if (!el.res.closed && el.type === ev.type) {
115
116
  el.res.write(msg);
116
117
  }
@@ -121,8 +122,8 @@ export class CompilerServer {
121
122
  log('info', 'Server disconnect requested');
122
123
  this.info.iteration = Date.now();
123
124
  await new Promise(r => setTimeout(r, 20));
124
- for (const el of this.#listeners) {
125
- el.res.destroy();
125
+ for (const el of Object.values(this.#listeners)) {
126
+ el.res.end();
126
127
  }
127
128
  }
128
129