Skip to content

Instantly share code, notes, and snippets.

@benmccormick
Last active June 17, 2018 21:39
Show Gist options
  • Save benmccormick/07aa6959cd5781dd7f3c2f37f9bc6a75 to your computer and use it in GitHub Desktop.
Save benmccormick/07aa6959cd5781dd7f3c2f37f9bc6a75 to your computer and use it in GitHub Desktop.
Mobx Codemod Example
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();
};
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