stdlib-js / google-summer-of-code

Google Summer of Code resources.
https://github.com/stdlib-js/stdlib
26 stars 7 forks source link

[RFC]: Achieve feature parity with builtin Node.js fs module #73

Closed HRIDYANSHU054 closed 5 months ago

HRIDYANSHU054 commented 6 months ago

Full name

Hridyanshu

University status

Yes

University name

Vivekananda Institute of Professional Studies Technical Campus

University program

BTech in AI & ML

Expected graduation

June 2025

Short biography

I am a pre final year student at VIPS TC School of Engineering and Technology, pursuing BTech in Ai & ML. Currently my skillset involves web development and machine learning. I started my coding journey during my first year in college in which I learned C and C++. My focus shifted towards web development because I wanted to create applications that were pleasant to the eyes in addition to being functional and not only limited to my console. I am also very excited by the potential machine learning holds in solving real world problems. I have been learning ML mainly through my college courses and online resources. Furthermore, I have done certain projects in ML that have contributed in piquing my interest. I like to code simply because it makes our lives much easier that is another reason I am a ML enthusiast. I believe in collaborative learning and contribute to open source projects whenever possible.

Timezone

India Standard Time ( UTC+5:30 )

Contact details

Hridyanshu054, 05417711621_ml@vips.edu, himank7794@gmail.com

Platform

Windows

Editor

VSCode mainly because its very easy to learn and start debugging with. Has a very clean and customizable interface, and it works great for my web development needs. I have also worked with Jupyter notebook and Pycharm for ML tasks.

Programming experience

These are some of my projects –

More on my portfolio https://jgjportfolio.vercel.app/

JavaScript experience

My JavaScript experience is well highlighted in the above projects. Project involving js are

My favorite features about Javascript are

My least favorite things about JavaScript

Node.js experience

I got introduced to node js from a book my friend recommended “Node Js Novice to Ninja”. I am using Node js mostly as a build tool, almost all my projects have some kind of node js involvement. I'm familiar with popular Node.js modules and frameworks like Express.js, furthermore I'm always eager to learn new ones relevant to the project demands. Currently I am also building a blog app with mongodb as a backend on Node js to integrate with my portfolio website.

C/Fortran experience

I was introduced to C programming in my first year of college. Since, then I have been using it mostly for my college coursework. Mostly I am familiar with C++, which I have used for both algorithmic problem solving and development. Also, I have worked with Arduino Programming language which is quite similar to C++ for my hardware projects.

Interest in stdlib

Something that excites me about contributing to stdlib is that it is aiming to provide a comprehensive library for JavaScript , something that is already there in other languages and which Javascript lacks , and something that I feel could really contribute to developers community. another thing about stdlib is that the way they truly implemented SOLID principles in their VAST codebase which makes everything look maintainable. To be among such batch of developers and to learn from them will prove a strong foundation in my career.

Version control

Yes

Contributions to stdlib

Open PR feat: add fs/append-file #1967 https://github.com/stdlib-js/stdlib/pull/1967 aligned with this project, I have aimed at bringing fs useful append-file functionality to stdlib and also this was an attempt o get familiar with the codebase by doing some wiring rewiring.

Async implementation


var fpath = join(__dirname, "examples", "fixtures", "file.txt");

appendFile(fpath, "beep boop\n", onAppend);

function onAppend(error) {
if (error) {
throw error;
}
}

Synchronous implementation

var appendFile = require( '@stdlib/fs/append-file' );

// Explicitly handle the error...
try{
appendFile.sync( '/path/to/file.txt', 'beep boop\n' );
} catch(err) {
throw err
}

Goals

The goal of this project is to provide feature parity with Node.js fs package, stdlib currently supports a limited number of fs functionalities. I would be contributing to add some more.

This project will also implement an abstraction layer so that these APIs will not become Node versions dependent and would instead use other workaround if user’s node versions requirement for a certain feature is not met.

Deliverables

After going through Node JS File System documentation and the existing fs functionalities within stdlib. I have decided on implementing the following APIs

access(path[, mode], clbk) ;

/**
* Asynchronously testing user's permissions for the file or directory specified by path
*
* @param {string|Buffer} path - file path
* @param {number} mode - The desired access permissions to test. Defaults to checking for existence only.
* @param {function} clbk - callback to invoke after the test.
*/

chmod(path, mode, clbk) ;

/**
* Asynchronously changes the permissions of a file or directory.
*
* @param {string|Buffer} path - file path
* @param {number} mode - The new permissions for the path, specified as an octal integer or a string representing permission bits.
* @param {function} clbk - callback to invoke after permissions are changed.
*/

copyFile(src, dest[, mode], clbk) ;

/**
 * Asynchronously copies src to dest.By default, dest is overwritten if it already exists.
 *
 * @param {(string|Buffer)} src - source filename to copy
 * @param {(string|Buffer)} dest - destination filename of the copy operation
 * @param {number} [mode] - modifiers for copy operation.
 * @param {Function} clbk - callback to invoke after copying src to dest
*/

chown(path, uid, gid, clbk) ;

/**
* Asynchronously changes the owner of a file or directory.
*
* @param {string|Buffer} path - path to the file or directory whose ownership has to be changed.
* @param {number} uid - user ID of the new owner.
* @param {number} gid - group ID of the new owner.
* @param {function} clbk - callback to invoke after ownership has changed.
*/

chownLink(path, uid, gid, clbk) ;

/**
* Asynchronously changes the owner of a file or symbolic link, without dereferencing it.
*
* @param {string|Buffer} path - path to the file or symbolic link.
* @param {number} uid - user ID of the new owner.
* @param {number} gid - group ID of the new owner.
* @param {function} clbk - callback to invoke after ownership has changed.
*/

createReadStream(path[, options]) ;

/**
* Asynchronously creates a readable stream for reading data from a file.
*
* @param {string|Buffer} path - path to the file to read from.
* @param {string|Object} [options] - an optional options object to configure the reading behavior.
* @property {string} [options.flags] the file open flags.Default ‘r’.
* @property {string} [options.encoding] - the text encoding to use when reading the file as text.
* @property {number|FileHandle} [options.fd] an existing file descriptor for the file.
* @property {number} [options.mode] - the mode in which to open the file. Default 0o666.
* @property {boolean} [options.autoClose] - whether to automatically close the file when the stream ends. Default true.
* @property {boolean} [options.emitClose] - whether to emit a 'close’ event when the stream ends. Default true.
* @property {number} [options.start] - the byte offset at which to start reading the file. Deafult 0.
* @property {Object|null} [options.fs] - a custom FS implementation to use for the stream.
* @property {number} [options.highWaterMark] - the maximum number of bytes to buffer before callbacks are called.
* @property {boolean} [options.flush] whether to flush the underlying file descriptor before closing. Defaults false.
* @return {fs.ReadStream} a readable stream for reading data from the file.
*/

createWriteStream(path[, options]) ;

/**
* Asynchronously creates a writable stream for writing data to a file.
*
* @param {string|Buffer} path - path to the file to write to.
* @param {string|Object} [options] - an optional options object to configure the writing behavior.
* @property {string} [options.flags] the file open flags.Default ‘w’.
* @property {string} [options.encoding] - the encoding to use when writing text data.Default ‘utf8’.
* @property {number|FileHandle} [options.fd] an existing file descriptor for the file.
* @property {number} [options.mode] - the mode in which to open the file. Default 0o666.
* @property {boolean} [options.autoClose] - whether to automatically close the file when the stream ends. Default true.
* @property {boolean} [options.emitClose] - whether to emit a 'close’ event when the stream ends. Default true.
* @property {number} [options.start] - the byte offset at which to start writing to the file. Deafult 0.
* @property {Object|null} [options.fs] - a custom FS implementation to use for the stream.
* @property {number} [options.highWaterMark] - the maximum number of bytes to buffer before callbacks are called.
* @property {boolean} [options.flush] whether to flush the underlying file descriptor before closing. Defaults false.
* @return {fs.WriteStream} a writable stream for writing data to the file.
*/

link(existingPath, newPath, clbk) ;

/**
* Asynchronously creates a hard link to a file.
*
* @param {string|Buffer} existingPath - path to the existing file.
* @param {string|Buffer} newPath – path where the hard link will be created.
* @param {function} clbk - callback to invoke after the hard link has been created.
*/

mkdir(path[, options], clbk) ;

/**
* Asynchronously creates a directory
*
* @param {string|Buffer} path - path to the directory to be created.
* @param {Object|number} [options] - an optional options object or a mode to be applied to the directory.
* @property {boolean} [options.recursive] whether to create parent directories recursively if they don't exist. Defaults to false.
 * @property {string|number} [options.mode] permissions for the created directory (octal integer or permission bit string). Defaults to 0o777 (full permissions).
* @param {function} clbk - callback to invoke after the directory has been created.
*/

mkdtemp(prefix[, options], clbk) ;

/**
* Asynchronously creates a unique temporary directory.
*
* @param {string|Buffer} prefix - prefix which will be used while generating the temporary directory name.
* @param {string|Object} [options] - an optional options object or the character encoding for the returned directory path.
* @property {string} [options.encoding] character encoding for the returned directory path. Defaults to 'utf8'.
* @param {function} clbk - callback to invoke after the temporary directory has been created.
*/

opendir(path[, options], clbk) ;

/**
* Asynchronously opens a directory for reading entries .
*
* @param {string|Buffer} path – path to directory.
* @param {Object} [options] - an optional options object to configure the directory reading behavior.
* @property {string|null} [options.encoding] character encoding for reading directory entries Defaults to 'utf8'. Set to null for raw Buffer entries.
* @property {number} [options.bufferSize] number of directory entries buffered internally when reading. Higher values improve performance but use more memory.
* @property {boolean} [options.recursive] Whether to follow symbolic links encountered while reading entries recursively. Defaults to false.
* @param {function} clbk - callback to invoke after opening the directory.
*/

rmdir(path[, options], clbk) ;

/**
* Asynchronously removes an empty directory.
*
* @param {string|Buffer} path -path to the directory to be removed. The directory must be empty.
* @param {Object} [options] - an optional options object to configure the directory removal behavior.
* @property {number} [options.maxRetries] number of times to retry the removal operation if certain errors occur. Default 0.
* @property {boolean} [options.retryDelay] delay in milliseconds between retries. Defaults to 100.
* @param {function} clbk - callback to invoke after the removal attempt.
*/

rm(path[, options], clbk) ;

/**
* Asynchronously removes a file or directory.
*
* @param {string|Buffer} path -path to the file or directory to be removed.
* @param {Object} [options] - an optional options object to configure the removal behavior.
* @property {boolean} [options.force] whether to ignore errors if the path doesn't exist. Default false.
* @property {number} [options.maxRetries] number of times to retry the removal operation if certain errors occur. Default 0.
* @property {boolean} [options.recursive] whether to recursively remove a directory and its content. Default false.
* @property {boolean} [options.retryDelay] delay in milliseconds between retries. Default 100.
* @param {function} clbk - callback to invoke after the removal attempt.
*/

stat(path[, options], clbk) ;

/**
* Asynchronously gets the file system stats for a file or directory.
*
* @param {string|Buffer} path -path to the file or directory whose stats are to be retrieved.
* @param {Object} [options] - an optional options object to controel stat behavior.
* @property {boolean} [options.bigInt] whether to use BigInt objects for numeric statistics properties. Default false.
* @param {function} clbk - callback to invoke after stats retrieval.
*/

statLink(path[, options], clbk) ;

/**
* Asynchronously gets the stats for a file or symbolic link, without following the link
*
* @param {string|Buffer} path -path to the file or directory whose stats are to be retrieved.
* @param {Object} [options] - an optional options object to controel stat behavior.
* @property {boolean} [options.bigInt] whether to use BigInt objects for numeric statistics properties. Default false.
* @param {function} clbk - callback to invoke after stats retrieval.
*/

statFs(path[, options], clbk) ;

/**
* Asynchronously gets file system statistics for the file system that the path refers to.
*
* @param {string|Buffer} path -path to the file or directory (used to determine the file system).
* @param {Object} [options] - an optional options object to control stat behavior.
* @property {boolean} [options.bigInt] whether to use BigInt objects for numeric stat properties. Default false.
* @param {function} clbk - callback to invoke after stats retrieval.
*/

symlink(target, path[, type], clbk) ;

/**
* Asynchronously creates a symbolic link to a file or directory.
*
* @param {string|Buffer} target -path to the file or directory that the symbolic link will point to.
* @param {string|Buffer} path -path where the symbolic link will be created.
* @param {string|null} [type] - an optional string specifying the type of symlink to create.
*        - 'file' (default for non-Windows platforms) or 'dir' can be specified. Ignored on Windows.
* @param {function} clbk - callback to invoke after the symlink has been created.
*/

truncate(path[, len], clbk) ;

/**
* Asynchronously changes the size of the file at a given path.
*
* @param {string|Buffer} path -path to the file to be truncated.
* @param {number} [len] – the new length of the file. Default 0.
* @param {function} clbk - callback to invoke after truncating the file.
*/

unwatchFile(filename[, listener]) ;

/**
* Asynchronously stops watching for changes on a file
*
* @param {string|Buffer} filename - path to the file.
* @param {function} listener – an optional listener function previously attached using `watchFile()`.
*/

utimes(path, atime, mtime, clbk) ;

/**
* Asynchronously change the access and modification timestamps of the object referenced by path.
*
* @param {string|Buffer} path - path to the file.
* @param {number|string|Date} atime - the new access timestamp. Can be a number representing milliseconds since epoch, a string in a recognized format, or a Date object.
* @param {number|string|Date} mtime - the new modification timestamp. Can be a number representing milliseconds since epoch, a string in a recognized format, or a Date object.
* @param {function} clbk – callback to invoke after updating the timestamps.
*/

utimesLink(path, atime, mtime, clbk) ;

/**
* Asynchronously change the access and modification timestamps of the object referenced by path. directly modifying the timestamps of the link itself if the path refers to a symbolic link.
*
* @param {string|Buffer} path - path to the file.
* @param {number|string|Date} atime - the new access timestamp. Can be a number representing milliseconds since epoch, a string in a recognized format, or a Date object.
* @param {number|string|Date} mtime - the new modification timestamp. Can be a number representing milliseconds since epoch, a string in a recognized format, or a Date object.
* @param {function} clbk – callback to invoke after updating the timestamps.
*/

watchFile(filename[, options], listener) ;

/**
* Asynchronously watches for changes on a file
*
* @param {string|Buffer} filename - path to the file.
* @param {Object} [options] - an optional options object to control watching behavior.
* @property {boolean} [options.bigInt] whether to use BigInt objects for numeric stat properties. Default false.
* @property {boolean} [options.persistent] whether the process should continue to run as long as files are being watched. Default true.
* @property {boolean} [options.interval]  the interval in milliseconds at which to poll the file for changes. Default 5007.
* @param {function} listener – the callback to be invoked when the file changes.
* @return {fs.StatWatcher} returns a stat watcher object that can be used to stop watching the file with `unwatchFile`.
*/

The sync versions of these functionalities will also be implemented. Please note these apis were considered as they covered the important functionalities for perforiming file system operations through stdlib, any addition or deletion to this list as or when suggested by the mentors would be priotised.

Testing

All of these API will be thoroughly tested using Tape framework to ensure proper functionality and interaction with the existing stdlib APIs, mocking APIs calls and checking whether expected data is returned.

Proper and elegant error handling will implemented providing concised error messages.

Proper compatability testing of these APIs will be done to ensure that they run as expected throughtout different Node versions.

Updates

Regular updates will be shared in my blog on the implemented APIs and challenges that I face that I face in implementing them.

Documentation and Refinement

I'll create detailed API documentation for each of the APIs that will be implemented, explaining exactly how to use them. For this I'll also include usage examples to make things crystal clear and cover any edge cases that users may face. Next, I'll update the stdlib user documentation to reflect these new functionalities. This way, anyone using stdlib will know exactly what these new fs methods do and how to use them. Finally I will remain energized and excited for the code reviews with my mentors, anything that could further optimized the code or the overall quality will be taken into consideration and implemented.

Why this project?

As a developer working on a project which simplifies development workflows and brings a more unified Node js environment is deeply rewardind. Also the code review sessions with the mentors gives me an excellent opportunity to learn best practices for efficient and maintainable code. Finally I believe that stdlib holds huge potential for bein a one stop solution for many things in Javascript be it numerical computing, data processing or even the built in Node js functionalities. I m eager to be a part of this ecosystem and to learn from mentors that are part of this.

Qualifications

I have a thorough understanding of Javascript fundamentals and experience with Node js which could be seen in my projects. I have a strong hold over file system operations and have used the fs package in many of my projects. Also through the Node js documentation and stdlib implementations I have gained some familiarity with the abstractions needed to be provided to support different env. I will be using this knowledge to ensure that all the apis re truly compatible across different Node JS versions. Also I have done some wiring rewiring in stdlib to create the append-file Api(currently an open PR), and as such I am familiar with the workings here and will use this in implementing the other Apis. Regarding the college coursework I have had subjects relevant to the project which includes Web Development, Software Engineering, Data Structures, Design and Analysis of Algorithms.

Prior art

Node js fs documentations. Stdlib already has some fs api including close, exists, open, readDir, readFile, readFileList, readJSON, readWASM, rename, resolveParentPath, resolveParentPathBy, unlink, writeFile ( in total 13 ) these provide sufficient examples from which the implementation of new APIs will take off. Readable-stream package.

Commitment

From May 22 to June 22 I will be having my end semester examinations. During this time I will not be able to dedicate much time in coding still I will try to allocate 2 to 3 hr. daily Apart from this I will be available to work full time on the project for the remaining timeframe.

Schedule

Assuming a 12 week schedule,

Will be extensively used for communicating with my mentors verifying the proposed plan of implementation and the order in which these APIs will be implemented, along with this I would also start implementation of some minor load Apis so that the first four weeks of coding in which I will be occupied in my exams could be consolidated. Also during this period, I would mostly like to communicate and clarify the Abstraction demand of the project, this would help me in sorting out the requirements and familiarizing myself with the plan in which these abstractions will be implemented so that I could make quality contribution to this aspect.

First 4 weeks ( Exam period )

During this time I will be working on creating the following api and opening PR for them access( ), chmod( ), chown( ), copyFile( ), link( ), chownLink( ) , stat( ), statFs( ), statLink( ) they will also be coming fully tested, documented, with enough suitable examples and benchmarking. I will also be opening any possible Issues regarding theses APIs. Though I will try to but as of now any changes in these implementations as or if demanded by code reviews only seems possible for me to implement in the 5th week.

5th week symslink( ) api will be implemented in this period. I will be implementing the changes demanded in code reviews in the APIs implemented in previous weeks. Any or modifications for them will be done in this week.

6th week midterm evaluation

7th and 8th week Opening PRs on the following APIs mkdir( ), mkdtemp( ), rmdir( ), openDir( ) They will also be thoroughly tested and fully documented with suitable examples to show working. Any modifications or optimizations as highlighted by the mentors will also be implemented. Issues on these APIs if any will be opened and addressed in these weeks.

9th and 10th week PRs will be opened on the following APIs rm( ), truncate( ), watchFile( ), unwatchFile( ) They will also be thoroughly tested and fully documented with suitable examples to show working. Any modifications or optimizations as highlighted by the mentors will also be implemented. Issues on these APIs if any will be opened and addressed in these weeks.

11th and 12th week createWriteStream( ), createReadStream( ), utimesLink( ), and utimes( )

This schedule is subjected to change if mentors demand and any API that is prioritized by the mentors will be implemented earlier.

I would like to highlight that this timeline is made in accordance to the 12 weeks timeline suggested. And I have adjusted my workload along with the exams to deliver this. But if the mentors allow and I sincerely request to extend this timeline from 12 to 16 weeks, this will also give me time to focus on my examinations and help in improving the quality of my contributions.

The 16 weeks schedule will include

First 4 weeks ( Exam period ) During this time I will be working on creating the following api and opening PR for them access( ), chmod( ), chown( ), copyFile( ), link( ) ,chownLink( ) they will also be coming fully tested, documented, with enough suitable examples and benchmarking. I will also be opening any possible Issues regarding theses APIs. Though I will try to but as of now any changes in these implementations as or if demanded by code reviews only seems possible for me to implement in the 5th week.

5th week symslink( ) api will be implemented in this period. I will be implementing the changes demanded in code reviews in the APIs implemented in previous weeks. Any or modifications for them will be done in this week.

6th and 7th week Opening PRs on the following APIs mkdir( ), mkdtemp( ), rmdir( ), openDir( ) They will also be thoroughly tested and fully documented with suitable examples to show working. Any modifications or optimizations as highlighted by the mentors will also be implemented. Issues on these APIs if any will be opened and addressed in these weeks.

8th and 9th week PRs will be opened on the following APIs rm( ), truncate( ), stat( ), statFs( ), statLink( ) They will also be thoroughly tested and fully documented with suitable examples to show working. Any modifications or optimizations as highlighted by the mentors will also be implemented. Issues on these APIs if any will be opened and addressed in these weeks.

10th week midterm evaluation

11th and 12th week Implementing the following APIs createWriteStream( ), createReadStream( ), utimesLink( ), and utimes( ) will be thoroughly tested and fully documented with suitable examples to show working. Any modifications or optimizations as highlighted by the mentors will also be implemented.

13th week watchFile( ), unwatchFile( ). Proper documentation , benchmarking and testing for the same.

14th and 15th week Implementing a promisified version for the async functionalities in these APIs. Proper documentation , benchmarking and testing for the same.

16th week Final revisions and testing.

Changes in this schedule from the 12 weeks one

Note

Related issues

Yes this idea has been proposed by @kgryte

link for the same - https://github.com/stdlib-js/google-summer-of-code/issues/10

Checklist

HRIDYANSHU054 commented 6 months ago

Hi @kgryte , @Planeshifter, @steff456
can you kindly review this proposal and if there are any ambiguities which should be cleared in it and any other general changes. Please can you also comment on the schedule.

Pranavchiku commented 6 months ago

@HRIDYANSHU054 thanks for filing the proposal, looks good. Would be worth mentioning about your plans in community bonding period, you may wrap a few things up to compensate for your exams during May 22 - June 22 which overlaps more with Phase1 . Also, can you please mention how many hours are you targeting ( 175 / 350 ) ?

kgryte commented 6 months ago

@HRIDYANSHU054 Thank you for sharing a draft of your proposal. A few comments:

  1. A 16-week schedule should be fine and makes sense in order to accommodate your examinations.
  2. Node's filesystem APIs have continued to evolve over the years, adding support for new options and functionality. E.g., fs.cp was added in v16.7.0. One of the core principles of stdlib is ensuring backward compatibility. Historically, we've supported all the way back to Node.js v0.10. While we could potentially relax this requirement, how do you plan to support stdlib APIs which can accommodate and smooth over the differences across Node.js versions?
  3. In order to implement the Promise API variants, we'd need to add various Promise functionality to stdlib. What APIs would we need to implement which would be prerequisite for fs promise packages?
  4. I noticed you've left out various fs APIs (e.g., cp, writevSync, fchmod, etc). Would you mind sharing why you've chosen the API set you have?

Ideally, any fs API we provide should work across all versions of Node.js that we support. And thus, for Node.js versions with missing functionality, we'd need to provide polyfills. And this could potentially be quite involved, and, if so, could affect your project timeline.

HRIDYANSHU054 commented 6 months ago

Thank you @Pranavchiku for reviewing this proposal, I have added my plan for the community bonding period , this was somehow left in the initial proposal.

In both the above possible schedules(12 weeks and 16 weeks) the project scope will span over 350 hours.

HRIDYANSHU054 commented 6 months ago

Thank you @kgryte for this review


First of all I really appreciate that you have given me the freedom to take the 16 weeks schedule .

Regarding your 2nd Question I am planning to use version checking and Pollyfilling and then provide the appropriate functionality for the user's Node version

I am taking an example of what I have thought of implementing promises these promisified versions would be provided as seperate APIs just like sync and async APIs are provided so fs.promises were supported in Node version 10 , so if the process Node version is 10 r greater I will be providing a fs.promiseS functionality now a suitable way to replace this functionality in versions that are older than the version 10, is to use JavaScript native Promises constructor and combine them with the callback based versions of fs functions

a demo for mkdir( )

function mkdirPromise(path, options = {}) {
  // Polyfill for Node.js versions below 10
  // internally implement Native promise + callback based async API
  if ( Number(process.versions.node.split('.')[0] ) < 10 ) {
    return new Promise((resolve, reject) => {
      fs.mkdir(path, options, (err) => {
        if (err) {
          reject(err);
        } else {
          resolve();
        }
      });
    });
  }

  // Using fs.promises API for versions  greater than 10
  return fs.promises.mkdir(path, options);
}

also we could have not even used the version checking and instead use the JavaScript promises along with callback based fs functions in the first place but then there are many options of the fs.promises functions which requires a lot of work to implement on our own .This I feel is something that I could start working on post GSOC.

Regarding 3rd, the APIs that I have seen in the codebase and documentations during this period could be implemented using native JavaScript promises and the functionalities which comes along with it , like then() and catch() ( not stating await and async since then and catch covers more older versions of Node JS), Promise.Resolve( ), Promise.Reject( ).

Regarding 4th

I have mentioned this in the proposal also under The Prior Art section that 13 ( close, exists, open, readDir, readFile, readFileList, readJSON, readWASM, rename, resolveParentPath, resolveParentPathBy, unlink, writeFile ) APIs have already been built by the stdlib contributors. So, the work for me on these APIs would be to refactor them if asked to and implement the promisified versions. Still, Also this list is subjected to changes .

HRIDYANSHU054 commented 6 months ago

@kgryte a simpler implementation for cp( ) promises using the above approach I stated would be like this

function cpPromise(src, dest, options = {}) {
  if (Number(process.versions.node.split('.')[0] ) > 16) {
    // Use fs.cp promise version for Node.js v16 and above
    return fs.promises.cp(src, dest, options);
  } else {
    // Fallback functionality implemented by using streams
    return new Promise((resolve, reject) => {
      fs.stat(src, (err, stats) => {
        if (err) {
          reject(err);
          return;
        }

        if (!stats.isDirectory()) {
          // copies a single file
          var rStream = fs.createReadStream(src);
          var wStream = fs.createWriteStream(path.join(dest, path.basename(src)));

          rStream.pipe(writeStream);
          rStream.on('end', () => resolve()); 

          return;
        }

        // copying entire directory
        mkdir(dest, { recursive: true }, (err) => {
          if (err) {
            reject(err);
            return;
          }

          var files = readdirSync(src);
          var promises = [];

          for (const file of files) {
            var srcFile = path.join(src, file);
            var destFile = path.join(dest, file);
            promises.push(cp(srcFile, destFile, options)); // Recursively calling for subdirectories
          }

          Promise.all(promises)
            .then(() => resolve())
            .catch(err => reject(err));
        });
      });
    });
  }
}

This is just a rough implementation and would be broken, modified and refined upon whenever the times comes to implement this. Also implementation of cp( ) would directly come after createWriteStream( ) and createReadStream( ) has been implemented.

Please check whether this implementation aligns with your vision of keeping abstraction and Node js version independency in fs promises and fs API s for stdlib