diff --git a/.changeset/clever-worms-juggle.md b/.changeset/clever-worms-juggle.md new file mode 100644 index 0000000000..18f3b3f8fe --- /dev/null +++ b/.changeset/clever-worms-juggle.md @@ -0,0 +1,10 @@ +--- +"@commercetools-frontend/application-config": patch +"@commercetools-frontend/codemod": patch +"@commercetools-frontend/create-mc-app": patch +"@commercetools-frontend/cypress": patch +"@commercetools-frontend/l10n": patch +"@commercetools-frontend/mc-scripts": patch +--- + +Replace fs.exists with fs.access diff --git a/packages/application-config/src/load-config.ts b/packages/application-config/src/load-config.ts index 39bf1b750c..86fcc72abc 100644 --- a/packages/application-config/src/load-config.ts +++ b/packages/application-config/src/load-config.ts @@ -6,11 +6,19 @@ import { MissingOrInvalidConfigError } from './errors'; import type { JSONSchemaForCustomApplicationConfigurationFiles } from './schemas/generated/custom-application.schema'; import type { JSONSchemaForCustomViewConfigurationFiles } from './schemas/generated/custom-view.schema'; +function doesFileExist(path: string): boolean { + try { + fs.accessSync(path); + return true; + } catch (error) { + return false; + } +} // Helper function to find the package root path from the current location, // for instance in respect to both source files and dist files. const findPackageRootPath = (dir: string): string => { const packageJsonPath = path.join(dir, 'package.json'); - if (fs.existsSync(packageJsonPath)) { + if (doesFileExist(packageJsonPath)) { return dir; } const parentDir = path.join(dir, '..'); diff --git a/packages/codemod/test/transforms.spec.ts b/packages/codemod/test/transforms.spec.ts index d8b1b62bb2..48f53d809d 100644 --- a/packages/codemod/test/transforms.spec.ts +++ b/packages/codemod/test/transforms.spec.ts @@ -8,6 +8,15 @@ import { runSnapshotTest } from 'jscodeshift/dist/testUtils'; const fixturesPath = path.join(__dirname, 'fixtures'); +const doesFileExist = (filePath: string): boolean => { + try { + fs.accessSync(filePath); + return true; + } catch (e) { + return false; + } +}; + describe.each` transformName | fixtureName ${'remove-deprecated-modal-level-props'} | ${'remove-deprecated-modal-level-props.tsx'} @@ -25,13 +34,13 @@ describe.each` beforeEach(() => { switch (transformName) { case 'rename-js-to-jsx': - if (!fs.existsSync(inputPath)) { + if (!doesFileExist(inputPath)) { fs.writeFileSync(inputPath, '/* Generated */\nexport {};'); } break; case 'rename-mod-css-to-module-css': const stylesFilePath = path.join(fixturesPath, 'styles.mod.css'); - if (!fs.existsSync(stylesFilePath)) { + if (!doesFileExist(stylesFilePath)) { fs.writeFileSync( stylesFilePath, '/* Generated */\nbody { font-size: 1rem; }' diff --git a/packages/create-mc-app/src/tasks/download-template.ts b/packages/create-mc-app/src/tasks/download-template.ts index 9405e48ccc..296509e3cb 100644 --- a/packages/create-mc-app/src/tasks/download-template.ts +++ b/packages/create-mc-app/src/tasks/download-template.ts @@ -1,10 +1,10 @@ -import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; import execa from 'execa'; import { Listr, type ListrTask } from 'listr2'; import { applicationTypes } from '../constants'; import type { TCliTaskOptions } from '../types'; +import { doesFileExist } from '../utils'; import { throwIfTemplateVersionDoesNotExist } from '../validations'; const filesToBeRemoved = ['CHANGELOG.md']; @@ -91,7 +91,7 @@ function downloadTemplate(options: TCliTaskOptions): ListrTask { options.projectDirectoryPath, 'package.json' ); - if (!fs.existsSync(templatePackageJsonPath)) { + if (!doesFileExist(templatePackageJsonPath)) { throw new Error( `Unable to verify that the template application has a package.json at "${templatePackageJsonPath}"` ); diff --git a/packages/create-mc-app/src/utils.ts b/packages/create-mc-app/src/utils.ts index 9f101bf0c7..3a1a625db8 100644 --- a/packages/create-mc-app/src/utils.ts +++ b/packages/create-mc-app/src/utils.ts @@ -8,6 +8,15 @@ import type { const isSemVer = (version: string) => /^(v?)([0-9].[0-9].[0-9])+/.test(version); +const doesFileExist = (path: string): boolean => { + try { + fs.accessSync(path); + return true; + } catch (error) { + return false; + } +}; + const shouldUseYarn = () => { try { const result = execa.commandSync('yarn --version', { stdio: 'ignore' }); @@ -56,7 +65,7 @@ const wordify = (slug: string) => const resolveFilePathByExtension = (requestedModule: string) => { const fileExtension = ['.js', '.ts', '.mjs', '.cjs'].find((ext) => { const filePath = `${requestedModule}${ext}`; - return fs.existsSync(filePath); + return doesFileExist(filePath); }); return `${requestedModule}${fileExtension}`; }; @@ -74,4 +83,5 @@ export { getPreferredPackageManager, getInstallCommand, isCustomView, + doesFileExist, }; diff --git a/packages/create-mc-app/src/validations.ts b/packages/create-mc-app/src/validations.ts index bf36edbade..dfd8b24c0f 100644 --- a/packages/create-mc-app/src/validations.ts +++ b/packages/create-mc-app/src/validations.ts @@ -3,7 +3,7 @@ import path from 'node:path'; import semver from 'semver'; import { applicationTypes, availableTemplates } from './constants'; import type { TApplicationType, TTemplate } from './types'; -import { isSemVer } from './utils'; +import { isSemVer, doesFileExist } from './utils'; const throwIfApplicationTypeIsNotSupported = ( applicationType: TApplicationType @@ -31,7 +31,7 @@ const throwIfTemplateIsNotSupported = (templateName: TTemplate) => { }; const throwIfProjectDirectoryExists = (dirName: string, dirPath: string) => { - if (fs.existsSync(dirPath)) { + if (doesFileExist(dirPath)) { throw new Error( `A directory named "${dirName}" already exists at this location "${dirPath}". Please choose a different project name or remove the directory, then try running the command again.` ); @@ -43,7 +43,7 @@ const throwIfTemplateVersionDoesNotExist = ( templateFolderPath: string, versionToCheck: string ) => { - if (!fs.existsSync(templateFolderPath)) { + if (!doesFileExist(templateFolderPath)) { throw new Error( `The downloaded template "${templateName}" does not exist for the given version "${versionToCheck}". Check the releases page if you are looking for a specific version: https://github.com/commercetools/merchant-center-application-kit/releases` ); diff --git a/packages/cypress/src/task/index.ts b/packages/cypress/src/task/index.ts index d70dab1965..b34f260799 100644 --- a/packages/cypress/src/task/index.ts +++ b/packages/cypress/src/task/index.ts @@ -8,6 +8,15 @@ import { } from '@commercetools-frontend/application-config'; import { CUSTOM_VIEW_HOST_ENTRY_POINT_URI_PATH } from '@commercetools-frontend/constants'; +function doesFileExist(path: string): boolean { + try { + fs.accessSync(path); + return true; + } catch (error) { + return false; + } +} + type CustomEntityConfigTaskOptions = { entryPointUriPath: string; dotfiles?: string[]; @@ -27,7 +36,7 @@ const loadEnvironmentVariables = ( return dotfiles.reduce((mergedEnvs, dotfile) => { const envPath = path.join(packageDirPath, dotfile); - if (!fs.existsSync(envPath)) { + if (!doesFileExist(envPath)) { return mergedEnvs; } diff --git a/packages/l10n/scripts/generate-l10n-data.js b/packages/l10n/scripts/generate-l10n-data.js index 152a565858..77103b08c5 100644 --- a/packages/l10n/scripts/generate-l10n-data.js +++ b/packages/l10n/scripts/generate-l10n-data.js @@ -17,6 +17,15 @@ const parseUnhandledTimeZones = require('./parse-unhandled-time-zones'); const prettierConfig = prettier.resolveConfig.sync(); +const doesFileExist = (filePath) => { + try { + fs.accessSync(filePath); + return true; + } catch (e) { + return false; + } +}; + const L10N_KEYS = { COUNTRY: 'country', CURRENCY: 'currency', @@ -350,7 +359,7 @@ function getUnhandledTimeZoneIds( } function ensureDirectoryExists(dir) { - if (!fs.existsSync(dir)) { + if (!doesFileExist(dir)) { fs.mkdirSync(dir, { recursive: true, }); diff --git a/packages/mc-scripts/src/cli.ts b/packages/mc-scripts/src/cli.ts index 5a859a41a2..aed3761967 100755 --- a/packages/mc-scripts/src/cli.ts +++ b/packages/mc-scripts/src/cli.ts @@ -10,6 +10,7 @@ import type { TCliCommandCompileHtmlOptions, TCliCommandConfigSyncOptions, } from './types'; +import doesFileExist from './utils/does-file-exist'; const cli = cac('mc-scripts'); @@ -241,7 +242,7 @@ function loadDotEnvFiles(globalOptions: TCliGlobalOptions) { const dotenvFilePath = path.resolve( path.join(applicationDirectory, dotenvFile) ); - if (fs.existsSync(dotenvFilePath)) { + if (doesFileExist(dotenvFilePath)) { dotenvExpand.expand(dotenv.config({ path: dotenvFilePath })); } }); diff --git a/packages/mc-scripts/src/commands/build.ts b/packages/mc-scripts/src/commands/build.ts index 3c8422b131..dd91ec4e28 100644 --- a/packages/mc-scripts/src/commands/build.ts +++ b/packages/mc-scripts/src/commands/build.ts @@ -9,6 +9,7 @@ import webpack, { type Configuration, type Stats } from 'webpack'; import { packageLocation as applicationStaticAssetsPath } from '@commercetools-frontend/assets'; import createWebpackConfigForProduction from '../config/create-webpack-config-for-production'; import paths from '../config/paths'; +import doesFileExist from '../utils/does-file-exist'; const measureFileSizesBeforeBuild = FileSizeReporter.measureFileSizesBeforeBuild; @@ -19,7 +20,7 @@ const WARN_AFTER_BUNDLE_GZIP_SIZE = 512 * 1024; const WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024; async function run() { - const hasWebpackConfig = fs.existsSync(paths.appWebpackConfig); + const hasWebpackConfig = doesFileExist(paths.appWebpackConfig); // Warn and crash if required files are missing if (!checkRequiredFiles([])) { diff --git a/packages/mc-scripts/src/commands/start.ts b/packages/mc-scripts/src/commands/start.ts index 5ae09c0c7d..83832d95b1 100644 --- a/packages/mc-scripts/src/commands/start.ts +++ b/packages/mc-scripts/src/commands/start.ts @@ -1,4 +1,3 @@ -import fs from 'fs'; import chalk from 'chalk'; import checkRequiredFiles from 'react-dev-utils/checkRequiredFiles'; import clearConsole from 'react-dev-utils/clearConsole'; @@ -14,15 +13,16 @@ import WebpackDevServer from 'webpack-dev-server'; import createWebpackConfigForDevelopment from '../config/create-webpack-config-for-development'; import paths from '../config/paths'; import createDevServerConfig from '../config/webpack-dev-server.config'; +import doesFileExist from '../utils/does-file-exist'; async function run() { - const useYarn = fs.existsSync(paths.yarnLockFile); + const useYarn = doesFileExist(paths.yarnLockFile); const isInteractive = process.stdout.isTTY; // Whether or not `react-refresh` is enabled, `react-refresh` is not 100% stable at this time, // which is why it's disabled by default. - const hasWebpackConfig = fs.existsSync(paths.appWebpackConfig); + const hasWebpackConfig = doesFileExist(paths.appWebpackConfig); // Warn and crash if required files are missing if (!checkRequiredFiles([])) { diff --git a/packages/mc-scripts/src/config/paths.ts b/packages/mc-scripts/src/config/paths.ts index 5d912adba5..aa17794b87 100644 --- a/packages/mc-scripts/src/config/paths.ts +++ b/packages/mc-scripts/src/config/paths.ts @@ -1,5 +1,6 @@ import fs from 'fs'; import path from 'path'; +import doesFileExist from '../utils/does-file-exist'; const moduleFileExtensions = ['js', 'mjs', 'cjs', 'jsx', 'ts', 'tsx']; @@ -12,7 +13,7 @@ const resolveApp = (relativePath: string) => // Resolve file paths in the order given const resolveModule = (resolveFn: typeof resolveApp, filePath: string) => { const extension = moduleFileExtensions.find((extension) => - fs.existsSync(resolveFn(`${filePath}.${extension}`)) + doesFileExist(resolveFn(`${filePath}.${extension}`)) ); if (extension) { diff --git a/packages/mc-scripts/src/utils/credentials-storage.ts b/packages/mc-scripts/src/utils/credentials-storage.ts index 4206607283..188a1a9483 100644 --- a/packages/mc-scripts/src/utils/credentials-storage.ts +++ b/packages/mc-scripts/src/utils/credentials-storage.ts @@ -2,6 +2,7 @@ import fs from 'fs'; import os from 'os'; import path from 'path'; import type { TMcCliAuthToken, TMcCliCredentialsStorage } from '../types'; +import doesFileExist from '../utils/does-file-exist'; const homedir = os.homedir(); const credentialsFolderPath = path.join(homedir, `.commercetools`); @@ -15,7 +16,7 @@ class CredentialsStorage { constructor() { // Ensure the credentials file is present - if (!fs.existsSync(credentialsFilePath)) { + if (!doesFileExist(credentialsFilePath)) { fs.mkdirSync(credentialsFolderPath, { recursive: true }); // Initialize with an empty object this._writeCredentials(); diff --git a/packages/mc-scripts/src/utils/does-file-exist.ts b/packages/mc-scripts/src/utils/does-file-exist.ts new file mode 100644 index 0000000000..7dfd241649 --- /dev/null +++ b/packages/mc-scripts/src/utils/does-file-exist.ts @@ -0,0 +1,12 @@ +import fs from 'node:fs'; + +function doesFileExist(path: string): boolean { + try { + fs.accessSync(path); + return true; + } catch (error) { + return false; + } +} + +export default doesFileExist;