Skip to content

Commit cc2c5a8

Browse files
Add FFI for access, copyFile, mkdtemp
1 parent 200e2c3 commit cc2c5a8

File tree

6 files changed

+142
-14
lines changed

6 files changed

+142
-14
lines changed

src/Node/FS/Async.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
export {
2+
access as accessImpl,
3+
copyFile as copyFileImpl,
4+
mkdtemp as mkdtempImpl,
25
rename as renameImpl,
36
truncate as truncateImpl,
47
chown as chownImpl,
@@ -22,7 +25,7 @@ export {
2225
read as readImpl,
2326
write as writeImpl,
2427
close as closeImpl
25-
} from "fs";
28+
} from "node:fs";
2629

2730
export function handleCallbackImpl(left, right, f) {
2831
return function (err, value) {

src/Node/FS/Async.purs

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
module Node.FS.Async
22
( Callback(..)
3+
, access
4+
, access'
5+
, copyFile
6+
, copyFile'
7+
, mkdtemp
8+
, mkdtemp'
39
, rename
410
, truncate
511
, chown
@@ -42,13 +48,15 @@ import Data.Either (Either(..))
4248
import Data.Function.Uncurried (Fn2, Fn6, Fn4, Fn3, runFn2, runFn6, runFn4, runFn3)
4349
import Data.Int (round)
4450
import Data.Maybe (Maybe(..))
45-
import Data.Nullable (Nullable, toNullable)
51+
import Data.Nullable (Nullable, toMaybe, toNullable)
4652
import Data.Time.Duration (Milliseconds(..))
4753
import Effect (Effect)
4854
import Effect.Exception (Error)
55+
import Effect.Uncurried (EffectFn1, EffectFn3, EffectFn4, mkEffectFn1, runEffectFn3, runEffectFn4)
4956
import Node.Buffer (Buffer, size)
50-
import Node.Encoding (Encoding)
57+
import Node.Encoding (Encoding(..), encodingToNode)
5158
import Node.FS (FileDescriptor, ByteCount, FilePosition, BufferLength, BufferOffset, FileMode, FileFlags, SymlinkType, fileFlagsToNode, symlinkTypeToNode)
59+
import Node.FS.Constants (AccessMode, CopyMode, defaultAccessMode, defaultCopyMode)
5260
import Node.FS.Internal (mkEffect)
5361
import Node.FS.Perms (Perms, permsToString, all, mkPerms)
5462
import Node.FS.Stats (StatsObj, Stats(..))
@@ -69,6 +77,31 @@ handleCallback cb = runFn3 handleCallbackImpl Left Right cb
6977
-- | Type synonym for callback functions.
7078
type Callback a = Either Error a -> Effect Unit
7179

80+
access :: String -> (Maybe Error -> Effect Unit) -> Effect Unit
81+
access path = access' path defaultAccessMode
82+
83+
access' :: String -> AccessMode -> (Maybe Error -> Effect Unit) -> Effect Unit
84+
access' path mode cb = runEffectFn3 accessImpl path mode $ mkEffectFn1 \err -> do
85+
cb $ toMaybe err
86+
87+
foreign import accessImpl :: EffectFn3 (String) (AccessMode) (EffectFn1 (Nullable Error) Unit) Unit
88+
89+
copyFile :: String -> String -> Callback Unit -> Effect Unit
90+
copyFile src dest = copyFile' src dest defaultCopyMode
91+
92+
copyFile' :: String -> String -> CopyMode -> Callback Unit -> Effect Unit
93+
copyFile' src dest mode cb = runEffectFn4 copyFileImpl src dest mode (handleCallback cb)
94+
95+
foreign import copyFileImpl :: EffectFn4 (String) (String) (CopyMode) (JSCallback Unit) (Unit)
96+
97+
mkdtemp :: String -> Callback String -> Effect Unit
98+
mkdtemp prefix = mkdtemp' prefix UTF8
99+
100+
mkdtemp' :: String -> Encoding -> Callback String -> Effect Unit
101+
mkdtemp' prefix encoding cb = runEffectFn3 mkdtempImpl prefix (encodingToNode encoding) (handleCallback cb)
102+
103+
foreign import mkdtempImpl :: EffectFn3 (String) (String) (JSCallback String) (Unit)
104+
72105
foreign import renameImpl :: Fn3 FilePath FilePath (JSCallback Unit) Unit
73106
foreign import truncateImpl :: Fn3 FilePath Int (JSCallback Unit) Unit
74107
foreign import chownImpl :: Fn4 FilePath Int Int (JSCallback Unit) Unit

src/Node/FS/Constants.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { constants } from "node:fs";
2+
3+
export const f_OK = constants.F_OK;
4+
5+
export const r_OK = constants.R_OK;
6+
7+
export const w_OK = constants.W_OK;
8+
9+
export const x_OK = constants.X_OK;
10+
11+
export const copyFile_EXCL = constants.COPYFILE_EXCL;
12+
13+
export const copyFile_FICLONE = constants.COPYFILE_FICLONE;
14+
15+
export const copyFile_FICLONE_FORCE = constants.COPYFILE_FICLONE_FORCE;
16+
17+
export const appendCopyMode = (l, r) => l | r;

src/Node/FS/Constants.purs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
module Node.FS.Constants where
2+
3+
import Prelude
4+
5+
import Data.Function.Uncurried (Fn2, runFn2)
6+
7+
-- | the mode parameter passed to `access` and `accessSync`.
8+
foreign import data AccessMode :: Type
9+
10+
-- | the file is visible to the calling process.
11+
-- | This is useful for determining if a file exists, but says nothing about rwx permissions. Default if no mode is specified.
12+
foreign import f_OK :: AccessMode
13+
14+
-- | the file can be read by the calling process.
15+
foreign import r_OK :: AccessMode
16+
17+
-- | the file can be written by the calling process.
18+
foreign import w_OK :: AccessMode
19+
20+
-- | the file can be executed by the calling process. This has no effect on Windows (will behave like fs.constants.F_OK).
21+
foreign import x_OK :: AccessMode
22+
23+
defaultAccessMode = f_OK :: AccessMode
24+
25+
foreign import data CopyMode :: Type
26+
27+
foreign import copyFile_EXCL :: CopyMode
28+
foreign import copyFile_FICLONE :: CopyMode
29+
foreign import copyFile_FICLONE_FORCE :: CopyMode
30+
31+
defaultCopyMode = copyFile_EXCL :: CopyMode
32+
33+
foreign import appendCopyMode :: Fn2 CopyMode CopyMode CopyMode
34+
35+
instance Semigroup CopyMode where
36+
append l r = runFn2 appendCopyMode l r

src/Node/FS/Sync.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
export {
1+
export {
2+
accessSync as accessImpl,
3+
copyFileSync as copyFileImpl,
4+
mkdtempSync as mkdtempImpl,
25
renameSync as renameSyncImpl,
36
truncateSync as truncateSyncImpl,
47
chownSync as chownSyncImpl,
@@ -24,4 +27,4 @@ export {
2427
writeSync as writeSyncImpl,
2528
fsyncSync as fsyncSyncImpl,
2629
closeSync as closeSyncImpl
27-
} from "fs";
30+
} from "node:fs";

src/Node/FS/Sync.purs

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
module Node.FS.Sync
2-
( rename
2+
( access
3+
, access'
4+
, copyFile
5+
, copyFile'
6+
, mkdtemp
7+
, mkdtemp'
8+
, rename
39
, truncate
410
, chown
511
, chmod
@@ -36,21 +42,51 @@ module Node.FS.Sync
3642
) where
3743

3844
import Prelude
39-
import Effect (Effect)
45+
4046
import Data.DateTime (DateTime)
41-
import Data.Time.Duration (Milliseconds(..))
4247
import Data.DateTime.Instant (fromDateTime, unInstant)
48+
import Data.Either (blush)
4349
import Data.Function.Uncurried (Fn1, Fn5, Fn3, Fn2, runFn1, runFn5, runFn3, runFn2)
44-
import Data.Nullable (Nullable(), toNullable)
4550
import Data.Int (round)
4651
import Data.Maybe (Maybe(..))
47-
import Node.Buffer (Buffer(), size)
48-
import Node.Encoding (Encoding)
52+
import Data.Nullable (Nullable, toNullable)
53+
import Data.Time.Duration (Milliseconds(..))
54+
import Effect (Effect)
55+
import Effect.Exception (Error, try)
56+
import Effect.Uncurried (EffectFn2, EffectFn3, runEffectFn2, runEffectFn3)
57+
import Node.Buffer (Buffer, size)
58+
import Node.Encoding (Encoding(..), encodingToNode)
4959
import Node.FS (FileDescriptor, ByteCount, FilePosition, BufferLength, BufferOffset, FileMode, FileFlags, SymlinkType, fileFlagsToNode, symlinkTypeToNode)
50-
import Node.FS.Stats (StatsObj, Stats(..))
51-
import Node.Path (FilePath())
52-
import Node.FS.Perms (Perms, permsToString, all, mkPerms)
60+
import Node.FS.Constants (AccessMode, defaultAccessMode, CopyMode, defaultCopyMode)
5361
import Node.FS.Internal (mkEffect)
62+
import Node.FS.Perms (Perms, permsToString, all, mkPerms)
63+
import Node.FS.Stats (StatsObj, Stats(..))
64+
import Node.Path (FilePath)
65+
66+
access :: String -> Effect (Maybe Error)
67+
access = flip access' defaultAccessMode
68+
69+
access' :: String -> AccessMode -> Effect (Maybe Error)
70+
access' path mode = do
71+
map blush $ try $ runEffectFn2 accessImpl path mode
72+
73+
foreign import accessImpl :: EffectFn2 (String) (AccessMode) ((Maybe Error))
74+
75+
copyFile :: String -> String -> Effect Unit
76+
copyFile src dest = runEffectFn3 copyFileImpl src dest defaultCopyMode
77+
78+
copyFile' :: String -> String -> CopyMode -> Effect Unit
79+
copyFile' src dest mode = runEffectFn3 copyFileImpl src dest mode
80+
81+
foreign import copyFileImpl :: EffectFn3 (String) (String) (CopyMode) (Unit)
82+
83+
mkdtemp :: String -> Effect String
84+
mkdtemp prefix = mkdtemp' prefix UTF8
85+
86+
mkdtemp' :: String -> Encoding -> Effect String
87+
mkdtemp' prefix encoding = runEffectFn2 mkdtempImpl prefix (encodingToNode encoding)
88+
89+
foreign import mkdtempImpl :: EffectFn2 (String) (String) (String)
5490

5591
foreign import renameSyncImpl :: Fn2 FilePath FilePath Unit
5692
foreign import truncateSyncImpl :: Fn2 FilePath Int Unit

0 commit comments

Comments
 (0)