-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
No simple way to author and share flow packages. #1996
Comments
It seems completely unnecessary. You can just have |
That assumes that everything used by user is exposed through index module which is not necessarily the case, definitely not the case for packages I work with Typed on tiny keyboard
|
+1 Yes, can't separate js.flow from transpiled sources and put them to separate root. flow-files kept class realizations, not only declarations. Sources in my packages compiled from src to dist directory. package.json entry point is "main": "dist/index.js" Documentation is weak, there is no common way to distribute types with npm package. graphql-js example is not a common way, flow files together with code. Some flow-typed projects projects declare all interface in module namespace. Flow developers use smurf-code style type names in global, as React$Component declare module React {
declare var exports: $Exports<'react'>;
} I think, best way is to autoextract flow-types from sources and put them to separate directory, generate flow-files like c++ h-files, But i don't know how. Workaround: manually put interfaces to separate directory and include it into package. my-package/.flowconfig [options]
module.name_mapper='^my-package/i/\(.*\)' -> '<PROJECT_ROOT>/i/\1' my-package/i/public.js: // @flow
export type MyType = number; my-app/app.js: // @flow
import type {MyType} from 'my-package/i/public' In this way we steel need to manually write entry point declarations and put it into flow-typed/my-package.js: my-package/flow-typed/my-package.js: declare module 'my-package' {
declare var exports = ...
} Another workaround: all interfaces as declarations in separate file. But there is a problem on reusing types between declaration files: #1778 my-package/flow-typed/my-package.js: declare module 'my-package' {
declare type myType = number;
} my-app/app.js: // @flow
import type {MyType} from 'my-package' |
In this case you can compile flow files and then copy original with |
Sure one could write such tool, but I'd argue it would be best for the ecosystem if such tool was bundled with flow itself or at least there was a guide on package authoring & distribution with a clear guide & tool recommendation. |
Alternative option (and arguably better one) maybe to do what typescript does, and allow type annotation generation from the source http://www.typescriptlang.org/docs/handbook/compiler-options.html Either way I still think that defaulting to |
Hey! So I've been thinking a lot about this over the past month or two as I've been working on flow-typed. I'm in the middle of several multi-day/heads-down chunks of work at the moment so I'll have to come back in a couple of days for a more complete mind dump of what I had in mind -- but I'm all about getting more thoughts and feedback here. tldr: Shipping |
I found a very easy way to do this, assuming you ship your package with two folders,
Flow will then correctly read the type definitions from the source. Hope this helps somebody |
So I promised to come back to this thread and expand on my thoughts above, so here goes (and I promise to re-format this into actual documentation on the website by next week sometime -- that is long overdue): I'll back up and give lots of context as a (potentially rambly) draft for the docs I just promised to write: Today we have 2 kinds of files in Flow: Implementation files and libdefs. Implementation FilesThese are the normal In addition to normal These shadow files are the recommended best-practice for shipping types with your projects! They let you include the original, typed source code right next to the compiled version of the code which can actually run in the browser/node/etc. As such, when you ship your projects to npm, you should simply include the original source code in a Libdef FilesLibdefs are the files that you either put in When we talk about libdefs we are _not_ talking about (Note to Jeff -- not for the docs: Let's revisit removing support for The great thing about libdefs is that, because they only define interfaces, they have much less surface area to be typechecked. This is a good thing because it is both faster for Flow to typecheck and it limits the number of breaking changes in Flow that might shine through (each new version of Flow is smarter than the last one, so its easy for version N+1 to find new kinds of issues that version N wasn't looking for or missed). Libdefs aren't completely immune to breaking changes in Flow, though: Sometimes new annotation syntax comes along that you might want to use (like flow-typedflow-typed is a shared repository of tested and versioned libdefs for public libraries. The various libdefs are maintained and contributed by the Flow community -- and you should contribute too! Check out the Readme there for more details. flow-typed is relatively new, but in the near future you can expect to see flow-typed play an increasingly important role in the day-to-day use of Flow with 3rd party libraries. For example: Let's say your library uses Flow v0.28 and everything typechecks perfectly before you publish to npm with 2 weeks go by and Flow v0.29 ships. Luckily everything in your library is clean and 0.29 doesn't find any new errors for you. At this point, anyone using your library with either Flow v0.28 or Flow v0.29 will benefit directly from the 2 more weeks go by and Flow v0.30 ships with lots of new kinds of error detection. In fact, it finds some issues with your library that 0.29 didn't notice before! (or maybe it's a little more strict and your library's code just needs some tweaking to preserve safety guarantees). Either way, you're busy and you just haven't had a chance to upgrade your library to v0.30 yet. Meanwhile users of your library have! Now we have a problem: The These newfound errors may or may not be relevant to your library's consumers. If they are relevant (or if the people who notice are good netizens), they'll come to your GitHub repo and send a pull request to fix the issue. But if the errors are not relevant to them, then those consumers are now burdened by noisy type errors that they don't really care about (and maybe don't have time to fix). Luckily there is a solution for the consumers in the latter camp: They can write a libdef to stub out your 3rd party library's interfaces! Better yet: They can then contribute those libdefs up to flow-typed so that others may benefit from their hard work as well. Because flow-typed allows you to specify the version of both Flow and the library the libdef is intended for, it's possible for users to quickly contribute interfaces for your library written using Flow v0.29 that also works for Flow v0.30. (Ok, I have to run to dinner now -- and I haven't had a chance to proof-read my ramblings yet -- but yolo I'm clicking "Comment" and will come back to clean this up and add to the website docs later...) |
I made the simple flow-copy-source module which will take a directory of .js files, and copy them into a destination directory with ".flow" appended to the filename. For example, it works well for projects that have a (.npmignore'd) "src" directory with ES6+/flow-typed code, and a (.gitignore'd) "js" directory containing the transpiled code and the .flow shadow files. ud and react-draggable-list are two projects published on npm using this which have the .js.flow files next to all of the transpiled .js files so that Flow types are automatically detected. This is all handled in the prepublish script of each of those modules' package.json files: |
Thanks @jeffmo for writing this all up. Here is my feedback / thoughts on the plan:
|
I'm glad you brought this up! A tool like this is on my medium-term roadmap. It turns out such a tool could easily generate both libdefs and foo.js // @flow
export function addNums(a: number, b: number): number {
return a + b;
};
**foo.js.flow** (naive version -- suffers from flow-versioning issues)
```js
// @flow
export function addNums(a: number, b: number): number {
return a + b;
}; foo.js.flow (compressed version -- less likely to suffer from flow-versioning issues) // @flow
declare export function addNums(a: number, b: number): number; Both versions of So why support the first version at all once the tool is ready?The main benefit of Additionally, there are some other opportunities in the future for What if |
Oh and I forgot to mention: Another great use-case for this kind of tool would be for generating best-effort libdefs for, say, old versions of Flow that aren't able to type-check a given implementation file without errors. By starting with a libdef that's 95% working you can minimize the amount of work to be done to tweak that version in order to work with Flow vN-1 (and then just upload this to flow-typed) |
Why not just use When minified for browser use, the comments will be removed - when used in development and in Node, they work fine. It adds a tiny amount of bloat compared to shipping React-Grid-Layout does this, and we see output like: // Types
/*:: import type {ResizeEvent, DragEvent, Layout, LayoutItem} from './utils';*/
// End Types
/**
* A reactive, fluid grid layout with draggable, resizable components.
*/
/*:: type State = {
activeDrag: ?LayoutItem,
layout: Layout,
mounted: boolean,
oldDragItem: ?LayoutItem,
oldResizeItem: ?LayoutItem
};*/
var ReactGridLayout = function (_React$Component) {
_inherits(ReactGridLayout, _React$Component);
... |
@STRML But will this work if, for example, a |
You're right - for those transpiled features it will not work correctly. |
I appreciate the proposals here, but lack of current, working examples seems to be an issue. I believe I've tried everything suggested here.
I suspect that some concise examples from existing libraries would go along way, but barring that, any suggestions are greatly welcome. Clarification When I say that the flow checker wants a libdef, what I should say instead is that it complains that the module is not found. |
That shouldn't be happening. Do you have node_modules under the [ignore] section of your .flowconfig? You shouldn't do that. (If there are specific dependencies causing unnecessary Flow errors, then block them specifically.) |
Thanks @agentme, this must have been what happened. I tried again and However, it also passes all checks even when I change my props to something invalid. My
|
=( |
@Yuripetusko You have to see the Flow types as separate from the Javascript code. The Flow type imports have nothing to do with what's going on in Javascript. You just import the types from where they are, that has nothing to do with what's going on in Javascript. |
Thank you, my problem was that i was trying to mix normal js exports and flowtypes somehow together, as soon as i started treating them separately it all worked fine |
tl;dr, is this issue solved? should I close it? |
Is there any place in docs that describe the way to bundle flow typings (.js.flow files) with a lib? |
I don't think there is any mention of |
Compare this description / discussion: facebook/flow#1996 (comment)
Likely not. We probably won't have the "simple" asked for above until flow can generate libdefs for the user (rather than the bloated results from copying original source to |
You don't need to generate or copy sources just reuse them. |
@TrySound that does make sense although you'd still want to generate file per module if you want to allow import per module rather than whole bundle. @agentme Is there any reason for flow-copy-source not to generate pointers instead of copying the whole file ? |
@Gozala Do you really need to install tool to solve this? |
I also have being considering to incorporate transform-flow-comments into my build tool chain which if works may just be good enough solution. |
Generating a single pointer pointing at the source index.js would work in the case that the module isn't built for any other files to be directly imported. Generating a |
If @bouk's suggestion works for you, I've created a script that does just that - it takes your entry point (ie https://github.com/LoganBarnett/cubed.js/blob/master/flow-dist.sh In If you need a more cross platform solution, I would imagine doing the text substitution would be fairly simple from a js file. This needs no recursion and the only artifact here is a relatively small |
I've opened #6504 to fix this. Please have a look |
I have a library which has .flow files alongside .js files ; yet when I import that in one of my application and wrongly use its methods ; the flow does not complain at all. [declarations] [options] flow-bin version: 0.96.0. Library: Note: I'm using npm link method for linking the node_modules. Any help is much appreciated. I've tried and searched all the solutions present in the net especially https://javascriptplayground.com/npm-flowjs-javascript/ but I've not had success. |
It shouldn't be necessary to list the library's files in the declarations section. That might be causing the problem. |
removing it also doesn't help |
@amrit07 if you use |
@amrit07 have the exact same problem. The imported types are interpreted as 'any' |
Documentation does not seem to provide much insight on what is an idiomatic way to write packages like what file extension to use how to build and publish to allow others consume your packages without needing to customize their configurations.
I will just assume that setup used by graphql-js is an idiomatic way to go about it:
src/
directory asmodule.js
files.Problem with such setup is that users of my library loose all of the type information that original source contained. There are ways to workaround it but they either require flow configuration on the consumer side or non trivial build step from the publisher side.
Proposal
I would like to propose following things to improve current situation & grow number of flow typed packages distributed over npm.
module.flow
an idiomatic file extension for flow typed files. For following reasons:module.js
you can't really generate compiled JS files alongside of them.module.js.flow
along the side ofmodule.js
in which case flow would give precedence tomodule.js.flow
overmodule.js
when importing./module
. Unfortunately no attempt to loadmodule.flow
is made. It would actually make sense to alter algorithm slightly so that flow would trymodule.flow
thenmodule.js.flow
and thenmodule.js
which in fact would match node's algorithm more closely which attempts to loadmodule
and thenmodule.js
.This would enable users to author their packages in
module.flow
files and then compile allmodule.flow
files tomodule.js
files along the side them. Publishing such package into npm also would preserve all the type information for consumers, since flow would first look fordep/module.flow
(which will be an original source) beforedep/module.js
.Note: Technically you could achieve more or less same even if your flow code was authored in
module.js
files but that would require copying and renaming them tomodule.js.flow
which as far as I can tell has no trivial cross platform solution & requiring extra scripts isn't great. Another alternative is to just author code asmodule.js.flow
and generatemodule.js
files, it's just authoring in.js.flow
file extension seems awkward.The text was updated successfully, but these errors were encountered: