From ccb06f43bff18f7a828468ab182a1708003c1d8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isaac=20Rold=C3=A1n?= Date: Thu, 26 Mar 2026 15:48:51 +0100 Subject: [PATCH] chore: fix 87 eslint warnings across the codebase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolve the majority of eslint warnings (107 → 20 remaining): - Replace 72 || with ?? (prefer-nullish-coalescing) for safer null/undefined handling - Replace 18 if-assign patterns with ??= for conciseness - Replace 4 ternaries with ?? where equivalent - Remove 4 stale eslint-disable directives - Fix 2 prefer-promise-reject-errors by wrapping in Error - Fix 4 no-negated-condition by flipping if/else branches - Suppress 1 only-throw-error in Result pattern (intentional generic TError) - Suppress 5 prefer-promise-reject-errors in tests (intentional non-Error rejections) - Suppress 1 prefer-nullish-coalescing where empty string fallthrough is intended The 20 remaining warnings are all switch-exhaustiveness-check which require domain-specific decisions about handling new enum/union variants. Co-authored-by: Claude Code --- .../src/cli/commands/app/app-logs/sources.ts | 6 ++--- .../app/src/cli/commands/app/function/run.ts | 4 ++-- .../src/cli/commands/app/webhook/trigger.ts | 2 +- .../app/src/cli/models/app/identifiers.ts | 8 +++---- .../app/src/cli/prompts/generate/extension.ts | 2 +- packages/app/src/cli/prompts/init/init.ts | 24 +++++++++---------- packages/app/src/cli/services/app-context.ts | 4 +--- .../services/app-logs/dev/poll-app-logs.ts | 2 +- .../logs-command/poll-app-logs.test.ts | 4 ++-- .../app-logs/logs-command/render-json-logs.ts | 2 +- .../logs-command/ui/components/Logs.tsx | 2 +- .../app/src/cli/services/app-logs/utils.ts | 8 +++---- .../app/src/cli/services/app/select-app.ts | 4 ++-- .../build/steps/include-assets-step.ts | 2 +- .../steps/include-assets/copy-source-entry.ts | 6 ++--- .../services/context/breakdown-extensions.ts | 2 +- .../context/identifiers-extensions.ts | 2 +- packages/app/src/cli/services/dev.ts | 4 +--- .../services/dev/extension/localization.ts | 14 +++++------ .../src/cli/services/dev/graphiql/server.ts | 7 +++--- .../dev/processes/uninstall-webhook.ts | 4 ++-- .../app/src/cli/services/dev/select-app.ts | 8 +++---- .../cli/services/dev/update-extension.test.ts | 10 ++++---- .../app/src/cli/services/extensions/common.ts | 2 +- .../flow/serialize-partners-fields.ts | 2 +- .../app/src/cli/services/function/build.ts | 2 +- packages/app/src/cli/services/generate.ts | 2 +- packages/app/src/cli/services/info.test.ts | 2 +- .../app/src/cli/services/init/template/npm.ts | 2 +- .../app/src/cli/services/local-storage.ts | 8 ++----- .../payments/extension-config-builder.ts | 4 ++-- .../cli/services/webhook/trigger-options.ts | 4 ++-- .../app-management-client.ts | 4 +--- .../partners-client.ts | 4 +--- .../extensions/theme/host-theme-manager.ts | 4 +--- packages/app/src/cli/utilities/json-schema.ts | 2 +- .../cli-kit/src/private/node/conf-store.ts | 4 +--- .../node/ui/components/Table/Table.tsx | 4 ++-- .../node/ui/components/TokenizedText.tsx | 1 + .../private/node/ui/hooks/use-select-state.ts | 4 +--- packages/cli-kit/src/public/node/analytics.ts | 8 +++---- packages/cli-kit/src/public/node/api/admin.ts | 4 +--- packages/cli-kit/src/public/node/dot-env.ts | 2 +- .../cli-kit/src/public/node/error-handler.ts | 2 +- .../cli-kit/src/public/node/global-context.ts | 4 +--- .../cli-kit/src/public/node/hooks/prerun.ts | 4 +--- packages/cli-kit/src/public/node/http.ts | 2 +- .../src/public/node/local-storage.test.ts | 3 +-- packages/cli-kit/src/public/node/mimes.ts | 2 +- packages/cli-kit/src/public/node/os.ts | 1 + packages/cli-kit/src/public/node/path.ts | 2 +- packages/cli-kit/src/public/node/result.ts | 1 + .../src/public/node/serial-batch-processor.ts | 4 +--- .../cli-kit/src/public/node/themes/api.ts | 1 - .../cli-kit/src/public/node/themes/conf.ts | 8 +++---- .../src/public/node/themes/factories.ts | 1 + packages/cli-kit/src/public/node/ui.tsx | 1 + packages/cli/src/index.ts | 1 - packages/e2e/setup/auth.ts | 1 - packages/plugin-cloudflare/src/tunnel.ts | 2 +- 60 files changed, 104 insertions(+), 136 deletions(-) diff --git a/packages/app/src/cli/commands/app/app-logs/sources.ts b/packages/app/src/cli/commands/app/app-logs/sources.ts index a9a51e53bf5..b76cf9f04e7 100644 --- a/packages/app/src/cli/commands/app/app-logs/sources.ts +++ b/packages/app/src/cli/commands/app/app-logs/sources.ts @@ -26,10 +26,10 @@ export default class Sources extends AppLinkedCommand { userProvidedConfigName: flags.config, }) - if (!app.errors.isEmpty()) { - process.exit(2) - } else { + if (app.errors.isEmpty()) { sources(app) + } else { + process.exit(2) } return {app} } diff --git a/packages/app/src/cli/commands/app/function/run.ts b/packages/app/src/cli/commands/app/function/run.ts index b4efc67d9d7..3f3bb602bb3 100644 --- a/packages/app/src/cli/commands/app/function/run.ts +++ b/packages/app/src/cli/commands/app/function/run.ts @@ -56,7 +56,7 @@ export default class FunctionRun extends AppUnlinkedCommand { if (targeting.length > 1 && isTTY({})) { const targets = targeting.map((target) => ({ label: target.target, - value: target.export || DEFAULT_FUNCTION_EXPORT, + value: target.export || DEFAULT_FUNCTION_EXPORT, // eslint-disable-line @typescript-eslint/prefer-nullish-coalescing -- empty export should use default })) functionExport = await renderAutocompletePrompt({ @@ -64,7 +64,7 @@ export default class FunctionRun extends AppUnlinkedCommand { choices: targets, }) } else { - functionExport = targeting?.[0]?.export || DEFAULT_FUNCTION_EXPORT + functionExport = targeting?.[0]?.export || DEFAULT_FUNCTION_EXPORT // eslint-disable-line @typescript-eslint/prefer-nullish-coalescing -- empty export should use default outputDebug( `Using export '${functionExport}'. Use the --export flag or an interactive terminal to select a different export.`, ) diff --git a/packages/app/src/cli/commands/app/webhook/trigger.ts b/packages/app/src/cli/commands/app/webhook/trigger.ts index d4a4cb4bef5..574179ce793 100644 --- a/packages/app/src/cli/commands/app/webhook/trigger.ts +++ b/packages/app/src/cli/commands/app/webhook/trigger.ts @@ -106,7 +106,7 @@ export default class WebhookTrigger extends AppLinkedCommand { deliveryMethod: flags['delivery-method'], address: flags.address, clientId: flags['client-id'], - clientSecret: flags['client-secret'] || flags['shared-secret'], + clientSecret: flags['client-secret'] || flags['shared-secret'], // eslint-disable-line @typescript-eslint/prefer-nullish-coalescing -- empty flag should try next path: flags.path, config: flags.config, organizationId: appContextResult.organization.id, diff --git a/packages/app/src/cli/models/app/identifiers.ts b/packages/app/src/cli/models/app/identifiers.ts index 7abbe7145c2..773bb3759cd 100644 --- a/packages/app/src/cli/models/app/identifiers.ts +++ b/packages/app/src/cli/models/app/identifiers.ts @@ -52,11 +52,9 @@ export async function updateAppIdentifiers( ): Promise { let dotenvFile = app.dotenv - if (!dotenvFile) { - dotenvFile = { - path: joinPath(app.directory, getDotEnvFileName(app.configPath)), - variables: {}, - } + dotenvFile ??= { + path: joinPath(app.directory, getDotEnvFileName(app.configPath)), + variables: {}, } const updatedVariables: {[key: string]: string} = {...(app.dotenv?.variables ?? {})} if (!systemEnvironment[app.idEnvironmentVariableName]) { diff --git a/packages/app/src/cli/prompts/generate/extension.ts b/packages/app/src/cli/prompts/generate/extension.ts index 425d7cf5705..66d0fb285af 100644 --- a/packages/app/src/cli/prompts/generate/extension.ts +++ b/packages/app/src/cli/prompts/generate/extension.ts @@ -92,7 +92,7 @@ const generateExtensionPrompts = async ( const extensionTemplate = extensionTemplates.find((template) => template.identifier === templateType)! - const name = options.name || (await promptName(options.directory, extensionTemplate.defaultName)) + const name = options.name || (await promptName(options.directory, extensionTemplate.defaultName)) // eslint-disable-line @typescript-eslint/prefer-nullish-coalescing -- empty name should prompt const flavor = options.extensionFlavor ?? (await promptFlavor(extensionTemplate)) const extensionContent = {name, flavor} diff --git a/packages/app/src/cli/prompts/init/init.ts b/packages/app/src/cli/prompts/init/init.ts index 7f1174fb482..bf5393e73f3 100644 --- a/packages/app/src/cli/prompts/init/init.ts +++ b/packages/app/src/cli/prompts/init/init.ts @@ -84,18 +84,16 @@ const init = async (options: InitOptions): Promise => { template: templates.reactRouter.url, } as const - if (!template) { - template = await renderSelectPrompt({ - choices: templateOptionsInOrder.map((key) => { - return { - label: templates[key].label || key, - value: key, - } - }), - message: 'Get started building your app:', - defaultValue: allTemplates.find((key) => templates[key].url === defaults.template), - }) - } + template ??= await renderSelectPrompt({ + choices: templateOptionsInOrder.map((key) => { + return { + label: templates[key].label || key, // eslint-disable-line @typescript-eslint/prefer-nullish-coalescing -- empty label should show key + value: key, + } + }), + message: 'Get started building your app:', + defaultValue: allTemplates.find((key) => templates[key].url === defaults.template), + }) const answers: InitOutput = { ...options, @@ -129,7 +127,7 @@ const init = async (options: InitOptions): Promise => { selectedUrl = `${selectedUrl}#${branch}` } - answers.template = selectedUrl || answers.template || defaults.template + answers.template = selectedUrl || answers.template || defaults.template // eslint-disable-line @typescript-eslint/prefer-nullish-coalescing -- empty URL should fall through answers.globalCLIResult = await installGlobalCLIPrompt() diff --git a/packages/app/src/cli/services/app-context.ts b/packages/app/src/cli/services/app-context.ts index d6cd226ef39..6a449f17701 100644 --- a/packages/app/src/cli/services/app-context.ts +++ b/packages/app/src/cli/services/app-context.ts @@ -92,9 +92,7 @@ export async function linkedAppContext({ const effectiveClientId = clientId ?? configClientId // Fetch the remote app, using a different clientID if provided via flag. - if (!remoteApp) { - remoteApp = await appFromIdentifiers({apiKey: effectiveClientId}) - } + remoteApp ??= await appFromIdentifiers({apiKey: effectiveClientId}) const developerPlatformClient = remoteApp.developerPlatformClient const organization = await fetchOrgFromId(remoteApp.organizationId, developerPlatformClient) diff --git a/packages/app/src/cli/services/app-logs/dev/poll-app-logs.ts b/packages/app/src/cli/services/app-logs/dev/poll-app-logs.ts index 3fe334c40ce..424360a129e 100644 --- a/packages/app/src/cli/services/app-logs/dev/poll-app-logs.ts +++ b/packages/app/src/cli/services/app-logs/dev/poll-app-logs.ts @@ -130,7 +130,7 @@ export const pollAppLogs = async ({ stdout, appLogsFetchInput: { jwtToken: nextJwtToken, - cursor: responseCursor || cursor, + cursor: responseCursor ?? cursor, }, developerPlatformClient, resubscribeCallback, diff --git a/packages/app/src/cli/services/app-logs/logs-command/poll-app-logs.test.ts b/packages/app/src/cli/services/app-logs/logs-command/poll-app-logs.test.ts index 278cda28fe2..267dd59e01e 100644 --- a/packages/app/src/cli/services/app-logs/logs-command/poll-app-logs.test.ts +++ b/packages/app/src/cli/services/app-logs/logs-command/poll-app-logs.test.ts @@ -44,13 +44,13 @@ const EMPTY_FILTERS = {status: undefined, sources: undefined} const createMockResponse = (data: any, status = 200, statusText = 'OK') => { if (status !== 200 || data.errors) { return { - errors: data.errors || [`Error with status ${status}`], + errors: data.errors ?? [`Error with status ${status}`], status, } } return { - app_logs: data.app_logs || [], + app_logs: data.app_logs ?? [], cursor: data.cursor, status, } diff --git a/packages/app/src/cli/services/app-logs/logs-command/render-json-logs.ts b/packages/app/src/cli/services/app-logs/logs-command/render-json-logs.ts index a1bb110297e..3d6adccff6e 100644 --- a/packages/app/src/cli/services/app-logs/logs-command/render-json-logs.ts +++ b/packages/app/src/cli/services/app-logs/logs-command/render-json-logs.ts @@ -87,7 +87,7 @@ export async function renderJsonLogs({ options: {variables, developerPlatformClient}, pollOptions: { jwtToken: nextJwtToken || pollOptions.jwtToken, - cursor: nextCursor || pollOptions.cursor, + cursor: nextCursor ?? pollOptions.cursor, filters: pollOptions.filters, }, storeNameById, diff --git a/packages/app/src/cli/services/app-logs/logs-command/ui/components/Logs.tsx b/packages/app/src/cli/services/app-logs/logs-command/ui/components/Logs.tsx index cfd3be3ada5..cf1ddbbf244 100644 --- a/packages/app/src/cli/services/app-logs/logs-command/ui/components/Logs.tsx +++ b/packages/app/src/cli/services/app-logs/logs-command/ui/components/Logs.tsx @@ -92,7 +92,7 @@ const Logs: FunctionComponent = ({ - {prettyPrintJsonIfPossible(appLog.inputQueryVariablesMetafieldValue) || ( + {prettyPrintJsonIfPossible(appLog.inputQueryVariablesMetafieldValue) ?? ( Metafield is not set )} diff --git a/packages/app/src/cli/services/app-logs/utils.ts b/packages/app/src/cli/services/app-logs/utils.ts index 728e2e0ff25..e3d46f31930 100644 --- a/packages/app/src/cli/services/app-logs/utils.ts +++ b/packages/app/src/cli/services/app-logs/utils.ts @@ -84,11 +84,11 @@ export function parseNetworkAccessRequestExecutedPayload(payload: string): Netwo const parsedPayload = JSON.parse(payload) return new NetworkAccessRequestExecutedLog({ attempt: parsedPayload.attempt, - connectTimeMs: parsedPayload.connect_time_ms || null, - writeReadTimeMs: parsedPayload.write_read_time_ms || null, + connectTimeMs: parsedPayload.connect_time_ms ?? null, + writeReadTimeMs: parsedPayload.write_read_time_ms ?? null, httpRequest: parsedPayload.http_request, - httpResponse: parsedPayload.http_response || null, - error: parsedPayload.error || null, + httpResponse: parsedPayload.http_response ?? null, + error: parsedPayload.error ?? null, }) } diff --git a/packages/app/src/cli/services/app/select-app.ts b/packages/app/src/cli/services/app/select-app.ts index b13ae3bc7b5..915e88933b3 100644 --- a/packages/app/src/cli/services/app/select-app.ts +++ b/packages/app/src/cli/services/app/select-app.ts @@ -27,11 +27,11 @@ export async function fetchAppRemoteConfiguration( flags: Flag[], activeAppVersion?: AppVersion, ) { - const appVersion = activeAppVersion || (await developerPlatformClient.activeAppVersion(remoteApp)) + const appVersion = activeAppVersion ?? (await developerPlatformClient.activeAppVersion(remoteApp)) const appModuleVersionsConfig = appVersion?.appModuleVersions.filter( (module) => extensionTypeStrategy(specifications, module.specification?.identifier) !== 'uuid', - ) || [] + ) ?? [] // This might be droppable -- if remote apps always have an active version and some modules? if (appModuleVersionsConfig.length === 0) return undefined diff --git a/packages/app/src/cli/services/build/steps/include-assets-step.ts b/packages/app/src/cli/services/build/steps/include-assets-step.ts index 958eb6996d1..0ae41d8b699 100644 --- a/packages/app/src/cli/services/build/steps/include-assets-step.ts +++ b/packages/app/src/cli/services/build/steps/include-assets-step.ts @@ -79,7 +79,7 @@ export async function executeIncludeAssetsStep( const counts = await Promise.all( config.inclusions.map(async (entry) => { const warn = (msg: string) => options.stdout.write(msg) - const sanitizedDest = entry.destination !== undefined ? sanitizeRelativePath(entry.destination, warn) : undefined + const sanitizedDest = entry.destination === undefined ? undefined : sanitizeRelativePath(entry.destination, warn) if (entry.type === 'pattern') { const sourceDir = entry.baseDir ? joinPath(extension.directory, entry.baseDir) : extension.directory diff --git a/packages/app/src/cli/services/build/steps/include-assets/copy-source-entry.ts b/packages/app/src/cli/services/build/steps/include-assets/copy-source-entry.ts index 7c7fa19c473..81ae331f926 100644 --- a/packages/app/src/cli/services/build/steps/include-assets/copy-source-entry.ts +++ b/packages/app/src/cli/services/build/steps/include-assets/copy-source-entry.ts @@ -27,11 +27,11 @@ export async function copySourceEntry( // Resolve destination path and log message up front, then dispatch on file vs directory. let destPath: string let logMsg: string - if (destination !== undefined) { - destPath = joinPath(outputDir, destination) + if (destination === undefined) { + destPath = joinPath(outputDir, basename(sourcePath)) logMsg = `Included ${source}\n` } else { - destPath = joinPath(outputDir, basename(sourcePath)) + destPath = joinPath(outputDir, destination) logMsg = `Included ${source}\n` } diff --git a/packages/app/src/cli/services/context/breakdown-extensions.ts b/packages/app/src/cli/services/context/breakdown-extensions.ts index 16569bbb695..9d854e8339a 100644 --- a/packages/app/src/cli/services/context/breakdown-extensions.ts +++ b/packages/app/src/cli/services/context/breakdown-extensions.ts @@ -314,7 +314,7 @@ async function resolveRemoteExtensionIdentifiersBreakdown( specs: ExtensionSpecification[], activeAppVersion?: AppVersion, ): Promise { - const version = activeAppVersion || (await developerPlatformClient.activeAppVersion(remoteApp)) + const version = activeAppVersion ?? (await developerPlatformClient.activeAppVersion(remoteApp)) if (!version) return const extensionIdentifiersBreakdown = loadExtensionsIdentifiersBreakdown( diff --git a/packages/app/src/cli/services/context/identifiers-extensions.ts b/packages/app/src/cli/services/context/identifiers-extensions.ts index cab2362f5a4..8a8887f93d4 100644 --- a/packages/app/src/cli/services/context/identifiers-extensions.ts +++ b/packages/app/src/cli/services/context/identifiers-extensions.ts @@ -233,7 +233,7 @@ function matchWebhooks(remoteSource: RemoteSource, extension: ExtensionInstance) const remoteVersionConfig = remoteSource.activeVersion?.config const remoteVersionConfigObj = remoteVersionConfig ? JSON.parse(remoteVersionConfig) : {} const localConfig = extension.configuration as unknown as SingleWebhookSubscriptionType - const remoteUri: string = remoteVersionConfigObj.uri || '' + const remoteUri: string = remoteVersionConfigObj.uri ?? '' return ( remoteVersionConfigObj.topic === localConfig.topic && remoteUri.endsWith(localConfig.uri) && diff --git a/packages/app/src/cli/services/dev.ts b/packages/app/src/cli/services/dev.ts index 620d7a86e05..63201dca8b4 100644 --- a/packages/app/src/cli/services/dev.ts +++ b/packages/app/src/cli/services/dev.ts @@ -352,9 +352,7 @@ async function setupNetworkingOptions( let frontendPort = frontendConfig?.configuration.port if (frontendConfig) { - if (!frontendPort) { - frontendPort = frontendConfig === backendConfig ? backendPort : await getAvailableTCPPort() - } + frontendPort ??= frontendConfig === backendConfig ? backendPort : await getAvailableTCPPort() frontendConfig.configuration.port = frontendPort } frontendPort = frontendPort ?? (await getAvailableTCPPort()) diff --git a/packages/app/src/cli/services/dev/extension/localization.ts b/packages/app/src/cli/services/dev/extension/localization.ts index ad0f1887e71..494e27ca607 100644 --- a/packages/app/src/cli/services/dev/extension/localization.ts +++ b/packages/app/src/cli/services/dev/extension/localization.ts @@ -32,13 +32,13 @@ export async function getLocalization( return {localization: undefined, status: ''} } - const localization = options.currentLocalizationPayload - ? options.currentLocalizationPayload - : ({ - defaultLocale: 'en', - translations: {}, - lastUpdated: 0, - } as Localization) + const localization = + options.currentLocalizationPayload ?? + ({ + defaultLocale: 'en', + translations: {}, + lastUpdated: 0, + } as Localization) let status: ExtensionAssetBuildStatus = 'success' diff --git a/packages/app/src/cli/services/dev/graphiql/server.ts b/packages/app/src/cli/services/dev/graphiql/server.ts index 90f6db89a2f..4ee8646d38a 100644 --- a/packages/app/src/cli/services/dev/graphiql/server.ts +++ b/packages/app/src/cli/services/dev/graphiql/server.ts @@ -40,6 +40,7 @@ export function deriveGraphiQLKey(apiSecret: string, storeFqdn: string): string * if non-empty, otherwise derives one deterministically from the app secret. */ export function resolveGraphiQLKey(providedKey: string | undefined, apiSecret: string, storeFqdn: string): string { + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- intentional: empty string after trim should fall through to deriveGraphiQLKey return providedKey?.trim() || deriveGraphiQLKey(apiSecret, storeFqdn) } @@ -83,10 +84,8 @@ export function setupGraphiQLServer({ let _token: string | undefined async function token(): Promise { - if (!_token) { - // eslint-disable-next-line require-atomic-updates - _token = await refreshToken() - } + // eslint-disable-next-line require-atomic-updates + _token ??= await refreshToken() return _token } diff --git a/packages/app/src/cli/services/dev/processes/uninstall-webhook.ts b/packages/app/src/cli/services/dev/processes/uninstall-webhook.ts index af73a463a70..71edd1e0812 100644 --- a/packages/app/src/cli/services/dev/processes/uninstall-webhook.ts +++ b/packages/app/src/cli/services/dev/processes/uninstall-webhook.ts @@ -44,8 +44,8 @@ export function setupSendUninstallWebhookProcess({ }): SendWebhookProcess | undefined { const {backendConfig, frontendConfig} = frontAndBackendConfig(webs) const webhooksPath = - webs.map(({configuration}) => configuration.webhooks_path).find((path) => path) || '/api/webhooks' - const sendUninstallWebhook = Boolean(webhooksPath) && remoteAppUpdated && Boolean(frontendConfig || backendConfig) + webs.map(({configuration}) => configuration.webhooks_path).find((path) => path) ?? '/api/webhooks' + const sendUninstallWebhook = Boolean(webhooksPath) && remoteAppUpdated && Boolean(frontendConfig ?? backendConfig) if (!sendUninstallWebhook) { return } diff --git a/packages/app/src/cli/services/dev/select-app.ts b/packages/app/src/cli/services/dev/select-app.ts index c0fea4a5bfe..34c2cfe9aaa 100644 --- a/packages/app/src/cli/services/dev/select-app.ts +++ b/packages/app/src/cli/services/dev/select-app.ts @@ -59,10 +59,7 @@ export async function selectOrCreateApp( {directory: options.directory}, ) - if (!app) { - if (attempt < MAX_PROMPT_RETRIES - 1) outputInfo('App selection failed. Retrying...') - continue - } else { + if (app) { const selectedToml = tomls[app.apiKey] if (selectedToml) setCachedCommandTomlPreference(selectedToml) @@ -72,6 +69,9 @@ export async function selectOrCreateApp( if (fullSelectedApp) { return fullSelectedApp } + } else { + if (attempt < MAX_PROMPT_RETRIES - 1) outputInfo('App selection failed. Retrying...') + continue } } diff --git a/packages/app/src/cli/services/dev/update-extension.test.ts b/packages/app/src/cli/services/dev/update-extension.test.ts index 80939e6075f..67304d3b8b7 100644 --- a/packages/app/src/cli/services/dev/update-extension.test.ts +++ b/packages/app/src/cli/services/dev/update-extension.test.ts @@ -278,7 +278,7 @@ describe('updateExtensionDraft()', () => { errors: [{message: 'Network error'}, {message: 'Timeout error'}], } const developerPlatformClient: DeveloperPlatformClient = testDeveloperPlatformClient({ - updateExtension: (_extensionInput: ExtensionUpdateDraftMutationVariables) => Promise.reject(systemError), + updateExtension: (_extensionInput: ExtensionUpdateDraftMutationVariables) => Promise.reject(systemError), // eslint-disable-line @typescript-eslint/prefer-promise-reject-errors -- testing non-Error rejection handling, }) await inTemporaryDirectory(async (tmpDir) => { @@ -313,7 +313,7 @@ describe('updateExtensionDraft()', () => { test('handles system error with message string', async () => { const systemError = {message: 'API connection failed'} const developerPlatformClient: DeveloperPlatformClient = testDeveloperPlatformClient({ - updateExtension: (_extensionInput: ExtensionUpdateDraftMutationVariables) => Promise.reject(systemError), + updateExtension: (_extensionInput: ExtensionUpdateDraftMutationVariables) => Promise.reject(systemError), // eslint-disable-line @typescript-eslint/prefer-promise-reject-errors -- testing non-Error rejection handling, }) await inTemporaryDirectory(async (tmpDir) => { @@ -348,7 +348,7 @@ describe('updateExtensionDraft()', () => { test('handles string error', async () => { const systemError = 'Connection timeout' const developerPlatformClient: DeveloperPlatformClient = testDeveloperPlatformClient({ - updateExtension: (_extensionInput: ExtensionUpdateDraftMutationVariables) => Promise.reject(systemError), + updateExtension: (_extensionInput: ExtensionUpdateDraftMutationVariables) => Promise.reject(systemError), // eslint-disable-line @typescript-eslint/prefer-promise-reject-errors -- testing non-Error rejection handling, }) await inTemporaryDirectory(async (tmpDir) => { @@ -382,7 +382,7 @@ describe('updateExtensionDraft()', () => { test('handles null/undefined error with fallback message', async () => { const developerPlatformClient: DeveloperPlatformClient = testDeveloperPlatformClient({ - updateExtension: (_extensionInput: ExtensionUpdateDraftMutationVariables) => Promise.reject(null), + updateExtension: (_extensionInput: ExtensionUpdateDraftMutationVariables) => Promise.reject(null), // eslint-disable-line @typescript-eslint/prefer-promise-reject-errors -- testing null rejection handling, }) await inTemporaryDirectory(async (tmpDir) => { @@ -415,7 +415,7 @@ describe('updateExtensionDraft()', () => { test('handles object error without errors or message properties', async () => { const systemError = {status: 500, code: 'INTERNAL_ERROR'} const developerPlatformClient: DeveloperPlatformClient = testDeveloperPlatformClient({ - updateExtension: (_extensionInput: ExtensionUpdateDraftMutationVariables) => Promise.reject(systemError), + updateExtension: (_extensionInput: ExtensionUpdateDraftMutationVariables) => Promise.reject(systemError), // eslint-disable-line @typescript-eslint/prefer-promise-reject-errors -- testing non-Error rejection handling, }) await inTemporaryDirectory(async (tmpDir) => { diff --git a/packages/app/src/cli/services/extensions/common.ts b/packages/app/src/cli/services/extensions/common.ts index 6075ebbb63d..b218e096010 100644 --- a/packages/app/src/cli/services/extensions/common.ts +++ b/packages/app/src/cli/services/extensions/common.ts @@ -11,7 +11,7 @@ export async function ensureDownloadedExtensionFlavorExists( extensionFlavor: ExtensionFlavor | undefined, templateDownloadDir: string, ): Promise { - const templatePath = extensionFlavor?.path || '' + const templatePath = extensionFlavor?.path ?? '' const origin = joinPath(templateDownloadDir, templatePath) if (!(await fileExists(origin))) { throw new AbortError(`\nThe extension is not available for ${extensionFlavor?.value}`) diff --git a/packages/app/src/cli/services/flow/serialize-partners-fields.ts b/packages/app/src/cli/services/flow/serialize-partners-fields.ts index 7a8a9c45469..31edcecd99f 100644 --- a/packages/app/src/cli/services/flow/serialize-partners-fields.ts +++ b/packages/app/src/cli/services/flow/serialize-partners-fields.ts @@ -13,7 +13,7 @@ const serializeConfigField = (field: SerializedField, type: FlowPartnersExtensio const serializedField: ConfigField = { key: field.name, - description: field.description ? field.description : undefined, + description: field.description ?? undefined, type: fieldType, } diff --git a/packages/app/src/cli/services/function/build.ts b/packages/app/src/cli/services/function/build.ts index 7680e1a8524..7e8caf4f6fa 100644 --- a/packages/app/src/cli/services/function/build.ts +++ b/packages/app/src/cli/services/function/build.ts @@ -464,7 +464,7 @@ export function ${identifier}() { return __runFunction(${alias}) }` } export function jsExports(fun: ExtensionInstance) { - const targets = fun.configuration.targeting || [] + const targets = fun.configuration.targeting ?? [] const withoutExport = targets.filter((target) => !target.export) const withExport = targets.filter((target) => Boolean(target.export)) diff --git a/packages/app/src/cli/services/generate.ts b/packages/app/src/cli/services/generate.ts index e0500470739..866a2e136ca 100644 --- a/packages/app/src/cli/services/generate.ts +++ b/packages/app/src/cli/services/generate.ts @@ -100,7 +100,7 @@ function limitReached(app: AppInterface, specifications: ExtensionSpecification[ const type = template.type const specification = specifications.find((spec) => spec.identifier === type || spec.externalIdentifier === type) const existingExtensions = app.extensionsForType({identifier: type, externalIdentifier: type}) - return existingExtensions.length >= (specification?.registrationLimit || 1) + return existingExtensions.length >= (specification?.registrationLimit ?? 1) } async function saveAnalyticsMetadata(promptAnswers: GenerateExtensionPromptOutput, typeFlag: string | undefined) { diff --git a/packages/app/src/cli/services/info.test.ts b/packages/app/src/cli/services/info.test.ts index 6edfc42dec8..00c9680a08d 100644 --- a/packages/app/src/cli/services/info.test.ts +++ b/packages/app/src/cli/services/info.test.ts @@ -292,7 +292,7 @@ function mockApp({ }, extension_directories: ['extensions/*'], }, - ...(app ? app : {}), + ...(app ?? {}), }) } diff --git a/packages/app/src/cli/services/init/template/npm.ts b/packages/app/src/cli/services/init/template/npm.ts index 123cdb1044a..27c306d84b1 100644 --- a/packages/app/src/cli/services/init/template/npm.ts +++ b/packages/app/src/cli/services/init/template/npm.ts @@ -16,7 +16,7 @@ export async function updateCLIDependencies({ local, useGlobalCLI, }: UpdateCLIDependenciesOptions): Promise { - packageJSON.dependencies = packageJSON.dependencies || {} + packageJSON.dependencies = packageJSON.dependencies ?? {} if (useGlobalCLI) { delete packageJSON.dependencies['@shopify/cli'] } else { diff --git a/packages/app/src/cli/services/local-storage.ts b/packages/app/src/cli/services/local-storage.ts index 111eb40d71d..bb0f6f4aedf 100644 --- a/packages/app/src/cli/services/local-storage.ts +++ b/packages/app/src/cli/services/local-storage.ts @@ -23,9 +23,7 @@ export interface AppLocalStorageSchema { let _appLocalStorageInstance: LocalStorage | undefined function appLocalStorage() { - if (!_appLocalStorageInstance) { - _appLocalStorageInstance = new LocalStorage({projectName: 'shopify-cli-app'}) - } + _appLocalStorageInstance ??= new LocalStorage({projectName: 'shopify-cli-app'}) return _appLocalStorageInstance } @@ -91,9 +89,7 @@ interface CommandLocalStorage { let _commandLocalStorageInstance: LocalStorage | undefined function commandLocalStorage() { - if (!_commandLocalStorageInstance) { - _commandLocalStorageInstance = new LocalStorage({projectName: 'shopify-cli-app-command'}) - } + _commandLocalStorageInstance ??= new LocalStorage({projectName: 'shopify-cli-app-command'}) return _commandLocalStorageInstance } diff --git a/packages/app/src/cli/services/payments/extension-config-builder.ts b/packages/app/src/cli/services/payments/extension-config-builder.ts index 8be80b6bc36..302ac29dded 100644 --- a/packages/app/src/cli/services/payments/extension-config-builder.ts +++ b/packages/app/src/cli/services/payments/extension-config-builder.ts @@ -59,7 +59,7 @@ export enum DashboardPaymentExtensionType { } export function buildExtensionConfig(extension: ExtensionRegistration, allExtensions: ExtensionRegistration[]): object { - const context = extension.activeVersion?.context || extension.draftVersion?.context || typeToContext(extension.type) + const context = extension.activeVersion?.context ?? extension.draftVersion?.context ?? typeToContext(extension.type) switch (context) { case OFFSITE_TARGET: return buildPaymentsToml( @@ -117,7 +117,7 @@ function buildPaymentsToml( const cliConfig = serialize(dashboardConfig, allExtensions) if (cliConfig) delete cliConfig.api_version - const context = extension.activeVersion?.context || extension.draftVersion?.context || typeToContext(extension.type) + const context = extension.activeVersion?.context ?? extension.draftVersion?.context ?? typeToContext(extension.type) const localExtensionRepresentation = { api_version: dashboardConfig.api_version, diff --git a/packages/app/src/cli/services/webhook/trigger-options.ts b/packages/app/src/cli/services/webhook/trigger-options.ts index fcce78cb903..24c64d82dd2 100644 --- a/packages/app/src/cli/services/webhook/trigger-options.ts +++ b/packages/app/src/cli/services/webhook/trigger-options.ts @@ -104,8 +104,8 @@ export async function collectAddressAndMethod( deliveryMethod: string | undefined, address: string | undefined, ): Promise<[string, string]> { - const actualMethod = deliveryMethod || deliveryMethodForAddress(address) || (await deliveryMethodPrompt()) - const actualAddress = address || (await addressPrompt(actualMethod)) + const actualMethod = deliveryMethod ?? deliveryMethodForAddress(address) ?? (await deliveryMethodPrompt()) + const actualAddress = address ?? (await addressPrompt(actualMethod)) return validateAddressMethod(actualAddress, actualMethod) } diff --git a/packages/app/src/cli/utilities/developer-platform-client/app-management-client.ts b/packages/app/src/cli/utilities/developer-platform-client/app-management-client.ts index 9ca082bd7f0..bce3901bd7a 100644 --- a/packages/app/src/cli/utilities/developer-platform-client/app-management-client.ts +++ b/packages/app/src/cli/utilities/developer-platform-client/app-management-client.ts @@ -191,9 +191,7 @@ export class AppManagementClient implements DeveloperPlatformClient { private static instance: AppManagementClient | undefined static getInstance(session?: Session): AppManagementClient { - if (!AppManagementClient.instance) { - AppManagementClient.instance = new AppManagementClient(session) - } + AppManagementClient.instance ??= new AppManagementClient(session) return AppManagementClient.instance } diff --git a/packages/app/src/cli/utilities/developer-platform-client/partners-client.ts b/packages/app/src/cli/utilities/developer-platform-client/partners-client.ts index c1ecc08c367..1c45d86a6cf 100644 --- a/packages/app/src/cli/utilities/developer-platform-client/partners-client.ts +++ b/packages/app/src/cli/utilities/developer-platform-client/partners-client.ts @@ -214,9 +214,7 @@ export class PartnersClient implements DeveloperPlatformClient { private static instance: PartnersClient | undefined static getInstance(session?: Session): PartnersClient { - if (!PartnersClient.instance) { - PartnersClient.instance = new PartnersClient(session) - } + PartnersClient.instance ??= new PartnersClient(session) return PartnersClient.instance } diff --git a/packages/app/src/cli/utilities/extensions/theme/host-theme-manager.ts b/packages/app/src/cli/utilities/extensions/theme/host-theme-manager.ts index 2122e2951fb..c80d08ee1d4 100644 --- a/packages/app/src/cli/utilities/extensions/theme/host-theme-manager.ts +++ b/packages/app/src/cli/utilities/extensions/theme/host-theme-manager.ts @@ -24,9 +24,7 @@ export class HostThemeManager extends ThemeManager { async findOrCreate(): Promise { let theme = await this.fetch() - if (!theme) { - theme = this.devPreview ? await this.createHostTheme() : await this.create() - } + theme ??= this.devPreview ? await this.createHostTheme() : await this.create() return theme } diff --git a/packages/app/src/cli/utilities/json-schema.ts b/packages/app/src/cli/utilities/json-schema.ts index 55855eddd4a..c31eec28290 100644 --- a/packages/app/src/cli/utilities/json-schema.ts +++ b/packages/app/src/cli/utilities/json-schema.ts @@ -59,7 +59,7 @@ export async function unifiedConfigurationParserFactory( ) // Finally, we de-duplicate the error set from both validations -- identical messages for identical paths are removed - let errors = zodParse.errors || [] + let errors = zodParse.errors ?? [] if (jsonSchemaParse.state === 'error') { errors = errors.concat(jsonSchemaParse.errors) } diff --git a/packages/cli-kit/src/private/node/conf-store.ts b/packages/cli-kit/src/private/node/conf-store.ts index 1c585eae41a..de29ede0030 100644 --- a/packages/cli-kit/src/private/node/conf-store.ts +++ b/packages/cli-kit/src/private/node/conf-store.ts @@ -42,9 +42,7 @@ let _instance: LocalStorage | undefined * @returns CLIKitStore. */ function cliKitStore() { - if (!_instance) { - _instance = new LocalStorage({projectName: `shopify-cli-kit${isUnitTest() ? '-test' : ''}`}) - } + _instance ??= new LocalStorage({projectName: `shopify-cli-kit${isUnitTest() ? '-test' : ''}`}) return _instance } diff --git a/packages/cli-kit/src/private/node/ui/components/Table/Table.tsx b/packages/cli-kit/src/private/node/ui/components/Table/Table.tsx index fed66801d59..aa3764258d7 100644 --- a/packages/cli-kit/src/private/node/ui/components/Table/Table.tsx +++ b/packages/cli-kit/src/private/node/ui/components/Table/Table.tsx @@ -16,7 +16,7 @@ export interface TableProps { function Table({rows, columns: columnsConfiguration}: TableProps) { const columns = Object.entries(columnsConfiguration).map(([key, {header, color}]) => { - const headerWidth = String(header || key).length + const headerWidth = String(header ?? key).length const columnWidths = rows.map((row) => { const value = row[key] @@ -34,7 +34,7 @@ function Table({rows, columns: columnsConfiguration}: Tabl } }) const headings = Object.entries(columnsConfiguration).reduce( - (headings, [column, {header}]) => ({...headings, [column]: header || column}), + (headings, [column, {header}]) => ({...headings, [column]: header ?? column}), {}, ) diff --git a/packages/cli-kit/src/private/node/ui/components/TokenizedText.tsx b/packages/cli-kit/src/private/node/ui/components/TokenizedText.tsx index 0b4c2bb58e9..2c9905e01fc 100644 --- a/packages/cli-kit/src/private/node/ui/components/TokenizedText.tsx +++ b/packages/cli-kit/src/private/node/ui/components/TokenizedText.tsx @@ -80,6 +80,7 @@ export function tokenItemToString(token: TokenItem): string { } else if ('command' in token) { return token.command } else if ('link' in token) { + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- empty label should fall through to url return token.link.label || token.link.url } else if ('char' in token) { return token.char diff --git a/packages/cli-kit/src/private/node/ui/hooks/use-select-state.ts b/packages/cli-kit/src/private/node/ui/hooks/use-select-state.ts index 1152e97598e..1b6b6065678 100644 --- a/packages/cli-kit/src/private/node/ui/hooks/use-select-state.ts +++ b/packages/cli-kit/src/private/node/ui/hooks/use-select-state.ts @@ -31,9 +31,7 @@ export default class OptionMap extends Map> { previous.next = item } - if (!firstItem) { - firstItem = item - } + firstItem ??= item items.push([option.value, item]) index++ diff --git a/packages/cli-kit/src/public/node/analytics.ts b/packages/cli-kit/src/public/node/analytics.ts index eed9957bd93..5578e3af328 100644 --- a/packages/cli-kit/src/public/node/analytics.ts +++ b/packages/cli-kit/src/public/node/analytics.ts @@ -79,15 +79,15 @@ export async function reportAnalyticsEvent(options: ReportAnalyticsEventOptions) } } const doOpenTelemetry = async () => { - const active = payload.public.cmd_all_timing_active_ms || 0 - const network = payload.public.cmd_all_timing_network_ms || 0 - const prompt = payload.public.cmd_all_timing_prompts_ms || 0 + const active = payload.public.cmd_all_timing_active_ms ?? 0 + const network = payload.public.cmd_all_timing_network_ms ?? 0 + const prompt = payload.public.cmd_all_timing_prompts_ms ?? 0 return recordMetrics( { skipMetricAnalytics, cliVersion: payload.public.cli_version, - owningPlugin: payload.public.cmd_all_plugin || '@shopify/cli', + owningPlugin: payload.public.cmd_all_plugin ?? '@shopify/cli', command: payload.public.command, exitMode: options.exitMode, }, diff --git a/packages/cli-kit/src/public/node/api/admin.ts b/packages/cli-kit/src/public/node/api/admin.ts index 68f90d5da7f..d121ea3b320 100644 --- a/packages/cli-kit/src/public/node/api/admin.ts +++ b/packages/cli-kit/src/public/node/api/admin.ts @@ -76,9 +76,7 @@ export async function adminRequestDoc( const {query, session, variables, version, responseOptions, preferredBehaviour} = options let apiVersion = version ?? LatestApiVersionByFQDN.get(session.storeFqdn) - if (!apiVersion) { - apiVersion = await fetchLatestSupportedApiVersion(session, preferredBehaviour) - } + apiVersion ??= await fetchLatestSupportedApiVersion(session, preferredBehaviour) let storeDomain = session.storeFqdn const addedHeaders = themeAccessHeaders(session) diff --git a/packages/cli-kit/src/public/node/dot-env.ts b/packages/cli-kit/src/public/node/dot-env.ts index 1c2e4cff31c..49394a1ce72 100644 --- a/packages/cli-kit/src/public/node/dot-env.ts +++ b/packages/cli-kit/src/public/node/dot-env.ts @@ -92,7 +92,7 @@ export function patchEnvFile(envFileContent: string | null, updatedValues: Recor if (match) { const key = match[1]!.trim() - const value = (match[2] || '').trim() + const value = (match[2] ?? '').trim() if (/^["'`]/.test(value) && !value.endsWith(value[0]!)) { multilineVariable = { diff --git a/packages/cli-kit/src/public/node/error-handler.ts b/packages/cli-kit/src/public/node/error-handler.ts index ceb1d576ceb..9b764be5c78 100644 --- a/packages/cli-kit/src/public/node/error-handler.ts +++ b/packages/cli-kit/src/public/node/error-handler.ts @@ -150,7 +150,7 @@ export async function sendErrorToBugsnag( } const errorHandler = (error: unknown) => { if (error) { - reject(error) + reject(error instanceof Error ? error : new Error(String(error))) } else { resolve(reportableError) } diff --git a/packages/cli-kit/src/public/node/global-context.ts b/packages/cli-kit/src/public/node/global-context.ts index fdbb5d87a2c..b21aa1c48cd 100644 --- a/packages/cli-kit/src/public/node/global-context.ts +++ b/packages/cli-kit/src/public/node/global-context.ts @@ -10,9 +10,7 @@ let _globalContext: GlobalContext | undefined * @returns Global context. */ function getGlobalContext(): GlobalContext { - if (!_globalContext) { - _globalContext = {currentCommandId: ''} - } + _globalContext ??= {currentCommandId: ''} return _globalContext } diff --git a/packages/cli-kit/src/public/node/hooks/prerun.ts b/packages/cli-kit/src/public/node/hooks/prerun.ts index b64c6c21cda..b1ab44b45ed 100644 --- a/packages/cli-kit/src/public/node/hooks/prerun.ts +++ b/packages/cli-kit/src/public/node/hooks/prerun.ts @@ -30,9 +30,7 @@ export const hook: Hook.Prerun = async (options) => { export function parseCommandContent(cmdInfo: {id: string; aliases: string[]; pluginAlias?: string}): CommandContent { let commandContent = parseCreateCommand(cmdInfo.pluginAlias) - if (!commandContent) { - commandContent = parseNormalCommand(cmdInfo.id, cmdInfo.aliases) - } + commandContent ??= parseNormalCommand(cmdInfo.id, cmdInfo.aliases) return commandContent } diff --git a/packages/cli-kit/src/public/node/http.ts b/packages/cli-kit/src/public/node/http.ts index 572328121d3..8cbc8556a57 100644 --- a/packages/cli-kit/src/public/node/http.ts +++ b/packages/cli-kit/src/public/node/http.ts @@ -258,7 +258,7 @@ export function downloadFile(url: string, to: string): Promise { }) .catch((err) => { tryToRemoveFile() - reject(err) + reject(err instanceof Error ? err : new Error(String(err))) }) }) }) diff --git a/packages/cli-kit/src/public/node/local-storage.test.ts b/packages/cli-kit/src/public/node/local-storage.test.ts index b50b5db7fc2..cc1ab842326 100644 --- a/packages/cli-kit/src/public/node/local-storage.test.ts +++ b/packages/cli-kit/src/public/node/local-storage.test.ts @@ -9,9 +9,8 @@ interface TestSchema { } // Helper to access private config for testing -// eslint-disable-next-line @typescript-eslint/no-explicit-any + function getConfig(storage: LocalStorage): any { - // eslint-disable-next-line @typescript-eslint/no-explicit-any return (storage as any).config } diff --git a/packages/cli-kit/src/public/node/mimes.ts b/packages/cli-kit/src/public/node/mimes.ts index 0cdcdd3e1be..eb2d7eb6a08 100644 --- a/packages/cli-kit/src/public/node/mimes.ts +++ b/packages/cli-kit/src/public/node/mimes.ts @@ -8,7 +8,7 @@ import {lookup, mimes} from 'mrmime' * @returns The mime type. */ export function lookupMimeType(fileName: string): string { - return lookup(fileName) || 'application/octet-stream' + return lookup(fileName) ?? 'application/octet-stream' } /** diff --git a/packages/cli-kit/src/public/node/os.ts b/packages/cli-kit/src/public/node/os.ts index 5c84c96964a..139f798cbb0 100644 --- a/packages/cli-kit/src/public/node/os.ts +++ b/packages/cli-kit/src/public/node/os.ts @@ -72,6 +72,7 @@ export function platformAndArch( function getEnvironmentVariable() { const {env} = process + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- empty string env vars should fall through return env.SUDO_USER || env.C9_USER || env.LOGNAME || env.USER || env.LNAME || env.USERNAME } diff --git a/packages/cli-kit/src/public/node/path.ts b/packages/cli-kit/src/public/node/path.ts index b1691d637e3..20ce55840cf 100644 --- a/packages/cli-kit/src/public/node/path.ts +++ b/packages/cli-kit/src/public/node/path.ts @@ -162,7 +162,7 @@ export function moduleDirectory(moduleURL: string | URL): string { */ export function cwd(): string { // eslint-disable-next-line @shopify/cli/no-process-cwd - return normalize(process.env.INIT_CWD ? process.env.INIT_CWD : process.cwd()) + return normalize(process.env.INIT_CWD || process.cwd()) // eslint-disable-line @typescript-eslint/prefer-nullish-coalescing -- empty env var should fall through } /** diff --git a/packages/cli-kit/src/public/node/result.ts b/packages/cli-kit/src/public/node/result.ts index 4e4f89e4b71..af40472c22d 100644 --- a/packages/cli-kit/src/public/node/result.ts +++ b/packages/cli-kit/src/public/node/result.ts @@ -104,6 +104,7 @@ export class Err { * A safe mode to throw the `error` of the `Result` */ valueOrBug(): TValue { + // eslint-disable-next-line @typescript-eslint/only-throw-error -- TError may not extend Error; this is intentional for the Result pattern throw this.error } diff --git a/packages/cli-kit/src/public/node/serial-batch-processor.ts b/packages/cli-kit/src/public/node/serial-batch-processor.ts index 3da1770aa6a..5ec9c439b02 100644 --- a/packages/cli-kit/src/public/node/serial-batch-processor.ts +++ b/packages/cli-kit/src/public/node/serial-batch-processor.ts @@ -12,9 +12,7 @@ export class SerialBatchProcessor { enqueue(item: T): void { this.queue.push(item) - if (!this.processingPromise) { - this.processingPromise = this.startProcessing() - } + this.processingPromise ??= this.startProcessing() } async waitForCompletion(): Promise { diff --git a/packages/cli-kit/src/public/node/themes/api.ts b/packages/cli-kit/src/public/node/themes/api.ts index ac8a8627302..a6e1f3bbcfe 100644 --- a/packages/cli-kit/src/public/node/themes/api.ts +++ b/packages/cli-kit/src/public/node/themes/api.ts @@ -134,7 +134,6 @@ export async function findDevelopmentThemeByName(name: string, session: AdminSes } if (themes.nodes.length === 1) { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const {id, processing, role, name} = themes.nodes[0]! return buildTheme({ diff --git a/packages/cli-kit/src/public/node/themes/conf.ts b/packages/cli-kit/src/public/node/themes/conf.ts index 515dcda18ce..b9b381ff89a 100644 --- a/packages/cli-kit/src/public/node/themes/conf.ts +++ b/packages/cli-kit/src/public/node/themes/conf.ts @@ -10,11 +10,9 @@ type HostThemeLocalStorageSchema = Record let _hostThemeLocalStorageInstance: LocalStorage | undefined export function hostThemeLocalStorage(): LocalStorage { - if (!_hostThemeLocalStorageInstance) { - _hostThemeLocalStorageInstance = new LocalStorage({ - projectName: 'shopify-cli-host-theme-conf', - }) - } + _hostThemeLocalStorageInstance ??= new LocalStorage({ + projectName: 'shopify-cli-host-theme-conf', + }) return _hostThemeLocalStorageInstance } diff --git a/packages/cli-kit/src/public/node/themes/factories.ts b/packages/cli-kit/src/public/node/themes/factories.ts index 1fda0a8674b..297458e4ccc 100644 --- a/packages/cli-kit/src/public/node/themes/factories.ts +++ b/packages/cli-kit/src/public/node/themes/factories.ts @@ -52,6 +52,7 @@ export function buildThemeAsset(asset?: RemoteAssetResponse): ThemeAsset | undef const {key, checksum, attachment, value} = asset // Note: for attachments, this is the size of the base64 string, not the real length of the file + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- empty string value should fall through to attachment for binary assets const stats = {size: (value || attachment || '').length, mtime: Date.now()} return {key, checksum, attachment, value, stats} } diff --git a/packages/cli-kit/src/public/node/ui.tsx b/packages/cli-kit/src/public/node/ui.tsx index c9ac3e6b3c7..42e08e9b3d7 100644 --- a/packages/cli-kit/src/public/node/ui.tsx +++ b/packages/cli-kit/src/public/node/ui.tsx @@ -654,6 +654,7 @@ interface IsTTYOptions { } export function isTTY({stdin = undefined, uiDebugOptions = defaultUIDebugOptions}: IsTTYOptions = {}) { + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- false should fall through to stdin/terminalSupportsPrompting return Boolean(uiDebugOptions.skipTTYCheck || stdin || terminalSupportsPrompting()) } diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 4e762b6067d..4791d509935 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -1,4 +1,3 @@ -/* eslint-disable @shopify/cli/specific-imports-in-bootstrap-code */ import VersionCommand from './cli/commands/version.js' import Search from './cli/commands/search.js' import Upgrade from './cli/commands/upgrade.js' diff --git a/packages/e2e/setup/auth.ts b/packages/e2e/setup/auth.ts index 5a37752bef3..3bb1e9cf0ca 100644 --- a/packages/e2e/setup/auth.ts +++ b/packages/e2e/setup/auth.ts @@ -1,4 +1,3 @@ -/* eslint-disable no-restricted-imports */ import {cliFixture} from './cli.js' import {executables} from './env.js' import {stripAnsi} from '../helpers/strip-ansi.js' diff --git a/packages/plugin-cloudflare/src/tunnel.ts b/packages/plugin-cloudflare/src/tunnel.ts index c361923f899..9e7766601fe 100644 --- a/packages/plugin-cloudflare/src/tunnel.ts +++ b/packages/plugin-cloudflare/src/tunnel.ts @@ -112,7 +112,7 @@ class TunnelClientInstance implements TunnelClient { write(chunk, _, callback) { outputDebug(chunk.toString()) if (resolved) return - if (!url) url = findUrl(chunk) + url ??= findUrl(chunk) if (findConnection(chunk)) connected = true if (connected) { if (url) {