Skip to content

Commit

Permalink
Allow all options in read/write streams interface (#77)
Browse files Browse the repository at this point in the history
* Allow all options in read/write streams interface

* Fix eslint issue
  • Loading branch information
JordanMartinez authored Jul 14, 2023
1 parent 0020e02 commit be0a346
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 112 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"parserOptions": {
"ecmaVersion": 6,
"ecmaVersion": 9,
"sourceType": "module"
},
"extends": "eslint:recommended",
Expand Down
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,24 @@ New features:
getGid :: Stats -> Number
getGid s = Stats.gid s
```
- Update `[fd]createReadStream`/`[fd]createWriteStream` to allow more options (#77 by @JordanMartinez)

| Removes... | ...in favor of |
| - | - |
| `createReadStreamWith` | `createReadStream'` |
| `fdCreateReadStreamWith` | `fdCreateReadStream'` |
| `createWriteStreamWith` | `createWriteStream'` |
| `fdCreateWriteStreamWith` | `fdCreateWriteStream'` |

In the new APIs, all options are exposed and may require converting
PureScript values to JavaScript ones.
```purs
filePath # createWriteStream'
{ flags: fileFlagsToNode R
, encoding: encodingToNode UTF8
, mode: permsToInt Perms.all
}
```

Bugfixes:

Expand Down
15 changes: 11 additions & 4 deletions src/Node/FS/Stream.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
export {
createReadStream as createReadStreamImpl,
createWriteStream as createWriteStreamImpl
} from "fs";
import fs from "node:fs";

export const createReadStreamImpl = (path) => fs.createReadStream(path);
export const createReadStreamOptsImpl = (path, opts) => fs.createReadStream(path, opts);
export const fdCreateReadStreamImpl = (fd) => fs.createReadStream(null, { fd });
export const fdCreateReadStreamOptsImpl = (fd, opts) => fs.createReadStream(null, { ...opts, fd});

export const createWriteStreamImpl = (path) => fs.createWriteStream(path);
export const createWriteStreamOptsImpl = (path, opts) => fs.createWriteStream(path, opts);
export const fdCreateWriteStreamImpl = (fd) => fs.createWriteStream(null, { fd });
export const fdCreateWriteStreamOptsImpl = (fd, opts) => fs.createWriteStream(null, { ...opts, fd});
228 changes: 121 additions & 107 deletions src/Node/FS/Stream.purs
Original file line number Diff line number Diff line change
@@ -1,138 +1,152 @@
module Node.FS.Stream
( createWriteStream
, fdCreateWriteStream
, WriteStreamOptions
, defaultWriteStreamOptions
, createWriteStreamWith
, fdCreateWriteStreamWith
, createWriteStream'
, fdCreateWriteStream
, fdCreateWriteStream'
, createReadStream
, fdCreateReadStream
, ReadStreamOptions
, defaultReadStreamOptions
, createReadStreamWith
, fdCreateReadStreamWith
, createReadStream'
, fdCreateReadStream
, fdCreateReadStream'
) where

import Prelude

import Data.Nullable (Nullable, notNull, null)
import Effect (Effect)
import Effect.Uncurried (EffectFn2, runEffectFn2)
import Effect.Uncurried (EffectFn1, EffectFn2, runEffectFn1, runEffectFn2)
import Node.FS (FileDescriptor)
import Node.FS.Constants (FileFlags(..), fileFlagsToNode)
import Node.FS.Perms (Perms)
import Node.FS.Perms as Perms
import Node.Path (FilePath)
import Node.Stream (Readable, Writable)

foreign import createReadStreamImpl :: forall opts. EffectFn2 (Nullable FilePath) { | opts } (Readable ())
foreign import createWriteStreamImpl :: forall opts. EffectFn2 (Nullable FilePath) { | opts } (Writable ())

readWrite :: Perms
readWrite = Perms.mkPerms rw rw rw
where
rw = Perms.read + Perms.write
import Prim.Row as Row

-- | Create a Writable stream which writes data to the specified file, using
-- | the default options.
createWriteStream
:: FilePath
createWriteStream :: FilePath -> Effect (Writable ())
createWriteStream f = runEffectFn1 createWriteStreamImpl f

foreign import createWriteStreamImpl :: EffectFn1 (FilePath) (Writable ())

type WriteStreamOptions =
( flags :: String
, encoding :: String
, mode :: Int
, autoClose :: Boolean
, emitClose :: Boolean
, start :: Int
)

-- | Create a Writable stream which writes data to the specified file.
-- | Unused options should not be specified. Some options
-- | (e.g. `flags`, `encoding`, and `mode`) should convert their
-- | PureScript values to the corresponding JavaScript ones:
-- | ```
-- | filePath # createWriteStream'
-- | { flags: fileFlagsToNode R
-- | , encoding: encodingToNode UTF8
-- | , mode: permsToInt Perms.all
-- | }
-- | ```
createWriteStream'
:: forall r trash
. Row.Union r trash WriteStreamOptions
=> FilePath
-> { | r }
-> Effect (Writable ())
createWriteStream = createWriteStreamWith defaultWriteStreamOptions
createWriteStream' f opts = runEffectFn2 createWriteStreamOptsImpl f opts

foreign import createWriteStreamOptsImpl :: forall r. EffectFn2 (FilePath) ({ | r }) ((Writable ()))

-- | Create a Writable stream which writes data to the specified file
-- | descriptor, using the default options.
fdCreateWriteStream
:: FileDescriptor
fdCreateWriteStream :: FileDescriptor -> Effect (Writable ())
fdCreateWriteStream f = runEffectFn1 fdCreateWriteStreamImpl f

foreign import fdCreateWriteStreamImpl :: EffectFn1 (FileDescriptor) (Writable ())

-- | Create a Writable stream which writes data to the specified file descriptor.
-- | Unused options should not be specified. Some options
-- | (e.g. `flags`, `encoding`, and `mode`) should convert their
-- | PureScript values to the corresponding JavaScript ones:
-- | ```
-- | filePath # fdCreateWriteStream'
-- | { flags: fileFlagsToNode R
-- | , encoding: encodingToNode UTF8
-- | , mode: permsToInt Perms.all
-- | }
-- | ```
fdCreateWriteStream'
:: forall r trash
. Row.Union r trash WriteStreamOptions
=> FileDescriptor
-> { | r }
-> Effect (Writable ())
fdCreateWriteStream = fdCreateWriteStreamWith defaultWriteStreamOptions
fdCreateWriteStream' f opts = runEffectFn2 fdCreateWriteStreamOptsImpl f opts

type WriteStreamOptions =
{ flags :: FileFlags
, perms :: Perms
}

defaultWriteStreamOptions :: WriteStreamOptions
defaultWriteStreamOptions =
{ flags: W
, perms: readWrite
}

-- | Like `createWriteStream`, but allows you to pass options.
createWriteStreamWith
:: WriteStreamOptions
-> FilePath
-> Effect (Writable ())
createWriteStreamWith opts file = runEffectFn2
createWriteStreamImpl
(notNull file)
{ mode: Perms.permsToInt opts.perms
, flags: fileFlagsToNode opts.flags
}

-- | Like `fdCreateWriteStream`, but allows you to pass options.
fdCreateWriteStreamWith
:: WriteStreamOptions
-> FileDescriptor
-> Effect (Writable ())
fdCreateWriteStreamWith opts fd = runEffectFn2
createWriteStreamImpl
null
{ fd
, mode: Perms.permsToInt opts.perms
, flags: fileFlagsToNode opts.flags
}
foreign import fdCreateWriteStreamOptsImpl :: forall r. EffectFn2 (FileDescriptor) ({ | r }) (Writable ())

-- | Create a Readable stream which reads data to the specified file, using
-- | the default options.
createReadStream
:: FilePath
-> Effect (Readable ())
createReadStream = createReadStreamWith defaultReadStreamOptions
createReadStream :: FilePath -> Effect (Readable ())
createReadStream p = runEffectFn1 createReadStreamImpl p

-- | Create a Readable stream which reads data to the specified file
-- | descriptor, using the default options.
fdCreateReadStream
:: FileDescriptor
-> Effect (Readable ())
fdCreateReadStream = fdCreateReadStreamWith defaultReadStreamOptions
foreign import createReadStreamImpl :: EffectFn1 (FilePath) (Readable ())

type ReadStreamOptions =
{ flags :: FileFlags
, perms :: Perms
( flags :: String
, encoding :: String
, mode :: Int
, autoClose :: Boolean
}

defaultReadStreamOptions :: ReadStreamOptions
defaultReadStreamOptions =
{ flags: R
, perms: readWrite
, autoClose: true
}
, emitClose :: Boolean
, start :: Int
, end :: Int
, highWaterMark :: Int
)

-- | Create a Readable stream which reads data from the specified file.
createReadStreamWith
:: ReadStreamOptions
-> FilePath
-- | Unused options should not be specified. Some options
-- | (e.g. `flags`, `encoding`, and `mode`) should convert their
-- | PureScript values to the corresponding JavaScript ones:
-- | ```
-- | filePath # createReadStream'
-- | { flags: fileFlagsToNode R
-- | , encoding: encodingToNode UTF8
-- | , mode: permsToInt Perms.all
-- | }
-- | ```
createReadStream'
:: forall r trash
. Row.Union r trash ReadStreamOptions
=> FilePath
-> { | r }
-> Effect (Readable ())
createReadStreamWith opts file = runEffectFn2
createReadStreamImpl
(notNull file)
{ mode: Perms.permsToInt opts.perms
, flags: fileFlagsToNode opts.flags
, autoClose: opts.autoClose
}

-- | Create a Readable stream which reads data from the specified file descriptor.
fdCreateReadStreamWith
:: ReadStreamOptions
-> FileDescriptor
createReadStream' path opts = runEffectFn2 createReadStreamOptsImpl path opts

foreign import createReadStreamOptsImpl :: forall r. EffectFn2 (FilePath) ({ | r }) ((Readable ()))

-- | Create a Readable stream which reads data to the specified file
-- | descriptor, using the default options.
fdCreateReadStream :: FileDescriptor -> Effect (Readable ())
fdCreateReadStream f = runEffectFn1 fdCreateReadStreamImpl f

foreign import fdCreateReadStreamImpl :: EffectFn1 (FileDescriptor) (Readable ())

-- | Create a Readable stream which reads data to the specified file descriptor.
-- | Unused options should not be specified. Some options
-- | (e.g. `flags`, `encoding`, and `mode`) should convert their
-- | PureScript values to the corresponding JavaScript ones:
-- | ```
-- | filePath # fdCreateReadStream'
-- | { flags: fileFlagsToNode R
-- | , encoding: encodingToNode UTF8
-- | , mode: permsToInt Perms.all
-- | }
-- | ```
fdCreateReadStream'
:: forall r trash
. Row.Union r trash ReadStreamOptions
=> FileDescriptor
-> { | r }
-> Effect (Readable ())
fdCreateReadStreamWith opts fd = runEffectFn2
createReadStreamImpl
null
{ fd
, mode: Perms.permsToInt opts.perms
, flags: fileFlagsToNode opts.flags
, autoClose: opts.autoClose
}
fdCreateReadStream' f opts = runEffectFn2 fdCreateReadStreamOptsImpl f opts

foreign import fdCreateReadStreamOptsImpl :: forall r. EffectFn2 (FileDescriptor) ({ | r }) ((Readable ()))

0 comments on commit be0a346

Please sign in to comment.