1+ /* eslint-disable @typescript-eslint/no-var-requires */
2+ /* eslint-disable no-inner-declarations */
13/**
24 * Platform Utilities
35 *
@@ -55,6 +57,9 @@ function getValidPlatforms(workspaceRoot) {
5557 platforms . push ( type . literal . text ) ;
5658 }
5759 }
60+ } else if ( ts . isLiteralTypeNode ( node . type ) && ts . isStringLiteral ( node . type . literal ) ) {
61+ // Handle single literal type: type Platform = 'browser';
62+ platforms . push ( node . type . literal . text ) ;
5863 }
5964 }
6065
@@ -77,21 +82,27 @@ function getValidPlatforms(workspaceRoot) {
7782}
7883
7984/**
80- * Extracts __platforms array from TypeScript AST
85+ * Extracts __platforms array from TypeScript AST with detailed error reporting
8186 *
82- * Returns:
83- * - string[] if valid platforms array found
84- * - 'NOT_CONST' if __platforms is not declared as const
85- * - 'NOT_LITERALS' if array contains non-literal values
86- * - null if __platforms export not found
87+ * Returns an object with:
88+ * - success: boolean - whether extraction was successful
89+ * - platforms: string[] - array of platform values (if successful)
90+ * - error: object - detailed error information (if unsuccessful)
91+ * - type: 'MISSING' | 'NOT_CONST' | 'NOT_ARRAY' | 'EMPTY_ARRAY' | 'NOT_LITERALS' | 'INVALID_VALUES'
92+ * - message: string - human-readable error message
93+ * - invalidValues: string[] - list of invalid platform values (for INVALID_VALUES type)
8794 *
8895 * @param {ts.SourceFile } sourceFile - TypeScript source file AST
89- * @returns {string[] | 'NOT_CONST' | 'NOT_LITERALS' | null }
96+ * @param {string } filePath - File path for context in error messages
97+ * @param {string[] } validPlatforms - Array of valid platform values
98+ * @returns {Object }
9099 */
91- function extractPlatformsFromAST ( sourceFile ) {
92- let platforms = null ;
100+ function extractPlatformsFromAST ( sourceFile , filePath , validPlatforms ) {
101+ let found = false ;
102+ let isConst = false ;
103+ let isArray = false ;
104+ let platforms = [ ] ;
93105 let hasNonStringLiteral = false ;
94- let isNotConst = false ;
95106
96107 function visit ( node ) {
97108 // Look for: export const __platforms = [...]
@@ -102,17 +113,15 @@ function extractPlatformsFromAST(sourceFile) {
102113 ) ;
103114
104115 if ( hasExport ) {
105- // Check if declaration is const
106- const isConst = ( node . declarationList . flags & ts . NodeFlags . Const ) !== 0 ;
116+ const isConstDecl = ( node . declarationList . flags & ts . NodeFlags . Const ) !== 0 ;
107117
108118 for ( const declaration of node . declarationList . declarations ) {
109119 if ( ts . isVariableDeclaration ( declaration ) &&
110120 ts . isIdentifier ( declaration . name ) &&
111121 declaration . name . text === '__platforms' ) {
112122
113- if ( ! isConst ) {
114- isNotConst = true ;
115- }
123+ found = true ;
124+ isConst = isConstDecl ;
116125
117126 let initializer = declaration . initializer ;
118127
@@ -126,9 +135,11 @@ function extractPlatformsFromAST(sourceFile) {
126135 initializer = initializer . expression ;
127136 }
128137
129- // Extract array elements
138+ // Check if it's an array
130139 if ( initializer && ts . isArrayLiteralExpression ( initializer ) ) {
131- platforms = [ ] ;
140+ isArray = true ;
141+
142+ // Extract array elements
132143 for ( const element of initializer . elements ) {
133144 if ( ts . isStringLiteral ( element ) ) {
134145 platforms . push ( element . text ) ;
@@ -137,8 +148,9 @@ function extractPlatformsFromAST(sourceFile) {
137148 hasNonStringLiteral = true ;
138149 }
139150 }
140- return ; // Found it, stop visiting
141151 }
152+
153+ return ; // Found it, stop visiting
142154 }
143155 }
144156 }
@@ -149,36 +161,104 @@ function extractPlatformsFromAST(sourceFile) {
149161
150162 visit ( sourceFile ) ;
151163
152- if ( platforms !== null ) {
153- if ( isNotConst ) {
154- return 'NOT_CONST' ;
155- }
156- if ( hasNonStringLiteral ) {
157- return 'NOT_LITERALS' ;
164+ // Detailed error reporting
165+ if ( ! found ) {
166+ return {
167+ success : false ,
168+ error : {
169+ type : 'MISSING' ,
170+ message : `File does not export '__platforms' constant`
171+ }
172+ } ;
173+ }
174+
175+ if ( ! isConst ) {
176+ return {
177+ success : false ,
178+ error : {
179+ type : 'NOT_CONST' ,
180+ message : `'__platforms' must be declared with 'const', found non-const declaration`
181+ }
182+ } ;
183+ }
184+
185+ if ( ! isArray ) {
186+ return {
187+ success : false ,
188+ error : {
189+ type : 'NOT_ARRAY' ,
190+ message : `'__platforms' must be an array literal, found ${ platforms . length === 0 ? 'non-array value' : 'other type' } `
191+ }
192+ } ;
193+ }
194+
195+ if ( hasNonStringLiteral ) {
196+ return {
197+ success : false ,
198+ error : {
199+ type : 'NOT_LITERALS' ,
200+ message : `'__platforms' must only contain string literals, found non-literal values`
201+ }
202+ } ;
203+ }
204+
205+ if ( platforms . length === 0 ) {
206+ return {
207+ success : false ,
208+ error : {
209+ type : 'EMPTY_ARRAY' ,
210+ message : `'__platforms' array is empty, must contain at least one platform`
211+ }
212+ } ;
213+ }
214+
215+ // Validate platform values if validPlatforms provided
216+ if ( validPlatforms ) {
217+ const invalidPlatforms = platforms . filter ( p => ! validPlatforms . includes ( p ) ) ;
218+ if ( invalidPlatforms . length > 0 ) {
219+ return {
220+ success : false ,
221+ error : {
222+ type : 'INVALID_VALUES' ,
223+ message : `Invalid platform values found` ,
224+ invalidValues : invalidPlatforms
225+ }
226+ } ;
158227 }
159228 }
160229
161- return platforms ;
230+ return {
231+ success : true ,
232+ platforms : platforms
233+ } ;
162234}
163235
164236/**
165- * Extract platforms from a file path
237+ * Extract platforms from a file path with detailed error reporting
166238 *
167239 * @param {string } filePath - Absolute path to the file
168- * @returns {string[] | 'NOT_CONST' | 'NOT_LITERALS' | null }
240+ * @param {string } workspaceRoot - Workspace root for resolving valid platforms
241+ * @returns {Object } Result object with success, platforms, and error information
169242 */
170- function extractPlatformsFromFile ( filePath ) {
243+ function extractPlatformsFromFile ( filePath , workspaceRoot ) {
171244 try {
245+ const validPlatforms = workspaceRoot ? getValidPlatforms ( workspaceRoot ) : null ;
172246 const content = fs . readFileSync ( filePath , 'utf-8' ) ;
173247 const sourceFile = ts . createSourceFile (
174248 filePath ,
175249 content ,
176250 ts . ScriptTarget . Latest ,
177251 true
178252 ) ;
179- return extractPlatformsFromAST ( sourceFile ) ;
253+ return extractPlatformsFromAST ( sourceFile , filePath , validPlatforms ) ;
180254 } catch ( error ) {
181- return null ;
255+ return {
256+ success : false ,
257+ error : {
258+ type : 'READ_ERROR' ,
259+ message : `Failed to read or parse file: ${ error . message } `
260+ }
261+ } ;
182262 }
183263}
184264
0 commit comments