{"action":"created","issue":{"url":"https://api.github.com/repos/facebook/flow/issues/1996","repository_url":"https://api.github.com/repos/facebook/flow","labels_url":"https://api.github.com/repos/facebook/flow/issues/1996/labels{/name}","comments_url":"https://api.github.com/repos/facebook/flow/issues/1996/comments","events_url":"https://api.github.com/repos/facebook/flow/issues/1996/events","html_url":"https://github.com/facebook/flow/issues/1996","id":162009841,"number":1996,"title":"No simple way to author and share flow packages.","user":{"login":"Gozala","id":21236,"avatar_url":"https://avatars.githubusercontent.com/u/21236?v=3","gravatar_id":"","url":"https://api.github.com/users/Gozala","html_url":"https://github.com/Gozala","followers_url":"https://api.github.com/users/Gozala/followers","following_url":"https://api.github.com/users/Gozala/following{/other_user}","gists_url":"https://api.github.com/users/Gozala/gists{/gist_id}","starred_url":"https://api.github.com/users/Gozala/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Gozala/subscriptions","organizations_url":"https://api.github.com/users/Gozala/orgs","repos_url":"https://api.github.com/users/Gozala/repos","events_url":"https://api.github.com/users/Gozala/events{/privacy}","received_events_url":"https://api.github.com/users/Gozala/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":9,"created_at":"2016-06-23T19:58:53Z","updated_at":"2016-07-06T21:58:16Z","closed_at":null,"body":"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.\r\n\r\nI will just assume that setup used by [graphql-js](https://github.com/graphql/graphql-js) is an idiomatic way to go about it:\r\n\r\n- Author source in `src/` directory as `module.js` files.\r\n- Use babel to transpile to plain JS.\r\n- Publish to npm.\r\n\r\nProblem 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.\r\n\r\n## Proposal\r\n\r\nI would like to propose following things to improve current situation & grow number of flow typed packages distributed over npm.\r\n\r\n1. Documentation should certainly include a guide on how to author and publish flow typed package.\r\n2. I would suggest to make `module.flow` an idiomatic file extension for flow typed files. For following reasons:\r\n  1. Flow extends JS syntax so sharing same file extensions does not really makes sense.\r\n  2. If you author files flow code in `module.js` you can't really generate compiled JS files alongside of them.\r\n3. In 0.19 introduced useful feature, that allows putting `module.js.flow` along the side of `module.js` in which case flow would give precedence to `module.js.flow` over `module.js` when importing `./module`. Unfortunately no attempt to load `module.flow` is made. It would actually make sense to alter algorithm slightly so that flow would try `module.flow` then `module.js.flow` and then `module.js` which in fact would match node's algorithm more closely which attempts to load `module` and then `module.js`.\r\n\r\n\r\nThis would enable users to author their packages in `module.flow` files and then compile all `module.flow` files to `module.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 for `dep/module.flow` (which will be an original source) before `dep/module.js`.\r\n\r\nNote: 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 to `module.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 as `module.js.flow` and generate `module.js` files, it's just authoring in `.js.flow` file extension seems awkward.\r\n"},"comment":{"url":"https://api.github.com/repos/facebook/flow/issues/comments/230919868","html_url":"https://github.com/facebook/flow/issues/1996#issuecomment-230919868","issue_url":"https://api.github.com/repos/facebook/flow/issues/1996","id":230919868,"user":{"login":"jeffmo","id":498293,"avatar_url":"https://avatars.githubusercontent.com/u/498293?v=3","gravatar_id":"","url":"https://api.github.com/users/jeffmo","html_url":"https://github.com/jeffmo","followers_url":"https://api.github.com/users/jeffmo/followers","following_url":"https://api.github.com/users/jeffmo/following{/other_user}","gists_url":"https://api.github.com/users/jeffmo/gists{/gist_id}","starred_url":"https://api.github.com/users/jeffmo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jeffmo/subscriptions","organizations_url":"https://api.github.com/users/jeffmo/orgs","repos_url":"https://api.github.com/users/jeffmo/repos","events_url":"https://api.github.com/users/jeffmo/events{/privacy}","received_events_url":"https://api.github.com/users/jeffmo/received_events","type":"User","site_admin":false},"created_at":"2016-07-06T21:58:16Z","updated_at":"2016-07-06T21:58:16Z","body":"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):\r\n\r\nI'll back up and give lots of context as a (potentially rambly) draft for the docs I just promised to write:\r\n\r\nToday we have 2 kinds of files in Flow: Implementation files and libdefs. \r\n\r\n## Implementation Files\r\n\r\nThese are the normal `.js` files you write code in. You might write some annotations in them to be compiled away later by Babel, but ultimately they contain the meat of your source code and the stuff that actually runs in the browser/node/etc.\r\n\r\nIn addition to normal `.js` files, Flow also supports a second kind of implementation file which we'll call \"shadow implementations\". These are just files that end in `.js.flow`. Shadow implementation files can have everything in them that a normal `.js` file can have, except that Flow will give them precedence over an adjacent `.js` file with the same name. So if `foo.js` and `foo.js.flow` sit right next to each other in the same directory, Flow will completely ignore `foo.js` and only read `foo.js.flow` instead.\r\n\r\n**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.\r\n\r\nAs such, when you ship your projects to npm, you should simply include the original source code in a `.js.flow` file that sits next to (and is named the same as) the compiled source code.\r\n\r\n## Libdef Files\r\n\r\nLibdefs are the files that you either put in `<PROJECT_ROOT>/flow-typed` or in the place(s) that you specify in the `[libs]` section of your config. They can ***only*** describe interfaces by way of `declare` statements -- but you can never write normal JS statements in them. [flow-typed](https://github.com/flowtype/flow-typed/) is a growing collection of versioned and tested libdefs for public 3rd-party libraries, but you can also write custom ones if you want.\r\n\r\nWhen we talk about libdefs we are ***not*** talking about `.js.flow` files -- they are different things. Libdefs can only contain `declare` statements -- including `declare module` statements. Shadow files act just like a `.js` file, except they *shadow* the `.js` file they would be if the \".flow\" were removed from their name. Putting a `declare module` inside a shadow file is not useful and almost certainly doesn't do what you want since shadow files already represent a module themselves.\r\n\r\n*(Note to Jeff -- not for the docs: Let's revisit removing support for `declare module` anywhere except for libdefs)*\r\n\r\nThe 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).\r\n\r\nLibdefs aren't completely immune to breaking changes in Flow, though: Sometimes new annotation syntax comes along that you might want to use (like `declare module.exports`) or old annotation syntax could be deprecated (like using `declare var exports` to declare the type of `module.exports`). We deal with this by versioning libdefs in flow-typed by the version of Flow they've been tested against (and by actually requiring tests for that libdef so that we can run it against future versions of Flow to see if it's still compatible). Luckily, though, most libdefs are forward-compatible most of the time since we don't make that many breaking changes to libdef syntax/semantics.\r\n\r\n## [flow-typed](https://github.com/flowtype/flow-typed/)\r\n\r\n**flow-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](https://github.com/flowtype/flow-typed/blob/master/README.md) there for more details.\r\n\r\nflow-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.\r\n\r\n**For example:** Let's say your library uses Flow v0.28 and everything typechecks perfectly before you publish to npm with `.js.flow` files.\r\n\r\n2 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 `.js.flow` files you shipped (because they are compatible and typecheck with both versions of Flow).\r\n\r\n2 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 `.js.flow` files you shipped to npm actually cause Flow errors in your consumers' projects!\r\n\r\nThese 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).\r\n\r\nLuckily 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.\r\n\r\n(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...)"}}
{"actor":{"display_login":"jeffmo"}}