From 7cb7f7211bd469583b59beea628a025414329546 Mon Sep 17 00:00:00 2001 From: Gonzalo Riestra Date: Wed, 27 May 2026 16:16:46 +0200 Subject: [PATCH] Revert "[Performance] Optimize CLI startup and project discovery" --- packages/cli-kit/src/public/node/fs.test.ts | 35 ------------------- packages/cli-kit/src/public/node/fs.ts | 11 +++--- packages/cli-kit/src/public/node/is-global.ts | 14 ++------ 3 files changed, 7 insertions(+), 53 deletions(-) diff --git a/packages/cli-kit/src/public/node/fs.test.ts b/packages/cli-kit/src/public/node/fs.test.ts index 6616642ee21..d30612b5b96 100644 --- a/packages/cli-kit/src/public/node/fs.test.ts +++ b/packages/cli-kit/src/public/node/fs.test.ts @@ -18,7 +18,6 @@ import { generateRandomNameForSubdirectory, readFileSync, glob, - globSync, detectEOL, copyDirectoryContents, symlink, @@ -320,40 +319,6 @@ describe('glob', () => { }) }) -describe('globSync', () => { - test('returns matches for the given pattern, including dotfiles by default (dot:true)', async () => { - await inTemporaryDirectory(async (tmpDir) => { - // Given - const visiblePath = joinPath(tmpDir, 'visible.toml') - const hiddenPath = joinPath(tmpDir, '.hidden.toml') - await writeFile(visiblePath, '') - await writeFile(hiddenPath, '') - - // When - const matches = globSync(joinPath(tmpDir, '*.toml')).map(normalizePath).sort() - - // Then - expect(matches).toEqual([normalizePath(hiddenPath), normalizePath(visiblePath)].sort()) - }) - }) - - test('honors an explicit dot:false option, excluding dotfiles', async () => { - await inTemporaryDirectory(async (tmpDir) => { - // Given - const visiblePath = joinPath(tmpDir, 'visible.toml') - const hiddenPath = joinPath(tmpDir, '.hidden.toml') - await writeFile(visiblePath, '') - await writeFile(hiddenPath, '') - - // When - const matches = globSync(joinPath(tmpDir, '*.toml'), {dot: false}).map(normalizePath) - - // Then - expect(matches).toEqual([normalizePath(visiblePath)]) - }) - }) -}) - describe('detectEOL', () => { test('detects the EOL of a file', async () => { // Given diff --git a/packages/cli-kit/src/public/node/fs.ts b/packages/cli-kit/src/public/node/fs.ts index e4f7cfcc057..5948c9f6bb6 100644 --- a/packages/cli-kit/src/public/node/fs.ts +++ b/packages/cli-kit/src/public/node/fs.ts @@ -17,7 +17,7 @@ import { import {sep, join} from 'pathe' import {findUp as internalFindUp, findUpSync as internalFindUpSync} from 'find-up' import {minimatch} from 'minimatch' -import {createRequire} from 'module' +import fastGlobLib from 'fast-glob' import { mkdirSync as fsMkdirSync, readFileSync as fsReadFileSync, @@ -33,6 +33,7 @@ import { accessSync, ReadStream, WriteStream, + statSync, } from 'fs' import { @@ -57,8 +58,6 @@ import * as os from 'os' import type {Pattern, Options as GlobOptions} from 'fast-glob' -const require = createRequire(import.meta.url) - /** * Strip the first `strip` parts of the path. * @@ -511,7 +510,7 @@ export function unixFileIsOwnedByCurrentUser(path: string): boolean | undefined if (!fileExistsSync(path)) return false try { - const stats = fsStatSync(path) + const stats = statSync(path) const currentUid = process.getuid() return stats.uid === currentUid @@ -595,13 +594,11 @@ export async function glob(pattern: Pattern | Pattern[], options?: GlobOptions): * @returns An array of pathnames that match the given pattern. */ export function globSync(pattern: Pattern | Pattern[], options?: GlobOptions): string[] { - // Performance: fast-glob is a heavy dependency. We lazy-load it here to avoid - // overhead during CLI startup for commands that don't need globbing. let overridenOptions = options if (options?.dot == null) { overridenOptions = {...options, dot: true} } - return (require('fast-glob') as typeof import('fast-glob')).sync(pattern, overridenOptions) + return fastGlobLib.sync(pattern, overridenOptions) } /** diff --git a/packages/cli-kit/src/public/node/is-global.ts b/packages/cli-kit/src/public/node/is-global.ts index f599c4195e5..2a60d6745ba 100644 --- a/packages/cli-kit/src/public/node/is-global.ts +++ b/packages/cli-kit/src/public/node/is-global.ts @@ -1,6 +1,6 @@ import {cwd, dirname, isSubpath, joinPath, sniffForPath} from './path.js' import {isUnitTest} from './context/local.js' -import {findPathUpSync, globSync, fileExistsSync} from './fs.js' +import {findPathUpSync, globSync} from './fs.js' import {realpathSync} from 'fs' import type {PackageManager} from './node-package-manager.js' @@ -140,17 +140,9 @@ export function inferPackageManagerForGlobalCLI(argv = process.argv, env = proce * @returns The project root directory, or undefined if not found. */ export function getProjectDir(directory: string): string | undefined { - // Performance: Check for the most common config files first using fileExistsSync (fast-path) - // to avoid the overhead of globbing/directory scanning in the common case. - const configFiles = ['shopify.app.toml', 'hydrogen.config.js', 'hydrogen.config.ts'] + const configFiles = ['shopify.app{,.*}.toml', 'hydrogen.config.js', 'hydrogen.config.ts'] const existsConfigFile = (directory: string) => { - for (const file of configFiles) { - const configPath = joinPath(directory, file) - if (fileExistsSync(configPath)) return configPath - } - - // Fallback to glob for custom app config files or if fast-path files were not found. - const configPaths = globSync(joinPath(directory, 'shopify.app.*.toml')) + const configPaths = globSync(configFiles.map((file) => joinPath(directory, file))) return configPaths.length > 0 ? configPaths[0] : undefined } try {