Skip to content

Commit bfb6188

Browse files
committed
refactor: separate into functions to improve readability
1 parent edb55d3 commit bfb6188

File tree

1 file changed

+123
-116
lines changed

1 file changed

+123
-116
lines changed

babel-plugin-code-push/index.js

+123-116
Original file line numberDiff line numberDiff line change
@@ -17,121 +17,10 @@ module.exports = function (babel, options) {
1717
: path.resolve(process.cwd(), "codepush.config.js");
1818

1919
// 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+
);
13524

13625
return {
13726
visitor: {
@@ -177,7 +66,7 @@ module.exports = function (babel, options) {
17766
OPTIONS_TO_BUNDLE.map((key) =>
17867
t.objectProperty(
17968
t.identifier(key),
180-
serializeConfigToNode(config[key])
69+
serializeConfigToNode(babel, importedIdentifiers, config[key])
18170
)
18271
)
18372
);
@@ -189,3 +78,121 @@ module.exports = function (babel, options) {
18978
},
19079
};
19180
};
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

Comments
 (0)