From 2148bbe4a541053c29dfccb0635bfdad9b2cdf7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isaac=20Rold=C3=A1n?= Date: Tue, 7 Jul 2026 12:19:13 +0200 Subject: [PATCH 1/2] Remove dev session support branching Assisted-By: devx/782ef931-ac0a-4cc4-bff1-a2511c379664 --- .changeset/remove-supports-dev-sessions.md | 5 + .../app/src/cli/models/app/app.test-data.ts | 2 - .../config/__snapshots__/link.test.ts.snap | 5 +- .../services/app/config/link-service.test.ts | 1 - .../src/cli/services/app/config/link.test.ts | 6 +- .../app/src/cli/services/app/config/link.ts | 2 +- .../app/src/cli/services/dev-clean.test.ts | 11 +- packages/app/src/cli/services/dev-clean.ts | 6 - packages/app/src/cli/services/dev.test.ts | 116 +---------------- packages/app/src/cli/services/dev.ts | 122 ++---------------- .../dev/processes/setup-dev-processes.test.ts | 10 +- .../dev/processes/setup-dev-processes.ts | 26 ++-- packages/app/src/cli/services/dev/ui.test.tsx | 12 +- packages/app/src/cli/services/dev/ui.tsx | 54 ++------ .../app/src/cli/services/dev/urls.test.ts | 8 -- packages/app/src/cli/services/dev/urls.ts | 3 +- .../utilities/developer-platform-client.ts | 1 - .../app-management-client.ts | 1 - .../partners-client.ts | 1 - 19 files changed, 63 insertions(+), 329 deletions(-) create mode 100644 .changeset/remove-supports-dev-sessions.md diff --git a/.changeset/remove-supports-dev-sessions.md b/.changeset/remove-supports-dev-sessions.md new file mode 100644 index 00000000000..aa0359c6959 --- /dev/null +++ b/.changeset/remove-supports-dev-sessions.md @@ -0,0 +1,5 @@ +--- +'@shopify/app': patch +--- + +Always use dev sessions for app dev diff --git a/packages/app/src/cli/models/app/app.test-data.ts b/packages/app/src/cli/models/app/app.test-data.ts index 2104a8f687a..7ef89aab3a1 100644 --- a/packages/app/src/cli/models/app/app.test-data.ts +++ b/packages/app/src/cli/models/app/app.test-data.ts @@ -1353,7 +1353,6 @@ export function testDeveloperPlatformClient(stubs: Partial when remote app is new and supports dev sessions then include automatically_update_urls_on_dev = true 1`] = ` +exports[`link > when remote app is new then include automatically_update_urls_on_dev = true 1`] = ` "# Learn more about configuring your app at https://shopify.dev/docs/apps/tools/cli/configuration application_url = "https://example.com" diff --git a/packages/app/src/cli/services/app/config/link-service.test.ts b/packages/app/src/cli/services/app/config/link-service.test.ts index 1fb6aba1059..fca01a594c5 100644 --- a/packages/app/src/cli/services/app/config/link-service.test.ts +++ b/packages/app/src/cli/services/app/config/link-service.test.ts @@ -29,7 +29,6 @@ beforeEach(async () => { function buildDeveloperPlatformClient(): DeveloperPlatformClient { return testDeveloperPlatformClient({ - supportsDevSessions: true, async appFromIdentifiers(apiKey: string): Promise { switch (apiKey) { case 'api-key': diff --git a/packages/app/src/cli/services/app/config/link.test.ts b/packages/app/src/cli/services/app/config/link.test.ts index ff69cf0f38a..d26f6ddf9a5 100644 --- a/packages/app/src/cli/services/app/config/link.test.ts +++ b/packages/app/src/cli/services/app/config/link.test.ts @@ -241,6 +241,7 @@ describe('link', () => { }, build: { include_config_on_deploy: true, + automatically_update_urls_on_dev: true, }, }) expect(content).toMatchSnapshot() @@ -342,6 +343,7 @@ describe('link', () => { }, build: { include_config_on_deploy: true, + automatically_update_urls_on_dev: true, }, }) expect(content).toMatchSnapshot() @@ -1195,14 +1197,14 @@ describe('link', () => { }) }) - test('when remote app is new and supports dev sessions then include automatically_update_urls_on_dev = true', async () => { + test('when remote app is new then include automatically_update_urls_on_dev = true', async () => { await inTemporaryDirectory(async (tmp) => { // Given const filePath = joinPath(tmp, 'shopify.app.toml') const initialContent = `scopes = "" ` writeFileSync(filePath, initialContent) - const developerPlatformClient = buildDeveloperPlatformClient({supportsDevSessions: true}) + const developerPlatformClient = buildDeveloperPlatformClient() const options: LinkOptions = { directory: tmp, developerPlatformClient, diff --git a/packages/app/src/cli/services/app/config/link.ts b/packages/app/src/cli/services/app/config/link.ts index df7722cb194..3104a35b868 100644 --- a/packages/app/src/cli/services/app/config/link.ts +++ b/packages/app/src/cli/services/app/config/link.ts @@ -360,7 +360,7 @@ export async function overwriteLocalConfigFileWithRemoteAppConfiguration(options existingBuildOptions: localAppOptions.existingBuildOptions, linkedAppAndClientIdFromFileAreInSync: localAppOptions.localAppIdMatchedRemote, linkedAppWasNewlyCreated: Boolean(remoteApp.newApp), - defaultToUpdateUrlsOnDev: developerPlatformClient.supportsDevSessions, + defaultToUpdateUrlsOnDev: true, }), } diff --git a/packages/app/src/cli/services/dev-clean.test.ts b/packages/app/src/cli/services/dev-clean.test.ts index 258dadf48f1..3d8fe124c37 100644 --- a/packages/app/src/cli/services/dev-clean.test.ts +++ b/packages/app/src/cli/services/dev-clean.test.ts @@ -44,19 +44,10 @@ describe('devClean', () => { // When/Then await expect(devClean(mockOptions)).rejects.toThrow(`Failed to stop the dev preview: ${errorMessage}`) }) - - test('throws AbortError when devSessions are not supported', async () => { - // Given - mockOptions.appContextResult.developerPlatformClient = customDevPlatformClient(undefined, false) - - // When/Then - await expect(devClean(mockOptions)).rejects.toThrow('Dev preview is not supported for this app.') - }) }) -function customDevPlatformClient(devSessionDeleteError?: string, supportsDevSessions = true) { +function customDevPlatformClient(devSessionDeleteError?: string) { return testDeveloperPlatformClient({ - supportsDevSessions, devSessionDelete: vi.fn().mockResolvedValue({ devSessionDelete: { userErrors: devSessionDeleteError ? [{message: devSessionDeleteError}] : [], diff --git a/packages/app/src/cli/services/dev-clean.ts b/packages/app/src/cli/services/dev-clean.ts index cbd781dd1b3..ee3118b365e 100644 --- a/packages/app/src/cli/services/dev-clean.ts +++ b/packages/app/src/cli/services/dev-clean.ts @@ -12,12 +12,6 @@ export async function devClean(options: DevCleanOptions) { const client = options.appContextResult.developerPlatformClient const remoteApp = options.appContextResult.remoteApp - if (!client.supportsDevSessions) { - throw new AbortError( - `Dev preview is not supported for this app. It's valid only for apps created on the Next-Gen Dev Platform.`, - ) - } - const result = await client.devSessionDelete({shopFqdn: options.store.shopDomain, appId: remoteApp.id}) if (result.devSessionDelete?.userErrors.length) { diff --git a/packages/app/src/cli/services/dev.test.ts b/packages/app/src/cli/services/dev.test.ts index 2806e279347..119576f884d 100644 --- a/packages/app/src/cli/services/dev.test.ts +++ b/packages/app/src/cli/services/dev.test.ts @@ -1,4 +1,4 @@ -import {dev, warnIfScopesDifferBeforeDev, blockIfMigrationIncomplete} from './dev.js' +import {dev, blockIfMigrationIncomplete} from './dev.js' import {setupDevProcesses} from './dev/processes/setup-dev-processes.js' import {renderDev} from './dev/ui.js' import {fetchAppRemoteConfiguration} from './app/select-app.js' @@ -12,7 +12,6 @@ import { } from '../models/app/app.test-data.js' import metadata from '../metadata.js' import {describe, expect, test, vi} from 'vitest' -import {mockAndCaptureOutput} from '@shopify/cli-kit/node/testing/output' import {hashString} from '@shopify/cli-kit/node/crypto' import {reportAnalyticsEvent} from '@shopify/cli-kit/node/analytics' import {checkPortAvailability, getAvailableTCPPort} from '@shopify/cli-kit/node/tcp' @@ -56,7 +55,7 @@ describe('dev', () => { remoteApp: testOrganizationApp({apiKey: 'api-key'}), organization: testOrganization(), specifications: [], - developerPlatformClient: testDeveloperPlatformClient({supportsDevSessions: false}), + developerPlatformClient: testDeveloperPlatformClient(), store, directory: app.directory, update: false, @@ -87,97 +86,15 @@ describe('dev', () => { }) }) -describe('warnIfScopesDifferBeforeDev', () => { - const appsWithScopes = (local: string, remote: string) => { - const localApp = testAppLinked({}) - const remoteApp = testOrganizationApp() - localApp.configuration = { - ...localApp.configuration, - access_scopes: {scopes: local, use_legacy_install_flow: false}, - } - remoteApp.configuration = { - ...remoteApp.configuration, - access_scopes: {scopes: remote, use_legacy_install_flow: false}, - } as any - return { - localApp, - remoteApp, - } - } - - test('does not warn if the scopes are the same', async () => { - // Given - const developerPlatformClient = testDeveloperPlatformClient({supportsDevSessions: false}) - const apps = appsWithScopes('scopes1,scopes2', 'scopes1,scopes2') - - // When - const mockOutput = mockAndCaptureOutput() - mockOutput.clear() - await warnIfScopesDifferBeforeDev({ - ...apps, - developerPlatformClient, - commandOptions: {project: testProject()} as any, - }) - - // Then - expect(mockOutput.warn()).toBe('') - }) - - test('warns if the scopes differ', async () => { - // Given - const apps = appsWithScopes('scopes1,scopes2', 'scopes3,scopes4') - const developerPlatformClient = testDeveloperPlatformClient({supportsDevSessions: false}) - - // When - const mockOutput = mockAndCaptureOutput() - mockOutput.clear() - await warnIfScopesDifferBeforeDev({ - ...apps, - developerPlatformClient, - commandOptions: {project: testProject()} as any, - }) - - // Then - expect(mockOutput.warn()).toContain("The scopes in your TOML don't match") - }) - - test('silent if scopes differ cosmetically', async () => { - // Given - const apps = appsWithScopes('scopes1, scopes2 ', ' scopes2, scopes1') - const developerPlatformClient = testDeveloperPlatformClient({supportsDevSessions: false}) - - // When - const mockOutput = mockAndCaptureOutput() - mockOutput.clear() - await warnIfScopesDifferBeforeDev({ - ...apps, - developerPlatformClient, - commandOptions: {project: testProject()} as any, - }) - - // Then - expect(mockOutput.warn()).toBe('') - }) -}) - describe('blockIfMigrationIncomplete', () => { const baseConfig = () => ({ localApp: testAppLinked({}), remoteApp: testOrganizationApp(), - developerPlatformClient: testDeveloperPlatformClient({supportsDevSessions: true}), - }) - - test('does nothing when dev sessions not supported', async () => { - const devConfig = { - ...baseConfig(), - developerPlatformClient: testDeveloperPlatformClient({supportsDevSessions: false}), - } as any - await expect(blockIfMigrationIncomplete(devConfig)).resolves.toBeUndefined() + developerPlatformClient: testDeveloperPlatformClient(), }) test('does nothing when all remote extensions have ids (migrated)', async () => { const developerPlatformClient = testDeveloperPlatformClient({ - supportsDevSessions: true, async appExtensionRegistrations() { return { app: { @@ -202,7 +119,6 @@ describe('blockIfMigrationIncomplete', () => { test('does nothing remote extensions dont have uids but are webhook subscriptions', async () => { const developerPlatformClient = testDeveloperPlatformClient({ - supportsDevSessions: true, async appExtensionRegistrations() { return { app: { @@ -227,7 +143,6 @@ describe('blockIfMigrationIncomplete', () => { test('throws AbortError when some remote extensions are missing ids (not migrated)', async () => { const developerPlatformClient = testDeveloperPlatformClient({ - supportsDevSessions: true, async appExtensionRegistrations() { return { app: { @@ -249,29 +164,4 @@ describe('blockIfMigrationIncomplete', () => { await expect(blockIfMigrationIncomplete(devConfig)).rejects.toThrow(/need to be assigned uid identifiers/) }) - - test('does nothing for Partners with missing ids (not migrated)', async () => { - const developerPlatformClient = testDeveloperPlatformClient({ - supportsDevSessions: false, - async appExtensionRegistrations() { - return { - app: { - extensionRegistrations: [ - {id: '', uuid: 'u1', title: 'Legacy Ext 1', type: 'theme'}, - {uuid: 'u2', title: 'Legacy Ext 2', type: 'web_pixel_extension'}, - ], - configurationRegistrations: [], - dashboardManagedExtensionRegistrations: [], - }, - } as any - }, - }) - - const devConfig = { - ...baseConfig(), - developerPlatformClient, - } as any - - await expect(blockIfMigrationIncomplete(devConfig)).resolves.toBeUndefined() - }) }) diff --git a/packages/app/src/cli/services/dev.ts b/packages/app/src/cli/services/dev.ts index 0d30481a791..a73ceb5fcc4 100644 --- a/packages/app/src/cli/services/dev.ts +++ b/packages/app/src/cli/services/dev.ts @@ -6,15 +6,8 @@ import { getURLs, shouldOrPromptUpdateURLs, startTunnelPlugin, - updateURLs, } from './dev/urls.js' -import { - enableDeveloperPreview, - disableDeveloperPreview, - developerPreviewUpdate, - showReusedDevValues, -} from './context.js' -import {fetchAppPreviewMode} from './dev/fetch.js' +import {showReusedDevValues} from './context.js' import {installAppDependencies} from './dependencies.js' import {DevConfig, DevProcesses, setupDevProcesses} from './dev/processes/setup-dev-processes.js' import {frontAndBackendConfig} from './dev/processes/utils.js' @@ -22,13 +15,12 @@ import {renderDev} from './dev/ui.js' import {DeveloperPreviewController} from './dev/ui/components/Dev.js' import {DevProcessFunction} from './dev/processes/types.js' import {getCachedAppInfo, setCachedAppInfo} from './local-storage.js' -import {canEnablePreviewMode} from './extensions/common.js' import {fetchAppRemoteConfiguration} from './app/select-app.js' import {DevSessionStatusManager} from './dev/processes/dev-session/dev-session-status-manager.js' import {TunnelMode} from './dev/tunnel-mode.js' import {PortDetail, renderPortWarnings} from './dev/port-warnings.js' import {DeveloperPlatformClient} from '../utilities/developer-platform-client.js' -import {Web, getAppScopesArray, AppLinkedInterface} from '../models/app/app.js' +import {Web, AppLinkedInterface} from '../models/app/app.js' import {Project} from '../models/project/project.js' import {Organization, OrganizationApp, OrganizationStore} from '../models/organization.js' import {getAnalyticsTunnelType} from '../utilities/analytics.js' @@ -44,10 +36,8 @@ import {AbortController} from '@shopify/cli-kit/node/abort' import {checkPortAvailability, getAvailableTCPPort} from '@shopify/cli-kit/node/tcp' import {TunnelClient} from '@shopify/cli-kit/node/plugins/tunnel' import {getBackendPort} from '@shopify/cli-kit/node/environment' -import {basename} from '@shopify/cli-kit/node/path' -import {renderWarning} from '@shopify/cli-kit/node/ui' import {reportAnalyticsEvent} from '@shopify/cli-kit/node/analytics' -import {OutputProcess, formatPackageManagerCommand} from '@shopify/cli-kit/node/output' +import {OutputProcess} from '@shopify/cli-kit/node/output' import {hashString} from '@shopify/cli-kit/node/crypto' import {AbortError} from '@shopify/cli-kit/node/error' @@ -167,7 +157,6 @@ async function prepareForDev(commandOptions: DevOptions): Promise { cachedUpdateURLs, remoteApp, apiKey, - developerPlatformClient, ) return { @@ -186,63 +175,11 @@ async function prepareForDev(commandOptions: DevOptions): Promise { } async function actionsBeforeSettingUpDevProcesses(devConfig: DevConfig) { - await warnIfScopesDifferBeforeDev(devConfig) await blockIfMigrationIncomplete(devConfig) } -/** - * Show a warning if the scopes in the local app configuration do not match the scopes in the remote app configuration. - * - * This is to flag that the developer may wish to run `shopify app deploy` to push the latest scopes. - * - */ -export async function warnIfScopesDifferBeforeDev({ - localApp, - remoteApp, - developerPlatformClient, - commandOptions, -}: Pick) { - if (developerPlatformClient.supportsDevSessions) return - const localAccess = localApp.configuration.access_scopes - const remoteAccess = remoteApp.configuration?.access_scopes - - const rationaliseScopes = (scopeString: string | undefined) => { - if (!scopeString) return scopeString - return scopeString - .split(',') - .map((scope) => scope.trim()) - .sort() - .join(',') - } - const localScopes = rationaliseScopes(localAccess?.scopes) - const remoteScopes = rationaliseScopes(remoteAccess?.scopes) - - if (!localAccess?.use_legacy_install_flow && localScopes !== remoteScopes) { - const nextSteps = [ - [ - 'Run', - {command: formatPackageManagerCommand(commandOptions.project.packageManager, 'shopify app deploy')}, - 'to push your scopes to the Partner Dashboard', - ], - ] - - renderWarning({ - headline: [`The scopes in your TOML don't match the scopes in your Partner Dashboard`], - body: [ - `Scopes in ${basename(localApp.configPath)}:`, - scopesMessage(getAppScopesArray(localApp.configuration)), - '\n', - 'Scopes in Partner Dashboard:', - scopesMessage(remoteAccess?.scopes?.split(',') ?? []), - ], - nextSteps, - }) - } -} - export async function blockIfMigrationIncomplete(devConfig: DevConfig) { const {developerPlatformClient, remoteApp} = devConfig - if (!developerPlatformClient.supportsDevSessions) return const extensions = (await developerPlatformClient.appExtensionRegistrations(remoteApp)).app.extensionRegistrations if ( @@ -279,7 +216,6 @@ async function handleUpdatingOfPartnerUrls( cachedUpdateURLs: boolean | undefined, remoteApp: OrganizationApp, apiKey: string, - developerPlatformClient: DeveloperPlatformClient, ) { const {backendConfig, frontendConfig} = frontAndBackendConfig(webs) let shouldUpdateURLs = false @@ -298,19 +234,10 @@ async function handleUpdatingOfPartnerUrls( localApp, apiKey, newURLs, - developerPlatformClient, }) if (shouldUpdateURLs) { - if (developerPlatformClient.supportsDevSessions) { - // For dev sessions, store the new URLs in the local app so that the manifest can be patched with them - // The local toml is not updated. - localApp.setDevApplicationURLs(newURLs) - } else { - // When running dev app urls are pushed directly to API Client config instead of creating a new app version - // so current app version and API Client config will have diferent url values. - await updateURLs(newURLs, apiKey, developerPlatformClient, localApp) - } + localApp.setDevApplicationURLs(newURLs) } } } @@ -410,14 +337,7 @@ async function launchDevProcesses({ const apiKey = config.remoteApp.apiKey const developerPlatformClient = config.developerPlatformClient const app = { - canEnablePreviewMode: developerPlatformClient.supportsDevSessions - ? false - : await canEnablePreviewMode({ - localApp: config.localApp, - developerPlatformClient, - apiKey, - organizationId: config.remoteApp.organizationId, - }), + canEnablePreviewMode: false, developmentStorePreviewEnabled: config.remoteApp.developmentStorePreviewEnabled, apiKey, id: config.remoteApp.id, @@ -432,7 +352,7 @@ async function launchDevProcesses({ graphiqlPort: config.graphiqlPort, app, abortController, - developerPreview: developerPreviewController(apiKey, developerPlatformClient), + developerPreview: developerPreviewController(), shopFqdn: config.storeFqdn, devSessionStatusManager, appURL: config.localApp.devApplicationURLs?.applicationUrl, @@ -443,24 +363,12 @@ async function launchDevProcesses({ }) } -function developerPreviewController( - apiKey: string, - developerPlatformClient: DeveloperPlatformClient, -): DeveloperPreviewController { - if (developerPlatformClient.supportsDevSessions) { - return { - fetchMode: () => Promise.resolve(false), - enable: () => Promise.resolve(false), - disable: () => Promise.resolve(), - update: () => Promise.resolve(false), - } - } - +function developerPreviewController(): DeveloperPreviewController { return { - fetchMode: async () => Boolean(await fetchAppPreviewMode(apiKey, developerPlatformClient)), - enable: async () => enableDeveloperPreview({apiKey, developerPlatformClient}), - disable: async () => disableDeveloperPreview({apiKey, developerPlatformClient}), - update: async (state: boolean) => developerPreviewUpdate({apiKey, developerPlatformClient, enabled: state}), + fetchMode: () => Promise.resolve(false), + enable: () => Promise.resolve(false), + disable: () => Promise.resolve(), + update: () => Promise.resolve(false), } } @@ -486,14 +394,6 @@ async function logMetadataForDev(options: { })) } -function scopesMessage(scopes: string[]) { - return { - list: { - items: scopes.length === 0 ? ['No scopes'] : scopes, - }, - } -} - async function validateCustomPorts(webConfigs: Web[], graphiqlPort: number) { const allPorts = webConfigs.map((config) => config.configuration.port).filter((port) => port) const duplicatedPort = allPorts.find((port, index) => allPorts.indexOf(port) !== index) 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 ee33c9a711c..de0626c6c3a 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 @@ -213,7 +213,8 @@ describe('setup-dev-processes', () => { appId: '1234', }, }) - expect(res.processes[3]).toMatchObject({ + const themeProcess = res.processes.find((process) => process.type === 'theme-app-extensions') + expect(themeProcess).toMatchObject({ type: 'theme-app-extensions', prefix: 'theme-extensions', function: runThemeAppExtensionsServer, @@ -233,7 +234,8 @@ describe('setup-dev-processes', () => { themeExtensionPort: 9293, }, }) - expect(res.processes[4]).toMatchObject({ + const sendWebhookProcess = res.processes.find((process) => process.type === 'send-webhook') + expect(sendWebhookProcess).toMatchObject({ type: 'send-webhook', prefix: 'webhooks', function: sendWebhook, @@ -347,8 +349,8 @@ describe('setup-dev-processes', () => { expect(res.graphiqlUrl).toBe(`http://localhost:${graphiqlPort}/graphiql?key=${encodeURIComponent(expectedKey)}`) }) - test('process list includes dev-session when useDevSession is true', async () => { - const developerPlatformClient: DeveloperPlatformClient = testDeveloperPlatformClient({supportsDevSessions: true}) + test('process list includes dev-session', async () => { + const developerPlatformClient: DeveloperPlatformClient = testDeveloperPlatformClient() const storeFqdn = 'store.myshopify.io' const storeId = '123456789' const remoteAppUpdated = true 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 8fe5b460bff..f0ec1c92b1c 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 @@ -151,20 +151,18 @@ export async function setupDevProcesses({ appDirectory: reloadedApp.directory, appWatcher, }), - developerPlatformClient.supportsDevSessions - ? await setupDevSessionProcess({ - app: reloadedApp, - apiKey, - developerPlatformClient, - url: network.proxyUrl, - appId: remoteApp.id, - organizationId: remoteApp.organizationId, - storeFqdn, - appWatcher, - appPreviewURL: appPreviewUrl, - devSessionStatusManager, - }) - : undefined, + await setupDevSessionProcess({ + app: reloadedApp, + apiKey, + developerPlatformClient, + url: network.proxyUrl, + appId: remoteApp.id, + organizationId: remoteApp.organizationId, + storeFqdn, + appWatcher, + appPreviewURL: appPreviewUrl, + devSessionStatusManager, + }), await setupPreviewThemeAppExtensionsProcess({ remoteApp, localApp: reloadedApp, diff --git a/packages/app/src/cli/services/dev/ui.test.tsx b/packages/app/src/cli/services/dev/ui.test.tsx index fceb2eebf76..425b1679e99 100644 --- a/packages/app/src/cli/services/dev/ui.test.tsx +++ b/packages/app/src/cli/services/dev/ui.test.tsx @@ -1,5 +1,4 @@ import {renderDev} from './ui.js' -import {Dev} from './ui/components/Dev.js' import {DevSessionUI} from './ui/components/DevSessionUI.js' import {DevSessionStatusManager} from './processes/dev-session/dev-session-status-manager.js' import {testDeveloperPlatformClient} from '../../models/app/app.test-data.js' @@ -9,7 +8,6 @@ import {AbortController} from '@shopify/cli-kit/node/abort' import {terminalSupportsPrompting} from '@shopify/cli-kit/node/system' vi.mock('@shopify/cli-kit/node/system') -vi.mock('./ui/components/Dev.js') vi.mock('../context.js') vi.mock('./ui/components/DevSessionUI.js') @@ -64,7 +62,6 @@ describe('ui', () => { devSessionStatusManager, }) - expect(vi.mocked(Dev)).not.toHaveBeenCalled() expect(concurrentProcess.action).toHaveBeenNthCalledWith( 1, process.stdout, @@ -189,7 +186,7 @@ describe('ui', () => { expect(developerPreview.disable).not.toHaveBeenCalled() }) - test('uses ink when terminal supports TTY', async () => { + test('renders dev session UI when terminal supports TTY', async () => { vi.mocked(terminalSupportsPrompting).mockReturnValue(true) const concurrentProcess = { prefix: 'prefix', @@ -227,11 +224,11 @@ describe('ui', () => { await new Promise((resolve) => setTimeout(resolve, 10)) - expect(vi.mocked(Dev)).toHaveBeenCalled() + expect(vi.mocked(DevSessionUI)).toHaveBeenCalled() expect(concurrentProcess.action).not.toHaveBeenCalled() }) - test('renders DevSessionUI when terminal supports TTY and app supports dev sessions', async () => { + test('renders DevSessionUI when terminal supports TTY', async () => { vi.mocked(terminalSupportsPrompting).mockReturnValue(true) const concurrentProcess = { prefix: 'prefix', @@ -250,7 +247,6 @@ describe('ui', () => { id: '123', developerPlatformClient: { ...developerPlatformClient, - supportsDevSessions: true, devSessionDelete: vi.fn(), }, extensions: [], @@ -283,7 +279,6 @@ describe('ui', () => { // React 19 no longer passes legacy context as second argument undefined, ) - expect(vi.mocked(Dev)).not.toHaveBeenCalled() }) test('calls devSessionDelete when DevSessionUI aborts', async () => { @@ -301,7 +296,6 @@ describe('ui', () => { id: '123', developerPlatformClient: { ...developerPlatformClient, - supportsDevSessions: true, devSessionDelete: vi.fn(), }, extensions: [], diff --git a/packages/app/src/cli/services/dev/ui.tsx b/packages/app/src/cli/services/dev/ui.tsx index af9fa1e5273..aa4a29bf732 100644 --- a/packages/app/src/cli/services/dev/ui.tsx +++ b/packages/app/src/cli/services/dev/ui.tsx @@ -1,11 +1,9 @@ -import {Dev, DevProps} from './ui/components/Dev.js' +import {type DevProps} from './ui/components/Dev.js' import {DevSessionUI} from './ui/components/DevSessionUI.js' import {DevSessionStatusManager} from './processes/dev-session/dev-session-status-manager.js' import React from 'react' import {render} from '@shopify/cli-kit/node/ui' import {terminalSupportsPrompting} from '@shopify/cli-kit/node/system' -import {isTruthy} from '@shopify/cli-kit/node/context/utilities' -import {isUnitTest} from '@shopify/cli-kit/node/context/local' export async function renderDev({ processes, @@ -13,7 +11,6 @@ export async function renderDev({ app, abortController, graphiqlUrl, - graphiqlPort, developerPreview, shopFqdn, devSessionStatusManager, @@ -30,17 +27,7 @@ export async function renderDev({ configPath?: string localURL?: string }) { - if (!terminalSupportsPrompting()) { - await renderDevNonInteractive({ - processes, - previewUrl, - graphiqlUrl, - app, - abortController, - developerPreview, - shopFqdn, - }) - } else if (app.developerPlatformClient.supportsDevSessions) { + if (terminalSupportsPrompting()) { return render( , - { - exitOnCtrlC: false, - }, - ) } + + await renderDevNonInteractive({ + processes, + previewUrl, + graphiqlUrl, + app, + abortController, + developerPreview, + shopFqdn, + }) } async function renderDevNonInteractive({ @@ -105,13 +85,3 @@ async function renderDevNonInteractive({ }), ) } - -// We should make this better later, but for now, we'll hardcode and see how it's received. -function isEditionWeek() { - if (isTruthy(process.env.IS_EDITION_WEEK)) return true - if (isUnitTest()) return false - const editionStart = new Date('2024-01-31T17:00:00.000Z') - const editionWeekEnd = new Date('2024-02-07T17:00:00.000Z') - const now = new Date() - return now >= editionStart && now <= editionWeekEnd -} diff --git a/packages/app/src/cli/services/dev/urls.test.ts b/packages/app/src/cli/services/dev/urls.test.ts index e21ec3aff65..204efbe56f9 100644 --- a/packages/app/src/cli/services/dev/urls.test.ts +++ b/packages/app/src/cli/services/dev/urls.test.ts @@ -206,7 +206,6 @@ describe('shouldOrPromptUpdateURLs', () => { appDirectory: '/path', newApp: true, apiKey: 'api-key', - developerPlatformClient: testDeveloperPlatformClient(), newURLs: { applicationUrl: 'https://example.com/home', redirectUrlWhitelist: ['https://example.com/auth/callback'], @@ -227,7 +226,6 @@ describe('shouldOrPromptUpdateURLs', () => { appDirectory: '/path', cachedUpdateURLs: true, apiKey: 'api-key', - developerPlatformClient: testDeveloperPlatformClient(), newURLs: { applicationUrl: 'https://example.com/home', redirectUrlWhitelist: ['https://example.com/auth/callback'], @@ -248,7 +246,6 @@ describe('shouldOrPromptUpdateURLs', () => { appDirectory: '/path', cachedUpdateURLs: false, apiKey: 'api-key', - developerPlatformClient: testDeveloperPlatformClient(), newURLs: { applicationUrl: 'https://example.com/home', redirectUrlWhitelist: ['https://example.com/auth/callback'], @@ -268,7 +265,6 @@ describe('shouldOrPromptUpdateURLs', () => { currentURLs, appDirectory: '/path', apiKey: 'api-key', - developerPlatformClient: testDeveloperPlatformClient(), newURLs: { applicationUrl: 'https://example.com/home', redirectUrlWhitelist: ['https://example.com/auth/callback'], @@ -289,7 +285,6 @@ describe('shouldOrPromptUpdateURLs', () => { currentURLs, appDirectory: '/path', apiKey: 'api-key', - developerPlatformClient: testDeveloperPlatformClient(), newURLs: { applicationUrl: 'https://example.com/home', redirectUrlWhitelist: ['https://example.com/auth/callback'], @@ -310,7 +305,6 @@ describe('shouldOrPromptUpdateURLs', () => { currentURLs, appDirectory: '/path', apiKey: 'api-key', - developerPlatformClient: testDeveloperPlatformClient(), newURLs: { applicationUrl: 'https://example.com/home', redirectUrlWhitelist: ['https://example.com/auth/callback'], @@ -335,7 +329,6 @@ describe('shouldOrPromptUpdateURLs', () => { appDirectory: '/path', apiKey: 'api-key', localApp: testApp({configuration: {...DEFAULT_CONFIG, client_id: 'different'}}) as AppLinkedInterface, - developerPlatformClient: testDeveloperPlatformClient(), newURLs: { applicationUrl: 'https://example.com/home', redirectUrlWhitelist: ['https://example.com/auth/callback'], @@ -360,7 +353,6 @@ describe('shouldOrPromptUpdateURLs', () => { appDirectory: '/path', apiKey: 'api-key', localApp: localApp as AppLinkedInterface, - developerPlatformClient: testDeveloperPlatformClient(), newURLs: { applicationUrl: 'https://example.com/home', redirectUrlWhitelist: ['https://example.com/auth/callback'], diff --git a/packages/app/src/cli/services/dev/urls.ts b/packages/app/src/cli/services/dev/urls.ts index 8db28d4a880..d4f356b5666 100644 --- a/packages/app/src/cli/services/dev/urls.ts +++ b/packages/app/src/cli/services/dev/urls.ts @@ -227,7 +227,6 @@ interface ShouldOrPromptUpdateURLsOptions { localApp?: AppLinkedInterface apiKey: string newURLs: ApplicationURLs - developerPlatformClient: DeveloperPlatformClient } export async function shouldOrPromptUpdateURLs(options: ShouldOrPromptUpdateURLsOptions): Promise { @@ -237,7 +236,7 @@ export async function shouldOrPromptUpdateURLs(options: ShouldOrPromptUpdateURLs if (options.cachedUpdateURLs === undefined) { shouldUpdateURLs = await updateURLsPrompt( - options.developerPlatformClient.supportsDevSessions, + true, options.currentURLs.applicationUrl, options.currentURLs.redirectUrlWhitelist, options.newURLs, diff --git a/packages/app/src/cli/utilities/developer-platform-client.ts b/packages/app/src/cli/utilities/developer-platform-client.ts index 7ffc52e1d6a..a5af2a5f01b 100644 --- a/packages/app/src/cli/utilities/developer-platform-client.ts +++ b/packages/app/src/cli/utilities/developer-platform-client.ts @@ -228,7 +228,6 @@ export interface DeveloperPlatformClient { readonly clientName: ClientName readonly webUiName: string readonly supportsAtomicDeployments: boolean - readonly supportsDevSessions: boolean readonly supportsStoreSearch: boolean readonly organizationSource: OrganizationSource readonly bundleFormat: 'zip' | 'br' 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 bb9fc2b2cef..a17b9bd857f 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 @@ -198,7 +198,6 @@ export class AppManagementClient implements DeveloperPlatformClient { public readonly clientName = ClientName.AppManagement public readonly webUiName = 'Developer Dashboard' public readonly supportsAtomicDeployments = true - public readonly supportsDevSessions = true public readonly supportsStoreSearch = true public readonly organizationSource = OrganizationSource.BusinessPlatform public readonly bundleFormat = 'br' 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 bc48f918dbb..e17d136507b 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 @@ -209,7 +209,6 @@ export class PartnersClient implements DeveloperPlatformClient { public readonly clientName = ClientName.Partners public readonly webUiName = 'Partner Dashboard' public readonly supportsAtomicDeployments = false - public readonly supportsDevSessions = false public readonly supportsStoreSearch = false public readonly organizationSource = OrganizationSource.Partners public readonly bundleFormat = 'zip' From 87d82ffa8db0a1bfcca6c688acfbf402ba5112de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isaac=20Rold=C3=A1n?= Date: Tue, 7 Jul 2026 12:28:01 +0200 Subject: [PATCH 2/2] Remove unused developer preview helpers Assisted-By: devx/782ef931-ac0a-4cc4-bff1-a2511c379664 --- packages/app/src/cli/services/context.ts | 44 ---------------------- packages/app/src/cli/services/dev/fetch.ts | 9 ----- 2 files changed, 53 deletions(-) diff --git a/packages/app/src/cli/services/context.ts b/packages/app/src/cli/services/context.ts index 41555451f9d..5dabb0beb08 100644 --- a/packages/app/src/cli/services/context.ts +++ b/packages/app/src/cli/services/context.ts @@ -13,10 +13,6 @@ import {getAppConfigurationFileName} from '../models/app/loader.js' import {ExtensionInstance} from '../models/extensions/extension-instance.js' import {ExtensionRegistration} from '../api/graphql/all_app_extension_registrations.js' -import { - DevelopmentStorePreviewUpdateInput, - DevelopmentStorePreviewUpdateSchema, -} from '../api/graphql/development_preview.js' import { allDeveloperPlatformClients, CreateAppOptions, @@ -410,43 +406,3 @@ export async function logMetadataForLoadedContext( api_key: app.apiKey, })) } - -export async function enableDeveloperPreview({ - apiKey, - developerPlatformClient, -}: { - apiKey: string - developerPlatformClient: DeveloperPlatformClient -}) { - return developerPreviewUpdate({apiKey, developerPlatformClient, enabled: true}) -} - -export async function disableDeveloperPreview({ - apiKey, - developerPlatformClient, -}: { - apiKey: string - developerPlatformClient: DeveloperPlatformClient -}) { - await developerPreviewUpdate({apiKey, developerPlatformClient, enabled: false}) -} - -export async function developerPreviewUpdate({ - apiKey, - developerPlatformClient, - enabled, -}: { - apiKey: string - developerPlatformClient: DeveloperPlatformClient - enabled: boolean -}) { - const input: DevelopmentStorePreviewUpdateInput = { - input: { - apiKey, - enabled, - }, - } - const result: DevelopmentStorePreviewUpdateSchema = await developerPlatformClient.updateDeveloperPreview(input) - const userErrors = result.developmentStorePreviewUpdate.userErrors - return !userErrors || userErrors.length === 0 -} diff --git a/packages/app/src/cli/services/dev/fetch.ts b/packages/app/src/cli/services/dev/fetch.ts index 7248acc98d0..e16cb8ff155 100644 --- a/packages/app/src/cli/services/dev/fetch.ts +++ b/packages/app/src/cli/services/dev/fetch.ts @@ -1,5 +1,4 @@ import {Organization, OrganizationStore} from '../../models/organization.js' -import {FindAppPreviewModeSchema} from '../../api/graphql/find_app_preview_mode.js' import {fetchCurrentAccountInformation} from '../context/partner-account-info.js' import { DeveloperPlatformClient, @@ -94,14 +93,6 @@ export async function fetchOrganizations(): Promise { return organizations } -export async function fetchAppPreviewMode( - apiKey: string, - developerPlatformClient: DeveloperPlatformClient, -): Promise { - const res: FindAppPreviewModeSchema = await developerPlatformClient.appPreviewMode({apiKey}) - return res.app?.developmentStorePreviewEnabled -} - export async function fetchOrgFromId( id: string, developerPlatformClient: DeveloperPlatformClient,