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 0ac71e5c4c9..ce01625a337 100644 --- a/packages/app/src/cli/models/app/app.test-data.ts +++ b/packages/app/src/cli/models/app/app.test-data.ts @@ -34,6 +34,7 @@ import { ClientName, CreateAppOptions, DeveloperPlatformClient, + MigrationDeveloperPlatformClient, DevSessionCreateOptions, DevSessionDeleteOptions, DevSessionUpdateOptions, @@ -1300,8 +1301,12 @@ const appLogsSubscribeResponse: AppLogsSubscribeResponse = { }, } -export function testDeveloperPlatformClient(stubs: Partial = {}): DeveloperPlatformClient { - const clientStub: DeveloperPlatformClient = { +type TestDeveloperPlatformClient = DeveloperPlatformClient & MigrationDeveloperPlatformClient + +export function testDeveloperPlatformClient( + stubs: Partial = {}, +): TestDeveloperPlatformClient { + const clientStub: TestDeveloperPlatformClient = { clientName: ClientName.AppManagement, webUiName: 'Test Dashboard', organizationSource: OrganizationSource.BusinessPlatform, @@ -1374,15 +1379,18 @@ export function testDeveloperPlatformClient(stubs: Partial = clientStub + const retVal: Partial = clientStub for (const [key, value] of Object.entries(clientStub)) { if (typeof value === 'function') { retVal[ - key as keyof Omit + key as keyof Omit< + TestDeveloperPlatformClient, + 'clientName' | 'webUiName' | 'organizationSource' | 'bundleFormat' + > ] = vi.fn().mockImplementation(value) } } - return retVal as DeveloperPlatformClient + return retVal as TestDeveloperPlatformClient } export const testPartnersServiceSession: Session = { diff --git a/packages/app/src/cli/services/context/deploy-app-version-migrations.ts b/packages/app/src/cli/services/context/deploy-app-version-migrations.ts index 9e862120cd4..42f2cadfab2 100644 --- a/packages/app/src/cli/services/context/deploy-app-version-migrations.ts +++ b/packages/app/src/cli/services/context/deploy-app-version-migrations.ts @@ -10,7 +10,7 @@ import { migrateAppModules, UIModulesMap, } from '../dev/migrate-app-module.js' -import {DeveloperPlatformClient} from '../../utilities/developer-platform-client.js' +import {MigrationDeveloperPlatformClient} from '../../utilities/developer-platform-client.js' import {PartnersClient} from '../../utilities/developer-platform-client/partners-client.js' import {AbortSilentError} from '@shopify/cli-kit/node/error' @@ -94,7 +94,7 @@ function migrationGroup(typesMap: {[key: string]: string[]}, type: string) { extensionsToMigrate: Parameters[0]['extensionsToMigrate'] appId: string remoteExtensions: RemoteSource[] - migrationClient: DeveloperPlatformClient + migrationClient: MigrationDeveloperPlatformClient }) => migrateAppModules({...options, type}), } } diff --git a/packages/app/src/cli/services/dev/fetch.test.ts b/packages/app/src/cli/services/dev/fetch.test.ts index dee6c3f227a..29d8cbc81f4 100644 --- a/packages/app/src/cli/services/dev/fetch.test.ts +++ b/packages/app/src/cli/services/dev/fetch.test.ts @@ -45,7 +45,7 @@ describe('fetchOrganizations', async () => { // Given const appManagementClient: AppManagementClient = testDeveloperPlatformClient({ organizations: () => Promise.resolve([ORG2]), - }) as AppManagementClient + }) as unknown as AppManagementClient vi.mocked(AppManagementClient.getInstance).mockReturnValue(appManagementClient) // When @@ -60,7 +60,7 @@ describe('fetchOrganizations', async () => { // Given const appManagementClient: AppManagementClient = testDeveloperPlatformClient({ organizations: () => Promise.resolve([]), - }) as AppManagementClient + }) as unknown as AppManagementClient vi.mocked(AppManagementClient.getInstance).mockReturnValue(appManagementClient) // When diff --git a/packages/app/src/cli/services/dev/migrate-app-module.ts b/packages/app/src/cli/services/dev/migrate-app-module.ts index c626040a0c7..da9b36decda 100644 --- a/packages/app/src/cli/services/dev/migrate-app-module.ts +++ b/packages/app/src/cli/services/dev/migrate-app-module.ts @@ -1,6 +1,6 @@ import {LocalSource, RemoteSource} from '../context/identifiers.js' import {ExtensionUuidsByLocalIdentifier} from '../../models/app/identifiers.js' -import {DeveloperPlatformClient} from '../../utilities/developer-platform-client.js' +import {MigrationDeveloperPlatformClient} from '../../utilities/developer-platform-client.js' import {MigrateAppModuleSchema, MigrateAppModuleVariables} from '../../api/graphql/extension_migrate_app_module.js' import {MAX_EXTENSION_HANDLE_LENGTH} from '../../models/extensions/schemas.js' import {AbortError} from '@shopify/cli-kit/node/error' @@ -91,7 +91,7 @@ export async function migrateAppModules(options: { appId: string type: string remoteExtensions: RemoteSource[] - migrationClient: DeveloperPlatformClient + migrationClient: MigrationDeveloperPlatformClient }) { const {extensionsToMigrate, appId, type, remoteExtensions, migrationClient} = options @@ -123,7 +123,7 @@ async function migrateAppModule(options: { registrationId: MigrateAppModuleVariables['registrationId'] registrationUuid: MigrateAppModuleVariables['registrationUuid'] type: MigrateAppModuleVariables['type'] - migrationClient: DeveloperPlatformClient + migrationClient: MigrationDeveloperPlatformClient }) { const {apiKey, registrationId, registrationUuid, type, migrationClient} = options diff --git a/packages/app/src/cli/services/dev/migrate-flow-extension.ts b/packages/app/src/cli/services/dev/migrate-flow-extension.ts index b5241e8f48f..34f30634750 100644 --- a/packages/app/src/cli/services/dev/migrate-flow-extension.ts +++ b/packages/app/src/cli/services/dev/migrate-flow-extension.ts @@ -4,14 +4,14 @@ import { MigrateFlowExtensionSchema, MigrateFlowExtensionVariables, } from '../../api/graphql/extension_migrate_flow_extension.js' -import {DeveloperPlatformClient} from '../../utilities/developer-platform-client.js' +import {MigrationDeveloperPlatformClient} from '../../utilities/developer-platform-client.js' import {AbortError} from '@shopify/cli-kit/node/error' export async function migrateFlowExtensions(options: { extensionsToMigrate: LocalRemoteSource[] appId: string remoteExtensions: RemoteSource[] - migrationClient: DeveloperPlatformClient + migrationClient: MigrationDeveloperPlatformClient }) { const {extensionsToMigrate, appId, remoteExtensions, migrationClient} = options @@ -46,7 +46,7 @@ async function migrateFlowExtension(options: { apiKey: MigrateFlowExtensionVariables['apiKey'] registrationId: MigrateFlowExtensionVariables['registrationId'] registrationUuid: MigrateFlowExtensionVariables['registrationUuid'] - migrationClient: DeveloperPlatformClient + migrationClient: MigrationDeveloperPlatformClient }) { const {apiKey, registrationId, registrationUuid, migrationClient} = options diff --git a/packages/app/src/cli/services/dev/migrate-to-ui-extension.ts b/packages/app/src/cli/services/dev/migrate-to-ui-extension.ts index 92596967f88..f105684f71b 100644 --- a/packages/app/src/cli/services/dev/migrate-to-ui-extension.ts +++ b/packages/app/src/cli/services/dev/migrate-to-ui-extension.ts @@ -4,14 +4,14 @@ import { MigrateToUiExtensionVariables, } from '../../api/graphql/extension_migrate_to_ui_extension.js' import {RemoteSource} from '../context/identifiers.js' -import {DeveloperPlatformClient} from '../../utilities/developer-platform-client.js' +import {MigrationDeveloperPlatformClient} from '../../utilities/developer-platform-client.js' import {AbortError} from '@shopify/cli-kit/node/error' export async function migrateExtensionsToUIExtension(options: { extensionsToMigrate: LocalRemoteSource[] appId: string remoteExtensions: RemoteSource[] - migrationClient: DeveloperPlatformClient + migrationClient: MigrationDeveloperPlatformClient }) { const {extensionsToMigrate, appId, remoteExtensions, migrationClient} = options @@ -41,7 +41,7 @@ async function migrateExtensionToUIExtension(options: { apiKey: MigrateToUiExtensionVariables['apiKey'] registrationId: MigrateToUiExtensionVariables['registrationId'] registrationUuid: MigrateToUiExtensionVariables['registrationUuid'] - migrationClient: DeveloperPlatformClient + migrationClient: MigrationDeveloperPlatformClient }) { const {apiKey, registrationId, registrationUuid, migrationClient} = options diff --git a/packages/app/src/cli/utilities/developer-platform-client.ts b/packages/app/src/cli/utilities/developer-platform-client.ts index 674a2dfa904..821bf4d2ff3 100644 --- a/packages/app/src/cli/utilities/developer-platform-client.ts +++ b/packages/app/src/cli/utilities/developer-platform-client.ts @@ -226,8 +226,6 @@ export interface DeveloperPlatformClient { sendSampleWebhook: (input: SendSampleWebhookVariables, organizationId: string) => Promise apiVersions: (organizationId: string) => Promise topics: (input: WebhookTopicsVariables, organizationId: string) => Promise - migrateFlowExtension: (input: MigrateFlowExtensionVariables) => Promise - migrateAppModule: (input: MigrateAppModuleVariables) => Promise updateURLs: (input: UpdateURLsVariables) => Promise currentAccountInfo: () => Promise targetSchemaDefinition: ( @@ -240,7 +238,6 @@ export interface DeveloperPlatformClient { apiKey: string, organizationId: string, ) => Promise - migrateToUiExtension: (input: MigrateToUiExtensionVariables) => Promise toExtensionGraphQLType: (input: string) => string subscribeToAppLogs: ( input: AppLogsSubscribeMutationVariables, @@ -254,7 +251,22 @@ export interface DeveloperPlatformClient { getCreateDevStoreLink: (org: Organization) => Promise } -const inProgressRefreshes = new WeakMap>() +/** + * The legacy extension migrations (Flow, app module, and UI extension) are only implemented by + * {@link PartnersClient}; the default {@link AppManagementClient} does not support them. Keeping + * these mutations on a dedicated interface lets the migration callers depend on just this surface + * rather than the full {@link DeveloperPlatformClient}. + */ +export interface MigrationDeveloperPlatformClient { + migrateFlowExtension: (input: MigrateFlowExtensionVariables) => Promise + migrateAppModule: (input: MigrateAppModuleVariables) => Promise + migrateToUiExtension: (input: MigrateToUiExtensionVariables) => Promise +} + +/** The subset of a developer platform client needed to refresh an expired token. */ +type TokenRefreshableClient = Pick + +const inProgressRefreshes = new WeakMap>() /** * Creates an unauthorized handler for a developer platform client that will refresh the token @@ -266,7 +278,7 @@ const inProgressRefreshes = new WeakMap * @returns The unauthorized handler. */ export function createUnauthorizedHandler( - client: DeveloperPlatformClient, + client: TokenRefreshableClient, tokenType: 'default' | 'businessPlatform' = 'default', ): UnauthorizedHandler { return { 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 fd006751360..737b73d7b91 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 @@ -53,18 +53,9 @@ import { } from '../../services/webhook/request-sample.js' import {PublicApiVersionsSchema} from '../../services/webhook/request-api-versions.js' import {WebhookTopicsSchema, WebhookTopicsVariables} from '../../services/webhook/request-topics.js' -import { - MigrateFlowExtensionSchema, - MigrateFlowExtensionVariables, -} from '../../api/graphql/extension_migrate_flow_extension.js' import {UpdateURLsSchema, UpdateURLsVariables} from '../../api/graphql/update_urls.js' import {CurrentAccountInfoQuery} from '../../api/graphql/partners/generated/current-account-info.js' import {ExtensionTemplate, ExtensionTemplatesResult} from '../../models/app/template.js' -import { - MigrateToUiExtensionVariables, - MigrateToUiExtensionSchema, -} from '../../api/graphql/extension_migrate_to_ui_extension.js' -import {MigrateAppModuleSchema, MigrateAppModuleVariables} from '../../api/graphql/extension_migrate_app_module.js' import {AppHomeSpecIdentifier} from '../../models/extensions/specifications/app_config_app_home.js' import {BrandingSpecIdentifier} from '../../models/extensions/specifications/app_config_branding.js' import {AppAccessSpecIdentifier} from '../../models/extensions/specifications/app_config_app_access.js' @@ -935,14 +926,6 @@ export class AppManagementClient implements DeveloperPlatformClient { } } - async migrateFlowExtension(_input: MigrateFlowExtensionVariables): Promise { - throw new BugError('Not implemented: migrateFlowExtension') - } - - async migrateAppModule(_input: MigrateAppModuleVariables): Promise { - throw new BugError('Not implemented: migrateAppModule') - } - async updateURLs(_input: UpdateURLsVariables): Promise { outputDebug('⚠️ updateURLs is not implemented') return {appUpdate: {userErrors: []}} @@ -997,10 +980,6 @@ export class AppManagementClient implements DeveloperPlatformClient { } } - async migrateToUiExtension(_input: MigrateToUiExtensionVariables): Promise { - throw new BugError('Not implemented: migrateToUiExtension') - } - toExtensionGraphQLType(input: string) { return input.toLowerCase() }