cleanup(core): replace fs-extra with node:fs (#28019)

This commit is contained in:
pralkarz 2024-09-25 22:00:39 +02:00 committed by GitHub
parent 37523fa441
commit 7f4c39ead4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
30 changed files with 160 additions and 117 deletions

View File

@ -31,7 +31,7 @@ describe('update-ci-webserver-for-static-serve migration', () => {
}; };
}); });
afterEach(() => { afterAll(() => {
tempFs.reset(); tempFs.reset();
}); });

View File

@ -5,7 +5,15 @@
"overrides": [ "overrides": [
{ {
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"], "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {} "rules": {
"no-restricted-imports": [
"error",
{
"name": "fs-extra",
"message": "Please use equivalent utilities from `node:fs` instead."
}
]
}
}, },
{ {
"files": ["*.ts"], "files": ["*.ts"],

View File

@ -52,7 +52,6 @@
"figures": "3.2.0", "figures": "3.2.0",
"flat": "^5.0.2", "flat": "^5.0.2",
"front-matter": "^4.0.2", "front-matter": "^4.0.2",
"fs-extra": "^11.1.0",
"ignore": "^5.0.4", "ignore": "^5.0.4",
"jest-diff": "^29.4.1", "jest-diff": "^29.4.1",
"jsonc-parser": "3.2.0", "jsonc-parser": "3.2.0",

View File

@ -1,7 +1,13 @@
import { createHash } from 'crypto'; import { createHash } from 'crypto';
import { execSync } from 'node:child_process'; import { execSync } from 'node:child_process';
import { existsSync, readFileSync, statSync, writeFileSync } from 'fs'; import {
import { copySync, ensureDirSync } from 'fs-extra'; cpSync,
existsSync,
mkdirSync,
readFileSync,
statSync,
writeFileSync,
} from 'node:fs';
import * as http from 'http'; import * as http from 'http';
import { minimatch } from 'minimatch'; import { minimatch } from 'minimatch';
import { URL } from 'node:url'; import { URL } from 'node:url';
@ -416,7 +422,7 @@ export async function generateGraph(
if (ext === '.html') { if (ext === '.html') {
const assetsFolder = join(fileFolderPath, 'static'); const assetsFolder = join(fileFolderPath, 'static');
const assets: string[] = []; const assets: string[] = [];
copySync(join(__dirname, '../../core/graph'), assetsFolder, { cpSync(join(__dirname, '../../core/graph'), assetsFolder, {
filter: (_src, dest) => { filter: (_src, dest) => {
const isntHtml = !/index\.html/.test(dest); const isntHtml = !/index\.html/.test(dest);
if (isntHtml && dest.includes('.')) { if (isntHtml && dest.includes('.')) {
@ -424,6 +430,7 @@ export async function generateGraph(
} }
return isntHtml; return isntHtml;
}, },
recursive: true,
}); });
const { projectGraphClientResponse } = const { projectGraphClientResponse } =
@ -457,7 +464,7 @@ export async function generateGraph(
bodyLines: [fileFolderPath, ...assets], bodyLines: [fileFolderPath, ...assets],
}); });
} else if (ext === '.json') { } else if (ext === '.json') {
ensureDirSync(dirname(fullFilePath)); mkdirSync(dirname(fullFilePath), { recursive: true });
const json = await createJsonOutput( const json = await createJsonOutput(
prunedGraph, prunedGraph,

View File

@ -1,5 +1,5 @@
import * as enquirer from 'enquirer'; import * as enquirer from 'enquirer';
import { unlinkSync, writeFileSync } from 'fs-extra'; import { unlinkSync, writeFileSync } from 'node:fs';
import { join } from 'path'; import { join } from 'path';
import { InitArgs } from '../init-v1'; import { InitArgs } from '../init-v1';
import { NxJsonConfiguration } from '../../../config/nx-json'; import { NxJsonConfiguration } from '../../../config/nx-json';

View File

@ -1,4 +1,4 @@
import { removeSync } from 'fs-extra'; import { rmSync } from 'node:fs';
import { readJsonFile, writeJsonFile } from '../../../../utils/fileutils'; import { readJsonFile, writeJsonFile } from '../../../../utils/fileutils';
export function cleanUpFiles(appName: string, isStandalone: boolean) { export function cleanUpFiles(appName: string, isStandalone: boolean) {
@ -21,13 +21,13 @@ export function cleanUpFiles(appName: string, isStandalone: boolean) {
} }
writeJsonFile(projectJsonPath, json); writeJsonFile(projectJsonPath, json);
removeSync('temp-workspace'); rmSync('temp-workspace', { recursive: true, force: true });
if (isStandalone) { if (isStandalone) {
removeSync('babel.config.json'); rmSync('babel.config.json', { recursive: true, force: true });
removeSync('jest.preset.js'); rmSync('jest.preset.js', { recursive: true, force: true });
removeSync('jest.config.ts'); rmSync('jest.config.ts', { recursive: true, force: true });
removeSync('libs'); rmSync('libs', { recursive: true, force: true });
removeSync('tools'); rmSync('tools', { recursive: true, force: true });
} }
} }

View File

@ -1,6 +1,6 @@
import { execSync } from 'child_process'; import { execSync } from 'child_process';
import { copySync, moveSync, readdirSync, removeSync } from 'fs-extra'; import { cpSync, mkdirSync, readdirSync, renameSync, rmSync } from 'node:fs';
import { join } from 'path'; import { dirname, join } from 'path';
import { InitArgs } from '../../init-v1'; import { InitArgs } from '../../init-v1';
import { import {
fileExists, fileExists,
@ -163,7 +163,7 @@ async function reorgnizeWorkspaceStructure(options: NormalizedOptions) {
} }
function createTempWorkspace(options: NormalizedOptions) { function createTempWorkspace(options: NormalizedOptions) {
removeSync('temp-workspace'); rmSync('temp-workspace', { recursive: true, force: true });
execSync( execSync(
`npx ${ `npx ${
@ -184,12 +184,16 @@ function createTempWorkspace(options: NormalizedOptions) {
output.log({ title: '🧹 Clearing unused files' }); output.log({ title: '🧹 Clearing unused files' });
copySync( cpSync(
join('temp-workspace', 'apps', options.reactAppName, 'project.json'), join('temp-workspace', 'apps', options.reactAppName, 'project.json'),
'project.json' 'project.json',
{ recursive: true }
); );
removeSync(join('temp-workspace', 'apps', options.reactAppName)); rmSync(join('temp-workspace', 'apps', options.reactAppName), {
removeSync('node_modules'); recursive: true,
force: true,
});
rmSync('node_modules', { recursive: true, force: true });
} }
function copyPackageJsonDepsFromTempWorkspace() { function copyPackageJsonDepsFromTempWorkspace() {
@ -239,6 +243,13 @@ function overridePackageDeps(
return base; return base;
} }
function moveSync(src: string, dest: string) {
const destParentDir = dirname(dest);
mkdirSync(destParentDir, { recursive: true });
rmSync(dest, { recursive: true, force: true });
return renameSync(src, dest);
}
function moveFilesToTempWorkspace(options: NormalizedOptions) { function moveFilesToTempWorkspace(options: NormalizedOptions) {
output.log({ title: '🚚 Moving your React app in your new Nx workspace' }); output.log({ title: '🚚 Moving your React app in your new Nx workspace' });
@ -267,10 +278,7 @@ function moveFilesToTempWorkspace(options: NormalizedOptions) {
f, f,
options.isStandalone options.isStandalone
? join('temp-workspace', f) ? join('temp-workspace', f)
: join('temp-workspace', 'apps', options.reactAppName, f), : join('temp-workspace', 'apps', options.reactAppName, f)
{
overwrite: true,
}
); );
} catch (error) { } catch (error) {
if (requiredCraFiles.includes(f)) { if (requiredCraFiles.includes(f)) {
@ -331,7 +339,7 @@ function copyFromTempWorkspaceToRoot() {
output.log({ title: '🚚 Folder restructuring.' }); output.log({ title: '🚚 Folder restructuring.' });
readdirSync('temp-workspace').forEach((f) => { readdirSync('temp-workspace').forEach((f) => {
moveSync(join('temp-workspace', f), f, { overwrite: true }); moveSync(join('temp-workspace', f), f);
}); });
} }
@ -345,6 +353,6 @@ function cleanUpUnusedFilesAndAddConfigFiles(options: NormalizedOptions) {
setupTsConfig(options.reactAppName, options.isStandalone); setupTsConfig(options.reactAppName, options.isStandalone);
if (options.isStandalone) { if (options.isStandalone) {
removeSync('apps'); rmSync('apps', { recursive: true, force: true });
} }
} }

View File

@ -1,4 +1,4 @@
import { readFileSync, renameSync } from 'fs-extra'; import { readFileSync, renameSync } from 'node:fs';
import { globWithWorkspaceContext } from '../../../../utils/workspace-context'; import { globWithWorkspaceContext } from '../../../../utils/workspace-context';
import { fileExists } from '../../../../utils/fileutils'; import { fileExists } from '../../../../utils/fileutils';

View File

@ -1,7 +1,6 @@
import * as chalk from 'chalk'; import * as chalk from 'chalk';
import { prompt } from 'enquirer'; import { prompt } from 'enquirer';
import { removeSync } from 'fs-extra'; import { readFileSync, rmSync, writeFileSync } from 'node:fs';
import { readFileSync, writeFileSync } from 'node:fs';
import { ReleaseType, valid } from 'semver'; import { ReleaseType, valid } from 'semver';
import { dirSync } from 'tmp'; import { dirSync } from 'tmp';
import type { DependencyBump } from '../../../release/changelog-renderer'; import type { DependencyBump } from '../../../release/changelog-renderer';
@ -962,7 +961,7 @@ async function applyChangesAndExit(
if (group.resolvedVersionPlans) { if (group.resolvedVersionPlans) {
group.resolvedVersionPlans.forEach((plan) => { group.resolvedVersionPlans.forEach((plan) => {
if (!args.dryRun) { if (!args.dryRun) {
removeSync(plan.absolutePath); rmSync(plan.absolutePath, { recursive: true, force: true });
if (args.verbose) { if (args.verbose) {
console.log(`Removing ${plan.relativePath}`); console.log(`Removing ${plan.relativePath}`);
} }

View File

@ -1,6 +1,6 @@
import { readFileSync, readdirSync } from 'fs';
import { pathExists, stat } from 'fs-extra';
import { exec } from 'node:child_process'; import { exec } from 'node:child_process';
import { existsSync, readFileSync, readdirSync } from 'node:fs';
import { stat } from 'node:fs/promises';
import { join } from 'path'; import { join } from 'path';
import { RELEASE_TYPES, ReleaseType } from 'semver'; import { RELEASE_TYPES, ReleaseType } from 'semver';
import { workspaceRoot } from '../../../utils/workspace-root'; import { workspaceRoot } from '../../../utils/workspace-root';
@ -54,8 +54,7 @@ const versionPlansDirectory = join('.nx', 'version-plans');
export async function readRawVersionPlans(): Promise<RawVersionPlan[]> { export async function readRawVersionPlans(): Promise<RawVersionPlan[]> {
const versionPlansPath = getVersionPlansAbsolutePath(); const versionPlansPath = getVersionPlansAbsolutePath();
const versionPlansPathExists = await pathExists(versionPlansPath); if (!existsSync(versionPlansPath)) {
if (!versionPlansPathExists) {
return []; return [];
} }

View File

@ -1,5 +1,6 @@
import { prompt } from 'enquirer'; import { prompt } from 'enquirer';
import { ensureDir, readFileSync, writeFile, writeFileSync } from 'fs-extra'; import { readFileSync, writeFileSync } from 'node:fs';
import { mkdir, writeFile } from 'node:fs/promises';
import { join } from 'node:path'; import { join } from 'node:path';
import { RELEASE_TYPES } from 'semver'; import { RELEASE_TYPES } from 'semver';
import { dirSync } from 'tmp'; import { dirSync } from 'tmp';
@ -299,7 +300,7 @@ async function createVersionPlanFileForBumps(
printDiff('', versionPlanFileContent, 1); printDiff('', versionPlanFileContent, 1);
const versionPlansAbsolutePath = getVersionPlansAbsolutePath(); const versionPlansAbsolutePath = getVersionPlansAbsolutePath();
await ensureDir(versionPlansAbsolutePath); await mkdir(versionPlansAbsolutePath, { recursive: true });
await writeFile( await writeFile(
join(versionPlansAbsolutePath, versionPlanFileName), join(versionPlansAbsolutePath, versionPlanFileName),
versionPlanFileContent versionPlanFileContent

View File

@ -1,5 +1,5 @@
import { prompt } from 'enquirer'; import { prompt } from 'enquirer';
import { removeSync } from 'fs-extra'; import { rmSync } from 'node:fs';
import { NxReleaseConfiguration, readNxJson } from '../../config/nx-json'; import { NxReleaseConfiguration, readNxJson } from '../../config/nx-json';
import { createProjectFileMapUsingProjectGraph } from '../../project-graph/file-map-utils'; import { createProjectFileMapUsingProjectGraph } from '../../project-graph/file-map-utils';
import { createProjectGraphAsync } from '../../project-graph/project-graph'; import { createProjectGraphAsync } from '../../project-graph/project-graph';
@ -162,7 +162,7 @@ export function createAPI(overrideReleaseConfig: NxReleaseConfiguration) {
} }
group.resolvedVersionPlans.forEach((plan) => { group.resolvedVersionPlans.forEach((plan) => {
if (!args.dryRun) { if (!args.dryRun) {
removeSync(plan.absolutePath); rmSync(plan.absolutePath, { recursive: true, force: true });
if (args.verbose) { if (args.verbose) {
console.log(`Removing ${plan.relativePath}`); console.log(`Removing ${plan.relativePath}`);
} }

View File

@ -1,4 +1,4 @@
import { rmSync } from 'fs-extra'; import { rmSync } from 'node:fs';
import { daemonClient } from '../../daemon/client/client'; import { daemonClient } from '../../daemon/client/client';
import { cacheDir, workspaceDataDirectory } from '../../utils/cache-directory'; import { cacheDir, workspaceDataDirectory } from '../../utils/cache-directory';
import { output } from '../../utils/output'; import { output } from '../../utils/output';

View File

@ -1,12 +1,7 @@
import { import { existsSync, unlinkSync } from 'node:fs';
existsSync,
readJson,
readJsonSync,
unlinkSync,
writeJson,
} from 'fs-extra';
import { join } from 'path'; import { join } from 'path';
import { DAEMON_DIR_FOR_CURRENT_WORKSPACE } from './tmp-dir'; import { DAEMON_DIR_FOR_CURRENT_WORKSPACE } from './tmp-dir';
import { readJsonFile, writeJsonFileAsync } from '../utils/fileutils';
export interface DaemonProcessJson { export interface DaemonProcessJson {
processId: number; processId: number;
@ -17,11 +12,11 @@ export const serverProcessJsonPath = join(
'server-process.json' 'server-process.json'
); );
export async function readDaemonProcessJsonCache(): Promise<DaemonProcessJson | null> { export function readDaemonProcessJsonCache(): DaemonProcessJson | null {
if (!existsSync(serverProcessJsonPath)) { if (!existsSync(serverProcessJsonPath)) {
return null; return null;
} }
return readJsonSync(serverProcessJsonPath); return readJsonFile(serverProcessJsonPath);
} }
export function deleteDaemonJsonProcessCache(): void { export function deleteDaemonJsonProcessCache(): void {
@ -35,11 +30,13 @@ export function deleteDaemonJsonProcessCache(): void {
export async function writeDaemonJsonProcessCache( export async function writeDaemonJsonProcessCache(
daemonJson: DaemonProcessJson daemonJson: DaemonProcessJson
): Promise<void> { ): Promise<void> {
await writeJson(serverProcessJsonPath, daemonJson); await writeJsonFileAsync(serverProcessJsonPath, daemonJson, {
appendNewLine: true,
});
} }
export async function waitForDaemonToExitAndCleanupProcessJson(): Promise<void> { export async function waitForDaemonToExitAndCleanupProcessJson(): Promise<void> {
const daemonProcessJson = await readDaemonProcessJsonCache(); const daemonProcessJson = readDaemonProcessJsonCache();
if (daemonProcessJson && daemonProcessJson.processId) { if (daemonProcessJson && daemonProcessJson.processId) {
await new Promise<void>((resolve, reject) => { await new Promise<void>((resolve, reject) => {
let count = 0; let count = 0;
@ -63,24 +60,13 @@ export async function waitForDaemonToExitAndCleanupProcessJson(): Promise<void>
} }
} }
export async function safelyCleanUpExistingProcess(): Promise<void> {
const daemonProcessJson = await readDaemonProcessJsonCache();
if (daemonProcessJson && daemonProcessJson.processId) {
try {
process.kill(daemonProcessJson.processId);
// we wait for the process to actually shut down before returning
await waitForDaemonToExitAndCleanupProcessJson();
} catch {}
}
}
// Must be sync for the help output use case // Must be sync for the help output use case
export function getDaemonProcessIdSync(): number | null { export function getDaemonProcessIdSync(): number | null {
if (!existsSync(serverProcessJsonPath)) { if (!existsSync(serverProcessJsonPath)) {
return null; return null;
} }
try { try {
const daemonProcessJson = readJsonSync(serverProcessJsonPath); const daemonProcessJson = readJsonFile(serverProcessJsonPath);
return daemonProcessJson.processId; return daemonProcessJson.processId;
} catch { } catch {
return null; return null;

View File

@ -1,8 +1,13 @@
import { workspaceRoot } from '../../utils/workspace-root'; import { workspaceRoot } from '../../utils/workspace-root';
import { ChildProcess, spawn } from 'child_process'; import { ChildProcess, spawn } from 'child_process';
import { readFileSync, statSync } from 'fs'; import {
existsSync,
mkdirSync,
readFileSync,
statSync,
writeFileSync,
} from 'node:fs';
import { FileHandle, open } from 'fs/promises'; import { FileHandle, open } from 'fs/promises';
import { ensureDirSync, ensureFileSync } from 'fs-extra';
import { connect } from 'net'; import { connect } from 'net';
import { join } from 'path'; import { join } from 'path';
import { performance } from 'perf_hooks'; import { performance } from 'perf_hooks';
@ -577,8 +582,10 @@ export class DaemonClient {
} }
async startInBackground(): Promise<ChildProcess['pid']> { async startInBackground(): Promise<ChildProcess['pid']> {
ensureDirSync(DAEMON_DIR_FOR_CURRENT_WORKSPACE); mkdirSync(DAEMON_DIR_FOR_CURRENT_WORKSPACE, { recursive: true });
ensureFileSync(DAEMON_OUTPUT_LOG_FILE); if (!existsSync(DAEMON_OUTPUT_LOG_FILE)) {
writeFileSync(DAEMON_OUTPUT_LOG_FILE, '');
}
this._out = await open(DAEMON_OUTPUT_LOG_FILE, 'a'); this._out = await open(DAEMON_OUTPUT_LOG_FILE, 'a');
this._err = await open(DAEMON_OUTPUT_LOG_FILE, 'a'); this._err = await open(DAEMON_OUTPUT_LOG_FILE, 'a');

View File

@ -3,8 +3,7 @@
* location within the OS's tmp directory where we write log files for background processes * location within the OS's tmp directory where we write log files for background processes
* and where we create the actual unix socket/named pipe for the daemon. * and where we create the actual unix socket/named pipe for the daemon.
*/ */
import { statSync, writeFileSync } from 'fs'; import { mkdirSync, rmSync, statSync, writeFileSync } from 'node:fs';
import { ensureDirSync, rmSync } from 'fs-extra';
import { join } from 'path'; import { join } from 'path';
import { workspaceDataDirectory } from '../utils/cache-directory'; import { workspaceDataDirectory } from '../utils/cache-directory';
import { createHash } from 'crypto'; import { createHash } from 'crypto';
@ -64,7 +63,7 @@ export function getSocketDir(alreadyUnique = false) {
process.env.NX_SOCKET_DIR ?? process.env.NX_SOCKET_DIR ??
process.env.NX_DAEMON_SOCKET_DIR ?? process.env.NX_DAEMON_SOCKET_DIR ??
(alreadyUnique ? tmpdir : socketDirName()); (alreadyUnique ? tmpdir : socketDirName());
ensureDirSync(dir); mkdirSync(dir, { recursive: true });
return dir; return dir;
} catch (e) { } catch (e) {

View File

@ -1,5 +1,11 @@
import { lstatSync, Mode, readFileSync, writeFileSync } from 'fs'; import {
import { removeSync, ensureDirSync } from 'fs-extra'; lstatSync,
mkdirSync,
Mode,
readFileSync,
rmSync,
writeFileSync,
} from 'node:fs';
import { dirSync, file } from 'tmp'; import { dirSync, file } from 'tmp';
import * as path from 'path'; import * as path from 'path';
import { import {
@ -22,7 +28,7 @@ describe('tree', () => {
console.log = jest.fn(); console.log = jest.fn();
dir = dirSync().name; dir = dirSync().name;
ensureDirSync(path.join(dir, 'parent/child')); mkdirSync(path.join(dir, 'parent/child'), { recursive: true });
writeFileSync(path.join(dir, 'root-file.txt'), 'root content'); writeFileSync(path.join(dir, 'root-file.txt'), 'root content');
writeFileSync( writeFileSync(
path.join(dir, 'parent', 'parent-file.txt'), path.join(dir, 'parent', 'parent-file.txt'),
@ -41,7 +47,7 @@ describe('tree', () => {
}); });
afterEach(() => { afterEach(() => {
removeSync(dir); rmSync(dir, { recursive: true, force: true });
}); });
afterAll(() => { afterAll(() => {

View File

@ -1,13 +1,13 @@
import { import {
chmodSync,
mkdirSync,
readdirSync, readdirSync,
readFileSync, readFileSync,
rmSync,
statSync, statSync,
writeFileSync, writeFileSync,
ensureDirSync, } from 'node:fs';
removeSync, import type { Mode } from 'node:fs';
chmodSync,
} from 'fs-extra';
import type { Mode } from 'fs';
import { logger } from '../utils/logger'; import { logger } from '../utils/logger';
import { output } from '../utils/output'; import { output } from '../utils/output';
import { dirname, join, relative, sep } from 'path'; import { dirname, join, relative, sep } from 'path';
@ -437,14 +437,14 @@ export function flushChanges(root: string, fileChanges: FileChange[]): void {
fileChanges.forEach((f) => { fileChanges.forEach((f) => {
const fpath = join(root, f.path); const fpath = join(root, f.path);
if (f.type === 'CREATE') { if (f.type === 'CREATE') {
ensureDirSync(dirname(fpath)); mkdirSync(dirname(fpath), { recursive: true });
writeFileSync(fpath, f.content); writeFileSync(fpath, f.content);
if (f.options?.mode) chmodSync(fpath, f.options.mode); if (f.options?.mode) chmodSync(fpath, f.options.mode);
} else if (f.type === 'UPDATE') { } else if (f.type === 'UPDATE') {
writeFileSync(fpath, f.content); writeFileSync(fpath, f.content);
if (f.options?.mode) chmodSync(fpath, f.options.mode); if (f.options?.mode) chmodSync(fpath, f.options.mode);
} else if (f.type === 'DELETE') { } else if (f.type === 'DELETE') {
removeSync(fpath); rmSync(fpath, { recursive: true, force: true });
} }
}); });
} }

View File

@ -1,17 +1,18 @@
import { dirname, join } from 'path';
import { tmpdir } from 'os';
import { import {
emptyDirSync, appendFileSync,
mkdirpSync, existsSync,
mkdirSync,
mkdtempSync, mkdtempSync,
outputFile,
readFile,
realpathSync, realpathSync,
renameSync,
rmSync, rmSync,
unlinkSync, unlinkSync,
} from 'fs-extra'; writeFileSync,
} from 'node:fs';
import { mkdir, readFile, writeFile } from 'node:fs/promises';
import { dirname, join } from 'path';
import { tmpdir } from 'os';
import { joinPathFragments } from '../utils/path'; import { joinPathFragments } from '../utils/path';
import { appendFileSync, existsSync, renameSync, writeFileSync } from 'fs';
import { setWorkspaceRoot, workspaceRoot } from '../utils/workspace-root'; import { setWorkspaceRoot, workspaceRoot } from '../utils/workspace-root';
type NestedFiles = { type NestedFiles = {
@ -47,13 +48,17 @@ export class TempFs {
} }
async createFile(filePath: string, content: string) { async createFile(filePath: string, content: string) {
await outputFile(joinPathFragments(this.tempDir, filePath), content); const dir = joinPathFragments(this.tempDir, dirname(filePath));
if (!existsSync(dir)) {
await mkdir(dir, { recursive: true });
}
await writeFile(joinPathFragments(this.tempDir, filePath), content);
} }
createFileSync(filePath: string, content: string) { createFileSync(filePath: string, content: string) {
let dir = joinPathFragments(this.tempDir, dirname(filePath)); let dir = joinPathFragments(this.tempDir, dirname(filePath));
if (!existsSync(dir)) { if (!existsSync(dir)) {
mkdirpSync(dir); mkdirSync(dir, { recursive: true });
} }
writeFileSync(joinPathFragments(this.tempDir, filePath), content); writeFileSync(joinPathFragments(this.tempDir, filePath), content);
} }
@ -81,11 +86,12 @@ export class TempFs {
} }
cleanup() { cleanup() {
rmSync(this.tempDir, { recursive: true }); rmSync(this.tempDir, { recursive: true, force: true });
setWorkspaceRoot(this.previousWorkspaceRoot); setWorkspaceRoot(this.previousWorkspaceRoot);
} }
reset() { reset() {
emptyDirSync(this.tempDir); rmSync(this.tempDir, { recursive: true, force: true });
mkdirSync(this.tempDir, { recursive: true });
} }
} }

View File

@ -1,7 +1,7 @@
import { mkdtemp, writeFile } from 'node:fs/promises';
import { hashArray, hashFile } from '../index'; import { hashArray, hashFile } from '../index';
import { tmpdir } from 'os'; import { tmpdir } from 'os';
import { mkdtemp, writeFile } from 'fs-extra';
import { join } from 'path'; import { join } from 'path';
describe('hasher', () => { describe('hasher', () => {

View File

@ -1,5 +1,4 @@
import { readFileSync, writeFileSync } from 'fs'; import { readFileSync, mkdirSync, writeFileSync } from 'fs';
import { ensureDirSync } from 'fs-extra';
import { dirname, join } from 'path'; import { dirname, join } from 'path';
import { performance } from 'perf_hooks'; import { performance } from 'perf_hooks';
import { ProjectGraph } from '../../config/project-graph'; import { ProjectGraph } from '../../config/project-graph';
@ -153,7 +152,7 @@ function writeLastProcessedLockfileHash(
hash: string, hash: string,
lockFile: ParsedLockFile lockFile: ParsedLockFile
) { ) {
ensureDirSync(dirname(lockFileHashFile)); mkdirSync(dirname(lockFileHashFile), { recursive: true });
writeFileSync(cachedParsedLockFile, JSON.stringify(lockFile, null, 2)); writeFileSync(cachedParsedLockFile, JSON.stringify(lockFile, null, 2));
writeFileSync(lockFileHashFile, hash); writeFileSync(lockFileHashFile, hash);
} }

View File

@ -1,5 +1,4 @@
import { existsSync } from 'fs'; import { existsSync, mkdirSync, renameSync } from 'node:fs';
import { ensureDirSync, renameSync } from 'fs-extra';
import { join } from 'path'; import { join } from 'path';
import { performance } from 'perf_hooks'; import { performance } from 'perf_hooks';
import { NxJsonConfiguration, PluginConfiguration } from '../config/nx-json'; import { NxJsonConfiguration, PluginConfiguration } from '../config/nx-json';
@ -39,7 +38,7 @@ export const nxFileMap = join(workspaceDataDirectory, 'file-map.json');
export function ensureCacheDirectory(): void { export function ensureCacheDirectory(): void {
try { try {
if (!existsSync(workspaceDataDirectory)) { if (!existsSync(workspaceDataDirectory)) {
ensureDirSync(workspaceDataDirectory); mkdirSync(workspaceDataDirectory, { recursive: true });
} }
} catch (e) { } catch (e) {
/* /*

View File

@ -1,5 +1,4 @@
import { workspaceRoot } from '../utils/workspace-root'; import { workspaceRoot } from '../utils/workspace-root';
import { mkdir, mkdirSync, pathExists, readFile, writeFile } from 'fs-extra';
import { join } from 'path'; import { join } from 'path';
import { performance } from 'perf_hooks'; import { performance } from 'perf_hooks';
import { import {
@ -8,6 +7,8 @@ import {
RemoteCacheV2, RemoteCacheV2,
} from './default-tasks-runner'; } from './default-tasks-runner';
import { spawn } from 'child_process'; import { spawn } from 'child_process';
import { existsSync, mkdirSync } from 'node:fs';
import { mkdir, readFile, writeFile } from 'node:fs/promises';
import { cacheDir } from '../utils/cache-directory'; import { cacheDir } from '../utils/cache-directory';
import { Task } from '../config/task-graph'; import { Task } from '../config/task-graph';
import { machineId } from 'node-machine-id'; import { machineId } from 'node-machine-id';
@ -288,7 +289,7 @@ export class Cache {
await this.remove(tdCommit); await this.remove(tdCommit);
await this.remove(td); await this.remove(td);
await mkdir(td); await mkdir(td, { recursive: true });
await writeFile( await writeFile(
join(td, 'terminalOutput'), join(td, 'terminalOutput'),
terminalOutput ?? 'no terminal output' terminalOutput ?? 'no terminal output'
@ -300,7 +301,7 @@ export class Cache {
await Promise.all( await Promise.all(
expandedOutputs.map(async (f) => { expandedOutputs.map(async (f) => {
const src = join(this.root, f); const src = join(this.root, f);
if (await pathExists(src)) { if (existsSync(src)) {
const cached = join(td, 'outputs', f); const cached = join(td, 'outputs', f);
await this.copy(src, cached); await this.copy(src, cached);
} }
@ -338,7 +339,7 @@ export class Cache {
await Promise.all( await Promise.all(
expandedOutputs.map(async (f) => { expandedOutputs.map(async (f) => {
const cached = join(cachedResult.outputsPath, f); const cached = join(cachedResult.outputsPath, f);
if (await pathExists(cached)) { if (existsSync(cached)) {
const src = join(this.root, f); const src = join(this.root, f);
await this.remove(src); await this.remove(src);
await this.copy(cached, src); await this.copy(cached, src);
@ -413,7 +414,7 @@ export class Cache {
const tdCommit = join(this.cachePath, `${task.hash}.commit`); const tdCommit = join(this.cachePath, `${task.hash}.commit`);
const td = join(this.cachePath, task.hash); const td = join(this.cachePath, task.hash);
if (await pathExists(tdCommit)) { if (existsSync(tdCommit)) {
const terminalOutput = await readFile( const terminalOutput = await readFile(
join(td, 'terminalOutput'), join(td, 'terminalOutput'),
'utf-8' 'utf-8'

View File

@ -1,5 +1,4 @@
import { readdirSync, statSync } from 'fs'; import { readdirSync, rmSync, statSync } from 'fs';
import { removeSync } from 'fs-extra';
import { join } from 'path'; import { join } from 'path';
const WEEK_IN_MS = 1000 * 60 * 60 * 24 * 7; const WEEK_IN_MS = 1000 * 60 * 60 * 24 * 7;
@ -39,10 +38,10 @@ function removeOld(records: string[]) {
if (time - s.mtimeMs > WEEK_IN_MS) { if (time - s.mtimeMs > WEEK_IN_MS) {
if (s.isDirectory()) { if (s.isDirectory()) {
try { try {
removeSync(`${r}.commit`); rmSync(`${r}.commit`, { recursive: true, force: true });
} catch (e) {} } catch (e) {}
} }
removeSync(r); rmSync(r, { recursive: true, force: true });
} }
} catch (e) {} } catch (e) {}
}); });

View File

@ -8,7 +8,6 @@ import {
makeAcyclic, makeAcyclic,
validateNoAtomizedTasks, validateNoAtomizedTasks,
} from './task-graph-utils'; } from './task-graph-utils';
import { ensureDirSync, removeSync, writeFileSync } from 'fs-extra';
import { tmpdir } from 'os'; import { tmpdir } from 'os';
import { workspaceRoot } from '../utils/workspace-root'; import { workspaceRoot } from '../utils/workspace-root';
import { cacheDir } from '../utils/cache-directory'; import { cacheDir } from '../utils/cache-directory';

View File

@ -1,7 +1,7 @@
import { fs } from 'memfs'; import { fs } from 'memfs';
import { createDirectory, isRelativePath } from './fileutils'; import { createDirectory, isRelativePath } from './fileutils';
jest.mock('fs', () => fs); jest.mock('node:fs', () => fs);
describe('fileutils', () => { describe('fileutils', () => {
describe(createDirectory.name, () => { describe(createDirectory.name, () => {

View File

@ -9,7 +9,8 @@ import {
mkdirSync, mkdirSync,
statSync, statSync,
existsSync, existsSync,
} from 'fs'; } from 'node:fs';
import { mkdir, readFile, writeFile } from 'node:fs/promises';
import { dirname } from 'path'; import { dirname } from 'path';
import * as tar from 'tar-stream'; import * as tar from 'tar-stream';
import { createGunzip } from 'zlib'; import { createGunzip } from 'zlib';
@ -95,6 +96,26 @@ export function writeJsonFile<T extends object = object>(
writeFileSync(path, content, { encoding: 'utf-8' }); writeFileSync(path, content, { encoding: 'utf-8' });
} }
/**
* Serializes the given data to JSON and writes it to a file asynchronously.
*
* @param path A path to a file.
* @param data data which should be serialized to JSON and written to the file
* @param options JSON serialize options
*/
export async function writeJsonFileAsync<T extends object = object>(
path: string,
data: T,
options?: JsonWriteOptions
): Promise<void> {
await mkdir(dirname(path), { recursive: true });
const serializedJson = serializeJson(data, options);
const content = options?.appendNewLine
? `${serializedJson}\n`
: serializedJson;
await writeFile(path, content, { encoding: 'utf-8' });
}
/** /**
* Check if a directory exists * Check if a directory exists
* @param path Path to directory * @param path Path to directory

View File

@ -1,4 +1,4 @@
import { readFileSync } from 'fs-extra'; import { readFileSync } from 'node:fs';
import ignore from 'ignore'; import ignore from 'ignore';
import { readFileIfExisting } from './fileutils'; import { readFileIfExisting } from './fileutils';
import { joinPathFragments } from './path'; import { joinPathFragments } from './path';

View File

@ -1,6 +1,6 @@
import { exec, execSync } from 'child_process'; import { exec, execSync } from 'child_process';
import { copyFileSync, existsSync, writeFileSync } from 'fs'; import { copyFileSync, existsSync, writeFileSync } from 'fs';
import { remove } from 'fs-extra'; import { rm } from 'node:fs/promises';
import { dirname, join, relative } from 'path'; import { dirname, join, relative } from 'path';
import { gte, lt } from 'semver'; import { gte, lt } from 'semver';
import { dirSync } from 'tmp'; import { dirSync } from 'tmp';
@ -351,7 +351,7 @@ export function createTempNpmDirectory() {
const cleanup = async () => { const cleanup = async () => {
try { try {
await remove(dir); await rm(dir, { recursive: true, force: true });
} catch { } catch {
// It's okay if this fails, the OS will clean it up eventually // It's okay if this fails, the OS will clean it up eventually
} }

View File

@ -1,7 +1,7 @@
import { fs } from 'memfs'; import { fs } from 'memfs';
import { createDirectory, isRelativePath } from './fileutils'; import { createDirectory, isRelativePath } from './fileutils';
jest.mock('fs', () => fs); jest.mock('node:fs', () => fs);
describe('fileutils', () => { describe('fileutils', () => {
describe(createDirectory.name, () => { describe(createDirectory.name, () => {