Categories
JavaScript Nodejs

Node.js FS Module — Truncating and Removing Files

Manipulating files and directories are basic operations for any program. Since Node.js is a server side platform and can interact with the computer that it’s running on directly, being able to manipulate files is a basic feature. Fortunately, Node.js has a fs module built into its library. It has many functions that can help with manipulating files and folders. File and directory operation that are supported include basic ones like manipulating and opening files in directories. Likewise, it can do the same for files. It can do this both synchronously and asynchronously. It has an asynchronous API that have functions that support promises. Also it can show statistics for a file. Almost all the file operations that we can think of can be done with the built in fs module. In this article, we will truncate files with the truncate family of functions and remove files and symbolic links with the unlink family of functions.

Truncate Files with the fs.truncate Family of Functions

We can truncate files with the Node.js truncate family of functions. Truncating a file is to shrink the file to a specified size. To truncate a file asynchronously we can use the truncate function. The function takes 3 arguments. The first argument is the path object, which can be a string, a Buffer object or an URL object. When a file descriptor is passed into the first argument instead of the path, it will automatically call ftruncate to truncate the file with the given file descriptor. Passing in a file descriptor is deprecated and may thrown an error in the future. The second argument is the length of the file in bytes that you want to truncate it to. The default value is 0. Any extra data bigger than the size specified is lost when the size is smaller than the original size. The third argument is a callback function that is run when the truncate operation ends. It takes an err parameter which is null when the truncate operation succeeds and has an object with the error information otherwise.

To truncate a file with the truncate function, we can write the following code:

const fs = require("fs");  
const truncateFile = "./files/truncateFile.txt";

fs.truncate(truncateFile, 1, err => {  
  if (err) throw err;  
  console.log("File truncated");  
});

If we run the code above, there should be a single byte of content left in the file you’re truncating.

The synchronous version of the truncate function is the truncateSync function. The function takes 2 arguments. The first argument is the path object, which can be a string, a Buffer object or an URL object. When a file descriptor is passed into the first argument instead of the path, it will automatically call ftruncateSync to truncate the file with the given file descriptor. Passing in a file descriptor is deprecated and may thrown an error in the future .The second argument is the length of the file in bytes that you want to truncate it to. The default value is 0. Any extra data bigger than the size specified is lost when the size is smaller than the original size. It returns undefined .

We can use the truncateSync function like in the following code:

const fs = require("fs");  
const truncateFile = "./files/truncateFile.txt";

try {  
  fs.truncateSync(truncateFile, 1);  
  console.log("File truncated");  
} catch (error) {  
  console.error(error);  
}

If we run the code above, there should be a single byte of content left in the file you’re truncating.

There’s also a promise version of the truncate function. The function takes 2 arguments. The first argument is the path object, which can be a string, a Buffer object or an URL object.The second argument is the length of the file in bytes that you want to truncate it to. The default value is 0. Any extra data bigger than the size specified is lost when the size is smaller than the original size. It returns a promise that is resolved with no arguments when the operation is successful.

To truncate a file with the promise version of the truncate function, we can write the following code:

const fsPromises = require("fs").promises;  
const truncateFile = "./files/truncateFile.txt";

(async () => {  
  try {  
    await fsPromises.truncate(truncateFile, 1);  
    console.log("File truncated");  
  } catch (error) {  
    console.error(error);  
  }  
})();

If we run the code above, again there should be a single byte of content left in the file you’re truncating.

Remove Files and Symbolic Links with the fs.unlink Family of Functions

We can remove a file or a symbolic link with the unlink function. The function takes 2 arguments. The first argument is the path object, which can be a string, a Buffer object or an URL object.The second argument is a callback function that takes an err object, which is null when the file or symbolic link removal operation succeeds, and has the error data if the operation failed. The unlink function doesn’t work on directories in any state. To remove directories, we should use the rmdir function.

To use the unlink function to remove a file, we can something like the code below:

const fs = require("fs");  
const fileToDelete = "./files/deleteFile.txt";

fs.unlink(fileToDelete, err => {  
  if (err) {  
    throw err;  
  }  
  console.log("Removal complete!");  
});

If we run the code above, the file that’s to be deleted should be gone.

The synchronous version of the unlink function is the unlinkSync function. The function takes one argument. The only argument is the path object, which can be a string, a Buffer object or an URL object. It returns undefined .

We can use it like in the following code:

const fs = require("fs");  
const fileToDelete = "./files/deleteFile.txt";

try {  
  fs.unlinkSync(fileToDelete);  
  console.log("Removal complete!");  
} catch (error) {  
  console.error(error);  
}

There’s also a promise version of the unlink function. The function takes one argument. The only argument is the path object, which can be a string, a Buffer object or an URL object. It returns a promise that’s resolved with no argument when the operation is successful.

If we run the code above, the file that’s to be deleted should be gone.

We can use it like in the following code:

const fsPromises = require("fs").promises;  
const fileToDelete = "./files/deleteFile.txt";

(async () => {  
  try {  
    await fsPromises.unlink(fileToDelete);  
    console.log("Removal complete!");  
  } catch (error) {  
    console.error(error);  
  }  
})();

If we run the code above, the file that’s to be deleted should be gone.

The promise version of the unlink function is a much better choice than the unlinkSync function when you want to do multiple things sequentially that includes a call to the unlink function since it doesn’t tie up the whole program waiting for the file or symbolic link deletion operation to complete before continuing to program other parts of the program.

In this article, we truncate files with the truncate family of functions and remove files and symbolic links with the unlink family of functions. The truncate family of functions let us specify the number of bytes to keep while truncating the rest of the file. The unlink family of functions remove files and symbolic links. If we want to do these operations sequentially with other operations, the promise versions of these functions. Even though the API is still experimental, it is much better than the synchronous versions of these functions since it allows for sequential and asynchronous operations with promises. Also, it helps avoid callback hell where we nest promises in too many levels.

Categories
Express JavaScript Nodejs

Easy Debugging with the errorhandler Express Middleware

The errorhandler Express middleware can be used to handle errors during app development.

In this article, we’ll look at how to use it to debug our code during development.

Why do we Need This Middleware?

We need this for debugging purposes. It shows the full error stack trace and internals of any object that’s passed to this module will be sent back to the client if an error occurs.

It’ll display as many details as possible about errors. Object details will be fully displayed. The data can be displayed as HTML, JSON, and plain text.

When the object is a standard Error object, the string provided by the stack property will be returned in HTML or text responses.

When an object is a non-error object, the result of util.inspect will be returned in HTML or text format.

Error involving JSON responses will be an object with enumerable properties from the object in the response.

Installing the Package

We can install it by running:

npm install errorhandler

Options

The errorhandler middleware takes a few options to control what to return.

log

The log property lets us provide a function to be called with the error and a string representation of the error.

It can be used to write the error to any desired location or set to false to only send the error back in the response.

The function has the signature (err, str, req, res) where err is the Error object, str is a string representation of the error, req is the request object and res is the response object.

This function is run after the response has been written.

The default value for this option is true unless process.env.NODE_ENV has the value 'test' .

Other possible values include true , which logs errors using console.error(str) , or false , which only sends the error back in the response.

Examples

We can use it as follows:

const express = require('express');  
const express = require('express');  
const bodyParser = require('body-parser');  
const errorHandler = require('errorhandler');  
const app = express();
app.use(bodyParser.json());
app.get('/', (req, res, next) => {  
  throw new Error('error');  
  res.send();  
})
app.use(errorHandler());
app.listen(3000);

Since our route throws an error, we should get objects with the error string and object logged.

We should get something like::

Connect  
500 Error: error  
   at app.get (/home/runner/index.js:9:9)  
   at Layer.handle [as handle_request] (/home/runner/node_modules/express/lib/router/layer.js:95:5)  
   at next (/home/runner/node_modules/express/lib/router/route.js:137:13)  
   at Route.dispatch (/home/runner/node_modules/express/lib/router/route.js:112:3)  
   at Layer.handle [as handle_request] (/home/runner/node_modules/express/lib/router/layer.js:95:5)  
   at /home/runner/node_modules/express/lib/router/index.js:281:22  
   at Function.process_params (/home/runner/node_modules/express/lib/router/index.js:335:12)  
   at next (/home/runner/node_modules/express/lib/router/index.js:275:10)  
   at jsonParser (/home/runner/node_modules/body-parser/lib/types/json.js:110:7)  
   at Layer.handle [as handle_request] (/home/runner/node_modules/express/lib/router/layer.js:95:5)

Displayed on our screen.

We can add our own custom logging function as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const errorHandler = require('errorhandler');  
const app = express();  
const errorNotification = (err, str, req) => {  
  console.log(str);  
}
app.use(bodyParser.json());
app.get('/', (req, res, next) => {  
  throw new Error('error');  
  res.send();  
})
app.use(errorHandler({ log: errorNotification }));
app.listen(3000);

In the code above, we added our own errorNotification function. All we did was logging the error string with our errorNotification handler function.

Then we should get:

Error: error  
    at app.get (/home/runner/index.js:12:9)  
    at Layer.handle [as handle_request] (/home/runner/node_modules/express/lib/router/layer.js:95:5)  
    at next (/home/runner/node_modules/express/lib/router/route.js:137:13)  
    at Route.dispatch (/home/runner/node_modules/express/lib/router/route.js:112:3)  
    at Layer.handle [as handle_request] (/home/runner/node_modules/express/lib/router/layer.js:95:5)  
    at /home/runner/node_modules/express/lib/router/index.js:281:22  
    at Function.process_params (/home/runner/node_modules/express/lib/router/index.js:335:12)  
    at next (/home/runner/node_modules/express/lib/router/index.js:275:10)  
    at jsonParser (/home/runner/node_modules/body-parser/lib/types/json.js:110:7)  
    at Layer.handle [as handle_request] (/home/runner/node_modules/express/lib/router/layer.js:95:5)

From the console.log output in addition to what we see on the page.

Conclusion

With the errorhandler middleware, we can debug our Express apps more easily because we can see more information about the error like the stack trace and the object with more error information.

Also, we can see the request and response object when the error occurred.

The error data can be displayed in HTML, JSON or plain text.

We can add it by including the middleware with use , but we have to be careful not run use this in production since it shows internal data about the error.

Categories
Express JavaScript

Guide to the Express Response Object — Files and JSON

The Express response object lets us send a response to the client.

Various kinds of responses like strings, JSON, and files can be sent. Also, we can send various headers and status code to the client in addition to the body.

In this article, we’ll look at various properties of the response object, including files and JSON responses.

Methods

res.download

res.download sends a file response to the server.

For example, if we have:

const express = require('express')  
const app = express()
app.use(express.json())  
app.use(express.urlencoded({ extended: true }))
app.get('/', (req, res) => {  
  res.download('./public/foo.txt');  
})
app.listen(3000, () => console.log('server started'));

Then when a request is made to this route, then we’ll get a file downloaded.

We can save a file with a different than the file on the server by writing:

const express = require('express');  
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/', (req, res) => {  
  res.download('./files/foo.txt', 'foobar.txt');  
});
app.listen(3000, () => console.log('server started'));

The file foo.txt from the server will be saved as foobar.txt by the client.

The download method also takes an error handler in case the download response fails.

For example, we can handle errors with the built-in error handler as follows:

const express = require('express');  
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/', (req, res, next) => {  
  res.download('./files/foo.txt', 'foobar.txt', err => next(err));  
});
app.listen(3000, () => console.log('server started'));

We called next with the error object passed in to pass it onto the error handler.

res.end([data] [, encoding])

res.end ends the response process. The method comes from response.end() of the http module.

We can use it to end the response without sending any data. To respond with data, we can use res.send() or other methods.

For example, we can use it as follows:

const express = require('express');  
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/', (req, res) => {  
  res.status(404).end();  
});
app.listen(3000, () => console.log('server started'));

Then we sent a 404 response back to the client with no data.

res.format(object)

The res.format method takes the Accept HTTP header from the request object and use res.accepts to select a handler for the request.

For example, we can use it as follows:

const express = require('express');  
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/', (req, res) => {  
  res.format({  
    'text/plain': () => {  
      res.send('hi');  
    }, 'text/html': () => {  
      res.send('<p>hi</p>');  
    }, 'application/json': () => {  
      res.json({ message: 'hi' });  
    }, 'default': () => {  
      res.status(406).end();  
    }  
  })  
});
app.listen(3000, () => console.log('server started'));

If we send a GET request to / with Accept header’s value set to text/plain , we get hi . If we send text/html as the Accept header’s value, we get <p>hi</p> , and so on.

default specifies the default response if none of the response types are matched.

It’ll work even if we abbreviate the MIME type names to something shorter:

const express = require('express');  
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/', (req, res) => {  
  res.format({  
    text: () => {  
      res.send('hi');  
    }, html: () => {  
      res.send('<p>hi</p>');  
    }, json: () => {  
      res.json({ message: 'hi' });  
    }, default: () => {  
      res.status(406).end();  
    }  
  })  
});
app.listen(3000, () => console.log('server started'));

Then we get the same thing as before.

res.get(field)

The get method returns the HTTP response header specified by field . The match isn’t case sensitive.

For example, we can use it as follows:

const express = require('express');  
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/', (req, res) => {    
  res.send(res.get('Content-Type'));  
});
app.listen(3000, () => console.log('server started'));

res.json([body])

res.json lets us send a JSON response to the client. The parameter can be any JSON type, including object, array, string, Boolean, number, or null.

For example, if we have:

const express = require('express')  
const app = express()
app.use(express.json())  
app.use(express.urlencoded({ extended: true }))
app.get('/', (req, res) => {  
  res.json({ message: 'hi' });  
})
app.listen(3000, () => console.log('server started'));

Then we get:

{"message":"hi"}

as the response.

res.jsonp([body])

We can use this to send a JSON response with JSONP support. It returns a callback with the JSON body passed in.

For example, we can use it as follows:

const express = require('express');  
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/', (req, res) => {  
  res.jsonp({ user: 'foo' });  
});
app.listen(3000, () => console.log('server started'));

If we send a GET request with ?callback=cb as the query string, then we get:

// typeof cb === 'function' && cb({"user":"foo"});

as the response. If we leave out the callback search parameter, then we get a normal JSON response:

{  
    "user": "foo"  
}

Conclusion

We can send various kinds of responses easily with the response object.

To send files, we can use download .

To send different things according to the Accept request header, we can use the format method.

Finally, to send JSON, we can use the json or jsonp methods depending on if we need to call a callback function on the client or not.

Categories
Express JavaScript Nodejs

Parse Cookies in Requests in Express Apps with Cookie-Parser

By default, Express 4.x or later doesn’t come with any middleware to parse cookies.

To do this, we can add the cookie-parser middleware.

In this article, we’ll look at how to use it to parse cookies sent with requests.

Adding the Package

We can install the package by running:

npm install cookie-parser

Then we can write:

const express = require('express')  
const cookieParser = require('cookie-parser')  
  
const app = express()  
app.use(cookieParser())

to add the middleware to our app.

Methods

cookieParser(secret, options)

The cookie-parser middleware’s cookieParser function takes a secret string or array of strings as the first argument and an options object as the second argument.

The secret is optional. If it’s not specified it won’t parse signed cookies. If a string is provided, it’ll be used as the secret. If an array of strings is provided, then each secret will be tried for decoding the signed cookie

options is an object that is passed into the cookie.parse as the second option.

cookieParser.JSONCookie(str)

The JSONCookie parses a JSON cookie. This returns the pared JSON value if it’s a JSON cookie. It’ll return the passed value otherwise.

cookieParser.JSONCookies(cookies)

The method will iterate over the keys and call JSONCookie on each value and replace the original value with the parsed value. This returns the same object that’s passed in.

cookieParser.signedCookie(str, secret)

signedCookie parses a cookie as a signed cookie. It’ll return the parsed unsigned value if it was a signed cookie and the signature is valid. If the value wasn’t signed, then the original value is returned. If the value is signed but the cookie can’t be validated with the secret, then false is returned.

cookieParser.signedCookies(cookies, secret)

This method will iterate over the keys and check if any value is a signed cookie. If it’s signed and the signature is valid, then the key will be deleted from the object and added to the new object that’s returned.

The secret can be an array or string. If it’s a string, then it’ll check against the string secret. Otherwise, each cookie will be checked with each string in the array.

The JSONCookie, JSONCookies, signedCookie and signedCookies methods will be automatically invoked depending on the type of cookie sent from the client. Parsing Unsigned Cookies

A simple example is parsing unsigned cookies as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const cookieParser = require('cookie-parser');  
const app = express();
app.use(bodyParser.json());  
app.use(cookieParser());
app.get('/', (req, res) => {  
  res.send(req.cookies);  
});
app.listen(3000);

Then when we send a GET request with the Cookie header’s value set to foo=bar , then we get:

{  
    "foo": "bar"  
}

as the response since req.cookies has the parsed cookie.

Parsing Signed Cookies

We can send a signed cookie and parse it as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const cookieParser = require('cookie-parser');  
const app = express();  
const secret = 'secret';
app.use(bodyParser.json());  
app.use(cookieParser(secret));
app.get('/cookie', (req, res) => {  
  res  
    .cookie('foo', 'bar', { signed: true })  
    .send();  
});
app.get('/', (req, res) => {    
  res.send(req.signedCookies);  
});
app.listen(3000);

The code has the /cookie endpoint to send the signed cookie to the client.

{ signed: true }

will make Express sign the cookie.

Then from the client, when we make a request to / , we get the signed cookie via req.signedCookies and so we get:

{  
    "foo": "bar"  
}

as the response from / .

Conclusion

We can use the cookie-parser middleware to parse the cookies.

It can parse both signed and unsigned cookies. To parse a signed cookie, we just have to sign our cookie with a secret and then cookie-parser can decode the cookie if we pass in the secret to the cookieParser middleware function.

The JSONCookie, JSONCookies, signedCookie and signedCookies methods will be automatically invoked depending on the type of cookie sent from the client.

Categories
JavaScript Nodejs

Node.js FS Module — Symbolic Links and Timestamps

Manipulating files and directories are basic operations for any program. Since Node.js is a server-side platform and can interact with the computer that it’s running on directly, being able to manipulate files is a basic feature.

Fortunately, Node.js has a fs module built into its library. It has many functions that can help with manipulating files and folders. File and directory operations that are supported include basic ones like manipulating and opening files in directories. Likewise, it can do the same for files.

It can do this both synchronously and asynchronously. It has an asynchronous API that has functions that support promises.

Also, it can show statistics for a file. Almost all the file operations that we can think of can be done with the built-in fs module.

In this article, we will create symbolic links with the symlink family of functions and set timestamps with the utimes family of functions.

Creating Symbolic Links

Symbolic links are files that reference other files in the form of relative or absolute paths of the file. We can create symbolic links in Node.js programs with the symlink function.

The function takes 4 arguments.

The first argument is the target path for our symbolic link which is the file path that we want to reference in our symbolic link. It can be in the form of a string, a buffer object, or an URL object.

The second argument is the path of the symbolic link, it can also be in the form of a string, a buffer object, or an URL object.

The third argument is the type, which is a string. It’s only available on Windows and ignored on other platforms. The possible values are 'dir' , 'file' , or 'junction' .

If the type argument isn’t set, it will automatically detect the type of the target and use 'file' or 'dir' . If the target doesn’t exist, then 'file' would be used. Windows requires that the symbolic link path to be absolute. When using 'junction' , the target argument will be converted to the absolute path.

The last argument is a callback function that’s called when the symbolic link creation operation ends. It has an err parameter which is null when the operation succeeds and has an object with the error information when it failed.

We can create a symbolic link with the symlink function as follows:

const fs = require("fs");  
const target = "./files/file.txt";  
const path = "./files/symlink";

fs.symlink(target, path, "file", err => {  
  if (err) {  
    throw err;  
  }  
  console.log("Symbolic link creation complete!");  
});

After running the code above, when we run stat ./files/symlink on POSIX systems, we should get output that looks something like the following:

File: './files/symlink' -> './files/file.txt'  
  Size: 16              Blocks: 0          IO Block: 512    symbolic link  
Device: eh/14d  Inode: 62487444831945583  Links: 1  
Access: (0777/lrwxrwxrwx)  Uid: ( 1000/hauyeung)   Gid: ( 1000/hauyeung)  
Access: 2019-11-03 11:22:19.787359800 -0800  
Modify: 2019-11-03 11:22:19.787359800 -0800  
Change: 2019-11-03 11:22:19.787359800 -0800  
 Birth: -

This means that are symbolic link has been successfully created.

There’s also a synchronous version of the symlink function that’s called the symlinkSync function. It takes 3 arguments.

The first argument is the target path for our symbolic link which is the file path that we want to reference in our symbolic link. It can be in the form of a string, a buffer object, or an URL object.

The second argument is the path of the symbolic link, it can also be in the form of a string, a buffer object, or an URL object. The third argument is the type, which is a string. It’s only available on Windows and ignored on other platforms.

The possible values are 'dir' , 'file' , or 'junction' . If the type argument isn’t set, it will automatically detect the type of the target and use 'file' or 'dir' . If the target doesn’t exist, then 'file' would be used. Windows requires that the symbolic link path to be absolute.

When using 'junction' , the target argument will be converted to the absolute path. It returns undefined .

We can use it to create symbolic links like in the following code:

const fs = require("fs");  
const target = "./files/file.txt";  
const path = "./files/symlink";

try {  
  fs.symlinkSync(target, path, "file");  
  console.log("Symbolic link creation complete!");  
} catch (error) {  
  console.error(error);  
}

After running the code above, when we run stat ./files/symlink on POSIX systems, we should get output that looks the same as the ones above.

There’s also a promise version of the symlink function. It takes 3 arguments.

The first argument is the target path for our symbolic link which is the file path that we want to reference in our symbolic link. It can be in the form of a string, a buffer object, or an URL object.

The second argument is the path of the symbolic link, it can also be in the form of a string, a buffer object, or an URL object.

The third argument is the type, which is a string. It’s only available on Windows and ignored on other platforms.

The possible values are 'dir' , 'file' , or 'junction' . If the type argument isn’t set, it will automatically detect type of the target and use 'file' or 'dir' . If the target doesn’t exist, then 'file' would be used.

Windows requires that the symbolic link path be absolute. When using 'junction' , the target argument will be converted to the absolute path. It returns a promise that resolves with no arguments when it’s successful.

We can use it to create symbolic links like in the following code:

const fsPromises = require("fs").promises;  
const target = "./files/file.txt";  
const path = "./files/symlink";

(async () => {  
  try {  
    await fsPromises.symlink(target, path, "file");  
    console.log("Symbolic link creation complete!");  
  } catch (error) {  
    console.error(error);  
  }  
})();

After running the code above, when we run stat ./files/symlink on POSIX systems, we should get output that looks the same as the ones above.

The promise version of the symlink function is a much better choice than the symlinkSync function when you want to do multiple things sequentially that includes a call to the symlink function since it doesn’t tie up the whole program waiting for the symbolic link creation operation to complete before continuing to program other parts of the program.

Changing Timestamps of Items Stored on Disk

We can change the timestamp of the last accessed time and the last time a file was modified with the utimes function.

The function takes 4 arguments.

The first is the path of the object stored on disk. It can be a string, a Buffer object, and an URL object.

The second argument is the atime which is the time that the object was last accessed. It can be a number, a string or a Date object.

If it’s a number, then it should be the UNIX timestamp.

If it’s a string, then it should be a string form of the UNIX timestamp.

If the value can’t be converted to a number or is NaN, Infinity or -Infinity then an error will be thrown.

The third argument is the mtime , which is the time that the object was last modified. It can be a number, a string or a Date object. It should be in the same format as the atime argument.

The fourth argument is a callback function which takes an err parameter. It’s null when the operation succeeds and has an object that has the error information if it fails.

We can use the utimes function like in the following code:

const fs = require("fs");  
const path = "./files/file.txt";

fs.utimes(  
  path,  
  new Date(2019, 0, 1, 0, 0, 0, 0),  
  new Date(2019, 0, 1, 0, 0, 0, 0),  
  err => {  
    if (err) {  
      throw err;  
    }  
    console.log("Timestamps changed");  
  }  
);

If we run the code above then run stat ./files/file.txt, we should get something like the following output:

File: './files/file.txt'  
  Size: 16              Blocks: 0          IO Block: 512    regular file  
Device: eh/14d  Inode: 22799473115106242  Links: 1  
Access: (0777/-rwxrwxrwx)  Uid: ( 1000/hauyeung)   Gid: ( 1000/hauyeung)  
Access: 2019-01-01 00:00:00.000000000 -0800  
Modify: 2019-01-01 00:00:00.000000000 -0800  
Change: 2019-11-03 11:41:16.155815100 -0800  
 Birth: -

As we can see, the Access and Modify times changed to 2019–01–01 00:00:00.000000000 , so we know that the utimes function has changed the timestamps successfully.

There’s a synchronous version of the utimes function called the utimesSync function.

The function takes 3 arguments.

The first is the path of the object stored on disk. It can be a string, a Buffer object and an URL object. The second argument is the atime which is the time that the object was last accessed.

It can be a number, a string or a Date object. If it’s a number, then it should be the UNIX timestamp. If it’s a string, then it should be a string form of the UNIX timestamp. If the value can’t be converted to a number or is NaN, Infinity or -Infinity then an error will be thrown.

The third argument is the mtime , which is the time that the object was last modified. It can be a number, a string or a Date object. It should be in the same format as the atime argument.

We can use it as in the following code:

const fs = require("fs");  
const path = "./files/file.txt";

try {  
  fs.utimesSync(  
    path,  
    new Date(2019, 0, 1, 0, 0, 0, 0),  
    new Date(2019, 0, 1, 0, 0, 0, 0)  
  );  
  console.log("Timestamps changed");  
} catch (error) {  
  console.error(error);  
}

If we run the code above then run stat ./files/file.txt, we should get the same output as we did above.

There’s also a promise version of the utimes function, which let us run utimes asynchronously while running it in sequence like we do with the utimesSync function.

The function takes 3 arguments. The first is the path of the object stored on disk. It can be a string, a Buffer object, and an URL object.

The second argument is the atime which is the time that the object was last accessed. It can be a number, a string or a Date object. If it’s a number, then it should be the UNIX timestamp.

If it’s a string, then it should be a string form of the UNIX timestamp. If the value can’t be converted to a number or is NaN, Infinity or -Infinity then an error will be thrown.

The third argument is the mtime , which is the time that the object was last modified. It can be a number, a string or a Date object. It should be in the same format as the atime argument.

We can use it as in the following code:

const fsPromises = require("fs").promises;  
const path = "./files/file.txt";

(async () => {  
  try {  
    await fsPromises.utimes(  
      path,  
      new Date(2019, 0, 1, 0, 0, 0, 0),  
      new Date(2019, 0, 1, 0, 0, 0, 0)  
    );  
    console.log("Timestamps changed");  
  } catch (error) {  
    console.error(error);  
  }  
})();

If we run the code above then run stat ./files/file.txt, we should also get the same output as the regular utimes example.

We can create symbolic links with the symlink family of functions.

It takes 3 arguments. The first is the path of the object stored on disk. It can be a string, a Buffer object, and an URL object.

The second argument is the atime which is the time that the object was last accessed. It can be a number, a string or a Date object. If it’s a number, then it should be the UNIX timestamp, and if it’s a string, then it should be a string form of the UNIX timestamp.

The regular asynchronous version also takes a callback function which runs when it ends. The utimes function changes the timestamp of the access and modified time of an object stored on disk. It takes the path of the entity to apply the change and timestamps for access and modified times.

The regular asynchronous version also takes a callback function which runs when it ends. They are handy for times when we need to do these operations in our Node.js programs.