@travetto/compiler 5.0.4 → 5.0.5

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
@@ -13,11 +13,14 @@ const modPath = (/** @type {Ctx} */ ctx, mod, file) => {
13
13
  return `${base}${file.includes('.') ? '' : file.includes('/') ? '.ts' : '/__index__.ts'}`.replace(TS_EXT, '.js');
14
14
  };
15
15
 
16
+ const needsWriting = (/** @type {string} */ src, /** @type {string} */ dest) =>
17
+ !existsSync(dest) || getAge(statSync(dest)) < getAge(statSync(src));
18
+
16
19
  const getTarget = (/** @type {Ctx} */ ctx, file = '') => ({
17
20
  dest: modPath(ctx, '@travetto/compiler', file),
18
21
  src: path.resolve(ctx.workspace.path, ctx.build.compilerModuleFolder, file),
19
22
  async writeIfStale(/** @type {(text:string)=>(string|Promise<string>)}*/ transform) {
20
- if (!existsSync(this.dest) || getAge(statSync(this.dest)) < getAge(statSync(this.src))) {
23
+ if (needsWriting(this.src, this.dest)) {
21
24
  const text = readFileSync(this.src, 'utf8');
22
25
  mkdirSync(path.dirname(this.dest), { recursive: true });
23
26
  writeFileSync(this.dest, await transform(text), 'utf8');
@@ -38,17 +41,23 @@ async function getEntry() {
38
41
  process.setSourceMapsEnabled(true); // Ensure source map during compilation/development
39
42
  process.env.NODE_OPTIONS = `${process.env.NODE_OPTIONS ?? ''} --enable-source-maps`; // Ensure it passes to children
40
43
 
41
- // Load manifest without compiling, just stripping types away
44
+ // eslint-disable-next-line no-undef
45
+ const manifestJs = path.resolve(__dirname, 'manifest-context.mjs');
42
46
  const loc = require.resolve('@travetto/manifest').replace(/__index__.*/, 'src/context.ts');
43
- const src = readFileSync(loc, 'utf8')
44
- // Remove type information
45
- .replace(/\s*[|]\s+undefined/g, '')
46
- .replace(/<([^>]|\n)+>/gsm, '')
47
- .replace(/[?]?: (string|[A-Z][a-zA-Z]+)/g, '')
48
- .replace(/^(import )?type .*$/gm, '');
47
+
48
+ // Compile if needed
49
+ if (needsWriting(loc, manifestJs)) {
50
+ const ts = (await import('typescript')).default;
51
+ const text = ts.transpile(readFileSync(loc, 'utf8'), {
52
+ target: ts.ScriptTarget.ES2022,
53
+ module: ts.ModuleKind.ESNext,
54
+ removeComments: true
55
+ }, manifestJs);
56
+ writeFileSync(manifestJs, text, 'utf8');
57
+ }
49
58
 
50
59
  // Load module on demand
51
- const { getManifestContext } = await import(`data:text/javascript;charset=utf-8,${encodeURIComponent(src)}`);
60
+ const { getManifestContext } = await import(manifestJs);
52
61
 
53
62
  /** @type {Ctx} */
54
63
  const ctx = getManifestContext();
@@ -75,6 +84,7 @@ async function getEntry() {
75
84
 
76
85
  // Load
77
86
  try {
87
+ /** @type {import('../support/entry.trvc')} */
78
88
  const res = await import(target('support/entry.trvc.ts').dest);
79
89
  return await res.main(ctx);
80
90
  } catch (err) {
@@ -83,4 +93,5 @@ async function getEntry() {
83
93
  }
84
94
  }
85
95
 
96
+ // eslint-disable-next-line no-undef
86
97
  module.exports = { getEntry };
@@ -0,0 +1,121 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { createRequire } from 'node:module';
4
+ const TOOL_FOLDER = '.trv/tool';
5
+ const COMPILER_FOLDER = '.trv/compiler';
6
+ const OUTPUT_FOLDER = '.trv/output';
7
+ const TYPES_FOLDER = '.trv/types';
8
+ const WS_ROOT = {};
9
+ function readPackage(dir) {
10
+ dir = dir.endsWith('.json') ? path.dirname(dir) : dir;
11
+ try {
12
+ const v = readFileSync(path.resolve(dir, 'package.json'), 'utf8');
13
+ return ({ ...JSON.parse(v), path: path.resolve(dir) });
14
+ }
15
+ catch { }
16
+ }
17
+ function findPackage(dir) {
18
+ let prev;
19
+ let pkg, curr = path.resolve(dir);
20
+ while (!pkg && curr !== prev) {
21
+ pkg = readPackage(curr);
22
+ [prev, curr] = [curr, path.dirname(curr)];
23
+ }
24
+ if (!pkg) {
25
+ throw new Error('Could not find a package.json');
26
+ }
27
+ else {
28
+ return pkg;
29
+ }
30
+ }
31
+ function resolveWorkspace(base = process.cwd()) {
32
+ if (base in WS_ROOT) {
33
+ return WS_ROOT[base];
34
+ }
35
+ let folder = base;
36
+ let prev;
37
+ let prevPkg, pkg;
38
+ while (prev !== folder) {
39
+ [prev, prevPkg] = [folder, pkg];
40
+ pkg = readPackage(folder) ?? pkg;
41
+ if ((pkg && (!!pkg.workspaces || !!pkg.travetto?.build?.isolated)) ||
42
+ existsSync(path.resolve(folder, '.git'))) {
43
+ break;
44
+ }
45
+ folder = path.dirname(folder);
46
+ }
47
+ if (!pkg) {
48
+ throw new Error('Could not find a package.json');
49
+ }
50
+ return WS_ROOT[base] = {
51
+ ...pkg,
52
+ name: pkg.name ?? 'untitled',
53
+ type: pkg.type,
54
+ manager: existsSync(path.resolve(pkg.path, 'yarn.lock')) ? 'yarn' : 'npm',
55
+ resolve: createRequire(`${pkg.path}/node_modules`).resolve.bind(null),
56
+ stripRoot: (full) => full === pkg.path ? '' : full.replace(`${pkg.path}/`, ''),
57
+ mono: !!pkg.workspaces || (!pkg.travetto?.build?.isolated && !!prevPkg)
58
+ };
59
+ }
60
+ function getCompilerUrl(ws) {
61
+ const port = (Math.abs([...ws.path].reduce((a, b) => (a * 33) ^ b.charCodeAt(0), 5381)) % 29000) + 20000;
62
+ return `http://localhost:${port}`;
63
+ }
64
+ function resolveModule(workspace, folder) {
65
+ let mod;
66
+ if (!folder && process.env.TRV_MODULE) {
67
+ mod = process.env.TRV_MODULE;
68
+ if (/[.][cm]?(t|j)sx?$/.test(mod)) {
69
+ try {
70
+ process.env.TRV_MODULE = mod = findPackage(path.dirname(mod)).name;
71
+ }
72
+ catch {
73
+ process.env.TRV_MODULE = mod = '';
74
+ }
75
+ }
76
+ }
77
+ if (mod) {
78
+ try {
79
+ folder = path.dirname(workspace.resolve(`${mod}/package.json`));
80
+ }
81
+ catch {
82
+ const workspacePkg = readPackage(workspace.path);
83
+ if (workspacePkg?.name === mod) {
84
+ folder = workspace.path;
85
+ }
86
+ else {
87
+ throw new Error(`Unable to resolve location for ${folder}`);
88
+ }
89
+ }
90
+ }
91
+ return findPackage(folder ?? '.');
92
+ }
93
+ export function getManifestContext(folder) {
94
+ const workspace = resolveWorkspace();
95
+ const mod = resolveModule(workspace, folder);
96
+ const build = workspace.travetto?.build ?? {};
97
+ return {
98
+ workspace: {
99
+ name: workspace.name,
100
+ path: workspace.path,
101
+ mono: workspace.mono,
102
+ manager: workspace.manager,
103
+ type: workspace.type ?? 'commonjs',
104
+ defaultEnv: workspace.travetto?.defaultEnv ?? 'local'
105
+ },
106
+ build: {
107
+ compilerFolder: build.compilerFolder ?? COMPILER_FOLDER,
108
+ compilerUrl: build.compilerUrl ?? getCompilerUrl(workspace),
109
+ compilerModuleFolder: workspace.stripRoot(path.dirname(workspace.resolve('@travetto/compiler/package.json'))),
110
+ outputFolder: build.outputFolder ?? OUTPUT_FOLDER,
111
+ toolFolder: build.toolFolder ?? TOOL_FOLDER,
112
+ typesFolder: build.typesFolder ?? TYPES_FOLDER
113
+ },
114
+ main: {
115
+ name: mod.name ?? 'untitled',
116
+ folder: workspace.stripRoot(mod.path),
117
+ version: mod.version,
118
+ description: mod.description
119
+ }
120
+ };
121
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/compiler",
3
- "version": "5.0.4",
3
+ "version": "5.0.5",
4
4
  "description": "The compiler infrastructure for the Travetto framework",
5
5
  "keywords": [
6
6
  "compiler",
@@ -33,12 +33,12 @@
33
33
  },
34
34
  "dependencies": {
35
35
  "@parcel/watcher": "^2.4.1",
36
- "@travetto/manifest": "^5.0.3",
37
- "@travetto/transformer": "^5.0.4",
36
+ "@travetto/manifest": "^5.0.4",
37
+ "@travetto/transformer": "^5.0.5",
38
38
  "@types/node": "^22.5.1"
39
39
  },
40
40
  "peerDependencies": {
41
- "@travetto/cli": "^5.0.4"
41
+ "@travetto/cli": "^5.0.5"
42
42
  },
43
43
  "peerDependenciesMeta": {
44
44
  "@travetto/cli": {
package/src/state.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import ts from 'typescript';
2
2
 
3
- import { path, ManifestModuleUtil, type ManifestModule, type ManifestRoot, ManifestIndex } from '@travetto/manifest';
3
+ import { path, ManifestModuleUtil, type ManifestModule, type ManifestRoot, ManifestIndex, ManifestModuleFolderType } from '@travetto/manifest';
4
4
  import { TransformerManager } from '@travetto/transformer';
5
5
 
6
6
  import { TypescriptUtil } from '../support/ts-util';
@@ -9,6 +9,9 @@ import { CompilerUtil } from './util';
9
9
  import { CompileEmitError, CompileStateEntry } from './types';
10
10
  import { CommonUtil } from '../support/util';
11
11
 
12
+ const TYPINGS_FOLDER_KEYS = new Set<ManifestModuleFolderType>(['$index', 'support', 'src']);
13
+ const TYPINGS_EXT_RE = /[.]d[.][cm]?ts([.]map)?$/;
14
+
12
15
  export class CompilerState implements ts.CompilerHost {
13
16
 
14
17
  static async get(idx: ManifestIndex): Promise<CompilerState> {
@@ -18,6 +21,7 @@ export class CompilerState implements ts.CompilerHost {
18
21
  private constructor() { }
19
22
 
20
23
  #outputPath: string;
24
+ #typingsPath: string;
21
25
  #sourceFiles = new Set<string>();
22
26
  #sourceDirectory = new Map<string, string>();
23
27
  #sourceToEntry = new Map<string, CompileStateEntry>();
@@ -39,11 +43,25 @@ export class CompilerState implements ts.CompilerHost {
39
43
  return ts.sys.readFile(this.#sourceToEntry.get(sourceFile)?.sourceFile ?? sourceFile);
40
44
  }
41
45
 
46
+ #writeExternalTypings(location: string, text: string, bom: boolean): void {
47
+ let core = location.replace('.map', '');
48
+ if (!this.#outputToEntry.has(core)) {
49
+ core = core.replace('.d.ts', '.js');
50
+ }
51
+ const entry = this.#outputToEntry.get(core);
52
+ if (entry) {
53
+ const relative = this.#manifestIndex.getFromSource(entry.sourceFile)?.relativeFile;
54
+ if (relative && TYPINGS_FOLDER_KEYS.has(ManifestModuleUtil.getFolderKey(relative))) {
55
+ ts.sys.writeFile(location.replace(this.#outputPath, this.#typingsPath), text, bom);
56
+ }
57
+ }
58
+ }
59
+
42
60
  async init(idx: ManifestIndex): Promise<this> {
43
61
  this.#manifestIndex = idx;
44
62
  this.#manifest = idx.manifest;
45
63
  this.#outputPath = path.resolve(this.#manifest.workspace.path, this.#manifest.build.outputFolder);
46
-
64
+ this.#typingsPath = path.resolve(this.#manifest.workspace.path, this.#manifest.build.typesFolder);
47
65
 
48
66
  this.#compilerOptions = {
49
67
  ...await TypescriptUtil.getCompilerOptions(this.#manifest),
@@ -241,7 +259,12 @@ export class CompilerState implements ts.CompilerHost {
241
259
  if (outputFile.endsWith('package.json')) {
242
260
  text = CompilerUtil.rewritePackageJSON(this.#manifest, text);
243
261
  }
244
- const location = this.#tscOutputFileToOuptut.get(outputFile)! ?? outputFile;
262
+ const location = this.#tscOutputFileToOuptut.get(outputFile) ?? outputFile;
263
+
264
+ if (TYPINGS_EXT_RE.test(outputFile)) {
265
+ this.#writeExternalTypings(location, text, bom);
266
+ }
267
+
245
268
  ts.sys.writeFile(location, text, bom);
246
269
  }
247
270
 
@@ -15,7 +15,7 @@ import { CommonUtil } from './util';
15
15
  // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
16
16
  export const main = (ctx: ManifestContext) => {
17
17
  const client = new CompilerClient(ctx, Log.scoped('client'));
18
- const buildFolders = [ctx.build.outputFolder, ctx.build.compilerFolder];
18
+ const buildFolders = [ctx.build.outputFolder, ctx.build.compilerFolder, ctx.build.typesFolder];
19
19
  Log.root = ctx.workspace.path;
20
20
  Log.initLevel('error');
21
21