Skip to content

Instantly share code, notes, and snippets.

@xjamundx
Last active October 16, 2017 12:30
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xjamundx/ffafa67925db6d7ffc4c86a7fb2bcb45 to your computer and use it in GitHub Desktop.
Save xjamundx/ffafa67925db6d7ffc4c86a7fb2bcb45 to your computer and use it in GitHub Desktop.

Trying Flow on my node.js code…Let’s see how this goes

Finding the getting started guide:

  1. google flow
  2. click “getflow.com”
  3. was something else
  4. google flow javascript
  5. found flowtype.org
  6. Click “get started” and landed here https://flowtype.org/docs/getting-started.html#_

Following the guide:

First thoughts, okay this is for a new project, but I’m not making a new project, so adapting to my life. In this case we’ll try with my node.js project.

  1. touch .flowconfig
  2. npm install --save-dev flow-bin
  3. Add // @flow to my index.js file // seems gross to me, but doing it anyway
  4. Typing npm run-script flow thought maybe it would work, but it doesn’t. get “missing script: flow”
  5. Typing ./node_modules/.bin/flow instead (not from docs)
  6. lots of weird startup stuff…. “flow is still initializing”
  7. “Found 43 errors”
node_modules/findup/test/fixture/f/e/d/c/b/a/top.json:1
  1: 
     ^ Unexpected end of input

node_modules/findup/test/fixture/f/e/d/c/config.json:1
  1: 
     ^ Unexpected end of input
.... // goes on an on

Errors some pretty unrelated to anything I'm doing. Giving up.

Will Try Some More Things....

  1. google the error messages
  2. Found facebook/flow#1420 (comment) trying it
  3. "Found 49 errors" > 6 more errors than last time!!?!?
  4. Okay there's a not about the main field with that regex, trying another regex .*/node_modules/.*/\(lib\|test\).*\.json$
  5. "Found 36 errors" > hey progress
  6. Let's look at the last two
node_modules/react/node_modules/fbjs/lib/Deferred.js.flow:60
 60:     Promise.prototype.done.apply(this._promise, arguments);
                           ^^^^ property `done`. Property not found in
497: declare class Promise<+R> {
     ^ Promise. See lib: /private/tmp/flow/flowlib_22c9017e/core.js:497

node_modules/react/node_modules/fbjs/lib/shallowEqual.js.flow:29
 29:     return x !== 0 || 1 / (x: $FlowIssue) === 1 / (y: $FlowIssue);
  1. Seems like facebook is breaking flow. Pretty weird.
  2. Googling it.
  3. Found facebookarchive/draft-js#305
  4. @zpao says we need to update fbjs. I don't even use that dep directly, so I don't agree.
  5. Getting annoyed again, but running npm ls fbjs
p2pnodeweb@1.29.0 /Users/jamuferguson/dev/paypal/web
├─┬ flux@2.1.1
│ └─┬ fbemitter@2.0.2
│   └── fbjs@0.7.2 
└─┬ react@15.3.1
  └── fbjs@0.8.4 
  1. grep 'version":' ./node_modules/fbjs/package.json
  2. "0.1.0-alpha.7"
  3. Hmm, seems old npm i fbjs
  4. grep 'version":' ./node_modules/fbjs/package.json
  5. "version": "0.8.4"
  6. seems better, let's
  7. ./node_modules/.bin/flow
  8. "Found 38 Errors" > Okay ,that's 2 more than before" and more JSON errors in there

giving up again, for now

@xjamundx
Copy link
Author

With some suggestions updated my flowconfig:

[options]
suppress_type=$FlowIssue
suppress_type=$FlowFixMe

[ignore]
.*/node_modules/.*[^e]\.json$
.*/node_modules/.*\(lib\|test\).*\.json$

Now get only 33 errors

node_modules/consumerweb-mocks/dummyData/rpsProfile.json:1
  1: 
     ^ Unexpected end of input

node_modules/fbemitter/node_modules/fbjs/lib/Deferred.js.flow:25
 25:   _promise: Promise;
                 ^^^^^^^ Promise. Application of polymorphic type needs <list of 1 argument>. (Can use `*` for inferrable ones)

node_modules/fbemitter/node_modules/fbjs/lib/Deferred.js.flow:37
 37:   getPromise(): Promise {
                     ^^^^^^^ Promise. Application of polymorphic type needs <list of 1 argument>. (Can use `*` for inferrable ones)

node_modules/fbemitter/node_modules/fbjs/lib/Deferred.js.flow:51
 51:   then(): Promise {
               ^^^^^^^ Promise. Application of polymorphic type needs <list of 1 argument>. (Can use `*` for inferrable ones)

node_modules/fbemitter/node_modules/fbjs/lib/Deferred.js.flow:56
 56:     Promise.prototype.done.apply(this._promise, arguments);
                           ^^^^ property `done`. Property not found in
497: declare class Promise<+R> {
     ^ Promise. See lib: /private/tmp/flow/flowlib_dffaaca/core.js:497

node_modules/fbemitter/node_modules/fbjs/lib/PromiseMap.js.flow:15
 15: var Deferred = require('Deferred');
                    ^^^^^^^^^^^^^^^^^^^ Deferred. Required module not found

node_modules/fbemitter/node_modules/fbjs/lib/PromiseMap.js.flow:31
 31:   get(key: string): Promise {
                         ^^^^^^^ Promise. Application of polymorphic type needs <list of 1 argument>. (Can use `*` for inferrable ones)

node_modules/fbemitter/node_modules/fbjs/lib/fetchWithRetries.js.flow:16
 16: var ExecutionEnvironment = require('ExecutionEnvironment');
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ExecutionEnvironment. Required module not found

node_modules/fbemitter/node_modules/fbjs/lib/fetchWithRetries.js.flow:18
 18: var sprintf = require('sprintf');
                   ^^^^^^^^^^^^^^^^^^ sprintf. Required module not found

node_modules/fbemitter/node_modules/fbjs/lib/fetchWithRetries.js.flow:19
 19: var fetch = require('fetch');
                 ^^^^^^^^^^^^^^^^ fetch. Required module not found

node_modules/fbemitter/node_modules/fbjs/lib/fetchWithRetries.js.flow:43
 43: ): Promise {
        ^^^^^^^ Promise. Application of polymorphic type needs <list of 1 argument>. (Can use `*` for inferrable ones)

node_modules/fbjs/lib/Deferred.js.flow:60
 60:     Promise.prototype.done.apply(this._promise, arguments);
                           ^^^^ property `done`. Property not found in
497: declare class Promise<+R> {
     ^ Promise. See lib: /private/tmp/flow/flowlib_dffaaca/core.js:497

node_modules/flux/flow/include/FluxContainer.js:14
 14: var FluxStoreGroup = require('FluxStoreGroup');
                          ^^^^^^^^^^^^^^^^^^^^^^^^^ FluxStoreGroup. Required module not found

node_modules/flux/flow/include/FluxContainer.js:17
 17: var shallowEqual = require('shallowEqual');
                        ^^^^^^^^^^^^^^^^^^^^^^^ shallowEqual. Required module not found

node_modules/flux/flow/include/FluxContainer.js:40
 40: ): ReactClass<DefaultProps, Props, State> {
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type application of identifier `ReactClass`. Too many type arguments. Expected at most 1
104: type ReactClass<Config> = _ReactClass<*, *, Config, *>;
                     ^^^^^^ See type parameters of definition here. See lib: /private/tmp/flow/flowlib_dffaaca/react.js:104

node_modules/flux/flow/include/FluxMapStore.js:15
 15: import type Dispatcher from 'Dispatcher';
                                 ^^^^^^^^^^^^ Dispatcher. Required module not found

node_modules/flux/flow/include/FluxMapStore.js:17
 17: var FluxReduceStore = require('FluxReduceStore');
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^ FluxReduceStore. Required module not found

node_modules/flux/flow/include/FluxMixinLegacy.js:15
 15: import type * as FluxStore from 'FluxStore';
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ import type * as FluxStore. This is invalid syntax. Maybe you meant: `import type FluxStore from "FluxStore"`?

node_modules/flux/flow/include/FluxMixinLegacy.js:15
 15: import type * as FluxStore from 'FluxStore';
                                     ^^^^^^^^^^^ FluxStore. Required module not found

node_modules/flux/flow/include/FluxMixinLegacy.js:17
 17: var FluxStoreGroup = require('FluxStoreGroup');
                          ^^^^^^^^^^^^^^^^^^^^^^^^^ FluxStoreGroup. Required module not found

node_modules/flux/flow/include/FluxReduceStore.js:15
 15: import type Dispatcher from 'Dispatcher';
                                 ^^^^^^^^^^^^ Dispatcher. Required module not found

node_modules/flux/flow/include/FluxReduceStore.js:17
 17: var FluxStore = require('FluxStore');
                     ^^^^^^^^^^^^^^^^^^^^ FluxStore. Required module not found

node_modules/flux/flow/include/FluxReduceStore.js:19
 19: var abstractMethod = require('abstractMethod');
                          ^^^^^^^^^^^^^^^^^^^^^^^^^ abstractMethod. Required module not found

node_modules/flux/flow/include/FluxStore.js:15
 15: import type Dispatcher from 'Dispatcher';
                                 ^^^^^^^^^^^^ Dispatcher. Required module not found

node_modules/flux/flow/include/FluxStoreGroup.js:15
 15: import type Dispatcher from 'Dispatcher';
                                 ^^^^^^^^^^^^ Dispatcher. Required module not found

node_modules/flux/flow/include/FluxStoreGroup.js:16
 16: import type FluxStore from 'FluxStore';
                                ^^^^^^^^^^^ FluxStore. Required module not found

node_modules/flux/flow/include/FluxStoreGroup.js:55
 55:   if (__DEV__) {
           ^^^^^^^ identifier `__DEV__`. Could not resolve name

node_modules/flux/node_modules/fbjs/flow/include/PromiseMap.js:15
 15: var Deferred = require('Deferred');
                    ^^^^^^^^^^^^^^^^^^^ Deferred. Required module not found

node_modules/flux/node_modules/fbjs/flow/include/PromiseMap.js:19
 19: import type * as Promise from 'Promise';
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ import type * as Promise. This is invalid syntax. Maybe you meant: `import type Promise from "Promise"`?

node_modules/flux/node_modules/fbjs/flow/include/fetchWithRetries.js:16
 16: var ExecutionEnvironment = require('ExecutionEnvironment');
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ExecutionEnvironment. Required module not found

node_modules/flux/node_modules/fbjs/flow/include/fetchWithRetries.js:19
 19: var sprintf = require('sprintf');
                   ^^^^^^^^^^^^^^^^^^ sprintf. Required module not found

node_modules/flux/node_modules/fbjs/flow/include/fetchWithRetries.js:20
 20: var fetch = require('fetch');
                 ^^^^^^^^^^^^^^^^ fetch. Required module not found

node_modules/react/node_modules/fbjs/lib/Deferred.js.flow:60
 60:     Promise.prototype.done.apply(this._promise, arguments);
                           ^^^^ property `done`. Property not found in
497: declare class Promise<+R> {
     ^ Promise. See lib: /private/tmp/flow/flowlib_dffaaca/core.js:497

The first one seems valid, the rest just seem random

@xjamundx
Copy link
Author

Added .*/node_modules/flux/* to the [ignore] thing and we only have 13 errors now. Again at this point I'm gritting my teeth pretty hard, but it seems to be getting better.

@xjamundx
Copy link
Author

Slightly worried that I'm breaking things. Like if I React to that list, it just won't type-check react right?

@xjamundx
Copy link
Author

xjamundx commented Aug 29, 2016

[options]
suppress_type=$FlowIssue
suppress_type=$FlowFixMe

[ignore]
.*/node_modules/.*[^e]\.json$
.*/node_modules/.*\(lib\|test\).*\.json$
.*/node_modules/flux/*
.*/node_modules/fbemitter/*

Now only shows these 3 errors

node_modules/consumerweb-mocks/dummyData/rpsProfile.json:1
  1: 
     ^ Unexpected end of input

node_modules/fbjs/lib/Deferred.js.flow:60
 60:     Promise.prototype.done.apply(this._promise, arguments);
                           ^^^^ property `done`. Property not found in
497: declare class Promise<+R> {
     ^ Promise. See lib: /private/tmp/flow/flowlib_3c13824c/core.js:497

node_modules/react/node_modules/fbjs/lib/Deferred.js.flow:60
 60:     Promise.prototype.done.apply(this._promise, arguments);
                           ^^^^ property `done`. Property not found in
497: declare class Promise<+R> {
     ^ Promise. See lib: /private/tmp/flow/flowlib_3c13824c/core.js:497


Found 3 errors

The first one is legit (it's an empty file)

@xjamundx
Copy link
Author

xjamundx commented Aug 29, 2016

Okay, seems like things are getting less crazy. Let's try adding // @flow to one of my controllers.

Now seeing this:

controllers/transfer/abc.js:111
111: export async function someMethod(req, res, next) {
                                                 ^^^ parameter `req`. Missing annotation

controllers/transfer/abc.js:111
111: export async function someMethod(req, res, next) {
                                                      ^^^ parameter `res`. Missing annotation

controllers/transfer/abc.js:111
111: export async function someMethod(req, res, next) {
                                                           ^^^^ parameter `next`. Missing annotation

controllers/transfer/abc.js:119
119:            return next()
                ^^^^^^^^^^^^^ async return. Missing annotation

controllers/transfer/abc.js:125
125:            return next()
                ^^^^^^^^^^^^^ async return. Missing annotation

...

@xjamundx
Copy link
Author

xjamundx commented Aug 29, 2016

So you can do this

function controllerMethod(req: http$ClientRequest, res: http$ServerResponse) {

@xjamundx
Copy link
Author

screen shot 2016-08-29 at 7 45 12 pm

@xjamundx
Copy link
Author

That worked pretty well, now running into this one:

363: export async function middleware(req: http$ClientRequest, res: http$ServerResponse, next) {
                                                                                             ^^^^ parameter `next`. Missing annotation

@xjamundx
Copy link
Author

We can call next a function. Pretty easy. next: function

@xjamundx
Copy link
Author

so (req, res, next) becomes (req: http$ClientRequest, res: http$ServerResponse, next: function)

@xjamundx
Copy link
Author

xjamundx commented Aug 30, 2016

Now we're getting this error:

controllers/app/file.js:79                                                                                                
 79:            toAmount: req.query.amount                                                                                             
                              ^^^^^ property `query`. Property not found in                                                            
 79:            toAmount: req.query.amount                                                                                             
                          ^^^ http$ClientRequest            

Which I assume means that while it knows about the vanilla node.js req it doens't know about express specific properties like req.query.

@xjamundx
Copy link
Author

Found a solution here:
http://stackoverflow.com/questions/39218191/import-type-definition-for-express/39218378#39218378

Also any would probably fine for those types, because it's a mess anyway.

@xjamundx
Copy link
Author

xjamundx commented Aug 30, 2016

Now seeing a ton of:

118:            return next()
                ^^^^^^^^^^^^^ async return. Missing annotation

I assume the problem here is that it's doesn't like that we use this shortcut to return and call next() on the same line, because technically it will return the results of the next() function (which is usualy nothing).

Maybe adding : void to the function declaration will help?

Or maybe I'll have to do:

next()
return

@xjamundx
Copy link
Author

Nothing seems to work.

Here's the results of trying return void next()

118:            return void next()
                ^^^^^^^^^^^^^^^^^^ async return. Missing annotation

Here's the results of putting them on separate lines:

119:            return
                ^^^^^^ async return. Missing annotation

@xjamundx
Copy link
Author

And async function always returns a Promise, so maybe it's getting confused? Or maybe there's just some special way that it needs to be annotated.

@xjamundx
Copy link
Author

xjamundx commented Aug 30, 2016

Okay got it. While I think it should be built-in, adding this to the end of the functional declaration seems to work

: Promise<void>

So our async middleware looks like this:

async function middleware(req: ExpressReq, res: any, next: function): Promise<void> {

@xjamundx
Copy link
Author

xjamundx commented Aug 30, 2016

Now running into this issue:

 const [contacts, fancyList: CustomType[] = [], randomThing = ''] = results
                                         ^^^^^^^^^^^^^^^^^^^ assignment of identifier `randomThing`. Could not resolve name

But I think it will be sorted out by:
facebook/flow#2239

@xjamundx
Copy link
Author

Was still getting these errors

node_modules/fbjs/lib/Deferred.js.flow:60
 60:     Promise.prototype.done.apply(this._promise, arguments);
                           ^^^^ property `done`. Property not found in
[libs]
497: declare class Promise<+R> {
     ^ Promise. See lib: /private/tmp/flow/flowlib_25b721b0/core.js:497

node_modules/react/node_modules/fbjs/lib/Deferred.js.flow:60
 60:     Promise.prototype.done.apply(this._promise, arguments);
                           ^^^^ property `done`. Property not found in
497: declare class Promise<+R> {
     ^ Promise. See lib: /private/tmp/flow/flowlib_25b721b0/core.js:497

So I added the following to the [ignore]:

.*/node_modules/.*fbjs/*

@xjamundx
Copy link
Author

Now trying to get babel to work. Seems kind of busted. Lots of these errors.

express-session deprecated undefined saveUninitialized option; provide saveUninitialized option node_modules/kraken-js/node_modules/meddleware/index.js:105:20
express-session deprecated req.secret; provide secret option node_modules/kraken-js/node_modules/meddleware/index.js:105:20
Tue, 30 Aug 2016 04:34:14 GMT unhandledRejection
SyntaxError: /Users/jamuferguson/dev/paypal/code/controllers/app/controller.js: Unexpected token (110:76)
  109 |  */
> 110 | export async function middleware(req: ExpressReq, res: any, next: function): Promise<void> {
      |                                                                             ^
  111 | 
    at Parser.pp.raise (/Users/jamuferguson/dev/paypal/code/node_modules/babylon/lib/parser/location.js:22:13)
    at Parser.pp.unexpected (/Users/jamuferguson/dev/paypal/code/node_modules/babylon/lib/parser/util.js:91:8)
    at Parser.pp.flowParsePrimaryType (/Users/jamuferguson/dev/paypal/code/node_modules/babylon/lib/plugins/flow.js:1101:8)

@xjamundx
Copy link
Author

xjamundx commented Aug 30, 2016

I guess we need to do this instead?

Replace next: function with next: Function

Weird that flow didn't mind the issue. Not actually seeing how to annotate functions very clearly. Looking here:
https://flowtype.org/docs/functions.html

@eliranmal
Copy link

this is totally fascinating.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment