diff --git a/packages/cli-kit/src/public/node/context/local.test.ts b/packages/cli-kit/src/public/node/context/local.test.ts index abe71bb52b7..133568f4280 100644 --- a/packages/cli-kit/src/public/node/context/local.test.ts +++ b/packages/cli-kit/src/public/node/context/local.test.ts @@ -10,11 +10,12 @@ import { macAddress, getThemeKitAccessDomain, opentelemetryDomain, + _resetIsShopify, } from './local.js' import {fileExists} from '../fs.js' import {exec} from '../system.js' -import {afterEach, expect, describe, vi, test} from 'vitest' +import {afterEach, beforeEach, expect, describe, vi, test} from 'vitest' vi.mock('../fs.js') vi.mock('../system.js') @@ -97,6 +98,10 @@ describe('isDevelopment', () => { }) describe('isShopify', () => { + beforeEach(() => { + _resetIsShopify() + }) + test('returns false when the SHOPIFY_RUN_AS_USER env. variable is truthy', async () => { // Given const env = {SHOPIFY_RUN_AS_USER: '1'} @@ -120,6 +125,18 @@ describe('isShopify', () => { // When await expect(isShopify()).resolves.toBe(true) }) + + test('memoizes the result', async () => { + // Given + vi.mocked(fileExists).mockResolvedValue(true) + + // When + await isShopify() + await isShopify() + + // Then + expect(fileExists).toHaveBeenCalledTimes(1) + }) }) describe('hasGit', () => { diff --git a/packages/cli-kit/src/public/node/context/local.ts b/packages/cli-kit/src/public/node/context/local.ts index ad816399db9..a6869e4b1bc 100644 --- a/packages/cli-kit/src/public/node/context/local.ts +++ b/packages/cli-kit/src/public/node/context/local.ts @@ -44,6 +44,11 @@ let memoizedIsVerbose: boolean | undefined */ let memoizedIsUnitTest: boolean | undefined +/** + * Memoized value for the shopify check. + */ +let memoizedIsShopify: Promise | undefined + /** * Returns true if the CLI is running in debug mode. * @@ -77,6 +82,14 @@ export function isVerbose(env = process.env): boolean { * @returns True if the CLI is used in a Shopify environment. */ export async function isShopify(env = process.env): Promise { + if (env === process.env) { + // Memoize the result to avoid repeated disk checks for the 'dev' executable. + return (memoizedIsShopify ??= checkIsShopify(env)) + } + return checkIsShopify(env) +} + +async function checkIsShopify(env: NodeJS.ProcessEnv): Promise { if (Object.prototype.hasOwnProperty.call(env, environmentVariables.runAsUser)) { return !isTruthy(env[environmentVariables.runAsUser]) } @@ -325,4 +338,11 @@ export function opentelemetryDomain(env = process.env): string { return isSet(domain) ? domain : 'https://otlp-http-production-cli.shopifysvc.com' } +/** + * Resets the memoized value for the shopify check. + */ +export function _resetIsShopify(): void { + memoizedIsShopify = undefined +} + export type CIMetadata = Metadata