Flow type checker & MeteorJS

Flow type checker & MeteorJS

Last week I finally decided to try Flow for my JavaScript projects. After struggling with having Flow working with Meteor, I decided to write a small post about it.

Flow

Flow is another open source tool by Facebook. It's a static type checker for JavaScript.

It is fairly easy to setup.
When using it with Babel for instance, you need to:

  • install Babel and flow preset
  • update the .babelrc file
  • install flow-bin
  • (optional) add a flow script in your package.json
  • run flow init

Here is the code to do the things mentioned above:

# Install babel and Flow preset
npm install --save-dev babel-cli babel-preset-flow

#open .babelrc with your favourite editor and add the preset
echo '{' > .babelrc
echo '    presets: ["flow"]' >> .babelrc
echo '}' >> .babelrc

# Install flow-bin
npm install --save-dev flow-bin

# optionnally edit your package.json

#...
# "scripts": {
#  "flow": "flow"
#  },
#...

# finally, create a .flowconfig file:
flow init

You can now run flow check to check for errors!

If you never used flow, you need to add this comment: //@flow to the files you want to be checked!

MeteorJS

Meteor is a platform to build Javascript applications. In meteor there is a lot going on under the hood. Most of the time Meteor has some compatibility with other libraries and frameworks, but sometimes it can be hard to integrate with other tools.

For instance, Meteor will install the Ecmascript package by default, so you don't need to configure Babel yourself. Ecmascript can handle Flow but when you try to install flow-bin and run check, you will most likely get this kind of error:

Error ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ server/main.js

Cannot resolve module meteor/meteor.

     1│ //@flow
     2│ import { Meteor } from 'meteor/meteor'

This is because Meteor has a special way to import files that starts with meteor/, and since those packages are not in node_modules/, Flow has no idea how to find them.

It was quite difficult to find a solution for that issue. There was no mention of Flow type in the Meteor doc and vise versa.

I knew that I would have to edit the .flowconfig somehow. Eventually, I found this article that explains everything.

The thing with those meteor/* packages is that they are located somewhere in the .meteor/local/build/ folder. We need to tell flow to look there too when checking.

The solution

I won't rephrase the article but this is the .flowconfig that did the trick:

[ignore]

.*/.meteor/local/build/programs/server/app/.*
.*/.meteor/local/build/programs/server/assets/.*
.*/.meteor/local/build/programs/server/npm/.*
.*/.meteor/local/build/programs/server/node_modules/.*
.*/.meteor/local/build/programs/web.browser/app/.*
.*/.meteor/local/build/main.js
.*/.meteor/packages/.*

.*/node_modules/fbjs/.*

.*/public/.*

[include]

[libs]

[lints]

[options]

module.name_mapper='^\/\(.*\)$' -> '<PROJECT_ROOT>/\1'
module.name_mapper='^meteor\/\(.*\):\(.*\)$' -> '<PROJECT_ROOT>/.meteor/local/build/programs/server/packages/\1_\2'
module.name_mapper='^meteor\/\(.*\)$' -> '<PROJECT_ROOT>/.meteor/local/build/programs/server/packages/\1'
module.name_mapper='^meteor\/\(.*\)$' -> '<PROJECT_ROOT>/.meteor/local/build/programs/web.browser/packages/\1'

[strict]

And Voilà! Flow should be working nice!

One Gotcha though: those meteor/ modules are located somewhere in the .meteor/local/build/ folder, so make sure that the app has been built before checking :)

Conclusion

Sometimes the simple things can be really difficult to setup and it can be even harder to find the solution.

Thankfully I found about that article that really helped. That's why I've decided to write about it and also create a gist so it might be easier to find the solution for the next person who will try to have Flow working with Meteor.