@esportsplus/typescript 0.29.6 → 0.31.1

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.
Files changed (129) hide show
  1. package/README.md +97 -3
  2. package/bin/tsc-alias +1 -1
  3. package/bin/tsc-lsp +3 -0
  4. package/build/cli/diagnostics.d.ts +8 -0
  5. package/build/cli/diagnostics.js +95 -0
  6. package/build/cli/tsc.d.ts +12 -2
  7. package/build/cli/tsc.js +343 -52
  8. package/build/compiler/ast.d.ts +7 -5
  9. package/build/compiler/ast.js +6 -6
  10. package/build/compiler/code.d.ts +5 -4
  11. package/build/compiler/code.js +12 -1
  12. package/build/compiler/coordinator.d.ts +16 -7
  13. package/build/compiler/coordinator.js +75 -41
  14. package/build/compiler/imports.d.ts +8 -3
  15. package/build/compiler/imports.js +34 -24
  16. package/build/compiler/index.d.ts +3 -0
  17. package/build/compiler/index.js +1 -0
  18. package/build/compiler/language-service.d.ts +36 -6
  19. package/build/compiler/language-service.js +252 -58
  20. package/build/compiler/plugins/index.d.ts +4 -2
  21. package/build/compiler/plugins/tsc.d.ts +1 -1
  22. package/build/compiler/plugins/vite.d.ts +6 -3
  23. package/build/compiler/plugins/vite.js +15 -8
  24. package/build/compiler/sourcemap.d.ts +52 -0
  25. package/build/compiler/sourcemap.js +265 -0
  26. package/build/compiler/types.d.ts +7 -6
  27. package/build/compiler/uid.d.ts +5 -2
  28. package/build/compiler/uid.js +33 -4
  29. package/build/index.d.ts +1 -1
  30. package/build/index.js +1 -1
  31. package/build/jsonc.d.ts +2 -0
  32. package/build/jsonc.js +85 -0
  33. package/build/lsp/bin.d.ts +1 -0
  34. package/build/lsp/bin.js +2 -0
  35. package/build/lsp/diagnostics.d.ts +10 -0
  36. package/build/lsp/diagnostics.js +69 -0
  37. package/build/lsp/index.d.ts +2 -0
  38. package/build/lsp/index.js +2 -0
  39. package/build/lsp/server.d.ts +4 -0
  40. package/build/lsp/server.js +130 -0
  41. package/build/lsp/workspace.d.ts +14 -0
  42. package/build/lsp/workspace.js +46 -0
  43. package/build/probe/adapter.d.ts +14 -0
  44. package/build/probe/adapter.js +42 -0
  45. package/build/probe/async/channel.d.ts +4 -0
  46. package/build/probe/async/channel.js +560 -0
  47. package/build/probe/async/value.d.ts +9 -0
  48. package/build/probe/async/value.js +16 -0
  49. package/build/probe/channels.d.ts +4 -0
  50. package/build/probe/channels.js +16 -0
  51. package/build/probe/exceptions/channel.d.ts +5 -0
  52. package/build/probe/exceptions/channel.js +657 -0
  53. package/build/probe/exceptions/jsdoc.d.ts +8 -0
  54. package/build/probe/exceptions/jsdoc.js +34 -0
  55. package/build/probe/exceptions/value.d.ts +39 -0
  56. package/build/probe/exceptions/value.js +158 -0
  57. package/build/probe/kernel/analyze.d.ts +8 -0
  58. package/build/probe/kernel/analyze.js +68 -0
  59. package/build/probe/kernel/ast.d.ts +11 -0
  60. package/build/probe/kernel/ast.js +49 -0
  61. package/build/probe/kernel/config.d.ts +5 -0
  62. package/build/probe/kernel/config.js +209 -0
  63. package/build/probe/kernel/fixpoint.d.ts +6 -0
  64. package/build/probe/kernel/fixpoint.js +206 -0
  65. package/build/probe/kernel/format.d.ts +4 -0
  66. package/build/probe/kernel/format.js +32 -0
  67. package/build/probe/kernel/graph.d.ts +4 -0
  68. package/build/probe/kernel/graph.js +507 -0
  69. package/build/probe/kernel/ids.d.ts +8 -0
  70. package/build/probe/kernel/ids.js +66 -0
  71. package/build/probe/kernel/program.d.ts +8 -0
  72. package/build/probe/kernel/program.js +13 -0
  73. package/build/probe/kernel/types.d.ts +134 -0
  74. package/build/probe/kernel/types.js +1 -0
  75. package/build/probe/overlay/base/async.jsonc +13 -0
  76. package/build/probe/overlay/base/exceptions.jsonc +54 -0
  77. package/build/probe/overlay/base/resources.jsonc +57 -0
  78. package/build/probe/overlay/load.d.ts +18 -0
  79. package/build/probe/overlay/load.js +302 -0
  80. package/build/probe/overlay/presets/express.jsonc +25 -0
  81. package/build/probe/overlay/presets/node.jsonc +17 -0
  82. package/build/probe/resources/channel.d.ts +4 -0
  83. package/build/probe/resources/channel.js +798 -0
  84. package/build/probe/resources/value.d.ts +9 -0
  85. package/build/probe/resources/value.js +36 -0
  86. package/build/ts.d.ts +3 -0
  87. package/build/ts.js +3 -0
  88. package/build/tsconfig.d.ts +2 -0
  89. package/build/tsconfig.js +150 -0
  90. package/package.json +29 -9
  91. package/tsconfig.base.json +19 -0
  92. package/tsconfig.dev.json +13 -0
  93. package/tsconfig.package.json +4 -1
  94. package/.claude/skills/code-audit/registry-typescript.json +0 -326
  95. package/.editorconfig +0 -9
  96. package/.gitattributes +0 -2
  97. package/.github/dependabot.yml +0 -25
  98. package/.github/workflows/bump.yml +0 -27
  99. package/.github/workflows/dependabot.yml +0 -58
  100. package/.github/workflows/publish.yml +0 -42
  101. package/.github/workflows/templates/bump.yml +0 -9
  102. package/.github/workflows/templates/dependabot.yml +0 -12
  103. package/.github/workflows/templates/publish.yml +0 -16
  104. package/pnpm-workspace.yaml +0 -6
  105. package/src/cli/tsc.ts +0 -235
  106. package/src/compiler/ast.ts +0 -60
  107. package/src/compiler/code.ts +0 -27
  108. package/src/compiler/coordinator.ts +0 -284
  109. package/src/compiler/imports.ts +0 -185
  110. package/src/compiler/index.ts +0 -7
  111. package/src/compiler/language-service.ts +0 -121
  112. package/src/compiler/plugins/index.ts +0 -5
  113. package/src/compiler/plugins/tsc.ts +0 -6
  114. package/src/compiler/plugins/vite.ts +0 -91
  115. package/src/compiler/types.ts +0 -83
  116. package/src/compiler/uid.ts +0 -10
  117. package/src/constants.ts +0 -4
  118. package/src/index.ts +0 -1
  119. package/tests/cli/tsc.test.ts +0 -155
  120. package/tests/compiler/ast.test.ts +0 -131
  121. package/tests/compiler/code.test.ts +0 -73
  122. package/tests/compiler/coordinator.bench.ts +0 -101
  123. package/tests/compiler/coordinator.test.ts +0 -872
  124. package/tests/compiler/imports.test.ts +0 -167
  125. package/tests/compiler/language-service.test.ts +0 -90
  126. package/tests/compiler/plugins.test.ts +0 -172
  127. package/tests/compiler/uid.test.ts +0 -70
  128. package/tsconfig.json +0 -3
  129. package/vitest.config.ts +0 -14
package/build/cli/tsc.js CHANGED
@@ -1,59 +1,196 @@
1
+ import { DiagnosticCategory } from 'typescript/unstable/sync';
1
2
  import { createRequire } from 'module';
3
+ import { format } from './diagnostics.js';
2
4
  import { PACKAGE_NAME } from '../constants.js';
3
5
  import { pathToFileURL } from 'url';
4
6
  import { spawn } from 'child_process';
5
7
  import coordinator from '../compiler/coordinator.js';
8
+ import fs from 'fs';
9
+ import languageService from '../compiler/language-service.js';
6
10
  import path from 'path';
7
- import ts from 'typescript';
11
+ import sourcemap from '../compiler/sourcemap.js';
12
+ import { analyze, analyzeProgram } from '../probe/kernel/analyze.js';
13
+ import { formatDiagnostics } from '../probe/kernel/format.js';
14
+ import { loadConfigFromTsconfig } from '../probe/kernel/config.js';
15
+ import { stripJsonc } from '../jsonc.js';
16
+ import { readPlugins } from '../tsconfig.js';
8
17
  const BACKSLASH_REGEX = /\\/g;
9
- let require = createRequire(import.meta.url), skipFlags = new Set(['--help', '--init', '--noEmit', '--showConfig', '--version', '-h', '-noEmit', '-v']);
10
- async function build(config, tsconfig, pluginConfigs) {
11
- let root = path.dirname(path.resolve(tsconfig)), parsed = ts.parseJsonConfigFileContent(config, ts.sys, root);
12
- if (parsed.errors.length > 0) {
13
- for (let i = 0, n = parsed.errors.length; i < n; i++) {
14
- console.error(ts.flattenDiagnosticMessageText(parsed.errors[i].messageText, '\n'));
15
- }
18
+ const INFORMATIONAL_FLAGS = new Set(['--help', '--init', '--showConfig', '--version', '-h', '-v']);
19
+ const NO_EMIT_FLAGS = new Set(['--noEmit', '-noEmit']);
20
+ const WATCH_FLAGS = new Set(['--watch', '-w']);
21
+ let require = createRequire(import.meta.url), skipFlags = new Set([...INFORMATIONAL_FLAGS, ...NO_EMIT_FLAGS]);
22
+ async function build(tsconfig, pluginConfigs, instance, noEmit = false) {
23
+ let opened = instance === undefined ? languageService.open(tsconfig) : undefined, root = path.dirname(path.resolve(tsconfig)), owned = instance === undefined, api = opened?.api ?? instance, snapshot = opened?.snapshot ?? api.updateSnapshot({ openProjects: [tsconfig] }), project = opened?.project ?? snapshot.getProject(tsconfig);
24
+ if (!project) {
25
+ teardown(snapshot, tsconfig, owned);
26
+ throw new Error(`${PACKAGE_NAME}: project not found for ${tsconfig}`);
27
+ }
28
+ let configDiagnostics = project.program.getConfigFileParsingDiagnostics();
29
+ if (configDiagnostics.some((diagnostic) => diagnostic.category === DiagnosticCategory.Error)) {
30
+ console.error(format(configDiagnostics, root));
31
+ teardown(snapshot, tsconfig, owned);
16
32
  process.exit(1);
17
33
  }
18
- let plugins = await loadPlugins(pluginConfigs, root);
19
- let program = ts.createProgram(parsed.fileNames, parsed.options), shared = new Map(), transformedFiles = new Map();
20
- for (let i = 0, n = parsed.fileNames.length; i < n; i++) {
21
- let fileName = parsed.fileNames[i], sourceFile = program.getSourceFile(fileName);
34
+ let { fileNames, options } = api.parseConfigFile(tsconfig), plugins, shared = new Map(), transformedFiles = new Map();
35
+ runAnalyze(tsconfig, project.program, project.checker);
36
+ try {
37
+ plugins = await loadPlugins(pluginConfigs, root);
38
+ }
39
+ catch (error) {
40
+ console.error(error instanceof Error ? error.message : String(error));
41
+ teardown(snapshot, tsconfig, owned);
42
+ process.exit(1);
43
+ }
44
+ for (let i = 0, n = fileNames.length; i < n; i++) {
45
+ let fileName = fileNames[i], sourceFile = project.program.getSourceFile(fileName);
22
46
  if (!sourceFile) {
23
47
  continue;
24
48
  }
25
- let result = coordinator.transform(plugins, sourceFile.getFullText(), sourceFile, program, root, shared);
49
+ let result = coordinator.transform(plugins, sourceFile.getFullText(), sourceFile, { checker: project.checker, configPath: tsconfig, program: project.program }, root, shared);
26
50
  if (result.changed) {
27
- transformedFiles.set(normalizePath(fileName), result.code);
51
+ transformedFiles.set(normalizePath(fileName), { code: result.code, mapping: result.map });
52
+ }
53
+ }
54
+ let program = transformedFiles.size === 0
55
+ ? project.program
56
+ : languageService.updateMany(tsconfig, new Map([...transformedFiles].map(([fileName, entry]) => [fileName, entry.code]))).program;
57
+ let diagnostics = [
58
+ ...program.getConfigFileParsingDiagnostics(),
59
+ ...program.getSyntacticDiagnostics(),
60
+ ...program.getBindDiagnostics(),
61
+ ...program.getSemanticDiagnostics(),
62
+ ...program.getGlobalDiagnostics(),
63
+ ...program.getProgramDiagnostics()
64
+ ];
65
+ if (diagnostics.length > 0) {
66
+ console.error(format(diagnostics, root, transformedFiles));
67
+ }
68
+ if (diagnostics.some((diagnostic) => diagnostic.category === DiagnosticCategory.Error)) {
69
+ teardown(snapshot, tsconfig, owned);
70
+ process.exit(1);
71
+ }
72
+ if (noEmit) {
73
+ teardown(snapshot, tsconfig, owned);
74
+ process.exit(0);
75
+ }
76
+ let code = await emit(tsconfig, fileNames, transformedFiles, root, options);
77
+ teardown(snapshot, tsconfig, owned);
78
+ if (code !== 0) {
79
+ process.exit(code);
80
+ }
81
+ return runTscAlias(process.argv.slice(2)).then((exitCode) => process.exit(exitCode));
82
+ }
83
+ function classifyFlags(args) {
84
+ let informational = false, noEmit = false, watch = false;
85
+ for (let i = 0, n = args.length; i < n; i++) {
86
+ let arg = args[i];
87
+ if (INFORMATIONAL_FLAGS.has(arg)) {
88
+ informational = true;
89
+ }
90
+ else if (NO_EMIT_FLAGS.has(arg)) {
91
+ noEmit = true;
92
+ }
93
+ else if (WATCH_FLAGS.has(arg)) {
94
+ watch = true;
95
+ }
96
+ }
97
+ return { informational, noEmit, watch };
98
+ }
99
+ function collectMaps(dir, results) {
100
+ for (let entry of fs.readdirSync(dir, { withFileTypes: true })) {
101
+ let full = path.join(dir, entry.name);
102
+ if (entry.isDirectory()) {
103
+ collectMaps(full, results);
104
+ }
105
+ else if (entry.name.endsWith('.js.map')) {
106
+ results.push(full);
107
+ }
108
+ }
109
+ }
110
+ function composeSourceMaps(mirrorOut, mirror, root, transformedFiles) {
111
+ let maps = [];
112
+ collectMaps(mirrorOut, maps);
113
+ for (let i = 0, n = maps.length; i < n; i++) {
114
+ let mapPath = maps[i], raw;
115
+ try {
116
+ raw = JSON.parse(fs.readFileSync(mapPath, 'utf8'));
117
+ }
118
+ catch {
119
+ continue;
120
+ }
121
+ if (!raw.sources || raw.sources.length === 0 || typeof raw.sources[0] !== 'string' || typeof raw.mappings !== 'string') {
122
+ continue;
123
+ }
124
+ let mirrorSource = path.resolve(path.dirname(mapPath), raw.sources[0]), relative = path.relative(mirror, mirrorSource), realSource = normalizePath(path.join(root, relative)), entry = transformedFiles.get(realSource);
125
+ if (!entry) {
126
+ continue;
127
+ }
128
+ let composed = sourcemap.composeEmittedMap({ mappings: raw.mappings, names: raw.names ?? [], sources: raw.sources, version: 3 }, entry.mapping, entry.code, fs.readFileSync(path.join(root, relative), 'utf8'));
129
+ if (raw.file !== undefined) {
130
+ composed.file = raw.file;
28
131
  }
132
+ if (raw.sourceRoot !== undefined) {
133
+ composed.sourceRoot = raw.sourceRoot;
134
+ }
135
+ fs.writeFileSync(mapPath, JSON.stringify(composed));
136
+ }
137
+ }
138
+ async function emit(tsconfig, fileNames, transformedFiles, root, options) {
139
+ let tscJs = path.join(path.dirname(require.resolve('typescript/package.json')), 'lib', 'tsc.js');
140
+ if (transformedFiles.size === 0) {
141
+ return spawnTsc(tscJs, ['-p', tsconfig]);
29
142
  }
30
- if (transformedFiles.size > 0) {
31
- let customHost = ts.createCompilerHost(parsed.options), originalGetSourceFile = customHost.getSourceFile.bind(customHost), originalReadFile = customHost.readFile.bind(customHost);
32
- customHost.getSourceFile = (fileName, languageVersion, onError, shouldCreateNewSourceFile) => {
33
- let transformed = transformedFiles.get(normalizePath(fileName));
34
- if (transformed) {
35
- return ts.createSourceFile(fileName, transformed, languageVersion, true);
143
+ let mirror = fs.mkdtempSync(path.join(root, '.esportsplus-tsc-'));
144
+ try {
145
+ let declaration = options.declaration === true, files = [], mirrorDecl = path.join(mirror, '__decl'), mirrorOut = path.join(mirror, '__emit'), realOutDir = typeof options.outDir === 'string' ? path.resolve(options.outDir) : root, realDeclDir = declaration
146
+ ? (typeof options.declarationDir === 'string' ? path.resolve(options.declarationDir) : realOutDir)
147
+ : undefined, realRootDir = typeof options.rootDir === 'string' ? path.resolve(options.rootDir) : undefined, separateDecl = realDeclDir !== undefined && normalizePath(realDeclDir) !== normalizePath(realOutDir);
148
+ for (let i = 0, n = fileNames.length; i < n; i++) {
149
+ let source = path.resolve(fileNames[i]), relative = path.relative(root, source);
150
+ if (relative.startsWith('..')) {
151
+ throw new Error(`${PACKAGE_NAME}: source ${normalizePath(source)} resolves outside the project root ${normalizePath(root)}; monorepo-external sources are not supported by the transform emit path`);
36
152
  }
37
- return originalGetSourceFile(fileName, languageVersion, onError, shouldCreateNewSourceFile);
38
- };
39
- customHost.readFile = (fileName) => {
40
- return transformedFiles.get(normalizePath(fileName)) ?? originalReadFile(fileName);
153
+ let target = path.join(mirror, relative), transformed = transformedFiles.get(normalizePath(fileNames[i]));
154
+ fs.mkdirSync(path.dirname(target), { recursive: true });
155
+ if (transformed === undefined) {
156
+ fs.copyFileSync(source, target);
157
+ }
158
+ else {
159
+ fs.writeFileSync(target, transformed.code);
160
+ }
161
+ files.push(normalizePath(target));
162
+ }
163
+ let compilerOptions = {
164
+ outDir: normalizePath(mirrorOut)
41
165
  };
42
- program = ts.createProgram(parsed.fileNames, parsed.options, customHost);
43
- }
44
- let { diagnostics, emitSkipped } = program.emit();
45
- diagnostics = ts.getPreEmitDiagnostics(program).concat(diagnostics);
46
- if (diagnostics.length > 0) {
47
- console.error(ts.formatDiagnosticsWithColorAndContext(diagnostics, {
48
- getCanonicalFileName: (fileName) => fileName,
49
- getCurrentDirectory: () => root,
50
- getNewLine: () => '\n'
166
+ if (declaration) {
167
+ compilerOptions.declarationDir = normalizePath(separateDecl ? mirrorDecl : mirrorOut);
168
+ }
169
+ if (realRootDir !== undefined) {
170
+ compilerOptions.rootDir = normalizePath(path.join(mirror, path.relative(root, realRootDir)));
171
+ }
172
+ fs.writeFileSync(path.join(mirror, 'tsconfig.json'), JSON.stringify({
173
+ compilerOptions,
174
+ exclude: [],
175
+ extends: normalizePath(tsconfig),
176
+ files,
177
+ include: []
51
178
  }));
179
+ let code = await spawnTsc(tscJs, ['-p', path.join(mirror, 'tsconfig.json')]);
180
+ if (code === 0) {
181
+ if (fs.existsSync(mirrorOut)) {
182
+ composeSourceMaps(mirrorOut, mirror, root, transformedFiles);
183
+ fs.cpSync(mirrorOut, realOutDir, { force: true, recursive: true });
184
+ }
185
+ if (separateDecl && realDeclDir !== undefined && fs.existsSync(mirrorDecl)) {
186
+ fs.cpSync(mirrorDecl, realDeclDir, { force: true, recursive: true });
187
+ }
188
+ }
189
+ return code;
52
190
  }
53
- if (emitSkipped) {
54
- process.exit(1);
191
+ finally {
192
+ fs.rmSync(mirror, { force: true, recursive: true });
55
193
  }
56
- return runTscAlias(process.argv.slice(2)).then((code) => process.exit(code));
57
194
  }
58
195
  function isPlugin(value) {
59
196
  return typeof value === 'object' && value !== null && 'transform' in value && typeof value.transform === 'function';
@@ -75,18 +212,15 @@ async function loadPlugins(configs, root) {
75
212
  }
76
213
  if (Array.isArray(plugin)) {
77
214
  for (let j = 0, m = plugin.length; j < m; j++) {
78
- if (isPlugin(plugin[j])) {
79
- plugins.push(plugin[j]);
80
- }
81
- else {
82
- console.error(`${PACKAGE_NAME}: plugin ${config.transform}[${j}] uses an invalid plugin format`);
215
+ if (!isPlugin(plugin[j])) {
216
+ throw new Error(`${PACKAGE_NAME}: plugin ${config.transform}[${j}] uses an invalid plugin format, expected { transform: Function }`);
83
217
  }
218
+ plugins.push(plugin[j]);
84
219
  }
85
220
  return;
86
221
  }
87
222
  if (!isPlugin(plugin)) {
88
- console.error(`${PACKAGE_NAME}: plugin ${config.transform} uses an invalid plugin format, expected { transform: Function } or Plugin[]`);
89
- return;
223
+ throw new Error(`${PACKAGE_NAME}: plugin ${config.transform} uses an invalid plugin format, expected { transform: Function } or Plugin[]`);
90
224
  }
91
225
  plugins.push(plugin);
92
226
  }));
@@ -95,20 +229,27 @@ async function loadPlugins(configs, root) {
95
229
  return plugins;
96
230
  }
97
231
  function main() {
98
- let tsconfig = ts.findConfigFile(process.cwd(), ts.sys.fileExists, 'tsconfig.json');
232
+ let args = process.argv.slice(2), tsconfig = projectPath(args) ?? languageService.findConfig(process.cwd());
99
233
  if (!tsconfig) {
100
234
  return passthrough();
101
235
  }
102
- let { config, error } = ts.readConfigFile(tsconfig, ts.sys.readFile);
103
- if (error) {
236
+ let flags = classifyFlags(args);
237
+ let pluginConfigs = resolvePluginConfigs(tsconfig);
238
+ if (pluginConfigs.length === 0) {
239
+ if (!flags.informational && !flags.watch) {
240
+ runAnalyze(tsconfig);
241
+ }
104
242
  return passthrough();
105
243
  }
106
- let pluginConfigs = config?.compilerOptions?.plugins?.filter((p) => typeof p === 'object' && p !== null && 'transform' in p) ?? [];
107
- if (pluginConfigs.length === 0) {
244
+ if (flags.informational) {
108
245
  return passthrough();
109
246
  }
247
+ if (flags.watch) {
248
+ console.error(`${PACKAGE_NAME}: --watch is not supported on the transformer plugin path; run a one-shot build or use real tsc directly`);
249
+ process.exit(1);
250
+ }
110
251
  console.log(`${PACKAGE_NAME}: found ${pluginConfigs.length} transformer plugin(s), using coordinated build...`);
111
- build(config, tsconfig, pluginConfigs).catch((err) => {
252
+ build(tsconfig, pluginConfigs, undefined, flags.noEmit).catch((err) => {
112
253
  console.error(`${PACKAGE_NAME}: ${err}`);
113
254
  process.exit(1);
114
255
  });
@@ -116,9 +257,52 @@ function main() {
116
257
  function normalizePath(fileName) {
117
258
  return path.resolve(fileName).replace(BACKSLASH_REGEX, '/');
118
259
  }
260
+ function projectPath(args) {
261
+ for (let i = 0, n = args.length; i < n; i++) {
262
+ let arg = args[i], value;
263
+ if (arg === '-p' || arg === '--project') {
264
+ value = args[i + 1];
265
+ }
266
+ else if (arg.startsWith('--project=')) {
267
+ value = arg.slice('--project='.length);
268
+ }
269
+ if (value !== undefined) {
270
+ let resolved = path.resolve(value);
271
+ return fs.existsSync(resolved) && fs.statSync(resolved).isDirectory()
272
+ ? path.join(resolved, 'tsconfig.json')
273
+ : resolved;
274
+ }
275
+ }
276
+ return null;
277
+ }
278
+ function runAnalyze(tsconfig, program, checker) {
279
+ let config;
280
+ try {
281
+ config = loadConfigFromTsconfig(tsconfig);
282
+ }
283
+ catch (error) {
284
+ console.error(`${PACKAGE_NAME}: analyze config error: ${error instanceof Error ? error.message : String(error)}`);
285
+ return;
286
+ }
287
+ if (!config) {
288
+ return;
289
+ }
290
+ try {
291
+ let result = program && checker ? analyzeProgram(program, checker, config) : analyze(config);
292
+ if (result.diagnostics.length > 0) {
293
+ console.error(formatDiagnostics(result.diagnostics, config.projectRoot));
294
+ if (config.failOnFindings) {
295
+ process.exit(1);
296
+ }
297
+ }
298
+ }
299
+ catch (error) {
300
+ console.error(`${PACKAGE_NAME}: analyze failed: ${error instanceof Error ? error.message : String(error)}`);
301
+ }
302
+ }
119
303
  function passthrough() {
120
- let args = process.argv.slice(2);
121
- spawn(process.execPath, [require.resolve('typescript/lib/tsc.js'), ...args], { stdio: 'inherit' })
304
+ let args = process.argv.slice(2), tsDir = path.dirname(require.resolve('typescript/package.json'));
305
+ spawn(process.execPath, [path.join(tsDir, 'lib', 'tsc.js'), ...args], { stdio: 'inherit' })
122
306
  .on('exit', async (code) => {
123
307
  if (code === 0) {
124
308
  code = await runTscAlias(args);
@@ -126,6 +310,13 @@ function passthrough() {
126
310
  process.exit(code ?? 0);
127
311
  });
128
312
  }
313
+ function resolvePluginConfigs(tsconfig) {
314
+ let plugins = readPlugins(tsconfig);
315
+ if (!Array.isArray(plugins)) {
316
+ return [];
317
+ }
318
+ return plugins.filter((p) => typeof p === 'object' && p !== null && 'transform' in p);
319
+ }
129
320
  function runTscAlias(args) {
130
321
  for (let i = 0, n = args.length; i < n; i++) {
131
322
  if (skipFlags.has(args[i])) {
@@ -137,7 +328,107 @@ function runTscAlias(args) {
137
328
  child.on('exit', (code) => resolve(code ?? 0));
138
329
  });
139
330
  }
331
+ function spawnTsc(tscJs, args) {
332
+ return new Promise((resolve) => {
333
+ let child = spawn(process.execPath, [tscJs, ...args], { stdio: 'inherit' });
334
+ child.on('exit', (code) => resolve(code ?? 0));
335
+ });
336
+ }
337
+ function legacyStripJsonc(text) {
338
+ let escaped = false, inBlockComment = false, inLineComment = false, inString = false, stripped = '';
339
+ for (let i = 0, n = text.length; i < n; i++) {
340
+ let char = text[i], next = text[i + 1];
341
+ if (inLineComment) {
342
+ if (char === '\n') {
343
+ inLineComment = false;
344
+ stripped += char;
345
+ }
346
+ continue;
347
+ }
348
+ if (inBlockComment) {
349
+ if (char === '*' && next === '/') {
350
+ inBlockComment = false;
351
+ i++;
352
+ }
353
+ continue;
354
+ }
355
+ if (inString) {
356
+ stripped += char;
357
+ if (escaped) {
358
+ escaped = false;
359
+ }
360
+ else if (char === '\\') {
361
+ escaped = true;
362
+ }
363
+ else if (char === '"') {
364
+ inString = false;
365
+ }
366
+ continue;
367
+ }
368
+ if (char === '"') {
369
+ inString = true;
370
+ stripped += char;
371
+ continue;
372
+ }
373
+ if (char === '/' && next === '/') {
374
+ inLineComment = true;
375
+ i++;
376
+ continue;
377
+ }
378
+ if (char === '/' && next === '*') {
379
+ inBlockComment = true;
380
+ i++;
381
+ continue;
382
+ }
383
+ stripped += char;
384
+ }
385
+ escaped = false;
386
+ inString = false;
387
+ let result = '';
388
+ for (let i = 0, n = stripped.length; i < n; i++) {
389
+ let char = stripped[i];
390
+ if (inString) {
391
+ result += char;
392
+ if (escaped) {
393
+ escaped = false;
394
+ }
395
+ else if (char === '\\') {
396
+ escaped = true;
397
+ }
398
+ else if (char === '"') {
399
+ inString = false;
400
+ }
401
+ continue;
402
+ }
403
+ if (char === '"') {
404
+ inString = true;
405
+ result += char;
406
+ continue;
407
+ }
408
+ if (char === ',') {
409
+ let j = i + 1;
410
+ while (j < n && (stripped[j] === ' ' || stripped[j] === '\n' || stripped[j] === '\r' || stripped[j] === '\t')) {
411
+ j++;
412
+ }
413
+ if (stripped[j] === ']' || stripped[j] === '}') {
414
+ continue;
415
+ }
416
+ }
417
+ result += char;
418
+ }
419
+ return result;
420
+ }
421
+ void legacyStripJsonc;
422
+ function teardown(snapshot, configPath, owned) {
423
+ if (owned) {
424
+ languageService.dispose(configPath);
425
+ return;
426
+ }
427
+ if (!snapshot.isDisposed()) {
428
+ snapshot.dispose();
429
+ }
430
+ }
140
431
  if (process.env.VITEST === undefined) {
141
432
  main();
142
433
  }
143
- export { build, isPlugin, loadPlugins, normalizePath, runTscAlias };
434
+ export { build, classifyFlags, isPlugin, loadPlugins, main, normalizePath, projectPath, resolvePluginConfigs, runTscAlias, stripJsonc };
@@ -1,14 +1,16 @@
1
1
  import type { Range } from './types.js';
2
- import { ts } from '../index.js';
2
+ import type { Expression, Node } from 'typescript/unstable/ast';
3
+ declare const inRange: (ranges: Range[], start: number, end: number) => boolean;
4
+ declare const test: (node: Node, fn: (n: Node) => boolean) => boolean;
3
5
  declare const _default: {
4
6
  expression: {
5
- name: (node: ts.Expression) => string | null;
7
+ name: (node: Expression) => string | null;
6
8
  };
7
- inRange: (ranges: Range[], start: number, end: number) => boolean;
9
+ inRange: typeof inRange;
8
10
  property: {
9
- path: (node: ts.Expression) => string | null;
11
+ path: (node: Expression) => string | null;
10
12
  };
11
- test: (node: ts.Node, fn: (n: ts.Node) => boolean) => boolean;
13
+ test: typeof test;
12
14
  };
13
15
  export default _default;
14
16
  export type { Range };
@@ -1,10 +1,10 @@
1
- import { ts } from '../index.js';
1
+ import { isIdentifier, isPropertyAccessExpression } from 'typescript/unstable/ast/is';
2
2
  const expression = {
3
3
  name: (node) => {
4
- if (ts.isIdentifier(node)) {
4
+ if (isIdentifier(node)) {
5
5
  return node.text;
6
6
  }
7
- if (ts.isPropertyAccessExpression(node)) {
7
+ if (isPropertyAccessExpression(node)) {
8
8
  return property.path(node);
9
9
  }
10
10
  return null;
@@ -22,11 +22,11 @@ const inRange = (ranges, start, end) => {
22
22
  const property = {
23
23
  path: (node) => {
24
24
  let current = node, parts = [];
25
- while (ts.isPropertyAccessExpression(current)) {
25
+ while (isPropertyAccessExpression(current)) {
26
26
  parts.push(current.name.text);
27
27
  current = current.expression;
28
28
  }
29
- if (ts.isIdentifier(current)) {
29
+ if (isIdentifier(current)) {
30
30
  parts.push(current.text);
31
31
  return parts.reverse().join('.');
32
32
  }
@@ -37,6 +37,6 @@ const test = (node, fn) => {
37
37
  if (fn(node)) {
38
38
  return true;
39
39
  }
40
- return !!ts.forEachChild(node, child => test(child, fn) || undefined);
40
+ return !!node.forEachChild(child => test(child, fn) || undefined);
41
41
  };
42
42
  export default { expression, inRange, property, test };
@@ -1,5 +1,6 @@
1
- declare const code: {
2
- (literals: TemplateStringsArray, ...values: unknown[]): string;
3
- escape(str: string): string;
4
- };
1
+ declare function code(literals: TemplateStringsArray, ...values: unknown[]): string;
2
+ declare namespace code {
3
+ var _a: (str: string) => string;
4
+ export { _a as escape };
5
+ }
5
6
  export default code;
@@ -1,3 +1,8 @@
1
+ const BACKSLASH_REGEX = /\\/g;
2
+ const CR_REGEX = /\r/g;
3
+ const LINE_SEPARATOR_REGEX = /\u2028/g;
4
+ const NEWLINE_REGEX = /\n/g;
5
+ const PARAGRAPH_SEPARATOR_REGEX = /\u2029/g;
1
6
  const SINGLE_QUOTE_REGEX = /'/g;
2
7
  const code = (literals, ...values) => {
3
8
  let buffer = '';
@@ -12,6 +17,12 @@ const code = (literals, ...values) => {
12
17
  return buffer;
13
18
  };
14
19
  code.escape = (str) => {
15
- return str.replace(SINGLE_QUOTE_REGEX, "\\'");
20
+ return str
21
+ .replace(BACKSLASH_REGEX, '\\\\')
22
+ .replace(SINGLE_QUOTE_REGEX, "\\'")
23
+ .replace(NEWLINE_REGEX, '\\n')
24
+ .replace(CR_REGEX, '\\r')
25
+ .replace(LINE_SEPARATOR_REGEX, '\\u2028')
26
+ .replace(PARAGRAPH_SEPARATOR_REGEX, '\\u2029');
16
27
  };
17
28
  export default code;
@@ -1,16 +1,25 @@
1
+ import type { SourceFile } from 'typescript/unstable/ast';
2
+ import type { Checker, Program } from 'typescript/unstable/sync';
1
3
  import type { Plugin, SharedContext } from './types.js';
2
- import { ts } from '../index.js';
4
+ import type { OffsetAnchor, PositionMapping } from './sourcemap.js';
3
5
  type CoordinatorResult = {
4
6
  changed: boolean;
5
7
  code: string;
6
- sourceFile: ts.SourceFile;
8
+ map: PositionMapping;
7
9
  };
8
- declare const _default: {
9
- transform: (plugins: Plugin[], code: string, file: ts.SourceFile, program: ts.Program, root: string, shared: SharedContext) => {
10
- changed: boolean;
11
- code: string;
12
- sourceFile: ts.SourceFile;
10
+ declare const transform: (plugins: Plugin[], code: string, file: SourceFile, project: {
11
+ checker: Checker;
12
+ configPath?: string;
13
+ program: Program;
14
+ }, root: string, shared: SharedContext) => {
15
+ changed: boolean;
16
+ code: string;
17
+ map: {
18
+ generations: OffsetAnchor[][];
13
19
  };
14
20
  };
21
+ declare const _default: {
22
+ transform: typeof transform;
23
+ };
15
24
  export default _default;
16
25
  export type { CoordinatorResult };