Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: export flow types #94

Merged
merged 14 commits into from
Aug 2, 2018
Merged

chore: export flow types #94

merged 14 commits into from
Aug 2, 2018

Conversation

ardok
Copy link
Collaborator

@ardok ardok commented Jul 29, 2018

Resolves: https://github.com/uber-web/baseui/issues/41


In order to export flow types, we need to include the original files that have the flow definition.
What we're going to do is to add export * from './types.js' from each components.
Then, we will add an accompanying files inside our dist directory (using a rollup plugin) that will end with .js.flow.
The content of the file will only be something like:

// @flow
export * from './src/index.js';

Then, we'll use flow-copy-source on our src directory by excluding some files using glob patterns.
And voila.

Alternatives

There's flow gen-flow-files, but it's still "experimental" and people seem to have issues with it.
facebook/flow#5519

Have tried it for baseui, and we also faced more issues:
facebook/flow#6171
facebook/flow#3281

Samples

// @flow
import {StatefulInput} from '@uber/baseui/input';
<StatefulInput onFocus={2} />

Error ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ src/App.js:21:33

Cannot create StatefulInput element because number [1] is incompatible with function type [2] in property onFocus.

     src/App.js
     18│         <p className="App-intro">
     19│           To get started, edit <code>src/App.js</code> and save to reload.
     20│         </p>
 [1] 21│         <StatefulInput onFocus={2} />
     22│       </div>
     23│     );
     24│   }

     node_modules/@uber/baseui/src/components/input/types.js
 [2] 76│   onFocus: (e: SyntheticFocusEvent<HTMLInputElement>) => void,
// @flow
import type {BaseInputPropsT} from '@uber/baseui/input';
const test: BaseInputPropsT = {
  hello: 2,
};

Error ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ src/App.js:9:31

Cannot assign object literal to test because:
 • property adjoined is missing in object literal [1] but exists in BaseInputPropsT [2].
 • property autoFocus is missing in object literal [1] but exists in BaseInputPropsT [2].
 • property disabled is missing in object literal [1] but exists in BaseInputPropsT [2].
 • property error is missing in object literal [1] but exists in BaseInputPropsT [2].
 • property id is missing in object literal [1] but exists in BaseInputPropsT [2].
 • property inputRef is missing in object literal [1] but exists in BaseInputPropsT [2].
 • property onBlur is missing in object literal [1] but exists in BaseInputPropsT [2].
 • property onChange is missing in object literal [1] but exists in BaseInputPropsT [2].
 • property onFocus is missing in object literal [1] but exists in BaseInputPropsT [2].
 • property overrides is missing in object literal [1] but exists in BaseInputPropsT [2].
 • property placeholder is missing in object literal [1] but exists in BaseInputPropsT [2].
 • property required is missing in object literal [1] but exists in BaseInputPropsT [2].
 • property size is missing in object literal [1] but exists in BaseInputPropsT [2].
 • property type is missing in object literal [1] but exists in BaseInputPropsT [2].
 • property value is missing in object literal [1] but exists in BaseInputPropsT [2].

         6│ import {StatefulInput} from '@uber/baseui/input';
         7│ import type {BaseInputPropsT} from '@uber/baseui/input';
         8│
 [2][1]  9│ const test: BaseInputPropsT = {
        10│   hello: 2,
        11│ };
        12│
        13│ class App extends Component<{}> {
        14│   render() {

Test

There might be other ways to test this, but this is how I test it:

  • Make these changes in package.json of baseui:
  "files": ["dist"],
  "main": "dist/baseui.js",
  "jsnext:main": "dist/baseui.es.js",
  "module": "dist/baseui.es.js",
  • At baseui root dir: yarn build
  • Remove package.json under dist
  • npm pack (npm pack will produce a tgz file).
  • Go to another project, call it foo, do npm install --save path/to/tgz/file
  • Go into foo/node_modules/@uber/baseui and copy the content of dist into the root of foo/node_modules/@uber/baseui.
  • Feel free to remove the dist directory.
  • ./node_modules/.bin/flow stop && ./node_modules/.bin/flow on your project root

@ardok ardok requested a review from gergelyke July 29, 2018 02:06
@ardok ardok changed the title chore: export flow type chore: export flow types Jul 29, 2018
package.json Outdated
@@ -18,6 +18,7 @@
},
"scripts": {
"lint": "eslint ./",
"flow": "flow --show-all-errors",
Copy link
Collaborator Author

@ardok ardok Jul 29, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be run on commit hook as well and be addressed in another PR

@@ -6,4 +6,5 @@ fi;
# When Buildkite publishes to npm, the published files are available in the root
# directory, which allows for a clean include or require of sub-modules.
yarn build
node ./scripts/prepublish-flow.js
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure whether this would work in CI?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Come to think of it, I could just add $FlowFixMe and be done with it during rollup.
So we might end up not needing this prepublish-flow.js

.npmignore Outdated
*.test.js
*.setup.js
*.stories.js
stories.js
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

*.stories.js
stories.js

Can these be combined into just stories.js?

.npmignore Outdated
*.stories.js
stories.js
*.test.js.snap
test
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

*.test.js
*.test.js.snap
test

Can we combine these into just test?

@ardok
Copy link
Collaborator Author

ardok commented Jul 29, 2018

I'm not sure how to fix this flowtype from input:

export function getComponent<T>(
  override: ?OverrideT<T>,
  defaultComponent: React.ComponentType<T>,
): React.ComponentType<T> {
  if (override && typeof override === 'object') {
    return override.component || defaultComponent;
  }
  return override || defaultComponent;
}

@DianaSuvorova
Copy link
Contributor

@ardok, rollup plugin you wrote looks interesting. Can you help me understand if the same result would be achieved if we use something like flow-copy-source in our prepublish.sh script instead?

rollup.config.js Outdated
@@ -9,6 +9,8 @@ import commonjs from 'rollup-plugin-commonjs';
import fs from 'fs';
import path from 'path';

import uberFlowEntry from './scripts/rollup-plugin-flow-entry';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's not use 'uber' prefix here

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okie

@ardok
Copy link
Collaborator Author

ardok commented Jul 30, 2018

@DianaSuvorova Actually, we should use that flow-copy-source to make all the src file ends with .js.flow.
But we would still need the plugin to produce an entry file.

@DianaSuvorova
Copy link
Contributor

@ardok

But we would still need the plugin to produce an entry file.

What do you mean by an entry file?

@ardok
Copy link
Collaborator Author

ardok commented Jul 30, 2018

@DianaSuvorova

// baseui.js.flow
// @flow
// $FlowFixMe path is assuming that it's already in root directory
export * from './src/index.js';

// input/index.js.flow
// @flow
// $FlowFixMe path is assuming that it's already in root directory
export * from '../src/components/input/index.js';

// etc...

rollup.config.js Outdated
@@ -70,6 +72,8 @@ function getSharedConfig({filePath, name}) {
'node_modules/create-react-context/index.js': ['createReactContext'],
},
}),
flowEntry(),
// flowCopySrc(),
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this

package.json Outdated
"files": ["dist"],
"main": "dist/baseui.js",
"jsnext:main": "dist/baseui.es.js",
"module": "dist/baseui.es.js",
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ay, remove these

@ardok ardok requested a review from DianaSuvorova August 1, 2018 22:35
Copy link
Contributor

@DianaSuvorova DianaSuvorova left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job! Left you some comments mostly questions. so sad gen-flow-files is so buggy that we have to do this.

@@ -0,0 +1,19 @@
/* eslint-disable flowtype/require-valid-file-annotation */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why don't you just add // @flow it shouldn't hurt

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, yeah, I'll try that

@@ -0,0 +1,73 @@
/* eslint-disable flowtype/require-valid-file-annotation */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here: // @flow ?

import path from 'path';

/*
We can consider this as well:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well, if you are adding this comment, can you explain why we didn't end up using it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will add more


function getFlowFileContent(filePath) {
/*
Since we're going to copy `dist` dictionary into root in our publish step,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is not the case anymore. We are not copying dist into root. we are distributing dist instead.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will update the comments

we will need to remove one level of the path.
Hence, instead of `../src` and `../../src`, they will become `./src` and `../src` respectively.
*/
const regex = new RegExp(/\.\.\//, 'g');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you explain what this regex matches. I guess some descriptive name instead of regex would do.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, will add more comments on it

@@ -13,3 +13,6 @@ export {
Caption as StyledCaption,
} from './styled-components';
export {STATE_CHANGE_TYPE, ADJOINED, SIZE} from './constants';

// Flow
export * from './types';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need to export these?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So that you could do:
import type {BaseInputPropsT} from '@uber/baseui/input

@DianaSuvorova
Copy link
Contributor

Looks good to me

@ardok ardok merged commit f7b3456 into master Aug 2, 2018
nadiia pushed a commit that referenced this pull request Aug 10, 2018
* chore: export flow type

* chore: simply flow export

* chore: add comment

* chore: use .js.flow files

* chore: rebase with master

* chore: rebase with master

* chore: remove flow from scripts

* chore: remove flowfixme

* chore: go away unpm

* chore: undo package.json changes on files and main stuff

* chore: address comments

* fix: flow error
@abmai abmai deleted the export-flow branch August 13, 2018 20:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants