├── .babelrc ├── .gitignore ├── .idea ├── babel-plugin-mobx-async-action.iml ├── encodings.xml ├── inspectionProfiles │ └── Project_Default.xml ├── misc.xml ├── modules.xml └── vcs.xml ├── .npmignore ├── .travis.yml ├── LICENSE ├── README.md ├── package.json ├── src └── index.js └── test ├── fixtures ├── handle-async-await-generator │ ├── .babelrc │ ├── actual.js │ └── expected.js ├── handle-base-case │ ├── .babelrc │ ├── actual.js │ └── expected.js ├── handle-custom-import │ ├── .babelrc │ ├── actual.js │ └── expected.js ├── handle-custom-package │ ├── .babelrc │ ├── actual.js │ └── expected.js ├── handle-mobx-imported-as-namespace-but-action-used-separately │ ├── .babelrc │ ├── actual.js │ └── expected.js ├── handle-mobx-imported-as-namespace │ ├── .babelrc │ ├── actual.js │ └── expected.js ├── handle-typescript-and-class-expression │ ├── .babelrc │ ├── actual.js │ └── expected.js ├── handle-when-function-has-extra-wrapper │ ├── .babelrc │ ├── actual.js │ └── expected.js ├── transform-typescript-decorated-methods │ ├── .babelrc │ ├── actual.js │ └── expected.js ├── transform-typescript-decorated-with-metadata │ ├── .babelrc │ ├── actual.js │ └── expected.js ├── work-with-latest-preset-and-typescript │ ├── .babelrc │ ├── actual.js │ └── expected.js └── work-with-latest-preset │ ├── .babelrc │ ├── actual.js │ └── expected.js └── index.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-0"] 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | lib 4 | package-lock.json 5 | /.idea 6 | -------------------------------------------------------------------------------- /.idea/babel-plugin-mobx-async-action.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 182 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | src 4 | package-lock.json 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - v8 4 | - v9 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Artur Eshenbrener 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # babel-plugin-mobx-async-action 2 | 3 | [![NPM](https://nodei.co/npm/babel-plugin-mobx-async-action.png)](https://www.npmjs.com/babel-plugin-mobx-async-action/) 4 | 5 | [![Build Status](https://travis-ci.com/Strate/babel-plugin-mobx-async-action.svg?branch=master)](https://travis-ci.com/Strate/babel-plugin-mobx-async-action) 6 | 7 | Converts all async actions to mobx's 4 `flow` utility call. 8 | 9 | * [Use other package](#toc-mobx-package) 10 | * [Use with Typescript](#toc-use-with-typescript) 11 | 12 | 13 | ## Example 14 | 15 | **In** 16 | 17 | ```js 18 | import { action } from "mobx"; 19 | 20 | action(async function doSome() { 21 | const response = await fetch("/api/list") 22 | this.items = await response.json(); 23 | }); 24 | ``` 25 | 26 | **Out** 27 | 28 | ```js 29 | "use strict"; 30 | 31 | import { action } from "mobx"; 32 | import { flow as _flow } from "mobx"; 33 | 34 | action((() => { 35 | var _ref = _flow(function* () { 36 | const response = yield fetch("/api/list"); 37 | this.items = yield response.json(); 38 | }); 39 | 40 | function doSome() { 41 | return _ref.apply(this, arguments); 42 | } 43 | 44 | return doSome; 45 | })()); 46 | ``` 47 | 48 | ## Motivation 49 | 50 | Motivation to use flow() well described in official mobx documentation: https://mobx.js.org/best/actions.html#flows 51 | However, it is much useful to write pure async/await actions, especially if original code written in typescript: generator 52 | functions can not be covered by types, especially results of `yield` calls. So, let write actions as before, but let 53 | babel and this plugin do all the rest. 54 | 55 | ## Caveats 56 | 57 | Plugin support only ES6 imports. Only this imports are supported: 58 | ``` 59 | import {action} from "mobx"; 60 | ``` 61 | ``` 62 | import {action as actionAlias} from "mobx"; 63 | ``` 64 | ``` 65 | import * as mobx from "mobx"; 66 | ``` 67 | ``` 68 | import * as mobxAlias from "mobx"; 69 | ``` 70 | ``` 71 | import * as mobx from "my-mobx-alias" 72 | ``` 73 | For example, this cases are **not supported**: 74 | ``` 75 | const mobx = require("mobx") 76 | ``` 77 | ``` 78 | const {action} = require("mobx") 79 | ``` 80 | ``` 81 | import * as mobx from "mobx"; 82 | const {action} = mobx; 83 | action(function() {}); 84 | ``` 85 | 86 | 87 | ## Installation 88 | 89 | ```sh 90 | $ npm install babel-plugin-mobx-async-action 91 | ``` 92 | 93 | ## Usage 94 | 95 | ### Via `.babelrc` (Recommended) 96 | 97 | **.babelrc** 98 | 99 | ```json 100 | { 101 | "plugins": ["mobx-async-action"] 102 | } 103 | ``` 104 | 105 | ### Via CLI 106 | 107 | ```sh 108 | $ babel --plugins mobx-async-action script.js 109 | ``` 110 | 111 | ### Via Node API 112 | 113 | ```javascript 114 | require("babel-core").transform("code", { 115 | plugins: ["mobx-async-action"] 116 | }); 117 | ``` 118 | 119 | 120 | ## Use other package. 121 | 122 | If you use wrapper for "mobx" package, you can pass it's name to plugin: 123 | 124 | #### .babelrc 125 | 126 | ```json5 127 | { 128 | "plugins": [ 129 | ["mobx-async-action", { 130 | "mobx-package": "mobx-custom" 131 | }] 132 | ] 133 | } 134 | ``` 135 | 136 | ## Use with typescript. 137 | 138 | This plugin could handle decorators code, emitted from typescript, such as: 139 | 140 | ```js 141 | import * as tslib_1 from "tslib"; 142 | import { action } from "mobx"; 143 | export default class Class2 { 144 | async method() { 145 | await 123 146 | await 321 147 | } 148 | } 149 | tslib_1.__decorate([ 150 | action 151 | ], Class2.prototype, "method", null); 152 | ``` 153 | 154 | To get this code worked, you should enable [importHelpers](https://www.typescriptlang.org/docs/handbook/compiler-options.html) 155 | compiler option, and get [tslib](https://www.npmjs.com/package/tslib) package installed. Also, typescript 156 | should emit es6 modules, so, you should target your compiler to es2015+. That's all, 157 | plugin detect import from "tslib" and handle typescript decorators. 158 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "babel-plugin-mobx-async-action", 3 | "version": "0.0.6", 4 | "description": "", 5 | "license": "MIT", 6 | "repository": "Strate/babel-plugin-mobx-async-action", 7 | "author": "Strate ", 8 | "main": "lib/index.js", 9 | "dependencies": { 10 | "babel-helper-remap-async-to-generator": "^6" 11 | }, 12 | "devDependencies": { 13 | "babel-cli": "^6.4.5", 14 | "babel-plugin-transform-decorators-legacy": "^1.3.4", 15 | "babel-preset-es2015": "^6.3.13", 16 | "babel-preset-stage-0": "^6.3.13", 17 | "mocha": "^2.2.5" 18 | }, 19 | "scripts": { 20 | "clean": "rm -rf lib", 21 | "build": "babel src -d lib", 22 | "test": "mocha --compilers js:babel-register", 23 | "test:watch": "npm run test -- --watch", 24 | "prepublish": "npm run clean && npm run build" 25 | }, 26 | "keywords": [ 27 | "mobx", 28 | "utils", 29 | "babel-plugin" 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import remapAsyncToGenerator from "babel-helper-remap-async-to-generator"; 2 | 3 | export default function (babel) { 4 | const {types: t} = babel; 5 | 6 | /** 7 | * t.isFunctionExpression() || t.isArrowFunctionExpression() 8 | */ 9 | function isAnyFunctionExpression() { 10 | return t.isFunctionExpression.apply(t, arguments) || 11 | t.isArrowFunctionExpression.apply(t, arguments) || 12 | t.isClassMethod.apply(t, arguments) 13 | ; 14 | } 15 | 16 | function isAction(node, actionIdentifier, mobxNamespaceIdentifier) { 17 | return (actionIdentifier && t.isIdentifier(node, {name: actionIdentifier})) || 18 | ( 19 | t.isMemberExpression(node) && 20 | t.isIdentifier(node.object, {name: 'action'}) && 21 | t.isIdentifier(node.property, {name: "bound"}) 22 | ) || 23 | ( 24 | mobxNamespaceIdentifier && 25 | t.isMemberExpression(node) && 26 | t.isIdentifier(node.object, {name: mobxNamespaceIdentifier}) && 27 | t.isIdentifier(node.property, {name: "action"}) 28 | ) 29 | } 30 | 31 | function convertToFlow(path, state) { 32 | if ( 33 | isAnyFunctionExpression(path.node) && 34 | path.node.async && 35 | t.isBlockStatement(path.get('body').node) 36 | ) { 37 | remapAsyncToGenerator(path, state.file, { 38 | wrapAsync: state.addImport(state.mobxPackage, "flow") 39 | }); 40 | } 41 | } 42 | 43 | const traverseSibling = { 44 | CallExpression(path, state) { 45 | const node = path.node; 46 | const actionIdentifier = this.actionIdentifier; 47 | const mobxNamespaceIdentifier = this.mobxNamespaceIdentifier; 48 | const mobxPackage = this.mobxPackage; 49 | if (isAction(node.callee, actionIdentifier, mobxNamespaceIdentifier)) { 50 | if (node.arguments.length === 1) { 51 | convertToFlow(path.get('arguments.0'), state) 52 | path.skip(); 53 | } else if (node.arguments.length === 2) { 54 | convertToFlow(path.get('arguments.1'), state) 55 | path.skip(); 56 | } 57 | } 58 | }, 59 | 60 | ["ClassMethod|ClassProperty"](path, state) { 61 | const actionIdentifier = this.actionIdentifier; 62 | const mobxNamespaceIdentifier = this.mobxNamespaceIdentifier; 63 | const mobxPackage = this.mobxPackage; 64 | const explicitClasses = this.classes; 65 | const classDeclaration = path.findParent(p => p.isClassDeclaration() || p.isClassExpression()) 66 | // If there is an explicit classes with actions, handle them separately 67 | if ( 68 | explicitClasses && 69 | t.isIdentifier(classDeclaration.node.id) && 70 | void 0 !== explicitClasses[classDeclaration.node.id.name] && 71 | t.isClassMethod(path.node) && 72 | t.isIdentifier(path.node.key) && 73 | ( 74 | // all code inside constructor should be handled as action too, because it could contain other action creations 75 | path.node.key.name === "constructor" || 76 | void 0 !== explicitClasses[classDeclaration.node.id.name][path.node.key.name] 77 | ) 78 | ) { 79 | if (path.node.key.name === "constructor") { 80 | path.get('body').get('body').forEach(cPath => { 81 | if (cPath.isExpressionStatement()) { 82 | const exprPath = cPath.get('expression') 83 | if (exprPath.isAssignmentExpression() && exprPath.get('operator').node === '=') { 84 | const leftPath = exprPath.get('left') 85 | const rightPath = exprPath.get('right') 86 | if ( 87 | leftPath.isMemberExpression() && 88 | leftPath.get('object').isThisExpression() && 89 | leftPath.get('property').isIdentifier() && 90 | leftPath.get('property').node.name in explicitClasses[classDeclaration.node.id.name] && 91 | (rightPath.isArrowFunctionExpression() || rightPath.isFunctionExpression()) 92 | ) { 93 | convertToFlow(rightPath, state) 94 | } 95 | } 96 | } 97 | }) 98 | } else { 99 | convertToFlow(path, state) 100 | } 101 | path.skip(); 102 | } else if (path.node.decorators) { 103 | for (const {expression} of path.node.decorators) { 104 | if ( 105 | isAction(expression, actionIdentifier, mobxNamespaceIdentifier) || 106 | (t.isCallExpression(expression) && isAction(expression.callee, actionIdentifier, mobxNamespaceIdentifier)) 107 | ) { 108 | if (t.isClassMethod(path.node)) { 109 | convertToFlow(path, state) 110 | path.skip(); 111 | } else if (t.isClassProperty(path.node)) { 112 | convertToFlow(path.get('value'), state) 113 | path.skip(); 114 | } 115 | } 116 | } 117 | } 118 | }, 119 | }; 120 | 121 | return { 122 | name: "mobx-async-action-transform", 123 | visitor: { 124 | Program(path, state) { 125 | let actionIdentifier; 126 | let mobxNamespaceIdentifier; 127 | let tslibNamespaceIdentifier; 128 | const mobxPackage = state.opts && state.opts["mobx-package"] || "mobx" 129 | path.traverse({ 130 | ImportDeclaration(path) { 131 | if (path.node.source.value === mobxPackage) { 132 | for (const specifier of path.node.specifiers) { 133 | if (t.isImportNamespaceSpecifier(specifier) || (specifier.imported.name === "action")) { 134 | if (t.isImportNamespaceSpecifier(specifier)) { 135 | mobxNamespaceIdentifier = specifier.local.name; 136 | } else if (specifier.imported.name === "action") { 137 | actionIdentifier = specifier.local.name; 138 | } 139 | } 140 | } 141 | } 142 | if (path.node.source.value === "tslib") { 143 | for (const specifier of path.node.specifiers) { 144 | if (t.isImportNamespaceSpecifier(specifier)) { 145 | tslibNamespaceIdentifier = specifier.local.name 146 | } 147 | } 148 | } 149 | } 150 | }) 151 | const context = {...state, actionIdentifier, mobxNamespaceIdentifier, mobxPackage, addImport: state.addImport} 152 | path.traverse(traverseSibling, context) 153 | const toTraverse = []; 154 | /** 155 | * Lookup for typescript decorators, and handle them separately 156 | */ 157 | path.traverse({ 158 | CallExpression(path) { 159 | const node = path.node 160 | if ( 161 | t.isMemberExpression(node.callee) && 162 | t.isIdentifier(node.callee.object, {name: tslibNamespaceIdentifier}) && 163 | t.isIdentifier(node.callee.property, {name: "__decorate"}) && 164 | node.arguments.length === 4 && 165 | t.isArrayExpression(node.arguments[0]) && 166 | ( 167 | node.arguments[0].elements.some(e => 168 | ( 169 | t.isIdentifier(e, {name: actionIdentifier}) 170 | ) || 171 | ( 172 | t.isMemberExpression(e) && 173 | t.isIdentifier(e.object, {name: mobxNamespaceIdentifier}) && 174 | t.isIdentifier(e.property, {name: "action"}) 175 | ) || ( 176 | t.isCallExpression(e) && 177 | t.isIdentifier(e.callee, {name: actionIdentifier}) 178 | ) || ( 179 | t.isCallExpression(e) && 180 | t.isMemberExpression(e.callee) && 181 | t.isIdentifier(e.callee.object, {name: mobxNamespaceIdentifier}) && 182 | t.isIdentifier(e.callee.property, {name: "action"}) 183 | ) 184 | ) 185 | ) && 186 | t.isMemberExpression(node.arguments[1]) && 187 | t.isIdentifier(node.arguments[1].property, {name: "prototype"}) && 188 | t.isStringLiteral(node.arguments[2]) 189 | ) { 190 | const className = node.arguments[1].object.name 191 | const methodName = node.arguments[2].value 192 | const traversePath = path.getStatementParent().parentPath 193 | const existsTraverseRequest = toTraverse.find(e => e.path === traversePath) 194 | if (!existsTraverseRequest) { 195 | toTraverse.push({ 196 | path: traversePath, 197 | classes: { 198 | [className]: {[methodName]: methodName} 199 | } 200 | }) 201 | } else { 202 | const existsClassRequest = existsTraverseRequest.classes[className] 203 | if (!existsClassRequest) { 204 | existsTraverseRequest.classes[className] = {[methodName]: methodName} 205 | } else { 206 | existsTraverseRequest.classes[className][methodName] = methodName 207 | } 208 | } 209 | } 210 | } 211 | }) 212 | toTraverse.forEach(({path, classes}) => path.traverse(traverseSibling, {...context, classes})) 213 | }, 214 | } 215 | }; 216 | } 217 | -------------------------------------------------------------------------------- /test/fixtures/handle-async-await-generator/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "parserOpts":{ 3 | "plugins":["decorators", "classProperties"] 4 | }, 5 | "plugins": [ 6 | "../../../src" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /test/fixtures/handle-async-await-generator/actual.js: -------------------------------------------------------------------------------- 1 | import {action} from "mobx"; 2 | 3 | function a1() { 4 | } 5 | 6 | action(function* doSome() { 7 | yield 1; 8 | yield 2; 9 | }); 10 | 11 | action(async function doSomeSpecial() { 12 | await 1; 13 | await 2; 14 | }) 15 | 16 | action(async () => { 17 | await 1; 18 | await 2; 19 | }); 20 | 21 | action(async () => { 22 | const a = [ 23 | await 1, 24 | await 2, 25 | ] 26 | }); 27 | 28 | class SomeClass { 29 | @action 30 | generatorMethod = function* () { 31 | yield 1; 32 | yield 2; 33 | } 34 | @action("named") 35 | generatorMethod2 = function* () { 36 | yield 1; 37 | yield 2; 38 | } 39 | 40 | @action 41 | async method() { 42 | await 1; 43 | await 2; 44 | } 45 | 46 | @action("named") 47 | async method1() { 48 | await 1; 49 | await 2; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /test/fixtures/handle-async-await-generator/expected.js: -------------------------------------------------------------------------------- 1 | import { flow as _flow } from "mobx"; 2 | import { action } from "mobx"; 3 | 4 | function a1() {} 5 | 6 | action(function* doSome() { 7 | yield 1; 8 | yield 2; 9 | }); 10 | 11 | action((() => { 12 | var _ref = _flow(function* () { 13 | yield 1; 14 | yield 2; 15 | }); 16 | 17 | function doSomeSpecial() { 18 | return _ref.apply(this, arguments); 19 | } 20 | 21 | return doSomeSpecial; 22 | })()); 23 | 24 | action(_flow(function* () { 25 | yield 1; 26 | yield 2; 27 | })); 28 | 29 | action(_flow(function* () { 30 | const a = [yield 1, yield 2]; 31 | })); 32 | 33 | class SomeClass { 34 | @action 35 | generatorMethod = function* () { 36 | yield 1; 37 | yield 2; 38 | }; 39 | 40 | @action("named") 41 | generatorMethod2 = function* () { 42 | yield 1; 43 | yield 2; 44 | }; 45 | 46 | @action 47 | method() { 48 | return _flow(function* () { 49 | yield 1; 50 | yield 2; 51 | })(); 52 | } 53 | 54 | @action("named") 55 | method1() { 56 | return _flow(function* () { 57 | yield 1; 58 | yield 2; 59 | })(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /test/fixtures/handle-base-case/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "parserOpts":{ 3 | "plugins":["decorators", "classProperties"] 4 | }, 5 | "plugins": [ 6 | "../../../src" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /test/fixtures/handle-base-case/actual.js: -------------------------------------------------------------------------------- 1 | import {action} from "mobx"; 2 | 3 | function a1() { 4 | } 5 | 6 | action(async function doSome() { 7 | const response = fetch("/api/list") 8 | this.items = await response.json(); 9 | }); 10 | 11 | action(async function doSome() { 12 | await 123 13 | }); 14 | 15 | action.bound(async function doSome() { 16 | await 123 17 | }); 18 | 19 | action("named", async function doSome() { 20 | await 123 21 | }); 22 | 23 | action.bound("named", async function doSome() { 24 | await 123 25 | }); 26 | 27 | action("named", async function doSome() { 28 | await 123 29 | }); 30 | 31 | class SomeAsyncClass { 32 | @action("named") 33 | m3 = async function () { 34 | await 123 35 | await 321 36 | }; 37 | m4 = action(async function () { 38 | await 123 39 | await 321 40 | }); 41 | @action 42 | m5 = async () => { 43 | }; 44 | m6 = action(async () => { 45 | await 123 46 | await 321 47 | }); 48 | @action 49 | m7 = blabla; 50 | 51 | @action 52 | async m1() { 53 | await 123 54 | await 321 55 | } 56 | 57 | @action.bound 58 | async m1() { 59 | await 123 60 | await 321 61 | } 62 | 63 | @action("name") 64 | async m2() { 65 | await 123 66 | await 321 67 | } 68 | } 69 | 70 | class SomeSyncClass { 71 | @action("named") 72 | m3 = function () { 73 | 123; 74 | this; 75 | }; 76 | m4 = action(function () { 77 | 123; 78 | this; 79 | }); 80 | @action 81 | m5 = () => { 82 | }; 83 | m6 = action(() => { 84 | 123; 85 | this; 86 | }); 87 | @action 88 | m7 = blabla; 89 | 90 | @action 91 | m1() { 92 | 123; 93 | this; 94 | } 95 | 96 | @action.bound 97 | m1() { 98 | 123; 99 | this; 100 | } 101 | 102 | @action("name") 103 | m2() { 104 | 123; 105 | this; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /test/fixtures/handle-base-case/expected.js: -------------------------------------------------------------------------------- 1 | import { flow as _flow } from "mobx"; 2 | import { action } from "mobx"; 3 | 4 | function a1() {} 5 | 6 | action((() => { 7 | var _ref = _flow(function* () { 8 | const response = fetch("/api/list"); 9 | this.items = yield response.json(); 10 | }); 11 | 12 | function doSome() { 13 | return _ref.apply(this, arguments); 14 | } 15 | 16 | return doSome; 17 | })()); 18 | 19 | action((() => { 20 | var _ref2 = _flow(function* () { 21 | yield 123; 22 | }); 23 | 24 | function doSome() { 25 | return _ref2.apply(this, arguments); 26 | } 27 | 28 | return doSome; 29 | })()); 30 | 31 | action.bound((() => { 32 | var _ref3 = _flow(function* () { 33 | yield 123; 34 | }); 35 | 36 | function doSome() { 37 | return _ref3.apply(this, arguments); 38 | } 39 | 40 | return doSome; 41 | })()); 42 | 43 | action("named", (() => { 44 | var _ref4 = _flow(function* () { 45 | yield 123; 46 | }); 47 | 48 | function doSome() { 49 | return _ref4.apply(this, arguments); 50 | } 51 | 52 | return doSome; 53 | })()); 54 | 55 | action.bound("named", (() => { 56 | var _ref5 = _flow(function* () { 57 | yield 123; 58 | }); 59 | 60 | function doSome() { 61 | return _ref5.apply(this, arguments); 62 | } 63 | 64 | return doSome; 65 | })()); 66 | 67 | action("named", (() => { 68 | var _ref6 = _flow(function* () { 69 | yield 123; 70 | }); 71 | 72 | function doSome() { 73 | return _ref6.apply(this, arguments); 74 | } 75 | 76 | return doSome; 77 | })()); 78 | 79 | class SomeAsyncClass { 80 | @action("named") 81 | m3 = _flow(function* () { 82 | yield 123; 83 | yield 321; 84 | }); 85 | m4 = action(_flow(function* () { 86 | yield 123; 87 | yield 321; 88 | })); 89 | 90 | @action 91 | m5 = _flow(function* () {}); 92 | m6 = action(_flow(function* () { 93 | yield 123; 94 | yield 321; 95 | })); 96 | 97 | @action 98 | m7 = blabla; 99 | 100 | @action 101 | m1() { 102 | return _flow(function* () { 103 | yield 123; 104 | yield 321; 105 | })(); 106 | } 107 | 108 | @action.bound 109 | m1() { 110 | return _flow(function* () { 111 | yield 123; 112 | yield 321; 113 | })(); 114 | } 115 | 116 | @action("name") 117 | m2() { 118 | return _flow(function* () { 119 | yield 123; 120 | yield 321; 121 | })(); 122 | } 123 | } 124 | 125 | class SomeSyncClass { 126 | @action("named") 127 | m3 = function () { 128 | 123; 129 | this; 130 | }; 131 | m4 = action(function () { 132 | 123; 133 | this; 134 | }); 135 | 136 | @action 137 | m5 = () => {}; 138 | m6 = action(() => { 139 | 123; 140 | this; 141 | }); 142 | 143 | @action 144 | m7 = blabla; 145 | 146 | @action 147 | m1() { 148 | 123; 149 | this; 150 | } 151 | 152 | @action.bound 153 | m1() { 154 | 123; 155 | this; 156 | } 157 | 158 | @action("name") 159 | m2() { 160 | 123; 161 | this; 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /test/fixtures/handle-custom-import/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "parserOpts":{ 3 | "plugins":["decorators", "classProperties"] 4 | }, 5 | "plugins": [ 6 | "../../../src" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /test/fixtures/handle-custom-import/actual.js: -------------------------------------------------------------------------------- 1 | import {action as otherName} from "mobx"; 2 | 3 | otherName(async function () { 4 | await 123 5 | await 321 6 | }); 7 | -------------------------------------------------------------------------------- /test/fixtures/handle-custom-import/expected.js: -------------------------------------------------------------------------------- 1 | import { flow as _flow } from "mobx"; 2 | import { action as otherName } from "mobx"; 3 | 4 | otherName(_flow(function* () { 5 | yield 123; 6 | yield 321; 7 | })); 8 | -------------------------------------------------------------------------------- /test/fixtures/handle-custom-package/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "parserOpts":{ 3 | "plugins":["decorators", "classProperties"] 4 | }, 5 | "plugins": [ 6 | ["../../../src", { 7 | "mobx-package": "mobx-custom" 8 | }] 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /test/fixtures/handle-custom-package/actual.js: -------------------------------------------------------------------------------- 1 | import {action as otherName} from "mobx-custom"; 2 | 3 | otherName(async function () { 4 | await 123 5 | await 321 6 | }); 7 | -------------------------------------------------------------------------------- /test/fixtures/handle-custom-package/expected.js: -------------------------------------------------------------------------------- 1 | import { flow as _flow } from "mobx-custom"; 2 | import { action as otherName } from "mobx-custom"; 3 | 4 | otherName(_flow(function* () { 5 | yield 123; 6 | yield 321; 7 | })); 8 | -------------------------------------------------------------------------------- /test/fixtures/handle-mobx-imported-as-namespace-but-action-used-separately/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "parserOpts":{ 3 | "plugins":["decorators", "classProperties"] 4 | }, 5 | "plugins": [ 6 | "../../../src" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /test/fixtures/handle-mobx-imported-as-namespace-but-action-used-separately/actual.js: -------------------------------------------------------------------------------- 1 | import * as mobx from "mobx"; 2 | import {action} from "mobx"; 3 | 4 | action(async function () { 5 | await 123 6 | }); 7 | 8 | mobx.action(async function () { 9 | await 123 10 | }); 11 | -------------------------------------------------------------------------------- /test/fixtures/handle-mobx-imported-as-namespace-but-action-used-separately/expected.js: -------------------------------------------------------------------------------- 1 | import { flow as _flow } from "mobx"; 2 | import * as mobx from "mobx"; 3 | import { action } from "mobx"; 4 | 5 | action(_flow(function* () { 6 | yield 123; 7 | })); 8 | 9 | mobx.action(_flow(function* () { 10 | yield 123; 11 | })); 12 | -------------------------------------------------------------------------------- /test/fixtures/handle-mobx-imported-as-namespace/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "parserOpts":{ 3 | "plugins":["decorators", "classProperties"] 4 | }, 5 | "plugins": [ 6 | "../../../src" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /test/fixtures/handle-mobx-imported-as-namespace/actual.js: -------------------------------------------------------------------------------- 1 | import * as mobxNamespace from "mobx"; 2 | 3 | function a1() { 4 | } 5 | 6 | mobxNamespace.action(async function doSome() { 7 | await 123 8 | }); 9 | 10 | mobxNamespace.action.bound(async function doSome() { 11 | await 123 12 | }); 13 | 14 | mobxNamespace.action("named", async function doSome() { 15 | await 123 16 | }); 17 | 18 | mobxNamespace.action.bound("named", async function doSome() { 19 | await 123 20 | }); 21 | 22 | mobxNamespace.action("named", async function doSome() { 23 | await 123 24 | }); 25 | 26 | class SomeAsyncClass { 27 | @mobxNamespace.action("named") 28 | m3 = async function () { 29 | await 123 30 | await 321 31 | }; 32 | m4 = mobxNamespace.action(async function () { 33 | await 123 34 | await 321 35 | }); 36 | @mobxNamespace.action 37 | m5 = async () => { 38 | }; 39 | m6 = mobxNamespace.action(async () => { 40 | await 123 41 | await 321 42 | }); 43 | @mobxNamespace.action 44 | m7 = blabla; 45 | 46 | @mobxNamespace.action 47 | async m1() { 48 | await 123 49 | await 321 50 | } 51 | 52 | @mobxNamespace.action.bound 53 | async m1() { 54 | await 123 55 | await 321 56 | } 57 | 58 | @mobxNamespace.action("name") 59 | async m2() { 60 | await 123 61 | await 321 62 | } 63 | } 64 | 65 | class SomeSyncClass { 66 | @mobxNamespace.action("named") 67 | m3 = function () { 68 | 123; 69 | this; 70 | }; 71 | m4 = mobxNamespace.action(function () { 72 | 123; 73 | this; 74 | }); 75 | @mobxNamespace.action 76 | m5 = () => { 77 | }; 78 | m6 = mobxNamespace.action(() => { 79 | 123; 80 | this; 81 | }); 82 | @mobxNamespace.action 83 | m7 = blabla; 84 | 85 | @mobxNamespace.action 86 | m1() { 87 | 123; 88 | this; 89 | } 90 | 91 | @mobxNamespace.action.bound 92 | m1() { 93 | 123; 94 | this; 95 | } 96 | 97 | @mobxNamespace.action("name") 98 | m2() { 99 | 123; 100 | this; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /test/fixtures/handle-mobx-imported-as-namespace/expected.js: -------------------------------------------------------------------------------- 1 | import { flow as _flow } from "mobx"; 2 | import * as mobxNamespace from "mobx"; 3 | 4 | function a1() {} 5 | 6 | mobxNamespace.action((() => { 7 | var _ref = _flow(function* () { 8 | yield 123; 9 | }); 10 | 11 | function doSome() { 12 | return _ref.apply(this, arguments); 13 | } 14 | 15 | return doSome; 16 | })()); 17 | 18 | mobxNamespace.action.bound(async function doSome() { 19 | await 123; 20 | }); 21 | 22 | mobxNamespace.action("named", (() => { 23 | var _ref2 = _flow(function* () { 24 | yield 123; 25 | }); 26 | 27 | function doSome() { 28 | return _ref2.apply(this, arguments); 29 | } 30 | 31 | return doSome; 32 | })()); 33 | 34 | mobxNamespace.action.bound("named", async function doSome() { 35 | await 123; 36 | }); 37 | 38 | mobxNamespace.action("named", (() => { 39 | var _ref3 = _flow(function* () { 40 | yield 123; 41 | }); 42 | 43 | function doSome() { 44 | return _ref3.apply(this, arguments); 45 | } 46 | 47 | return doSome; 48 | })()); 49 | 50 | class SomeAsyncClass { 51 | @mobxNamespace.action("named") 52 | m3 = _flow(function* () { 53 | yield 123; 54 | yield 321; 55 | }); 56 | m4 = mobxNamespace.action(_flow(function* () { 57 | yield 123; 58 | yield 321; 59 | })); 60 | 61 | @mobxNamespace.action 62 | m5 = _flow(function* () {}); 63 | m6 = mobxNamespace.action(_flow(function* () { 64 | yield 123; 65 | yield 321; 66 | })); 67 | 68 | @mobxNamespace.action 69 | m7 = blabla; 70 | 71 | @mobxNamespace.action 72 | m1() { 73 | return _flow(function* () { 74 | yield 123; 75 | yield 321; 76 | })(); 77 | } 78 | 79 | @mobxNamespace.action.bound 80 | async m1() { 81 | await 123; 82 | await 321; 83 | } 84 | 85 | @mobxNamespace.action("name") 86 | m2() { 87 | return _flow(function* () { 88 | yield 123; 89 | yield 321; 90 | })(); 91 | } 92 | } 93 | 94 | class SomeSyncClass { 95 | @mobxNamespace.action("named") 96 | m3 = function () { 97 | 123; 98 | this; 99 | }; 100 | m4 = mobxNamespace.action(function () { 101 | 123; 102 | this; 103 | }); 104 | 105 | @mobxNamespace.action 106 | m5 = () => {}; 107 | m6 = mobxNamespace.action(() => { 108 | 123; 109 | this; 110 | }); 111 | 112 | @mobxNamespace.action 113 | m7 = blabla; 114 | 115 | @mobxNamespace.action 116 | m1() { 117 | 123; 118 | this; 119 | } 120 | 121 | @mobxNamespace.action.bound 122 | m1() { 123 | 123; 124 | this; 125 | } 126 | 127 | @mobxNamespace.action("name") 128 | m2() { 129 | 123; 130 | this; 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /test/fixtures/handle-typescript-and-class-expression/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "parserOpts":{ 3 | "plugins":["decorators", "classProperties"] 4 | }, 5 | "plugins": [ 6 | "../../../src" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /test/fixtures/handle-typescript-and-class-expression/actual.js: -------------------------------------------------------------------------------- 1 | import * as tslib_1 from "tslib"; 2 | import {action} from "mobx"; 3 | import * as mobx from "mobx"; 4 | 5 | let Class1 = class Class1 { 6 | constructor() { 7 | this.method1 = async () => { 8 | await 123 9 | await 321 10 | }; 11 | this.method2 = async () => { 12 | await 123 13 | await 321 14 | } 15 | } 16 | 17 | async method() { 18 | await 123 19 | await 321 20 | } 21 | 22 | method2() { 23 | let Class2 = class Class2 { 24 | async method() { 25 | await 123 26 | await 321 27 | } 28 | } 29 | 30 | tslib_1.__decorate([ 31 | action 32 | ], Class2.prototype, "method", null); 33 | return Class2; 34 | } 35 | 36 | @action 37 | async method3() { 38 | await 1 39 | let Class2 = class Class2 { 40 | async method() { 41 | await 123 42 | await 321 43 | } 44 | } 45 | 46 | tslib_1.__decorate([ 47 | action 48 | ], Class2.prototype, "method", null); 49 | return Class2; 50 | } 51 | } 52 | 53 | tslib_1.__decorate([ 54 | mobx.action 55 | ], Class1.prototype, "method", null); 56 | tslib_1.__decorate([ 57 | action 58 | ], Class1.prototype, "method1", void 0); 59 | export default class Class2 { 60 | async method() { 61 | await 123 62 | await 321 63 | } 64 | } 65 | tslib_1.__decorate([ 66 | action 67 | ], Class2.prototype, "method", null); 68 | -------------------------------------------------------------------------------- /test/fixtures/handle-typescript-and-class-expression/expected.js: -------------------------------------------------------------------------------- 1 | import { flow as _flow } from "mobx"; 2 | import * as tslib_1 from "tslib"; 3 | import { action } from "mobx"; 4 | import * as mobx from "mobx"; 5 | 6 | let Class1 = class Class1 { 7 | constructor() { 8 | this.method1 = _flow(function* () { 9 | yield 123; 10 | yield 321; 11 | }); 12 | this.method2 = async () => { 13 | await 123; 14 | await 321; 15 | }; 16 | } 17 | 18 | method() { 19 | return _flow(function* () { 20 | yield 123; 21 | yield 321; 22 | })(); 23 | } 24 | 25 | method2() { 26 | let Class2 = class Class2 { 27 | method() { 28 | return _flow(function* () { 29 | yield 123; 30 | yield 321; 31 | })(); 32 | } 33 | }; 34 | 35 | tslib_1.__decorate([action], Class2.prototype, "method", null); 36 | return Class2; 37 | } 38 | 39 | @action 40 | method3() { 41 | return _flow(function* () { 42 | yield 1; 43 | let Class2 = class Class2 { 44 | method() { 45 | return _flow(function* () { 46 | yield 123; 47 | yield 321; 48 | })(); 49 | } 50 | }; 51 | 52 | tslib_1.__decorate([action], Class2.prototype, "method", null); 53 | return Class2; 54 | })(); 55 | } 56 | }; 57 | 58 | tslib_1.__decorate([mobx.action], Class1.prototype, "method", null); 59 | tslib_1.__decorate([action], Class1.prototype, "method1", void 0); 60 | export default class Class2 { 61 | method() { 62 | return _flow(function* () { 63 | yield 123; 64 | yield 321; 65 | })(); 66 | } 67 | } 68 | tslib_1.__decorate([action], Class2.prototype, "method", null); 69 | -------------------------------------------------------------------------------- /test/fixtures/handle-when-function-has-extra-wrapper/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "parserOpts":{ 3 | "plugins":["decorators", "classProperties"] 4 | }, 5 | "plugins": [ 6 | "../../../src" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /test/fixtures/handle-when-function-has-extra-wrapper/actual.js: -------------------------------------------------------------------------------- 1 | import {action} from "mobx"; 2 | 3 | action(other(deep(wrapper(async function () { 4 | await 123 5 | })))) 6 | -------------------------------------------------------------------------------- /test/fixtures/handle-when-function-has-extra-wrapper/expected.js: -------------------------------------------------------------------------------- 1 | import { action } from "mobx"; 2 | 3 | action(other(deep(wrapper(async function () { 4 | await 123; 5 | })))); 6 | -------------------------------------------------------------------------------- /test/fixtures/transform-typescript-decorated-methods/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "parserOpts":{ 3 | "plugins":["decorators", "classProperties"] 4 | }, 5 | "plugins": [ 6 | "../../../src" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /test/fixtures/transform-typescript-decorated-methods/actual.js: -------------------------------------------------------------------------------- 1 | import * as tslib_1 from "tslib"; 2 | import {action} from "mobx"; 3 | import * as mobx from "mobx"; 4 | 5 | class Class1 { 6 | constructor() { 7 | this.method1 = async () => { 8 | await 123 9 | await 321 10 | }; 11 | this.method2 = async () => { 12 | await 123 13 | await 321 14 | } 15 | } 16 | 17 | async method() { 18 | await 123 19 | await 321 20 | } 21 | 22 | method2() { 23 | class Class2 { 24 | async method() { 25 | await 123 26 | await 321 27 | } 28 | } 29 | 30 | tslib_1.__decorate([ 31 | action 32 | ], Class2.prototype, "method", null); 33 | return Class2; 34 | } 35 | 36 | @action 37 | async method3() { 38 | await 1 39 | class Class2 { 40 | async method() { 41 | await 123 42 | await 321 43 | } 44 | } 45 | 46 | tslib_1.__decorate([ 47 | action 48 | ], Class2.prototype, "method", null); 49 | return Class2; 50 | } 51 | } 52 | 53 | tslib_1.__decorate([ 54 | mobx.action 55 | ], Class1.prototype, "method", null); 56 | tslib_1.__decorate([ 57 | action 58 | ], Class1.prototype, "method1", void 0); 59 | export default class Class2 { 60 | async method() { 61 | await 123 62 | await 321 63 | } 64 | } 65 | tslib_1.__decorate([ 66 | action 67 | ], Class2.prototype, "method", null); 68 | -------------------------------------------------------------------------------- /test/fixtures/transform-typescript-decorated-methods/expected.js: -------------------------------------------------------------------------------- 1 | import { flow as _flow } from "mobx"; 2 | import * as tslib_1 from "tslib"; 3 | import { action } from "mobx"; 4 | import * as mobx from "mobx"; 5 | 6 | class Class1 { 7 | constructor() { 8 | this.method1 = _flow(function* () { 9 | yield 123; 10 | yield 321; 11 | }); 12 | this.method2 = async () => { 13 | await 123; 14 | await 321; 15 | }; 16 | } 17 | 18 | method() { 19 | return _flow(function* () { 20 | yield 123; 21 | yield 321; 22 | })(); 23 | } 24 | 25 | method2() { 26 | class Class2 { 27 | method() { 28 | return _flow(function* () { 29 | yield 123; 30 | yield 321; 31 | })(); 32 | } 33 | } 34 | 35 | tslib_1.__decorate([action], Class2.prototype, "method", null); 36 | return Class2; 37 | } 38 | 39 | @action 40 | method3() { 41 | return _flow(function* () { 42 | yield 1; 43 | class Class2 { 44 | method() { 45 | return _flow(function* () { 46 | yield 123; 47 | yield 321; 48 | })(); 49 | } 50 | } 51 | 52 | tslib_1.__decorate([action], Class2.prototype, "method", null); 53 | return Class2; 54 | })(); 55 | } 56 | } 57 | 58 | tslib_1.__decorate([mobx.action], Class1.prototype, "method", null); 59 | tslib_1.__decorate([action], Class1.prototype, "method1", void 0); 60 | export default class Class2 { 61 | method() { 62 | return _flow(function* () { 63 | yield 123; 64 | yield 321; 65 | })(); 66 | } 67 | } 68 | tslib_1.__decorate([action], Class2.prototype, "method", null); 69 | -------------------------------------------------------------------------------- /test/fixtures/transform-typescript-decorated-with-metadata/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "parserOpts":{ 3 | "plugins":["decorators", "classProperties"] 4 | }, 5 | "plugins": [ 6 | "../../../src" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /test/fixtures/transform-typescript-decorated-with-metadata/actual.js: -------------------------------------------------------------------------------- 1 | import * as tslib_1 from "tslib"; 2 | import {action} from "mobx"; 3 | 4 | export default class Class2 { 5 | async method() { 6 | await 123 7 | await 321 8 | } 9 | } 10 | tslib_1.__decorate([ 11 | action, 12 | tslib_1.__metadata("design:type", Function), 13 | tslib_1.__metadata("design:paramtypes", []), 14 | tslib_1.__metadata("design:returntype", Promise) 15 | ], Class2.prototype, "method", null); 16 | -------------------------------------------------------------------------------- /test/fixtures/transform-typescript-decorated-with-metadata/expected.js: -------------------------------------------------------------------------------- 1 | import { flow as _flow } from "mobx"; 2 | import * as tslib_1 from "tslib"; 3 | import { action } from "mobx"; 4 | 5 | export default class Class2 { 6 | method() { 7 | return _flow(function* () { 8 | yield 123; 9 | yield 321; 10 | })(); 11 | } 12 | } 13 | tslib_1.__decorate([action, tslib_1.__metadata("design:type", Function), tslib_1.__metadata("design:paramtypes", []), tslib_1.__metadata("design:returntype", Promise)], Class2.prototype, "method", null); 14 | -------------------------------------------------------------------------------- /test/fixtures/work-with-latest-preset-and-typescript/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "../../../src", 4 | "transform-decorators-legacy" 5 | ], 6 | "presets": [ 7 | "es2015", 8 | "stage-2" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /test/fixtures/work-with-latest-preset-and-typescript/actual.js: -------------------------------------------------------------------------------- 1 | import * as tslib_1 from "tslib"; 2 | import {action} from "mobx"; 3 | import * as mobx from "mobx"; 4 | 5 | class Class1 { 6 | constructor() { 7 | this.method1 = async () => { 8 | await 123 9 | await 321 10 | }; 11 | this.method2 = async () => { 12 | await 123 13 | await 321 14 | } 15 | } 16 | 17 | async method() { 18 | await 123 19 | await 321 20 | } 21 | 22 | method2() { 23 | class Class2 { 24 | async method() { 25 | await 123 26 | await 321 27 | } 28 | } 29 | 30 | tslib_1.__decorate([ 31 | action 32 | ], Class2.prototype, "method", null); 33 | return Class2; 34 | } 35 | 36 | @action 37 | async method3() { 38 | class Class2 { 39 | async method() { 40 | await 123 41 | await 321 42 | } 43 | } 44 | 45 | tslib_1.__decorate([ 46 | action 47 | ], Class2.prototype, "method", null); 48 | return Class2; 49 | } 50 | } 51 | 52 | tslib_1.__decorate([ 53 | mobx.action 54 | ], Class1.prototype, "method", null); 55 | tslib_1.__decorate([ 56 | action 57 | ], Class1.prototype, "method1", void 0); 58 | export default class Class2 { 59 | async method() { 60 | await 123 61 | await 321 62 | } 63 | } 64 | tslib_1.__decorate([ 65 | action 66 | ], Class2.prototype, "method", null); 67 | -------------------------------------------------------------------------------- /test/fixtures/work-with-latest-preset-and-typescript/expected.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = undefined; 7 | 8 | var _mobx = require("mobx"); 9 | 10 | var mobx = _interopRequireWildcard(_mobx); 11 | 12 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 13 | 14 | var _desc, _value, _class; 15 | 16 | var _tslib = require("tslib"); 17 | 18 | var tslib_1 = _interopRequireWildcard(_tslib); 19 | 20 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } 21 | 22 | function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } 23 | 24 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 25 | 26 | function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) { 27 | var desc = {}; 28 | Object['ke' + 'ys'](descriptor).forEach(function (key) { 29 | desc[key] = descriptor[key]; 30 | }); 31 | desc.enumerable = !!desc.enumerable; 32 | desc.configurable = !!desc.configurable; 33 | 34 | if ('value' in desc || desc.initializer) { 35 | desc.writable = true; 36 | } 37 | 38 | desc = decorators.slice().reverse().reduce(function (desc, decorator) { 39 | return decorator(target, property, desc) || desc; 40 | }, desc); 41 | 42 | if (context && desc.initializer !== void 0) { 43 | desc.value = desc.initializer ? desc.initializer.call(context) : void 0; 44 | desc.initializer = undefined; 45 | } 46 | 47 | if (desc.initializer === void 0) { 48 | Object['define' + 'Property'](target, property, desc); 49 | desc = null; 50 | } 51 | 52 | return desc; 53 | } 54 | 55 | var Class1 = (_class = function () { 56 | function Class1() { 57 | var _this = this; 58 | 59 | _classCallCheck(this, Class1); 60 | 61 | this.method1 = (0, _mobx.flow)( /*#__PURE__*/regeneratorRuntime.mark(function _callee() { 62 | return regeneratorRuntime.wrap(function _callee$(_context) { 63 | while (1) { 64 | switch (_context.prev = _context.next) { 65 | case 0: 66 | _context.next = 2; 67 | return 123; 68 | 69 | case 2: 70 | _context.next = 4; 71 | return 321; 72 | 73 | case 4: 74 | case "end": 75 | return _context.stop(); 76 | } 77 | } 78 | }, _callee, _this); 79 | })); 80 | this.method2 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2() { 81 | return regeneratorRuntime.wrap(function _callee2$(_context2) { 82 | while (1) { 83 | switch (_context2.prev = _context2.next) { 84 | case 0: 85 | _context2.next = 2; 86 | return 123; 87 | 88 | case 2: 89 | _context2.next = 4; 90 | return 321; 91 | 92 | case 4: 93 | case "end": 94 | return _context2.stop(); 95 | } 96 | } 97 | }, _callee2, _this); 98 | })); 99 | } 100 | 101 | _createClass(Class1, [{ 102 | key: "method", 103 | value: function method() { 104 | var _this2 = this; 105 | 106 | return (0, _mobx.flow)( /*#__PURE__*/regeneratorRuntime.mark(function _callee3() { 107 | return regeneratorRuntime.wrap(function _callee3$(_context3) { 108 | while (1) { 109 | switch (_context3.prev = _context3.next) { 110 | case 0: 111 | _context3.next = 2; 112 | return 123; 113 | 114 | case 2: 115 | _context3.next = 4; 116 | return 321; 117 | 118 | case 4: 119 | case "end": 120 | return _context3.stop(); 121 | } 122 | } 123 | }, _callee3, _this2); 124 | }))(); 125 | } 126 | }, { 127 | key: "method2", 128 | value: function method2() { 129 | var Class2 = function () { 130 | function Class2() { 131 | _classCallCheck(this, Class2); 132 | } 133 | 134 | _createClass(Class2, [{ 135 | key: "method", 136 | value: function method() { 137 | var _this3 = this; 138 | 139 | return (0, _mobx.flow)( /*#__PURE__*/regeneratorRuntime.mark(function _callee4() { 140 | return regeneratorRuntime.wrap(function _callee4$(_context4) { 141 | while (1) { 142 | switch (_context4.prev = _context4.next) { 143 | case 0: 144 | _context4.next = 2; 145 | return 123; 146 | 147 | case 2: 148 | _context4.next = 4; 149 | return 321; 150 | 151 | case 4: 152 | case "end": 153 | return _context4.stop(); 154 | } 155 | } 156 | }, _callee4, _this3); 157 | }))(); 158 | } 159 | }]); 160 | 161 | return Class2; 162 | }(); 163 | 164 | tslib_1.__decorate([_mobx.action], Class2.prototype, "method", null); 165 | return Class2; 166 | } 167 | }, { 168 | key: "method3", 169 | value: function method3() { 170 | var _this5 = this; 171 | 172 | return (0, _mobx.flow)( /*#__PURE__*/regeneratorRuntime.mark(function _callee6() { 173 | var Class2; 174 | return regeneratorRuntime.wrap(function _callee6$(_context6) { 175 | while (1) { 176 | switch (_context6.prev = _context6.next) { 177 | case 0: 178 | Class2 = function () { 179 | function Class2() { 180 | _classCallCheck(this, Class2); 181 | } 182 | 183 | _createClass(Class2, [{ 184 | key: "method", 185 | value: function method() { 186 | var _this4 = this; 187 | 188 | return (0, _mobx.flow)( /*#__PURE__*/regeneratorRuntime.mark(function _callee5() { 189 | return regeneratorRuntime.wrap(function _callee5$(_context5) { 190 | while (1) { 191 | switch (_context5.prev = _context5.next) { 192 | case 0: 193 | _context5.next = 2; 194 | return 123; 195 | 196 | case 2: 197 | _context5.next = 4; 198 | return 321; 199 | 200 | case 4: 201 | case "end": 202 | return _context5.stop(); 203 | } 204 | } 205 | }, _callee5, _this4); 206 | }))(); 207 | } 208 | }]); 209 | 210 | return Class2; 211 | }(); 212 | 213 | tslib_1.__decorate([_mobx.action], Class2.prototype, "method", null); 214 | return _context6.abrupt("return", Class2); 215 | 216 | case 3: 217 | case "end": 218 | return _context6.stop(); 219 | } 220 | } 221 | }, _callee6, _this5); 222 | }))(); 223 | } 224 | }]); 225 | 226 | return Class1; 227 | }(), (_applyDecoratedDescriptor(_class.prototype, "method3", [_mobx.action], Object.getOwnPropertyDescriptor(_class.prototype, "method3"), _class.prototype)), _class); 228 | 229 | 230 | tslib_1.__decorate([mobx.action], Class1.prototype, "method", null); 231 | tslib_1.__decorate([_mobx.action], Class1.prototype, "method1", void 0); 232 | 233 | var Class2 = function () { 234 | function Class2() { 235 | _classCallCheck(this, Class2); 236 | } 237 | 238 | _createClass(Class2, [{ 239 | key: "method", 240 | value: function method() { 241 | var _this6 = this; 242 | 243 | return (0, _mobx.flow)( /*#__PURE__*/regeneratorRuntime.mark(function _callee7() { 244 | return regeneratorRuntime.wrap(function _callee7$(_context7) { 245 | while (1) { 246 | switch (_context7.prev = _context7.next) { 247 | case 0: 248 | _context7.next = 2; 249 | return 123; 250 | 251 | case 2: 252 | _context7.next = 4; 253 | return 321; 254 | 255 | case 4: 256 | case "end": 257 | return _context7.stop(); 258 | } 259 | } 260 | }, _callee7, _this6); 261 | }))(); 262 | } 263 | }]); 264 | 265 | return Class2; 266 | }(); 267 | 268 | exports.default = Class2; 269 | 270 | tslib_1.__decorate([_mobx.action], Class2.prototype, "method", null); 271 | -------------------------------------------------------------------------------- /test/fixtures/work-with-latest-preset/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "../../../src", 4 | "transform-decorators-legacy" 5 | ], 6 | "presets": [ 7 | "es2015", 8 | "stage-2" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /test/fixtures/work-with-latest-preset/actual.js: -------------------------------------------------------------------------------- 1 | import {action} from "mobx"; 2 | 3 | function a1() { 4 | } 5 | 6 | action(function* doSome() { 7 | yield 1; 8 | yield 2; 9 | }); 10 | 11 | action(async function doSomeSpecial() { 12 | await 1; 13 | await 2; 14 | }) 15 | 16 | action(async () => { 17 | await 1; 18 | await 2; 19 | }); 20 | 21 | action(async () => { 22 | const a = [ 23 | await 1, 24 | await 2, 25 | ] 26 | }); 27 | 28 | class SomeClass { 29 | @action 30 | generatorMethod = function* () { 31 | yield 1; 32 | yield 2; 33 | } 34 | @action("named") 35 | generatorMethod2 = function* () { 36 | yield 1; 37 | yield 2; 38 | } 39 | 40 | @action 41 | async method() { 42 | await 1; 43 | await 2; 44 | } 45 | 46 | @action("named") 47 | async method1() { 48 | await 1; 49 | await 2; 50 | } 51 | 52 | @action 53 | method2 = async () => { 54 | await 1 55 | await 2 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /test/fixtures/work-with-latest-preset/expected.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _mobx = require("mobx"); 4 | 5 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 6 | 7 | var _dec, _dec2, _desc, _value, _class, _descriptor, _descriptor2, _descriptor3; 8 | 9 | function _initDefineProp(target, property, descriptor, context) { 10 | if (!descriptor) return; 11 | Object.defineProperty(target, property, { 12 | enumerable: descriptor.enumerable, 13 | configurable: descriptor.configurable, 14 | writable: descriptor.writable, 15 | value: descriptor.initializer ? descriptor.initializer.call(context) : void 0 16 | }); 17 | } 18 | 19 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 20 | 21 | function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) { 22 | var desc = {}; 23 | Object['ke' + 'ys'](descriptor).forEach(function (key) { 24 | desc[key] = descriptor[key]; 25 | }); 26 | desc.enumerable = !!desc.enumerable; 27 | desc.configurable = !!desc.configurable; 28 | 29 | if ('value' in desc || desc.initializer) { 30 | desc.writable = true; 31 | } 32 | 33 | desc = decorators.slice().reverse().reduce(function (desc, decorator) { 34 | return decorator(target, property, desc) || desc; 35 | }, desc); 36 | 37 | if (context && desc.initializer !== void 0) { 38 | desc.value = desc.initializer ? desc.initializer.call(context) : void 0; 39 | desc.initializer = undefined; 40 | } 41 | 42 | if (desc.initializer === void 0) { 43 | Object['define' + 'Property'](target, property, desc); 44 | desc = null; 45 | } 46 | 47 | return desc; 48 | } 49 | 50 | function _initializerWarningHelper(descriptor, context) { 51 | throw new Error('Decorating class property failed. Please ensure that transform-class-properties is enabled.'); 52 | } 53 | 54 | function a1() {} 55 | 56 | (0, _mobx.action)( /*#__PURE__*/regeneratorRuntime.mark(function doSome() { 57 | return regeneratorRuntime.wrap(function doSome$(_context) { 58 | while (1) { 59 | switch (_context.prev = _context.next) { 60 | case 0: 61 | _context.next = 2; 62 | return 1; 63 | 64 | case 2: 65 | _context.next = 4; 66 | return 2; 67 | 68 | case 4: 69 | case "end": 70 | return _context.stop(); 71 | } 72 | } 73 | }, doSome, this); 74 | })); 75 | 76 | (0, _mobx.action)(function () { 77 | var _ref = (0, _mobx.flow)( /*#__PURE__*/regeneratorRuntime.mark(function _callee() { 78 | return regeneratorRuntime.wrap(function _callee$(_context2) { 79 | while (1) { 80 | switch (_context2.prev = _context2.next) { 81 | case 0: 82 | _context2.next = 2; 83 | return 1; 84 | 85 | case 2: 86 | _context2.next = 4; 87 | return 2; 88 | 89 | case 4: 90 | case "end": 91 | return _context2.stop(); 92 | } 93 | } 94 | }, _callee, this); 95 | })); 96 | 97 | function doSomeSpecial() { 98 | return _ref.apply(this, arguments); 99 | } 100 | 101 | return doSomeSpecial; 102 | }()); 103 | 104 | (0, _mobx.action)((0, _mobx.flow)( /*#__PURE__*/regeneratorRuntime.mark(function _callee2() { 105 | return regeneratorRuntime.wrap(function _callee2$(_context3) { 106 | while (1) { 107 | switch (_context3.prev = _context3.next) { 108 | case 0: 109 | _context3.next = 2; 110 | return 1; 111 | 112 | case 2: 113 | _context3.next = 4; 114 | return 2; 115 | 116 | case 4: 117 | case "end": 118 | return _context3.stop(); 119 | } 120 | } 121 | }, _callee2, undefined); 122 | }))); 123 | 124 | (0, _mobx.action)((0, _mobx.flow)( /*#__PURE__*/regeneratorRuntime.mark(function _callee3() { 125 | var a; 126 | return regeneratorRuntime.wrap(function _callee3$(_context4) { 127 | while (1) { 128 | switch (_context4.prev = _context4.next) { 129 | case 0: 130 | _context4.next = 2; 131 | return 1; 132 | 133 | case 2: 134 | _context4.t0 = _context4.sent; 135 | _context4.next = 5; 136 | return 2; 137 | 138 | case 5: 139 | _context4.t1 = _context4.sent; 140 | a = [_context4.t0, _context4.t1]; 141 | 142 | case 7: 143 | case "end": 144 | return _context4.stop(); 145 | } 146 | } 147 | }, _callee3, undefined); 148 | }))); 149 | 150 | var SomeClass = (_dec = (0, _mobx.action)("named"), _dec2 = (0, _mobx.action)("named"), (_class = function () { 151 | function SomeClass() { 152 | _classCallCheck(this, SomeClass); 153 | 154 | _initDefineProp(this, "generatorMethod", _descriptor, this); 155 | 156 | _initDefineProp(this, "generatorMethod2", _descriptor2, this); 157 | 158 | _initDefineProp(this, "method2", _descriptor3, this); 159 | } 160 | 161 | _createClass(SomeClass, [{ 162 | key: "method", 163 | value: function method() { 164 | var _this = this; 165 | 166 | return (0, _mobx.flow)( /*#__PURE__*/regeneratorRuntime.mark(function _callee4() { 167 | return regeneratorRuntime.wrap(function _callee4$(_context5) { 168 | while (1) { 169 | switch (_context5.prev = _context5.next) { 170 | case 0: 171 | _context5.next = 2; 172 | return 1; 173 | 174 | case 2: 175 | _context5.next = 4; 176 | return 2; 177 | 178 | case 4: 179 | case "end": 180 | return _context5.stop(); 181 | } 182 | } 183 | }, _callee4, _this); 184 | }))(); 185 | } 186 | }, { 187 | key: "method1", 188 | value: function method1() { 189 | var _this2 = this; 190 | 191 | return (0, _mobx.flow)( /*#__PURE__*/regeneratorRuntime.mark(function _callee5() { 192 | return regeneratorRuntime.wrap(function _callee5$(_context6) { 193 | while (1) { 194 | switch (_context6.prev = _context6.next) { 195 | case 0: 196 | _context6.next = 2; 197 | return 1; 198 | 199 | case 2: 200 | _context6.next = 4; 201 | return 2; 202 | 203 | case 4: 204 | case "end": 205 | return _context6.stop(); 206 | } 207 | } 208 | }, _callee5, _this2); 209 | }))(); 210 | } 211 | }]); 212 | 213 | return SomeClass; 214 | }(), (_descriptor = _applyDecoratedDescriptor(_class.prototype, "generatorMethod", [_mobx.action], { 215 | enumerable: true, 216 | initializer: function initializer() { 217 | return (/*#__PURE__*/regeneratorRuntime.mark(function _callee6() { 218 | return regeneratorRuntime.wrap(function _callee6$(_context7) { 219 | while (1) { 220 | switch (_context7.prev = _context7.next) { 221 | case 0: 222 | _context7.next = 2; 223 | return 1; 224 | 225 | case 2: 226 | _context7.next = 4; 227 | return 2; 228 | 229 | case 4: 230 | case "end": 231 | return _context7.stop(); 232 | } 233 | } 234 | }, _callee6, this); 235 | }) 236 | ); 237 | } 238 | }), _descriptor2 = _applyDecoratedDescriptor(_class.prototype, "generatorMethod2", [_dec], { 239 | enumerable: true, 240 | initializer: function initializer() { 241 | return (/*#__PURE__*/regeneratorRuntime.mark(function _callee7() { 242 | return regeneratorRuntime.wrap(function _callee7$(_context8) { 243 | while (1) { 244 | switch (_context8.prev = _context8.next) { 245 | case 0: 246 | _context8.next = 2; 247 | return 1; 248 | 249 | case 2: 250 | _context8.next = 4; 251 | return 2; 252 | 253 | case 4: 254 | case "end": 255 | return _context8.stop(); 256 | } 257 | } 258 | }, _callee7, this); 259 | }) 260 | ); 261 | } 262 | }), _applyDecoratedDescriptor(_class.prototype, "method", [_mobx.action], Object.getOwnPropertyDescriptor(_class.prototype, "method"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "method1", [_dec2], Object.getOwnPropertyDescriptor(_class.prototype, "method1"), _class.prototype), _descriptor3 = _applyDecoratedDescriptor(_class.prototype, "method2", [_mobx.action], { 263 | enumerable: true, 264 | initializer: function initializer() { 265 | var _this3 = this; 266 | 267 | return (0, _mobx.flow)( /*#__PURE__*/regeneratorRuntime.mark(function _callee8() { 268 | return regeneratorRuntime.wrap(function _callee8$(_context9) { 269 | while (1) { 270 | switch (_context9.prev = _context9.next) { 271 | case 0: 272 | _context9.next = 2; 273 | return 1; 274 | 275 | case 2: 276 | _context9.next = 4; 277 | return 2; 278 | 279 | case 4: 280 | case "end": 281 | return _context9.stop(); 282 | } 283 | } 284 | }, _callee8, _this3); 285 | })); 286 | } 287 | })), _class)); 288 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import fs from 'fs'; 3 | import assert from 'assert'; 4 | import { transformFileSync } from 'babel-core'; 5 | import plugin from '../src'; 6 | 7 | function trim(str) { 8 | return str.replace(/^\s+|\s+$/, ''); 9 | } 10 | 11 | describe('', () => { 12 | const fixturesDir = path.join(__dirname, 'fixtures'); 13 | fs.readdirSync(fixturesDir).map((caseName) => { 14 | it(`should ${caseName.split('-').join(' ')}`, () => { 15 | const fixtureDir = path.join(fixturesDir, caseName); 16 | const actualPath = path.join(fixtureDir, 'actual.js'); 17 | const actual = transformFileSync(actualPath).code; 18 | 19 | const expected = fs.readFileSync( 20 | path.join(fixtureDir, 'expected.js') 21 | ).toString(); 22 | 23 | // console.log(path.join(fixtureDir, 'expected.js')) 24 | // console.log(actual) 25 | 26 | assert.equal(trim(actual), trim(expected)); 27 | }); 28 | }); 29 | }); 30 | --------------------------------------------------------------------------------