From 7cdb87eb192bc932ddb07a723aa3292c08606bf8 Mon Sep 17 00:00:00 2001 From: "anirudh.bharti" Date: Tue, 17 Sep 2024 07:03:44 -0700 Subject: [PATCH] chore: replace mkdirp with mkdir fs (#46388) Summary: This pull request replaces the use of mkdirp with Node.js's built-in fs.mkdirSync({ recursive: true }) function, which is available in Node.js version 10.12.0 and above. This change reduces the number of external dependencies and simplifies the codebase by using the native capabilities of Node.js. The motivation behind this change is to remove the unnecessary mkdirp dependency, as Node.js natively supports recursive directory creation since version 10.12.0. This streamlines the code and reduces the reliance on external libraries. ## Changelog: [INTERNAL] [REMOVED] - Replaced mkdirp with fs.mkdirSync({ recursive: true }) in build scripts and codegen. Requires Node.js 10.12.0 and above. Pull Request resolved: https://github.com/facebook/react-native/pull/46388 Test Plan: I ran the build and codegen scripts locally with Node.js version 10.12.0 and above after replacing mkdirp, ensuring the scripts work as expected. No issues were encountered, and all processes, including directory creation and file handling, function correctly. Reviewed By: cortinico Differential Revision: D62852488 Pulled By: huntie fbshipit-source-id: 76f44102a80b499521c156308d276a17d279ce38 --- flow-typed/npm/mkdirp_v0.5.x.js | 18 ---------- package.json | 1 - packages/react-native-codegen/package.json | 1 - .../react-native-codegen/scripts/build.js | 4 +-- .../src/cli/generators/generate-all.js | 3 +- packages/react-native/package.json | 1 - .../generate-specs-cli-executor-test.js | 34 ++++++------------- .../codegen/generate-artifacts-executor.js | 3 +- .../codegen/generate-specs-cli-executor.js | 5 ++- .../scripts/generate-provider-cli.js | 3 +- scripts/__tests__/scm-utils-test.js | 10 +++--- scripts/scm-utils.js | 3 +- 12 files changed, 23 insertions(+), 63 deletions(-) delete mode 100644 flow-typed/npm/mkdirp_v0.5.x.js diff --git a/flow-typed/npm/mkdirp_v0.5.x.js b/flow-typed/npm/mkdirp_v0.5.x.js deleted file mode 100644 index 79522197f96..00000000000 --- a/flow-typed/npm/mkdirp_v0.5.x.js +++ /dev/null @@ -1,18 +0,0 @@ -// flow-typed signature: b1b274e8ae71623bf11c20224c446842 -// flow-typed version: c6154227d1/mkdirp_v0.5.x/flow_>=v0.104.x - -declare module 'mkdirp' { - declare type Options = number | { - mode?: number, - fs?: mixed, - ... - }; - - declare type Callback = (err: ?Error, path: ?string) => void; - - declare module.exports: { - (path: string, options?: Options | Callback, callback?: Callback): void, - sync(path: string, options?: Options): void, - ... - }; -} diff --git a/package.json b/package.json index 94254be159f..a189e26f75d 100644 --- a/package.json +++ b/package.json @@ -89,7 +89,6 @@ "metro-babel-register": "^0.80.10", "metro-memory-fs": "^0.80.10", "micromatch": "^4.0.4", - "mkdirp": "^0.5.1", "node-fetch": "^2.2.0", "nullthrows": "^1.1.1", "prettier": "2.8.8", diff --git a/packages/react-native-codegen/package.json b/packages/react-native-codegen/package.json index f1751461542..dc1de6cdf09 100644 --- a/packages/react-native-codegen/package.json +++ b/packages/react-native-codegen/package.json @@ -34,7 +34,6 @@ "hermes-parser": "0.23.1", "invariant": "^2.2.4", "jscodeshift": "^0.14.0", - "mkdirp": "^0.5.1", "nullthrows": "^1.1.1", "yargs": "^17.6.2" }, diff --git a/packages/react-native-codegen/scripts/build.js b/packages/react-native-codegen/scripts/build.js index a8a34a61fba..249b2b9401d 100644 --- a/packages/react-native-codegen/scripts/build.js +++ b/packages/react-native-codegen/scripts/build.js @@ -27,7 +27,6 @@ const chalk = require('chalk'); const fs = require('fs'); const glob = require('glob'); const micromatch = require('micromatch'); -const mkdirp = require('mkdirp'); const path = require('path'); const prettier = require('prettier'); const prettierConfig = JSON.parse( @@ -60,7 +59,8 @@ function getBuildPath(file, buildFolder) { function buildFile(file, silent) { const destPath = getBuildPath(file, BUILD_DIR); - mkdirp.sync(path.dirname(destPath)); + fs.mkdirSync(path.dirname(destPath), {recursive: true}); + if (micromatch.isMatch(file, IGNORE_PATTERN)) { silent || process.stdout.write( diff --git a/packages/react-native-codegen/src/cli/generators/generate-all.js b/packages/react-native-codegen/src/cli/generators/generate-all.js index 46d20751020..2f4482be45e 100644 --- a/packages/react-native-codegen/src/cli/generators/generate-all.js +++ b/packages/react-native-codegen/src/cli/generators/generate-all.js @@ -16,7 +16,6 @@ const RNCodegen = require('../../generators/RNCodegen.js'); const fs = require('fs'); -const mkdirp = require('mkdirp'); const args = process.argv.slice(2); if (args.length < 3) { @@ -39,7 +38,7 @@ if (schemaText == null) { throw new Error(`Can't find schema at ${schemaPath}`); } -mkdirp.sync(outputDirectory); +fs.mkdirSync(outputDirectory, {recursive: true}); let schema; try { diff --git a/packages/react-native/package.json b/packages/react-native/package.json index bd1af9b82c5..898b5d2e68e 100644 --- a/packages/react-native/package.json +++ b/packages/react-native/package.json @@ -132,7 +132,6 @@ "memoize-one": "^5.0.0", "metro-runtime": "^0.81.0-alpha.0", "metro-source-map": "^0.81.0-alpha.0", - "mkdirp": "^0.5.1", "nullthrows": "^1.1.1", "pretty-format": "^29.7.0", "promise": "^8.3.0", diff --git a/packages/react-native/scripts/codegen/__tests__/generate-specs-cli-executor-test.js b/packages/react-native/scripts/codegen/__tests__/generate-specs-cli-executor-test.js index dc0d2a5eaba..4e221f3b6a8 100644 --- a/packages/react-native/scripts/codegen/__tests__/generate-specs-cli-executor-test.js +++ b/packages/react-native/scripts/codegen/__tests__/generate-specs-cli-executor-test.js @@ -19,40 +19,23 @@ describe('generateSpec', () => { const platform = 'ios'; const libraryType = 'all'; const schemaPath = './'; - const componentsOutputDir = normalize( - 'app/ios/build/generated/ios/react/renderer/components/library', - ); - const modulesOutputDir = normalize('app/ios/build/generated/ios/library'); const outputDirectory = normalize('app/ios/build/generated/ios'); const libraryName = 'library'; const packageName = 'com.library'; const generators = ['componentsIOS', 'modulesIOS', 'modulesCxx']; + // Create a mock for fs.mkdirSync + const mkdirSyncMock = jest.fn(); + jest.mock('fs', () => ({ readFileSync: (path, encoding) => { expect(path).toBe(schemaPath); expect(encoding).toBe('utf-8'); return fixtures.schemaText; }, - })); - - let mkdirpSyncInvoked = 0; - jest.mock('mkdirp', () => ({ - sync: folder => { - if (mkdirpSyncInvoked === 0) { - expect(folder).toBe(outputDirectory); - } - - if (mkdirpSyncInvoked === 1) { - expect(folder).toBe(componentsOutputDir); - } - - if (mkdirpSyncInvoked === 2) { - expect(folder).toBe(modulesOutputDir); - } - - mkdirpSyncInvoked += 1; - }, + mkdirSync: mkdirSyncMock, // Use the mock for mkdirSync + readdirSync: jest.fn().mockReturnValue([]), + renameSync: jest.fn(), })); // We cannot mock directly the `RNCodegen` object because the @@ -83,6 +66,9 @@ describe('generateSpec', () => { libraryType, ); - expect(mkdirpSyncInvoked).toBe(1); + expect(mkdirSyncMock).toHaveBeenCalledTimes(1); + expect(mkdirSyncMock).toHaveBeenCalledWith(outputDirectory, { + recursive: true, + }); }); }); diff --git a/packages/react-native/scripts/codegen/generate-artifacts-executor.js b/packages/react-native/scripts/codegen/generate-artifacts-executor.js index 50717a825e1..ed8d1f718b4 100644 --- a/packages/react-native/scripts/codegen/generate-artifacts-executor.js +++ b/packages/react-native/scripts/codegen/generate-artifacts-executor.js @@ -21,7 +21,6 @@ const generateSpecsCLIExecutor = require('./generate-specs-cli-executor'); const {execSync} = require('child_process'); const fs = require('fs'); const glob = require('glob'); -const mkdirp = require('mkdirp'); const os = require('os'); const path = require('path'); @@ -513,7 +512,7 @@ function createComponentProvider(schemas, supportedApplePlatforms) { 'React', 'Fabric', ); - mkdirp.sync(outputDir); + fs.mkdirSync(outputDir, {recursive: true}); utils.getCodegen().generateFromSchemas( { schemas: schemas, diff --git a/packages/react-native/scripts/codegen/generate-specs-cli-executor.js b/packages/react-native/scripts/codegen/generate-specs-cli-executor.js index c0e9ef183d3..daae945a196 100644 --- a/packages/react-native/scripts/codegen/generate-specs-cli-executor.js +++ b/packages/react-native/scripts/codegen/generate-specs-cli-executor.js @@ -11,7 +11,6 @@ const utils = require('./codegen-utils'); const fs = require('fs'); -const mkdirp = require('mkdirp'); const path = require('path'); const GENERATORS = { @@ -33,7 +32,7 @@ function createOutputDirectoryIfNeeded(outputDirectory, libraryName) { if (!outputDirectory) { outputDirectory = path.resolve(__dirname, '..', 'Libraries', libraryName); } - mkdirp.sync(outputDirectory); + fs.mkdirSync(outputDirectory, {recursive: true}); } /** @@ -95,7 +94,7 @@ function generateSpecFromInMemorySchema( // * this subdir structure is Android-only, not applicable to iOS const files = fs.readdirSync(outputDirectory); const jniOutputDirectory = `${outputDirectory}/jni/react/renderer/components/${libraryName}`; - mkdirp.sync(jniOutputDirectory); + fs.mkdirSync(jniOutputDirectory, {recursive: true}); files .filter(f => f.endsWith('.h') || f.endsWith('.cpp')) .forEach(f => { diff --git a/packages/react-native/scripts/generate-provider-cli.js b/packages/react-native/scripts/generate-provider-cli.js index 22afb409405..22141ce8b7e 100644 --- a/packages/react-native/scripts/generate-provider-cli.js +++ b/packages/react-native/scripts/generate-provider-cli.js @@ -11,7 +11,6 @@ const utils = require('./codegen/codegen-utils'); const fs = require('fs'); -const mkdirp = require('mkdirp'); const yargs = require('yargs'); const argv = yargs @@ -49,7 +48,7 @@ function generateProvider(platform, schemaListPath, outputDirectory) { if (!outputDirectory) { throw new Error('outputDir is required'); } - mkdirp.sync(outputDirectory); + fs.mkdirSync(outputDirectory, {recursive: true}); let schemaPaths; try { diff --git a/scripts/__tests__/scm-utils-test.js b/scripts/__tests__/scm-utils-test.js index e1c000eaaad..83b553cd3e7 100644 --- a/scripts/__tests__/scm-utils-test.js +++ b/scripts/__tests__/scm-utils-test.js @@ -11,7 +11,7 @@ const {isTaggedLatest, revertFiles, saveFiles} = require('../scm-utils'); let execResult = null; const cpMock = jest.fn(); -const mkdirpSyncMock = jest.fn(); +const mkdirSyncMock = jest.fn(); jest .mock('shelljs', () => ({ exec: () => { @@ -29,6 +29,7 @@ jest })) .mock('fs', () => ({ existsSync: jest.fn().mockImplementation(_ => true), + mkdirSync: mkdirSyncMock, })) .mock('path', () => ({ dirname: jest @@ -36,9 +37,6 @@ jest .mockImplementation(filePath => filePath.includes('/') ? filePath.split('/')[0] : '.', ), - })) - .mock('mkdirp', () => ({ - sync: mkdirpSyncMock, })); describe('scm-utils', () => { @@ -64,7 +62,9 @@ describe('scm-utils', () => { it('it should save files in the temp folder', () => { const tmpFolder = '/tmp'; saveFiles(['package.json', 'android/package.json'], tmpFolder); - expect(mkdirpSyncMock).toHaveBeenCalledWith(`${tmpFolder}/android`); + expect(mkdirSyncMock).toHaveBeenCalledWith(`${tmpFolder}/android`, { + recursive: true, + }); expect(cpMock).toHaveBeenNthCalledWith( 1, 'package.json', diff --git a/scripts/scm-utils.js b/scripts/scm-utils.js index 2e7b228716b..f9b0474e7c8 100644 --- a/scripts/scm-utils.js +++ b/scripts/scm-utils.js @@ -11,7 +11,6 @@ 'use strict'; const fs = require('fs'); -const mkdirp = require('mkdirp'); const path = require('path'); const {cp, echo, exec, exit} = require('shelljs'); @@ -75,7 +74,7 @@ function saveFiles(filePaths /*: Array */, tmpFolder /*: string */) { const dirName = path.dirname(filePath); if (dirName !== '.') { const destFolder = `${tmpFolder}/${dirName}`; - mkdirp.sync(destFolder); + fs.mkdirSync(destFolder, {recursive: true}); } cp(filePath, `${tmpFolder}/${filePath}`); }