11#!/usr/bin/env node
22
3+ /**
4+ * Copyright 2025, Optimizely
5+ *
6+ * Licensed under the Apache License, Version 2.0 (the "License");
7+ * you may not use this file except in compliance with the License.
8+ * You may obtain a copy of the License at
9+ *
10+ * http://www.apache.org/licenses/LICENSE-2.0
11+ *
12+ * Unless required by applicable law or agreed to in writing, software
13+ * distributed under the License is distributed on an "AS IS" BASIS,
14+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+ * See the License for the specific language governing permissions and
16+ * limitations under the License.
17+ */
18+
319/**
420 * Auto-add __platforms to files
521 *
1329 * 4. Inserts __platforms export at the end of the file
1430 */
1531
32+ /* eslint-disable @typescript-eslint/no-var-requires */
1633const fs = require ( 'fs' ) ;
1734const path = require ( 'path' ) ;
1835const ts = require ( 'typescript' ) ;
@@ -84,26 +101,27 @@ function ensurePlatformImport(content, filePath) {
84101 let lastImportEnd = 0 ;
85102
86103 function visit ( node ) {
87- if ( ts . isImportDeclaration ( node ) ) {
88- const moduleSpecifier = node . moduleSpecifier ;
89- if ( ts . isStringLiteral ( moduleSpecifier ) ) {
90- // Check if this import is from platform_support
91- if ( moduleSpecifier . text . includes ( 'platform_support' ) ) {
92- // Check if it imports Platform type
93- if ( node . importClause && node . importClause . namedBindings ) {
94- const namedBindings = node . importClause . namedBindings ;
95- if ( ts . isNamedImports ( namedBindings ) ) {
96- for ( const element of namedBindings . elements ) {
97- if ( element . name . text === 'Platform' ) {
98- hasPlatformImport = true ;
99- break ;
100- }
101- }
102- }
103- }
104- }
104+ if ( ! ts . isImportDeclaration ( node ) ) return ;
105+
106+ lastImportEnd = node . end ;
107+
108+ const moduleSpecifier = node . moduleSpecifier ;
109+ if ( ! ts . isStringLiteral ( moduleSpecifier ) ) return ;
110+
111+ // Check if this import is from platform_support
112+ if ( ! moduleSpecifier . text . includes ( 'platform_support' ) ) return ;
113+
114+ // Check if it imports Platform type
115+ if ( ! node . importClause ?. namedBindings ) return ;
116+
117+ const namedBindings = node . importClause . namedBindings ;
118+ if ( ! ts . isNamedImports ( namedBindings ) ) return ;
119+
120+ for ( const element of namedBindings . elements ) {
121+ if ( element . name . text === 'Platform' ) {
122+ hasPlatformImport = true ;
123+ break ;
105124 }
106- lastImportEnd = node . end ;
107125 }
108126 }
109127
@@ -175,19 +193,19 @@ function isPlatformExportAtEnd(content, filePath) {
175193 }
176194
177195 // Find __platforms export
178- if ( ts . isVariableStatement ( node ) ) {
179- const hasExport = node . modifiers ?. some (
180- mod => mod . kind === ts . SyntaxKind . ExportKeyword
181- ) ;
182-
183- if ( hasExport ) {
184- for ( const declaration of node . declarationList . declarations ) {
185- if ( ts . isVariableDeclaration ( declaration ) &&
186- ts . isIdentifier ( declaration . name ) &&
187- declaration . name . text === '__platforms' ) {
188- platformExportEnd = node . end ;
189- }
190- }
196+ if ( ! ts . isVariableStatement ( node ) ) return ;
197+
198+ const hasExport = node . modifiers ?. some (
199+ mod => mod . kind === ts . SyntaxKind . ExportKeyword
200+ ) ;
201+
202+ if ( ! hasExport ) return ;
203+
204+ for ( const declaration of node . declarationList . declarations ) {
205+ if ( ts . isVariableDeclaration ( declaration ) &&
206+ ts . isIdentifier ( declaration . name ) &&
207+ declaration . name . text === '__platforms' ) {
208+ platformExportEnd = node . end ;
191209 }
192210 }
193211 }
@@ -218,40 +236,42 @@ function extractExistingPlatformExport(content, filePath) {
218236 const linesToRemove = new Set ( ) ;
219237
220238 function visit ( node ) {
221- if ( ts . isVariableStatement ( node ) ) {
222- const hasExport = node . modifiers ?. some (
223- mod => mod . kind === ts . SyntaxKind . ExportKeyword
224- ) ;
239+ if ( ! ts . isVariableStatement ( node ) ) return ;
240+
241+ const hasExport = node . modifiers ?. some (
242+ mod => mod . kind === ts . SyntaxKind . ExportKeyword
243+ ) ;
244+
245+ if ( ! hasExport ) return ;
246+
247+ for ( const declaration of node . declarationList . declarations ) {
248+ if ( ! ts . isVariableDeclaration ( declaration ) ||
249+ ! ts . isIdentifier ( declaration . name ) ||
250+ declaration . name . text !== '__platforms' ) {
251+ continue ;
252+ }
225253
226- if ( hasExport ) {
227- for ( const declaration of node . declarationList . declarations ) {
228- if ( ts . isVariableDeclaration ( declaration ) &&
229- ts . isIdentifier ( declaration . name ) &&
230- declaration . name . text === '__platforms' ) {
231- // Extract the full statement
232- const startLine = sourceFile . getLineAndCharacterOfPosition ( node . getStart ( ) ) . line ;
233- const endLine = sourceFile . getLineAndCharacterOfPosition ( node . getEnd ( ) ) . line ;
234-
235- const statementLines = [ ] ;
236- for ( let i = startLine ; i <= endLine ; i ++ ) {
237- linesToRemove . add ( i ) ;
238- statementLines . push ( lines [ i ] ) ;
239- }
240- exportStatement = statementLines . join ( '\n' ) ;
241- }
242- }
254+ // Extract the full statement
255+ const startLine = sourceFile . getLineAndCharacterOfPosition ( node . getStart ( ) ) . line ;
256+ const endLine = sourceFile . getLineAndCharacterOfPosition ( node . getEnd ( ) ) . line ;
257+
258+ const statementLines = [ ] ;
259+ for ( let i = startLine ; i <= endLine ; i ++ ) {
260+ linesToRemove . add ( i ) ;
261+ statementLines . push ( lines [ i ] ) ;
243262 }
263+ exportStatement = statementLines . join ( '\n' ) ;
244264 }
245265 }
246266
247267 ts . forEachChild ( sourceFile , visit ) ;
248268
249269 if ( ! exportStatement ) {
250- return { content , statement : null , removed : false } ;
270+ return { restContent : content , platformExportStatement : null } ;
251271 }
252272
253273 const filteredLines = lines . filter ( ( _ , index ) => ! linesToRemove . has ( index ) ) ;
254- return { content : filteredLines . join ( '\n' ) , statement : exportStatement , removed : true } ;
274+ return { restContent : filteredLines . join ( '\n' ) , platformExportStatement : exportStatement } ;
255275}
256276
257277/**
@@ -288,7 +308,7 @@ function processFile(filePath) {
288308 // If file already has valid platforms, use those (preserve existing values)
289309 // Otherwise, determine from filename or default to universal
290310 let platforms ;
291- if ( ! existingPlatforms || needsFixing ) {
311+ if ( needsFixing ) {
292312 // No __platforms export or has errors, determine from filename
293313 const platformsFromFilename = getPlatformFromFilename ( filePath ) ;
294314 platforms = platformsFromFilename || [ '__universal__' ] ;
@@ -303,9 +323,8 @@ function processFile(filePath) {
303323 if ( needsFixing ) {
304324 // Has issues (MISSING, NOT_ARRAY, NOT_LITERALS, INVALID_VALUES, etc.), fix them
305325 const extracted = extractExistingPlatformExport ( content , filePath ) ;
306- if ( extracted . removed ) {
307- content = extracted . content ;
308- }
326+ content = extracted . restContent ;
327+
309328 action = 'fixed' ;
310329 modified = true ;
311330
@@ -323,20 +342,12 @@ function processFile(filePath) {
323342
324343 // Extract it and move to end without modification
325344 const extracted = extractExistingPlatformExport ( content , filePath ) ;
326- if ( extracted . removed ) {
327- content = extracted . content ;
328-
329- // Ensure Platform import exists
330- const importResult = ensurePlatformImport ( content , filePath ) ;
331- content = importResult . content ;
332-
333- // Add the original statement at the end
334- content = addPlatformExportStatement ( content , extracted . statement ) ;
335- action = 'moved' ;
336- modified = true ;
337- } else {
338- return { skipped : true , reason : 'could not extract export' } ;
339- }
345+ content = extracted . restContent ;
346+
347+ // Add the original statement at the end
348+ content = addPlatformExportStatement ( content , extracted . platformExportStatement ) ;
349+ action = 'moved' ;
350+ modified = true ;
340351 }
341352
342353 if ( modified ) {
0 commit comments