Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor: eliminate fs.promises #196

Merged
merged 8 commits into from
Dec 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
"patterns": [{
"group": ["node:*"],
"message": "Don't use prefixes with Node.js built-ins."
}, {
"name": "fs",
"importNames": ["promises"],
"message": "Use util.promisify(fs.*)() instead of fs.promises.*()."
}]
}],
"simple-import-sort/exports": "error",
Expand Down
12 changes: 8 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"test": "npm run test:unit && npm run lint",
"test:unit": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js --verbose",
"test:coverage": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js --verbose --coverage",
"test:handles": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js --verbose",
"test:handles": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js --verbose --detectOpenHandles",
"bump:minor": "./node_modules/.bin/release-it minor --no-git --no-github && npm run update:readme",
"bump:patch": "./node_modules/.bin/release-it patch --no-git --no-github && npm run update:readme",
"update:readme": "./scripts/update-readme-help.sh",
Expand All @@ -54,7 +54,6 @@
},
"dependencies": {
"@fast-csv/format": "4.3.5",
"@types/tar": "6.1.3",
"7zip-min": "1.4.3",
"archiver": "^5.3.1",
"async": "3.2.4",
Expand Down Expand Up @@ -90,6 +89,7 @@
"@types/micromatch": "4.0.2",
"@types/node": "18.11.9",
"@types/semver": "7.3.12",
"@types/tar": "6.1.3",
"@types/xml2js": "0.4.11",
"@types/yargs": "17.0.13",
"@types/yauzl": "2.10.0",
Expand Down
7 changes: 4 additions & 3 deletions src/modules/outputCleaner.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { promises as fsPromises } from 'fs';
import fs from 'fs';
import { isNotJunk } from 'junk';
import path from 'path';
import trash from 'trash';
import util from 'util';

import ProgressBar, { Symbols } from '../console/progressBar.js';
import fsPoly from '../polyfill/fsPoly.js';
Expand Down Expand Up @@ -91,15 +92,15 @@ export default class OutputCleaner extends Module {
}

// Find all subdirectories and files in the directory
const subPaths = (await fsPromises.readdir(dirsToClean))
const subPaths = (await util.promisify(fs.readdir)(dirsToClean))
.filter((basename) => isNotJunk(basename))
.map((basename) => path.join(dirsToClean, basename));

// Categorize the subdirectories and files
const subDirs: string[] = [];
const subFiles: string[] = [];
await Promise.all(subPaths.map(async (subPath) => {
if ((await fsPromises.lstat(subPath)).isDirectory()) {
if ((await util.promisify(fs.lstat)(subPath)).isDirectory()) {
subDirs.push(subPath);
} else {
subFiles.push(subPath);
Expand Down
5 changes: 3 additions & 2 deletions src/modules/reportGenerator.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { promises as fsPromises } from 'fs';
import fs from 'fs';
import util from 'util';

import ProgressBar from '../console/progressBar.js';
import DATStatus from '../types/datStatus.js';
Expand Down Expand Up @@ -38,7 +39,7 @@ export default class ReportGenerator extends Module {
return csv.split('\n').slice(1).join('\n');
})
.join('\n');
await fsPromises.writeFile(report, contents);
await util.promisify(fs.writeFile)(report, contents);
await this.progressBar.logDebug(`${report}: wrote ${datsStatuses.length.toLocaleString()} status${datsStatuses.length !== 1 ? 'es' : ''}`);

await this.progressBar.logInfo('Done generating report');
Expand Down
5 changes: 3 additions & 2 deletions src/modules/romWriter.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Semaphore } from 'async-mutex';
import fs, { promises as fsPromises } from 'fs';
import fs from 'fs';
import path from 'path';
import util from 'util';

import ProgressBar, { Symbols } from '../console/progressBar.js';
import Constants from '../constants.js';
Expand Down Expand Up @@ -88,7 +89,7 @@ export default class ROMWriter extends Module {
private static async ensureOutputDirExists(outputFilePath: string): Promise<void> {
const outputDir = path.dirname(outputFilePath);
if (!await fsPoly.exists(outputDir)) {
await fsPromises.mkdir(outputDir, { recursive: true });
await util.promisify(fs.mkdir)(outputDir, { recursive: true });
}
}

Expand Down
30 changes: 16 additions & 14 deletions src/polyfill/fsPoly.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import crypto from 'crypto';
import fs, { PathLike, promises as fsPromises, RmOptions } from 'fs';
import fs, { PathLike, RmOptions } from 'fs';
import { isNotJunk } from 'junk';
import os from 'os';
import path from 'path';
import semver from 'semver';
import util from 'util';

export default class FsPoly {
/**
* There is no promise version of existsSync()
*/
static async exists(pathLike: PathLike): Promise<boolean> {
try {
await fsPromises.access(pathLike); // throw if file doesn't exist
await util.promisify(fs.access)(pathLike); // throw if file doesn't exist
return true;
} catch (e) {
return false;
Expand All @@ -20,7 +21,7 @@ export default class FsPoly {

static async isDirectory(pathLike: PathLike): Promise<boolean> {
try {
return (await fsPromises.lstat(pathLike)).isDirectory();
return (await util.promisify(fs.lstat)(pathLike)).isDirectory();
} catch (e) {
return false;
}
Expand Down Expand Up @@ -55,10 +56,10 @@ export default class FsPoly {

try {
// Added in: v10.0.0
return await fsPromises.mkdtemp(prefixProcessed);
return await util.promisify(fs.mkdtemp)(prefixProcessed);
} catch (e) {
// Added in: v10.0.0
return await fsPromises.mkdtemp(path.join(process.cwd(), 'tmp') + path.sep);
return await util.promisify(fs.mkdtemp)(path.join(process.cwd(), 'tmp') + path.sep);
}
}

Expand All @@ -81,7 +82,7 @@ export default class FsPoly {

static async renameOverwrite(oldPath: PathLike, newPath: PathLike, attempt = 1): Promise<void> {
try {
await fsPromises.rename(oldPath, newPath);
await util.promisify(fs.rename)(oldPath, newPath);
} catch (e) {
if (attempt >= 3) {
throw e;
Expand All @@ -96,7 +97,7 @@ export default class FsPoly {

/**
* fs.rm() was added in: v14.14.0
* fsPromises.rm() was added in: v14.14.0
* util.promisify(fs.rm)() was added in: v14.14.0
*/
static async rm(pathLike: PathLike, options: RmOptions = {}): Promise<void> {
const optionsWithRetry = {
Expand All @@ -106,7 +107,7 @@ export default class FsPoly {

try {
// Added in: v10.0.0
await fsPromises.access(pathLike); // throw if file doesn't exist
await util.promisify(fs.access)(pathLike); // throw if file doesn't exist
} catch (e) {
if (optionsWithRetry?.force) {
return;
Expand All @@ -119,17 +120,17 @@ export default class FsPoly {
// DEP0147
if (semver.lt(process.version, '16.0.0')) {
// Added in: v10.0.0
await fsPromises.rmdir(pathLike, optionsWithRetry);
await util.promisify(fs.rmdir)(pathLike, optionsWithRetry);
} else {
// Added in: v14.14.0
await fsPromises.rm(pathLike, {
await util.promisify(fs.rm)(pathLike, {
...optionsWithRetry,
recursive: true,
});
}
} else {
// Added in: v10.0.0
await fsPromises.unlink(pathLike);
await util.promisify(fs.unlink)(pathLike);
}
}

Expand Down Expand Up @@ -174,14 +175,15 @@ export default class FsPoly {
static async touch(filePath: string): Promise<void> {
const dirname = path.dirname(filePath);
if (!await this.exists(dirname)) {
await fsPromises.mkdir(dirname, { recursive: true });
await util.promisify(fs.mkdir)(dirname, { recursive: true });
}

const time = new Date();
try {
await fsPromises.utimes(filePath, time, time);
await util.promisify(fs.utimes)(filePath, time, time);
} catch (e) {
await (await fsPromises.open(filePath, 'a')).close();
const file = await util.promisify(fs.open)(filePath, 'a');
await util.promisify(fs.close)(file);
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/types/archives/zip.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import archiver from 'archiver';
import fs, { promises as fsPromises } from 'fs';
import fs from 'fs';
import path from 'path';
import { Readable } from 'stream';
import { clearInterval } from 'timers';
import util from 'util';
import yauzl, { Entry } from 'yauzl';

import fsPoly from '../../polyfill/fsPoly.js';
Expand Down Expand Up @@ -66,7 +67,7 @@ export default class Zip extends Archive {

const localDir = path.dirname(localFile);
if (!await fsPoly.exists(localDir)) {
await fsPromises.mkdir(localDir, { recursive: true });
await util.promisify(fs.mkdir)(localDir, { recursive: true });
}

return this.extractEntryToStream(
Expand Down
7 changes: 4 additions & 3 deletions src/types/files/file.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import crc32 from 'crc/crc32';
import fs, { PathLike, promises as fsPromises } from 'fs';
import fs, { PathLike } from 'fs';
import path from 'path';
import { Readable } from 'stream';
import util from 'util';

import Constants from '../../constants.js';
import fsPoly from '../../polyfill/fsPoly.js';
Expand Down Expand Up @@ -47,7 +48,7 @@ export default class File {
let finalSize = size;
if (finalSize === undefined) {
if (await fsPoly.exists(filePath)) {
finalSize = (await fsPromises.stat(filePath)).size;
finalSize = (await util.promisify(fs.stat)(filePath)).size;
} else {
finalSize = 0;
}
Expand Down Expand Up @@ -150,7 +151,7 @@ export default class File {
Constants.GLOBAL_TEMP_DIR,
`${path.basename(this.getFilePath())}.temp`,
));
await fsPromises.copyFile(this.getFilePath(), temp);
await util.promisify(fs.copyFile)(this.getFilePath(), temp);
try {
return await callback(temp);
} finally {
Expand Down
5 changes: 3 additions & 2 deletions src/types/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import 'reflect-metadata';

import { Expose, instanceToPlain, plainToInstance } from 'class-transformer';
import fg from 'fast-glob';
import fs, { promises as fsPromises } from 'fs';
import fs from 'fs';
import { isNotJunk } from 'junk';
import micromatch from 'micromatch';
import moment from 'moment';
import os from 'os';
import path from 'path';
import util from 'util';

import LogLevel from '../console/logLevel.js';
import Constants from '../constants.js';
Expand Down Expand Up @@ -326,7 +327,7 @@ export default class Options implements OptionsProps {

// Filter to files
const isFiles = await Promise.all(
globbedPaths.map(async (inputPath) => (await fsPromises.lstat(inputPath)).isFile()),
globbedPaths.map(async (inputPath) => (await util.promisify(fs.lstat)(inputPath)).isFile()),
);
const globbedFiles = globbedPaths
.filter((inputPath, idx) => isFiles[idx])
Expand Down
5 changes: 3 additions & 2 deletions src/types/patches/upsPatch.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { promises as fsPromises } from 'fs';
import fs from 'fs';
import path from 'path';
import util from 'util';

import Constants from '../../constants.js';
import FilePoly from '../../polyfill/filePoly.js';
Expand Down Expand Up @@ -62,7 +63,7 @@ export default class UPSPatch extends Patch {
Constants.GLOBAL_TEMP_DIR,
`${path.basename(sourceFilePath)}.ups`,
));
await fsPromises.copyFile(sourceFilePath, targetFilePath);
await util.promisify(fs.copyFile)(sourceFilePath, targetFilePath);
const targetFile = await FilePoly.fileFrom(targetFilePath, 'r+');

const sourceFile = await FilePoly.fileFrom(sourceFilePath, 'r');
Expand Down
5 changes: 3 additions & 2 deletions src/types/patches/vcdiffPatch.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// eslint-disable-next-line max-classes-per-file
import { promises as fsPromises } from 'fs';
import fs from 'fs';
import path from 'path';
import util from 'util';

import Constants from '../../constants.js';
import FilePoly from '../../polyfill/filePoly.js';
Expand Down Expand Up @@ -248,7 +249,7 @@ export default class VcdiffPatch extends Patch {
Constants.GLOBAL_TEMP_DIR,
`${path.basename(sourceFilePath)}.vcdiff`,
));
await fsPromises.copyFile(sourceFilePath, targetFilePath);
await util.promisify(fs.copyFile)(sourceFilePath, targetFilePath);
const targetFile = await FilePoly.fileFrom(targetFilePath, 'r+');

const sourceFile = await FilePoly.fileFrom(sourceFilePath, 'r');
Expand Down
5 changes: 3 additions & 2 deletions test/modules/reportGenerator.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import fg from 'fast-glob';
import { promises as fsPromises } from 'fs';
import fs from 'fs';
import path from 'path';
import util from 'util';

import Constants from '../../src/constants.js';
import ReportGenerator from '../../src/modules/reportGenerator.js';
Expand Down Expand Up @@ -66,7 +67,7 @@ async function wrapReportGenerator(
path.dirname(options.getOutputReportPath()),
`${Constants.COMMAND_NAME}_*.csv`,
).replace(/\\/g, '/'))).slice(-1)[0];
const contents = (await fsPromises.readFile(outputReportPath)).toString();
const contents = (await util.promisify(fs.readFile)(outputReportPath)).toString();

await callback(contents);

Expand Down
Loading