@esportsplus/typescript 0.28.3 → 0.28.4

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.
@@ -43,6 +43,20 @@ function applyPrepend(code, file, prepend) {
43
43
  }
44
44
  return code.slice(0, position) + prepend.join('\n') + code.slice(position);
45
45
  }
46
+ function createPatchedProgram(baseProgram, fileName, newContent) {
47
+ let baseHost = ts.createCompilerHost(baseProgram.getCompilerOptions()), options = baseProgram.getCompilerOptions();
48
+ return ts.createProgram(baseProgram.getRootFileNames(), options, {
49
+ ...baseHost,
50
+ getSourceFile: (name, languageVersion) => {
51
+ if (name === fileName || name === fileName.replace(/\\/g, '/')) {
52
+ return ts.createSourceFile(name, newContent, languageVersion, true);
53
+ }
54
+ return baseProgram.getSourceFile(name) ?? baseHost.getSourceFile(name, languageVersion);
55
+ },
56
+ fileExists: (name) => baseHost.fileExists(name),
57
+ readFile: (name) => name === fileName ? newContent : baseHost.readFile(name)
58
+ }, baseProgram);
59
+ }
46
60
  function hasPattern(code, patterns) {
47
61
  for (let i = 0, n = patterns.length; i < n; i++) {
48
62
  if (code.indexOf(patterns[i]) !== -1) {
@@ -99,7 +113,6 @@ function modify(code, file, pkg, options) {
99
113
  }
100
114
  return replaceReverse(code, replacements);
101
115
  }
102
- ;
103
116
  function replaceReverse(code, replacements) {
104
117
  if (replacements.length === 0) {
105
118
  return code;
@@ -112,58 +125,47 @@ function replaceReverse(code, replacements) {
112
125
  }
113
126
  return result;
114
127
  }
115
- ;
116
128
  const transform = (plugins, code, file, program, shared) => {
117
129
  if (plugins.length === 0) {
118
130
  return { changed: false, code, sourceFile: file };
119
131
  }
120
- let allImports = [], allPrepend = [], allReplacements = [], checker = program.getTypeChecker(), fileName = file.fileName, originalFile = file;
132
+ let changed = false, currentCode = code, currentFile = file, currentProgram = program, fileName = file.fileName;
121
133
  for (let i = 0, n = plugins.length; i < n; i++) {
122
134
  let plugin = plugins[i];
123
- if (plugin.patterns && !hasPattern(code, plugin.patterns)) {
135
+ if (plugin.patterns && !hasPattern(currentCode, plugin.patterns)) {
124
136
  continue;
125
137
  }
126
138
  let { imports, prepend, replacements } = plugin.transform({
127
- checker,
128
- code,
129
- program,
139
+ checker: currentProgram.getTypeChecker(),
140
+ code: currentCode,
141
+ program: currentProgram,
130
142
  shared,
131
- sourceFile: originalFile
132
- });
143
+ sourceFile: currentFile
144
+ }), pluginChanged = false;
133
145
  if (replacements?.length) {
134
- allReplacements.push(...replacements);
146
+ currentCode = applyIntents(currentCode, currentFile, replacements);
147
+ pluginChanged = true;
135
148
  }
136
149
  if (prepend?.length) {
137
- allPrepend.push(...prepend);
150
+ currentCode = applyPrepend(currentCode, currentFile, prepend);
151
+ pluginChanged = true;
138
152
  }
139
153
  if (imports?.length) {
140
- allImports.push(...imports);
154
+ currentCode = applyImports(currentCode, currentFile, imports);
155
+ pluginChanged = true;
141
156
  }
142
- }
143
- let currentCode = code, currentFile = originalFile;
144
- if (allReplacements.length > 0) {
145
- allReplacements.sort((a, b) => a.node.getStart(originalFile) - b.node.getStart(originalFile));
146
- for (let i = 1, n = allReplacements.length; i < n; i++) {
147
- let prev = allReplacements[i - 1], curr = allReplacements[i], prevEnd = prev.node.end, currStart = curr.node.getStart(originalFile);
148
- if (currStart < prevEnd) {
149
- console.warn(`[coordinator] Overlapping replacements detected at ${fileName}:`, `[${prev.node.getStart(originalFile)}-${prevEnd}] overlaps [${currStart}-${curr.node.end}]`);
157
+ if (pluginChanged) {
158
+ changed = true;
159
+ if (i < n - 1) {
160
+ currentProgram = createPatchedProgram(program, fileName, currentCode);
161
+ currentFile = currentProgram.getSourceFile(fileName) ||
162
+ ts.createSourceFile(fileName, currentCode, file.languageVersion, true);
163
+ }
164
+ else {
165
+ currentFile = ts.createSourceFile(fileName, currentCode, file.languageVersion, true);
150
166
  }
151
167
  }
152
- currentCode = applyIntents(currentCode, currentFile, allReplacements);
153
- currentFile = ts.createSourceFile(fileName, currentCode, currentFile.languageVersion, true);
154
- }
155
- if (allPrepend.length > 0) {
156
- currentCode = applyPrepend(currentCode, currentFile, allPrepend);
157
- currentFile = ts.createSourceFile(fileName, currentCode, currentFile.languageVersion, true);
158
- }
159
- if (allImports.length > 0) {
160
- currentCode = applyImports(currentCode, currentFile, allImports);
161
- currentFile = ts.createSourceFile(fileName, currentCode, currentFile.languageVersion, true);
162
- }
163
- return {
164
- changed: currentCode !== code,
165
- code: currentCode,
166
- sourceFile: currentFile
167
- };
168
+ }
169
+ return { changed, code: currentCode, sourceFile: currentFile };
168
170
  };
169
171
  export default { transform };
package/package.json CHANGED
@@ -39,7 +39,7 @@
39
39
  },
40
40
  "type": "module",
41
41
  "types": "build/index.d.ts",
42
- "version": "0.28.3",
42
+ "version": "0.28.4",
43
43
  "scripts": {
44
44
  "build": "tsc && tsc-alias",
45
45
  "-": "-"
@@ -73,6 +73,28 @@ function applyPrepend(code: string, file: ts.SourceFile, prepend: string[]): str
73
73
  return code.slice(0, position) + prepend.join('\n') + code.slice(position);
74
74
  }
75
75
 
76
+ function createPatchedProgram(baseProgram: ts.Program, fileName: string, newContent: string) {
77
+ let baseHost = ts.createCompilerHost(baseProgram.getCompilerOptions()),
78
+ options = baseProgram.getCompilerOptions();
79
+
80
+ return ts.createProgram(
81
+ baseProgram.getRootFileNames(),
82
+ options,
83
+ {
84
+ ...baseHost,
85
+ getSourceFile: (name, languageVersion) => {
86
+ if (name === fileName || name === fileName.replace(/\\/g, '/')) {
87
+ return ts.createSourceFile(name, newContent, languageVersion, true);
88
+ }
89
+ return baseProgram.getSourceFile(name) ?? baseHost.getSourceFile(name, languageVersion);
90
+ },
91
+ fileExists: (name) => baseHost.fileExists(name),
92
+ readFile: (name) => name === fileName ? newContent : baseHost.readFile(name)
93
+ },
94
+ baseProgram
95
+ );
96
+ }
97
+
76
98
  function hasPattern(code: string, patterns: string[]): boolean {
77
99
  for (let i = 0, n = patterns.length; i < n; i++) {
78
100
  if (code.indexOf(patterns[i]) !== -1) {
@@ -148,7 +170,7 @@ function modify(code: string, file: ts.SourceFile, pkg: string, options: ModifyO
148
170
  }
149
171
 
150
172
  return replaceReverse(code, replacements);
151
- };
173
+ }
152
174
 
153
175
  function replaceReverse(code: string, replacements: Replacement[]): string {
154
176
  if (replacements.length === 0) {
@@ -166,8 +188,7 @@ function replaceReverse(code: string, replacements: Replacement[]): string {
166
188
  }
167
189
 
168
190
  return result;
169
- };
170
-
191
+ }
171
192
 
172
193
  const transform = (
173
194
  plugins: Plugin[],
@@ -180,88 +201,58 @@ const transform = (
180
201
  return { changed: false, code, sourceFile: file };
181
202
  }
182
203
 
183
- let allImports = [],
184
- allPrepend = [],
185
- allReplacements = [],
186
- checker = program.getTypeChecker(),
187
- fileName = file.fileName,
188
- // Keep original source file for symbol resolution - checker operations
189
- // require nodes from a file that's part of the program's module graph
190
- originalFile = file;
191
-
192
- // Phase 1: Collect intents from all plugins using original source file
193
- // This ensures checker.getSymbolAtLocation() and getAliasedSymbol() work
194
- // correctly for re-exports and module resolution
204
+ let changed = false,
205
+ currentCode = code,
206
+ currentFile = file,
207
+ currentProgram = program,
208
+ fileName = file.fileName;
209
+
195
210
  for (let i = 0, n = plugins.length; i < n; i++) {
196
211
  let plugin = plugins[i];
197
212
 
198
- if (plugin.patterns && !hasPattern(code, plugin.patterns)) {
213
+ if (plugin.patterns && !hasPattern(currentCode, plugin.patterns)) {
199
214
  continue;
200
215
  }
201
216
 
202
217
  let { imports, prepend, replacements } = plugin.transform({
203
- checker,
204
- code,
205
- program,
206
- shared,
207
- sourceFile: originalFile
208
- });
218
+ checker: currentProgram.getTypeChecker(),
219
+ code: currentCode,
220
+ program: currentProgram,
221
+ shared,
222
+ sourceFile: currentFile
223
+ }),
224
+ pluginChanged = false;
209
225
 
210
226
  if (replacements?.length) {
211
- allReplacements.push(...replacements);
227
+ currentCode = applyIntents(currentCode, currentFile, replacements);
228
+ pluginChanged = true;
212
229
  }
213
230
 
214
231
  if (prepend?.length) {
215
- allPrepend.push(...prepend);
232
+ currentCode = applyPrepend(currentCode, currentFile, prepend);
233
+ pluginChanged = true;
216
234
  }
217
235
 
218
236
  if (imports?.length) {
219
- allImports.push(...imports);
237
+ currentCode = applyImports(currentCode, currentFile, imports);
238
+ pluginChanged = true;
220
239
  }
221
- }
222
240
 
223
- // Phase 2: Apply all collected intents
224
- let currentCode = code,
225
- currentFile = originalFile;
226
-
227
- if (allReplacements.length > 0) {
228
- // Sort by start position to detect overlaps
229
- allReplacements.sort((a, b) => a.node.getStart(originalFile) - b.node.getStart(originalFile));
230
-
231
- // Check for overlapping replacements
232
- for (let i = 1, n = allReplacements.length; i < n; i++) {
233
- let prev = allReplacements[i - 1],
234
- curr = allReplacements[i],
235
- prevEnd = prev.node.end,
236
- currStart = curr.node.getStart(originalFile);
237
-
238
- if (currStart < prevEnd) {
239
- console.warn(
240
- `[coordinator] Overlapping replacements detected at ${fileName}:`,
241
- `[${prev.node.getStart(originalFile)}-${prevEnd}] overlaps [${currStart}-${curr.node.end}]`
242
- );
241
+ if (pluginChanged) {
242
+ changed = true;
243
+ // Create patched program for next plugin
244
+ if (i < n - 1) {
245
+ currentProgram = createPatchedProgram(program, fileName, currentCode);
246
+ currentFile = currentProgram.getSourceFile(fileName) ||
247
+ ts.createSourceFile(fileName, currentCode, file.languageVersion, true);
248
+ }
249
+ else {
250
+ currentFile = ts.createSourceFile(fileName, currentCode, file.languageVersion, true);
243
251
  }
244
252
  }
245
-
246
- currentCode = applyIntents(currentCode, currentFile, allReplacements);
247
- currentFile = ts.createSourceFile(fileName, currentCode, currentFile.languageVersion, true);
248
- }
249
-
250
- if (allPrepend.length > 0) {
251
- currentCode = applyPrepend(currentCode, currentFile, allPrepend);
252
- currentFile = ts.createSourceFile(fileName, currentCode, currentFile.languageVersion, true);
253
- }
254
-
255
- if (allImports.length > 0) {
256
- currentCode = applyImports(currentCode, currentFile, allImports);
257
- currentFile = ts.createSourceFile(fileName, currentCode, currentFile.languageVersion, true);
258
253
  }
259
254
 
260
- return {
261
- changed: currentCode !== code,
262
- code: currentCode,
263
- sourceFile: currentFile
264
- };
255
+ return { changed, code: currentCode, sourceFile: currentFile };
265
256
  };
266
257
 
267
258