From 0c53ab159ee143b37ce0e5ec4fa69518ff4c34b1 Mon Sep 17 00:00:00 2001 From: Ryan Bahan Date: Mon, 26 Jan 2026 16:32:33 -0700 Subject: [PATCH 1/2] make remote dev console the default case --- .../dev-session/dev-session-process.test.ts | 25 ++++++++++--------- .../dev/processes/dev-session/dev-session.ts | 7 +++--- .../dev/processes/setup-dev-processes.test.ts | 12 ++++----- .../dev/processes/setup-dev-processes.ts | 7 +++--- .../cli-kit/src/private/node/constants.ts | 2 +- .../cli-kit/src/public/node/context/local.ts | 9 ++++--- 6 files changed, 31 insertions(+), 31 deletions(-) diff --git a/packages/app/src/cli/services/dev/processes/dev-session/dev-session-process.test.ts b/packages/app/src/cli/services/dev/processes/dev-session/dev-session-process.test.ts index f51e4be5a7..e28fbf1daf 100644 --- a/packages/app/src/cli/services/dev/processes/dev-session/dev-session-process.test.ts +++ b/packages/app/src/cli/services/dev/processes/dev-session/dev-session-process.test.ts @@ -20,7 +20,7 @@ import {AbortSignal, AbortController} from '@shopify/cli-kit/node/abort' import {flushPromises} from '@shopify/cli-kit/node/promises' import * as outputContext from '@shopify/cli-kit/node/ui/components' import {readdir} from '@shopify/cli-kit/node/fs' -import {firstPartyDev, skipLocalDevConsole} from '@shopify/cli-kit/node/context/local' +import {firstPartyDev, useLocalDevConsole} from '@shopify/cli-kit/node/context/local' vi.mock('@shopify/cli-kit/node/fs') vi.mock('@shopify/cli-kit/node/archiver') @@ -33,7 +33,7 @@ vi.mock('@shopify/cli-kit/node/context/local', async (importOriginal) => { return { ...original, firstPartyDev: vi.fn().mockReturnValue(false), - skipLocalDevConsole: vi.fn().mockReturnValue(false), + useLocalDevConsole: vi.fn().mockReturnValue(false), } }) @@ -219,10 +219,10 @@ describe('pushUpdatesForDevSession', () => { contextSpy.mockRestore() }) - test('updates preview URL to appLocalProxyURL when extension is previewable (dev console shown by default)', async () => { - // Given - dev console is shown by default when skipLocalDevConsole is false + test('updates preview URL to appPreviewURL by default (local dev console is opt-in)', async () => { + // Given - dev console is NOT shown by default (requires both firstPartyDev AND useLocalDevConsole) vi.mocked(firstPartyDev).mockReturnValue(false) - vi.mocked(skipLocalDevConsole).mockReturnValue(false) + vi.mocked(useLocalDevConsole).mockReturnValue(false) const extension = await testUIExtension({type: 'ui_extension'}) const newApp = testAppLinked({allExtensions: [extension]}) @@ -234,13 +234,13 @@ describe('pushUpdatesForDevSession', () => { await flushPromises() // Then - expect(devSessionStatusManager.status.previewURL).toBe(options.appLocalProxyURL) + expect(devSessionStatusManager.status.previewURL).toBe(options.appPreviewURL) }) - test('updates preview URL to appPreviewURL when both skip conditions are met', async () => { - // Given - dev console is skipped only when !firstPartyDev() AND skipLocalDevConsole() - vi.mocked(firstPartyDev).mockReturnValue(false) - vi.mocked(skipLocalDevConsole).mockReturnValue(true) + test('updates preview URL to appLocalProxyURL when 1P dev opts in with useLocalDevConsole', async () => { + // Given - dev console is shown only when firstPartyDev() AND useLocalDevConsole() + vi.mocked(firstPartyDev).mockReturnValue(true) + vi.mocked(useLocalDevConsole).mockReturnValue(true) const extension = await testUIExtension({type: 'ui_extension'}) const newApp = testAppLinked({allExtensions: [extension]}) @@ -252,8 +252,9 @@ describe('pushUpdatesForDevSession', () => { await flushPromises() // Then - expect(devSessionStatusManager.status.previewURL).toBe(options.appPreviewURL) - vi.mocked(skipLocalDevConsole).mockReturnValue(false) + expect(devSessionStatusManager.status.previewURL).toBe(options.appLocalProxyURL) + vi.mocked(firstPartyDev).mockReturnValue(false) + vi.mocked(useLocalDevConsole).mockReturnValue(false) }) test('updates preview URL to appPreviewURL when no previewable extensions', async () => { diff --git a/packages/app/src/cli/services/dev/processes/dev-session/dev-session.ts b/packages/app/src/cli/services/dev/processes/dev-session/dev-session.ts index 82b3b89f80..b6d9f39e6f 100644 --- a/packages/app/src/cli/services/dev/processes/dev-session/dev-session.ts +++ b/packages/app/src/cli/services/dev/processes/dev-session/dev-session.ts @@ -10,7 +10,7 @@ import {endHRTimeInMs, startHRTime} from '@shopify/cli-kit/node/hrtime' import {ClientError} from 'graphql-request' import {JsonMapType} from '@shopify/cli-kit/node/toml' import {AbortError} from '@shopify/cli-kit/node/error' -import {firstPartyDev, isUnitTest, skipLocalDevConsole} from '@shopify/cli-kit/node/context/local' +import {firstPartyDev, isUnitTest, useLocalDevConsole} from '@shopify/cli-kit/node/context/local' import {dirname, joinPath} from '@shopify/cli-kit/node/path' import {readdir} from '@shopify/cli-kit/node/fs' import {SerialBatchProcessor} from '@shopify/cli-kit/node/serial-batch-processor' @@ -240,13 +240,12 @@ export class DevSession { /** * Update the preview URL, it only changes if we move between a non-previewable state and a previewable state. * (i.e. if we go from a state with no extensions to a state with ui-extensions or vice versa) - * Skip the dev console only when BOTH: SHOPIFY_CLI_1P_DEV is NOT enabled AND SHOPIFY_SKIP_LOCAL_DEV_CONSOLE is set. + * Use local dev console only when BOTH: SHOPIFY_CLI_1P_DEV is enabled AND SHOPIFY_USE_LOCAL_DEV_CONSOLE is set. * @param event - The app event */ private updatePreviewURL(event: AppEvent) { const hasPreview = event.app.allExtensions.filter((ext) => ext.isPreviewable).length > 0 - const skipDevConsole = !firstPartyDev() && skipLocalDevConsole() - const useDevConsole = !skipDevConsole && hasPreview + const useDevConsole = firstPartyDev() && useLocalDevConsole() && hasPreview const newPreviewURL = useDevConsole ? this.options.appLocalProxyURL : this.options.appPreviewURL this.statusManager.updateStatus({previewURL: newPreviewURL}) } diff --git a/packages/app/src/cli/services/dev/processes/setup-dev-processes.test.ts b/packages/app/src/cli/services/dev/processes/setup-dev-processes.test.ts index 4b8a460a23..db3168b0ce 100644 --- a/packages/app/src/cli/services/dev/processes/setup-dev-processes.test.ts +++ b/packages/app/src/cli/services/dev/processes/setup-dev-processes.test.ts @@ -35,7 +35,7 @@ import {Config} from '@oclif/core' import {getEnvironmentVariables} from '@shopify/cli-kit/node/environment' import {isStorefrontPasswordProtected} from '@shopify/theme' import {fetchTheme} from '@shopify/cli-kit/node/themes/api' -import {firstPartyDev, skipLocalDevConsole} from '@shopify/cli-kit/node/context/local' +import {firstPartyDev, useLocalDevConsole} from '@shopify/cli-kit/node/context/local' vi.mock('../../context/identifiers.js') vi.mock('@shopify/cli-kit/node/session.js') @@ -69,10 +69,10 @@ beforeEach(() => { role: 'theme', processing: false, }) - // By default, firstPartyDev is false (dev console URL only used when enabled) + // By default, firstPartyDev is false vi.mocked(firstPartyDev).mockReturnValue(false) - // By default, skipLocalDevConsole is false - vi.mocked(skipLocalDevConsole).mockReturnValue(false) + // By default, useLocalDevConsole is false (local dev console is opt-in for 1P devs) + vi.mocked(useLocalDevConsole).mockReturnValue(false) }) const appContextResult = { @@ -168,8 +168,8 @@ describe('setup-dev-processes', () => { graphiqlKey, }) - // Dev console is shown by default (only skipped when !firstPartyDev() AND skipLocalDevConsole()) - expect(res.previewUrl).toBe('https://example.com/proxy/extensions/dev-console') + // Dev console is NOT shown by default (only shown when firstPartyDev() AND useLocalDevConsole()) + expect(res.previewUrl).toBe('https://store.myshopify.io/admin/oauth/redirect_from_cli?client_id=api-key') expect(res.processes[0]).toMatchObject({ type: 'web', prefix: 'web-backend-frontend', diff --git a/packages/app/src/cli/services/dev/processes/setup-dev-processes.ts b/packages/app/src/cli/services/dev/processes/setup-dev-processes.ts index 81cf850062..545c490f72 100644 --- a/packages/app/src/cli/services/dev/processes/setup-dev-processes.ts +++ b/packages/app/src/cli/services/dev/processes/setup-dev-processes.ts @@ -22,7 +22,7 @@ import {AppEventWatcher} from '../app-events/app-event-watcher.js' import {reloadApp} from '../../../models/app/loader.js' import {getAvailableTCPPort} from '@shopify/cli-kit/node/tcp' import {isTruthy} from '@shopify/cli-kit/node/context/utilities' -import {firstPartyDev, skipLocalDevConsole} from '@shopify/cli-kit/node/context/local' +import {firstPartyDev, useLocalDevConsole} from '@shopify/cli-kit/node/context/local' import {getEnvironmentVariables} from '@shopify/cli-kit/node/environment' import {outputInfo} from '@shopify/cli-kit/node/output' @@ -100,11 +100,10 @@ export async function setupDevProcesses({ const appWatcher = new AppEventWatcher(reloadedApp, network.proxyUrl) // Decide on the appropriate preview URL for a session with these processes - // Skip the dev console only when BOTH: SHOPIFY_CLI_1P_DEV is NOT enabled AND SHOPIFY_SKIP_LOCAL_DEV_CONSOLE is set + // Use local dev console only when BOTH: SHOPIFY_CLI_1P_DEV is enabled AND SHOPIFY_USE_LOCAL_DEV_CONSOLE is set const anyPreviewableExtensions = reloadedApp.allExtensions.some((ext) => ext.isPreviewable) const devConsoleURL = `${network.proxyUrl}/extensions/dev-console` - const skipDevConsole = !firstPartyDev() && skipLocalDevConsole() - const useDevConsole = !skipDevConsole && anyPreviewableExtensions + const useDevConsole = firstPartyDev() && useLocalDevConsole() && anyPreviewableExtensions const previewURL = useDevConsole ? devConsoleURL : appPreviewUrl const graphiqlURL = shouldRenderGraphiQL diff --git a/packages/cli-kit/src/private/node/constants.ts b/packages/cli-kit/src/private/node/constants.ts index 6dbe539f8f..6b070fbf73 100644 --- a/packages/cli-kit/src/private/node/constants.ts +++ b/packages/cli-kit/src/private/node/constants.ts @@ -19,7 +19,7 @@ export const environmentVariables = { enableCliRedirect: 'SHOPIFY_CLI_ENABLE_CLI_REDIRECT', env: 'SHOPIFY_CLI_ENV', firstPartyDev: 'SHOPIFY_CLI_1P_DEV', - skipLocalDevConsole: 'SHOPIFY_SKIP_LOCAL_DEV_CONSOLE', + useLocalDevConsole: 'SHOPIFY_USE_LOCAL_DEV_CONSOLE', noAnalytics: 'SHOPIFY_CLI_NO_ANALYTICS', partnersToken: 'SHOPIFY_CLI_PARTNERS_TOKEN', runAsUser: 'SHOPIFY_RUN_AS_USER', diff --git a/packages/cli-kit/src/public/node/context/local.ts b/packages/cli-kit/src/public/node/context/local.ts index fde5bc4e49..7a5ab7d684 100644 --- a/packages/cli-kit/src/public/node/context/local.ts +++ b/packages/cli-kit/src/public/node/context/local.ts @@ -113,13 +113,14 @@ export function firstPartyDev(env = process.env): boolean { } /** - * Returns true if the local dev console should be skipped. + * Returns true if the local dev console should be used. + * This is an opt-in flag for 1P developers to use the local dev console. * * @param env - The environment variables from the environment of the current process. - * @returns True if SHOPIFY_SKIP_LOCAL_DEV_CONSOLE is truthy. + * @returns True if SHOPIFY_USE_LOCAL_DEV_CONSOLE is truthy. */ -export function skipLocalDevConsole(env = process.env): boolean { - return isTruthy(env[environmentVariables.skipLocalDevConsole]) +export function useLocalDevConsole(env = process.env): boolean { + return isTruthy(env[environmentVariables.useLocalDevConsole]) } /** From 091da61cabc9a55dc996fcb8f63853fc54e65ba1 Mon Sep 17 00:00:00 2001 From: Ryan Bahan Date: Tue, 27 Jan 2026 08:43:36 -0700 Subject: [PATCH 2/2] always use local console for 1p devs --- .../dev-session/dev-session-process.test.ts | 14 +++++--------- .../dev/processes/dev-session/dev-session.ts | 6 +++--- .../dev/processes/setup-dev-processes.test.ts | 8 +++----- .../services/dev/processes/setup-dev-processes.ts | 6 +++--- packages/cli-kit/src/private/node/constants.ts | 1 - packages/cli-kit/src/public/node/context/local.ts | 11 ----------- 6 files changed, 14 insertions(+), 32 deletions(-) diff --git a/packages/app/src/cli/services/dev/processes/dev-session/dev-session-process.test.ts b/packages/app/src/cli/services/dev/processes/dev-session/dev-session-process.test.ts index e28fbf1daf..895681ce27 100644 --- a/packages/app/src/cli/services/dev/processes/dev-session/dev-session-process.test.ts +++ b/packages/app/src/cli/services/dev/processes/dev-session/dev-session-process.test.ts @@ -20,7 +20,7 @@ import {AbortSignal, AbortController} from '@shopify/cli-kit/node/abort' import {flushPromises} from '@shopify/cli-kit/node/promises' import * as outputContext from '@shopify/cli-kit/node/ui/components' import {readdir} from '@shopify/cli-kit/node/fs' -import {firstPartyDev, useLocalDevConsole} from '@shopify/cli-kit/node/context/local' +import {firstPartyDev} from '@shopify/cli-kit/node/context/local' vi.mock('@shopify/cli-kit/node/fs') vi.mock('@shopify/cli-kit/node/archiver') @@ -33,7 +33,6 @@ vi.mock('@shopify/cli-kit/node/context/local', async (importOriginal) => { return { ...original, firstPartyDev: vi.fn().mockReturnValue(false), - useLocalDevConsole: vi.fn().mockReturnValue(false), } }) @@ -219,10 +218,9 @@ describe('pushUpdatesForDevSession', () => { contextSpy.mockRestore() }) - test('updates preview URL to appPreviewURL by default (local dev console is opt-in)', async () => { - // Given - dev console is NOT shown by default (requires both firstPartyDev AND useLocalDevConsole) + test('updates preview URL to appPreviewURL by default (local dev console only for 1P devs)', async () => { + // Given - dev console is NOT shown by default (only for 1P devs) vi.mocked(firstPartyDev).mockReturnValue(false) - vi.mocked(useLocalDevConsole).mockReturnValue(false) const extension = await testUIExtension({type: 'ui_extension'}) const newApp = testAppLinked({allExtensions: [extension]}) @@ -237,10 +235,9 @@ describe('pushUpdatesForDevSession', () => { expect(devSessionStatusManager.status.previewURL).toBe(options.appPreviewURL) }) - test('updates preview URL to appLocalProxyURL when 1P dev opts in with useLocalDevConsole', async () => { - // Given - dev console is shown only when firstPartyDev() AND useLocalDevConsole() + test('updates preview URL to appLocalProxyURL when 1P dev has previewable extensions', async () => { + // Given - dev console is shown for 1P devs with previewable extensions vi.mocked(firstPartyDev).mockReturnValue(true) - vi.mocked(useLocalDevConsole).mockReturnValue(true) const extension = await testUIExtension({type: 'ui_extension'}) const newApp = testAppLinked({allExtensions: [extension]}) @@ -254,7 +251,6 @@ describe('pushUpdatesForDevSession', () => { // Then expect(devSessionStatusManager.status.previewURL).toBe(options.appLocalProxyURL) vi.mocked(firstPartyDev).mockReturnValue(false) - vi.mocked(useLocalDevConsole).mockReturnValue(false) }) test('updates preview URL to appPreviewURL when no previewable extensions', async () => { diff --git a/packages/app/src/cli/services/dev/processes/dev-session/dev-session.ts b/packages/app/src/cli/services/dev/processes/dev-session/dev-session.ts index b6d9f39e6f..e4b3035eae 100644 --- a/packages/app/src/cli/services/dev/processes/dev-session/dev-session.ts +++ b/packages/app/src/cli/services/dev/processes/dev-session/dev-session.ts @@ -10,7 +10,7 @@ import {endHRTimeInMs, startHRTime} from '@shopify/cli-kit/node/hrtime' import {ClientError} from 'graphql-request' import {JsonMapType} from '@shopify/cli-kit/node/toml' import {AbortError} from '@shopify/cli-kit/node/error' -import {firstPartyDev, isUnitTest, useLocalDevConsole} from '@shopify/cli-kit/node/context/local' +import {firstPartyDev, isUnitTest} from '@shopify/cli-kit/node/context/local' import {dirname, joinPath} from '@shopify/cli-kit/node/path' import {readdir} from '@shopify/cli-kit/node/fs' import {SerialBatchProcessor} from '@shopify/cli-kit/node/serial-batch-processor' @@ -240,12 +240,12 @@ export class DevSession { /** * Update the preview URL, it only changes if we move between a non-previewable state and a previewable state. * (i.e. if we go from a state with no extensions to a state with ui-extensions or vice versa) - * Use local dev console only when BOTH: SHOPIFY_CLI_1P_DEV is enabled AND SHOPIFY_USE_LOCAL_DEV_CONSOLE is set. + * Use local dev console only for 1P developers (SHOPIFY_CLI_1P_DEV is enabled). * @param event - The app event */ private updatePreviewURL(event: AppEvent) { const hasPreview = event.app.allExtensions.filter((ext) => ext.isPreviewable).length > 0 - const useDevConsole = firstPartyDev() && useLocalDevConsole() && hasPreview + const useDevConsole = firstPartyDev() && hasPreview const newPreviewURL = useDevConsole ? this.options.appLocalProxyURL : this.options.appPreviewURL this.statusManager.updateStatus({previewURL: newPreviewURL}) } diff --git a/packages/app/src/cli/services/dev/processes/setup-dev-processes.test.ts b/packages/app/src/cli/services/dev/processes/setup-dev-processes.test.ts index db3168b0ce..bb9d3ff1bf 100644 --- a/packages/app/src/cli/services/dev/processes/setup-dev-processes.test.ts +++ b/packages/app/src/cli/services/dev/processes/setup-dev-processes.test.ts @@ -35,7 +35,7 @@ import {Config} from '@oclif/core' import {getEnvironmentVariables} from '@shopify/cli-kit/node/environment' import {isStorefrontPasswordProtected} from '@shopify/theme' import {fetchTheme} from '@shopify/cli-kit/node/themes/api' -import {firstPartyDev, useLocalDevConsole} from '@shopify/cli-kit/node/context/local' +import {firstPartyDev} from '@shopify/cli-kit/node/context/local' vi.mock('../../context/identifiers.js') vi.mock('@shopify/cli-kit/node/session.js') @@ -69,10 +69,8 @@ beforeEach(() => { role: 'theme', processing: false, }) - // By default, firstPartyDev is false + // By default, firstPartyDev is false (local dev console only shown for 1P devs) vi.mocked(firstPartyDev).mockReturnValue(false) - // By default, useLocalDevConsole is false (local dev console is opt-in for 1P devs) - vi.mocked(useLocalDevConsole).mockReturnValue(false) }) const appContextResult = { @@ -168,7 +166,7 @@ describe('setup-dev-processes', () => { graphiqlKey, }) - // Dev console is NOT shown by default (only shown when firstPartyDev() AND useLocalDevConsole()) + // Dev console is NOT shown by default (only shown for 1P devs) expect(res.previewUrl).toBe('https://store.myshopify.io/admin/oauth/redirect_from_cli?client_id=api-key') expect(res.processes[0]).toMatchObject({ type: 'web', diff --git a/packages/app/src/cli/services/dev/processes/setup-dev-processes.ts b/packages/app/src/cli/services/dev/processes/setup-dev-processes.ts index 545c490f72..0687de5a44 100644 --- a/packages/app/src/cli/services/dev/processes/setup-dev-processes.ts +++ b/packages/app/src/cli/services/dev/processes/setup-dev-processes.ts @@ -22,7 +22,7 @@ import {AppEventWatcher} from '../app-events/app-event-watcher.js' import {reloadApp} from '../../../models/app/loader.js' import {getAvailableTCPPort} from '@shopify/cli-kit/node/tcp' import {isTruthy} from '@shopify/cli-kit/node/context/utilities' -import {firstPartyDev, useLocalDevConsole} from '@shopify/cli-kit/node/context/local' +import {firstPartyDev} from '@shopify/cli-kit/node/context/local' import {getEnvironmentVariables} from '@shopify/cli-kit/node/environment' import {outputInfo} from '@shopify/cli-kit/node/output' @@ -100,10 +100,10 @@ export async function setupDevProcesses({ const appWatcher = new AppEventWatcher(reloadedApp, network.proxyUrl) // Decide on the appropriate preview URL for a session with these processes - // Use local dev console only when BOTH: SHOPIFY_CLI_1P_DEV is enabled AND SHOPIFY_USE_LOCAL_DEV_CONSOLE is set + // Use local dev console only for 1P developers (SHOPIFY_CLI_1P_DEV is enabled) const anyPreviewableExtensions = reloadedApp.allExtensions.some((ext) => ext.isPreviewable) const devConsoleURL = `${network.proxyUrl}/extensions/dev-console` - const useDevConsole = firstPartyDev() && useLocalDevConsole() && anyPreviewableExtensions + const useDevConsole = firstPartyDev() && anyPreviewableExtensions const previewURL = useDevConsole ? devConsoleURL : appPreviewUrl const graphiqlURL = shouldRenderGraphiQL diff --git a/packages/cli-kit/src/private/node/constants.ts b/packages/cli-kit/src/private/node/constants.ts index 6b070fbf73..d76fba7470 100644 --- a/packages/cli-kit/src/private/node/constants.ts +++ b/packages/cli-kit/src/private/node/constants.ts @@ -19,7 +19,6 @@ export const environmentVariables = { enableCliRedirect: 'SHOPIFY_CLI_ENABLE_CLI_REDIRECT', env: 'SHOPIFY_CLI_ENV', firstPartyDev: 'SHOPIFY_CLI_1P_DEV', - useLocalDevConsole: 'SHOPIFY_USE_LOCAL_DEV_CONSOLE', noAnalytics: 'SHOPIFY_CLI_NO_ANALYTICS', partnersToken: 'SHOPIFY_CLI_PARTNERS_TOKEN', runAsUser: 'SHOPIFY_RUN_AS_USER', diff --git a/packages/cli-kit/src/public/node/context/local.ts b/packages/cli-kit/src/public/node/context/local.ts index 7a5ab7d684..ce1afcffc5 100644 --- a/packages/cli-kit/src/public/node/context/local.ts +++ b/packages/cli-kit/src/public/node/context/local.ts @@ -112,17 +112,6 @@ export function firstPartyDev(env = process.env): boolean { return isTruthy(env[environmentVariables.firstPartyDev]) } -/** - * Returns true if the local dev console should be used. - * This is an opt-in flag for 1P developers to use the local dev console. - * - * @param env - The environment variables from the environment of the current process. - * @returns True if SHOPIFY_USE_LOCAL_DEV_CONSOLE is truthy. - */ -export function useLocalDevConsole(env = process.env): boolean { - return isTruthy(env[environmentVariables.useLocalDevConsole]) -} - /** * Return gitpodURL if we are running in gitpod. * Https://www.gitpod.io/docs/environment-variables#default-environment-variables.