ttsc 0.15.2 → 0.15.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.
@@ -236,6 +236,7 @@ interface ProjectResult {
236
236
  }
237
237
 
238
238
  interface ProjectTransformation {
239
+ dependencies?: Record<string, string[]>;
239
240
  result: TtscBuildResult;
240
241
  typescript: Record<string, string>;
241
242
  }
@@ -362,17 +363,20 @@ function createProcessDiagnostic(
362
363
  function toCompilerTransformation(
363
364
  project: ProjectTransformation,
364
365
  ): ITtscCompilerTransformation {
365
- const { result, typescript } = project;
366
+ const { dependencies, result, typescript } = project;
367
+ const dependencyField = dependencies === undefined ? {} : { dependencies };
366
368
  if (result.status === 0 && !hasErrorDiagnostics(result.diagnostics)) {
367
369
  return {
368
370
  ...(result.diagnostics.length === 0
369
371
  ? {}
370
372
  : { diagnostics: result.diagnostics }),
373
+ ...dependencyField,
371
374
  type: "success",
372
375
  typescript,
373
376
  };
374
377
  }
375
378
  return {
379
+ ...dependencyField,
376
380
  diagnostics:
377
381
  result.diagnostics.length === 0
378
382
  ? [createProcessDiagnostic(result)]
@@ -299,7 +299,11 @@ function isRelativeSpecifier(specifier: string): boolean {
299
299
  * commas before handing off to `JSON.parse`.
300
300
  */
301
301
  function parseJsonc(input: string): unknown {
302
- return JSON.parse(stripTrailingCommas(stripComments(input)));
302
+ return JSON.parse(stripTrailingCommas(stripComments(stripLeadingBom(input))));
303
+ }
304
+
305
+ function stripLeadingBom(input: string): string {
306
+ return input.charCodeAt(0) === 0xfeff ? input.slice(1) : input;
303
307
  }
304
308
 
305
309
  /**
@@ -38,6 +38,7 @@ import { outputText, spawnNative } from "./spawnNative";
38
38
  * to their transformed TypeScript source text.
39
39
  */
40
40
  export function transformProjectInMemory(options: ITtscCompilerContext): {
41
+ dependencies?: Record<string, string[]>;
41
42
  result: TtscBuildResult;
42
43
  typescript: Record<string, string>;
43
44
  } {
@@ -70,6 +71,7 @@ function transformProjectWithNativeHost(
70
71
  options: ITtscCompilerContext,
71
72
  project: ITtscParsedProjectConfig,
72
73
  ): {
74
+ dependencies?: Record<string, string[]>;
73
75
  result: TtscBuildResult;
74
76
  typescript: Record<string, string>;
75
77
  } {
@@ -97,6 +99,9 @@ function transformProjectWithNativeHost(
97
99
  outputText(res.stderr),
98
100
  );
99
101
  return {
102
+ ...(output.dependencies === undefined
103
+ ? {}
104
+ : { dependencies: output.dependencies }),
100
105
  result: {
101
106
  diagnostics: output.diagnostics,
102
107
  status: res.status ?? 1,
@@ -112,6 +117,7 @@ function transformProjectWithPlugins(
112
117
  cwd: string,
113
118
  project: ITtscParsedProjectConfig,
114
119
  ): {
120
+ dependencies?: Record<string, string[]>;
115
121
  result: TtscBuildResult;
116
122
  typescript: Record<string, string>;
117
123
  } {
@@ -149,6 +155,9 @@ function transformProjectWithPlugins(
149
155
  if (transformers.length === 0) {
150
156
  const transformed = transformProjectWithNativeHost(options, project);
151
157
  return {
158
+ ...(transformed.dependencies === undefined
159
+ ? {}
160
+ : { dependencies: transformed.dependencies }),
152
161
  result: appendBuildOutput(checked, transformed.result),
153
162
  typescript: transformed.typescript,
154
163
  };
@@ -180,6 +189,9 @@ function transformProjectWithPlugins(
180
189
  stderr: outputText(res.stderr),
181
190
  };
182
191
  return {
192
+ ...(output.dependencies === undefined
193
+ ? {}
194
+ : { dependencies: output.dependencies }),
183
195
  result: appendBuildOutput(checked, result),
184
196
  typescript: output.typescript,
185
197
  };
@@ -312,16 +324,23 @@ function nativePluginEnv(
312
324
  * The `typescript` field must be a `Record<string, string>`. Any other shape is
313
325
  * treated as a protocol error and throws with the stderr/stdout context. JSON
314
326
  * parse errors are also wrapped with the same context message.
327
+ *
328
+ * The optional `dependencies` field (per-file consulted-source lists, see
329
+ * `ITtscCompilerTransformation`) is forwarded when well-formed; entries that
330
+ * are not string arrays are dropped rather than failing the transform — the
331
+ * field is advisory watch metadata, not output.
315
332
  */
316
333
  function parseNativeTransformOutput(
317
334
  stdout: string,
318
335
  stderr: string,
319
336
  ): {
337
+ dependencies?: Record<string, string[]>;
320
338
  diagnostics: ITtscCompilerDiagnostic[];
321
339
  typescript: Record<string, string>;
322
340
  } {
323
341
  try {
324
342
  const parsed = JSON.parse(stdout) as {
343
+ dependencies?: Record<string, string[]>;
325
344
  diagnostics?: ITtscCompilerDiagnostic[];
326
345
  typescript?: Record<string, string>;
327
346
  };
@@ -330,7 +349,9 @@ function parseNativeTransformOutput(
330
349
  "ttsc: native transform host did not return a TypeScript source map",
331
350
  );
332
351
  }
352
+ const dependencies = parseDependencyLists(parsed.dependencies);
333
353
  return {
354
+ ...(dependencies === undefined ? {} : { dependencies }),
334
355
  diagnostics: Array.isArray(parsed.diagnostics) ? parsed.diagnostics : [],
335
356
  typescript: parsed.typescript,
336
357
  };
@@ -345,6 +366,31 @@ function parseNativeTransformOutput(
345
366
  }
346
367
  }
347
368
 
369
+ /**
370
+ * Normalize the optional `dependencies` envelope field into a record of string
371
+ * arrays, or `undefined` when absent or carrying nothing usable.
372
+ */
373
+ function parseDependencyLists(
374
+ value: unknown,
375
+ ): Record<string, string[]> | undefined {
376
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
377
+ return undefined;
378
+ }
379
+ const output: Record<string, string[]> = {};
380
+ for (const [key, entries] of Object.entries(value)) {
381
+ if (!Array.isArray(entries)) {
382
+ continue;
383
+ }
384
+ const files = entries.filter(
385
+ (entry): entry is string => typeof entry === "string",
386
+ );
387
+ if (files.length !== 0) {
388
+ output[key] = files;
389
+ }
390
+ }
391
+ return Object.keys(output).length === 0 ? undefined : output;
392
+ }
393
+
348
394
  /** Type guard: true when `value` is a non-null, non-array object of strings. */
349
395
  function isTextRecord(value: unknown): value is Record<string, string> {
350
396
  return (
@@ -220,10 +220,26 @@ function linkVirtualEntry(
220
220
  }
221
221
  return;
222
222
  }
223
+ if (
224
+ process.platform === "win32" &&
225
+ entry.isSymbolicLink() &&
226
+ isDirectorySymlinkTarget(realEntry)
227
+ ) {
228
+ fs.symlinkSync(realEntry, virtualEntry, "junction");
229
+ return;
230
+ }
223
231
  // Symlinks (and other special entries) are re-symlinked as-is.
224
232
  fs.symlinkSync(realEntry, virtualEntry);
225
233
  }
226
234
 
235
+ function isDirectorySymlinkTarget(realEntry: string): boolean {
236
+ try {
237
+ return fs.statSync(realEntry).isDirectory();
238
+ } catch {
239
+ return false;
240
+ }
241
+ }
242
+
227
243
  /**
228
244
  * Walk from `projectRoot` upward (up to `MAX_VIRTUAL_PARENT_DEPTH` steps),
229
245
  * stopping early at a workspace root (`pnpm-workspace.yaml` or `.git`). The