/
extendJSConfig.js
80 lines (70 loc) · 2.13 KB
/
extendJSConfig.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
module.exports = function extendJSConfig (value, source) {
const recast = require('recast')
const stringifyJS = require('./stringifyJS')
let exportsIdentifier = null
const ast = recast.parse(source)
recast.types.visit(ast, {
visitAssignmentExpression (path) {
const { node } = path
if (
node.left.type === 'MemberExpression' &&
node.left.object.name === 'module' &&
node.left.property.name === 'exports'
) {
let theExports = node.right
if (
theExports.type === 'CallExpression' &&
theExports.callee.type === 'Identifier' &&
theExports.callee.name === 'defineConfig'
) {
theExports = theExports.arguments[0]
}
if (theExports.type === 'ObjectExpression') {
augmentExports(theExports)
} else if (theExports.type === 'Identifier') {
// do a second pass
exportsIdentifier = theExports.name
}
return false
}
this.traverse(path)
}
})
if (exportsIdentifier) {
recast.types.visit(ast, {
visitVariableDeclarator ({ node }) {
if (
node.id.name === exportsIdentifier &&
node.init.type === 'ObjectExpression'
) {
augmentExports(node.init)
}
return false
}
})
}
function augmentExports (node) {
const valueAST = recast.parse(`(${stringifyJS(value, null, 2)})`)
const props = valueAST.program.body[0].expression.properties
const existingProps = node.properties
for (const prop of props) {
const isUndefinedProp =
prop.value.type === 'Identifier' && prop.value.name === 'undefined'
const existing = existingProps.findIndex(p => {
return !p.computed && p.key.name === prop.key.name
})
if (existing > -1) {
// replace
existingProps[existing].value = prop.value
// remove `undefined` props
if (isUndefinedProp) {
existingProps.splice(existing, 1)
}
} else if (!isUndefinedProp) {
// append
existingProps.push(prop)
}
}
}
return recast.print(ast).code
}