@travetto/compiler 4.1.2 → 5.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/bin/common.js CHANGED
@@ -10,8 +10,13 @@ const TS_EXT = /[.]tsx?$/;
10
10
 
11
11
  const getAge = (/** @type {{mtimeMs:number, ctimeMs:number}} */ st) => Math.max(st.mtimeMs, st.ctimeMs);
12
12
 
13
+ const modPath = (/** @type {Ctx} */ ctx, mod, file) => {
14
+ const base = path.resolve(ctx.workspace.path, ctx.build.compilerFolder, 'node_modules', mod, file);
15
+ return `${base}${file.includes('.') ? '' : file.includes('/') ? '.ts' : '/__index__.ts'}`.replace(TS_EXT, '.js');
16
+ };
17
+
13
18
  const getTarget = (/** @type {Ctx} */ ctx, file = '') => ({
14
- dest: path.resolve(ctx.workspace.path, ctx.build.compilerFolder, 'node_modules', '@travetto/compiler', file).replace(TS_EXT, '.js'),
19
+ dest: modPath(ctx, '@travetto/compiler', file),
15
20
  src: path.resolve(ctx.workspace.path, ctx.build.compilerModuleFolder, file),
16
21
  async writeIfStale(/** @type {(text:string)=>(string|Promise<string>)}*/ transform) {
17
22
  if (!existsSync(this.dest) || getAge(statSync(this.dest)) < getAge(statSync(this.src))) {
@@ -28,8 +33,7 @@ const getTranspiler = async (/** @type {Ctx} */ ctx) => {
28
33
  return (content = '') =>
29
34
  ts.transpile(content, { target: ts.ScriptTarget.ES2022, module, esModuleInterop: true, allowSyntheticDefaultImports: true })
30
35
  .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'}`)}'`);
36
+ .replace(/from '(@travetto\/[^/']+)([/][^']+)?'/g, (_, mod, file) => `from '${modPath(ctx, mod, file)}'`);
33
37
  };
34
38
 
35
39
  /** @returns {Promise<import('@travetto/compiler/support/entry.trvc')>} */
@@ -44,14 +48,21 @@ export async function getEntry() {
44
48
 
45
49
  // Setup Tsconfig
46
50
  const tsconfig = path.resolve(ctx.workspace.path, 'tsconfig.json');
47
- existsSync(tsconfig) || writeFileSync(tsconfig, JSON.stringify({ extends: '@travetto/compiler/tsconfig.trv.json' }), 'utf8');
51
+ existsSync(tsconfig) || writeFileSync(tsconfig,
52
+ JSON.stringify({ extends: '@travetto/compiler/tsconfig.trv.json' }), 'utf8');
48
53
 
49
54
  // Compile support folder
50
- await target('package.json').writeIfStale(text => JSON.stringify(Object.assign(JSON.parse(text), { type: ctx.workspace.type }), null, 2));
55
+ await target('package.json').writeIfStale(text =>
56
+ JSON.stringify(Object.assign(JSON.parse(text), { type: ctx.workspace.type }), null, 2)
57
+ );
51
58
 
52
59
  let transpile;
53
60
  for (const file of readdirSync(target('support').src, { recursive: true, encoding: 'utf8' })) {
54
- if (TS_EXT.test(file)) { await target(`support/${file}`).writeIfStale(async (text) => (transpile ??= await getTranspiler(ctx))(text)); }
61
+ if (TS_EXT.test(file)) {
62
+ await target(`support/${file}`).writeIfStale(async (text) =>
63
+ (transpile ??= await getTranspiler(ctx))(text)
64
+ );
65
+ }
55
66
  }
56
67
 
57
68
  // Load
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/compiler",
3
- "version": "4.1.2",
3
+ "version": "5.0.0-rc.0",
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.1",
34
- "@travetto/manifest": "^4.1.0",
35
- "@travetto/transformer": "^4.1.2",
36
- "@types/node": "^20.14.8"
34
+ "@travetto/manifest": "^5.0.0-rc.0",
35
+ "@travetto/transformer": "^5.0.0-rc.0",
36
+ "@types/node": "^20.14.10"
37
37
  },
38
38
  "peerDependencies": {
39
- "@travetto/cli": "^4.1.2"
39
+ "@travetto/cli": "^5.0.0-rc.0"
40
40
  },
41
41
  "peerDependenciesMeta": {
42
42
  "@travetto/cli": {
package/src/event.ts CHANGED
@@ -2,6 +2,6 @@ import type { CompilerEvent, CompilerEventType } from '../support/types';
2
2
 
3
3
  export class EventUtil {
4
4
  static sendEvent<K extends CompilerEventType, T extends CompilerEvent & { type: K }>(type: K, payload: T['payload']): void {
5
- process.connected && process.send!({ type, payload }, undefined, { swallowErrors: true });
5
+ process.connected && process.send!({ type, payload }, undefined, undefined, () => { });
6
6
  }
7
7
  }
package/src/util.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import ts from 'typescript';
2
2
 
3
- import { ManifestContext, ManifestModuleFileType, ManifestModuleUtil, ManifestRoot, Package, path } from '@travetto/manifest';
3
+ import { path, ManifestContext, ManifestModuleFileType, ManifestModuleUtil, ManifestRoot, Package } from '@travetto/manifest';
4
4
 
5
5
  type OutputToSource = (outputFile: string) => ({ sourceFile: string } | undefined);
6
6
 
package/src/watch.ts CHANGED
@@ -19,7 +19,6 @@ type FileShape = {
19
19
  action: WatchAction;
20
20
  };
21
21
 
22
-
23
22
  /**
24
23
  * Watch support, based on compiler state and manifest details
25
24
  */
@@ -44,7 +43,7 @@ export class CompilerWatcher {
44
43
  ignores = ['node_modules/**'];
45
44
  }
46
45
 
47
- // Disable exclusions until parcel watcher fixes itself
46
+ // TODO: Fix once node/parcel sort this out
48
47
  return os.platform() === 'linux' ? [] : [
49
48
  ...ignores,
50
49
  '.git', '**/.git',
@@ -1,6 +1,5 @@
1
1
  // @trv-no-transform
2
2
  import fs from 'node:fs/promises';
3
- import path from 'node:path';
4
3
 
5
4
  import type { ManifestContext } from '@travetto/manifest';
6
5
 
@@ -10,6 +9,8 @@ import { CompilerSetup } from './setup';
10
9
  import { CompilerServer } from './server/server';
11
10
  import { CompilerRunner } from './server/runner';
12
11
  import { CompilerClient } from './server/client';
12
+ import { CommonUtil } from './util';
13
+
13
14
 
14
15
  // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
15
16
  export const main = (ctx: ManifestContext) => {
@@ -63,7 +64,7 @@ export const main = (ctx: ManifestContext) => {
63
64
  if (await client.clean()) {
64
65
  return console.log(`Clean triggered ${ctx.workspace.path}:`, buildFolders);
65
66
  } else {
66
- await Promise.all(buildFolders.map(f => fs.rm(path.resolve(ctx.workspace.path, f), { force: true, recursive: true })));
67
+ await Promise.all(buildFolders.map(f => fs.rm(CommonUtil.resolveWorkspace(ctx, f), { force: true, recursive: true })));
67
68
  return console.log(`Cleaned ${ctx.workspace.path}:`, buildFolders);
68
69
  }
69
70
  },
@@ -72,6 +73,8 @@ export const main = (ctx: ManifestContext) => {
72
73
  events: async (type: string, handler: (ev: unknown) => unknown): Promise<void> => {
73
74
  if (type === 'change' || type === 'log' || type === 'progress' || type === 'state') {
74
75
  for await (const ev of client.fetchEvents(type)) { await handler(ev); }
76
+ } else if (type === 'all') {
77
+ for await (const ev of client.fetchEvents(type)) { await handler(ev); }
75
78
  } else {
76
79
  throw new Error(`Unknown event type: ${type}`);
77
80
  }
@@ -98,12 +101,11 @@ export const main = (ctx: ManifestContext) => {
98
101
  }
99
102
 
100
103
  return (mod, args) => {
101
- const outputRoot = path.resolve(ctx.workspace.path, ctx.build.outputFolder);
102
- process.env.TRV_MANIFEST = path.resolve(outputRoot, 'node_modules', ctx.main.name); // Setup for running
104
+ process.env.TRV_MANIFEST = CommonUtil.resolveWorkspace(ctx, ctx.build.outputFolder, 'node_modules', ctx.main.name); // Setup for running
103
105
  if (args) {
104
106
  process.argv = [process.argv0, mod, ...args];
105
107
  }
106
- return import(path.join(outputRoot, 'node_modules', mod)); // Return function to run import on a module
108
+ return import(CommonUtil.resolveWorkspace(ctx, ctx.build.outputFolder, 'node_modules', mod)); // Return function to run import on a module
107
109
  };
108
110
  },
109
111
 
@@ -93,10 +93,13 @@ export class CompilerClient {
93
93
  }
94
94
 
95
95
  /** Fetch compiler events */
96
- async * fetchEvents<
96
+ /** Fetch compiler events */
97
+ fetchEvents<
97
98
  V extends CompilerEventType,
98
99
  T extends (CompilerEvent & { type: V })['payload']
99
- >(type: V, cfg: FetchEventsConfig<T> = {}): AsyncIterable<T> {
100
+ >(type: V, cfg?: FetchEventsConfig<T>): AsyncIterable<T>;
101
+ fetchEvents(type: 'all', cfg?: FetchEventsConfig<CompilerEvent>): AsyncIterable<CompilerEvent>;
102
+ async * fetchEvents<T = unknown>(type: string, cfg: FetchEventsConfig<T> = {}): AsyncIterable<T> {
100
103
  let info = await this.info();
101
104
  if (!info) {
102
105
  return;
@@ -11,7 +11,7 @@ export class ProcessHandle {
11
11
  #log: Logger;
12
12
 
13
13
  constructor(ctx: ManifestContext, name: string) {
14
- this.#file = path.resolve(ctx.workspace.path, ctx.build.toolFolder, `${name}.pid`);
14
+ this.#file = CommonUtil.resolveWorkspace(ctx, ctx.build.toolFolder, `${name}.pid`);
15
15
  this.#log = Log.scoped(`process-handle.${name}`);
16
16
  }
17
17
 
@@ -51,8 +51,12 @@ export class ProcessHandle {
51
51
  async ensureKilled(gracePeriod: number = 3000): Promise<boolean> {
52
52
  const start = Date.now();
53
53
  const pid = await this.getPid();
54
+ if (!pid) {
55
+ return false;
56
+ }
57
+
54
58
  this.#log.debug('Ensuring Killed', pid);
55
- while (pid && (Date.now() - start) < gracePeriod) { // Ensure its done
59
+ while ((Date.now() - start) < gracePeriod) { // Ensure its done
56
60
  if (!await this.isRunning()) {
57
61
  return true;
58
62
  }
@@ -60,9 +64,9 @@ export class ProcessHandle {
60
64
  }
61
65
  try {
62
66
  this.#log.debug('Force Killing', pid);
63
- pid && process.kill(pid); // Force kill
67
+ process.kill(pid); // Force kill
64
68
  } catch { }
65
69
  this.#log.debug('Did Kill', this.#file, !!pid);
66
- return pid !== undefined;
70
+ return true;
67
71
  }
68
72
  }
@@ -1,5 +1,4 @@
1
1
  import cp from 'node:child_process';
2
- import path from 'node:path';
3
2
  import { rmSync } from 'node:fs';
4
3
 
5
4
  import type { ManifestContext, DeltaEvent } from '@travetto/manifest';
@@ -35,8 +34,8 @@ export class CompilerRunner {
35
34
  log.debug(`Started watch=${watch} changed=${changed.slice(0, 10).map(x => `${x.module}/${x.file}`)}`);
36
35
  }
37
36
 
38
- const main = path.resolve(ctx.workspace.path, ctx.build.compilerFolder, 'node_modules', '@travetto/compiler/support/entry.compiler.js');
39
- const deltaFile = path.resolve(ctx.workspace.path, ctx.build.compilerFolder, `manifest-delta-${Date.now()}.json`);
37
+ const main = CommonUtil.resolveWorkspace(ctx, ctx.build.compilerFolder, 'node_modules', '@travetto/compiler/support/entry.compiler.js');
38
+ const deltaFile = CommonUtil.resolveWorkspace(ctx, ctx.build.compilerFolder, `manifest-delta-${Date.now()}.json`);
40
39
 
41
40
  const changedFiles = changed[0]?.file === '*' ? ['*'] : changed.map(ev => ev.sourceFile);
42
41
 
@@ -49,7 +48,7 @@ export class CompilerRunner {
49
48
  const proc = cp.spawn(process.argv0, [main, deltaFile, `${watch}`], {
50
49
  env: {
51
50
  ...process.env,
52
- TRV_MANIFEST: path.resolve(ctx.workspace.path, ctx.build.outputFolder, 'node_modules', ctx.workspace.name),
51
+ TRV_MANIFEST: CommonUtil.resolveWorkspace(ctx, ctx.build.outputFolder, 'node_modules', ctx.workspace.name),
53
52
  },
54
53
  detached: true,
55
54
  stdio: ['pipe', 1, 2, 'ipc'],
@@ -1,6 +1,5 @@
1
1
  import http from 'node:http';
2
2
  import fs from 'node:fs/promises';
3
- import path from 'node:path';
4
3
  import { setMaxListeners } from 'node:events';
5
4
 
6
5
  import type { ManifestContext } from '@travetto/manifest';
@@ -20,7 +19,8 @@ export class CompilerServer {
20
19
 
21
20
  #ctx: ManifestContext;
22
21
  #server: http.Server;
23
- #listeners: Record<string, { res: http.ServerResponse, type: CompilerEventType }> = {};
22
+ #listenersAll = new Set<http.ServerResponse>();
23
+ #listeners: Partial<Record<CompilerEventType | 'all', Record<string, http.ServerResponse>>> = {};
24
24
  #shutdown = new AbortController();
25
25
  signal = this.#shutdown.signal;
26
26
  info: CompilerServerInfo;
@@ -95,25 +95,43 @@ export class CompilerServer {
95
95
  return output;
96
96
  }
97
97
 
98
- async #addListener(type: string, res: http.ServerResponse): Promise<void> {
98
+ #addListener(type: CompilerEventType | 'all', res: http.ServerResponse): void {
99
99
  res.writeHead(200);
100
100
  const id = `id_${Date.now()}_${Math.random()}`.replace('.', '1');
101
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
102
- this.#listeners[id] = { res, type: type as 'change' };
103
- if (type === 'state') { // Send on initial connect
104
- res.write(JSON.stringify({ state: this.info.state }));
101
+ (this.#listeners[type] ??= {})[id] = res;
102
+ this.#listenersAll.add(res);
103
+ if (type === 'state' || type === 'all') { // Send on initial connect
104
+ this.#emitEvent({ type: 'state', payload: { state: this.info.state } }, id);
105
+ } else {
106
+ res.write('\n'); // Send at least one byte on listen
105
107
  }
106
- res.write('\n'); // Send at least one byte on listen
107
108
 
108
109
  // Do not wait on it
109
- res.on('close', () => { delete this.#listeners[id]; });
110
+ res.on('close', () => {
111
+ delete this.#listeners[type]?.[id];
112
+ this.#listenersAll.delete(res);
113
+ });
110
114
  }
111
115
 
112
- #emitEvent(ev: CompilerEvent): void {
113
- const msg = `${JSON.stringify(ev.payload)}\n`;
114
- for (const el of Object.values(this.#listeners)) {
115
- if (!el.res.closed && el.type === ev.type) {
116
- el.res.write(msg);
116
+ #emitEvent(ev: CompilerEvent, to?: string): void {
117
+ if (this.#listeners.all) {
118
+ const msg = JSON.stringify(ev);
119
+ for (const [id, item] of Object.entries(this.#listeners.all)) {
120
+ if (item.closed || (to && id !== to)) {
121
+ continue;
122
+ }
123
+ item.write(msg);
124
+ item.write('\n');
125
+ }
126
+ }
127
+ if (this.#listeners[ev.type]) {
128
+ const msg = JSON.stringify(ev.payload);
129
+ for (const [id, item] of Object.entries(this.#listeners[ev.type]!)) {
130
+ if (item.closed || (to && id !== to)) {
131
+ continue;
132
+ }
133
+ item.write(msg);
134
+ item.write('\n');
117
135
  }
118
136
  }
119
137
  }
@@ -122,15 +140,16 @@ export class CompilerServer {
122
140
  log.info('Server disconnect requested');
123
141
  this.info.iteration = Date.now();
124
142
  await CommonUtil.blockingTimeout(20);
125
- for (const el of Object.values(this.#listeners)) {
126
- try { el.res.end(); } catch { }
143
+ for (const el of this.#listenersAll) {
144
+ try { el.end(); } catch { }
127
145
  }
128
146
  this.#listeners = {}; // Ensure its empty
147
+ this.#listenersAll.clear();
129
148
  }
130
149
 
131
150
  async #clean(): Promise<{ clean: boolean }> {
132
151
  await Promise.all([this.#ctx.build.compilerFolder, this.#ctx.build.outputFolder]
133
- .map(f => fs.rm(path.resolve(this.#ctx.workspace.path, f), { recursive: true, force: true })));
152
+ .map(f => fs.rm(CommonUtil.resolveWorkspace(this.#ctx, f), { recursive: true, force: true })));
134
153
  return { clean: true };
135
154
  }
136
155
 
@@ -145,7 +164,8 @@ export class CompilerServer {
145
164
  let out: unknown;
146
165
  let close = false;
147
166
  switch (action) {
148
- case 'event': return await this.#addListener(subAction, res);
167
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
168
+ case 'event': return this.#addListener(subAction as 'change', res);
149
169
  case 'clean': out = await this.#clean(); break;
150
170
  case 'stop': out = JSON.stringify({ closing: true }); close = true; break;
151
171
  case 'info':
package/support/setup.ts CHANGED
@@ -1,6 +1,6 @@
1
- import path from 'node:path';
2
1
  import { createRequire } from 'node:module';
3
2
  import fs from 'node:fs/promises';
3
+ import path from 'node:path';
4
4
 
5
5
  import { type DeltaEvent, type ManifestContext, type Package } from '@travetto/manifest';
6
6
 
@@ -27,7 +27,7 @@ export class CompilerSetup {
27
27
  Pick<typeof import('@travetto/manifest'), 'ManifestDeltaUtil' | 'ManifestUtil'>
28
28
  > => {
29
29
  const all = ['util', 'delta'].map(f =>
30
- import(path.resolve(ctx.workspace.path, ctx.build.compilerFolder, 'node_modules', `@travetto/manifest/src/${f}.js`))
30
+ import(CommonUtil.resolveWorkspace(ctx, ctx.build.compilerFolder, 'node_modules', `@travetto/manifest/src/${f}.js`))
31
31
  );
32
32
  return Promise.all(all).then(props => Object.assign({}, ...props));
33
33
  };
@@ -50,11 +50,11 @@ export class CompilerSetup {
50
50
  static async #transpileFile(ctx: ManifestContext, inputFile: string, outputFile: string): Promise<void> {
51
51
  const type = CommonUtil.getFileType(inputFile);
52
52
  if (type === 'js' || type === 'ts') {
53
- const compilerOut = path.resolve(ctx.workspace.path, ctx.build.compilerFolder, 'node_modules');
53
+ const compilerOut = CommonUtil.resolveWorkspace(ctx, ctx.build.compilerFolder, 'node_modules');
54
54
 
55
55
  const text = (await fs.readFile(inputFile, 'utf8'))
56
56
  .replace(/from '([.][^']+)'/g, (_, i) => `from '${i.replace(/[.]js$/, '')}.js'`)
57
- .replace(/from '(@travetto\/(.*?))'/g, (_, i, s) => `from '${path.resolve(compilerOut, `${i}${s.includes('/') ? '.js' : '/__index__.js'}`)}'`);
57
+ .replace(/from '(@travetto\/(.*?))'/g, (_, i, s) => `from '${compilerOut}/${i}${s.includes('/') ? '.js' : '/__index__.js'}'`);
58
58
 
59
59
  const ts = (await import('typescript')).default;
60
60
  const content = ts.transpile(text, {
@@ -92,7 +92,7 @@ export class CompilerSetup {
92
92
  if (file.startsWith('.')) {
93
93
  continue;
94
94
  }
95
- const resolvedInput = path.resolve(sub, file);
95
+ const resolvedInput = path.resolve(sub, file).replaceAll('\\', '/'); // To posix
96
96
  const stat = await fs.stat(resolvedInput);
97
97
 
98
98
  if (stat.isDirectory()) {
@@ -105,14 +105,14 @@ export class CompilerSetup {
105
105
  }
106
106
  }
107
107
 
108
- const outputFolder = path.resolve(ctx.workspace.path, ctx.build.compilerFolder, 'node_modules', module);
108
+ const outputFolder = CommonUtil.resolveWorkspace(ctx, ctx.build.compilerFolder, 'node_modules', module);
109
109
  const out: ModFile[] = [];
110
110
  for (const input of files) {
111
111
  const output = this.#sourceToOutputExt(input.replace(inputFolder, outputFolder));
112
112
  const inputTs = await fs.stat(input).then(RECENT_STAT, () => 0);
113
113
  if (inputTs) {
114
114
  const outputTs = await fs.stat(output).then(RECENT_STAT, () => 0);
115
- await fs.mkdir(path.dirname(output), { recursive: true, });
115
+ await fs.mkdir(path.dirname(output), { recursive: true });
116
116
  out.push({ input, output, stale: inputTs > outputTs });
117
117
  }
118
118
  }
@@ -202,7 +202,7 @@ export class CompilerSetup {
202
202
 
203
203
  if (changes) {
204
204
  await Log.wrap('reset', async log => {
205
- await fs.rm(path.resolve(ctx.workspace.path, ctx.build.outputFolder), { recursive: true, force: true });
205
+ await fs.rm(CommonUtil.resolveWorkspace(ctx, ctx.build.outputFolder), { recursive: true, force: true });
206
206
  log.info('Clearing output due to compiler changes');
207
207
  }, false);
208
208
  }
@@ -1,7 +1,7 @@
1
1
  import fs from 'node:fs/promises';
2
- import path from 'node:path';
3
2
 
4
- import { ManifestContext } from '@travetto/manifest';
3
+ import { type ManifestContext } from '@travetto/manifest';
4
+ import { CommonUtil } from './util';
5
5
 
6
6
  const OPT_CACHE: Record<string, import('typescript').CompilerOptions> = {};
7
7
 
@@ -11,10 +11,10 @@ export class TypescriptUtil {
11
11
  */
12
12
  static async getCompilerOptions(ctx: ManifestContext): Promise<{}> {
13
13
  if (!(ctx.workspace.path in OPT_CACHE)) {
14
- let tsconfig = path.resolve(ctx.workspace.path, 'tsconfig.json');
14
+ let tsconfig = CommonUtil.resolveWorkspace(ctx, 'tsconfig.json');
15
15
 
16
16
  if (!await fs.stat(tsconfig).then(_ => true, _ => false)) {
17
- tsconfig = path.resolve(ctx.workspace.path, ctx.build.compilerModuleFolder, 'tsconfig.trv.json');
17
+ tsconfig = CommonUtil.resolveWorkspace(ctx, ctx.build.compilerModuleFolder, 'tsconfig.trv.json');
18
18
  }
19
19
 
20
20
  const ts = (await import('typescript')).default;
@@ -29,7 +29,7 @@ export class TypescriptUtil {
29
29
  resolveJsonModule: true,
30
30
  sourceRoot: ctx.workspace.path,
31
31
  rootDir: ctx.workspace.path,
32
- outDir: path.resolve(ctx.workspace.path),
32
+ outDir: CommonUtil.resolveWorkspace(ctx),
33
33
  module: ctx.workspace.type === 'commonjs' ? ts.ModuleKind.CommonJS : ts.ModuleKind.ESNext,
34
34
  };
35
35
  }
package/support/util.ts CHANGED
@@ -1,10 +1,15 @@
1
1
  import fs from 'node:fs/promises';
2
- import path from 'node:path';
3
2
  import { setMaxListeners } from 'node:events';
4
3
  import timers from 'node:timers/promises';
4
+ import posix from 'node:path/posix';
5
+ import native from 'node:path';
6
+
7
+ import { type ManifestContext } from '@travetto/manifest';
5
8
 
6
9
  import { Log } from './log';
7
10
 
11
+ const toPosix = (file: string): string => file.replaceAll('\\', '/');
12
+
8
13
  export class CommonUtil {
9
14
  /**
10
15
  * Determine file type
@@ -19,7 +24,7 @@ export class CommonUtil {
19
24
  * Write text file, and ensure folder exists
20
25
  */
21
26
  static writeTextFile = (file: string, content: string): Promise<void> =>
22
- fs.mkdir(path.dirname(file), { recursive: true }).then(() => fs.writeFile(file, content, 'utf8'));
27
+ fs.mkdir(native.dirname(file), { recursive: true }).then(() => fs.writeFile(file, content, 'utf8'));
23
28
 
24
29
  /**
25
30
  * Restartable Event Stream
@@ -92,4 +97,12 @@ export class CommonUtil {
92
97
  static queueMacroTask(): Promise<void> {
93
98
  return timers.setImmediate(undefined);
94
99
  }
100
+
101
+ /**
102
+ * Resolve path for workspace, ensuring posix compliant slashes
103
+ */
104
+ static resolveWorkspace(ctx: ManifestContext, ...args: string[]): string {
105
+ const all = [process.cwd(), ctx.workspace.path, ...args].map(toPosix);
106
+ return process.platform === 'win32' ? toPosix(native.resolve(...all)) : posix.resolve(...all);
107
+ }
95
108
  }
package/tsconfig.trv.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "target": "esnext",
5
5
  "moduleResolution": "Bundler",
6
6
  "lib": [
7
- "es2022"
7
+ "ES2023"
8
8
  ],
9
9
  "jsx": "react-jsx",
10
10
  "strict": true,