@@ -17,7 +17,7 @@ const fs = require('fs');
1717const path = require ( 'path' ) ;
1818const ts = require ( 'typescript' ) ;
1919const { minimatch } = require ( 'minimatch' ) ;
20- const { extractPlatformsFromAST } = require ( './platform-utils' ) ;
20+ const { extractPlatformsFromAST, getValidPlatforms } = require ( './platform-utils' ) ;
2121
2222const WORKSPACE_ROOT = path . join ( __dirname , '..' ) ;
2323const PLATFORMS = [ 'browser' , 'node' , 'react_native' ] ;
@@ -162,9 +162,57 @@ function ensurePlatformImport(content, filePath) {
162162}
163163
164164/**
165- * Remove existing __platforms export from the content
165+ * Check if __platforms export is at the end of the file
166166 */
167- function removeExistingPlatformExport ( content , filePath ) {
167+ function isPlatformExportAtEnd ( content , filePath ) {
168+ const sourceFile = ts . createSourceFile (
169+ filePath ,
170+ content ,
171+ ts . ScriptTarget . Latest ,
172+ true
173+ ) ;
174+
175+ let platformExportEnd = - 1 ;
176+ let lastStatementEnd = - 1 ;
177+
178+ function visit ( node ) {
179+ // Track the last statement
180+ if ( ts . isStatement ( node ) && node . parent === sourceFile ) {
181+ lastStatementEnd = Math . max ( lastStatementEnd , node . end ) ;
182+ }
183+
184+ // Find __platforms export
185+ if ( ts . isVariableStatement ( node ) ) {
186+ const hasExport = node . modifiers ?. some (
187+ mod => mod . kind === ts . SyntaxKind . ExportKeyword
188+ ) ;
189+
190+ if ( hasExport ) {
191+ for ( const declaration of node . declarationList . declarations ) {
192+ if ( ts . isVariableDeclaration ( declaration ) &&
193+ ts . isIdentifier ( declaration . name ) &&
194+ declaration . name . text === '__platforms' ) {
195+ platformExportEnd = node . end ;
196+ }
197+ }
198+ }
199+ }
200+ }
201+
202+ ts . forEachChild ( sourceFile , visit ) ;
203+
204+ if ( platformExportEnd === - 1 ) {
205+ return false ; // No export found
206+ }
207+
208+ // Check if __platforms is the last statement (allowing for trailing whitespace/newlines)
209+ return platformExportEnd === lastStatementEnd ;
210+ }
211+
212+ /**
213+ * Extract the existing __platforms export statement as-is
214+ */
215+ function extractExistingPlatformExport ( content , filePath ) {
168216 const sourceFile = ts . createSourceFile (
169217 filePath ,
170218 content ,
@@ -173,6 +221,7 @@ function removeExistingPlatformExport(content, filePath) {
173221 ) ;
174222
175223 const lines = content . split ( '\n' ) ;
224+ let exportStatement = null ;
176225 const linesToRemove = new Set ( ) ;
177226
178227 function visit ( node ) {
@@ -186,13 +235,16 @@ function removeExistingPlatformExport(content, filePath) {
186235 if ( ts . isVariableDeclaration ( declaration ) &&
187236 ts . isIdentifier ( declaration . name ) &&
188237 declaration . name . text === '__platforms' ) {
189- // Mark this line for removal
238+ // Extract the full statement
190239 const startLine = sourceFile . getLineAndCharacterOfPosition ( node . getStart ( ) ) . line ;
191240 const endLine = sourceFile . getLineAndCharacterOfPosition ( node . getEnd ( ) ) . line ;
192241
242+ const statementLines = [ ] ;
193243 for ( let i = startLine ; i <= endLine ; i ++ ) {
194244 linesToRemove . add ( i ) ;
245+ statementLines . push ( lines [ i ] ) ;
195246 }
247+ exportStatement = statementLines . join ( '\n' ) ;
196248 }
197249 }
198250 }
@@ -201,23 +253,29 @@ function removeExistingPlatformExport(content, filePath) {
201253
202254 ts . forEachChild ( sourceFile , visit ) ;
203255
204- if ( linesToRemove . size === 0 ) {
205- return { content, removed : false } ;
256+ if ( ! exportStatement ) {
257+ return { content, statement : null , removed : false } ;
206258 }
207259
208260 const filteredLines = lines . filter ( ( _ , index ) => ! linesToRemove . has ( index ) ) ;
209- return { content : filteredLines . join ( '\n' ) , removed : true } ;
261+ return { content : filteredLines . join ( '\n' ) , statement : exportStatement , removed : true } ;
210262}
211263
212264/**
213265 * Add __platforms export at the end of the file
214266 */
267+ function addPlatformExportStatement ( content , statement ) {
268+ // Trim trailing whitespace and add the statement (with blank line before)
269+ return content . trimEnd ( ) + '\n\n' + statement + '\n' ;
270+ }
271+
272+ /**
273+ * Add __platforms export at the end of the file (when creating new)
274+ */
215275function addPlatformExport ( content , platforms ) {
216276 const platformsStr = platforms . map ( p => `'${ p } '` ) . join ( ', ' ) ;
217- const exportStatement = `\n\nexport const __platforms: Platform[] = [${ platformsStr } ];\n` ;
218-
219- // Trim trailing whitespace and ensure we end with the export (with blank line before)
220- return content . trimEnd ( ) + exportStatement ;
277+ const exportStatement = `export const __platforms: Platform[] = [${ platformsStr } ];` ;
278+ return addPlatformExportStatement ( content , exportStatement ) ;
221279}
222280
223281/**
@@ -226,66 +284,80 @@ function addPlatformExport(content, platforms) {
226284function processFile ( filePath ) {
227285 let content = fs . readFileSync ( filePath , 'utf-8' ) ;
228286
287+ // Get valid platforms for validation
288+ const validPlatforms = getValidPlatforms ( WORKSPACE_ROOT ) ;
289+
229290 // Use TypeScript parser to check for existing __platforms
230- const existingPlatforms = extractPlatformsFromAST (
231- ts . createSourceFile ( filePath , content , ts . ScriptTarget . Latest , true )
291+ const result = extractPlatformsFromAST (
292+ ts . createSourceFile ( filePath , content , ts . ScriptTarget . Latest , true ) ,
293+ filePath ,
294+ validPlatforms // Validate platform values
232295 ) ;
233296
297+ // Extract platforms and error info from result
298+ const existingPlatforms = result . success ? result . platforms : null ;
299+ const needsFixing = result . error && [ 'MISSING' , 'NOT_CONST' , 'NOT_ARRAY' , 'EMPTY_ARRAY' , 'NOT_LITERALS' , 'INVALID_VALUES' ] . includes ( result . error . type ) ;
300+
234301 // Determine platforms for this file
235- // If file already has platforms, use those (preserve existing values)
302+ // If file already has valid platforms, use those (preserve existing values)
236303 // Otherwise, determine from filename or default to universal
237304 let platforms ;
238- if ( existingPlatforms === null ) {
239- // No __platforms export, determine from filename
305+ if ( ! existingPlatforms || needsFixing ) {
306+ // No __platforms export or has errors , determine from filename
240307 const platformsFromFilename = getPlatformFromFilename ( filePath ) ;
241308 platforms = platformsFromFilename || [ '__universal__' ] ;
242- } else if ( Array . isArray ( existingPlatforms ) ) {
309+ } else {
243310 // Has valid __platforms, preserve the existing values
244311 platforms = existingPlatforms ;
245- } else {
246- // Has issues (NOT_CONST, NOT_LITERALS), determine from filename
247- const platformsFromFilename = getPlatformFromFilename ( filePath ) ;
248- platforms = platformsFromFilename || [ '__universal__' ] ;
249312 }
250313
251314 let modified = false ;
252315 let action = 'skipped' ;
253316
254- if ( existingPlatforms === null ) {
255- // No __platforms export, add it
256- action = 'added' ;
257- modified = true ;
258- } else if ( Array . isArray ( existingPlatforms ) ) {
259- // Has __platforms but might need to be moved or updated
260- // Remove existing and re-add at the end
261- const removed = removeExistingPlatformExport ( content , filePath ) ;
262- if ( removed . removed ) {
263- content = removed . content ;
264- action = 'moved' ;
265- modified = true ;
266- } else {
267- return { skipped : true , reason : 'already has export at end' } ;
317+ if ( needsFixing ) {
318+ // Has issues (MISSING, NOT_CONST, NOT_LITERALS, INVALID_VALUES, etc.), fix them
319+ const extracted = extractExistingPlatformExport ( content , filePath ) ;
320+ if ( extracted . removed ) {
321+ content = extracted . content ;
268322 }
269- } else {
270- // Has issues (NOT_CONST, NOT_LITERALS), fix them
271- const removed = removeExistingPlatformExport ( content , filePath ) ;
272- content = removed . content ;
273323 action = 'fixed' ;
274324 modified = true ;
275- }
276-
277- if ( modified ) {
325+
278326 // Ensure Platform import exists
279327 const importResult = ensurePlatformImport ( content , filePath ) ;
280328 content = importResult . content ;
281329
282330 // Add __platforms export at the end
283331 content = addPlatformExport ( content , platforms ) ;
332+ } else if ( existingPlatforms ) {
333+ // Has valid __platforms structure - check if it's already at the end
334+ if ( isPlatformExportAtEnd ( content , filePath ) ) {
335+ return { skipped : true , reason : 'already has export at end' } ;
336+ }
284337
338+ // Extract it and move to end without modification
339+ const extracted = extractExistingPlatformExport ( content , filePath ) ;
340+ if ( extracted . removed ) {
341+ content = extracted . content ;
342+
343+ // Ensure Platform import exists
344+ const importResult = ensurePlatformImport ( content , filePath ) ;
345+ content = importResult . content ;
346+
347+ // Add the original statement at the end
348+ content = addPlatformExportStatement ( content , extracted . statement ) ;
349+ action = 'moved' ;
350+ modified = true ;
351+ } else {
352+ return { skipped : true , reason : 'could not extract export' } ;
353+ }
354+ }
355+
356+ if ( modified ) {
285357 // Write back to file
286358 fs . writeFileSync ( filePath , content , 'utf-8' ) ;
287359
288- return { skipped : false , action, platforms, addedImport : importResult . added } ;
360+ return { skipped : false , action, platforms } ;
289361 }
290362
291363 return { skipped : true , reason : 'no changes needed' } ;
@@ -345,15 +417,15 @@ function main() {
345417 switch ( result . action ) {
346418 case 'added' :
347419 added ++ ;
348- console . log ( `➕ ${ relativePath } → [${ result . platforms . join ( ', ' ) } ]${ result . addedImport ? ' (added import)' : '' } ` ) ;
420+ console . log ( `➕ ${ relativePath } → [${ result . platforms . join ( ', ' ) } ]` ) ;
349421 break ;
350422 case 'moved' :
351423 moved ++ ;
352- console . log ( `📍 ${ relativePath } → moved to end [${ result . platforms . join ( ', ' ) } ]${ result . addedImport ? ' (added import)' : '' } ` ) ;
424+ console . log ( `📍 ${ relativePath } → moved to end [${ result . platforms . join ( ', ' ) } ]` ) ;
353425 break ;
354426 case 'fixed' :
355427 fixed ++ ;
356- console . log ( `🔧 ${ relativePath } → fixed [${ result . platforms . join ( ', ' ) } ]${ result . addedImport ? ' (added import)' : '' } ` ) ;
428+ console . log ( `🔧 ${ relativePath } → fixed [${ result . platforms . join ( ', ' ) } ]` ) ;
357429 break ;
358430 }
359431 }
0 commit comments