-
Notifications
You must be signed in to change notification settings - Fork 3
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
First release #2
Comments
I think the role of this library is coming a bit better in focus. Macho is going to use the world mocking pretty extensively for it's cli tests and I'm not happy with how that works yet. So I'd like to wrap this up and preferably release it before returning to Macho. I propose to focus this library on providing a monadic api for doing IO in node. The underlying IO monad being used should be exposed in some way but I'd argue that for the most part you don't need direct access to that at all (you just start with one of the Monad-returning functions and chain from there). By going this way, I think it's a bit easier to show people what this library is about. We can have it mirror the native node implementation (of course using curried functions and IO monads instead of callbacks) so those familiar with Node and Monads should be able to use it straight away. Should there at some point be an interesting in splitting out the IO monad itself into a separate library, for instance to have the flexibility to build another lib for browser IO on top of it, that's of course always a possibility. I've started by automatically creating Monad versions of every Because working in js involves importing a lot of possibly IO oriented libs, I want to add a very simple function to wrap any external function into an IO action, one that automatically adds a method to the world: const myIo = io.extend({
// Resolve returns a synchronous value.
'my.resolve': (path) => require('resolve')(path)
// Globby returns a promise.
globby: (globs) => require('globby')(globs)
})
// myIo contains the native IO actions.
myIo.fs.readFile(...)
// myIo is extended with the user provided IO actions.
myIO.my.resolve(...) For testing, I think a generator-based approach could be really cool: const io = require('./cli')
const myCliTest = ioTestHelper(io, function * () {
// Wait for the cli to call `io.process.argv`.
yield take('process.argv')
// Respond with some made-up answer.
yield put(['myCli', './foo.txt'])
// Wait again for the cli. This time it calls `io.fs.readFile` passing some arguments.
const [readPath, readOptions] = yield take('io.fs.readFile')
// Again return some response.
yield put('Some text in a file\n')
...
}) The test helper could throw if the cli calls another io action than the one specified in the generator. What do you think? |
Btw, the cli app in the test scenario above is just a suggestion. I don't think I'd recommend testing the entire app in that way. Because the functions that make up the app are pure though, we can use it to write effective unit tests for the different parts of the cli. |
This is great! |
Hey, sorry, saw I forgot to respond to this. Perhaps I misunderstand the comment, but the problem I found with just using the functions is that from the outside, you have no idea what the function is supposed to do. The only way to find out is to run it, incurring the side effects, which you don't want in the test scenario. So the names are basically there to make testing nicer. Without them, the test can be told a function is called with certain arguments, but whether it is If you don't rely on the testing functionality and just want to run your IO monads, they bring no advantage. But you won't see them either in using the lib, so I think that's ok, right? |
done. I moved it over and OS-ed it. |
Thanks! Publishes v1.0.0, added some badges and enabled greenkeeper. |
Stuff that needs to happen before we can go public with this. Feel free to add additional points.
npm publish
.The text was updated successfully, but these errors were encountered: