@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
@@ -1,284 +0,0 @@
1
- import type { ImportIntent, Plugin, Replacement, ReplacementIntent, SharedContext } from './types';
2
- import type { ModifyOptions } from './imports';
3
- import { ts } from '~/index';
4
-
5
- import imports from './imports';
6
- import languageService from './language-service';
7
-
8
-
9
- type CoordinatorResult = {
10
- changed: boolean;
11
- code: string;
12
- sourceFile: ts.SourceFile;
13
- };
14
-
15
-
16
- function applyImports(code: string, file: ts.SourceFile, intents: ImportIntent[]): string {
17
- let merged = new Map<string, { add?: string[]; namespace?: string; remove?: string[] }>();
18
-
19
- for (let i = 0, n = intents.length; i < n; i++) {
20
- let intent = intents[i],
21
- existing = merged.get(intent.package);
22
-
23
- if (existing) {
24
- if (intent.add) {
25
- (existing.add ??= []).push(...intent.add);
26
- }
27
- if (intent.namespace) {
28
- existing.namespace = intent.namespace;
29
- }
30
- if (intent.remove) {
31
- (existing.remove ??= []).push(...intent.remove);
32
- }
33
- }
34
- else {
35
- merged.set(intent.package, {
36
- add: intent.add ? [...intent.add] : undefined,
37
- namespace: intent.namespace,
38
- remove: intent.remove ? [...intent.remove] : undefined
39
- });
40
- }
41
- }
42
-
43
- let keys = [...merged.keys()];
44
-
45
- for (let i = 0, n = keys.length; i < n; i++) {
46
- code = modify(code, file, keys[i], merged.get(keys[i])!);
47
-
48
- if (i < n - 1) {
49
- file = ts.createSourceFile(file.fileName, code, file.languageVersion, true);
50
- }
51
- }
52
-
53
- return code;
54
- }
55
-
56
- function applyIntents(code: string, file: ts.SourceFile, intents: ReplacementIntent[]): string {
57
- if (intents.length === 0) {
58
- return code;
59
- }
60
-
61
- return replaceReverse(
62
- code,
63
- intents.map(intent => ({
64
- end: intent.node.end,
65
- newText: intent.generate(file),
66
- start: intent.node.getStart(file)
67
- }))
68
- );
69
- }
70
-
71
- function applyPrepend(code: string, file: ts.SourceFile, prepend: string[]): string {
72
- if (prepend.length === 0) {
73
- return code;
74
- }
75
-
76
- let position = 0;
77
-
78
- for (let i = 0, n = file.statements.length; i < n; i++) {
79
- let stmt = file.statements[i];
80
-
81
- if (ts.isImportDeclaration(stmt)) {
82
- position = stmt.end;
83
- }
84
- else {
85
- break;
86
- }
87
- }
88
-
89
- if (position === 0) {
90
- return prepend.join('\n') + '\n' + code;
91
- }
92
-
93
- return code.slice(0, position) + '\n' + prepend.join('\n') + '\n' + code.slice(position);
94
- }
95
-
96
- function hasPattern(code: string, patterns: string[]): boolean {
97
- for (let i = 0, n = patterns.length; i < n; i++) {
98
- if (code.indexOf(patterns[i]) !== -1) {
99
- return true;
100
- }
101
- }
102
-
103
- return false;
104
- }
105
-
106
- function modify(code: string, file: ts.SourceFile, pkg: string, options: ModifyOptions): string {
107
- if (!options.add && !options.namespace && !options.remove) {
108
- return code;
109
- }
110
-
111
- let { namespace } = options,
112
- add = options.add ? new Set(options.add) : null,
113
- found = imports.all(file, pkg);
114
-
115
- if (found.length === 0) {
116
- let statements: string[] = [];
117
-
118
- if (namespace) {
119
- statements.push(`import * as ${namespace} from '${pkg}';`);
120
- }
121
-
122
- if (add && add.size > 0) {
123
- statements.push(`import { ${[...add].sort().join(', ')} } from '${pkg}';`);
124
- }
125
-
126
- if (statements.length === 0) {
127
- return code;
128
- }
129
-
130
- return statements.join('\n') + '\n' + code;
131
- }
132
-
133
- let remove = options.remove ? new Set(options.remove) : null,
134
- specifiers = new Set<string>();
135
-
136
- for (let i = 0, n = found.length; i < n; i++) {
137
- for (let [name, alias] of found[i].specifiers) {
138
- if (!remove || (!remove.has(name) && !remove.has(alias))) {
139
- let base = name === alias ? name : `${name} as ${alias}`;
140
-
141
- // Preserve type-only specifiers with an inline `type` modifier so the merged import
142
- // stays erasable — otherwise `import type { X }` re-emits as a runtime `import { X }`
143
- // and fails at load time when X has no runtime export.
144
- specifiers.add(found[i].typeOnly.has(name) ? `type ${base}` : base);
145
- }
146
- }
147
- }
148
-
149
- if (add) {
150
- for (let name of add) {
151
- specifiers.add(name);
152
- }
153
- }
154
-
155
- let statements: string[] = [];
156
-
157
- if (namespace) {
158
- statements.push(`import * as ${namespace} from '${pkg}';`);
159
- }
160
-
161
- if (specifiers.size > 0) {
162
- statements.push(`import { ${[...specifiers].sort().join(', ')} } from '${pkg}';`);
163
- }
164
-
165
- let replacements: Replacement[] = [];
166
-
167
- for (let i = 0, n = found.length; i < n; i++) {
168
- replacements.push({
169
- end: found[i].end,
170
- newText: i === 0 ? statements.join('\n') : '',
171
- start: found[i].start
172
- });
173
- }
174
-
175
- return replaceReverse(code, replacements);
176
- }
177
-
178
- function replaceReverse(code: string, replacements: Replacement[]): string {
179
- if (replacements.length === 0) {
180
- return code;
181
- }
182
-
183
- replacements.sort((a, b) => b.start - a.start);
184
-
185
- let parts: string[] = [],
186
- pos = code.length;
187
-
188
- for (let i = 0, n = replacements.length; i < n; i++) {
189
- let r = replacements[i];
190
-
191
- if (r.end < pos) {
192
- parts.push(code.substring(r.end, pos));
193
- }
194
-
195
- parts.push(r.newText);
196
- pos = r.start;
197
- }
198
-
199
- if (pos > 0) {
200
- parts.push(code.substring(0, pos));
201
- }
202
-
203
- return parts.reverse().join('');
204
- }
205
-
206
-
207
- const transform = (
208
- plugins: Plugin[],
209
- code: string,
210
- file: ts.SourceFile,
211
- program: ts.Program,
212
- root: string,
213
- shared: SharedContext
214
- ) => {
215
- if (plugins.length === 0) {
216
- return { changed: false, code, sourceFile: file };
217
- }
218
-
219
- let changed = false,
220
- currentCode = code,
221
- currentFile = file,
222
- currentProgram = program,
223
- fileName = file.fileName,
224
- last = plugins.length - 1;
225
-
226
- for (let i = 0, n = plugins.length; i < n; i++) {
227
- let plugin = plugins[i];
228
-
229
- if (plugin.patterns && !hasPattern(currentCode, plugin.patterns)) {
230
- continue;
231
- }
232
-
233
- let { imports, prepend, replacements } = plugin.transform({
234
- checker: currentProgram.getTypeChecker(),
235
- code: currentCode,
236
- program: currentProgram,
237
- shared,
238
- sourceFile: currentFile
239
- }),
240
- pluginChanged = false;
241
-
242
- if (replacements?.length) {
243
- currentCode = applyIntents(currentCode, currentFile, replacements);
244
- pluginChanged = true;
245
- }
246
-
247
- if (prepend?.length) {
248
- if (pluginChanged) {
249
- currentFile = ts.createSourceFile(fileName, currentCode, file.languageVersion, true);
250
- }
251
-
252
- currentCode = applyPrepend(currentCode, currentFile, prepend);
253
- pluginChanged = true;
254
- }
255
-
256
- if (imports?.length) {
257
- if (pluginChanged) {
258
- currentFile = ts.createSourceFile(fileName, currentCode, file.languageVersion, true);
259
- }
260
-
261
- currentCode = applyImports(currentCode, currentFile, imports);
262
- pluginChanged = true;
263
- }
264
-
265
- if (pluginChanged) {
266
- changed = true;
267
-
268
- if (i < last) {
269
- currentProgram = languageService.update(root, fileName, currentCode);
270
- currentFile = currentProgram.getSourceFile(fileName) ||
271
- ts.createSourceFile(fileName, currentCode, file.languageVersion, true);
272
- }
273
- else {
274
- currentFile = ts.createSourceFile(fileName, currentCode, file.languageVersion, true);
275
- }
276
- }
277
- }
278
-
279
- return { changed, code: currentCode, sourceFile: currentFile };
280
- };
281
-
282
-
283
- export default { transform };
284
- export type { CoordinatorResult };
@@ -1,185 +0,0 @@
1
- import { ts } from '~/index';
2
-
3
-
4
- type ImportInfo = {
5
- end: number;
6
- specifiers: Map<string, string>;
7
- // propertyName keys that were imported type-only, whether via a type-only clause
8
- // (`import type { A }`) or an inline specifier (`import { type A }`). Preserved so a rewrite
9
- // re-emits them as type imports instead of runtime imports.
10
- typeOnly: Set<string>;
11
- start: number;
12
- };
13
-
14
- type ModifyOptions = {
15
- add?: Iterable<string>;
16
- namespace?: string;
17
- remove?: Iterable<string>;
18
- };
19
-
20
-
21
- let cache = new WeakMap<ts.SourceFile, Map<string, Set<string>>>();
22
-
23
-
24
- function fileNameMatchesPackage(fileName: string, pkg: string): boolean {
25
- let normalized = fileName.replace(/\\/g, '/'),
26
- marker = `/node_modules/${pkg}/`;
27
-
28
- return normalized.includes(marker);
29
- }
30
-
31
-
32
- // Find all named imports from a specific package
33
- const all = (file: ts.SourceFile, pkg: string): ImportInfo[] => {
34
- let imports: ImportInfo[] = [];
35
-
36
- for (let i = 0, n = file.statements.length; i < n; i++) {
37
- let stmt = file.statements[i];
38
-
39
- if (!ts.isImportDeclaration(stmt)) {
40
- continue;
41
- }
42
-
43
- let moduleSpecifier = stmt.moduleSpecifier;
44
-
45
- if (!ts.isStringLiteral(moduleSpecifier) || moduleSpecifier.text !== pkg) {
46
- continue;
47
- }
48
-
49
- let bindings = stmt.importClause?.namedBindings,
50
- declTypeOnly = stmt.importClause?.isTypeOnly ?? false,
51
- specifiers = new Map<string, string>(),
52
- typeOnly = new Set<string>();
53
-
54
- if (bindings && ts.isNamedImports(bindings)) {
55
- for (let j = 0, m = bindings.elements.length; j < m; j++) {
56
- let element = bindings.elements[j],
57
- name = element.name.text,
58
- propertyName = element.propertyName?.text || name;
59
-
60
- specifiers.set(propertyName, name);
61
-
62
- if (declTypeOnly || element.isTypeOnly) {
63
- typeOnly.add(propertyName);
64
- }
65
- }
66
- }
67
-
68
- imports.push({ end: stmt.end, specifiers, start: stmt.getStart(file), typeOnly });
69
- }
70
-
71
- return imports;
72
- };
73
-
74
- // Check if node's symbol originates from a specific package (with optional symbol name validation)
75
- const includes = (checker: ts.TypeChecker, node: ts.Node, pkg: string, symbolName?: string): boolean => {
76
- if (!ts.isIdentifier(node)) {
77
- return false;
78
- }
79
-
80
- if (symbolName && node.text !== symbolName) {
81
- return false;
82
- }
83
-
84
- let file = node.getSourceFile(),
85
- imports = cache.get(file);
86
-
87
- if (!imports) {
88
- imports = new Map();
89
- cache.set(file, imports);
90
- }
91
-
92
- let names = imports.get(pkg);
93
-
94
- if (!names) {
95
- names = new Set();
96
-
97
- let packages = all(file, pkg);
98
-
99
- for (let i = 0, n = packages.length; i < n; i++) {
100
- for (let [, localName] of packages[i].specifiers) {
101
- names.add(localName);
102
- }
103
- }
104
-
105
- imports.set(pkg, names);
106
- }
107
-
108
- // Fast path: direct import from package
109
- if (names.has(node.text)) {
110
- let symbol = checker.getSymbolAtLocation(node);
111
-
112
- if (symbol) {
113
- let declarations = symbol.getDeclarations();
114
-
115
- if (declarations && declarations.length > 0) {
116
- for (let i = 0, n = declarations.length; i < n; i++) {
117
- let decl = declarations[i];
118
-
119
- if (ts.isImportSpecifier(decl)) {
120
- let importDecl = decl.parent?.parent?.parent;
121
-
122
- if (importDecl && ts.isImportDeclaration(importDecl) && ts.isStringLiteral(importDecl.moduleSpecifier)) {
123
- if (importDecl.moduleSpecifier.text === pkg) {
124
- return true;
125
- }
126
- }
127
- }
128
-
129
- if (fileNameMatchesPackage(decl.getSourceFile().fileName, pkg)) {
130
- return true;
131
- }
132
- }
133
- }
134
- }
135
-
136
- // If checker failed but name matches direct import, trust it
137
- return true;
138
- }
139
-
140
- // Slow path: check for re-exports via aliased symbol
141
- let symbol = checker.getSymbolAtLocation(node);
142
-
143
- if (!symbol) {
144
- return false;
145
- }
146
-
147
- // Check declarations
148
- let declarations = symbol.getDeclarations();
149
-
150
- if (declarations && declarations.length > 0) {
151
- for (let i = 0, n = declarations.length; i < n; i++) {
152
- let decl = declarations[i];
153
-
154
- if (fileNameMatchesPackage(decl.getSourceFile().fileName, pkg)) {
155
- return true;
156
- }
157
- }
158
- }
159
-
160
- // Check aliased symbol for re-exports
161
- try {
162
- let aliased = checker.getAliasedSymbol(symbol);
163
-
164
- if (aliased && aliased !== symbol) {
165
- let aliasedDecls = aliased.getDeclarations();
166
-
167
- if (aliasedDecls) {
168
- for (let i = 0, n = aliasedDecls.length; i < n; i++) {
169
- if (fileNameMatchesPackage(aliasedDecls[i].getSourceFile().fileName, pkg)) {
170
- return true;
171
- }
172
- }
173
- }
174
- }
175
- }
176
- catch {
177
- // getAliasedSymbol can throw for non-alias symbols
178
- }
179
-
180
- return false;
181
- };
182
-
183
-
184
- export default { all, includes };
185
- export type { ImportInfo, ModifyOptions };
@@ -1,7 +0,0 @@
1
- export { default as ast } from './ast';
2
- export { default as code } from './code';
3
- export { default as coordinator } from './coordinator';
4
- export { default as imports } from './imports';
5
- export { default as plugin } from './plugins';
6
- export { default as uid } from './uid';
7
- export type * from './types';
@@ -1,121 +0,0 @@
1
- import { PACKAGE_NAME } from '~/constants';
2
- import { ts } from '~/index';
3
-
4
- import path from 'path';
5
-
6
-
7
- type LanguageServiceEntry = {
8
- contents: Map<string, string>;
9
- host: ts.LanguageServiceHost;
10
- rootFiles: Set<string>;
11
- service: ts.LanguageService;
12
- versions: Map<string, number>;
13
- };
14
-
15
-
16
- let cache = new Map<string, LanguageServiceEntry>();
17
-
18
-
19
- function create(root: string): LanguageServiceEntry {
20
- let tsconfig = ts.findConfigFile(root, ts.sys.fileExists, 'tsconfig.json');
21
-
22
- if (!tsconfig) {
23
- throw new Error(`${PACKAGE_NAME}: tsconfig.json not found`);
24
- }
25
-
26
- let file = ts.readConfigFile(tsconfig, ts.sys.readFile);
27
-
28
- if (file.error) {
29
- throw new Error(`${PACKAGE_NAME}: error reading tsconfig.json ${file.error.messageText}`);
30
- }
31
-
32
- let parsed = ts.parseJsonConfigFileContent(
33
- file.config,
34
- ts.sys,
35
- path.dirname(tsconfig)
36
- );
37
-
38
- if (parsed.errors.length > 0) {
39
- throw new Error(`${PACKAGE_NAME}: error parsing tsconfig.json ${parsed.errors[0].messageText}`);
40
- }
41
-
42
- let contents = new Map<string, string>(),
43
- rootFiles = new Set(parsed.fileNames.map(f => f.replace(/\\/g, '/'))),
44
- versions = new Map<string, number>();
45
-
46
- for (let fileName of rootFiles) {
47
- versions.set(fileName, 0);
48
- }
49
-
50
- let host: ts.LanguageServiceHost = {
51
- fileExists: ts.sys.fileExists,
52
- getCompilationSettings: () => parsed.options,
53
- getCurrentDirectory: () => root,
54
- getDefaultLibFileName: ts.getDefaultLibFilePath,
55
- getScriptFileNames: () => [...rootFiles],
56
- getScriptSnapshot: (fileName: string) => {
57
- let content = contents.get(fileName);
58
-
59
- if (content !== undefined) {
60
- return ts.ScriptSnapshot.fromString(content);
61
- }
62
-
63
- if (!ts.sys.fileExists(fileName)) {
64
- return undefined;
65
- }
66
-
67
- return ts.ScriptSnapshot.fromString(ts.sys.readFile(fileName) || '');
68
- },
69
- getScriptVersion: (fileName: string) => String(versions.get(fileName) || 0),
70
- readFile: ts.sys.readFile
71
- };
72
-
73
- return { contents, host, rootFiles, service: ts.createLanguageService(host), versions };
74
- }
75
-
76
- function getEntry(root: string): LanguageServiceEntry {
77
- let entry = cache.get(root);
78
-
79
- if (!entry) {
80
- entry = create(root);
81
- cache.set(root, entry);
82
- }
83
-
84
- return entry;
85
- }
86
-
87
-
88
- const invalidate = (root: string, fileName: string): void => {
89
- let entry = cache.get(root);
90
-
91
- if (entry) {
92
- let normalized = fileName.replace(/\\/g, '/');
93
-
94
- entry.contents.delete(normalized);
95
- entry.versions.set(normalized, (entry.versions.get(normalized) || 0) + 1);
96
- }
97
- };
98
-
99
- const update = (root: string, fileName: string, content: string): ts.Program => {
100
- let entry = getEntry(root),
101
- normalized = fileName.replace(/\\/g, '/');
102
-
103
- if (!entry.rootFiles.has(normalized)) {
104
- entry.rootFiles.add(normalized);
105
- }
106
-
107
- entry.contents.set(normalized, content);
108
- entry.versions.set(normalized, (entry.versions.get(normalized) || 0) + 1);
109
-
110
- let program = entry.service.getProgram();
111
-
112
- if (!program) {
113
- throw new Error(`${PACKAGE_NAME}: failed to get program from language service`);
114
- }
115
-
116
- return program;
117
- };
118
-
119
-
120
- export default { invalidate, update };
121
- export { invalidate, update };
@@ -1,5 +0,0 @@
1
- import tsc from './tsc';
2
- import vite from './vite';
3
-
4
-
5
- export default { tsc, vite };
@@ -1,6 +0,0 @@
1
- import type { Plugin } from '../types';
2
-
3
-
4
- export default (plugins: Plugin[]) => {
5
- return () => plugins;
6
- };
@@ -1,91 +0,0 @@
1
- import type { Plugin, SharedContext } from '../types';
2
- import type { ResolvedConfig } from 'vite';
3
- import { ts } from '~/index';
4
-
5
- import coordinator from '../coordinator';
6
- import languageService from '../language-service';
7
-
8
-
9
- type VitePlugin = {
10
- configResolved: (config: unknown) => void;
11
- enforce: 'pre';
12
- name: string;
13
- transform: (code: string, id: string) => { code: string; map: null } | null;
14
- watchChange: (id: string) => void;
15
- };
16
-
17
- type VitePluginOptions = {
18
- name: string;
19
- onWatchChange?: () => void;
20
- plugins: Plugin[];
21
- };
22
-
23
-
24
- const DIRECTORY_SEPARATOR_REGEX = /\\/g;
25
-
26
- const FILE_REGEX = /\.[tj]sx?$/;
27
-
28
-
29
- let contexts = new Map<string, SharedContext>();
30
-
31
-
32
- export default ({ name, onWatchChange, plugins }: VitePluginOptions) => {
33
- return ({ root }: { root?: string } = {}): VitePlugin => {
34
- return {
35
- configResolved(config: unknown) {
36
- root ??= (config as ResolvedConfig).root;
37
- },
38
- enforce: 'pre',
39
- name: `${name}/compiler/vite`,
40
- transform(code: string, id: string) {
41
- if (!FILE_REGEX.test(id) || id.includes('node_modules')) {
42
- return null;
43
- }
44
-
45
- try {
46
- let normalizedId = id.replace(DIRECTORY_SEPARATOR_REGEX, '/'),
47
- prog = languageService.update(root || '', normalizedId, code),
48
- sourceFile = prog.getSourceFile(normalizedId);
49
-
50
- if (!sourceFile) {
51
- sourceFile = ts.createSourceFile(normalizedId, code, ts.ScriptTarget.Latest, true);
52
- }
53
-
54
- let key = root || '',
55
- ctx = contexts.get(key);
56
-
57
- if (!ctx) {
58
- ctx = new Map();
59
- contexts.set(key, ctx);
60
- }
61
-
62
- let result = coordinator.transform(
63
- plugins,
64
- code,
65
- sourceFile,
66
- prog,
67
- key,
68
- ctx
69
- );
70
-
71
- if (!result.changed) {
72
- return null;
73
- }
74
-
75
- return { code: result.code, map: null };
76
- }
77
- catch (error) {
78
- console.error(`${name}: error transforming ${id}:`, error);
79
- return null;
80
- }
81
- },
82
- watchChange(id: string) {
83
- if (FILE_REGEX.test(id)) {
84
- onWatchChange?.();
85
- contexts.delete(root || '');
86
- languageService.invalidate(root || '', id);
87
- }
88
- }
89
- };
90
- };
91
- };