PureScript bindings to node's fs
module.
spago install node-fs
Module documentation is published on Pursuit.
Node.js file I/O for purescript
License: MIT License
PureScript bindings to node's fs
module.
spago install node-fs
Module documentation is published on Pursuit.
Also avoid using Error
from Global
, and change the Sync methods to use the Exception
effect rather than returning an Either Error a
.
When I run Node.FS.Aff.copyFile
, it fails when the file already exists.
That's because of the definition of defaultCopyMode
which uses the fs.constants.COPYFILE_EXCL
flag.
There's two issues:
(1) The default is inconsistent with the underlying node API. fs.copyFile
without a specified copy mode operates as if no flags were applied. It allows overwriting files on copy.
https://nodejs.org/api/fs.html#fscopyfilesrc-dest-mode-callback
Asynchronously copies src to dest. By default, dest is overwritten if it already exists.
(2) There's no way to use this library to get at the node default behavior.
The structure of the Node.FS.Constants
api only allows appending flags not removing them.
There's no export of a "noFlags :: CopyMode".
In order to implement this: purescript-deprecated/purescript-node-fs-aff#7, I think these functions:
foreign import fdOpen :: forall eff.
FilePath -> FileFlags -> Maybe FileMode -> Callback eff FileDescriptor -> Eff (fs :: FS | eff) Unit
foreign import fdRead :: forall eff.
FileDescriptor -> Buffer -> BufferOffset -> BufferLength -> Maybe FilePosition -> Callback eff ByteCount -> Eff (fs :: FS | eff) Unit
foreign import fdNext :: forall eff.
FileDescriptor -> Buffer -> Callback eff ByteCount -> Eff (fs :: FS | eff) Unit
foreign import fdWrite :: forall eff.
FileDescriptor -> Buffer -> BufferOffset -> BufferLength -> Callback eff ByteCount -> Eff (fs :: FS | eff) Unit
foreign import fdAppend :: forall eff.
FileDescriptor -> Buffer -> Callback eff ByteCount -> Eff (fs :: FS | eff) Unit
foreign import fdClose :: forall opts eff.
FileDescriptor -> Callback eff Unit -> Eff (fs :: FS | eff) Unit
need to be added to Node.FS.Async
. Does that sound correct? Do the above types look correct?
Once #53 is merged, we need to unify mkdir'
and mkdirRecursive'
into the mkdir'
. I also think mkdir
and mkdirRecursive
should be unified into mkdir
.
Hi @garyb
Over the last day or so I have pushed a few commits to master, including @timbod7's PR. I think it might be good to publish a new release soon, perhaps once purescript-node/purescript-node-buffer#8 is merged or closed? Anyway I just wanted to give you a heads up in case you want to review anything.
Compatibility with 0.9.1 appears to be blocked until the purescript-datetime
rewrite is complete.
The only other issue I can see is changing import Data.Maybe.Unsafe (fromJust)
to import Data.Maybe (fromJust)
. I'll include that in a PR once purescript-datetime
is ready. ๐
/cc @felixSchl
I think the current situation with purescript-node-fs
and purescript-node-fs-aff
is less than ideal. Some thoughts:
node-fs
, in many ways, is a low-level FFI binding to Node.js' fs
module. However, it has some high-level features, eg Perms
, Encoding
.node-fs-aff
is a higher-level library than node-fs
, but only in one way as far as I can tell (i.e. it uses aff
)type FilePath = String
has no place in a high-level filesystem library. In a high-level filesystem library, we should be using something like purescript-pathy for paths.I propose that we merge both of these into one library (purescript-filesystem?) with separate high-level and low-level parts. The low-level parts should closely mirror node's fs
module, use String
for everything, and return Eff
actions, while the high-level parts should be designed first and foremost in a way that makes sense and is easy to use, should use proper types like Perms
, Encoding
, and Path
, and return Aff
actions.
If there's a need for it, we can break out the low-level parts into a separate library.
It also might be a good time to think about how to deal with other backends. Preferably the high-level library would be able to support backends other than node.js. (Perhaps free monads would be a good fit for enabling this?)
Hi,
I was trying to pass a range to createReadStreamWith
, however, I couldn't find the start
and end
options in the ReadStreamOptions
. Will you accept a PR for this?
Reference:
https://nodejs.org/api/fs.html#fs_fs_createreadstream_path_options
For example, in Node.FS.Stream
, createReadStream
has the type:
createReadStream :: FilePath -> Effect (Readable ())
But the Node API can raise an exception, for instance, if the file doesn't exists. Likely the type should be:
createReadStream :: FilePath -> Effect (Either Error (Readable ()))
Is there any other solution that would be preferred here over catching the exception and returning an Either
?
Node's fs
module's createReadStream
and createWriteStream
are missing.
How would they fit into the purescript way of doing things? Or more generally,
I guess - how would the whole EventEmitter
concept fit into purescript. Essentially,
we need to wrap up events somehow to tap into what's happening to the stream.
I was trying to run some code that used this library through purescript-backend-optimizer when I ran into a runtime error.
For details on the runtime error and what caused it, you can see the discussion in aristanetworks/purescript-backend-optimizer#29.
However, the TLDR of that discussion is that this library should be changed to use EffectFn
instead of constructing effects via the unsafe mkEffect
util currently defined in Node.FS.Internal
(my assumption is that mkEffect
predates the existance of EffectFn
in the ecosystem).
After psc 0.7 is released.
What is the node compatibility for this & how is it enforced?
It is not large API surface: watch, watchFile, unwatchFile, FSWatcher, StatWatcher
.
What do you think, should it go to a separate module Node.FS.Watch
?
IMO, these tend to decrease the readability of the underlying API.
I am not sure whether this is a node-fs or spago problem, therefor i'm cross posting. Please close when this issue is not relevant for this repo.
Reproduce & error:
mkdir nodefssync
cd nodefssync
spago init
spago install node-fs node-buffer
now paste source code into Main.purs
module Main where
import Prelude
import Effect (Effect)
import Effect.Console (log)
import Node.FS.Sync
import Node.Encoding
main :: Effect Unit
main = do
_ <- readTextFile UTF8 "blabla"
log "๐"
spago bundle-app --platform=node
node index.js
ยป node index.js
(node:654122) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
(Use `node --trace-warnings ...` to show where the warning was created)
/home/flip111/nodefssync/index.js:109
import {
^^^^^^
SyntaxError: Cannot use import statement outside a module
at Object.compileFunction (node:vm:360:18)
at wrapSafe (node:internal/modules/cjs/loader:1048:15)
at Module._compile (node:internal/modules/cjs/loader:1083:27)
at Module._extensions..js (node:internal/modules/cjs/loader:1173:10)
at Module.load (node:internal/modules/cjs/loader:997:32)
at Module._load (node:internal/modules/cjs/loader:838:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
at node:internal/main/run_main_module:18:47
Node.js v18.8.0
Related file: https://github.com/purescript-node/purescript-node-fs/blob/c6c52c510b55940bbcf475fa25913bc7eb415acb/src/Node/FS/Sync.js
Spago post: purescript/spago#916
Because mkdir
uses a file mode of 777 decimal (as opposed to 777 octal), it will create directories that the owner is not allowed to write into (amongst other things). The created directory actually ends up having permissions 1411, since 777 in decimal is 1411 in octal.
I think the fix should be simply to get #11 merged. Is there anything I can do to help with this?
This is a failing example that's close to what I was using.
I'm not sure if the problem is with stat
or catchException
, but essentially this is the problem:
You can use catchException
to discharge an EXCEPTION
assumption from your program. Great! If we use enough catchException
s, the compiler tells us (assuming everything was well-typed) that our program won't have any uncaught exceptions at runtime.
Except it does. catchException
doesn't ... catch the exception ... when using stat
on a path that doesn't exist.
This threw me for a loop since I was assuming that uncaught runtime exceptions wouldn't happen.
To prevent issues like #27 from occurring again.
I'd like to understand how the FFI calls work in this library. From a quick look, it seems like calling something like return $ runFn4 ...
as the implementation of something of type Eff
would evaluate the right hand side too eagerly.
Since doing async using callbacks is the de facto in node land, I was wondering if it was time to extract the type Callback
into it's own module, slap a monad instance onto it or integrate it easily with purescript-aff or contT? It would be great to get something like the aff monad just "out of the box" without some guff like this in order to write "nice looking" async code.
Each of these methods
purescript-node-fs/src/Node/FS/Stats.purs
Lines 35 to 40 in a9da8b9
Stats -> Boolean
function so they seem redundant, and using the isDirectory :: Fn0 Boolean
directly resulted in this issue aristanetworks/purescript-backend-optimizer#35 because this
context wasn't preserved after compilation.FilePosition is a newtyped Int, so there is no random access > 2G with the purscript API.
Node.js can do this just fine - node.js numbers are safe to use as integers up to 53 bits.
Making FilePosition a Number would work but I don't like seeing offsets with a decimal point. I used Data.Int53 in my workaround module.
It could be argued that buffer lengths, offsets and bytecounts should be Int53s too. But these are all breaking changes and I can live with doing IO in chunks < 2GB.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.