@esportsplus/typescript 0.28.5 → 0.29.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.
@@ -0,0 +1,326 @@
1
+ {
2
+ "project": "@esportsplus/typescript",
3
+ "version": "0.29.0",
4
+ "target": "src/ tests/",
5
+ "runs": [
6
+ {
7
+ "date": "2026-04-11",
8
+ "commit": "e0657fe",
9
+ "mode": "full",
10
+ "files_audited": 13,
11
+ "files_skipped": 0,
12
+ "findings_new": 2,
13
+ "findings_recurring": 0,
14
+ "sqale_rating": "A",
15
+ "agent_results": {
16
+ "correctness": { "status": "ok", "symbols": 26, "sub_targets": 1, "findings": 1 },
17
+ "security": { "status": "ok", "symbols": 14, "sub_targets": 1, "findings": 0 },
18
+ "performance": { "status": "ok", "symbols": 15, "sub_targets": 1, "findings": 1 },
19
+ "architecture": { "status": "ok", "symbols": 32, "sub_targets": 1, "findings": 0 },
20
+ "testing": { "status": "ok", "symbols": 16, "sub_targets": 1, "findings": 1 }
21
+ },
22
+ "agent_overlap": {},
23
+ "estimated_remaining": null
24
+ },
25
+ {
26
+ "date": "2026-04-11",
27
+ "commit": "e0657fe",
28
+ "mode": "incremental",
29
+ "files_audited": 13,
30
+ "files_skipped": 0,
31
+ "findings_new": 0,
32
+ "findings_recurring": 1,
33
+ "sqale_rating": "A",
34
+ "agent_results": {
35
+ "correctness": { "status": "ok", "symbols": 26, "sub_targets": 1, "findings": 0 },
36
+ "security": { "status": "ok", "symbols": 14, "sub_targets": 1, "findings": 0 },
37
+ "performance": { "status": "ok", "symbols": 15, "sub_targets": 1, "findings": 0 },
38
+ "architecture": { "status": "ok", "symbols": 32, "sub_targets": 1, "findings": 0 },
39
+ "testing": { "status": "ok", "symbols": 16, "sub_targets": 1, "findings": 1 }
40
+ },
41
+ "agent_overlap": {},
42
+ "estimated_remaining": null
43
+ },
44
+ {
45
+ "date": "2026-04-11",
46
+ "commit": "e0657fe",
47
+ "mode": "incremental",
48
+ "files_audited": 13,
49
+ "files_skipped": 0,
50
+ "findings_new": 0,
51
+ "findings_recurring": 0,
52
+ "sqale_rating": "A",
53
+ "agent_results": {
54
+ "correctness": { "status": "ok", "symbols": 26, "sub_targets": 1, "findings": 0 },
55
+ "security": { "status": "ok", "symbols": 14, "sub_targets": 1, "findings": 0 },
56
+ "performance": { "status": "ok", "symbols": 15, "sub_targets": 1, "findings": 0 },
57
+ "architecture": { "status": "ok", "symbols": 32, "sub_targets": 1, "findings": 0 },
58
+ "testing": { "status": "ok", "symbols": 16, "sub_targets": 1, "findings": 0 }
59
+ },
60
+ "agent_overlap": {},
61
+ "estimated_remaining": null
62
+ },
63
+ {
64
+ "date": "2026-04-11",
65
+ "commit": "59ea7a3",
66
+ "mode": "incremental",
67
+ "files_audited": 19,
68
+ "files_skipped": 0,
69
+ "findings_new": 9,
70
+ "findings_recurring": 1,
71
+ "sqale_rating": "B",
72
+ "agent_results": {
73
+ "correctness": { "status": "ok", "symbols": 26, "sub_targets": 1, "findings": 0 },
74
+ "security": { "status": "ok", "symbols": 14, "sub_targets": 1, "findings": 0 },
75
+ "performance": { "status": "ok", "symbols": 15, "sub_targets": 1, "findings": 0 },
76
+ "architecture": { "status": "ok", "symbols": 32, "sub_targets": 1, "findings": 2 },
77
+ "testing": { "status": "ok", "symbols": 35, "sub_targets": 1, "findings": 7 }
78
+ },
79
+ "agent_overlap": {},
80
+ "estimated_remaining": null
81
+ },
82
+ {
83
+ "date": "2026-04-11",
84
+ "commit": "59ea7a3",
85
+ "mode": "incremental",
86
+ "files_audited": 21,
87
+ "files_skipped": 0,
88
+ "findings_new": 0,
89
+ "findings_recurring": 0,
90
+ "sqale_rating": "A",
91
+ "agent_results": {
92
+ "correctness": { "status": "ok", "symbols": 24, "sub_targets": 1, "findings": 0 },
93
+ "security": { "status": "ok", "symbols": 14, "sub_targets": 1, "findings": 0 },
94
+ "performance": { "status": "ok", "symbols": 13, "sub_targets": 1, "findings": 0 },
95
+ "architecture": { "status": "ok", "symbols": 30, "sub_targets": 1, "findings": 0 },
96
+ "testing": { "status": "ok", "symbols": 35, "sub_targets": 1, "findings": 0 }
97
+ },
98
+ "agent_overlap": {},
99
+ "estimated_remaining": null
100
+ },
101
+ {
102
+ "date": "2026-04-11",
103
+ "commit": "59ea7a3",
104
+ "mode": "incremental",
105
+ "files_audited": 21,
106
+ "files_skipped": 0,
107
+ "findings_new": 0,
108
+ "findings_recurring": 0,
109
+ "sqale_rating": "A",
110
+ "agent_results": {
111
+ "correctness": { "status": "ok", "symbols": 24, "sub_targets": 1, "findings": 0 },
112
+ "security": { "status": "ok", "symbols": 14, "sub_targets": 1, "findings": 0 },
113
+ "performance": { "status": "ok", "symbols": 13, "sub_targets": 1, "findings": 0 },
114
+ "architecture": { "status": "ok", "symbols": 30, "sub_targets": 1, "findings": 0 },
115
+ "testing": { "status": "ok", "symbols": 35, "sub_targets": 1, "findings": 0 }
116
+ },
117
+ "agent_overlap": {},
118
+ "estimated_remaining": null
119
+ }
120
+ ],
121
+ "findings": {
122
+ "F-001": {
123
+ "status": "implemented",
124
+ "file": "src/compiler/coordinator.ts",
125
+ "symbol": "transform",
126
+ "category": "correctness",
127
+ "title": "AST Position Staleness After Code Modification",
128
+ "content_hash": "ast-position-staleness-coordinator-transform",
129
+ "file_hash": "",
130
+ "first_seen": "2026-04-11",
131
+ "last_seen": "2026-04-11",
132
+ "found_by": ["correctness"],
133
+ "priority_score": 66
134
+ },
135
+ "F-002": {
136
+ "status": "deferred",
137
+ "file": "src/compiler/coordinator.ts",
138
+ "symbol": "applyImports",
139
+ "category": "optimize",
140
+ "title": "Redundant SourceFile Recreation in applyImports Loop",
141
+ "content_hash": "redundant-sourcefile-recreation-applyimports",
142
+ "file_hash": "",
143
+ "first_seen": "2026-04-11",
144
+ "last_seen": "2026-04-11",
145
+ "found_by": ["performance"],
146
+ "priority_score": 44
147
+ },
148
+ "F-003": {
149
+ "status": "implemented",
150
+ "file": "src/",
151
+ "symbol": "*",
152
+ "category": "coverage",
153
+ "title": "Complete Absence of Test Infrastructure",
154
+ "content_hash": "missing-test-infrastructure",
155
+ "file_hash": "",
156
+ "first_seen": "2026-04-11",
157
+ "last_seen": "2026-04-11",
158
+ "found_by": ["testing"],
159
+ "priority_score": 114
160
+ },
161
+ "F-004": {
162
+ "status": "implemented",
163
+ "file": "src/compiler/language-service.ts",
164
+ "symbol": "get",
165
+ "category": "loc",
166
+ "title": "languageService.get() is dead code",
167
+ "content_hash": "dead-code-language-service-get",
168
+ "file_hash": "",
169
+ "first_seen": "2026-04-11",
170
+ "last_seen": "2026-04-11",
171
+ "found_by": ["architecture"],
172
+ "priority_score": 45
173
+ },
174
+ "F-005": {
175
+ "status": "implemented",
176
+ "file": "src/compiler/language-service.ts",
177
+ "symbol": "delete",
178
+ "category": "loc",
179
+ "title": "languageService.delete() is dead code",
180
+ "content_hash": "dead-code-language-service-delete",
181
+ "file_hash": "",
182
+ "first_seen": "2026-04-11",
183
+ "last_seen": "2026-04-11",
184
+ "found_by": ["architecture"],
185
+ "priority_score": 45
186
+ },
187
+ "F-006": {
188
+ "status": "implemented",
189
+ "file": "src/compiler/language-service.ts",
190
+ "symbol": "*",
191
+ "category": "coverage",
192
+ "title": "language-service.ts has 0 test coverage",
193
+ "content_hash": "no-test-coverage-language-service",
194
+ "file_hash": "",
195
+ "first_seen": "2026-04-11",
196
+ "last_seen": "2026-04-11",
197
+ "found_by": ["testing"],
198
+ "priority_score": 50
199
+ },
200
+ "F-007": {
201
+ "status": "open",
202
+ "file": "src/cli/tsc.ts",
203
+ "symbol": "*",
204
+ "category": "coverage",
205
+ "title": "cli/tsc.ts has 0 test coverage",
206
+ "content_hash": "no-test-coverage-cli-tsc",
207
+ "file_hash": "",
208
+ "first_seen": "2026-04-11",
209
+ "last_seen": "2026-04-11",
210
+ "found_by": ["testing"],
211
+ "priority_score": 35
212
+ },
213
+ "F-008": {
214
+ "status": "implemented",
215
+ "file": "src/compiler/coordinator.ts",
216
+ "symbol": "transform",
217
+ "category": "test-quality",
218
+ "title": "coordinator plugin.transform() throw path untested",
219
+ "content_hash": "test-quality-coordinator-throw-path",
220
+ "file_hash": "",
221
+ "first_seen": "2026-04-11",
222
+ "last_seen": "2026-04-11",
223
+ "found_by": ["testing"],
224
+ "priority_score": 48
225
+ },
226
+ "F-009": {
227
+ "status": "implemented",
228
+ "file": "src/compiler/coordinator.ts",
229
+ "symbol": "transform",
230
+ "category": "test-quality",
231
+ "title": "coordinator null sourceFile fallback path untested",
232
+ "content_hash": "test-quality-coordinator-null-sourcefile",
233
+ "file_hash": "",
234
+ "first_seen": "2026-04-11",
235
+ "last_seen": "2026-04-11",
236
+ "found_by": ["testing"],
237
+ "priority_score": 48
238
+ },
239
+ "F-010": {
240
+ "status": "implemented",
241
+ "file": "src/compiler/plugins/vite.ts",
242
+ "symbol": "transform",
243
+ "category": "test-quality",
244
+ "title": "vite plugin error catch path untested",
245
+ "content_hash": "test-quality-vite-error-catch",
246
+ "file_hash": "",
247
+ "first_seen": "2026-04-11",
248
+ "last_seen": "2026-04-11",
249
+ "found_by": ["testing"],
250
+ "priority_score": 48
251
+ },
252
+ "F-011": {
253
+ "status": "implemented",
254
+ "file": "src/compiler/plugins/vite.ts",
255
+ "symbol": "transform",
256
+ "category": "test-quality",
257
+ "title": "vite plugin sourceFile undefined fallback untested",
258
+ "content_hash": "test-quality-vite-sourcefile-fallback",
259
+ "file_hash": "",
260
+ "first_seen": "2026-04-11",
261
+ "last_seen": "2026-04-11",
262
+ "found_by": ["testing"],
263
+ "priority_score": 45
264
+ },
265
+ "F-012": {
266
+ "status": "implemented",
267
+ "file": "src/compiler/imports.ts",
268
+ "symbol": "includes",
269
+ "category": "test-quality",
270
+ "title": "imports.includes() getAliasedSymbol catch block untested",
271
+ "content_hash": "test-quality-imports-aliased-catch",
272
+ "file_hash": "",
273
+ "first_seen": "2026-04-11",
274
+ "last_seen": "2026-04-11",
275
+ "found_by": ["testing"],
276
+ "priority_score": 42
277
+ }
278
+ },
279
+ "clean_symbols": {},
280
+ "convergence": {
281
+ "per_category": {
282
+ "correctness": {
283
+ "findings_per_run": [1, 0, 0, 0, 0, 0],
284
+ "successful_runs": 6,
285
+ "consecutive_zero": 5,
286
+ "last_agent_success": true,
287
+ "status": "CONVERGED",
288
+ "reason": "0 new findings on 5 consecutive successful runs"
289
+ },
290
+ "security": {
291
+ "findings_per_run": [0, 0, 0, 0, 0, 0],
292
+ "successful_runs": 6,
293
+ "consecutive_zero": 6,
294
+ "last_agent_success": true,
295
+ "status": "CONVERGED",
296
+ "reason": "0 new findings on 6 consecutive successful runs"
297
+ },
298
+ "performance": {
299
+ "findings_per_run": [1, 0, 0, 0, 0, 0],
300
+ "successful_runs": 6,
301
+ "consecutive_zero": 5,
302
+ "last_agent_success": true,
303
+ "status": "CONVERGED",
304
+ "reason": "0 new findings on 5 consecutive successful runs"
305
+ },
306
+ "architecture": {
307
+ "findings_per_run": [0, 0, 0, 2, 0, 0],
308
+ "successful_runs": 6,
309
+ "consecutive_zero": 2,
310
+ "last_agent_success": true,
311
+ "status": "CONVERGED",
312
+ "reason": "0 new findings on 2 consecutive runs after fixes"
313
+ },
314
+ "testing": {
315
+ "findings_per_run": [1, 1, 0, 7, 0, 0],
316
+ "successful_runs": 6,
317
+ "consecutive_zero": 2,
318
+ "last_agent_success": true,
319
+ "status": "CONVERGED",
320
+ "reason": "0 new findings on 2 consecutive runs after fixes"
321
+ }
322
+ },
323
+ "overall": "CONVERGED",
324
+ "reason": "all 5 categories converged with 0 findings on 2+ consecutive runs"
325
+ }
326
+ }
@@ -40,4 +40,4 @@ jobs:
40
40
  env:
41
41
  NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
42
42
  - run: pnpm build
43
- - run: pnpm publish --provenance --no-git-checks
43
+ - run: pnpm publish --no-git-checks
@@ -1 +1,10 @@
1
- export {};
1
+ import type { Plugin } from '../compiler/types.js';
2
+ type PluginConfig = {
3
+ transform: string;
4
+ };
5
+ declare function build(config: object, tsconfig: string, pluginConfigs: PluginConfig[]): Promise<void>;
6
+ declare function isPlugin(value: unknown): value is Plugin;
7
+ declare function loadPlugins(configs: PluginConfig[], root: string): Promise<Plugin[]>;
8
+ declare function normalizePath(fileName: string): string;
9
+ declare function runTscAlias(args: string[]): Promise<number>;
10
+ export { build, isPlugin, loadPlugins, normalizePath, runTscAlias };
package/build/cli/tsc.js CHANGED
@@ -1,10 +1,10 @@
1
- import { spawn } from 'child_process';
2
1
  import { createRequire } from 'module';
2
+ import { PACKAGE_NAME } from '../constants.js';
3
3
  import { pathToFileURL } from 'url';
4
+ import { spawn } from 'child_process';
5
+ import coordinator from '../compiler/coordinator.js';
4
6
  import path from 'path';
5
7
  import ts from 'typescript';
6
- import coordinator from '../compiler/coordinator.js';
7
- import { PACKAGE_NAME } from '../constants.js';
8
8
  const BACKSLASH_REGEX = /\\/g;
9
9
  let require = createRequire(import.meta.url), skipFlags = new Set(['--help', '--init', '--noEmit', '--showConfig', '--version', '-h', '-noEmit', '-v']);
10
10
  async function build(config, tsconfig, pluginConfigs) {
@@ -22,7 +22,7 @@ async function build(config, tsconfig, pluginConfigs) {
22
22
  if (!sourceFile) {
23
23
  continue;
24
24
  }
25
- let result = coordinator.transform(plugins, sourceFile.getFullText(), sourceFile, program, shared);
25
+ let result = coordinator.transform(plugins, sourceFile.getFullText(), sourceFile, program, root, shared);
26
26
  if (result.changed) {
27
27
  transformedFiles.set(normalizePath(fileName), result.code);
28
28
  }
@@ -137,4 +137,7 @@ function runTscAlias(args) {
137
137
  child.on('exit', (code) => resolve(code ?? 0));
138
138
  });
139
139
  }
140
- main();
140
+ if (process.env.VITEST === undefined) {
141
+ main();
142
+ }
143
+ export { build, isPlugin, loadPlugins, normalizePath, runTscAlias };
@@ -1,8 +1,5 @@
1
- import ts from 'typescript';
2
- type Range = {
3
- end: number;
4
- start: number;
5
- };
1
+ import type { Range } from './types.js';
2
+ import { ts } from '../index.js';
6
3
  declare const _default: {
7
4
  expression: {
8
5
  name: (node: ts.Expression) => string | null;
@@ -1,4 +1,4 @@
1
- import ts from 'typescript';
1
+ import { ts } from '../index.js';
2
2
  const expression = {
3
3
  name: (node) => {
4
4
  if (ts.isIdentifier(node)) {
@@ -6,8 +6,7 @@ type CoordinatorResult = {
6
6
  sourceFile: ts.SourceFile;
7
7
  };
8
8
  declare const _default: {
9
- createPatchedProgram: (baseProgram: ts.Program, fileName: string, newContent: string) => ts.Program;
10
- transform: (plugins: Plugin[], code: string, file: ts.SourceFile, program: ts.Program, shared: SharedContext) => {
9
+ transform: (plugins: Plugin[], code: string, file: ts.SourceFile, program: ts.Program, root: string, shared: SharedContext) => {
11
10
  changed: boolean;
12
11
  code: string;
13
12
  sourceFile: ts.SourceFile;
@@ -1,13 +1,32 @@
1
1
  import { ts } from '../index.js';
2
2
  import imports from './imports.js';
3
+ import languageService from './language-service.js';
3
4
  function applyImports(code, file, intents) {
5
+ let merged = new Map();
4
6
  for (let i = 0, n = intents.length; i < n; i++) {
5
- let intent = intents[i];
6
- code = modify(code, file, intent.package, {
7
- add: intent.add,
8
- namespace: intent.namespace,
9
- remove: intent.remove
10
- });
7
+ let intent = intents[i], existing = merged.get(intent.package);
8
+ if (existing) {
9
+ if (intent.add) {
10
+ (existing.add ??= []).push(...intent.add);
11
+ }
12
+ if (intent.namespace) {
13
+ existing.namespace = intent.namespace;
14
+ }
15
+ if (intent.remove) {
16
+ (existing.remove ??= []).push(...intent.remove);
17
+ }
18
+ }
19
+ else {
20
+ merged.set(intent.package, {
21
+ add: intent.add ? [...intent.add] : undefined,
22
+ namespace: intent.namespace,
23
+ remove: intent.remove ? [...intent.remove] : undefined
24
+ });
25
+ }
26
+ }
27
+ let keys = [...merged.keys()];
28
+ for (let i = 0, n = keys.length; i < n; i++) {
29
+ code = modify(code, file, keys[i], merged.get(keys[i]));
11
30
  if (i < n - 1) {
12
31
  file = ts.createSourceFile(file.fileName, code, file.languageVersion, true);
13
32
  }
@@ -39,9 +58,9 @@ function applyPrepend(code, file, prepend) {
39
58
  }
40
59
  }
41
60
  if (position === 0) {
42
- return prepend.join('\n') + code;
61
+ return prepend.join('\n') + '\n' + code;
43
62
  }
44
- return code.slice(0, position) + prepend.join('\n') + code.slice(position);
63
+ return code.slice(0, position) + '\n' + prepend.join('\n') + '\n' + code.slice(position);
45
64
  }
46
65
  function hasPattern(code, patterns) {
47
66
  for (let i = 0, n = patterns.length; i < n; i++) {
@@ -104,32 +123,25 @@ function replaceReverse(code, replacements) {
104
123
  return code;
105
124
  }
106
125
  replacements.sort((a, b) => b.start - a.start);
107
- let result = code;
126
+ let parts = [], pos = code.length;
108
127
  for (let i = 0, n = replacements.length; i < n; i++) {
109
128
  let r = replacements[i];
110
- result = result.substring(0, r.start) + r.newText + result.substring(r.end);
129
+ if (r.end < pos) {
130
+ parts.push(code.substring(r.end, pos));
131
+ }
132
+ parts.push(r.newText);
133
+ pos = r.start;
134
+ }
135
+ if (pos > 0) {
136
+ parts.push(code.substring(0, pos));
111
137
  }
112
- return result;
138
+ return parts.reverse().join('');
113
139
  }
114
- const createPatchedProgram = (baseProgram, fileName, newContent) => {
115
- let baseHost = ts.createCompilerHost(baseProgram.getCompilerOptions()), options = baseProgram.getCompilerOptions();
116
- return ts.createProgram(baseProgram.getRootFileNames(), options, {
117
- ...baseHost,
118
- getSourceFile: (name, languageVersion) => {
119
- if (name === fileName || name === fileName.replace(/\\/g, '/')) {
120
- return ts.createSourceFile(name, newContent, languageVersion, true);
121
- }
122
- return baseProgram.getSourceFile(name) ?? baseHost.getSourceFile(name, languageVersion);
123
- },
124
- fileExists: (name) => baseHost.fileExists(name),
125
- readFile: (name) => name === fileName ? newContent : baseHost.readFile(name)
126
- }, baseProgram);
127
- };
128
- const transform = (plugins, code, file, program, shared) => {
140
+ const transform = (plugins, code, file, program, root, shared) => {
129
141
  if (plugins.length === 0) {
130
142
  return { changed: false, code, sourceFile: file };
131
143
  }
132
- let changed = false, currentCode = code, currentFile = file, currentProgram = program, fileName = file.fileName;
144
+ let changed = false, currentCode = code, currentFile = file, currentProgram = program, fileName = file.fileName, last = plugins.length - 1;
133
145
  for (let i = 0, n = plugins.length; i < n; i++) {
134
146
  let plugin = plugins[i];
135
147
  if (plugin.patterns && !hasPattern(currentCode, plugin.patterns)) {
@@ -147,17 +159,23 @@ const transform = (plugins, code, file, program, shared) => {
147
159
  pluginChanged = true;
148
160
  }
149
161
  if (prepend?.length) {
162
+ if (pluginChanged) {
163
+ currentFile = ts.createSourceFile(fileName, currentCode, file.languageVersion, true);
164
+ }
150
165
  currentCode = applyPrepend(currentCode, currentFile, prepend);
151
166
  pluginChanged = true;
152
167
  }
153
168
  if (imports?.length) {
169
+ if (pluginChanged) {
170
+ currentFile = ts.createSourceFile(fileName, currentCode, file.languageVersion, true);
171
+ }
154
172
  currentCode = applyImports(currentCode, currentFile, imports);
155
173
  pluginChanged = true;
156
174
  }
157
175
  if (pluginChanged) {
158
176
  changed = true;
159
- if (i < n - 1) {
160
- currentProgram = createPatchedProgram(program, fileName, currentCode);
177
+ if (i < last) {
178
+ currentProgram = languageService.update(root, fileName, currentCode);
161
179
  currentFile = currentProgram.getSourceFile(fileName) ||
162
180
  ts.createSourceFile(fileName, currentCode, file.languageVersion, true);
163
181
  }
@@ -168,4 +186,4 @@ const transform = (plugins, code, file, program, shared) => {
168
186
  }
169
187
  return { changed, code: currentCode, sourceFile: currentFile };
170
188
  };
171
- export default { createPatchedProgram, transform };
189
+ export default { transform };
@@ -1,5 +1,9 @@
1
1
  import { ts } from '../index.js';
2
2
  let cache = new WeakMap();
3
+ function fileNameMatchesPackage(fileName, pkg) {
4
+ let normalized = fileName.replace(/\\/g, '/'), marker = `/node_modules/${pkg}/`;
5
+ return normalized.includes(marker);
6
+ }
3
7
  const all = (file, pkg) => {
4
8
  let imports = [];
5
9
  for (let i = 0, n = file.statements.length; i < n; i++) {
@@ -60,7 +64,7 @@ const includes = (checker, node, pkg, symbolName) => {
60
64
  }
61
65
  }
62
66
  }
63
- if (decl.getSourceFile().fileName.includes(pkg)) {
67
+ if (fileNameMatchesPackage(decl.getSourceFile().fileName, pkg)) {
64
68
  return true;
65
69
  }
66
70
  }
@@ -76,7 +80,7 @@ const includes = (checker, node, pkg, symbolName) => {
76
80
  if (declarations && declarations.length > 0) {
77
81
  for (let i = 0, n = declarations.length; i < n; i++) {
78
82
  let decl = declarations[i];
79
- if (decl.getSourceFile().fileName.includes(pkg)) {
83
+ if (fileNameMatchesPackage(decl.getSourceFile().fileName, pkg)) {
80
84
  return true;
81
85
  }
82
86
  }
@@ -87,7 +91,7 @@ const includes = (checker, node, pkg, symbolName) => {
87
91
  let aliasedDecls = aliased.getDeclarations();
88
92
  if (aliasedDecls) {
89
93
  for (let i = 0, n = aliasedDecls.length; i < n; i++) {
90
- if (aliasedDecls[i].getSourceFile().fileName.includes(pkg)) {
94
+ if (fileNameMatchesPackage(aliasedDecls[i].getSourceFile().fileName, pkg)) {
91
95
  return true;
92
96
  }
93
97
  }
@@ -0,0 +1,9 @@
1
+ import { ts } from '../index.js';
2
+ declare const invalidate: (root: string, fileName: string) => void;
3
+ declare const update: (root: string, fileName: string, content: string) => ts.Program;
4
+ declare const _default: {
5
+ invalidate: (root: string, fileName: string) => void;
6
+ update: (root: string, fileName: string, content: string) => ts.Program;
7
+ };
8
+ export default _default;
9
+ export { invalidate, update };
@@ -0,0 +1,73 @@
1
+ import { PACKAGE_NAME } from '../constants.js';
2
+ import { ts } from '../index.js';
3
+ import path from 'path';
4
+ let cache = new Map();
5
+ function create(root) {
6
+ let tsconfig = ts.findConfigFile(root, ts.sys.fileExists, 'tsconfig.json');
7
+ if (!tsconfig) {
8
+ throw new Error(`${PACKAGE_NAME}: tsconfig.json not found`);
9
+ }
10
+ let file = ts.readConfigFile(tsconfig, ts.sys.readFile);
11
+ if (file.error) {
12
+ throw new Error(`${PACKAGE_NAME}: error reading tsconfig.json ${file.error.messageText}`);
13
+ }
14
+ let parsed = ts.parseJsonConfigFileContent(file.config, ts.sys, path.dirname(tsconfig));
15
+ if (parsed.errors.length > 0) {
16
+ throw new Error(`${PACKAGE_NAME}: error parsing tsconfig.json ${parsed.errors[0].messageText}`);
17
+ }
18
+ let contents = new Map(), rootFiles = new Set(parsed.fileNames.map(f => f.replace(/\\/g, '/'))), versions = new Map();
19
+ for (let fileName of rootFiles) {
20
+ versions.set(fileName, 0);
21
+ }
22
+ let host = {
23
+ fileExists: ts.sys.fileExists,
24
+ getCompilationSettings: () => parsed.options,
25
+ getCurrentDirectory: () => root,
26
+ getDefaultLibFileName: ts.getDefaultLibFilePath,
27
+ getScriptFileNames: () => [...rootFiles],
28
+ getScriptSnapshot: (fileName) => {
29
+ let content = contents.get(fileName);
30
+ if (content !== undefined) {
31
+ return ts.ScriptSnapshot.fromString(content);
32
+ }
33
+ if (!ts.sys.fileExists(fileName)) {
34
+ return undefined;
35
+ }
36
+ return ts.ScriptSnapshot.fromString(ts.sys.readFile(fileName) || '');
37
+ },
38
+ getScriptVersion: (fileName) => String(versions.get(fileName) || 0),
39
+ readFile: ts.sys.readFile
40
+ };
41
+ return { contents, host, rootFiles, service: ts.createLanguageService(host), versions };
42
+ }
43
+ function getEntry(root) {
44
+ let entry = cache.get(root);
45
+ if (!entry) {
46
+ entry = create(root);
47
+ cache.set(root, entry);
48
+ }
49
+ return entry;
50
+ }
51
+ const invalidate = (root, fileName) => {
52
+ let entry = cache.get(root);
53
+ if (entry) {
54
+ let normalized = fileName.replace(/\\/g, '/');
55
+ entry.contents.delete(normalized);
56
+ entry.versions.set(normalized, (entry.versions.get(normalized) || 0) + 1);
57
+ }
58
+ };
59
+ const update = (root, fileName, content) => {
60
+ let entry = getEntry(root), normalized = fileName.replace(/\\/g, '/');
61
+ if (!entry.rootFiles.has(normalized)) {
62
+ entry.rootFiles.add(normalized);
63
+ }
64
+ entry.contents.set(normalized, content);
65
+ entry.versions.set(normalized, (entry.versions.get(normalized) || 0) + 1);
66
+ let program = entry.service.getProgram();
67
+ if (!program) {
68
+ throw new Error(`${PACKAGE_NAME}: failed to get program from language service`);
69
+ }
70
+ return program;
71
+ };
72
+ export default { invalidate, update };
73
+ export { invalidate, update };