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

Add checkOpen option #20

Merged
merged 2 commits into from
Feb 19, 2024
Merged

Add checkOpen option #20

merged 2 commits into from
Feb 19, 2024

Conversation

ehmicky
Copy link
Contributor

@ehmicky ehmicky commented Feb 17, 2024

Fixes #7.

The methods in this package check two different things:

  1. Whether the argument has the correct stream type
  2. Whether the stream is writable/readable, i.e. whether it has been closed

There are times when one would want to check only 1. but not 2.. For example:

  • The user might not need the stream to be open since many stream core methods (finished(), .pipe(), etc.) work fine with closed streams.
  • The user might want to provide with a different error message for 1. and 2.

This PR adds a checkOpen boolean option to toggle off that specific check.

By default, it is false for isStream() and true for the others to keep backward compatibility. I.e. this is not a breaking change.

return isStream(stream)
&& stream.writable !== false
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@sindresorhus
Copy link
Owner

sindresorhus commented Feb 19, 2024

By default, it is false for isStream() and true for the others to keep backward compatibility. I.e. this is not a breaking change.

Is this a default you would have chosen if you made this package from scratch today?

@ehmicky
Copy link
Contributor Author

ehmicky commented Feb 19, 2024

Probably not. The better behavior would probably be for checkOpen to always default to true, for all methods including isStream().

I wanted to avoid any breaking change, but I was also suggesting making a major release with #21, for safety, so I could change the default value if you want?

If you'd want to do a major release, I can also do a PR to update the supported Node.js range.

"node": "^12.20.0 || ^14.13.1 || >=16.0.0"

@sindresorhus
Copy link
Owner

I wanted to avoid any breaking change, but I was also suggesting making a major release with #21, for safety, so I could change the default value if you want?

Yeah, then lets change the default.

If you'd want to do a major release, I can also do a PR to update the supported Node.js range.

I can handle that when releasing 👍

@ehmicky
Copy link
Contributor Author

ehmicky commented Feb 19, 2024

There is one catch though. The checkOpen option uses the readable and writable properties. Those properties are always defined (I checked the source code) for all stream classes exposed by core Node.js:

  • stream: Readable, Writable, Duplex, Transform, PassThrough
  • fs: createReadStream(), createWriteStream()
  • http: OutgoingMessage, IncomingMessage, ServerResponse, ClientRequest
  • net: Socket

However, those inherit all from a base class stream.Stream. That base class is actually quite useless:

  • It is undocumented (although it can be imported and used)
  • It is called legacy.js in the source code
  • It only does two things:
    • Inherit from EventEmitter
    • Add a .pipe() method, which is overridden by most of the classes above

Unfortunately, that base class does not define any readable/writable property. But its .pipe() method does expect those properties to exist.

https://github.com/nodejs/node/blob/0550bc149c4e9e13e861f48a112fedde360616db/lib/internal/streams/legacy.js#L20

https://github.com/nodejs/node/blob/0550bc149c4e9e13e861f48a112fedde360616db/lib/internal/streams/legacy.js#L28

So technically, one could inherit from this undocumented base class and miss those properties. But then the .pipe() method would not properly work. And it would differ from all other stream classes.

@ehmicky
Copy link
Contributor Author

ehmicky commented Feb 19, 2024

I thought of a solution to support the above edge case: if stream.writable and stream.readable are both undefined, this means an instance of the Stream base class was passed as argument. If that happens, checkOpen should be a noop with isStream() (but not with other methods).

@ehmicky
Copy link
Contributor Author

ehmicky commented Feb 19, 2024

I implemented the solution above: ready for review 👍

@sindresorhus sindresorhus merged commit dd03f79 into sindresorhus:main Feb 19, 2024
1 check passed
@ehmicky ehmicky deleted the check-open branch February 19, 2024 19:21
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.

depending on definition of writable stream
2 participants