@ttsc/unplugin 0.8.0 → 0.9.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/LICENSE +21 -0
- package/README.md +17 -16
- package/lib/api.js +13 -18
- package/lib/api.js.map +1 -1
- package/lib/api.mjs +4 -0
- package/lib/api.mjs.map +1 -0
- package/lib/bun.js +13 -12
- package/lib/bun.js.map +1 -1
- package/lib/bun.mjs +31 -0
- package/lib/bun.mjs.map +1 -0
- package/lib/core/index.d.ts +2 -2
- package/lib/core/index.js +28 -18
- package/lib/core/index.js.map +1 -1
- package/lib/core/index.mjs +46 -0
- package/lib/core/index.mjs.map +1 -0
- package/lib/core/options.d.ts +3 -3
- package/lib/core/options.js +5 -5
- package/lib/core/options.js.map +1 -1
- package/lib/core/options.mjs +14 -0
- package/lib/core/options.mjs.map +1 -0
- package/lib/core/transform.d.ts +10 -2
- package/lib/core/transform.js +264 -119
- package/lib/core/transform.js.map +1 -1
- package/lib/core/transform.mjs +446 -0
- package/lib/core/transform.mjs.map +1 -0
- package/lib/esbuild.js +9 -8
- package/lib/esbuild.js.map +1 -1
- package/lib/esbuild.mjs +6 -0
- package/lib/esbuild.mjs.map +1 -0
- package/lib/farm.js +9 -8
- package/lib/farm.js.map +1 -1
- package/lib/farm.mjs +6 -0
- package/lib/farm.mjs.map +1 -0
- package/lib/index.js +10 -8
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +6 -0
- package/lib/index.mjs.map +1 -0
- package/lib/next.js +10 -9
- package/lib/next.js.map +1 -1
- package/lib/next.mjs +18 -0
- package/lib/next.mjs.map +1 -0
- package/lib/rolldown.js +9 -8
- package/lib/rolldown.js.map +1 -1
- package/lib/rolldown.mjs +6 -0
- package/lib/rolldown.mjs.map +1 -0
- package/lib/rollup.js +9 -8
- package/lib/rollup.js.map +1 -1
- package/lib/rollup.mjs +6 -0
- package/lib/rollup.mjs.map +1 -0
- package/lib/rspack.js +9 -8
- package/lib/rspack.js.map +1 -1
- package/lib/rspack.mjs +6 -0
- package/lib/rspack.mjs.map +1 -0
- package/lib/vite.js +9 -8
- package/lib/vite.js.map +1 -1
- package/lib/vite.mjs +6 -0
- package/lib/vite.mjs.map +1 -0
- package/lib/webpack.js +9 -8
- package/lib/webpack.js.map +1 -1
- package/lib/webpack.mjs +6 -0
- package/lib/webpack.mjs.map +1 -0
- package/package.json +30 -18
- package/src/bun.ts +1 -1
- package/src/core/index.ts +16 -4
- package/src/core/options.ts +3 -3
- package/src/core/transform.ts +306 -61
package/src/core/transform.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import * as Diff from "diff-match-patch-es";
|
|
2
1
|
import fs from "node:fs";
|
|
2
|
+
import crypto from "node:crypto";
|
|
3
|
+
import os from "node:os";
|
|
3
4
|
import path from "node:path";
|
|
4
|
-
import MagicString from "magic-string";
|
|
5
5
|
import type {
|
|
6
6
|
ITtscCompilerDiagnostic,
|
|
7
7
|
ITtscCompilerTransformation,
|
|
@@ -21,13 +21,33 @@ export interface TtscTransformAlias {
|
|
|
21
21
|
replacement: string;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
export interface TtscCachedProjectTransform {
|
|
25
|
+
inputHashes: Record<string, string>;
|
|
26
|
+
projectRoot: string;
|
|
27
|
+
result: ITtscCompilerTransformation;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type TtscTransformCache = Map<
|
|
31
|
+
string,
|
|
32
|
+
Promise<TtscCachedProjectTransform>
|
|
33
|
+
>;
|
|
34
|
+
|
|
35
|
+
export function createTtscTransformCache(): TtscTransformCache {
|
|
36
|
+
return new Map();
|
|
37
|
+
}
|
|
38
|
+
|
|
24
39
|
export async function transformTtsc(
|
|
25
40
|
id: string,
|
|
26
41
|
source: string,
|
|
27
42
|
options: ResolvedTtscUnpluginOptions,
|
|
28
43
|
aliases?: unknown,
|
|
44
|
+
cache?: TtscTransformCache,
|
|
29
45
|
): Promise<TtscTransformResult | undefined> {
|
|
30
|
-
const
|
|
46
|
+
const clean = stripQuery(id);
|
|
47
|
+
if (clean.includes("\0")) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
const file = path.resolve(clean);
|
|
31
51
|
if (isDeclarationFile(file)) {
|
|
32
52
|
return undefined;
|
|
33
53
|
}
|
|
@@ -36,28 +56,45 @@ export async function transformTtsc(
|
|
|
36
56
|
const tsconfigDir = path.dirname(tsconfig);
|
|
37
57
|
const baseUrl = resolveBaseUrl(tsconfigDir, options.compilerOptions);
|
|
38
58
|
const aliasPaths = createAliasPaths(baseUrl, aliases);
|
|
39
|
-
const
|
|
59
|
+
const key = createTransformCacheKey({
|
|
40
60
|
aliasPaths,
|
|
41
|
-
baseUrl,
|
|
42
61
|
compilerOptions: options.compilerOptions,
|
|
62
|
+
plugins: options.plugins,
|
|
43
63
|
tsconfig,
|
|
44
64
|
});
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
65
|
+
|
|
66
|
+
let transformed = cache?.get(key);
|
|
67
|
+
if (transformed !== undefined) {
|
|
68
|
+
const cached = await transformed;
|
|
69
|
+
if (matchesCachedSource(cached, file, source)) {
|
|
70
|
+
reportSuccessDiagnostics(cached.result);
|
|
71
|
+
const code = selectTransformedSource({
|
|
72
|
+
file,
|
|
73
|
+
projectRoot: cached.projectRoot,
|
|
74
|
+
result: cached.result,
|
|
75
|
+
});
|
|
76
|
+
return createTransformResult(source, code);
|
|
77
|
+
}
|
|
78
|
+
cache?.delete(key);
|
|
79
|
+
transformed = undefined;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (transformed === undefined) {
|
|
83
|
+
transformed = transformProject({
|
|
84
|
+
aliasPaths,
|
|
85
|
+
baseUrl,
|
|
86
|
+
compilerOptions: options.compilerOptions,
|
|
87
|
+
currentFile: file,
|
|
88
|
+
currentSource: source,
|
|
49
89
|
plugins: options.plugins,
|
|
50
|
-
tsconfig
|
|
51
|
-
}).transform();
|
|
52
|
-
const code = selectTransformedSource({
|
|
53
|
-
file,
|
|
54
|
-
projectRoot: path.dirname(effectiveTsconfig),
|
|
55
|
-
result,
|
|
90
|
+
tsconfig,
|
|
56
91
|
});
|
|
57
|
-
|
|
58
|
-
} finally {
|
|
59
|
-
configured.dispose();
|
|
92
|
+
cache?.set(key, transformed);
|
|
60
93
|
}
|
|
94
|
+
const { projectRoot, result } = await transformed;
|
|
95
|
+
reportSuccessDiagnostics(result);
|
|
96
|
+
const code = selectTransformedSource({ file, projectRoot, result });
|
|
97
|
+
return createTransformResult(source, code);
|
|
61
98
|
}
|
|
62
99
|
|
|
63
100
|
export function stripQuery(id: string): string {
|
|
@@ -75,49 +112,157 @@ export function isDeclarationFile(id: string): boolean {
|
|
|
75
112
|
export function createTransformResult(
|
|
76
113
|
source: string,
|
|
77
114
|
code: string,
|
|
78
|
-
id: string,
|
|
79
115
|
): TtscTransformResult | undefined {
|
|
80
116
|
if (source === code) {
|
|
81
117
|
return undefined;
|
|
82
118
|
}
|
|
119
|
+
return { code };
|
|
120
|
+
}
|
|
83
121
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
122
|
+
function matchesCachedSource(
|
|
123
|
+
cached: TtscCachedProjectTransform,
|
|
124
|
+
file: string,
|
|
125
|
+
source: string,
|
|
126
|
+
): boolean {
|
|
127
|
+
const currentKey = toProjectKey(cached.projectRoot, file);
|
|
128
|
+
const currentHashes = collectProjectInputHashes(cached.projectRoot);
|
|
129
|
+
currentHashes[currentKey] = hashText(source);
|
|
130
|
+
return sameHashes(cached.inputHashes, currentHashes);
|
|
131
|
+
}
|
|
87
132
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
133
|
+
function collectInputHashes(props: {
|
|
134
|
+
currentFile: string;
|
|
135
|
+
currentSource: string;
|
|
136
|
+
projectRoot: string;
|
|
137
|
+
result: ITtscCompilerTransformation;
|
|
138
|
+
}): Record<string, string> {
|
|
139
|
+
const hashes = collectProjectInputHashes(props.projectRoot);
|
|
140
|
+
if (props.result.type !== "exception") {
|
|
141
|
+
for (const key of Object.keys(props.result.typescript)) {
|
|
142
|
+
const file = path.resolve(props.projectRoot, key);
|
|
143
|
+
try {
|
|
144
|
+
hashes[key] = hashText(fs.readFileSync(file, "utf8"));
|
|
145
|
+
} catch {
|
|
146
|
+
// A plugin may synthesize a virtual TypeScript file. It should not
|
|
147
|
+
// decide cache reuse for real source files.
|
|
148
|
+
}
|
|
94
149
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
150
|
+
}
|
|
151
|
+
hashes[toProjectKey(props.projectRoot, props.currentFile)] = hashText(
|
|
152
|
+
props.currentSource,
|
|
153
|
+
);
|
|
154
|
+
return hashes;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function collectProjectInputHashes(
|
|
158
|
+
projectRoot: string,
|
|
159
|
+
): Record<string, string> {
|
|
160
|
+
const hashes: Record<string, string> = {};
|
|
161
|
+
for (const file of listProjectInputFiles(projectRoot)) {
|
|
162
|
+
try {
|
|
163
|
+
hashes[toProjectKey(projectRoot, file)] = hashText(fs.readFileSync(file));
|
|
164
|
+
} catch {
|
|
165
|
+
// File watchers may observe a transform while another process is moving
|
|
166
|
+
// or deleting files. The missing key invalidates older cache entries.
|
|
98
167
|
}
|
|
168
|
+
}
|
|
169
|
+
return hashes;
|
|
170
|
+
}
|
|
99
171
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
172
|
+
function listProjectInputFiles(root: string): string[] {
|
|
173
|
+
const out: string[] = [];
|
|
174
|
+
const stack = [root];
|
|
175
|
+
while (stack.length !== 0) {
|
|
176
|
+
const current = stack.pop()!;
|
|
177
|
+
let entries: fs.Dirent[];
|
|
178
|
+
try {
|
|
179
|
+
entries = fs.readdirSync(current, { withFileTypes: true });
|
|
180
|
+
} catch {
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
for (const entry of entries) {
|
|
184
|
+
if (isIgnoredProjectDirectory(entry.name)) {
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
const file = path.join(current, entry.name);
|
|
188
|
+
if (entry.isDirectory()) {
|
|
189
|
+
stack.push(file);
|
|
190
|
+
} else if (entry.isFile()) {
|
|
191
|
+
out.push(file);
|
|
192
|
+
}
|
|
106
193
|
}
|
|
107
|
-
offset += text.length;
|
|
108
194
|
}
|
|
195
|
+
out.sort();
|
|
196
|
+
return out;
|
|
197
|
+
}
|
|
109
198
|
|
|
110
|
-
|
|
111
|
-
|
|
199
|
+
function isIgnoredProjectDirectory(name: string): boolean {
|
|
200
|
+
return (
|
|
201
|
+
name === ".git" ||
|
|
202
|
+
name === ".ttsc" ||
|
|
203
|
+
name === ".cache" ||
|
|
204
|
+
name === ".next" ||
|
|
205
|
+
name === ".nuxt" ||
|
|
206
|
+
name === ".svelte-kit" ||
|
|
207
|
+
name === ".turbo" ||
|
|
208
|
+
name === ".vite" ||
|
|
209
|
+
name === "build" ||
|
|
210
|
+
name === "coverage" ||
|
|
211
|
+
name === "dist" ||
|
|
212
|
+
name === "node_modules" ||
|
|
213
|
+
name === "out" ||
|
|
214
|
+
name === "temp" ||
|
|
215
|
+
name === "tmp"
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function sameHashes(
|
|
220
|
+
left: Record<string, string>,
|
|
221
|
+
right: Record<string, string>,
|
|
222
|
+
): boolean {
|
|
223
|
+
const leftKeys = Object.keys(left);
|
|
224
|
+
const rightKeys = Object.keys(right);
|
|
225
|
+
if (leftKeys.length !== rightKeys.length) {
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
return leftKeys.every((key) => right[key] === left[key]);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function hashText(input: string | Buffer): string {
|
|
232
|
+
return crypto.createHash("sha256").update(input).digest("hex");
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
async function transformProject(props: {
|
|
236
|
+
aliasPaths: Record<string, string[]>;
|
|
237
|
+
baseUrl: string;
|
|
238
|
+
compilerOptions: Record<string, unknown>;
|
|
239
|
+
currentFile: string;
|
|
240
|
+
currentSource: string;
|
|
241
|
+
plugins?: ResolvedTtscUnpluginOptions["plugins"];
|
|
242
|
+
tsconfig: string;
|
|
243
|
+
}): Promise<TtscCachedProjectTransform> {
|
|
244
|
+
const configured = createTransformTsconfig(props);
|
|
245
|
+
const projectRoot = path.dirname(props.tsconfig);
|
|
246
|
+
try {
|
|
247
|
+
const result = new TtscCompiler({
|
|
248
|
+
cwd: projectRoot,
|
|
249
|
+
plugins: props.plugins,
|
|
250
|
+
projectRoot,
|
|
251
|
+
tsconfig: configured.path,
|
|
252
|
+
}).transform();
|
|
253
|
+
return {
|
|
254
|
+
inputHashes: collectInputHashes({
|
|
255
|
+
currentFile: props.currentFile,
|
|
256
|
+
currentSource: props.currentSource,
|
|
257
|
+
projectRoot,
|
|
258
|
+
result,
|
|
259
|
+
}),
|
|
260
|
+
projectRoot,
|
|
261
|
+
result,
|
|
262
|
+
};
|
|
263
|
+
} finally {
|
|
264
|
+
configured.dispose();
|
|
112
265
|
}
|
|
113
|
-
return {
|
|
114
|
-
code: magic.toString(),
|
|
115
|
-
map: magic.generateMap({
|
|
116
|
-
file: `${id}.map`,
|
|
117
|
-
includeContent: true,
|
|
118
|
-
source: id,
|
|
119
|
-
}),
|
|
120
|
-
};
|
|
121
266
|
}
|
|
122
267
|
|
|
123
268
|
function createTransformTsconfig(props: {
|
|
@@ -126,10 +271,13 @@ function createTransformTsconfig(props: {
|
|
|
126
271
|
compilerOptions: Record<string, unknown>;
|
|
127
272
|
tsconfig: string;
|
|
128
273
|
}): { path: string; dispose: () => void } {
|
|
129
|
-
const compilerOptions =
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
274
|
+
const compilerOptions = normalizeCompilerOptionsForGeneratedTsconfig(
|
|
275
|
+
{
|
|
276
|
+
...props.compilerOptions,
|
|
277
|
+
...createAliasCompilerOptions(props),
|
|
278
|
+
},
|
|
279
|
+
path.dirname(props.tsconfig),
|
|
280
|
+
);
|
|
133
281
|
if (Object.keys(compilerOptions).length === 0) {
|
|
134
282
|
return {
|
|
135
283
|
path: props.tsconfig,
|
|
@@ -137,18 +285,13 @@ function createTransformTsconfig(props: {
|
|
|
137
285
|
};
|
|
138
286
|
}
|
|
139
287
|
|
|
140
|
-
const directory = path.
|
|
141
|
-
const file = path.join(
|
|
142
|
-
directory,
|
|
143
|
-
`.ttsc-unplugin-${process.pid}-${Date.now()}-${Math.random()
|
|
144
|
-
.toString(36)
|
|
145
|
-
.slice(2)}.json`,
|
|
146
|
-
);
|
|
288
|
+
const directory = fs.mkdtempSync(path.join(os.tmpdir(), "ttsc-unplugin-"));
|
|
289
|
+
const file = path.join(directory, "tsconfig.json");
|
|
147
290
|
fs.writeFileSync(
|
|
148
291
|
file,
|
|
149
292
|
JSON.stringify(
|
|
150
293
|
{
|
|
151
|
-
extends:
|
|
294
|
+
extends: normalizePath(props.tsconfig),
|
|
152
295
|
compilerOptions,
|
|
153
296
|
},
|
|
154
297
|
null,
|
|
@@ -158,10 +301,55 @@ function createTransformTsconfig(props: {
|
|
|
158
301
|
);
|
|
159
302
|
return {
|
|
160
303
|
path: file,
|
|
161
|
-
dispose: () => fs.rmSync(
|
|
304
|
+
dispose: () => fs.rmSync(directory, { force: true, recursive: true }),
|
|
162
305
|
};
|
|
163
306
|
}
|
|
164
307
|
|
|
308
|
+
function normalizeCompilerOptionsForGeneratedTsconfig(
|
|
309
|
+
compilerOptions: Record<string, unknown>,
|
|
310
|
+
tsconfigDir: string,
|
|
311
|
+
): Record<string, unknown> {
|
|
312
|
+
const output = { ...compilerOptions };
|
|
313
|
+
for (const key of ["baseUrl", "declarationDir", "outDir", "rootDir"]) {
|
|
314
|
+
if (typeof output[key] === "string") {
|
|
315
|
+
output[key] = path.resolve(tsconfigDir, output[key]);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
for (const key of ["rootDirs", "typeRoots"]) {
|
|
319
|
+
if (Array.isArray(output[key])) {
|
|
320
|
+
output[key] = output[key].map((entry) =>
|
|
321
|
+
typeof entry === "string" ? path.resolve(tsconfigDir, entry) : entry,
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
if (hasPaths(output.paths) && typeof output.baseUrl !== "string") {
|
|
326
|
+
output.baseUrl = tsconfigDir;
|
|
327
|
+
}
|
|
328
|
+
if (Array.isArray(output.plugins)) {
|
|
329
|
+
output.plugins = output.plugins.map((entry) =>
|
|
330
|
+
normalizePluginConfigForGeneratedTsconfig(entry, tsconfigDir),
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
return output;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
function normalizePluginConfigForGeneratedTsconfig(
|
|
337
|
+
entry: unknown,
|
|
338
|
+
tsconfigDir: string,
|
|
339
|
+
): unknown {
|
|
340
|
+
if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
|
|
341
|
+
return entry;
|
|
342
|
+
}
|
|
343
|
+
const output: Record<string, unknown> = { ...entry };
|
|
344
|
+
for (const key of ["config", "source", "transform"]) {
|
|
345
|
+
const value = output[key];
|
|
346
|
+
if (typeof value === "string" && isRelativeSpecifier(value)) {
|
|
347
|
+
output[key] = path.resolve(tsconfigDir, value);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
return output;
|
|
351
|
+
}
|
|
352
|
+
|
|
165
353
|
function createAliasCompilerOptions(props: {
|
|
166
354
|
aliasPaths: Record<string, string[]>;
|
|
167
355
|
baseUrl: string;
|
|
@@ -179,6 +367,15 @@ function createAliasCompilerOptions(props: {
|
|
|
179
367
|
};
|
|
180
368
|
}
|
|
181
369
|
|
|
370
|
+
function hasPaths(value: unknown): boolean {
|
|
371
|
+
return (
|
|
372
|
+
typeof value === "object" &&
|
|
373
|
+
value !== null &&
|
|
374
|
+
!Array.isArray(value) &&
|
|
375
|
+
Object.keys(value).length !== 0
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
|
|
182
379
|
function readPaths(value: unknown): Record<string, string[]> {
|
|
183
380
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
184
381
|
return {};
|
|
@@ -256,6 +453,44 @@ function normalizeAliases(aliases: unknown): TtscTransformAlias[] {
|
|
|
256
453
|
return [];
|
|
257
454
|
}
|
|
258
455
|
|
|
456
|
+
function createTransformCacheKey(props: {
|
|
457
|
+
aliasPaths: Record<string, string[]>;
|
|
458
|
+
compilerOptions: Record<string, unknown>;
|
|
459
|
+
plugins?: ResolvedTtscUnpluginOptions["plugins"];
|
|
460
|
+
tsconfig: string;
|
|
461
|
+
}): string {
|
|
462
|
+
return stableStringify({
|
|
463
|
+
aliasPaths: props.aliasPaths,
|
|
464
|
+
compilerOptions: props.compilerOptions,
|
|
465
|
+
plugins: props.plugins,
|
|
466
|
+
tsconfig: path.resolve(props.tsconfig),
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
function stableStringify(value: unknown): string {
|
|
471
|
+
if (Array.isArray(value)) {
|
|
472
|
+
return `[${value.map(stableStringify).join(",")}]`;
|
|
473
|
+
}
|
|
474
|
+
if (value && typeof value === "object") {
|
|
475
|
+
return `{${Object.entries(value)
|
|
476
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
477
|
+
.map(([key, item]) => `${JSON.stringify(key)}:${stableStringify(item)}`)
|
|
478
|
+
.join(",")}}`;
|
|
479
|
+
}
|
|
480
|
+
return JSON.stringify(value);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
function isRelativeSpecifier(value: string): boolean {
|
|
484
|
+
return (
|
|
485
|
+
value === "." ||
|
|
486
|
+
value === ".." ||
|
|
487
|
+
value.startsWith("./") ||
|
|
488
|
+
value.startsWith("../") ||
|
|
489
|
+
value.startsWith(".\\") ||
|
|
490
|
+
value.startsWith("..\\")
|
|
491
|
+
);
|
|
492
|
+
}
|
|
493
|
+
|
|
259
494
|
function isAlias(value: unknown): value is TtscTransformAlias {
|
|
260
495
|
return (
|
|
261
496
|
typeof value === "object" &&
|
|
@@ -292,6 +527,16 @@ function selectTransformedSource(props: {
|
|
|
292
527
|
throw new Error(`ttsc transform did not return output for ${props.file}`);
|
|
293
528
|
}
|
|
294
529
|
|
|
530
|
+
function reportSuccessDiagnostics(result: ITtscCompilerTransformation): void {
|
|
531
|
+
if (result.type !== "success" || result.diagnostics === undefined) {
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
const text = formatDiagnostics(result.diagnostics);
|
|
535
|
+
if (text.length !== 0) {
|
|
536
|
+
process.stderr.write(`${text}\n`);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
|
|
295
540
|
function formatDiagnostics(diagnostics: ITtscCompilerDiagnostic[]): string {
|
|
296
541
|
if (diagnostics.length === 0) {
|
|
297
542
|
return "ttsc transform failed";
|