Skip to content

node, ws: address() method on Server and related classes can return a string#25597

Merged
sheetalkamat merged 4 commits intoDefinitelyTyped:masterfrom
thw0rted:node-addressinfo
May 8, 2018
Merged

node, ws: address() method on Server and related classes can return a string#25597
sheetalkamat merged 4 commits intoDefinitelyTyped:masterfrom
thw0rted:node-addressinfo

Conversation

@thw0rted
Copy link
Copy Markdown
Contributor

@thw0rted thw0rted commented May 8, 2018

  • Use a meaningful title for the pull request. Include the name of the package modified.

  • Test the change in your own code. (Compile and run.)

  • Add or edit tests to reflect the change. (Run with npm test.)

  • Follow the advice from the readme.

  • Avoid common mistakes.

  • Run npm run lint package-name (or tsc if no tslint.json is present).

  • Provide a URL to documentation or source code which provides context for the suggested changes:

  • Increase the version number in the header if appropriate. N/A

  • If you are making substantial changes, consider adding a tslint.json containing { "extends": "dtslint/dt.json" }. N/A


Two open questions before this gets merged.

One, is it OK to make changes to multiple packages in one PR? The update to ws is what I actually wanted to make but doing so required exposing the interface from node. Changing the function signature in node broke tests on several other packages, so I fixed those at the same time. I can submit separate PRs if need be.

Two, is there a convention about where to put named interfaces for structures that aren't named in the actual library being described? Node does not actually define an AddressInfo type anywhere in its codebase or documentation, but it's an object shape that's used in many places so it makes sense to have one in the typings. I'm just not sure where it belongs. I moved it into net because that made sense to me.

@thw0rted thw0rted mentioned this pull request May 8, 2018
9 tasks
@typescript-bot typescript-bot added Popular package This PR affects a popular package (as counted by NPM download counts). The Travis CI build failed labels May 8, 2018
@typescript-bot
Copy link
Copy Markdown
Contributor

typescript-bot commented May 8, 2018

@thw0rted Thank you for submitting this PR!

🔔 @hertzg @parambirs @tellnes @WilcoBakker @octo-sniffle @smac89 @Flarna @mwiktorczyk @wwwy3y3 @DeividasBakanas @kjin @alvis @OliverJAsh @eps1lon @Hannes-Magnusson-CK @jkomyno @ajafff @hoo29 @n-e @markisme @Taisiias @dex4er @MugeSo @nickmorton @loyd @elithrar @mlamp @TitaneBoy @orblazer - please review this PR in the next few days. Be sure to explicitly select Approve or Request Changes in the GitHub UI so I know what's going on.

If no reviewer appears after a week, a DefinitelyTyped maintainer will review the PR instead.

@typescript-bot
Copy link
Copy Markdown
Contributor

typescript-bot commented May 8, 2018

@thw0rted The Travis CI build failed! Please review the logs for more information.

Once you've pushed the fixes, the build will automatically re-run. Thanks!

@thw0rted
Copy link
Copy Markdown
Contributor Author

thw0rted commented May 8, 2018

Whoever comes to review this, can you take a look at that Travis build? It looks like some kind of internal error, not related to the PR.

@Flarna
Copy link
Copy Markdown
Contributor

Flarna commented May 8, 2018

Node part looks correct.
@thw0rted regarding CI fail I have no idea... maybe retry by pushing again or close/reopen.

@typescript-bot typescript-bot added the Owner Approved A listed owner of this package signed off on the pull request. label May 8, 2018
@thw0rted thw0rted closed this May 8, 2018
@thw0rted thw0rted reopened this May 8, 2018
@typescript-bot
Copy link
Copy Markdown
Contributor

A definition owner has approved this PR ⭐️. A maintainer will merge this PR shortly. If it shouldn't be merged yet, please leave a comment saying so and we'll wait. Thank you for your contribution to DefinitelyTyped!

Amending commit message to re-trigger Travis build.
@thw0rted thw0rted force-pushed the node-addressinfo branch from 44a9fbf to 902921d Compare May 8, 2018 13:27
@sheetalkamat sheetalkamat merged commit ba59e57 into DefinitelyTyped:master May 8, 2018
KSXGitHub pushed a commit to KSXGitHub/DefinitelyTyped that referenced this pull request May 12, 2018
… string (DefinitelyTyped#25597)

* node: ClearTextStream hasn't existed for 3 years

* node: move AddressInfo to net module; address() can return string

* ws: Server.address() can return string (same as net.Server.address etc)

* Fix some tests that assumed Server.address returns AddressInfo
Amending commit message to re-trigger Travis build.
@austinried
Copy link
Copy Markdown
Contributor

austinried commented Jun 1, 2018

Hey @thw0rted @Flarna just so you're aware, this type of change breaks compatibility with older node type definitions. Because you updated @types/node for version 10 with a new interface, using that interface in any other package (like @types/ws) means they now have a dependency on the version 10 node types. The version of the @types package is in general supposed to match the version of the npm package it describes like that so you can easily tell what version of the package the types describe (since there are typically breaking interface changes between major versions).

This creates a breaking situation for anyone using the ws package and the associated types on a version of node < 10, because they will want to use an @types/node package that accurately describes their node version (e.g.: @types/node@6 if they're using node 6 LTS) but they don't have this new interface.

I have opened a PR to fix this issue #26196 in @types/ws, but I didn't realize this was a change made to @types/node at the same time, so I would also recommend reverting the other changes here that affect swaggerize-express, smtp-server, and net-keepalive as I imagine they don't actually require node >= 10 either.

@thw0rted
Copy link
Copy Markdown
Contributor Author

thw0rted commented Jun 1, 2018

I thought the way NPM was supposed to handle this was that the top level project can rely on @types/node@6 and @types/ws@latest, and NPM would automatically (?) add a second-order dependency under node_modules/@types/ws/node_modules/@types/node with the v10 typings. Is that not what's happening? Is it not desirable?

Alternately: in this specific case, I believe the problem is that an anonymous interface was given a name and exported, then used in the packages you listed. The interface has existed and been used in more or less all versions of @types/node... would it be easier to just to back through all the older versions and make the same changes I made in v10 (and I think maybe also v9)?

@austinried
Copy link
Copy Markdown
Contributor

NPM does not resolve it that way in this case, no. The dependencies for @types/ws lists "@types/node": "*" which means any version satisfies the constraint, and it will install the latest if none is already installed. I think it would also be undesirable for it to install its own dependency for node 10 just for this interface, as it doesn't actually seem to have a lot to do with changes made in node 10.

You could also go back and make the interface available in older versions of node, but to do it the right way you'd want to find out when that interface was introduced and go all the way back to that version. After reading through your changes and the ws code that actually returns that AddressInfo object a little more, I think that might actually be most appropriate since it is returning the object directly from http.Server's address() method.

@thw0rted
Copy link
Copy Markdown
Contributor Author

thw0rted commented Jun 1, 2018

I'm still kind of new at this, but I think the problem is one of conventions in the vanilla-JS world. Before TS came along, JS didn't have the vocabulary to discuss interfaces -- at least, not something universal and consistent. So you had years of docs saying "this function returns an object with the following structure..." but never gave a name to that structure. Since the canonical docs that were (probably) used to generate the initial DT typings don't explicitly label an interface (and why would they?), it's up to individual DT authors to decide if and how to name interfaces -- and once that decision is made, it has ramifications for all versions in the future.

Now, with the benefit of hindsight (!), I can say that the decision to not name the interface used in these functions -- or worse yet, to name it in some places and not others -- was a mistake. But retroactively fixing that mistake, going to a better design, causes the breakage you're seeing. Like I said, I'm new here, so I don't know how the community wants to see these problems solved. I think the structure-I-call-AddressInfo has been in Node for as far back as I can still find docs, but whose code am I going to break if I reach back into older versions and label it?

@austinried
Copy link
Copy Markdown
Contributor

austinried commented Jun 1, 2018

No worries, I can't really say I'm an expert either but I've got some experience under my belt with tracking down these type definition issues since we deal with quite a lot of them at my work.

Regarding your concerns about labeling the interface, it's not really the giving it a name that breaks it, it's that you added that name in a version of the node types that not everyone can use, and then imported it into the dependent packages. The name itself in TS isn't taken into account when it comes to type compatibility. Your AddressInfo and someone else's anonymous { port: number; family: string; address: string; } are perfectly compatible, you can replace one with the other just fine. Here's some more info on the subject: https://www.typescriptlang.org/docs/handbook/type-compatibility.html

@Flarna
Copy link
Copy Markdown
Contributor

Flarna commented Jun 1, 2018

I'm quite sure that net.server.address() returns string | AddressInfo since more or less always. The string case is if a Pipe/UnixDomainSocket is used, AddressInfo in case a TCP socket is used. The string case was not documented from node for a long time (see nodejs/node#12907) so searching through the history of node docs will not give the truth.
Dependencies between typings like this are a pain as on the one hand it's perfectly valid to mix latest ws with node 6, 8 or 10 - but most fixes for node typings are only done in latest version.

In this case it would be most likely best to update also older node versions. But as this change is breaking for quite some users - pipe/domain socket servers are use rare and even then users know what they use but after the change a cast/type check is needed it may result in complains.
I was thinking about using a generic to select between TCP/Pipe but as it is possible to switch between them it's not possible.

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

Labels

Owner Approved A listed owner of this package signed off on the pull request. Popular package This PR affects a popular package (as counted by NPM download counts).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants