Last active
June 17, 2018 21:39
-
-
Save benmccormick/07aa6959cd5781dd7f3c2f37f9bc6a75 to your computer and use it in GitHub Desktop.
Mobx Codemod Example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module.exports = function (file, api) { | |
const j = api.jscodeshift; | |
const buildDecoratorPropertiesFromCurrentObject = currentObj => { | |
let decoratorProps = []; | |
currentObj.properties.forEach(prop => { | |
if (prop.value.type === 'CallExpression' && prop.value.callee.name === 'computed') { | |
prop.kind = 'get'; | |
let fnBody = prop.value.arguments[0]; | |
if (fnBody.type === 'ArrowFunctionExpression' && fnBody.body.type !== 'BlockStatement') { | |
prop.value = j.functionExpression(null, fnBody.params, | |
j.blockStatement([j.returnStatement(fnBody.body)]), | |
false); | |
} else { | |
prop.value = j.functionExpression(null, fnBody.params, fnBody.body, false); | |
} | |
} | |
}); | |
let dataProps = currentObj.properties.filter(prop => !(prop.value.type === 'CallExpression' && prop.value.callee.name === 'computed')); | |
dataProps.forEach(prop => { | |
if (prop.value.type === 'CallExpression' && prop.value.callee.name === 'action') { | |
// copy action to the decorator area first... | |
let args = prop.value.arguments; | |
let dupProp = Object.assign({}, prop); | |
dupProp.value = Object.assign({}, dupProp.value); | |
dupProp.value.arguments = (args.length === 2) ? args.slice(0, 1) : []; | |
decoratorProps.push(dupProp); | |
// then flatten things out | |
prop.value = (args.length === 2) ? args[1] : args[0]; | |
} | |
}); | |
return [dataProps, decoratorProps]; | |
} | |
return j(file.source) | |
// We're looking for a CallExpression for extend observable | |
.find(j.CallExpression, { | |
callee: { | |
name: 'extendObservable' | |
} | |
}) | |
// Verify that it's only using 2 arguments so far, and that the second one is an Object Expression | |
.filter(p => p.value.arguments.length == 2 && p.value.arguments[1].type == "ObjectExpression") | |
.forEach(p => { | |
// Now we want to | |
// 1. Add a 3rd argument | |
// 2. Move action declarations to that argument | |
// 3. Convert action statements to plain functions | |
// 4. Convert computeds to get statements, or just move them down to the second object? | |
let args = p.value.arguments; | |
let [dataProps, decoratorProps] = buildDecoratorPropertiesFromCurrentObject(args[1]); | |
args[1].properties = dataProps; | |
args.push(j.objectExpression(decoratorProps)); | |
}) | |
.toSource(); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { extendObservable, computed, action} from 'mobx'; | |
export class Example { | |
constructor() { | |
extendObservable(this, { | |
foo: false, | |
bar: false, | |
currentData: computed(() => { | |
return foo || bar; | |
}), | |
otherData: computed(() => foo || bar), | |
setFoo: action('Set Foo', val => { | |
this.foo = val; | |
}), | |
setBar: action('Set Bar', val => { | |
this.bar = val; | |
}), | |
}); | |
} | |
unrelatedMethod(key) { | |
return key; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment