DEV Community

Lukas Gaucas
Lukas Gaucas

Posted on • Updated on

Node.js file system CRUD

Let me tell you one thing before getting into README.md . I had nothing to do with this before . I am Windows user since childhood . Lot's of vibe of the filesystem particular comes (are borrowed) from Linux or related kernels ...


README.md

Execute scripts one by one keeping the order of executions as such:

  1. node CREATE : 1.1 if file not exists – will be created 1.2 if file existed before hand – a message it already existed will be presented

TIP : In order to see changes, before making next step for INSERT command , I am highly suggesting to open people.json file at the side to observe changes whilst INSERTing (appending) a new record ;

  1. node INSERT – this will append ./people.json file with a new record at very end of top-level array JSON string
  2. node REMOVE – this will swap recently appended record with an object of null
  3. node DELETE – this will completely remove (delete) file from system (the directory)

CREATE

const isExist = require("fs");

const PATH = `./people.json`;

// This could be rewritten using fsPromises Class as promisified version of check whether file exists or not :
// @https://nodejs.org/api/fs.html#fspromisesaccesspath-mode
isExist.access(PATH, isExist.F_OK, async (err) => {
  if (err) {
    console.error(`File by the name of ${PATH} has not existed ; ${PATH} was created .`);
    const dummy_content = `[{"id": 0, "db_engine" : "MOCKED_mongoDB", "metadata": "some_metadata", "filename": "${PATH}"}]`;
    try {
      await isExist.writeFile( PATH, dummy_content, {flag : "w+" /* r+ would throw an error !*/} , dummy_res => dummy_res /* ? res : console.info("Dummy async operation done!") */);
    } 
    catch (err) {
      console.error(err)
    }
  }
  else { console.log(`File of ${PATH} already exists`); 
  };
});
Enter fullscreen mode Exit fullscreen mode

INSERT

const fs = require("fs");
const fsPromises = require("fs").promises;

const PATH = `./people.json`;

async function main(){

let f1 = await (fsPromises.readFile(PATH, {encoding: "utf-8"})); console.log( "current files content is: ", f1 ); // Reading the file before inserting (appending) something new may take some time , that's why hereby we strongly should use fsPromise over synchronous fs Class
let file_descriptor = null;
  try {
      /* must explicitly change default flag of "r" to sth like "r+" ! : @https://nodejs.org/api/fs.html#fs_file_system_flags */
      file_descriptor = await fsPromises.open(PATH, "r+"); // let's assign a value to the file of people.json as file descriptor (fd)
      console.log("file_handle_descriptor reference: ", file_descriptor.fd); /* (^see below for caret) hereby file_descriptor.fd technically equals to 3 , yes simply No. 3 */
      console.log({filehandleBuffer : file_descriptor})
  }
  catch(file_descriptor_error) {
    console.error(file_descriptor_error);
  }

  // Signature of : <Buffer 00 00 00 00 00> where as each pair of 00 called "hex dump" ; Each byte (8 bits) is represented as a two-digit hexadecimal number [@wikipedia.org]
  let YOUR_CONTENT = ',{"id": 1, "new_data": "CRUD 123"}]'; // your content wished to be appended (inserted)
  console.log("YOUR_CONTENT_LENGTH: ", YOUR_CONTENT.length)
  /* 
  Signature of fs.write() :    
  isExist.write(fd, buffer, offset [of buffer given], Buffer.alloc(length, whereas each byte presented in duplex of hex dump), position [at file start writing], (err, bytesWritten, buffer)=>{return;} | (err, stringWritten, string)=>{return;}) 
  */
  fs.write(file_descriptor.fd, Buffer.from(YOUR_CONTENT), 0, null, f1.length-1,  (err, bytesWritten, buffer)=>{
          if (err) {throw err;}
          else {
              console.log("bytesWritten: ", bytesWritten);
              console.log("buffer: ", buffer);
          }
  });

  // return;

}
main();
Enter fullscreen mode Exit fullscreen mode

REMOVE

const fsPromises = require('fs').promises;

async function main(){

  let f1 = await (fsPromises.readFile('./people.json', {encoding: "utf-8"})); console.log( "current files content is: ", Array.isArray(JSON.parse(f1)));

  let f1Parsed = JSON.parse(f1);

  let temp = [];
  f1Parsed.forEach((value, index)=>{
      temp.push({index : value})
  });

  console.log("temp before delete: ", temp);

  temp.forEach((val, inx)=>{
    if(
        temp.find((obj) => obj.index.id && inx === 1)
    )
    {   
        delete temp[inx];
    }
  });

  console.log("temp after delete: ", temp);

  await fsPromises.writeFile('./people.json', JSON.stringify(temp));

  // return;

}
main()
Enter fullscreen mode Exit fullscreen mode

NOTE : after deleting the record a new record could be added following pattern [{ ... , null , a new record }] . However, the top level array – keep attention – will stay sparsed (i.e. of static index) !

DELETE

const fsPromises = require('fs').promises;

const PATH = './people.json';

async function remove(){

  try{
  await fsPromises.unlink(PATH);
  console.info(`File by the name of ${PATH} was deleted`);
  }
  catch(err){
  console.error(err, `File by the name of ${PATH} does not exist ; TIP: Run node CREATE.js on Shell first`);
  }

  // return;

}
remove()
Enter fullscreen mode Exit fullscreen mode

NOTE : At the time of writing this CRUD on replit.com IDE ,i.e.: the only way to require CJS modules was as so: require('fs').promise instead of require('fs/promises') : technically both works but depends on what IDE you work , so please pay extra attention at this part !


FINAL NOTE : this CRUD could be improved , but I am sharing its state as is , nevertheless there are limitless features or tweaks to be applied upon . If any typo found and (or) suggestions could be made, please leave it in the comment section below . Thank you and see you in the next one !

Discussion (0)