Skip to main content

workflow_node/
fs.rs

1use crate::require;
2use js_sys::Object;
3use lazy_static::lazy_static;
4use wasm_bindgen::prelude::*;
5
6lazy_static! {
7    static ref FS: Fs = require("fs").unchecked_into();
8    static ref FSP: FsPromises = require("fs/promises").unchecked_into();
9}
10
11#[wasm_bindgen]
12extern "C" {
13
14    /// Binding to the Node.js `fs/promises` module, exposing the promise-based
15    /// (asynchronous) file system API.
16    #[wasm_bindgen(extends = Object)]
17    #[derive(Clone)]
18    pub type FsPromises;
19
20    #[wasm_bindgen(catch, js_name = readdir, method)]
21    async fn fs_readdir(this: &FsPromises, path: &str) -> std::result::Result<JsValue, JsValue>;
22
23    #[wasm_bindgen(catch, js_name = readdir, method)]
24    async fn fs_readdir_with_options(
25        this: &FsPromises,
26        path: &str,
27        options: Object,
28    ) -> std::result::Result<JsValue, JsValue>;
29
30    /// Binding to the Node.js `fs` module, exposing the synchronous
31    /// (`*Sync`) file system API.
32    #[wasm_bindgen(extends = Object)]
33    #[derive(Clone)]
34    pub type Fs;
35
36    /// Reads the contents of a directory, passing the resulting entries to the
37    /// supplied JavaScript callback (`fs.readdirSync`).
38    #[wasm_bindgen(js_name = readdirSync, method)]
39    pub fn fs_readdir_sync(this: &Fs, path: &str, callback: js_sys::Function);
40
41    #[wasm_bindgen(catch, js_name = existsSync, method)]
42    fn fs_exists_sync(this: &Fs, path: &str) -> std::result::Result<bool, JsValue>;
43
44    #[wasm_bindgen(catch, js_name = writeFileSync, method)]
45    fn fs_write_file_sync(
46        this: &Fs,
47        path: &str,
48        data: JsValue,
49        options: Object,
50    ) -> std::result::Result<(), JsValue>;
51
52    #[wasm_bindgen(catch, js_name = readFileSync, method)]
53    fn fs_read_file_sync(
54        this: &Fs,
55        path: &str,
56        options: Object,
57    ) -> std::result::Result<JsValue, JsValue>;
58
59    #[wasm_bindgen(catch, js_name = mkdirSync, method)]
60    fn fs_mkdir_sync(this: &Fs, path: &str, options: Object) -> std::result::Result<(), JsValue>;
61
62    #[wasm_bindgen(catch, js_name = renameSync, method)]
63    fn fs_rename_sync(this: &Fs, from: &str, to: &str) -> std::result::Result<(), JsValue>;
64
65    #[wasm_bindgen(catch, js_name = unlinkSync, method)]
66    fn fs_unlink_sync(this: &Fs, path: &str) -> std::result::Result<(), JsValue>;
67
68    #[wasm_bindgen(catch, js_name = statSync, method)]
69    fn fs_stat_sync(this: &Fs, path: &str) -> std::result::Result<JsValue, JsValue>;
70}
71
72unsafe impl Send for Fs {}
73unsafe impl Sync for Fs {}
74unsafe impl Send for FsPromises {}
75unsafe impl Sync for FsPromises {}
76
77/// Asynchronously reads the contents of the directory at `path`, returning an
78/// array of the names of the entries it contains.
79#[inline(always)]
80pub async fn readdir(path: &str) -> std::result::Result<JsValue, JsValue> {
81    FSP.fs_readdir(path).await
82}
83
84/// Asynchronously reads the contents of the directory at `path`, applying the
85/// given options (e.g. `withFileTypes`, `recursive`, `encoding`).
86#[inline(always)]
87pub async fn readdir_with_options(
88    path: &str,
89    options: Object,
90) -> std::result::Result<JsValue, JsValue> {
91    FSP.fs_readdir_with_options(path, options).await
92}
93
94/// Reads the contents of the directory at `path`, delivering the resulting
95/// entries to the supplied JavaScript `callback`.
96#[inline(always)]
97pub fn readdir_sync(path: &str, callback: js_sys::Function) {
98    FS.fs_readdir_sync(path, callback)
99}
100
101/// Synchronously returns `true` if a file system entry exists at `path`.
102#[inline(always)]
103pub fn exists_sync(path: &str) -> std::result::Result<bool, JsValue> {
104    FS.fs_exists_sync(path)
105}
106
107/// Synchronously writes `data` to the file at `path`, creating or replacing it
108/// according to the supplied options (e.g. `encoding`, `mode`, `flag`).
109#[inline(always)]
110pub fn write_file_sync(
111    path: &str,
112    data: JsValue,
113    options: Object,
114) -> std::result::Result<(), JsValue> {
115    FS.fs_write_file_sync(path, data, options)
116}
117
118/// Synchronously reads and returns the contents of the file at `path`. The
119/// returned value is a `Buffer`, or a string when an `encoding` is given in
120/// `options`.
121#[inline(always)]
122pub fn read_file_sync(path: &str, options: Object) -> std::result::Result<JsValue, JsValue> {
123    FS.fs_read_file_sync(path, options)
124}
125
126/// Synchronously creates the directory at `path`, honouring the supplied
127/// options (e.g. `recursive`, `mode`).
128#[inline(always)]
129pub fn mkdir_sync(path: &str, options: Object) -> std::result::Result<(), JsValue> {
130    FS.fs_mkdir_sync(path, options)
131}
132
133/// Synchronously removes the file (or symbolic link) at `path`.
134#[inline(always)]
135pub fn unlink_sync(path: &str) -> std::result::Result<(), JsValue> {
136    FS.fs_unlink_sync(path)
137}
138
139/// Synchronously renames (moves) the file or directory from `from` to `to`.
140#[inline(always)]
141pub fn rename_sync(from: &str, to: &str) -> std::result::Result<(), JsValue> {
142    FS.fs_rename_sync(from, to)
143}
144
145/// Synchronously retrieves the [`fs.Stats`](https://nodejs.org/api/fs.html#class-fsstats)
146/// object describing the file system entry at `path`.
147#[inline(always)]
148pub fn stat_sync(path: &str) -> std::result::Result<JsValue, JsValue> {
149    FS.fs_stat_sync(path)
150}