@travetto/compiler 5.0.2 → 5.0.3
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 +21 -10
- package/bin/trvc.js +1 -1
- package/package.json +4 -5
- package/src/compiler.ts +5 -4
- package/src/state.ts +82 -82
- package/src/types.ts +1 -1
- package/src/util.ts +2 -54
- package/src/watch.ts +2 -2
- package/support/setup.ts +9 -9
- package/support/ts-util.ts +2 -1
- package/tsconfig.trv.json +2 -0
package/bin/common.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
// @ts-check
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import { getManifestContext } from '@travetto/manifest/bin/context.js';
|
|
2
|
+
const { statSync, readFileSync, writeFileSync, mkdirSync, readdirSync, existsSync, rmSync } = require('node:fs');
|
|
3
|
+
const path = require('node:path');
|
|
6
4
|
|
|
7
5
|
/** @typedef {import('@travetto/manifest').ManifestContext} Ctx */
|
|
8
6
|
|
|
@@ -36,13 +34,23 @@ const getTranspiler = async (/** @type {Ctx} */ ctx) => {
|
|
|
36
34
|
.replace(/from '(@travetto\/[^/']+)([/][^']+)?'/g, (_, mod, file) => `from '${modPath(ctx, mod, file)}'`);
|
|
37
35
|
};
|
|
38
36
|
|
|
39
|
-
|
|
40
|
-
async function imp(f = '') { try { return require(f); } catch { return import(f); } }
|
|
41
|
-
|
|
42
|
-
export async function getEntry() {
|
|
37
|
+
async function getEntry() {
|
|
43
38
|
process.setSourceMapsEnabled(true); // Ensure source map during compilation/development
|
|
44
39
|
process.env.NODE_OPTIONS = `${process.env.NODE_OPTIONS ?? ''} --enable-source-maps`; // Ensure it passes to children
|
|
45
40
|
|
|
41
|
+
// Load manifest without compiling, just stripping types away
|
|
42
|
+
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, '');
|
|
49
|
+
|
|
50
|
+
// Load module on demand
|
|
51
|
+
const { getManifestContext } = await import(`data:text/javascript;charset=utf-8,${encodeURIComponent(src)}`);
|
|
52
|
+
|
|
53
|
+
/** @type {Ctx} */
|
|
46
54
|
const ctx = getManifestContext();
|
|
47
55
|
const target = getTarget.bind(null, ctx);
|
|
48
56
|
|
|
@@ -67,9 +75,12 @@ export async function getEntry() {
|
|
|
67
75
|
|
|
68
76
|
// Load
|
|
69
77
|
try {
|
|
70
|
-
|
|
78
|
+
const res = await import(target('support/entry.trvc.ts').dest);
|
|
79
|
+
return await res.main(ctx);
|
|
71
80
|
} catch (err) {
|
|
72
81
|
rmSync(target('.').dest, { recursive: true, force: true });
|
|
73
82
|
throw err;
|
|
74
83
|
}
|
|
75
|
-
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
module.exports = { getEntry };
|
package/bin/trvc.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/compiler",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.3",
|
|
4
4
|
"description": "The compiler infrastructure for the Travetto framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"compiler",
|
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
"email": "travetto.framework@gmail.com",
|
|
14
14
|
"name": "Travetto Framework"
|
|
15
15
|
},
|
|
16
|
-
"type": "module",
|
|
17
16
|
"files": [
|
|
18
17
|
"__index__.ts",
|
|
19
18
|
"src",
|
|
@@ -34,12 +33,12 @@
|
|
|
34
33
|
},
|
|
35
34
|
"dependencies": {
|
|
36
35
|
"@parcel/watcher": "^2.4.1",
|
|
37
|
-
"@travetto/manifest": "^5.0.
|
|
38
|
-
"@travetto/transformer": "^5.0.
|
|
36
|
+
"@travetto/manifest": "^5.0.2",
|
|
37
|
+
"@travetto/transformer": "^5.0.3",
|
|
39
38
|
"@types/node": "^22.5.1"
|
|
40
39
|
},
|
|
41
40
|
"peerDependencies": {
|
|
42
|
-
"@travetto/cli": "^5.0.
|
|
41
|
+
"@travetto/cli": "^5.0.3"
|
|
43
42
|
},
|
|
44
43
|
"peerDependenciesMeta": {
|
|
45
44
|
"@travetto/cli": {
|
package/src/compiler.ts
CHANGED
|
@@ -27,6 +27,7 @@ export class Compiler {
|
|
|
27
27
|
const state = await CompilerState.get(new ManifestIndex());
|
|
28
28
|
log.debug('Running compiler with dirty file', dirty);
|
|
29
29
|
const dirtyFiles = ManifestModuleUtil.getFileType(dirty) === 'ts' ? [dirty] : (await fs.readFile(dirty, 'utf8')).split(/\n/).filter(x => !!x);
|
|
30
|
+
log.debug('Running compiler with dirty file', dirtyFiles);
|
|
30
31
|
await new Compiler(state, dirtyFiles, watch === 'true').run();
|
|
31
32
|
}
|
|
32
33
|
|
|
@@ -41,7 +42,7 @@ export class Compiler {
|
|
|
41
42
|
this.#state = state;
|
|
42
43
|
this.#dirtyFiles = dirtyFiles[0] === '*' ?
|
|
43
44
|
this.#state.getAllFiles() :
|
|
44
|
-
dirtyFiles.map(f => this.#state.getBySource(f)!.
|
|
45
|
+
dirtyFiles.map(f => this.#state.getBySource(f)!.sourceFile);
|
|
45
46
|
this.#watch = watch;
|
|
46
47
|
|
|
47
48
|
this.#ctrl = new AbortController();
|
|
@@ -90,7 +91,7 @@ export class Compiler {
|
|
|
90
91
|
* Compile in a single pass, only emitting dirty files
|
|
91
92
|
*/
|
|
92
93
|
getCompiler(): CompileEmitter {
|
|
93
|
-
return (
|
|
94
|
+
return (sourceFile: string, needsNewProgram?: boolean) => this.#state.compileSourceFile(sourceFile, needsNewProgram);
|
|
94
95
|
}
|
|
95
96
|
|
|
96
97
|
/**
|
|
@@ -165,9 +166,9 @@ export class Compiler {
|
|
|
165
166
|
try {
|
|
166
167
|
for await (const ev of new CompilerWatcher(this.#state, this.#signal).watchChanges()) {
|
|
167
168
|
if (ev.action !== 'delete') {
|
|
168
|
-
const err = await emitter(ev.entry.
|
|
169
|
+
const err = await emitter(ev.entry.sourceFile, true);
|
|
169
170
|
if (err) {
|
|
170
|
-
log.info('Compilation Error', CompilerUtil.buildTranspileError(ev.entry.
|
|
171
|
+
log.info('Compilation Error', CompilerUtil.buildTranspileError(ev.entry.sourceFile, err));
|
|
171
172
|
} else {
|
|
172
173
|
log.info(`Compiled ${ev.entry.sourceFile} on ${ev.action}`);
|
|
173
174
|
}
|
package/src/state.ts
CHANGED
|
@@ -9,16 +9,6 @@ import { CompilerUtil } from './util';
|
|
|
9
9
|
import { CompileEmitError, CompileStateEntry } from './types';
|
|
10
10
|
import { CommonUtil } from '../support/util';
|
|
11
11
|
|
|
12
|
-
function folderMapper(root: string, prefix: string): { dir: string, translate: (val: string) => string } {
|
|
13
|
-
let matched: string = '~~';
|
|
14
|
-
prefix = `/${prefix}`;
|
|
15
|
-
const final = path.resolve(root).replace(/\/[^\/]+/, m => {
|
|
16
|
-
matched = m;
|
|
17
|
-
return prefix;
|
|
18
|
-
});
|
|
19
|
-
return { dir: final, translate: (file: string) => file.replace(prefix, matched) };
|
|
20
|
-
}
|
|
21
|
-
|
|
22
12
|
export class CompilerState implements ts.CompilerHost {
|
|
23
13
|
|
|
24
14
|
static async get(idx: ManifestIndex): Promise<CompilerState> {
|
|
@@ -27,14 +17,12 @@ export class CompilerState implements ts.CompilerHost {
|
|
|
27
17
|
|
|
28
18
|
private constructor() { }
|
|
29
19
|
|
|
30
|
-
#rootDir: string;
|
|
31
|
-
#inputPathToSourcePath: (file: string) => string;
|
|
32
20
|
#outputPath: string;
|
|
33
|
-
#
|
|
34
|
-
#
|
|
35
|
-
#inputToEntry = new Map<string, CompileStateEntry>();
|
|
21
|
+
#sourceFiles = new Set<string>();
|
|
22
|
+
#sourceDirectory = new Map<string, string>();
|
|
36
23
|
#sourceToEntry = new Map<string, CompileStateEntry>();
|
|
37
24
|
#outputToEntry = new Map<string, CompileStateEntry>();
|
|
25
|
+
#tscOutputFileToOuptut = new Map<string, string>();
|
|
38
26
|
|
|
39
27
|
#sourceContents = new Map<string, string | undefined>();
|
|
40
28
|
#sourceFileObjects = new Map<string, ts.SourceFile>();
|
|
@@ -47,18 +35,22 @@ export class CompilerState implements ts.CompilerHost {
|
|
|
47
35
|
#compilerOptions: ts.CompilerOptions;
|
|
48
36
|
#program: ts.Program;
|
|
49
37
|
|
|
50
|
-
#readFile(
|
|
51
|
-
return ts.sys.readFile(this.#
|
|
38
|
+
#readFile(sourceFile: string): string | undefined {
|
|
39
|
+
return ts.sys.readFile(this.#sourceToEntry.get(sourceFile)?.sourceFile ?? sourceFile);
|
|
52
40
|
}
|
|
53
41
|
|
|
54
42
|
async init(idx: ManifestIndex): Promise<this> {
|
|
55
43
|
this.#manifestIndex = idx;
|
|
56
44
|
this.#manifest = idx.manifest;
|
|
57
|
-
const mapper = folderMapper(this.#manifest.workspace.path, '##');
|
|
58
|
-
this.#rootDir = mapper.dir;
|
|
59
|
-
this.#inputPathToSourcePath = mapper.translate;
|
|
60
|
-
|
|
61
45
|
this.#outputPath = path.resolve(this.#manifest.workspace.path, this.#manifest.build.outputFolder);
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
this.#compilerOptions = {
|
|
49
|
+
...await TypescriptUtil.getCompilerOptions(this.#manifest),
|
|
50
|
+
rootDir: this.#manifest.workspace.path,
|
|
51
|
+
outDir: this.#outputPath
|
|
52
|
+
};
|
|
53
|
+
|
|
62
54
|
this.#modules = Object.values(this.#manifest.modules);
|
|
63
55
|
|
|
64
56
|
// Register all inputs
|
|
@@ -74,7 +66,7 @@ export class CompilerState implements ts.CompilerHost {
|
|
|
74
66
|
...base.$package ?? []
|
|
75
67
|
];
|
|
76
68
|
for (const [file, type] of files) {
|
|
77
|
-
if (CompilerUtil.validFile(type)
|
|
69
|
+
if (CompilerUtil.validFile(type)) {
|
|
78
70
|
this.registerInput(x, file);
|
|
79
71
|
}
|
|
80
72
|
}
|
|
@@ -82,12 +74,6 @@ export class CompilerState implements ts.CompilerHost {
|
|
|
82
74
|
|
|
83
75
|
this.#transformerManager = await TransformerManager.create(this.#manifestIndex);
|
|
84
76
|
|
|
85
|
-
this.#compilerOptions = {
|
|
86
|
-
...await TypescriptUtil.getCompilerOptions(this.#manifest),
|
|
87
|
-
rootDir: this.#rootDir,
|
|
88
|
-
outDir: this.#outputPath
|
|
89
|
-
};
|
|
90
|
-
|
|
91
77
|
return this;
|
|
92
78
|
}
|
|
93
79
|
|
|
@@ -108,7 +94,7 @@ export class CompilerState implements ts.CompilerHost {
|
|
|
108
94
|
.filter(x => x.files.src?.length)[0]
|
|
109
95
|
.files.src[0].sourceFile;
|
|
110
96
|
|
|
111
|
-
return this.getBySource(randomSource)!.
|
|
97
|
+
return this.getBySource(randomSource)!.sourceFile;
|
|
112
98
|
}
|
|
113
99
|
|
|
114
100
|
async createProgram(force = false): Promise<ts.Program> {
|
|
@@ -120,19 +106,25 @@ export class CompilerState implements ts.CompilerHost {
|
|
|
120
106
|
return this.#program;
|
|
121
107
|
}
|
|
122
108
|
|
|
123
|
-
async
|
|
109
|
+
async compileSourceFile(sourceFile: string, needsNewProgram = false): Promise<CompileEmitError | undefined> {
|
|
110
|
+
const output = this.#sourceToEntry.get(sourceFile)?.outputFile;
|
|
111
|
+
if (!output) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
124
115
|
const program = await this.createProgram(needsNewProgram);
|
|
125
116
|
try {
|
|
126
|
-
switch (ManifestModuleUtil.getFileType(
|
|
117
|
+
switch (ManifestModuleUtil.getFileType(sourceFile)) {
|
|
118
|
+
case 'typings':
|
|
127
119
|
case 'package-json':
|
|
128
|
-
this.writeFile(
|
|
120
|
+
this.writeFile(output, this.readFile(sourceFile)!, false), undefined;
|
|
129
121
|
break;
|
|
130
122
|
case 'js':
|
|
131
|
-
this.writeFile(
|
|
123
|
+
this.writeFile(output, ts.transpile(this.readFile(sourceFile)!, this.#compilerOptions), false);
|
|
132
124
|
break;
|
|
133
125
|
case 'ts': {
|
|
134
126
|
const result = program.emit(
|
|
135
|
-
program.getSourceFile(
|
|
127
|
+
program.getSourceFile(sourceFile)!,
|
|
136
128
|
(...args) => this.writeFile(...args), undefined, false,
|
|
137
129
|
this.#transformerManager.get()
|
|
138
130
|
);
|
|
@@ -153,78 +145,89 @@ export class CompilerState implements ts.CompilerHost {
|
|
|
153
145
|
}
|
|
154
146
|
|
|
155
147
|
registerInput(module: ManifestModule, moduleFile: string): CompileStateEntry {
|
|
156
|
-
const
|
|
157
|
-
const
|
|
148
|
+
const relativeSource = `${module.sourceFolder || '.'}/${moduleFile}`;
|
|
149
|
+
const relativeOutput = `${module.outputFolder}/${moduleFile}`;
|
|
150
|
+
const sourceFile = path.resolve(this.#manifest.workspace.path, relativeSource);
|
|
158
151
|
const sourceFolder = path.dirname(sourceFile);
|
|
159
|
-
const inputFile = path.resolve(this.#rootDir, relativeInput); // Ensure input is isolated
|
|
160
|
-
const inputFolder = path.dirname(inputFile);
|
|
161
152
|
const fileType = ManifestModuleUtil.getFileType(moduleFile);
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
153
|
+
const isTypings = fileType === 'typings';
|
|
154
|
+
const tscOutputFile = path.resolve(this.#outputPath, ManifestModuleUtil.withOutputExtension(relativeSource));
|
|
155
|
+
const outputFile = path.resolve(this.#outputPath, ManifestModuleUtil.withOutputExtension(relativeOutput));
|
|
165
156
|
|
|
166
|
-
const entry = { sourceFile,
|
|
157
|
+
const entry: CompileStateEntry = { sourceFile, outputFile, module, tscOutputFile };
|
|
167
158
|
|
|
168
|
-
this.#
|
|
159
|
+
this.#outputToEntry.set(outputFile, entry);
|
|
160
|
+
this.#sourceFiles.add(sourceFile);
|
|
161
|
+
this.#sourceHashes.set(sourceFile, -1); // Unknown
|
|
169
162
|
this.#sourceToEntry.set(sourceFile, entry);
|
|
170
|
-
this.#
|
|
163
|
+
this.#sourceDirectory.set(sourceFolder, sourceFolder);
|
|
164
|
+
|
|
165
|
+
this.#tscOutputFileToOuptut.set(tscOutputFile, outputFile);
|
|
166
|
+
this.#tscOutputFileToOuptut.set(`${tscOutputFile}.map`, `${outputFile}.map`);
|
|
171
167
|
|
|
172
|
-
if (
|
|
173
|
-
|
|
168
|
+
if (!isTypings) {
|
|
169
|
+
const srcBase = `${ManifestModuleUtil.withoutSourceExtension(tscOutputFile)}.d.ts`;
|
|
170
|
+
const outBase = `${ManifestModuleUtil.withoutSourceExtension(outputFile)}.d.ts`;
|
|
171
|
+
this.#tscOutputFileToOuptut.set(`${srcBase}.map`, `${outBase}.map`);
|
|
172
|
+
this.#tscOutputFileToOuptut.set(srcBase, outBase);
|
|
174
173
|
}
|
|
175
174
|
|
|
176
|
-
this.#inputFiles.add(inputFile);
|
|
177
|
-
this.#sourceHashes.set(sourceFile, -1); // Unknown
|
|
178
175
|
return entry;
|
|
179
176
|
}
|
|
180
177
|
|
|
181
|
-
checkIfSourceChanged(
|
|
182
|
-
const contents = this.#readFile(
|
|
183
|
-
const prevHash = this.#sourceHashes.get(
|
|
178
|
+
checkIfSourceChanged(sourceFile: string): boolean {
|
|
179
|
+
const contents = this.#readFile(sourceFile);
|
|
180
|
+
const prevHash = this.#sourceHashes.get(sourceFile);
|
|
184
181
|
if (!contents || (contents.length === 0 && prevHash)) {
|
|
185
182
|
return false; // Ignore empty file
|
|
186
183
|
}
|
|
187
184
|
const currentHash = CommonUtil.naiveHash(contents);
|
|
188
185
|
const changed = prevHash !== currentHash;
|
|
189
186
|
if (changed) {
|
|
190
|
-
this.#sourceHashes.set(
|
|
191
|
-
this.#sourceContents.set(
|
|
192
|
-
this.#sourceFileObjects.delete(
|
|
187
|
+
this.#sourceHashes.set(sourceFile, currentHash);
|
|
188
|
+
this.#sourceContents.set(sourceFile, contents);
|
|
189
|
+
this.#sourceFileObjects.delete(sourceFile);
|
|
193
190
|
}
|
|
194
191
|
return changed;
|
|
195
192
|
}
|
|
196
193
|
|
|
197
|
-
|
|
198
|
-
const
|
|
199
|
-
if (outputFile) {
|
|
200
|
-
this.#outputToEntry.delete(outputFile);
|
|
194
|
+
removeSource(sourceFile: string): void {
|
|
195
|
+
const entry = this.#sourceToEntry.get(sourceFile)!;
|
|
196
|
+
if (entry.outputFile) {
|
|
197
|
+
this.#outputToEntry.delete(entry.outputFile);
|
|
201
198
|
}
|
|
202
|
-
|
|
203
|
-
this.#
|
|
204
|
-
this.#
|
|
199
|
+
|
|
200
|
+
this.#sourceFileObjects.delete(sourceFile);
|
|
201
|
+
this.#sourceContents.delete(sourceFile);
|
|
202
|
+
this.#sourceHashes.delete(sourceFile);
|
|
205
203
|
this.#sourceToEntry.delete(sourceFile);
|
|
206
|
-
this.#
|
|
207
|
-
|
|
204
|
+
this.#sourceFiles.delete(sourceFile);
|
|
205
|
+
|
|
206
|
+
const tscOutputDts = `${ManifestModuleUtil.withoutSourceExtension(entry.tscOutputFile)}.d.ts`;
|
|
207
|
+
this.#tscOutputFileToOuptut.delete(entry.tscOutputFile);
|
|
208
|
+
this.#tscOutputFileToOuptut.delete(`${entry.tscOutputFile}.map`);
|
|
209
|
+
this.#tscOutputFileToOuptut.delete(tscOutputDts);
|
|
210
|
+
this.#tscOutputFileToOuptut.delete(`${tscOutputDts}.map`);
|
|
208
211
|
}
|
|
209
212
|
|
|
210
213
|
getAllFiles(): string[] {
|
|
211
|
-
return [...this.#
|
|
214
|
+
return [...this.#sourceFiles];
|
|
212
215
|
}
|
|
213
216
|
|
|
214
217
|
/* Start Compiler Host */
|
|
215
218
|
getCanonicalFileName(file: string): string { return file; }
|
|
216
|
-
getCurrentDirectory(): string { return this.#
|
|
219
|
+
getCurrentDirectory(): string { return this.#manifest.workspace.path; }
|
|
217
220
|
getDefaultLibFileName(opts: ts.CompilerOptions): string { return ts.getDefaultLibFileName(opts); }
|
|
218
221
|
getNewLine(): string { return ts.sys.newLine; }
|
|
219
222
|
useCaseSensitiveFileNames(): boolean { return ts.sys.useCaseSensitiveFileNames; }
|
|
220
223
|
getDefaultLibLocation(): string { return path.dirname(ts.getDefaultLibFilePath(this.#compilerOptions)); }
|
|
221
224
|
|
|
222
|
-
fileExists(
|
|
223
|
-
return this.#
|
|
225
|
+
fileExists(sourceFile: string): boolean {
|
|
226
|
+
return this.#sourceToEntry.has(sourceFile) || ts.sys.fileExists(sourceFile);
|
|
224
227
|
}
|
|
225
228
|
|
|
226
|
-
directoryExists(
|
|
227
|
-
return this.#
|
|
229
|
+
directoryExists(sourceDir: string): boolean {
|
|
230
|
+
return this.#sourceDirectory.has(sourceDir) || ts.sys.directoryExists(sourceDir);
|
|
228
231
|
}
|
|
229
232
|
|
|
230
233
|
writeFile(
|
|
@@ -237,25 +240,22 @@ export class CompilerState implements ts.CompilerHost {
|
|
|
237
240
|
): void {
|
|
238
241
|
if (outputFile.endsWith('package.json')) {
|
|
239
242
|
text = CompilerUtil.rewritePackageJSON(this.#manifest, text);
|
|
240
|
-
} else if (!this.#compilerOptions.inlineSourceMap && this.#compilerOptions.sourceMap && outputFile.endsWith('.map')) {
|
|
241
|
-
text = CompilerUtil.rewriteSourceMap(this.#manifest, text, f => this.#outputToEntry.get(f.replace(/[.]map$/, ''))!);
|
|
242
|
-
} else if (this.#compilerOptions.inlineSourceMap && CompilerUtil.isSourceMapUrlPosData(data)) {
|
|
243
|
-
text = CompilerUtil.rewriteInlineSourceMap(this.#manifest, text, f => this.#outputToEntry.get(f)!, data);
|
|
244
243
|
}
|
|
245
|
-
|
|
244
|
+
const location = this.#tscOutputFileToOuptut.get(outputFile)! ?? outputFile;
|
|
245
|
+
ts.sys.writeFile(location, text, bom);
|
|
246
246
|
}
|
|
247
247
|
|
|
248
|
-
readFile(
|
|
249
|
-
const res = this.#sourceContents.get(
|
|
250
|
-
this.#sourceContents.set(
|
|
248
|
+
readFile(sourceFile: string): string | undefined {
|
|
249
|
+
const res = this.#sourceContents.get(sourceFile) ?? this.#readFile(sourceFile);
|
|
250
|
+
this.#sourceContents.set(sourceFile, res);
|
|
251
251
|
return res;
|
|
252
252
|
}
|
|
253
253
|
|
|
254
|
-
getSourceFile(
|
|
255
|
-
if (!this.#sourceFileObjects.has(
|
|
256
|
-
const content = this.readFile(
|
|
257
|
-
this.#sourceFileObjects.set(
|
|
254
|
+
getSourceFile(sourceFile: string, language: ts.ScriptTarget): ts.SourceFile {
|
|
255
|
+
if (!this.#sourceFileObjects.has(sourceFile)) {
|
|
256
|
+
const content = this.readFile(sourceFile)!;
|
|
257
|
+
this.#sourceFileObjects.set(sourceFile, ts.createSourceFile(sourceFile, content ?? '', language));
|
|
258
258
|
}
|
|
259
|
-
return this.#sourceFileObjects.get(
|
|
259
|
+
return this.#sourceFileObjects.get(sourceFile)!;
|
|
260
260
|
}
|
|
261
261
|
}
|
package/src/types.ts
CHANGED
|
@@ -5,4 +5,4 @@ import type { ManifestModule } from '@travetto/manifest';
|
|
|
5
5
|
export type CompileEmitError = Error | readonly ts.Diagnostic[];
|
|
6
6
|
export type CompileEmitter = (file: string, newProgram?: boolean) => Promise<CompileEmitError | undefined>;
|
|
7
7
|
export type CompileEmitEvent = { file: string, i: number, total: number, err?: CompileEmitError };
|
|
8
|
-
export type CompileStateEntry = { sourceFile: string,
|
|
8
|
+
export type CompileStateEntry = { sourceFile: string, tscOutputFile: string, outputFile?: string, module: ManifestModule };
|
package/src/util.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
type OutputToSource = (outputFile: string) => ({ sourceFile: string } | undefined);
|
|
3
|
+
import { ManifestModuleFileType, ManifestModuleUtil, ManifestRoot, Package } from '@travetto/manifest';
|
|
6
4
|
|
|
7
5
|
const nativeCwd = process.cwd();
|
|
8
6
|
|
|
@@ -14,57 +12,7 @@ export class CompilerUtil {
|
|
|
14
12
|
/**
|
|
15
13
|
* Determine if this is a manifest file we care about
|
|
16
14
|
*/
|
|
17
|
-
static validFile = (type: ManifestModuleFileType): boolean => type === 'ts' || type === 'package-json' || type === 'js';
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Determines if write callback data has sourcemap information
|
|
21
|
-
* @param data
|
|
22
|
-
* @returns
|
|
23
|
-
*/
|
|
24
|
-
static isSourceMapUrlPosData(data?: ts.WriteFileCallbackData): data is { sourceMapUrlPos: number } {
|
|
25
|
-
return data !== undefined && data !== null && typeof data === 'object' && ('sourceMapUrlPos' in data);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Rewrite's sourcemap locations to real folders
|
|
30
|
-
* @returns
|
|
31
|
-
*/
|
|
32
|
-
static rewriteSourceMap(ctx: ManifestContext, text: string, outputToSource: OutputToSource): string {
|
|
33
|
-
const data: { sourceRoot?: string, sources: string[] } = JSON.parse(text);
|
|
34
|
-
const output = ManifestModuleUtil.withOutputExtension(path.resolve(ctx.workspace.path, ctx.build.outputFolder, data.sources[0]));
|
|
35
|
-
const { sourceFile } = outputToSource(output) ?? {};
|
|
36
|
-
|
|
37
|
-
if (sourceFile) {
|
|
38
|
-
delete data.sourceRoot;
|
|
39
|
-
data.sources = [sourceFile];
|
|
40
|
-
text = JSON.stringify(data);
|
|
41
|
-
}
|
|
42
|
-
return text;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Rewrite's inline sourcemap locations to real folders
|
|
47
|
-
* @param text
|
|
48
|
-
* @param outputToSource
|
|
49
|
-
* @param writeData
|
|
50
|
-
* @returns
|
|
51
|
-
*/
|
|
52
|
-
static rewriteInlineSourceMap(
|
|
53
|
-
ctx: ManifestContext,
|
|
54
|
-
text: string,
|
|
55
|
-
outputToSource: OutputToSource,
|
|
56
|
-
{ sourceMapUrlPos }: ts.WriteFileCallbackData & { sourceMapUrlPos: number }
|
|
57
|
-
): string {
|
|
58
|
-
const sourceMapUrl = text.substring(sourceMapUrlPos);
|
|
59
|
-
const [prefix, sourceMapData] = sourceMapUrl.split('base64,');
|
|
60
|
-
const rewritten = this.rewriteSourceMap(ctx, Buffer.from(sourceMapData, 'base64url').toString('utf8'), outputToSource);
|
|
61
|
-
return [
|
|
62
|
-
text.substring(0, sourceMapUrlPos),
|
|
63
|
-
prefix,
|
|
64
|
-
'base64,',
|
|
65
|
-
Buffer.from(rewritten, 'utf8').toString('base64url')
|
|
66
|
-
].join('');
|
|
67
|
-
}
|
|
15
|
+
static validFile = (type: ManifestModuleFileType): boolean => type === 'ts' || type === 'package-json' || type === 'js' || type === 'typings';
|
|
68
16
|
|
|
69
17
|
/**
|
|
70
18
|
* Rewrites the package.json to target output file names, and pins versions
|
package/src/watch.ts
CHANGED
|
@@ -189,10 +189,10 @@ export class CompilerWatcher {
|
|
|
189
189
|
entry = this.#state.registerInput(mod, moduleFile);
|
|
190
190
|
} else if (!entry) {
|
|
191
191
|
continue;
|
|
192
|
-
} else if (action === 'update' && !this.#state.checkIfSourceChanged(entry.
|
|
192
|
+
} else if (action === 'update' && !this.#state.checkIfSourceChanged(entry.sourceFile)) {
|
|
193
193
|
continue;
|
|
194
194
|
} else if (action === 'delete') {
|
|
195
|
-
this.#state.
|
|
195
|
+
this.#state.removeSource(entry.sourceFile);
|
|
196
196
|
}
|
|
197
197
|
|
|
198
198
|
outEvents.push({ action, file: entry.sourceFile, entry });
|
package/support/setup.ts
CHANGED
|
@@ -33,26 +33,26 @@ export class CompilerSetup {
|
|
|
33
33
|
};
|
|
34
34
|
|
|
35
35
|
/** Convert a file to a given ext */
|
|
36
|
-
static #sourceToExtension(
|
|
37
|
-
return
|
|
36
|
+
static #sourceToExtension(sourceFile: string, ext: string): string {
|
|
37
|
+
return sourceFile.replace(/[.][tj]sx?$/, ext);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
41
|
* Get the output file name for a given input
|
|
42
42
|
*/
|
|
43
|
-
static #sourceToOutputExt(
|
|
44
|
-
return this.#sourceToExtension(
|
|
43
|
+
static #sourceToOutputExt(sourceFile: string): string {
|
|
44
|
+
return this.#sourceToExtension(sourceFile, '.js');
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
48
|
* Output a file, support for ts, js, and package.json
|
|
49
49
|
*/
|
|
50
|
-
static async #transpileFile(ctx: ManifestContext,
|
|
51
|
-
const type = CommonUtil.getFileType(
|
|
50
|
+
static async #transpileFile(ctx: ManifestContext, sourceFile: string, outputFile: string): Promise<void> {
|
|
51
|
+
const type = CommonUtil.getFileType(sourceFile);
|
|
52
52
|
if (type === 'js' || type === 'ts') {
|
|
53
53
|
const compilerOut = CommonUtil.resolveWorkspace(ctx, ctx.build.compilerFolder, 'node_modules');
|
|
54
54
|
|
|
55
|
-
const text = (await fs.readFile(
|
|
55
|
+
const text = (await fs.readFile(sourceFile, 'utf8'))
|
|
56
56
|
.replace(/from '([.][^']+)'/g, (_, i) => `from '${i.replace(/[.]js$/, '')}.js'`)
|
|
57
57
|
.replace(/from '(@travetto\/(.*?))'/g, (_, i, s) => `from '${compilerOut}/${i}${s.includes('/') ? '.js' : '/__index__.js'}'`);
|
|
58
58
|
|
|
@@ -61,10 +61,10 @@ export class CompilerSetup {
|
|
|
61
61
|
...await TypescriptUtil.getCompilerOptions(ctx),
|
|
62
62
|
sourceMap: false,
|
|
63
63
|
inlineSourceMap: true,
|
|
64
|
-
},
|
|
64
|
+
}, sourceFile);
|
|
65
65
|
await CommonUtil.writeTextFile(outputFile, content);
|
|
66
66
|
} else if (type === 'package-json') {
|
|
67
|
-
const pkg: Package = JSON.parse(await fs.readFile(
|
|
67
|
+
const pkg: Package = JSON.parse(await fs.readFile(sourceFile, 'utf8'));
|
|
68
68
|
const main = pkg.main ? this.#sourceToOutputExt(pkg.main) : undefined;
|
|
69
69
|
const files = pkg.files?.map(x => this.#sourceToOutputExt(x));
|
|
70
70
|
|
package/support/ts-util.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
|
+
import type { CompilerOptions } from 'typescript';
|
|
2
3
|
|
|
3
4
|
import type { ManifestContext } from '@travetto/manifest';
|
|
4
5
|
import { CommonUtil } from './util';
|
|
5
6
|
|
|
6
|
-
const OPT_CACHE: Record<string,
|
|
7
|
+
const OPT_CACHE: Record<string, CompilerOptions> = {};
|
|
7
8
|
|
|
8
9
|
export class TypescriptUtil {
|
|
9
10
|
/**
|