This recipe transforms imports of fs.F_OK, fs.R_OK, fs.W_OK, and fs.X_OK from the root fs module to fs.constants, addressing the deprecation of these constants at the module root level.
What It Does
The codemod transforms:
fs.F_OK → fs.constants.F_OK
fs.R_OK → fs.constants.R_OK
fs.W_OK → fs.constants.W_OK
fs.X_OK → fs.constants.X_OK
Usage
npx codemod nodejs/fs-access-mode-constants
Examples
Basic Usage
const fs = require('node:fs');
fs.access('/path/to/file', fs.F_OK, callback);
const fs = require('node:fs');
fs.access('/path/to/file', fs.constants.F_OK, callback);
Combined Access Modes
const fs = require('node:fs');
fs.access('/path/to/file', fs.R_OK | fs.W_OK, callback);
const fs = require('node:fs');
fs.access('/path/to/file', fs.constants.R_OK | fs.constants.W_OK, callback);
Multiple Checks
import { access, F_OK, R_OK, X_OK } from 'node:fs';
access('/script.sh', F_OK, (err) => {
if (!err) {
access('/script.sh', X_OK, (err) => {
console.log(err ? 'not executable' : 'executable');
});
}
});
import { access, constants } from 'node:fs';
access('/script.sh', constants.F_OK, (err) => {
if (!err) {
access('/script.sh', constants.X_OK, (err) => {
console.log(err ? 'not executable' : 'executable');
});
}
});
Access Mode Constants
F_OK - File Existence
Checks if the file exists (without checking permissions):
import { access, constants } from 'node:fs/promises';
try {
await access('/path/to/file', constants.F_OK);
console.log('File exists');
} catch {
console.log('File does not exist');
}
R_OK - Read Permission
Checks if the file is readable:
import { access, constants } from 'node:fs/promises';
try {
await access('/path/to/file', constants.R_OK);
console.log('File is readable');
} catch {
console.log('File is not readable');
}
W_OK - Write Permission
Checks if the file is writable:
import { access, constants } from 'node:fs/promises';
try {
await access('/path/to/file', constants.W_OK);
console.log('File is writable');
} catch {
console.log('File is not writable');
}
X_OK - Execute Permission
Checks if the file is executable:
import { access, constants } from 'node:fs/promises';
try {
await access('/path/to/script.sh', constants.X_OK);
console.log('File is executable');
} catch {
console.log('File is not executable');
}
Why Migrate?
Access mode constants at the root fs module level were deprecated to improve API organization and consistency.
Moving to fs.constants:
- Groups related constants together
- Aligns with the location of other fs constants
- Provides better API organization
- Matches conventions used by other Node.js modules
Combining Access Modes
You can combine multiple access modes using the bitwise OR operator (|):
import { access, constants } from 'node:fs/promises';
// Check if file is both readable AND writable
try {
await access('/path/to/file', constants.R_OK | constants.W_OK);
console.log('File is readable and writable');
} catch {
console.log('File is not readable and/or not writable');
}
fs.access() should not be used to check file accessibility before fs.open(). Instead, open the file directly and handle errors. Using access() first introduces a race condition.
Common Patterns
Check Before Read
import { access, readFile, constants } from 'node:fs/promises';
try {
await access('/config.json', constants.R_OK);
const data = await readFile('/config.json', 'utf8');
console.log(JSON.parse(data));
} catch (err) {
console.error('Cannot read config:', err.message);
}
Verify Multiple Files
import { access, constants } from 'node:fs/promises';
const files = ['file1.txt', 'file2.txt', 'file3.txt'];
const results = await Promise.allSettled(
files.map(file => access(file, constants.F_OK))
);
results.forEach((result, i) => {
if (result.status === 'fulfilled') {
console.log(`${files[i]} exists`);
} else {
console.log(`${files[i]} does not exist`);
}
});
Other fs.constants
The fs.constants object also includes:
- File Open Flags:
O_RDONLY, O_WRONLY, O_RDWR, etc.
- File Copy Flags:
COPYFILE_EXCL, COPYFILE_FICLONE, etc.
- File Type Constants:
S_IFMT, S_IFREG, S_IFDIR, etc.
Deprecation Reference
This migration addresses DEP0176.