# Modules, files, and the command line

# Running a program

node reader.js notes.txt

process.argv[2] is notes.txt in this example. Treat command-line input as untrusted: validate the path and handle missing files and read errors. Use node:path to construct paths rather than concatenating platform-specific separators.

# Modules: two styles

Node's traditional module system is CommonJS:

const { readFile } = require('node:fs');
const { join } = require('node:path');
module.exports = { join };

Node also supports ECMAScript modules. In a .mjs file, or in a package with "type": "module":

import { readFile } from 'node:fs/promises';
export { readFile };

Use one module system consistently per project. Mixing export in a .js file with require elsewhere fails without the matching "type" declaration or a transform step; do not treat mixed syntax as a runnable recipe.

# Async filesystem APIs

An error-first callback receives an error before a value:

const { readFile } = require('node:fs');

readFile('notes.txt', 'utf8', (error, text) => {
  if (error) {
    console.error(error);
    return;
  }
  console.log(text);
});
console.log('Reading started');

The Promise-based equivalent works with async/await:

const { readFile } = require('node:fs/promises');

async function showFile(path) {
  try {
    console.log(await readFile(path, 'utf8'));
  } catch (error) {
    console.error('Unable to read file:', error);
  }
}

Without 'utf8', readFile returns a Buffer of bytes, not a string. Avoid synchronous filesystem operations on a busy server's request path because they block other callbacks.

# Relating this to the folder-activity task

The pet project asks for added/removed file detection. A naive setInterval + fs.readdir poll that only looks at the latest listing can report additions but misses removals. A robust polling approach keeps the previous filename set and compares it with the new set on each successful read:

const previous = new Set(oldNames);
const current = new Set(newNames);

const added = newNames.filter((name) => !previous.has(name));
const removed = oldNames.filter((name) => !current.has(name));

Start with an initial baseline snapshot, and handle read errors without treating an unreadable folder as empty. fs.watch is another API, but filesystem events can be platform-dependent.

Node filesystem API (opens new window) · Node packages and modules (opens new window)