@@ -17,121 +17,10 @@ module.exports = function (babel, options) {
17
17
: path . resolve ( process . cwd ( ) , "codepush.config.js" ) ;
18
18
19
19
// Load config and imports from `codepush.config.js`
20
- const { config, configImports, importedIdentifiers } = loadConfig ( configPath ) ;
21
-
22
- // Helper to serialize config values to AST nodes
23
- function serializeConfigToNode ( value ) {
24
- if (
25
- [ "string" , "number" , "boolean" ] . includes ( typeof value ) ||
26
- value === null
27
- ) {
28
- return t . valueToNode ( value ) ; // Handle primitive values
29
- }
30
-
31
- if ( Array . isArray ( value ) ) {
32
- return t . arrayExpression ( value . map ( serializeConfigToNode ) ) ; // Recursively handle arrays
33
- }
34
-
35
- if ( typeof value === "object" && value !== null ) {
36
- return t . objectExpression (
37
- Object . entries ( value ) . map ( ( [ key , val ] ) =>
38
- t . objectProperty ( t . identifier ( key ) , serializeConfigToNode ( val ) )
39
- )
40
- ) ;
41
- }
42
-
43
- // Use identifier for imported symbols instead of inlining
44
- if ( importedIdentifiers . has ( value . name ) ) {
45
- return t . identifier ( value . name ) ;
46
- }
47
-
48
- // For inline functions, parse and serialize them as expressions
49
- if ( typeof value === "function" ) {
50
- const valueString = value . toString ( ) ;
51
- try {
52
- return parseExpression ( valueString , { sourceType : "module" } ) ;
53
- } catch ( error ) {
54
- throw new Error (
55
- `Failed to parse function ${ value . name || "anonymous" } : ${
56
- error . message
57
- } `
58
- ) ;
59
- }
60
- }
61
-
62
- throw new Error ( `Unsupported config value type: ${ typeof value } ` ) ;
63
- }
64
-
65
- function loadConfig ( configPath ) {
66
- if ( ! fs . existsSync ( configPath ) ) {
67
- throw new Error (
68
- "codepush.config.js not found. Please ensure it exists in the root directory."
69
- ) ;
70
- }
71
-
72
- const configModule = require ( configPath ) ;
73
-
74
- const configCode = fs . readFileSync ( configPath , "utf8" ) ;
75
- const ast = parse ( configCode , {
76
- sourceType : "module" ,
77
- } ) ;
78
-
79
- // Extract import declarations and track imported identifiers
80
- const imports = [ ] ;
81
- const importedIdentifiers = new Set ( ) ;
82
-
83
- const convertRequireIntoImportStatement = ( declaration ) => {
84
- const moduleName = declaration . init . arguments [ 0 ] . value ;
85
- if ( t . isIdentifier ( declaration . id ) ) {
86
- // Case for `const fs = require("fs")`
87
- return t . importDeclaration (
88
- [ t . importDefaultSpecifier ( declaration . id ) ] ,
89
- t . stringLiteral ( moduleName )
90
- ) ;
91
- } else if ( t . isObjectPattern ( declaration . id ) ) {
92
- // Case for `const { parse } = require("module")`
93
- const importSpecifiers = declaration . id . properties . map ( ( property ) =>
94
- t . importSpecifier ( property . value , property . key )
95
- ) ;
96
- return t . importDeclaration (
97
- importSpecifiers ,
98
- t . stringLiteral ( moduleName )
99
- ) ;
100
- }
101
- } ;
102
-
103
- ast . program . body . forEach ( ( node ) => {
104
- if ( t . isImportDeclaration ( node ) ) {
105
- // Handle import statements
106
- imports . push ( node ) ;
107
- node . specifiers . forEach ( ( specifier ) => {
108
- importedIdentifiers . add ( specifier . local . name ) ;
109
- } ) ;
110
- } else if ( t . isVariableDeclaration ( node ) ) {
111
- node . declarations . forEach ( ( declaration ) => {
112
- if (
113
- t . isCallExpression ( declaration . init ) &&
114
- t . isIdentifier ( declaration . init . callee , { name : "require" } ) &&
115
- declaration . init . arguments . length === 1 &&
116
- t . isStringLiteral ( declaration . init . arguments [ 0 ] )
117
- ) {
118
- let importDeclaration =
119
- convertRequireIntoImportStatement ( declaration ) ;
120
- imports . push ( importDeclaration ) ;
121
- declaration . id . properties . forEach ( ( dec ) => {
122
- importedIdentifiers . add ( dec . value . name ) ; // Track the imported identifier
123
- } ) ;
124
- }
125
- } ) ;
126
- }
127
- } ) ;
128
-
129
- return {
130
- config : configModule . default || configModule ,
131
- configImports : imports ,
132
- importedIdentifiers,
133
- } ;
134
- }
20
+ const { config, configImports, importedIdentifiers } = loadConfig (
21
+ babel ,
22
+ configPath
23
+ ) ;
135
24
136
25
return {
137
26
visitor : {
@@ -177,7 +66,7 @@ module.exports = function (babel, options) {
177
66
OPTIONS_TO_BUNDLE . map ( ( key ) =>
178
67
t . objectProperty (
179
68
t . identifier ( key ) ,
180
- serializeConfigToNode ( config [ key ] )
69
+ serializeConfigToNode ( babel , importedIdentifiers , config [ key ] )
181
70
)
182
71
)
183
72
) ;
@@ -189,3 +78,121 @@ module.exports = function (babel, options) {
189
78
} ,
190
79
} ;
191
80
} ;
81
+
82
+ /** loads config file from configPath */
83
+ function loadConfig ( babel , configPath ) {
84
+ if ( ! fs . existsSync ( configPath ) ) {
85
+ throw new Error (
86
+ "codepush.config.js not found. Please ensure it exists in the root directory."
87
+ ) ;
88
+ }
89
+
90
+ const { types : t } = babel ;
91
+ const configModule = require ( configPath ) ;
92
+
93
+ const configCode = fs . readFileSync ( configPath , "utf8" ) ;
94
+ const ast = parse ( configCode , {
95
+ sourceType : "module" ,
96
+ } ) ;
97
+
98
+ // Extract import declarations and track imported identifiers
99
+ const imports = [ ] ;
100
+ const importedIdentifiers = new Set ( ) ;
101
+
102
+ const convertRequireIntoImportStatement = ( declaration ) => {
103
+ const moduleName = declaration . init . arguments [ 0 ] . value ;
104
+ if ( t . isIdentifier ( declaration . id ) ) {
105
+ // Case for `const fs = require("fs")`
106
+ return t . importDeclaration (
107
+ [ t . importDefaultSpecifier ( declaration . id ) ] ,
108
+ t . stringLiteral ( moduleName )
109
+ ) ;
110
+ } else if ( t . isObjectPattern ( declaration . id ) ) {
111
+ // Case for `const { parse } = require("module")`
112
+ const importSpecifiers = declaration . id . properties . map ( ( property ) =>
113
+ t . importSpecifier ( property . value , property . key )
114
+ ) ;
115
+ return t . importDeclaration ( importSpecifiers , t . stringLiteral ( moduleName ) ) ;
116
+ }
117
+ } ;
118
+
119
+ ast . program . body . forEach ( ( node ) => {
120
+ if ( t . isImportDeclaration ( node ) ) {
121
+ // Handle import statements
122
+ imports . push ( node ) ;
123
+ node . specifiers . forEach ( ( specifier ) => {
124
+ importedIdentifiers . add ( specifier . local . name ) ;
125
+ } ) ;
126
+ } else if ( t . isVariableDeclaration ( node ) ) {
127
+ // Handle require function
128
+ node . declarations . forEach ( ( declaration ) => {
129
+ if (
130
+ t . isCallExpression ( declaration . init ) &&
131
+ t . isIdentifier ( declaration . init . callee , { name : "require" } ) &&
132
+ declaration . init . arguments . length === 1 &&
133
+ t . isStringLiteral ( declaration . init . arguments [ 0 ] )
134
+ ) {
135
+ const importDeclaration =
136
+ convertRequireIntoImportStatement ( declaration ) ;
137
+ imports . push ( importDeclaration ) ;
138
+ declaration . id . properties . forEach ( ( dec ) => {
139
+ importedIdentifiers . add ( dec . value . name ) ; // Track the imported identifier
140
+ } ) ;
141
+ }
142
+ } ) ;
143
+ }
144
+ } ) ;
145
+
146
+ return {
147
+ config : configModule . default || configModule ,
148
+ configImports : imports ,
149
+ importedIdentifiers,
150
+ } ;
151
+ }
152
+
153
+ /** Helper to serialize config values to AST nodes */
154
+ function serializeConfigToNode ( babel , importedIdentifiers , value ) {
155
+ const { types : t } = babel ;
156
+ if ( [ "string" , "number" , "boolean" ] . includes ( typeof value ) || value == null ) {
157
+ return t . valueToNode ( value ) ; // Handle primitive values
158
+ }
159
+
160
+ if ( Array . isArray ( value ) ) {
161
+ return t . arrayExpression (
162
+ // Recursively handle arrays
163
+ value . map ( ( v ) => serializeConfigToNode ( babel , importedIdentifiers , v ) )
164
+ ) ;
165
+ }
166
+
167
+ if ( typeof value === "object" ) {
168
+ return t . objectExpression (
169
+ Object . entries ( value ) . map ( ( [ key , val ] ) =>
170
+ t . objectProperty (
171
+ t . identifier ( key ) ,
172
+ serializeConfigToNode ( babel , importedIdentifiers , val )
173
+ )
174
+ )
175
+ ) ;
176
+ }
177
+
178
+ // Use identifier for imported symbols instead of inlining
179
+ if ( importedIdentifiers . has ( value . name ) ) {
180
+ return t . identifier ( value . name ) ;
181
+ }
182
+
183
+ // For inline functions, parse and serialize them as expressions
184
+ if ( typeof value === "function" ) {
185
+ const valueString = value . toString ( ) ;
186
+ try {
187
+ return parseExpression ( valueString , { sourceType : "module" } ) ;
188
+ } catch ( error ) {
189
+ throw new Error (
190
+ `Failed to parse function ${ value . name || "anonymous" } : ${
191
+ error . message
192
+ } `
193
+ ) ;
194
+ }
195
+ }
196
+
197
+ throw new Error ( `Unsupported config value type: ${ typeof value } ` ) ;
198
+ }
0 commit comments