Skip to content

Commit 5d423df

Browse files
committed
refactor: separate cb hell to fns
1 parent e1095d3 commit 5d423df

1 file changed

Lines changed: 59 additions & 58 deletions

File tree

  • packages/feature-flags-webpack-plugin/src
Lines changed: 59 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,73 @@
1-
import { Plugin, Compiler } from 'webpack'
1+
import { Expression, CallExpression, Identifier, SpreadElement } from 'estree'
2+
import { Compilation, Compiler, javascript } from 'webpack'
23

3-
const featureFlagsFunctionName = 'isFeatureEnabled'
4+
type PluginOptions = {
5+
/**
6+
* Function name for match
7+
*
8+
* @default 'isFeatureEnabled'
9+
*/
10+
isFeatureEnabledFnName: string
11+
/**
12+
* Object with flags
13+
*/
14+
flags: Record<string, any>
15+
}
416

5-
function isFeatureFlagFunction(expression: any) {
6-
if (expression.callee.property) {
7-
return expression.callee.property.name === featureFlagsFunctionName
17+
class FeatureFlagsWebpackPlugin {
18+
constructor(public options: PluginOptions) {
19+
Object.assign(this.options, { isFeatureEnabledFnName: 'isFeatureEnabled' })
820
}
9-
return expression.callee.name === featureFlagsFunctionName
10-
}
1121

12-
function getFeatureProperties(expression: any) {
13-
if (!expression || !expression.arguments.length) return []
14-
return expression.arguments[0].properties
15-
}
22+
apply(compiler: Compiler) {
23+
const { isFeatureEnabledFnName, flags } = this.options
1624

17-
function getFeatureFlag(properties: any) {
18-
return properties.reduce((result: any, property: any) => {
19-
const key = property.key.name
20-
const value = property.value.value
21-
result[key] = value
22-
return result
23-
}, {})
24-
}
25+
function onCallExpression(expression: Expression, parser: javascript.JavascriptParser) {
26+
if (isFeatureFlagFunction(expression, isFeatureEnabledFnName)) {
27+
const argument = expression.arguments[0]
28+
if (isIdentifier(argument)) {
29+
const isEnabled = flags[argument.name] !== undefined
30+
const result = isEnabled ? parser.evaluate(true) : parser.evaluate(false)
31+
if (result !== undefined) {
32+
result.setRange(expression.range)
33+
}
34+
return result
35+
}
36+
}
37+
return undefined
38+
}
2539

26-
function isEnabledFlag(flag: any, options: any) {
27-
return options.some(
28-
(option: any) => option.value === flag.value && option.component === flag.component,
29-
)
30-
}
40+
function onParseJavascript(parser: javascript.JavascriptParser) {
41+
parser.hooks.evaluate
42+
.for('CallExpression')
43+
.tap('FeatureFlagsWebpackPlugin', (expression) => onCallExpression(expression, parser))
44+
}
3145

32-
class FeatureFlagsWebpackPlugin extends Plugin {
33-
options: any[]
46+
function onThisCompilation(_compilation: Compilation, compilationParams: any) {
47+
compilationParams.normalModuleFactory.hooks.parser
48+
.for('javascript/auto')
49+
.tap('FeatureFlagsWebpackPlugin', onParseJavascript)
50+
}
3451

35-
constructor(options: any[]) {
36-
super()
37-
this.options = options || []
52+
compiler.hooks.thisCompilation.tap('FeatureFlagsWebpackPlugin', onThisCompilation)
3853
}
54+
}
3955

40-
apply(compiler: Compiler) {
41-
const options = this.options
42-
43-
compiler.hooks.thisCompilation.tap(
44-
'FeatureFlagsWebpackPlugin',
45-
(_, { normalModuleFactory }) => {
46-
normalModuleFactory.hooks.parser
47-
.for('javascript/auto')
48-
.tap('FeatureFlagsWebpackPlugin', (parser) => {
49-
// @ts-expect-error
50-
const getTrue = () => parser.evaluate(true)
51-
// @ts-expect-error
52-
const getFalse = () => parser.evaluate(false)
53-
54-
parser.hooks.evaluate
55-
.for('CallExpression')
56-
.tap('FeatureFlagsWebpackPlugin', (expression) => {
57-
if (!isFeatureFlagFunction(expression)) return
56+
function isFeatureFlagFunction(
57+
expression: Expression,
58+
isFeatureEnabledFnName: string,
59+
): expression is CallExpression {
60+
// prettier-ignore
61+
return (
62+
expression.type === 'CallExpression'
63+
&& expression.arguments.length > 0
64+
&& expression.callee.type === 'Identifier'
65+
&& expression.callee.name === isFeatureEnabledFnName
66+
)
67+
}
5868

59-
const properties = getFeatureProperties(expression)
60-
const flag = getFeatureFlag(properties)
61-
const isEnabled = isEnabledFlag(flag, options)
62-
const result = isEnabled ? getTrue() : getFalse()
63-
result.setRange(expression.range)
64-
return result
65-
})
66-
})
67-
},
68-
)
69-
}
69+
function isIdentifier(expression: Expression | SpreadElement): expression is Identifier {
70+
return expression.type === 'Identifier'
7071
}
7172

7273
module.exports = FeatureFlagsWebpackPlugin

0 commit comments

Comments
 (0)