Giter VIP home page Giter VIP logo

purescript-node-fs's Introduction

purescript-node-fs

Latest release Build status Pursuit

PureScript bindings to node's fs module.

Installation

spago install node-fs

Documentation

Module documentation is published on Pursuit.

purescript-node-fs's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

purescript-node-fs's Issues

Impossible to overwrite files with `copyFile`

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".

asynchronous fdOpen, fdRead, etc

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?

Unify `mkdir` and `mkdirRecursive`

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.

0.9.1 Compatibility

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. ๐Ÿ‘

Reorganising node-fs and node-fs-aff

/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)
  • This is a weird mixture of high-level and low-level things which creates unnecessary work for us.
  • We should have one place for high-level filesystem things, and one place for low-level filesystem things.
  • 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?)

Errors in some APIs can't be handled

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?

Read- and write streams

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.

Use `EffectFn` instead of unsafe `mkEffect` util

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).

Node version?

What is the node compatibility for this & how is it enforced?

Implement Watch Api bindings

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?

node-fs triggers build error with spago/esbuild

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

`mkdir` uses mode 1411, not 777

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?

`stat` can result in unexpected runtime failures

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 catchExceptions, 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.

Functions too eager?

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.

Remove redundant/impure `StatsObj` `Fn0` methods

Each of these methods

, isFile :: Fn0 Boolean
, isDirectory :: Fn0 Boolean
, isBlockDevice :: Fn0 Boolean
, isCharacterDevice :: Fn0 Boolean
, isFIFO :: Fn0 Boolean
, isSocket :: Fn0 Boolean
has a corresponding standalone 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 restricts random access to 2GB

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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.